//-------------------------------------------------------------- #region Methods //-------------------------------------------------------------- /// <inheritdoc/> internal override void Flatten(ArrayList <Vector3F> vertices, ArrayList <int> strokeIndices, ArrayList <int> fillIndices) { Triangulator triangulator = null; var segmentVertices = ResourcePools <Vector2F> .Lists.Obtain(); var segmentStartIndices = ResourcePools <int> .Lists.Obtain(); Vector2F previousVertex = new Vector2F(float.NaN); foreach (var curve in Segments) { segmentVertices.Clear(); curve.Flatten(segmentVertices, MaxNumberOfIterations, Tolerance); // Flatten should always return an even number of vertices. But if Flatten() // is erroneous we simply ignore the last vertex. int vertexCount = segmentVertices.Count; if (vertexCount % 2 != 0) { vertexCount--; } if (vertexCount < 2) { continue; } Vector2F segmentStartVertex = segmentVertices[0]; bool isNewShape; int segmentStartIndex; // Start of current segment in 'vertices'. if (segmentStartVertex == previousVertex) { // Continuation of current shape: Skip first vertex of segment. isNewShape = false; segmentStartIndex = vertices.Count - 1; } else { // Start of new shape: Previous segments are no longer needed. isNewShape = true; segmentStartIndices.Clear(); segmentStartIndex = vertices.Count; } // Check for closed shapes. Vector2F segmentEndVertex = segmentVertices[segmentVertices.Count - 1]; bool isClosedShape = false; int shapeStartIndex = -1; // Check if current segment is closed. if (vertexCount > 2 && segmentStartVertex == segmentEndVertex) { // Closed shape found. isClosedShape = true; shapeStartIndex = segmentStartIndex; } // Check if last n segments are closed. if (!isClosedShape) { int numberOfSegments = segmentStartIndices.Count; var vertexArray = vertices.Array; Vector3F v = new Vector3F(segmentEndVertex.X, segmentEndVertex.Y, 0); for (int i = 0; i < numberOfSegments; i++) { int startIndex = segmentStartIndices[i]; if (v == vertexArray[startIndex]) { // Closed shape found. isClosedShape = true; shapeStartIndex = startIndex; break; } } } if (isClosedShape) { segmentStartIndices.Clear(); } else { segmentStartIndices.Add(segmentStartIndex); } CommitVertices(segmentVertices, isNewShape, isClosedShape, vertices); if (IsStroked(curve)) { // Apply stroke. int lineCount = vertexCount / 2; Stroke(segmentStartIndex, lineCount, isClosedShape, shapeStartIndex, strokeIndices); } if (isClosedShape && IsFilled) { // Apply fill. Fill(vertices, shapeStartIndex, fillIndices, ref triangulator); } previousVertex.X = segmentEndVertex.X; previousVertex.Y = segmentEndVertex.Y; } ResourcePools <Vector2F> .Lists.Recycle(segmentVertices); ResourcePools <int> .Lists.Recycle(segmentStartIndices); if (triangulator != null) { triangulator.Recycle(); } }