Exemplo n.º 1
0
        internal static bool Make(VGPath path, out StencilVertex[] vertices, out int tris)
        {
            vertices = null;
            // Count triangles
            tris =
                path.GetCount(VGPath.SegmentType.CurveTo) * 2 +
                path.GetCount(VGPath.SegmentType.LineTo) +
                path.GetCount(VGPath.SegmentType._Tesselated);

            if (tris == 0)
                return false;

            // Tesselate
            vertices = new StencilVertex[tris * 3];
            StencilVertex start = new StencilVertex();
            Vector2 last = new Vector2();
            int index = 0;

            start.Set(0, 0, Constants.Coef_Solid);
            for (var s = path.FirstSegment; s != null; s = s.Next)
            {
                switch (s.Value.Type)
                {
                    case VGPath.SegmentType.CurveTo:
                        {
                            vertices[index++].Set(last.X, last.Y, Constants.Coef_Solid);
                            vertices[index++].Set(s.Value.Target.X, s.Value.Target.Y, Constants.Coef_Solid);
                            vertices[index++] = start;

                            vertices[index++].Set(last.X, last.Y, Constants.Coef_BezierStart);
                            vertices[index++].Set(s.Value.Controls[0].X, s.Value.Controls[0].Y, Constants.Coef_BezierControl);
                            vertices[index++].Set(s.Value.Target.X, s.Value.Target.Y, Constants.Coef_BezierEnd);
                        }
                        break;
                    case VGPath.SegmentType.LineTo:
                    case VGPath.SegmentType._Tesselated:
                        {
                            vertices[index++].Set(last.X, last.Y, Constants.Coef_Solid);
                            vertices[index++].Set(s.Value.Target.X, s.Value.Target.Y, Constants.Coef_Solid);
                            vertices[index++] = start;
                        }
                        break;
                    case VGPath.SegmentType.MoveTo:
                        {
                            start.Set(s.Value.Target.X, s.Value.Target.Y, Constants.Coef_Solid);
                        }
                        break;
                    default:
                        continue;
                }

                last = s.Value.Target;
            }

            return true;
        }
Exemplo n.º 2
0
        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;
        }