Update PathGeometryConverter.cs

This commit is contained in:
Wiesław Šoltés 2022-11-21 20:38:54 +01:00
Родитель 69007d4f3c
Коммит 5bb6949412
1 изменённых файлов: 89 добавлений и 70 удалений

Просмотреть файл

@ -1,7 +1,6 @@
#nullable enable
using System;
using Core2D.Model.Path;
using Core2D.ViewModels.Path;
using Core2D.ViewModels.Path.Segments;
using Core2D.ViewModels.Shapes;
using PDF = PdfSharp.Drawing;
@ -10,22 +9,93 @@ namespace Core2D.Modules.Renderer.PdfSharp;
public static class PathGeometryConverter
{
public static PDF.XGraphicsPath ToXGraphicsPath(this PathShapeViewModel pg, Func<double, double> scale)
public static PDF.XGraphicsPath? ToXGraphicsPath(this PathShapeViewModel pathShape, Func<double, double> scale)
{
var gp = new PDF.XGraphicsPath()
var graphicsPath = new PDF.XGraphicsPath
{
FillMode = pg.FillRule == FillRule.EvenOdd ? PDF.XFillMode.Alternate : PDF.XFillMode.Winding
FillMode = pathShape.FillRule == FillRule.EvenOdd ? PDF.XFillMode.Alternate : PDF.XFillMode.Winding
};
foreach (var pf in pg.Figures)
foreach (var figure in pathShape.Figures)
{
var startPoint = pf.StartPoint;
foreach (var segment in pf.Segments)
if (figure.StartPoint is null)
{
if (segment is ArcSegmentViewModel arcSegment)
return null;
}
var startPoint = figure.StartPoint;
foreach (var segment in figure.Segments)
{
switch (segment)
{
#if WPF
case LineSegmentViewModel lineSegment:
{
if (lineSegment.Point is null)
{
return null;
}
graphicsPath.AddLine(
scale(startPoint.X),
scale(startPoint.Y),
scale(lineSegment.Point.X),
scale(lineSegment.Point.Y));
startPoint = lineSegment.Point;
break;
}
case CubicBezierSegmentViewModel cubicBezierSegment:
{
if (cubicBezierSegment.Point1 is null || cubicBezierSegment.Point2 is null || cubicBezierSegment.Point3 is null)
{
return null;
}
graphicsPath.AddBezier(
scale(startPoint.X),
scale(startPoint.Y),
scale(cubicBezierSegment.Point1.X),
scale(cubicBezierSegment.Point1.Y),
scale(cubicBezierSegment.Point2.X),
scale(cubicBezierSegment.Point2.Y),
scale(cubicBezierSegment.Point3.X),
scale(cubicBezierSegment.Point3.Y));
startPoint = cubicBezierSegment.Point3;
break;
}
case QuadraticBezierSegmentViewModel quadraticBezierSegment:
{
if (quadraticBezierSegment.Point1 is null || quadraticBezierSegment.Point2 is null)
{
return null;
}
var p1 = startPoint;
var p2 = quadraticBezierSegment.Point1;
var p3 = quadraticBezierSegment.Point2;
var x1 = p1.X;
var y1 = p1.Y;
var x2 = p1.X + (2.0 * (p2.X - p1.X)) / 3.0;
var y2 = p1.Y + (2.0 * (p2.Y - p1.Y)) / 3.0;
var x3 = x2 + (p3.X - p1.X) / 3.0;
var y3 = y2 + (p3.Y - p1.Y) / 3.0;
var x4 = p3.X;
var y4 = p3.Y;
graphicsPath.AddBezier(
scale(x1),
scale(y1),
scale(x2),
scale(y2),
scale(x3),
scale(y3),
scale(x4),
scale(y4));
startPoint = quadraticBezierSegment.Point2;
break;
}
case ArcSegmentViewModel arcSegment:
{
if (arcSegment.Point is null || arcSegment.Size is null)
{
return null;
}
var point1 = new PDF.XPoint(
scale(startPoint.X),
scale(startPoint.Y));
@ -35,80 +105,29 @@ public static class PathGeometryConverter
var size = new PDF.XSize(
scale(arcSegment.Size.Width),
scale(arcSegment.Size.Height));
gp.AddArc(
graphicsPath.AddArc(
point1,
point2,
size, arcSegment.RotationAngle, arcSegment.IsLargeArc,
arcSegment.SweepDirection == SweepDirection.Clockwise ? PDF.XSweepDirection.Clockwise : PDF.XSweepDirection.Counterclockwise);
startPoint = arcSegment.Point;
#else
// TODO: Convert WPF/SVG elliptical arc segment format to GDI+ bezier curves.
startPoint = arcSegment.Point;
#endif
}
else if (segment is CubicBezierSegmentViewModel cubicBezierSegment)
{
gp.AddBezier(
scale(startPoint.X),
scale(startPoint.Y),
scale(cubicBezierSegment.Point1.X),
scale(cubicBezierSegment.Point1.Y),
scale(cubicBezierSegment.Point2.X),
scale(cubicBezierSegment.Point2.Y),
scale(cubicBezierSegment.Point3.X),
scale(cubicBezierSegment.Point3.Y));
startPoint = cubicBezierSegment.Point3;
}
else if (segment is LineSegmentViewModel)
{
var lineSegment = segment as LineSegmentViewModel;
gp.AddLine(
scale(startPoint.X),
scale(startPoint.Y),
scale(lineSegment.Point.X),
scale(lineSegment.Point.Y));
startPoint = lineSegment.Point;
}
else if (segment is QuadraticBezierSegmentViewModel quadraticBezierSegment)
{
var p1 = startPoint;
var p2 = quadraticBezierSegment.Point1;
var p3 = quadraticBezierSegment.Point2;
double x1 = p1.X;
double y1 = p1.Y;
double x2 = p1.X + (2.0 * (p2.X - p1.X)) / 3.0;
double y2 = p1.Y + (2.0 * (p2.Y - p1.Y)) / 3.0;
double x3 = x2 + (p3.X - p1.X) / 3.0;
double y3 = y2 + (p3.Y - p1.Y) / 3.0;
double x4 = p3.X;
double y4 = p3.Y;
gp.AddBezier(
scale(x1),
scale(y1),
scale(x2),
scale(y2),
scale(x3),
scale(y3),
scale(x4),
scale(y4));
startPoint = quadraticBezierSegment.Point2;
}
else
{
throw new NotSupportedException("Not supported segment type: " + segment.GetType());
break;
}
default:
throw new NotSupportedException("Not supported segment type: " + segment.GetType());
}
}
if (pf.IsClosed)
if (figure.IsClosed)
{
gp.CloseFigure();
graphicsPath.CloseFigure();
}
else
{
gp.StartFigure();
graphicsPath.StartFigure();
}
}
return gp;
return graphicsPath;
}
}