public static void CubicToLine(IPathRender output, PointF cur, PointF c1, PointF c2, PointF pt, double resolution) { int k = 0; int l = 0; var tempSet = new ControlSet[64]; var controlSet = new ControlSet[64]; tempSet[l++] = new ControlSet(cur, c1, c2, pt); while (l > 0) { var control1 = tempSet[--l]; double b = control1.CalcBreadth(resolution); if (b > resolution) { var control3 = control1.Bisect(); tempSet[l++] = control1; tempSet[l++] = control3; } else { controlSet[k++] = control1; } } while (k > 0) { var control2 = controlSet[--k]; var p = control2.getPoint(); output.Line(cur, p); cur = p; } }
static void Quadratify(IPathRender output, PointF a, PointF b, PointF c, PointF d, float resolutionSq) { // find intersection between bezier arms var s = PointF.Empty; Intersect(a, b, c, d, ref s); // find distance between the midpoints float dx = (a.X + d.X + s.X * 4 - (b.X + c.X) * 3) * 0.125f; float dy = (a.Y + d.Y + s.Y * 4 - (b.Y + c.Y) * 3) * 0.125f; // split curve if the quadratic isn't close enough if (dx * dx + dy * dy > resolutionSq) { var p01 = MidPoint(a, b); var p12 = MidPoint(b, c); var p23 = MidPoint(c, d); var p02 = MidPoint(p01, p12); var p13 = MidPoint(p12, p23); var p03 = MidPoint(p02, p13); // recursive call to subdivide curve Quadratify(output, a, p01, p02, p03, resolutionSq); Quadratify(output, p03, p13, p23, d, resolutionSq); } else { // end recursion by drawing quadratic bezier output.Quad(a, s, d); } }
public static void QuadToCubic(IPathRender output, PointF cur, PointF c1, PointF pt) { float xctrl1 = c1.X + (cur.X - c1.X) / 3f; float yctrl1 = c1.Y + (cur.Y - c1.Y) / 3f; float xctrl2 = c1.X + (pt.X - c1.X) / 3f; float yctrl2 = c1.Y + (pt.Y - c1.Y) / 3f; output.Cubic(cur, new PointF(xctrl1, yctrl1), new PointF(xctrl2, yctrl2), pt); }
static void Close(IPathRender output, PathRenderFeatures features, PointF cur, PointF start) { if ((features & PathRenderFeatures.Close) != 0) { output.Close(cur); } else { output.Line(cur, start); } }
static void Cubic(IPathRender output, PathRenderFeatures features, PointF cur, PointF c1, PointF c2, PointF pt, float resolution) { if ((features & PathRenderFeatures.Cubic) != 0) { output.Cubic(cur, c1, c2, pt); return; } if ((features & PathRenderFeatures.Quad) != 0) { CubicToQuad(output, cur, c1, c2, pt, resolution); } else { CubicToLine(output, cur, c1, c2, pt, 0.025); } }
public static void Render(GraphicsPath path, IPathRender render, PathRenderFeatures features) { Render(path, render, features, DefaultResolution); }
public static void Render(GraphicsPath path, IPathRender render, PathRenderFeatures features, float resolution) { int n = path.PointCount; if (n > 0) { var bezier = new PointF[3]; int bezierIdx = 0; var points = path.PathPoints; var types = path.PathTypes; var start = PointF.Empty; var cur = PointF.Empty; for (int i = 0; i < n; ++i) { var type = (PathPointType)types[i]; var pointType = (PathPointType)((int)type & (int)PathPointType.PathTypeMask); var pt = points[i]; if (type == PathPointType.Start) { render.Move(cur, pt); start = cur = pt; } else if (type == PathPointType.CloseSubpath) { Close(render, features, cur, start); cur = start; } else if (type == PathPointType.PathMarker) { } else if (pointType == PathPointType.Line) { if (i == 0) { render.Move(cur, pt); start = pt; } else { render.Line(cur, pt); } cur = pt; if (((int)type & (int)PathPointType.CloseSubpath) != 0) { Close(render, features, cur, start); cur = start; } } else if (pointType == PathPointType.Bezier || pointType == PathPointType.Bezier3) { bezier[bezierIdx++] = pt; if (bezierIdx == 3) { Cubic(render, features, cur, bezier[0], bezier[1], pt, resolution); cur = pt; bezierIdx = 0; if (((int)type & (int)PathPointType.CloseSubpath) != 0) { Close(render, features, cur, start); cur = start; } } } } } }
public static void CubicToQuad(IPathRender output, PointF cur, PointF c1, PointF c2, PointF pt, float resolution) { Quadratify(output, cur, c1, c2, pt, resolution * resolution); }