Skip to content

Commit a516973

Browse files
committed
fix SkipEdgesBeforeMinY algorithm
1 parent eb510f3 commit a516973

4 files changed

Lines changed: 68 additions & 6 deletions

File tree

src/ImageSharp.Drawing/Shapes/Rasterization/PolygonScanner.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,24 +139,34 @@ private void SkipEdgesBeforeMinY()
139139
int i0 = 1;
140140
int i1 = 0;
141141

142-
// Do fake scans for the lines belonging to edge start and endpoints before minY
142+
// Do fake scans for the lines that start before minY. belonging to edge start and endpoints before minY
143+
// Only "scan" at start edge positions (defined by values in sorted0) and end positions (defined by values in sorted1).
144+
// Walk both lists simultaneously following "merge sort" logic.
143145
while (this.SubPixelY < this.minY)
144146
{
145147
this.EnterEdges();
146148
this.LeaveEdges();
147149
this.activeEdges.RemoveLeavingEdges();
148150

149-
float y0 = this.edges[this.sorted0[i0]].Y0;
150-
float y1 = this.edges[this.sorted1[i1]].Y1;
151+
bool hasMore0 = i0 < this.sorted0.Length;
152+
bool hasMore1 = i1 < this.sorted1.Length;
153+
154+
if (!hasMore0 && !hasMore1)
155+
{
156+
break;
157+
}
158+
159+
float y0 = hasMore0 ? this.edges[this.sorted0[i0]].Y0 : float.MaxValue;
160+
float y1 = hasMore1 ? this.edges[this.sorted1[i1]].Y1 : float.MaxValue;
151161

152162
if (y0 < y1)
153163
{
154-
this.SubPixelY = y1;
164+
this.SubPixelY = y0;
155165
i0++;
156166
}
157167
else
158168
{
159-
this.SubPixelY = y0;
169+
this.SubPixelY = y1;
160170
i1++;
161171
}
162172
}

tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Numerics;
66
using SixLabors.ImageSharp.Drawing.Processing;
77
using SixLabors.ImageSharp.PixelFormats;
8+
using SixLabors.ImageSharp.Processing;
89
using Xunit;
910

1011
namespace SixLabors.ImageSharp.Drawing.Tests.Drawing
@@ -74,5 +75,25 @@ public void PathExtendingOffEdgeOfImageShouldNotBeCropped<TPixel>(TestImageProvi
7475
appendPixelTypeToFileName: false,
7576
appendSourceFileOrDescription: false);
7677
}
78+
79+
[Theory]
80+
[WithSolidFilledImages(40, 40, "White", PixelTypes.Rgba32)]
81+
public void DrawPathClippedOnTop<TPixel>(TestImageProvider<TPixel> provider)
82+
where TPixel : unmanaged, IPixel<TPixel>
83+
{
84+
PointF[] points =
85+
{
86+
new PointF(10f, -10f),
87+
new PointF(20f, 20f),
88+
new PointF(30f, -30f)
89+
};
90+
91+
IPath path = new PathBuilder().AddLines(points).Build();
92+
93+
provider.VerifyOperation(
94+
image => image.Mutate(x => x.Draw(Color.Black, 1, path)),
95+
appendSourceFileOrDescription: false,
96+
appendPixelTypeToFileName: false);
97+
}
7798
}
7899
}

tests/ImageSharp.Drawing.Tests/Shapes/Scan/PolygonScannerTests.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ public void NegativeOrientation01(IntersectionRule intersectionRule)
427427
}
428428

429429
[Fact]
430-
public void OutOfBounds()
430+
public void OutOfBounds1()
431431
{
432432
IPath poly = PolygonFactory.CreatePolygon((1, -5), (5, -5), (5, -3), (10, -1), (10, 2), (12, 4), (1, 4));
433433

@@ -445,6 +445,34 @@ public void OutOfBounds()
445445
this.TestScan(poly, 0, 3, 2, expected);
446446
}
447447

448+
[Fact]
449+
public void OutOfBounds2()
450+
{
451+
IPath poly = PolygonFactory.CreatePolygon((3, -3), (3, 1), (1, 1), (1, -1), (2, -1.5f), (2, 0.5f), (3, -3));
452+
FuzzyFloat[][] expected =
453+
{
454+
new FuzzyFloat[] { 1, 2, 2.14285707, 3 },
455+
new FuzzyFloat[] { 1, 2, 2, 3 },
456+
new FuzzyFloat[] { 1, 3 }
457+
};
458+
459+
this.TestScan(poly, 0, 1, 2, expected);
460+
}
461+
462+
[Fact]
463+
public void AllOutOfBounds()
464+
{
465+
IPath poly = PolygonFactory.CreatePolygon((1, -3), (3, -3), (2, -1));
466+
FuzzyFloat[][] expected =
467+
{
468+
Array.Empty<FuzzyFloat>(),
469+
Array.Empty<FuzzyFloat>(),
470+
Array.Empty<FuzzyFloat>(),
471+
};
472+
473+
this.TestScan(poly, 0, 1, 2, expected);
474+
}
475+
448476
private static (float Y, FuzzyFloat[] X) Empty(float y) => (y, Array.Empty<FuzzyFloat>());
449477

450478
private static FuzzyFloat F(float x, float eps) => new(x, eps);
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)