Skip to content

Commit 07e9867

Browse files
committed
refactor FillRegionProcessor, drop MemoryManager.AllocateFake
1 parent 0d54955 commit 07e9867

File tree

2 files changed

+55
-26
lines changed

2 files changed

+55
-26
lines changed

src/ImageSharp.Drawing/Processing/Drawing/Processors/FillRegionProcessor.cs

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -96,36 +96,35 @@ protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle source
9696
using (BrushApplicator<TPixel> applicator = this.Brush.CreateApplicator(source, rect, this.Options))
9797
{
9898
int scanlineWidth = maxX - minX;
99-
using (BasicArrayBuffer<float> buffer = source.MemoryManager.AllocateFake<float>(maxIntersections))
100-
using (BasicArrayBuffer<float> scanline = source.MemoryManager.AllocateFake<float>(scanlineWidth))
99+
using (IBuffer<float> bBuffer = source.MemoryManager.Allocate<float>(maxIntersections))
100+
using (IBuffer<float> bScanline = source.MemoryManager.Allocate<float>(scanlineWidth))
101101
{
102102
bool scanlineDirty = true;
103103
float subpixelFraction = 1f / subpixelCount;
104104
float subpixelFractionPoint = subpixelFraction / subpixelCount;
105+
106+
Span<float> buffer = bBuffer.GetSpan();
107+
Span<float> scanline = bScanline.GetSpan();
108+
105109
for (int y = minY; y < maxY; y++)
106110
{
107111
if (scanlineDirty)
108112
{
109-
// clear the buffer
110-
for (int x = 0; x < scanlineWidth; x++)
111-
{
112-
scanline[x] = 0;
113-
}
114-
113+
scanline.Clear();
115114
scanlineDirty = false;
116115
}
117116

118117
float yPlusOne = y + 1;
119118
for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction)
120119
{
121-
int pointsFound = region.Scan(subPixel + offset, buffer.GetSpan(), configuration);
120+
int pointsFound = region.Scan(subPixel + offset, buffer, configuration);
122121
if (pointsFound == 0)
123122
{
124123
// nothing on this line skip
125124
continue;
126125
}
127126

128-
QuickSort(new Span<float>(buffer.Array, 0, pointsFound));
127+
QuickSort(buffer.Slice(0, pointsFound));
129128

130129
for (int point = 0; point < pointsFound; point += 2)
131130
{
@@ -181,39 +180,53 @@ protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle source
181180
}
182181
}
183182

184-
applicator.Apply(scanline.GetSpan(), minX, y);
183+
applicator.Apply(scanline, minX, y);
185184
}
186185
}
187186
}
188187
}
189188
}
190189

191190
[MethodImpl(MethodImplOptions.AggressiveInlining)]
192-
private static void Swap(Span<float> data, int left, int right)
191+
private static void Swap(ref float left, ref float right)
193192
{
194-
float tmp = data[left];
195-
data[left] = data[right];
196-
data[right] = tmp;
193+
float tmp = left;
194+
left = right;
195+
right = tmp;
197196
}
198197

199198
private static void QuickSort(Span<float> data)
200199
{
201-
QuickSort(data, 0, data.Length - 1);
200+
if (data.Length < 2)
201+
{
202+
return;
203+
}
204+
else if (data.Length == 2)
205+
{
206+
if (data[0] > data[1])
207+
{
208+
Swap(ref data[0], ref data[1]);
209+
}
210+
211+
return;
212+
}
213+
214+
QuickSort(ref data[0], 0, data.Length - 1);
202215
}
203216

204-
private static void QuickSort(Span<float> data, int lo, int hi)
217+
private static void QuickSort(ref float data0, int lo, int hi)
205218
{
206219
if (lo < hi)
207220
{
208-
int p = Partition(data, lo, hi);
209-
QuickSort(data, lo, p);
210-
QuickSort(data, p + 1, hi);
221+
int p = Partition(ref data0, lo, hi);
222+
QuickSort(ref data0, lo, p);
223+
QuickSort(ref data0, p + 1, hi);
211224
}
212225
}
213226

214-
private static int Partition(Span<float> data, int lo, int hi)
227+
private static int Partition(ref float data0, int lo, int hi)
215228
{
216-
float pivot = data[lo];
229+
float pivot = Unsafe.Add(ref data0, lo);
217230
int i = lo - 1;
218231
int j = hi + 1;
219232
while (true)
@@ -222,20 +235,20 @@ private static int Partition(Span<float> data, int lo, int hi)
222235
{
223236
i = i + 1;
224237
}
225-
while (data[i] < pivot && i < hi);
238+
while (Unsafe.Add(ref data0, i) < pivot && i < hi);
226239

227240
do
228241
{
229242
j = j - 1;
230243
}
231-
while (data[j] > pivot && j > lo);
244+
while (Unsafe.Add(ref data0, j) > pivot && j > lo);
232245

233246
if (i >= j)
234247
{
235248
return j;
236249
}
237250

238-
Swap(data, i, j);
251+
Swap(ref Unsafe.Add(ref data0, i), ref Unsafe.Add(ref data0, j));
239252
}
240253
}
241254
}

tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212

1313
namespace SixLabors.ImageSharp.Tests.Drawing
1414
{
15-
15+
using System;
16+
17+
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
18+
using SixLabors.Primitives;
1619

1720
[GroupOutput("Drawing")]
1821
public class FillSolidBrushTests
@@ -67,6 +70,19 @@ public void WhenColorIsOpaque_OverridePreviousColor<TPixel>(TestImageProvider<TP
6770
}
6871
}
6972

73+
[Theory]
74+
[WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, 5, 7, 3, 8)]
75+
[WithSolidFilledImages(16, 16, "Red", PixelTypes.Rgba32, 8, 5, 6, 4)]
76+
public void FillRegion<TPixel>(TestImageProvider<TPixel> provider, int x0, int y0, int w, int h)
77+
where TPixel : struct, IPixel<TPixel>
78+
{
79+
FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})";
80+
var region = new RectangleF(x0, y0, w, h);
81+
TPixel color = TestUtils.GetPixelOfNamedColor<TPixel>("Blue");
82+
83+
provider.RunValidatingProcessorTest(c => c.Fill(color, region), testDetails, ImageComparer.Exact);
84+
}
85+
7086
public static readonly TheoryData<bool, string, float, PixelBlenderMode, float> BlendData =
7187
new TheoryData<bool, string, float, PixelBlenderMode, float>()
7288
{

0 commit comments

Comments
 (0)