コード例 #1
0
ファイル: VGPreparedPath.cs プロジェクト: liwq-net/XnaVG
 internal VGPreparedPath(FillMesh fill, StrokeMesh stroke, VGLineCap startCap, VGLineCap endCap, VGLineJoin join, float miterLimit, Vector4 extents)
 {
     Fill = fill;
     Stroke = stroke;
     StartCap = startCap;
     EndCap = endCap;
     Join = join;
     MiterLimit = miterLimit;
     Extents = extents;
 }
コード例 #2
0
ファイル: StrokeMesh.cs プロジェクト: liwq-net/XnaVG
        internal StrokeMesh(GraphicsDevice device, VGPath path, VGLineCap startCap, VGLineCap endCap, VGLineJoin join, float miterLimit)
        {
            int solidCount, radialCount, i, j, moves;

            // No triangles at all, don't bother...
            if (path.IsEmpty)
                return;

            // Approximate triangle counts
            moves = path.GetCount(VGPath.SegmentType.MoveTo);
            GetCapTris(startCap, out i, out j);
            solidCount = moves * i;
            radialCount = moves * j;

            GetCapTris(endCap, out i, out j);
            solidCount += moves * i;
            radialCount += moves * j;

            GetJoinTris(join, out i, out j);
            solidCount += path.Count * i;
            radialCount += path.Count * j;

            solidCount += (path.GetCount(VGPath.SegmentType.LineTo) + path.GetCount(VGPath.SegmentType._Tesselated)) * 2;

            // Initialize
            _solid = new SolidStrokeBuilder(solidCount, miterLimit);
            _radial = new RadialStrokeBuilder(radialCount);

            var startCapFunc = GetCapFunction(startCap);
            var endCapFunc = GetCapFunction(endCap);
            var joinFunc = GetJoinFunction(join);

            // Tesselate
            VGPath.Segment last = null;
            Vector2 lastNormal = Vector2.Zero;
            var lastStart = path.FirstSegment;

            for (var s = lastStart; s != null; s = s.Next)
            {
                switch (s.Value.Type)
                {
                    case VGPath.SegmentType.LineTo:
                        {
                            Vector2 n, mn;
                            VectorMath.GetLeftNormal(last.Target, s.Value.Target, out n);
                            mn = -n;

                            _solid.AddVertex(last.Target, mn);
                            _solid.AddVertex(last.Target, n);
                            _solid.AddVertex(s.Value.Target, n);
                            _solid.AddVertex(last.Target, mn);
                            _solid.AddVertex(s.Value.Target, n);
                            _solid.AddVertex(s.Value.Target, mn);
                        }
                        break;
                    case VGPath.SegmentType._Tesselated:
                        {
                            if (last.Type != VGPath.SegmentType._Tesselated)
                                VectorMath.GetLeftNormal(last.Target, s.Value.Target, out lastNormal);

                            Vector2 lastRtNormal = -lastNormal;
                            _solid.AddVertex(last.Target, lastRtNormal);
                            _solid.AddVertex(last.Target, lastNormal);
                            _solid.AddVertex(s.Value.Target, s.Value.Controls[0]);
                            _solid.AddVertex(last.Target, lastRtNormal);
                            _solid.AddVertex(s.Value.Target, s.Value.Controls[0]);
                            _solid.AddVertex(s.Value.Target, -s.Value.Controls[0]);

                            lastNormal = s.Value.Controls[0];
                        }
                        break;

                    case VGPath.SegmentType.MoveTo:
                        {
                            if (s.Previous != null && s.Previous.Value.Type != VGPath.SegmentType.Close && s.Previous.Value.Type != VGPath.SegmentType.MoveTo)
                            {
                                startCapFunc(lastStart, true);
                                endCapFunc(s.Previous, false);
                            }

                            lastStart = s;
                        }
                        break;
                    case VGPath.SegmentType.Close:
                        break;
                    default:
                        throw new InvalidOperationException("Trying to stroke non-flattened path!");
                }

                if (s.Value.MakeJoin && s.Next != null)
                    joinFunc(s);

                last = s.Value;
            }

            // Do the caps
            if (path.LastSegment.Value.Type != VGPath.SegmentType.Close && path.LastSegment.Value.Type != VGPath.SegmentType.MoveTo)
            {
                startCapFunc(lastStart, true);
                endCapFunc(path.LastSegment, false);
            }

            // Create buffer
            _vertices[0] = _solid.Build(device, out _tris[0]);
            _vertices[1] = _radial.Build(device, out _tris[1]);

            // Free builders
            _radial = null;
            _solid = null;
        }
コード例 #3
0
ファイル: StrokeMesh.cs プロジェクト: liwq-net/XnaVG
 private void GetCapTris(VGLineCap cap, out int solidTris, out int roundTris)
 {
     solidTris = roundTris = 0;
     switch (cap)
     {
         case VGLineCap.Butt:
             return;
         case VGLineCap.Round:
             roundTris = 2;
             return;
         case VGLineCap.Triangle:
             solidTris = 1;
             break;
         case VGLineCap.Square:
             solidTris = 2;
             break;
         default:
             throw new NotImplementedException("This cap style (" + cap + ") is not implemented!");
     }
 }
コード例 #4
0
ファイル: StrokeMesh.cs プロジェクト: liwq-net/XnaVG
 private _Cap GetCapFunction(VGLineCap cap)
 {
     switch (cap)
     {
         case VGLineCap.Butt: return (a, b) => { };
         case VGLineCap.Round: return MakeRoundCap;
         case VGLineCap.Triangle: return MakeTriangleCap;
         case VGLineCap.Square: return MakeSquareCap;
         default:
             throw new NotImplementedException("This cap style (" + cap + ") is not implemented!");
     }
 }