public void RawIteratorReturnsCorrectPointsAndVerb() { using (var path = new SKPath()) { path.MoveTo(20, 20); path.QuadTo(20, 50, 80, 50); path.QuadTo(20, 50, 20, 80); using (var iter = path.CreateRawIterator()) { var points = new SKPoint[4]; var verb = iter.Next(points); Assert.Equal(SKPathVerb.Move, verb); Assert.Equal(new[] { new SKPoint(20, 20), SKPoint.Empty, SKPoint.Empty, SKPoint.Empty }, points); verb = iter.Next(points); Assert.Equal(SKPathVerb.Quad, verb); Assert.Equal(new[] { new SKPoint(20, 20), new SKPoint(20, 50), new SKPoint(80, 50), SKPoint.Empty }, points); verb = iter.Next(points); Assert.Equal(SKPathVerb.Quad, verb); Assert.Equal(new[] { new SKPoint(80, 50), new SKPoint(20, 50), new SKPoint(20, 80), SKPoint.Empty }, points); verb = iter.Next(points); Assert.Equal(SKPathVerb.Done, verb); // note: when the iteration is Done, it doesn't touch the points Assert.Equal(new[] { new SKPoint(80, 50), new SKPoint(20, 50), new SKPoint(20, 80), SKPoint.Empty }, points); } } }
private static List <SKPoint> CreateLinearPathPoints(SKPath path) { var ring = new List <SKPoint>(); using (var iterator = path.CreateRawIterator()) { var points = new SKPoint[4]; // we must start with a move var verb = iterator.Next(points); if (verb == SKPathVerb.Move) { ring.Add(points[0]); // loop through all the lines while ((verb = iterator.Next(points)) == SKPathVerb.Line) { ring.Add(points[1]); } // if we encountered a curve of some sort, then this is invalid if (verb != SKPathVerb.Move && verb != SKPathVerb.Close && verb != SKPathVerb.Done) { ring.Clear(); } } } return(ring.Count > 0 ? ring : null); }
public static List <(SKPoint Point, byte Type)> GetPathTypes(this SKPath skPath) { // System.Drawing.Drawing2D.GraphicsPath.PathTypes // System.Drawing.Drawing2D.PathPointType // byte -> PathPointType var pathTypes = new List <(SKPoint Point, byte Type)>(); using (var iterator = skPath.CreateRawIterator()) { var points = new SKPoint[4]; var pathVerb = SKPathVerb.Move; (SKPoint Point, byte Type)lastPoint = (default, 0);
public static void Generate(SKPath skPath, StringBuilder sb, string indent = "", string id = "skPath") { sb.AppendLine($"{indent}var {id} = new {nameof(SKPath)}()"); sb.AppendLine($"{indent}{{"); sb.AppendLine($"{indent} {nameof(SKPath.FillType)} = {(skPath.FillType == SKPathFillType.Winding ? $"{nameof(SKPathFillType)}.{nameof(SKPathFillType.Winding)}" : $"{nameof(SKPathFillType)}.{nameof(SKPathFillType.EvenOdd)}")}"); sb.AppendLine($"{indent}}};"); using (var rawIterator = skPath.CreateRawIterator()) { var skPoints = new SKPoint[4]; var skPathVerb = SKPathVerb.Move; while ((skPathVerb = rawIterator.Next(skPoints)) != SKPathVerb.Done) { switch (skPathVerb) { case SKPathVerb.Move: sb.AppendLine($"{indent}{id}.{nameof(SKPath.MoveTo)}({skPoints[0].X.WriteFloat()}, {skPoints[0].Y.WriteFloat()});"); break; case SKPathVerb.Line: sb.AppendLine($"{indent}{id}.{nameof(SKPath.LineTo)}({skPoints[1].X.WriteFloat()}, {skPoints[1].Y.WriteFloat()});"); break; case SKPathVerb.Cubic: sb.AppendLine($"{indent}{id}.{nameof(SKPath.CubicTo)}({skPoints[1].X.WriteFloat()}, {skPoints[1].Y.WriteFloat()}, {skPoints[2].X.WriteFloat()}, {skPoints[2].Y.WriteFloat()}, {skPoints[3].X.WriteFloat()}, {skPoints[3].Y.WriteFloat()});"); break; case SKPathVerb.Quad: sb.AppendLine($"{indent}{id}.{nameof(SKPath.QuadTo)}({skPoints[1].X.WriteFloat()}, {skPoints[1].Y.WriteFloat()}, {skPoints[2].X.WriteFloat()}, {skPoints[2].Y.WriteFloat()});"); break; case SKPathVerb.Conic: sb.AppendLine($"{indent}{id}.{nameof(SKPath.ConicTo)}({skPoints[1].X.WriteFloat()}, {skPoints[1].Y.WriteFloat()}, {skPoints[2].X.WriteFloat()}, {skPoints[2].Y.WriteFloat()}, {rawIterator.ConicWeight().WriteFloat()});"); break; case SKPathVerb.Close: sb.AppendLine($"{indent}{id}.{nameof(SKPath.Close)}();"); break; case SKPathVerb.Done: default: break; } } } }
public static IPathGeometry ToPathGeometry(SKPath path, double dx, double dy, IFactory factory) { var geometry = factory.CreatePathGeometry( ImmutableArray.Create <IPathFigure>(), path.FillType == SKPathFillType.EvenOdd ? FillRule.EvenOdd : FillRule.Nonzero); var context = factory.CreateGeometryContext(geometry); using (var iterator = path.CreateRawIterator()) { var points = new SKPoint[4]; var pathVerb = SKPathVerb.Move; while ((pathVerb = iterator.Next(points)) != SKPathVerb.Done) { switch (pathVerb) { case SKPathVerb.Move: { context.BeginFigure( factory.CreatePointShape(points[0].X + dx, points[0].Y + dy), false, false); } break; case SKPathVerb.Line: { context.LineTo( factory.CreatePointShape(points[1].X + dx, points[1].Y + dy)); } break; case SKPathVerb.Cubic: { context.CubicBezierTo( factory.CreatePointShape(points[1].X + dx, points[1].Y + dy), factory.CreatePointShape(points[2].X + dx, points[2].Y + dy), factory.CreatePointShape(points[3].X + dx, points[3].Y + dy)); } break; case SKPathVerb.Quad: { context.QuadraticBezierTo( factory.CreatePointShape(points[1].X + dx, points[1].Y + dy), factory.CreatePointShape(points[2].X + dx, points[2].Y + dy)); } break; case SKPathVerb.Conic: { var quads = SKPath.ConvertConicToQuads(points[0], points[1], points[2], iterator.ConicWeight(), 1); context.QuadraticBezierTo( factory.CreatePointShape(quads[1].X + dx, quads[1].Y + dy), factory.CreatePointShape(quads[2].X + dx, quads[2].Y + dy)); context.QuadraticBezierTo( factory.CreatePointShape(quads[3].X + dx, quads[3].Y + dy), factory.CreatePointShape(quads[4].X + dx, quads[4].Y + dy)); } break; case SKPathVerb.Close: { context.SetClosedState(true); } break; } } } return(geometry); }
public static SKPath CloneWithTransform(this SKPath pathIn, Func <SKPoint, SKPoint> transform) { SKPath pathOut = new(); using (SKPath.RawIterator iterator = pathIn.CreateRawIterator()) { SKPoint[] points = new SKPoint[4]; SKPathVerb pathVerb = SKPathVerb.Move; SKPoint firstPoint = new(); SKPoint lastPoint = new(); while ((pathVerb = iterator.Next(points)) != SKPathVerb.Done) { switch (pathVerb) { case SKPathVerb.Move: pathOut.MoveTo(transform(points[0])); firstPoint = lastPoint = points[0]; break; case SKPathVerb.Line: SKPoint[] linePoints = Interpolate(points[0], points[1]); foreach (SKPoint pt in linePoints) { pathOut.LineTo(transform(pt)); } lastPoint = points[1]; break; case SKPathVerb.Cubic: SKPoint[] cubicPoints = FlattenCubic(points[0], points[1], points[2], points[3]); foreach (SKPoint pt in cubicPoints) { pathOut.LineTo(transform(pt)); } lastPoint = points[3]; break; case SKPathVerb.Quad: SKPoint[] quadPoints = FlattenQuadratic(points[0], points[1], points[2]); foreach (SKPoint pt in quadPoints) { pathOut.LineTo(transform(pt)); } lastPoint = points[2]; break; case SKPathVerb.Conic: SKPoint[] conicPoints = FlattenConic(points[0], points[1], points[2], iterator.ConicWeight()); foreach (SKPoint pt in conicPoints) { pathOut.LineTo(transform(pt)); } lastPoint = points[2]; break; case SKPathVerb.Close: SKPoint[] closePoints = Interpolate(lastPoint, firstPoint); foreach (SKPoint pt in closePoints) { pathOut.LineTo(transform(pt)); } firstPoint = lastPoint = new SKPoint(0, 0); pathOut.Close(); break; } } } return(pathOut); }
public static PathShapeViewModel ToPathGeometry(SKPath path, IViewModelFactory viewModelFactory) { var geometry = viewModelFactory.CreatePathShape( null, ImmutableArray.Create <PathFigureViewModel>(), path.FillType == SKPathFillType.EvenOdd ? FillRule.EvenOdd : FillRule.Nonzero); var context = viewModelFactory.CreateGeometryContext(geometry); using var iterator = path.CreateRawIterator(); var points = new SKPoint[4]; var pathVerb = SKPathVerb.Move; while ((pathVerb = iterator.Next(points)) != SKPathVerb.Done) { switch (pathVerb) { case SKPathVerb.Move: { context.BeginFigure( viewModelFactory.CreatePointShape(points[0].X, points[0].Y), false); } break; case SKPathVerb.Line: { context.LineTo( viewModelFactory.CreatePointShape(points[1].X, points[1].Y)); } break; case SKPathVerb.Cubic: { context.CubicBezierTo( viewModelFactory.CreatePointShape(points[1].X, points[1].Y), viewModelFactory.CreatePointShape(points[2].X, points[2].Y), viewModelFactory.CreatePointShape(points[3].X, points[3].Y)); } break; case SKPathVerb.Quad: { context.QuadraticBezierTo( viewModelFactory.CreatePointShape(points[1].X, points[1].Y), viewModelFactory.CreatePointShape(points[2].X, points[2].Y)); } break; case SKPathVerb.Conic: { var quads = SKPath.ConvertConicToQuads(points[0], points[1], points[2], iterator.ConicWeight(), 1); context.QuadraticBezierTo( viewModelFactory.CreatePointShape(quads[1].X, quads[1].Y), viewModelFactory.CreatePointShape(quads[2].X, quads[2].Y)); context.QuadraticBezierTo( viewModelFactory.CreatePointShape(quads[3].X, quads[3].Y), viewModelFactory.CreatePointShape(quads[4].X, quads[4].Y)); } break; case SKPathVerb.Close: { context.SetClosedState(true); } break; } } return(geometry); }
internal static PathShape ToPathShape(IToolContext context, SKPath path, ShapeStyle style, IBaseShape pointTemplate) { var pathShape = new PathShape() { Points = new ObservableCollection <IPointShape>(), Shapes = new ObservableCollection <IBaseShape>(), FillType = ToPathFillType(path.FillType), Text = new Text(), StyleId = style.Title }; var figureShape = default(FigureShape); using (var iterator = path.CreateRawIterator()) { var points = new SKPoint[4]; var pathVerb = SKPathVerb.Move; var firstPoint = new SKPoint(); var lastPoint = new SKPoint(); while ((pathVerb = iterator.Next(points)) != SKPathVerb.Done) { switch (pathVerb) { case SKPathVerb.Move: { figureShape = new FigureShape() { Points = new ObservableCollection <IPointShape>(), Shapes = new ObservableCollection <IBaseShape>(), IsFilled = true, IsClosed = false }; figureShape.Owner = pathShape; pathShape.Shapes.Add(figureShape); firstPoint = lastPoint = points[0]; } break; case SKPathVerb.Line: { var lastPointShape = pathShape.GetLastPoint(); if (lastPointShape == null) { lastPointShape = new PointShape(points[0].X, points[0].Y, pointTemplate); } var lineShape = new LineShape() { Points = new ObservableCollection <IPointShape>(), StartPoint = lastPointShape, Point = new PointShape(points[1].X, points[1].Y, pointTemplate), Text = new Text(), StyleId = style.Title }; lineShape.Owner = figureShape; lineShape.StartPoint.Owner = lineShape; lineShape.Point.Owner = lineShape; figureShape.Shapes.Add(lineShape); lastPoint = points[1]; } break; case SKPathVerb.Cubic: { var lastPointShape = pathShape.GetLastPoint(); if (lastPointShape == null) { lastPointShape = new PointShape(points[0].X, points[0].Y, pointTemplate); } var cubicBezierShape = new CubicBezierShape() { Points = new ObservableCollection <IPointShape>(), StartPoint = lastPointShape, Point1 = new PointShape(points[1].X, points[1].Y, pointTemplate), Point2 = new PointShape(points[2].X, points[2].Y, pointTemplate), Point3 = new PointShape(points[3].X, points[3].Y, pointTemplate), Text = new Text(), StyleId = style.Title }; cubicBezierShape.Owner = figureShape; cubicBezierShape.StartPoint.Owner = cubicBezierShape; cubicBezierShape.Point1.Owner = cubicBezierShape; cubicBezierShape.Point2.Owner = cubicBezierShape; cubicBezierShape.Point3.Owner = cubicBezierShape; figureShape.Shapes.Add(cubicBezierShape); lastPoint = points[3]; } break; case SKPathVerb.Quad: { var lastPointShape = pathShape.GetLastPoint(); if (lastPointShape == null) { lastPointShape = new PointShape(points[0].X, points[0].Y, pointTemplate); } var quadraticBezierShape = new QuadraticBezierShape() { Points = new ObservableCollection <IPointShape>(), StartPoint = lastPointShape, Point1 = new PointShape(points[1].X, points[1].Y, pointTemplate), Point2 = new PointShape(points[2].X, points[2].Y, pointTemplate), Text = new Text(), StyleId = style.Title }; quadraticBezierShape.Owner = figureShape; quadraticBezierShape.StartPoint.Owner = quadraticBezierShape; quadraticBezierShape.Point1.Owner = quadraticBezierShape; quadraticBezierShape.Point2.Owner = quadraticBezierShape; figureShape.Shapes.Add(quadraticBezierShape); lastPoint = points[2]; } break; case SKPathVerb.Conic: { var lastPointShape = pathShape.GetLastPoint(); if (lastPointShape == null) { lastPointShape = new PointShape(points[0].X, points[0].Y, pointTemplate); } var conicShape = new ConicShape() { Points = new ObservableCollection <IPointShape>(), StartPoint = lastPointShape, Point1 = new PointShape(points[1].X, points[1].Y, pointTemplate), Point2 = new PointShape(points[2].X, points[2].Y, pointTemplate), Weight = iterator.ConicWeight(), Text = new Text(), StyleId = style.Title }; conicShape.Owner = figureShape; conicShape.StartPoint.Owner = conicShape; conicShape.Point1.Owner = conicShape; conicShape.Point2.Owner = conicShape; figureShape.Shapes.Add(conicShape); lastPoint = points[2]; } break; case SKPathVerb.Close: { #if USE_CLOSE_SHAPE var line = new LineShape() { Points = new ObservableCollection <IPointShape>(), StartPoint = pathShape.GetLastPoint(), Point = pathShape.GetFirstPoint(), Text = new Text(), StyleId = style.Title }; line.Owner = figureShape; line.StartPoint.Owner = line; line.Point.Owner = line; figureShape.Shapes.Add(line); #else figureShape.IsClosed = true; firstPoint = lastPoint = new SKPoint(0, 0); #endif } break; } } } return(pathShape); }