/// <summary>Generates a stroke now using these settings. /// Note that the given path may be modified.</summary> public void Generate(VectorPath path) { // First, simplify the path (eliminates loops etc): path.SimplifyCurve(); // Always recalculate bounds: path.RecalculateBounds(); // For each line, we can now generate the two // offset curves and sample them individually. float halfWidth = Width / 2f; // Tidy values: OuterLength = 0f; InnerLength = 0f; InnerCount = 0; OuterCount = 0; float nx; float ny; // Are we using linejoin? bool lineJoinActive = (LineJoinMode & StrokeLineMode.JoinActive) != 0; VectorPoint current = path.FirstPathNode; while (current != null) { VectorLine line = current as VectorLine; // Set the current line: CurrentLine = line; if (line == null) { // Move to. Complete the previous contour: CompleteContour((current as MoveToPoint).ClosePoint != null); // Go to next: current = current.Next; continue; } if (lineJoinActive) { // Get start normal: line.StartNormal(out nx, out ny); StartNormal = new Vector2(nx, ny); } // First of line: bool applyLineJoin = AtLeastOneLine && lineJoinActive; if (applyLineJoin) { // Compare StartNormal with EndNormal and figure out if we're adding extra verts to // inner or outer. // Original point: OriginalLinePoint = new Vector2( current.Previous.X, current.Previous.Y ); // Get the angle between them: float angle = (float)System.Math.Atan2( StartNormal.x * EndNormal.y - StartNormal.y * EndNormal.x, StartNormal.x * EndNormal.x + StartNormal.y * EndNormal.y ); // If we're in miter mode, find the miter length. // If it exceeds the miter limit, set angle to 0 so we just end up with a bevel. if (LineJoinMode == StrokeLineMode.Miter) { // Compute the miter length now: float miterRatio = 1f / (float)System.Math.Sin(angle / 2f); if (miterRatio > MiterLimit || -miterRatio > MiterLimit) { // Out of range! angle = 0f; } else { // Set the miter length now: MiterLength = miterRatio * halfWidth; } } LineAngle = angle; // Very close to zero -> Do nothing (this is ~5 degrees): if (angle > 0.08f) { // Apply join to outer: ApplyLineJoinNow = true; applyLineJoin = false; } else if (angle > -0.08f) { applyLineJoin = false; } // Else apply join to inner (by leaving applyLineJoin true). } // Change to outer curve: Outer = true; // Extrude and sample it: current.ExtrudeAndSample(path, halfWidth, this); // Increase length so far: OuterLength += line.Length; // Change to inner curve: Outer = false; if (applyLineJoin) { // Apply join to inner: ApplyLineJoinNow = true; } // Extrude and sample it: current.ExtrudeAndSample(path, -halfWidth, this); // Increase length so far: InnerLength += line.Length; if (lineJoinActive) { // Get end normal: line.EndNormal(out nx, out ny); EndNormal = new Vector2(nx, ny); } // We've seen at least one line: AtLeastOneLine = true; // Next: current = current.Next; } // Complete the final contour: CompleteContour(path.LatestPathNode.IsClose); }