From 2d6cb1aa0c4924cb8d2f492aa80246cc0a637cb7 Mon Sep 17 00:00:00 2001 From: BobLd <38405645+BobLd@users.noreply.github.com> Date: Mon, 1 Apr 2024 13:49:37 +0100 Subject: [PATCH] Properly implement Quadtratic and Cubic bezier-curves and use Quadtratic in CalculatePath to fix #625 --- src/UglyToad.PdfPig.Core/PdfSubpath.cs | 352 +++++++++++++----- .../TransformationMatrix.cs | 14 +- .../TrueType/Glyphs/Glyph.cs | 6 +- .../Fonts/CharacterPathTests.cs | 12 +- .../Geometry/BezierCurveTests.cs | 134 +++---- .../GenerateLetterGlyphImages.cs | 8 +- .../SkiaHelpers/SkiaExtensions.cs | 28 +- .../Geometry/GeometryExtensions.cs | 36 +- 8 files changed, 387 insertions(+), 203 deletions(-) diff --git a/src/UglyToad.PdfPig.Core/PdfSubpath.cs b/src/UglyToad.PdfPig.Core/PdfSubpath.cs index cee2c652..3dcd005c 100644 --- a/src/UglyToad.PdfPig.Core/PdfSubpath.cs +++ b/src/UglyToad.PdfPig.Core/PdfSubpath.cs @@ -176,7 +176,7 @@ } /// - /// Add a to the path. + /// Add a to the path. /// public void BezierCurveTo(double x1, double y1, double x2, double y2, double x3, double y3) { @@ -187,7 +187,29 @@ shoeLaceSum += (x3 - x2) * (y3 + y2); var to = new PdfPoint(x3, y3); - commands.Add(new BezierCurve(currentPosition.Value, new PdfPoint(x1, y1), new PdfPoint(x2, y2), to)); + commands.Add(new CubicBezierCurve(currentPosition.Value, new PdfPoint(x1, y1), new PdfPoint(x2, y2), to)); + currentPosition = to; + } + else + { + // PDF Reference 1.7 p226 + throw new ArgumentNullException("BezierCurveTo(): currentPosition is null."); + } + } + + /// + /// Add a to the path. + /// Only used in fonts. + /// + public void BezierCurveTo(double x1, double y1, double x2, double y2) + { + if (currentPosition.HasValue) + { + shoeLaceSum += (x1 - currentPosition.Value.X) * (y1 + currentPosition.Value.Y); + shoeLaceSum += (x2 - x1) * (y2 + y1); + + var to = new PdfPoint(x2, y2); + commands.Add(new QuadraticBezierCurve(currentPosition.Value, new PdfPoint(x1, y1), to)); currentPosition = to; } else @@ -540,14 +562,127 @@ } /// - /// Draw a Bezier curve given by the start, control and end points. + /// Draw a quadratic Bezier-curve given by the start, control and end points. + /// Only used in fonts. /// - public class BezierCurve : IPathCommand + public sealed class QuadraticBezierCurve : BezierCurve { /// - /// The start point of the Bezier curve. + /// Create a quadratic Bezier-curve at the provided points. + /// Only used in fonts. /// - public PdfPoint StartPoint { get; } + public QuadraticBezierCurve(PdfPoint startPoint, PdfPoint controlPoint, PdfPoint endPoint) + : base(startPoint, endPoint) + { + ControlPoint = controlPoint; + } + + /// + /// The control point of the curve. + /// + public PdfPoint ControlPoint { get; } + + /// + public override void WriteSvg(StringBuilder builder, double height) + { + builder.Append($"C {ControlPoint.X} {height - ControlPoint.Y}, {EndPoint.X} {height - EndPoint.Y} "); + } + + /// + protected internal override bool TrySolve(bool isX, double currentMin, double currentMax, out (double min, double max) solutions) + { + solutions = default((double, double)); + + // Given k points the general form is: + // P = (1-t)^(k - i - 1)*t^(i)*P_i + // + // For 3 points this gives: + // P = (1-t)^2*P_1 + 2(1-t)*t*P_2 + t^2*P_3 + // The differential is: + // P' = 2(1-t)(P_2 - P_1) + 2t(P_3 - P_2) + + var p1 = isX ? StartPoint.X : StartPoint.Y; + var p2 = isX ? ControlPoint.X : ControlPoint.Y; + var p3 = isX ? EndPoint.X : EndPoint.Y; + + var t = (p1 - p2) / (p1 - 2.0 * p2 + p3); + + if (t >= 0 && t <= 1) + { + var sol = ValueWithT(p1, p2, p3, t); + if (sol < currentMin) + { + currentMin = sol; + } + + if (sol > currentMax) + { + currentMax = sol; + } + } + + solutions = (currentMin, currentMax); + + return true; + } + + /// + public override IReadOnlyList ToLines(int n) + { + if (n < 1) + { + throw new ArgumentException("BezierCurve.ToLines(): n must be greater than 0."); + } + + List lines = new List(); + var previousPoint = StartPoint; + + for (int p = 1; p <= n; p++) + { + double t = p / (double)n; + var currentPoint = new PdfPoint(ValueWithT(StartPoint.X, ControlPoint.X, EndPoint.X, t), + ValueWithT(StartPoint.Y, ControlPoint.Y, EndPoint.Y, t)); + lines.Add(new Line(previousPoint, currentPoint)); + previousPoint = currentPoint; + } + + return lines; + } + + /// + public override bool Equals(object obj) + { + if (obj is QuadraticBezierCurve curve) + { + return StartPoint.Equals(curve.StartPoint) && + ControlPoint.Equals(curve.ControlPoint) && + EndPoint.Equals(curve.EndPoint); + } + + return false; + } + + /// + public override int GetHashCode() + { + return HashCode.Combine(StartPoint, ControlPoint, EndPoint); + } + } + + /// + /// Draw a cubic Bezier-curve given by the start, control and end points. + /// + public sealed class CubicBezierCurve : BezierCurve + { + /// + /// Create a cubic Bezier-curve at the provided points. + /// + public CubicBezierCurve(PdfPoint startPoint, PdfPoint firstControlPoint, PdfPoint secondControlPoint, PdfPoint endPoint) + : base(startPoint, endPoint) + { + FirstControlPoint = firstControlPoint; + SecondControlPoint = secondControlPoint; + } /// /// The first control point of the curve. @@ -559,71 +694,16 @@ /// public PdfPoint SecondControlPoint { get; } - /// - /// The end point of the curve. - /// - public PdfPoint EndPoint { get; } - - /// - /// Create a Bezier curve at the provided points. - /// - public BezierCurve(PdfPoint startPoint, PdfPoint firstControlPoint, PdfPoint secondControlPoint, PdfPoint endPoint) + /// + public override void WriteSvg(StringBuilder builder, double height) { - StartPoint = startPoint; - FirstControlPoint = firstControlPoint; - SecondControlPoint = secondControlPoint; - EndPoint = endPoint; + builder.Append($"C {FirstControlPoint.X} {height - FirstControlPoint.Y}, {SecondControlPoint.X} {height - SecondControlPoint.Y}, {EndPoint.X} {height - EndPoint.Y} "); } - /// - public PdfRectangle? GetBoundingRectangle() + /// + protected internal override bool TrySolve(bool isX, double currentMin, double currentMax, out (double min, double max) solutions) { - // Optimised - double minX; - double maxX; - if (StartPoint.X <= EndPoint.X) - { - minX = StartPoint.X; - maxX = EndPoint.X; - } - else - { - minX = EndPoint.X; - maxX = StartPoint.X; - } - - double minY; - double maxY; - if (StartPoint.Y <= EndPoint.Y) - { - minY = StartPoint.Y; - maxY = EndPoint.Y; - } - else - { - minY = EndPoint.Y; - maxY = StartPoint.Y; - } - - if (TrySolveQuadratic(true, minX, maxX, out var xSolutions)) - { - minX = xSolutions.min; - maxX = xSolutions.max; - } - - if (TrySolveQuadratic(false, minY, maxY, out var ySolutions)) - { - minY = ySolutions.min; - maxY = ySolutions.max; - } - - return new PdfRectangle(minX, minY, maxX, maxY); - } - - /// - public void WriteSvg(StringBuilder builder, double height) - { - builder.Append($"C {FirstControlPoint.X} { height - FirstControlPoint.Y}, { SecondControlPoint.X} {height - SecondControlPoint.Y}, {EndPoint.X} {height - EndPoint.Y} "); + return TrySolveQuadratic(isX, currentMin, currentMax, out solutions); } private bool TrySolveQuadratic(bool isX, double currentMin, double currentMax, out (double min, double max) solutions) @@ -705,27 +785,8 @@ return true; } - /// - /// Calculate the value of the Bezier curve at t. - /// - public static double ValueWithT(double p1, double p2, double p3, double p4, double t) - { - // P = (1−t)^3*P_1 + 3(1−t)^2*t*P_2 + 3(1−t)*t^2*P_3 + t^3*P_4 - var oneMinusT = 1 - t; - var p = ((oneMinusT * oneMinusT * oneMinusT) * p1) - + (3 * (oneMinusT * oneMinusT) * t * p2) - + (3 * oneMinusT * (t * t) * p3) - + ((t * t * t) * p4); - - return p; - } - - /// - /// Converts the bezier curve into approximated lines. - /// - /// Number of lines required (minimum is 1). - /// - public IReadOnlyList ToLines(int n) + /// + public override IReadOnlyList ToLines(int n) { if (n < 1) { @@ -749,7 +810,7 @@ /// public override bool Equals(object obj) { - if (obj is BezierCurve curve) + if (obj is CubicBezierCurve curve) { return StartPoint.Equals(curve.StartPoint) && FirstControlPoint.Equals(curve.FirstControlPoint) && @@ -766,6 +827,119 @@ } } + /// + /// Draw a Bezier-curve given by the start, control and end points. + /// + public abstract class BezierCurve : IPathCommand + { + /// + /// The start point of the Bezier-curve. + /// + public PdfPoint StartPoint { get; } + + /// + /// The end point of the curve. + /// + public PdfPoint EndPoint { get; } + + /// + /// Create a Bezier-curve at the provided points. + /// + protected BezierCurve(PdfPoint startPoint, PdfPoint endPoint) + { + StartPoint = startPoint; + EndPoint = endPoint; + } + + /// + public PdfRectangle? GetBoundingRectangle() + { + // Optimised + double minX; + double maxX; + if (StartPoint.X <= EndPoint.X) + { + minX = StartPoint.X; + maxX = EndPoint.X; + } + else + { + minX = EndPoint.X; + maxX = StartPoint.X; + } + + double minY; + double maxY; + if (StartPoint.Y <= EndPoint.Y) + { + minY = StartPoint.Y; + maxY = EndPoint.Y; + } + else + { + minY = EndPoint.Y; + maxY = StartPoint.Y; + } + + if (TrySolve(true, minX, maxX, out var xSolutions)) + { + minX = xSolutions.min; + maxX = xSolutions.max; + } + + if (TrySolve(false, minY, maxY, out var ySolutions)) + { + minY = ySolutions.min; + maxY = ySolutions.max; + } + + return new PdfRectangle(minX, minY, maxX, maxY); + } + + /// + public abstract void WriteSvg(StringBuilder builder, double height); + + /// + /// TODO + /// + protected internal abstract bool TrySolve(bool isX, double currentMin, double currentMax, out (double min, double max) solutions); + + /// + /// Calculate the value of the Quadratic Bezier-curve at t. + /// + public static double ValueWithT(double p1, double p2, double p3, double t) + { + // P = (1−t)^2*P_1 + 2(1−t)*t*P_2 + t^2*P_3 + var oneMinusT = 1 - t; + var p = ((oneMinusT * oneMinusT) * p1) + + (2 * (oneMinusT) * t * p2) + + ((t * t) * p3); + + return p; + } + + /// + /// Calculate the value of the Cubic Bezier-curve at t. + /// + public static double ValueWithT(double p1, double p2, double p3, double p4, double t) + { + // P = (1−t)^3*P_1 + 3(1−t)^2*t*P_2 + 3(1−t)*t^2*P_3 + t^3*P_4 + var oneMinusT = 1 - t; + var p = ((oneMinusT * oneMinusT * oneMinusT) * p1) + + (3 * (oneMinusT * oneMinusT) * t * p2) + + (3 * oneMinusT * (t * t) * p3) + + ((t * t * t) * p4); + + return p; + } + + /// + /// Converts the bezier curve into approximated lines. + /// + /// Number of lines required (minimum is 1). + public abstract IReadOnlyList ToLines(int n); + } + /// /// Compares two s for equality. Paths will only be considered equal if the commands which construct the paths are in the same order. /// diff --git a/src/UglyToad.PdfPig.Core/TransformationMatrix.cs b/src/UglyToad.PdfPig.Core/TransformationMatrix.cs index cd9dc1dc..1496c7a3 100644 --- a/src/UglyToad.PdfPig.Core/TransformationMatrix.cs +++ b/src/UglyToad.PdfPig.Core/TransformationMatrix.cs @@ -295,13 +295,19 @@ var to = Transform(line.To); trSubpath.LineTo(to.X, to.Y); } - else if (c is BezierCurve curve) + else if (c is CubicBezierCurve cubic) { - var first = Transform(curve.FirstControlPoint); - var second = Transform(curve.SecondControlPoint); - var end = Transform(curve.EndPoint); + var first = Transform(cubic.FirstControlPoint); + var second = Transform(cubic.SecondControlPoint); + var end = Transform(cubic.EndPoint); trSubpath.BezierCurveTo(first.X, first.Y, second.X, second.Y, end.X, end.Y); } + else if (c is QuadraticBezierCurve quadratic) + { + var control = Transform(quadratic.ControlPoint); + var end = Transform(quadratic.EndPoint); + trSubpath.BezierCurveTo(control.X, control.Y, end.X, end.Y); + } else if (c is Close) { trSubpath.CloseSubpath(); diff --git a/src/UglyToad.PdfPig.Fonts/TrueType/Glyphs/Glyph.cs b/src/UglyToad.PdfPig.Fonts/TrueType/Glyphs/Glyph.cs index 324688c6..632bd57f 100644 --- a/src/UglyToad.PdfPig.Fonts/TrueType/Glyphs/Glyph.cs +++ b/src/UglyToad.PdfPig.Fonts/TrueType/Glyphs/Glyph.cs @@ -182,16 +182,14 @@ } else if (contour[j + 1].IsOnCurve) { - var pPrevious = contour[j - 1]; var pNext = contour[j + 1]; - subpath.BezierCurveTo(pPrevious.X, pPrevious.Y, pNow.X, pNow.Y, pNext.X, pNext.Y); + subpath.BezierCurveTo(pNow.X, pNow.Y, pNext.X, pNext.Y); ++j; } else { - var pPrevious = contour[j - 1]; var pmid = midValue(pNow, contour[j + 1]); - subpath.BezierCurveTo(pPrevious.X, pPrevious.Y, pNow.X, pNow.Y, pmid.X, pmid.Y); + subpath.BezierCurveTo(pNow.X, pNow.Y, pmid.X, pmid.Y); } } subpath.CloseSubpath(); diff --git a/src/UglyToad.PdfPig.Tests/Fonts/CharacterPathTests.cs b/src/UglyToad.PdfPig.Tests/Fonts/CharacterPathTests.cs index 85918411..bd0debfc 100644 --- a/src/UglyToad.PdfPig.Tests/Fonts/CharacterPathTests.cs +++ b/src/UglyToad.PdfPig.Tests/Fonts/CharacterPathTests.cs @@ -8,11 +8,11 @@ [Fact] public void BezierCurveGeneratesCorrectBoundingBox() { - var curve = new PdfSubpath.BezierCurve(new PdfPoint(60, 105), - new PdfPoint(75, 30), - new PdfPoint(215, 115), + var curve = new PdfSubpath.CubicBezierCurve(new PdfPoint(60, 105), + new PdfPoint(75, 30), + new PdfPoint(215, 115), new PdfPoint(140, 160)); - + var result = curve.GetBoundingRectangle(); Assert.NotNull(result); Assert.Equal(160, result.Value.Top); @@ -26,7 +26,7 @@ [Fact] public void LoopBezierCurveGeneratesCorrectBoundingBox() { - var curve = new PdfSubpath.BezierCurve(new PdfPoint(166, 142), + var curve = new PdfSubpath.CubicBezierCurve(new PdfPoint(166, 142), new PdfPoint(75, 30), new PdfPoint(215, 115), new PdfPoint(140, 160)); @@ -45,7 +45,7 @@ [Fact] public void BezierCurveAddsCorrectSvgCommand() { - var curve = new PdfSubpath.BezierCurve(new PdfPoint(60, 105), + var curve = new PdfSubpath.CubicBezierCurve(new PdfPoint(60, 105), new PdfPoint(75, 30), new PdfPoint(215, 115), new PdfPoint(140, 160)); diff --git a/src/UglyToad.PdfPig.Tests/Geometry/BezierCurveTests.cs b/src/UglyToad.PdfPig.Tests/Geometry/BezierCurveTests.cs index 0e8dde12..de7c9774 100644 --- a/src/UglyToad.PdfPig.Tests/Geometry/BezierCurveTests.cs +++ b/src/UglyToad.PdfPig.Tests/Geometry/BezierCurveTests.cs @@ -4,7 +4,7 @@ using UglyToad.PdfPig.Geometry; using static UglyToad.PdfPig.Core.PdfSubpath; - public class BezierCurveTests + public class CubicBezierCurveTests { private static readonly DoubleComparer DoubleComparer = new DoubleComparer(3); private static readonly DoubleComparer PreciseDoubleComparer = new DoubleComparer(6); @@ -15,391 +15,391 @@ { new object[] { - new BezierCurve(new PdfPoint(860.9740224161592, 157.5429444845594), new PdfPoint(344.7182734270533, 213.88461672251213), new PdfPoint(854.7209159935761, 959.185777687854), new PdfPoint(905.7470922668831, 16.404795800137208)), + new CubicBezierCurve(new PdfPoint(860.9740224161592, 157.5429444845594), new PdfPoint(344.7182734270533, 213.88461672251213), new PdfPoint(854.7209159935761, 959.185777687854), new PdfPoint(905.7470922668831, 16.404795800137208)), new PdfLine(254.79108145162598, 682.060779843296, 947.7904279176938, 520.4272311180389), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(860.9740224161592, 157.5429444845594), new PdfPoint(344.7182734270533, 213.88461672251213), new PdfPoint(854.7209159935761, 959.185777687854), new PdfPoint(905.7470922668831, 16.404795800137208)), + new CubicBezierCurve(new PdfPoint(860.9740224161592, 157.5429444845594), new PdfPoint(344.7182734270533, 213.88461672251213), new PdfPoint(854.7209159935761, 959.185777687854), new PdfPoint(905.7470922668831, 16.404795800137208)), new PdfLine(729.8566728331167, 136.87608890796832, 990.5738508807495, 839.4324109521033), new PdfPoint[] { new PdfPoint(748.25810798903, 186.4625591984302), new PdfPoint(829.089079069829, 404.27831715898503), } }, new object[] { - new BezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), + new CubicBezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), new PdfLine(88.36094493352186, 597.4280390307932, 602.2923798085163, 245.06103961412552), new PdfPoint[] { new PdfPoint(592.4920528842322, 251.78044138111852), new PdfPoint(463.44158905248514, 340.2613585384481), } }, new object[] { - new BezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), + new CubicBezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), new PdfLine(665.1316218529099, 713.5599052691191, 586.3797657351924, 403.96970028621337), new PdfPoint[] { new PdfPoint(594.0987775183773, 434.31476842847394), } }, new object[] { - new BezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), + new CubicBezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), new PdfLine(804.1323688937351, 66.82304158268526, 940.224642584682, 100.47258256631386), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), + new CubicBezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), new PdfLine(812.8104597545758, 745.4386135457731, 318.3220239520439, 8.025319010011579), new PdfPoint[] { new PdfPoint(447.12538816961035, 200.10526725150086), new PdfPoint(610.3284245812009, 443.48424246088365), } }, new object[] { - new BezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), + new CubicBezierCurve(new PdfPoint(212.206206559851, 172.10078974021147), new PdfPoint(997.301042585529, 180.0045754823748), new PdfPoint(933.8767807399723, 931.436109575299), new PdfPoint(188.95424054200916, 62.185727940236355)), new PdfLine(697.2949312513251, 648.7844047047331, 839.7087362266726, 142.62959416728316), new PdfPoint[] { new PdfPoint(766.2642561966622, 403.65960373023546), new PdfPoint(745.1687908479832, 478.63527949852437), } }, new object[] { - new BezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), + new CubicBezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), new PdfLine(728.6021436206884, 342.0432715186694, 358.18963651006, 701.7986839375765), new PdfPoint[] { new PdfPoint(560.5715695500569, 505.2394576985048), } }, new object[] { - new BezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), + new CubicBezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), new PdfLine(355.302180992641, 584.1839996311045, 667.9136863127338, 812.4410346366244), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), + new CubicBezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), new PdfLine(792.6269422654265, 273.42816187201356, 952.9930110855164, 77.33157342656027), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), + new CubicBezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), new PdfLine(325.37975926326266, 492.66111408728386, 913.4899158744134, 500.3537703864336), new PdfPoint[] { new PdfPoint(546.2479353326921, 495.5501357217896), } }, new object[] { - new BezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), + new CubicBezierCurve(new PdfPoint(162.30704808607365, 77.7857017776299), new PdfPoint(654.5209449168806, 511.8017465626018), new PdfPoint(39.140335951874825, 185.74361298083087), new PdfPoint(886.0097844389244, 713.4305002270161)), new PdfLine(465.07931499599465, 884.2994016134486, 50.2667032360784, 395.9516429181256), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), + new CubicBezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), new PdfLine(324.6339714193924, 894.3162595100404, 980.3117167961021, 179.2305485734329), new PdfPoint[] { new PdfPoint(447.17620899022927, 760.6710295308544), } }, new object[] { - new BezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), + new CubicBezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), new PdfLine(234.3408935547563, 927.5491824730019, 207.72270423898487, 133.5652610679523), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), + new CubicBezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), new PdfLine(65.09615514441158, 591.9902038678356, 954.7371941806332, 932.2313731349518), new PdfPoint[] { new PdfPoint(418.1216123613029, 727.0039780465277), } }, new object[] { - new BezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), + new CubicBezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), new PdfLine(339.46434964602633, 183.7357141951579, 60.811093697461295, 155.73387900126434), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), + new CubicBezierCurve(new PdfPoint(94.5510147955867, 954.8838185846764), new PdfPoint(842.5175777578082, 857.3411537953642), new PdfPoint(393.2405256504369, 894.0951969270949), new PdfPoint(295.14463007696446, 485.31151069277814)), new PdfLine(278.2347023405965, 917.386189447998, 247.1459794296712, 521.2005738378359), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), + new CubicBezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), new PdfLine(587.2729667027255, 259.030420708796, 484.6376100771876, 963.951407114335), new PdfPoint[] { new PdfPoint(552.0129702448811, 501.20341353429967), new PdfPoint(517.2933000779457, 739.6653329588719), } }, new object[] { - new BezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), + new CubicBezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), new PdfLine(816.8296988364423, 746.2086830959222, 3.46277248213811, 809.5714236153934), new PdfPoint[] { new PdfPoint(613.2846778895625, 762.0652048309472), } }, new object[] { - new BezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), + new CubicBezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), new PdfLine(560.0064517763149, 301.3770694336605, 753.7553240633188, 898.319162798539), new PdfPoint[] { new PdfPoint(619.0791872752442, 483.38072175574905), } }, new object[] { - new BezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), + new CubicBezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), new PdfLine(623.1281970170056, 275.3483340185553, 302.8753987740701, 471.6548554918094), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), + new CubicBezierCurve(new PdfPoint(886.2246600944047, 424.21223636569306), new PdfPoint(193.37982587845337, 561.8168900800805), new PdfPoint(142.7023893319638, 663.0592498576402), new PdfPoint(623.1621885864697, 764.1597027877965)), new PdfLine(864.450032242052, 186.96506468480533, 826.8630880039641, 128.24197360402235), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), + new CubicBezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), new PdfLine(812.6218111750429, 408.5331924593578, 977.316830923921, 236.95892418679153), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), + new CubicBezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), new PdfLine(385.9780089087079, 480.59420237123163, 978.9247102753087, 688.5102135329972), new PdfPoint[] { new PdfPoint(570.8435601367289, 545.4170741807284), } }, new object[] { - new BezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), + new CubicBezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), new PdfLine(975.415154947096, 389.2211415358068, 784.0273503458359, 816.3183722500186), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), + new CubicBezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), new PdfLine(9.623350905034522, 540.8884601927914, 656.7986861143004, 260.68139283950296), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), + new CubicBezierCurve(new PdfPoint(741.7837621228784, 579.5834860990241), new PdfPoint(467.9250981072021, 391.151508990668), new PdfPoint(363.9348547812733, 907.7828368542935), new PdfPoint(398.33133393885555, 595.4799798620128)), new PdfLine(115.74084344003543, 599.980254898775, 551.5217964035138, 790.9417820407351), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), + new CubicBezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), new PdfLine(237.7978352805149, 786.1896089759643, 585.0592514258757, 705.0119767611551), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), + new CubicBezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), new PdfLine(558.5653313005904, 666.4921114581327, 360.4834930562492, 83.78829620601691), new PdfPoint[] { new PdfPoint(486.51491141314335, 454.5390372588546), new PdfPoint(502.37913196387734, 501.2073331654721), new PdfPoint(487.17926688095383, 456.4933934441966), } }, new object[] { - new BezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), + new CubicBezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), new PdfLine(104.55978912027008, 57.53865842452832, 871.8296698367745, 778.2391903340998), new PdfPoint[] { new PdfPoint(573.8142472187677, 498.3117762702451), } }, new object[] { - new BezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), + new CubicBezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), new PdfLine(659.0571440544695, 336.2959913781267, 203.4469774579617, 748.1490737189705), new PdfPoint[] { new PdfPoint(482.8630677523453, 495.5682788191853), } }, new object[] { - new BezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), + new CubicBezierCurve(new PdfPoint(761.1330468650299, 456.00742702080333), new PdfPoint(182.90272632814052, 617.3448547080981), new PdfPoint(721.876316846038, 281.94753549503184), new PdfPoint(340.73639627949484, 580.77195708543)), new PdfLine(452.87536927032426, 215.0197140000346, 710.2231575812335, 694.4299018319648), new PdfPoint[] { new PdfPoint(602.4966262601054, 493.74740537798215), } }, new object[] { - new BezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), + new CubicBezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), new PdfLine(714.4640515887536, 821.9230436439221, 610.7576468776002, 752.4659521198244), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), + new CubicBezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), new PdfLine(805.0974764755789, 377.4993051728441, 789.6394933705419, 195.31328867320363), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), + new CubicBezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), new PdfLine(643.8193142857785, 192.33689963389267, 957.4633999511751, 664.8632026912574), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), + new CubicBezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), new PdfLine(222.66810768767786, 419.5890343762126, 831.173170361083, 160.22486369346035), new PdfPoint[] { new PdfPoint(489.5301582372624, 305.8439586599893), } }, new object[] { - new BezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), + new CubicBezierCurve(new PdfPoint(865.9944513828455, 956.5362580453102), new PdfPoint(782.6869569291499, 747.3495997791625), new PdfPoint(317.18348234495784, 31.68848505555455), new PdfPoint(398.5671847222113, 176.87460728239634)), new PdfLine(653.8226121220232, 324.86672038120514, 280.12608023148135, 1.8176514901221408), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), + new CubicBezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), new PdfLine(857.0486102867367, 8.053120258918911, 689.6009745287959, 489.4170154955638), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), + new CubicBezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), new PdfLine(784.7831019215643, 688.0133561511867, 621.3775330041834, 299.36972195021605), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), + new CubicBezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), new PdfLine(926.449282686191, 928.527953644007, 570.8158929584562, 397.32608249528033), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), + new CubicBezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), new PdfLine(745.8848784094445, 706.5077086524171, 905.541769813007, 244.76748165592775), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), + new CubicBezierCurve(new PdfPoint(571.0331154847579, 710.9172996950756), new PdfPoint(603.826336638094, 764.8051595944524), new PdfPoint(889.7321919148364, 831.3142555845308), new PdfPoint(537.5059435773143, 360.1678513223413)), new PdfLine(563.4446397905452, 260.0561288178326, 462.78668418670253, 720.424868017386), new PdfPoint[] { new PdfPoint(540.6377802339489, 364.3654714444053), } }, new object[] { - new BezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), + new CubicBezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), new PdfLine(735.7728875760906, 71.71025174000023, 509.4157424519464, 98.71654353902338), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), + new CubicBezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), new PdfLine(290.6164038900004, 831.9249213821381, 519.4846042793789, 532.4912102190885), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), + new CubicBezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), new PdfLine(838.5087104882521, 808.8048725506934, 103.65632203336162, 813.6019503826726), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), + new CubicBezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), new PdfLine(351.39319636968924, 519.0210361462613, 657.4630070539363, 810.9560590151057), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), + new CubicBezierCurve(new PdfPoint(462.50581163068796, 546.9240692426745), new PdfPoint(724.5292960882908, 328.1770520621827), new PdfPoint(228.71930273635854, 186.30096428379704), new PdfPoint(432.60327076584093, 555.6858096007285)), new PdfLine(353.53963245785314, 294.14283010796936, 709.6774633468119, 830.4539260427701), new PdfPoint[] { new PdfPoint(498.4426937326664, 512.3536261995338), new PdfPoint(394.2946897465945, 355.5162297966572), } }, new object[] { - new BezierCurve(new PdfPoint(514.5423236364574, 750.5549041630848), new PdfPoint(301.0481922911653, 383.0262248024422), new PdfPoint(344.8999855512257, 479.2380329411904), new PdfPoint(936.3442536990252, 905.2054764541147)), + new CubicBezierCurve(new PdfPoint(514.5423236364574, 750.5549041630848), new PdfPoint(301.0481922911653, 383.0262248024422), new PdfPoint(344.8999855512257, 479.2380329411904), new PdfPoint(936.3442536990252, 905.2054764541147)), new PdfLine(399.9106058852349, 824.3378921470427, 592.8116030553027, 246.70363535307936), new PdfPoint[] { new PdfPoint(457.40664110278004, 652.1683333644837), new PdfPoint(484.6170207749005, 570.6879487652808), } }, new object[] { - new BezierCurve(new PdfPoint(514.5423236364574, 750.5549041630848), new PdfPoint(301.0481922911653, 383.0262248024422), new PdfPoint(344.8999855512257, 479.2380329411904), new PdfPoint(936.3442536990252, 905.2054764541147)), + new CubicBezierCurve(new PdfPoint(514.5423236364574, 750.5549041630848), new PdfPoint(301.0481922911653, 383.0262248024422), new PdfPoint(344.8999855512257, 479.2380329411904), new PdfPoint(936.3442536990252, 905.2054764541147)), new PdfLine(826.4422311470968, 63.988003211555956, 53.64088839817449, 169.14904278567656), new PdfPoint[] { } }, new object[] { - new BezierCurve(new PdfPoint(514.5423236364574, 750.5549041630848), new PdfPoint(301.0481922911653, 383.0262248024422), new PdfPoint(344.8999855512257, 479.2380329411904), new PdfPoint(936.3442536990252, 905.2054764541147)), + new CubicBezierCurve(new PdfPoint(514.5423236364574, 750.5549041630848), new PdfPoint(301.0481922911653, 383.0262248024422), new PdfPoint(344.8999855512257, 479.2380329411904), new PdfPoint(936.3442536990252, 905.2054764541147)), new PdfLine(63.79296653085132, 824.6522054066996, 583.240959660422, 508.2047961495084), new PdfPoint[] { new PdfPoint(429.09432343278115, 602.1108354934324), new PdfPoint(482.80839235708083, 569.3882565700844), } }, new object[] { - new BezierCurve(new PdfPoint(458.50781394598704, 707.3485601935173), new PdfPoint(748.9434779967539, 564.5704869197178), new PdfPoint(585.631258629734, 176.9209403651224), new PdfPoint(941.3690598933631, 810.6237820894949)), + new CubicBezierCurve(new PdfPoint(458.50781394598704, 707.3485601935173), new PdfPoint(748.9434779967539, 564.5704869197178), new PdfPoint(585.631258629734, 176.9209403651224), new PdfPoint(941.3690598933631, 810.6237820894949)), new PdfLine(858.0542006924267, 341.47945951061007, 433.8542949825894, 745.0827456986186), new PdfPoint[] { new PdfPoint(592.1372218843604, 594.4850944848324), new PdfPoint(495.5670660759227, 686.366379009761), new PdfPoint(722.5408527250166, 470.41308685421814), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(326.2357536886028, 288.677023060252, 619.1470513533108, 901.0961222063911), new PdfPoint[] { new PdfPoint(416.08706148161923, 476.5381858573592), new PdfPoint(502.03557864242435, 656.2393918955745), new PdfPoint(536.1359422779292, 727.5364505775408), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(629.3474858004759, 487.28739837111635, 299.8830299735877, 909.475729551436), new PdfPoint[] { new PdfPoint(521.6238559803111, 625.3285700304907), new PdfPoint(507.1287870133768, 643.9031047618156), new PdfPoint(587.138939481947, 541.375040957758), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(538.9251091148191, 479.2330068612399, 480.22096698155246, 922.603946932848), new PdfPoint[] { new PdfPoint(519.2565485724904, 627.7824594315703), new PdfPoint(534.6183658439363, 511.7602654714332), new PdfPoint(510.0087018496723, 697.6280673586205), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(310.5455186650514, 198.7470740535222, 576.0638592446712, 824.557301144184), new PdfPoint[] { new PdfPoint(429.88688944378305, 480.02726805184784), new PdfPoint(503.13503708244207, 652.6685997491355), new PdfPoint(534.1246812723195, 725.7092651343974), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(444.55767730339, 830.1279827584818, 791.9021809752611, 112.98057959909968), new PdfPoint[] { new PdfPoint(558.1937680022871, 595.5083861090311), new PdfPoint(585.3436265805482, 539.453229428223), new PdfPoint(509.30077476036126, 696.455666879191), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(577.0683277988691, 893.501658783371, 484.526604079171, 449.9617060977552), new PdfPoint[] { new PdfPoint(521.204454228015, 625.7536760950204), new PdfPoint(494.56752682342517, 498.0864893835719), new PdfPoint(543.8188906700069, 734.1416082225257), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(728.4474245894388, 171.61053488736044, 453.36320863722045, 827.8850101340745), new PdfPoint[] { new PdfPoint(547.3866186775634, 603.5712890740092), new PdfPoint(577.1131481652287, 532.6520526761924), new PdfPoint(508.80699470905273, 695.6115480452754), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(612.6791399228442, 543.8367328799828, 296.02688700623446, 839.5333062790671), new PdfPoint[] { new PdfPoint(554.0303686415244, 598.6041963741395), new PdfPoint(509.1959187925791, 640.4715542358172), new PdfPoint(590.9874165558272, 564.0929231065433), } }, new object[] { - new BezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), + new CubicBezierCurve(new PdfPoint(257.49795998118753, 441.06811766151986), new PdfPoint(939.9811830880345, 581.4356546220961), new PdfPoint(333.65358960691793, 569.9741022882824), new PdfPoint(549.8549381788116, 738.9885079920657)), new PdfLine(821.7010676907131, 61.7139119382617, 456.865417708614, 817.4864163011968), new PdfPoint[] { new PdfPoint(567.3781193717792, 588.5546731889699), new PdfPoint(589.0169510459666, 543.728916696448), new PdfPoint(512.7201754656179, 701.780919448937), } }, new object[] { - new BezierCurve(new PdfPoint(689.9339095577008, 819.1509167750643), new PdfPoint(91.7293938752487, 735.5359196067776), new PdfPoint(643.7352012702722, 26.344515492747412), new PdfPoint(576.406805896636, 125.74372626431362)), + new CubicBezierCurve(new PdfPoint(689.9339095577008, 819.1509167750643), new PdfPoint(91.7293938752487, 735.5359196067776), new PdfPoint(643.7352012702722, 26.344515492747412), new PdfPoint(576.406805896636, 125.74372626431362)), new PdfLine(604.8045113270402, 23.87003518469999, 428.32162520427863, 682.1304647860862), new PdfPoint[] { new PdfPoint(432.15313855588636, 667.8393701634704), new PdfPoint(579.1518317449497, 119.55151599631576), new PdfPoint(578.215503704165, 123.04390957574823), } }, new object[] { - new BezierCurve(new PdfPoint(814.4149501833379, 401.71941182812145), new PdfPoint(135.72990952948194, 281.0865094136146), new PdfPoint(620.9400702233997, 265.5947273598864), new PdfPoint(7.934191369715626, 823.4171385446947)), + new CubicBezierCurve(new PdfPoint(814.4149501833379, 401.71941182812145), new PdfPoint(135.72990952948194, 281.0865094136146), new PdfPoint(620.9400702233997, 265.5947273598864), new PdfPoint(7.934191369715626, 823.4171385446947)), new PdfLine(578.8014613067338, 130.17633578810862, 53.08065925533256, 807.255035108184), new PdfPoint[] { new PdfPoint(419.12248807828684, 335.82775966254644), new PdfPoint(338.39810018166963, 439.793140806256), new PdfPoint(140.32343925823216, 694.8945810821413), } }, new object[] { - new BezierCurve(new PdfPoint(218.276369458279, 235.3424839558388), new PdfPoint(284.1217842134851, 982.5910790231849), new PdfPoint(366.6074844595172, 582.3854701119949), new PdfPoint(32.42150688046408, 51.18416289826666)), + new CubicBezierCurve(new PdfPoint(218.276369458279, 235.3424839558388), new PdfPoint(284.1217842134851, 982.5910790231849), new PdfPoint(366.6074844595172, 582.3854701119949), new PdfPoint(32.42150688046408, 51.18416289826666)), new PdfLine(360.84227236659336, 883.0984708659082, 134.65259158424092, 204.85753196849643), new PdfPoint[] { new PdfPoint(262.25442342530295, 587.4779323933412), new PdfPoint(276.68708006114014, 630.7549667550165), new PdfPoint(166.69043710960756, 300.924595480044), } }, new object[] { - new BezierCurve(new PdfPoint(218.276369458279, 235.3424839558388), new PdfPoint(284.1217842134851, 982.5910790231849), new PdfPoint(366.6074844595172, 582.3854701119949), new PdfPoint(32.42150688046408, 51.18416289826666)), + new CubicBezierCurve(new PdfPoint(218.276369458279, 235.3424839558388), new PdfPoint(284.1217842134851, 982.5910790231849), new PdfPoint(366.6074844595172, 582.3854701119949), new PdfPoint(32.42150688046408, 51.18416289826666)), new PdfLine(47.837368636920566, 70.9255239988813, 307.4295713877724, 706.0977994394767), new PdfPoint[] { new PdfPoint(265.3481171796182, 603.1325611156734), new PdfPoint(276.7157187476435, 630.9468994422933), new PdfPoint(54.30803564806219, 86.7580037326037), } }, new object[] { - new BezierCurve(new PdfPoint(218.276369458279, 235.3424839558388), new PdfPoint(284.1217842134851, 982.5910790231849), new PdfPoint(366.6074844595172, 582.3854701119949), new PdfPoint(32.42150688046408, 51.18416289826666)), + new CubicBezierCurve(new PdfPoint(218.276369458279, 235.3424839558388), new PdfPoint(284.1217842134851, 982.5910790231849), new PdfPoint(366.6074844595172, 582.3854701119949), new PdfPoint(32.42150688046408, 51.18416289826666)), new PdfLine(80.91649794342514, 86.06780648689072, 385.7230402289716, 904.9572417263104), new PdfPoint[] { new PdfPoint(257.2955610347613, 559.9255861785546), new PdfPoint(268.58529358253224, 590.2564401055265), new PdfPoint(139.04696640209485, 242.24039428432843), } } @@ -408,7 +408,7 @@ [Theory] [MemberData(nameof(IntersectLineData))] - public void IntersectLine(BezierCurve source, PdfLine other, PdfPoint[] expected) + public void IntersectLine(CubicBezierCurve source, PdfLine other, PdfPoint[] expected) { var intersections = source.Intersect(other); Assert.Equal(expected.Length, intersections.Length); diff --git a/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/GenerateLetterGlyphImages.cs b/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/GenerateLetterGlyphImages.cs index 87d5db64..c5df64b4 100644 --- a/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/GenerateLetterGlyphImages.cs +++ b/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/GenerateLetterGlyphImages.cs @@ -24,7 +24,7 @@ private const string OutputPath = "ImagesGlyphs"; - private const float Scale = 2.5f; + private const float Scale = 10f; private static readonly SKMatrix ScaleMatrix = SKMatrix.CreateScale(Scale, Scale); @@ -125,6 +125,12 @@ Run("FontMatrix-raw"); } + [Fact] + public void JudgementDocument() + { + Run("Judgement Document"); + } + [Fact] public void veraPDF_Issue1010_4() { diff --git a/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/SkiaHelpers/SkiaExtensions.cs b/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/SkiaHelpers/SkiaExtensions.cs index 9b55742d..6b994a1f 100644 --- a/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/SkiaHelpers/SkiaExtensions.cs +++ b/src/UglyToad.PdfPig.Tests/Integration/VisualVerification/SkiaHelpers/SkiaExtensions.cs @@ -41,21 +41,21 @@ { skPath.LineTo((float)line.To.X, (float)line.To.Y); } - else if (c is PdfSubpath.BezierCurve curve) + else if (c is PdfSubpath.CubicBezierCurve curve) { - if (curve.StartPoint.Equals(curve.FirstControlPoint)) // TODO - This needs to be fixed in PdfPig - { - // Quad curve - skPath.QuadTo((float)curve.SecondControlPoint.X, (float)curve.SecondControlPoint.Y, - (float)curve.EndPoint.X, (float)curve.EndPoint.Y); - } - else - { - // Cubic curve - skPath.CubicTo((float)curve.FirstControlPoint.X, (float)curve.FirstControlPoint.Y, - (float)curve.SecondControlPoint.X, (float)curve.SecondControlPoint.Y, - (float)curve.EndPoint.X, (float)curve.EndPoint.Y); - } + skPath.CubicTo((float)curve.FirstControlPoint.X, + (float)curve.FirstControlPoint.Y, + (float)curve.SecondControlPoint.X, + (float)curve.SecondControlPoint.Y, + (float)curve.EndPoint.X, + (float)curve.EndPoint.Y); + } + else if (c is PdfSubpath.QuadraticBezierCurve quadratic) + { + skPath.QuadTo((float)quadratic.ControlPoint.X, + (float)quadratic.ControlPoint.Y, + (float)quadratic.EndPoint.X, + (float)quadratic.EndPoint.Y); } else if (c is PdfSubpath.Close) { diff --git a/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs b/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs index 4994b497..b483846e 100644 --- a/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs +++ b/src/UglyToad.PdfPig/Geometry/GeometryExtensions.cs @@ -804,11 +804,11 @@ #region Path Bezier Curve /// - /// Split a bezier curve into 2 bezier curves, at tau. + /// Split a cubic bezier-curve into 2 bezier-curves, at tau. /// - /// The original bezier curve. + /// The original cubic bezier-curve. /// The t value were to split the curve, usually between 0 and 1, but not necessary. - public static (BezierCurve, BezierCurve) Split(this BezierCurve bezierCurve, double tau) + public static (CubicBezierCurve, CubicBezierCurve) Split(this CubicBezierCurve bezierCurve, double tau) { // De Casteljau Algorithm PdfPoint[][] points = new PdfPoint[4][]; @@ -835,29 +835,29 @@ } } - return (new BezierCurve(points[0][0], points[1][0], points[2][0], points[3][0]), - new BezierCurve(points[3][0], points[2][1], points[1][2], points[0][3])); + return (new CubicBezierCurve(points[0][0], points[1][0], points[2][0], points[3][0]), + new CubicBezierCurve(points[3][0], points[2][1], points[1][2], points[0][3])); } /// /// Checks if the curve and the line are intersecting. - /// Avoid using this method as it is not optimised. Use instead. + /// Avoid using this method as it is not optimised. Use instead. /// - public static bool IntersectsWith(this BezierCurve bezierCurve, PdfLine line) + public static bool IntersectsWith(this CubicBezierCurve bezierCurve, PdfLine line) { return IntersectsWith(bezierCurve, line.Point1, line.Point2); } /// /// Checks if the curve and the line are intersecting. - /// Avoid using this method as it is not optimised. Use instead. + /// Avoid using this method as it is not optimised. Use instead. /// - public static bool IntersectsWith(this BezierCurve bezierCurve, Line line) + public static bool IntersectsWith(this CubicBezierCurve bezierCurve, Line line) { return IntersectsWith(bezierCurve, line.From, line.To); } - private static bool IntersectsWith(BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) + private static bool IntersectsWith(CubicBezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) { return Intersect(bezierCurve, p1, p2).Length > 0; } @@ -865,7 +865,7 @@ /// /// Get the s that are the intersections of the line and the curve. /// - public static PdfPoint[] Intersect(this BezierCurve bezierCurve, PdfLine line) + public static PdfPoint[] Intersect(this CubicBezierCurve bezierCurve, PdfLine line) { return Intersect(bezierCurve, line.Point1, line.Point2); } @@ -873,12 +873,12 @@ /// /// Get the s that are the intersections of the line and the curve. /// - public static PdfPoint[] Intersect(this BezierCurve bezierCurve, Line line) + public static PdfPoint[] Intersect(this CubicBezierCurve bezierCurve, Line line) { return Intersect(bezierCurve, line.From, line.To); } - private static PdfPoint[] Intersect(BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) + private static PdfPoint[] Intersect(CubicBezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) { var ts = IntersectT(bezierCurve, p1, p2); if (ts is null || ts.Length == 0) return []; @@ -905,8 +905,8 @@ /// /// Get the t values that are the intersections of the line and the curve. /// - /// List of t values where the and the intersect. - public static double[]? IntersectT(this BezierCurve bezierCurve, PdfLine line) + /// List of t values where the and the intersect. + public static double[]? IntersectT(this CubicBezierCurve bezierCurve, PdfLine line) { return IntersectT(bezierCurve, line.Point1, line.Point2); } @@ -914,13 +914,13 @@ /// /// Get the t values that are the intersections of the line and the curve. /// - /// List of t values where the and the intersect. - public static double[]? IntersectT(this BezierCurve bezierCurve, Line line) + /// List of t values where the and the intersect. + public static double[]? IntersectT(this CubicBezierCurve bezierCurve, Line line) { return IntersectT(bezierCurve, line.From, line.To); } - private static double[]? IntersectT(BezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) + private static double[]? IntersectT(CubicBezierCurve bezierCurve, PdfPoint p1, PdfPoint p2) { // if the bounding boxes do not intersect, they cannot intersect var bezierBbox = bezierCurve.GetBoundingRectangle();