From edb6db2611334867eb9db454a55f1f2d05e90fd7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 25 Oct 2023 22:17:44 +1000 Subject: [PATCH] Fix arcs and do not throw when outlining --- .../Shapes/ArcLineSegment.cs | 76 +++++++++++-------- .../Shapes/PolygonClipper/BoundsF.cs | 3 - .../Shapes/PolygonClipper/PolygonOffsetter.cs | 14 ++-- .../Drawing/DrawLinesTests.cs | 42 ++++++++-- .../Drawing/DrawPathTests.cs | 47 ++++++++++-- .../Shapes/PolygonClipper/ClipperTests.cs | 9 --- .../DrawLinesInvalidPoints_Rgba32_T(1).png | 3 + ...sInvalidPoints_Rgba32_T(1)_NoAntialias.png | 3 + .../DrawLinesInvalidPoints_Rgba32_T(5).png | 3 + ...sInvalidPoints_Rgba32_T(5)_NoAntialias.png | 3 + .../DrawCircleUsingAddArc_359.png | 3 + .../DrawCircleUsingAddArc_360.png | 3 + .../DrawCircleUsingArcTo_False.png | 3 + .../DrawCircleUsingArcTo_True.png | 3 + 14 files changed, 149 insertions(+), 66 deletions(-) create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1).png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1)_NoAntialias.png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5).png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5)_NoAntialias.png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_359.png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_360.png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_False.png create mode 100644 tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_True.png diff --git a/src/ImageSharp.Drawing/Shapes/ArcLineSegment.cs b/src/ImageSharp.Drawing/Shapes/ArcLineSegment.cs index 774506b1..2d4eed66 100644 --- a/src/ImageSharp.Drawing/Shapes/ArcLineSegment.cs +++ b/src/ImageSharp.Drawing/Shapes/ArcLineSegment.cs @@ -32,9 +32,20 @@ public class ArcLineSegment : ILineSegment public ArcLineSegment(PointF from, PointF to, SizeF radius, float rotation, bool largeArc, bool sweep) { rotation = GeometryUtilities.DegreeToRadian(rotation); - bool circle = largeArc && ((Vector2)to - (Vector2)from).LengthSquared() < ZeroTolerance && radius.Width > 0 && radius.Height > 0; - this.linePoints = EllipticArcFromEndParams(from, to, radius, rotation, largeArc, sweep, circle); - this.EndPoint = this.linePoints[this.linePoints.Length - 1]; + bool ellipse = largeArc && ((Vector2)to - (Vector2)from).LengthSquared() < ZeroTolerance && radius.Width > 0 && radius.Height > 0; + if (ellipse) + { + // The circle always has a start angle of 0 which is positioned at 3 o'clock. + // This means the centre point is to the left of the start position. + Vector2 center = (Vector2)from - new Vector2(radius.Width, 0); + this.linePoints = EllipticArcToBezierCurve(from, center, radius, rotation, 0, sweep ? 2 * MathF.PI : -2 * MathF.PI); + } + else + { + this.linePoints = EllipticArcFromEndParams(from, to, radius, rotation, largeArc, sweep); + } + + this.EndPoint = this.linePoints[^1]; } /// @@ -59,16 +70,24 @@ public ArcLineSegment(PointF center, SizeF radius, float rotation, float startAn bool largeArc = Math.Abs(sweepAngle) > MathF.PI; bool sweep = sweepAngle > 0; - bool circle = largeArc && (to - from).LengthSquared() < ZeroTolerance && radius.Width > 0 && radius.Height > 0; + bool ellipse = largeArc && (to - from).LengthSquared() < ZeroTolerance && radius.Width > 0 && radius.Height > 0; - this.linePoints = EllipticArcFromEndParams(from, to, radius, rotation, largeArc, sweep, circle); - this.EndPoint = this.linePoints[this.linePoints.Length - 1]; + if (ellipse) + { + this.linePoints = EllipticArcToBezierCurve(from, center, radius, rotation, startAngle, sweepAngle); + } + else + { + this.linePoints = EllipticArcFromEndParams(from, to, radius, rotation, largeArc, sweep); + } + + this.EndPoint = this.linePoints[^1]; } private ArcLineSegment(PointF[] linePoints) { this.linePoints = linePoints; - this.EndPoint = this.linePoints[this.linePoints.Length - 1]; + this.EndPoint = this.linePoints[^1]; } /// @@ -89,7 +108,7 @@ public ILineSegment Transform(Matrix3x2 matrix) return this; } - var transformedPoints = new PointF[this.linePoints.Length]; + PointF[] transformedPoints = new PointF[this.linePoints.Length]; for (int i = 0; i < this.linePoints.Length; i++) { transformedPoints[i] = PointF.Transform(this.linePoints[i], matrix); @@ -101,32 +120,23 @@ public ILineSegment Transform(Matrix3x2 matrix) /// ILineSegment ILineSegment.Transform(Matrix3x2 matrix) => this.Transform(matrix); - private static PointF[] EllipticArcFromEndParams(PointF from, PointF to, SizeF radius, float rotation, bool largeArc, bool sweep, bool circle) + private static PointF[] EllipticArcFromEndParams( + PointF from, + PointF to, + SizeF radius, + float rotation, + bool largeArc, + bool sweep) { - { - var absRadius = Vector2.Abs(radius); - - if (circle) - { - // It's a circle. SVG arcs cannot handle this so let's hack together our own angles. - // This appears to match the behavior of Web CanvasRenderingContext2D.arc(). - // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc - Vector2 center = (Vector2)from - new Vector2(absRadius.X, 0); - return EllipticArcToBezierCurve(from, center, absRadius, rotation, 0, 2 * MathF.PI); - } - else - { - if (EllipticArcOutOfRange(from, to, radius)) - { - return new[] { from, to }; - } - - float xRotation = rotation; - EndpointToCenterArcParams(from, to, ref absRadius, xRotation, largeArc, sweep, out Vector2 center, out Vector2 angles); + Vector2 absRadius = Vector2.Abs(radius); - return EllipticArcToBezierCurve(from, center, absRadius, xRotation, angles.X, angles.Y); - } + if (EllipticArcOutOfRange(from, to, radius)) + { + return new[] { from, to }; } + + EndpointToCenterArcParams(from, to, ref absRadius, rotation, largeArc, sweep, out Vector2 center, out Vector2 angles); + return EllipticArcToBezierCurve(from, center, absRadius, rotation, angles.X, angles.Y); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -296,8 +306,8 @@ private static float Clamp(float val, float min, float max) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static float SvgAngle(double ux, double uy, double vx, double vy) { - var u = new Vector2((float)ux, (float)uy); - var v = new Vector2((float)vx, (float)vy); + Vector2 u = new((float)ux, (float)uy); + Vector2 v = new((float)vx, (float)vy); // (F.6.5.4) float dot = Vector2.Dot(u, v); diff --git a/src/ImageSharp.Drawing/Shapes/PolygonClipper/BoundsF.cs b/src/ImageSharp.Drawing/Shapes/PolygonClipper/BoundsF.cs index 574feec6..9d48889a 100644 --- a/src/ImageSharp.Drawing/Shapes/PolygonClipper/BoundsF.cs +++ b/src/ImageSharp.Drawing/Shapes/PolygonClipper/BoundsF.cs @@ -14,9 +14,6 @@ internal struct BoundsF public BoundsF(float l, float t, float r, float b) { - Guard.MustBeGreaterThanOrEqualTo(r, l, nameof(r)); - Guard.MustBeGreaterThanOrEqualTo(b, t, nameof(r)); - this.Left = l; this.Top = t; this.Right = r; diff --git a/src/ImageSharp.Drawing/Shapes/PolygonClipper/PolygonOffsetter.cs b/src/ImageSharp.Drawing/Shapes/PolygonClipper/PolygonOffsetter.cs index ad886ff8..501ba036 100644 --- a/src/ImageSharp.Drawing/Shapes/PolygonClipper/PolygonOffsetter.cs +++ b/src/ImageSharp.Drawing/Shapes/PolygonClipper/PolygonOffsetter.cs @@ -99,10 +99,14 @@ public void Execute(float delta, PathsF solution) clipper.Execute(ClippingOperation.Union, FillRule.Positive, solution); } - // PolygonClipper will throw for unhandled exceptions but we need to explicitly capture an empty result. + // PolygonClipper will throw for unhandled exceptions but if a result is empty + // we should just return the original path. if (solution.Count == 0) { - throw new ClipperException("An error occurred while attempting to clip the polygon. Check input for invalid entries."); + foreach (PathF path in this.solution) + { + solution.Add(path); + } } } @@ -213,9 +217,9 @@ private void DoGroupOffset(Group group) } else { - Vector2 d = new(MathF.Ceiling(this.groupDelta)); - Vector2 xy = path[0] - d; - BoundsF r = new(xy.X, xy.Y, xy.X, xy.Y); + float d = this.groupDelta; + Vector2 xy = path[0]; + BoundsF r = new(xy.X - d, xy.Y - d, xy.X + d, xy.Y + d); group.OutPath = r.AsPath(); } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawLinesTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawLinesTests.cs index 6065ce7b..382af441 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawLinesTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawLinesTests.cs @@ -19,11 +19,36 @@ public void DrawLines_Simple(TestImageProvider provider, string where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - var pen = new SolidPen(color, thickness); + SolidPen pen = new(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } + [Theory] + [WithSolidFilledImages(30, 30, "White", PixelTypes.Rgba32, 1f, true)] + [WithSolidFilledImages(30, 30, "White", PixelTypes.Rgba32, 5f, true)] + [WithSolidFilledImages(30, 30, "White", PixelTypes.Rgba32, 1f, false)] + [WithSolidFilledImages(30, 30, "White", PixelTypes.Rgba32, 5f, false)] + public void DrawLinesInvalidPoints(TestImageProvider provider, float thickness, bool antialias) + where TPixel : unmanaged, IPixel + { + SolidPen pen = new(Color.Black, thickness); + PointF[] path = { new Vector2(15f, 15f), new Vector2(15f, 15f) }; + + GraphicsOptions options = new() + { + Antialias = antialias + }; + + string aa = antialias ? string.Empty : "_NoAntialias"; + FormattableString outputDetails = $"T({thickness}){aa}"; + + provider.RunValidatingProcessorTest( + c => c.SetGraphicsOptions(options).DrawLine(pen, path), + outputDetails, + appendSourceFileOrDescription: false); + } + [Theory] [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] public void DrawLines_Dash(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) @@ -74,7 +99,7 @@ public void DrawLines_EndCapRound(TestImageProvider provider, st where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - PatternPen pen = new PatternPen(new PenOptions(color, thickness, new float[] { 3f, 3f }) { EndCapStyle = EndCapStyle.Round }); + PatternPen pen = new(new PenOptions(color, thickness, new float[] { 3f, 3f }) { EndCapStyle = EndCapStyle.Round }); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -85,7 +110,7 @@ public void DrawLines_EndCapButt(TestImageProvider provider, str where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - PatternPen pen = new PatternPen(new PenOptions(color, thickness, new float[] { 3f, 3f }) { EndCapStyle = EndCapStyle.Butt }); + PatternPen pen = new(new PenOptions(color, thickness, new float[] { 3f, 3f }) { EndCapStyle = EndCapStyle.Butt }); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -96,7 +121,7 @@ public void DrawLines_EndCapSquare(TestImageProvider provider, s where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - PatternPen pen = new PatternPen(new PenOptions(color, thickness, new float[] { 3f, 3f }) { EndCapStyle = EndCapStyle.Square }); + PatternPen pen = new(new PenOptions(color, thickness, new float[] { 3f, 3f }) { EndCapStyle = EndCapStyle.Square }); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -107,7 +132,7 @@ public void DrawLines_JointStyleRound(TestImageProvider provider where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - var pen = new SolidPen(new PenOptions(color, thickness) { JointStyle = JointStyle.Round }); + SolidPen pen = new(new PenOptions(color, thickness) { JointStyle = JointStyle.Round }); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -118,7 +143,7 @@ public void DrawLines_JointStyleSquare(TestImageProvider provide where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - var pen = new SolidPen(new PenOptions(color, thickness) { JointStyle = JointStyle.Square }); + SolidPen pen = new(new PenOptions(color, thickness) { JointStyle = JointStyle.Square }); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -129,7 +154,7 @@ public void DrawLines_JointStyleMiter(TestImageProvider provider where TPixel : unmanaged, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - var pen = new SolidPen(new PenOptions(color, thickness) { JointStyle = JointStyle.Miter }); + SolidPen pen = new(new PenOptions(color, thickness) { JointStyle = JointStyle.Miter }); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -145,7 +170,8 @@ private static void DrawLinesImpl( { PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; - var options = new GraphicsOptions { Antialias = antialias }; + GraphicsOptions options = new() + { Antialias = antialias }; string aa = antialias ? string.Empty : "_NoAntialias"; FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs index e84437bd..bbd196d7 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs @@ -26,20 +26,20 @@ public class DrawPathTests public void DrawPath(TestImageProvider provider, string colorName, byte alpha, float thickness) where TPixel : unmanaged, IPixel { - var linearSegment = new LinearLineSegment( + LinearLineSegment linearSegment = new( new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300)); - var bezierSegment = new CubicBezierLineSegment( + CubicBezierLineSegment bezierSegment = new( new Vector2(50, 300), new Vector2(500, 500), new Vector2(60, 10), new Vector2(10, 400)); - var ellipticArcSegment1 = new ArcLineSegment(new Vector2(10, 400), new Vector2(150, 450), new SizeF((float)Math.Sqrt(5525), 40), GeometryUtilities.RadianToDegree((float)Math.Atan2(25, 70)), true, true); - var ellipticArcSegment2 = new ArcLineSegment(new(150, 450), new(149F, 450), new SizeF(140, 70), 0, true, true); + ArcLineSegment ellipticArcSegment1 = new(new Vector2(10, 400), new Vector2(150, 450), new SizeF((float)Math.Sqrt(5525), 40), GeometryUtilities.RadianToDegree((float)Math.Atan2(25, 70)), true, true); + ArcLineSegment ellipticArcSegment2 = new(new(150, 450), new(149F, 450), new SizeF(140, 70), 0, true, true); - var path = new Path(linearSegment, bezierSegment, ellipticArcSegment1, ellipticArcSegment2); + Path path = new(linearSegment, bezierSegment, ellipticArcSegment1, ellipticArcSegment2); Rgba32 rgba = TestUtils.GetColorByName(colorName); rgba.A = alpha; @@ -67,7 +67,7 @@ public void PathExtendingOffEdgeOfImageShouldNotBeCropped(TestImageProvi { for (int i = 0; i < 300; i += 20) { - var points = new PointF[] { new Vector2(100, 2), new Vector2(-10, i) }; + PointF[] points = new PointF[] { new Vector2(100, 2), new Vector2(-10, i) }; x.DrawLine(pen, points); } }, @@ -91,7 +91,38 @@ public void DrawPathClippedOnTop(TestImageProvider provider) provider.VerifyOperation( image => image.Mutate(x => x.Draw(Color.Black, 1, path)), - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + + [Theory] + [WithSolidFilledImages(300, 300, "White", PixelTypes.Rgba32, 360)] + [WithSolidFilledImages(300, 300, "White", PixelTypes.Rgba32, 359)] + public void DrawCircleUsingAddArc(TestImageProvider provider, float sweep) + where TPixel : unmanaged, IPixel + { + IPath path = new PathBuilder().AddArc(new Point(150, 150), 50, 50, 0, 40, sweep).Build(); + + provider.VerifyOperation( + image => image.Mutate(x => x.Draw(Color.Black, 1, path)), + testOutputDetails: $"{sweep}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + + [Theory] + [WithSolidFilledImages(300, 300, "White", PixelTypes.Rgba32, true)] + [WithSolidFilledImages(300, 300, "White", PixelTypes.Rgba32, false)] + public void DrawCircleUsingArcTo(TestImageProvider provider, bool sweep) + where TPixel : unmanaged, IPixel + { + Point origin = new(150, 150); + IPath path = new PathBuilder().MoveTo(origin).ArcTo(50, 50, 0, true, sweep, origin).Build(); + + provider.VerifyOperation( + image => image.Mutate(x => x.Draw(Color.Black, 1, path)), + testOutputDetails: $"{sweep}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } } diff --git a/tests/ImageSharp.Drawing.Tests/Shapes/PolygonClipper/ClipperTests.cs b/tests/ImageSharp.Drawing.Tests/Shapes/PolygonClipper/ClipperTests.cs index ead04412..4abfe7d8 100644 --- a/tests/ImageSharp.Drawing.Tests/Shapes/PolygonClipper/ClipperTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Shapes/PolygonClipper/ClipperTests.cs @@ -130,13 +130,4 @@ public void ClippingRectanglesCreateCorrectNumberOfPoints() Assert.Equal(8, points.Count); } - - [Fact] - public void ClipperOffsetThrowsPublicException() - { - PointF naan = new(float.NaN, float.NaN); - Polygon path = new(new LinearLineSegment(new[] { naan, naan, naan, naan })); - - Assert.Throws(() => path.GenerateOutline(10)); - } } diff --git a/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1).png b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1).png new file mode 100644 index 00000000..b3859ce0 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:459dcb4b0e81dc7e850babc169510ac2298636c7a65c06802f104dca3ce87a45 +size 165 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1)_NoAntialias.png b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1)_NoAntialias.png new file mode 100644 index 00000000..a10f7de6 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(1)_NoAntialias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d2ab1c8fd901a5bede28a3036a4df9cb551e6a13c154a988da1700c89fb67b4 +size 161 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5).png b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5).png new file mode 100644 index 00000000..f4d76fb0 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:635053b4ce23dafc080d4d9de9e808819d264461ee5e0543acfefb8c9a04d00e +size 187 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5)_NoAntialias.png b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5)_NoAntialias.png new file mode 100644 index 00000000..ce158e06 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawLinesTests/DrawLinesInvalidPoints_Rgba32_T(5)_NoAntialias.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5482537fd9d8f4ad4c6e03ae1ae0d7f8035ecb29f541778009653ab7796510dd +size 173 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_359.png b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_359.png new file mode 100644 index 00000000..76e601ac --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_359.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b48a33ee84606f1b74ebb1fe047df7eedd8a36758a17860d04b2b11a2116e55 +size 3927 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_360.png b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_360.png new file mode 100644 index 00000000..b0c7fed2 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingAddArc_360.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30d023cfe508a969b3386dfaea3b1b30be935ee932f3e57df705b966c93ef341 +size 3930 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_False.png b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_False.png new file mode 100644 index 00000000..deff10c0 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_False.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9eadf653708a1d8031e543f17cdea79140792140cce59444979aeccf32a8d983 +size 4148 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_True.png b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_True.png new file mode 100644 index 00000000..aae3b2ca --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/DrawPathTests/DrawCircleUsingArcTo_True.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b752270cb16a191a1868fc91a7a11806f1138259846954ca05ea5c937ece301a +size 3571