Skip to content

Commit 1e1d6ea

Browse files
Merge pull request #132 from SixLabors/af/simplify-path
Optimize PathGradientBrush, cleanup InternalPath, share ThreadLocal code
2 parents d8960b8 + bc50f77 commit 1e1d6ea

28 files changed

Lines changed: 581 additions & 1143 deletions

.github/workflows/build-and-test.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ on:
99
pull_request:
1010
branches:
1111
- master
12-
1312
jobs:
1413
Build:
1514
strategy:
@@ -45,6 +44,20 @@ jobs:
4544

4645
steps:
4746
- uses: actions/checkout@v2
47+
48+
# See https://github.com/actions/checkout/issues/165#issuecomment-657673315
49+
- name: Create LFS file list
50+
run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id
51+
52+
- name: Restore LFS cache
53+
uses: actions/cache@v2
54+
id: lfs-cache
55+
with:
56+
path: .git/lfs
57+
key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }}-v1
58+
59+
- name: Git LFS Pull
60+
run: git lfs pull
4861

4962
- name: Install NuGet
5063
uses: NuGet/setup-nuget@v1
@@ -68,12 +81,14 @@ jobs:
6881
- name: Build
6982
shell: pwsh
7083
run: ./ci-build.ps1 "${{matrix.options.framework}}"
84+
env:
85+
SIXLABORS_TESTING: True
7186

7287
- name: Test
7388
shell: pwsh
7489
run: ./ci-test.ps1 "${{matrix.options.os}}" "${{matrix.options.framework}}" "${{matrix.options.runtime}}" "${{matrix.options.codecov}}"
7590
env:
76-
CI: True
91+
SIXLABORS_TESTING: True
7792
XUNIT_PATH: .\tests\ImageSharp.Drawing.Tests # Required for xunit
7893

7994
- name: Export Failed Output
@@ -119,3 +134,4 @@ jobs:
119134
run: |
120135
nuget.exe push .\artifacts\*.nupkg ${{secrets.MYGET_TOKEN}} -Source https://www.myget.org/F/sixlabors/api/v2/package
121136
nuget.exe push .\artifacts\*.snupkg ${{secrets.MYGET_TOKEN}} -Source https://www.myget.org/F/sixlabors/api/v3/index.json
137+
# TODO: If github.ref starts with 'refs/tags' then it was tag push and we can optionally push out package to nuget.org

src/ImageSharp.Drawing/Processing/GradientBrush.cs

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Buffers;
66
using System.Numerics;
77
using System.Threading;
8+
using SixLabors.ImageSharp.Drawing.Utilities;
89
using SixLabors.ImageSharp.Memory;
910
using SixLabors.ImageSharp.PixelFormats;
1011

@@ -59,7 +60,7 @@ internal abstract class GradientBrushApplicator<TPixel> : BrushApplicator<TPixel
5960

6061
private readonly int scalineWidth;
6162

62-
private readonly ThreadLocal<ThreadContextData> threadContextData;
63+
private readonly ThreadLocalBlenderBuffers<TPixel> blenderBuffers;
6364

6465
private bool isDisposed;
6566

@@ -85,9 +86,7 @@ protected GradientBrushApplicator(
8586
this.repetitionMode = repetitionMode;
8687
this.scalineWidth = target.Width;
8788
this.allocator = configuration.MemoryAllocator;
88-
this.threadContextData = new ThreadLocal<ThreadContextData>(
89-
() => new ThreadContextData(this.allocator, this.scalineWidth),
90-
true);
89+
this.blenderBuffers = new ThreadLocalBlenderBuffers<TPixel>(this.allocator, this.scalineWidth);
9190
}
9291

9392
internal TPixel this[int x, int y]
@@ -140,9 +139,8 @@ protected GradientBrushApplicator(
140139
/// <inheritdoc />
141140
public override void Apply(Span<float> scanline, int x, int y)
142141
{
143-
ThreadContextData contextData = this.threadContextData.Value;
144-
Span<float> amounts = contextData.AmountSpan.Slice(0, scanline.Length);
145-
Span<TPixel> overlays = contextData.OverlaySpan.Slice(0, scanline.Length);
142+
Span<float> amounts = this.blenderBuffers.AmountSpan.Slice(0, scanline.Length);
143+
Span<TPixel> overlays = this.blenderBuffers.OverlaySpan.Slice(0, scanline.Length);
146144
float blendPercentage = this.Options.BlendPercentage;
147145

148146
// TODO: Remove bounds checks.
@@ -193,12 +191,7 @@ protected override void Dispose(bool disposing)
193191

194192
if (disposing)
195193
{
196-
foreach (ThreadContextData data in this.threadContextData.Values)
197-
{
198-
data.Dispose();
199-
}
200-
201-
this.threadContextData.Dispose();
194+
this.blenderBuffers.Dispose();
202195
}
203196

204197
this.isDisposed = true;
@@ -225,33 +218,6 @@ protected override void Dispose(bool disposing)
225218

226219
return (localGradientFrom, localGradientTo);
227220
}
228-
229-
private sealed class ThreadContextData : IDisposable
230-
{
231-
private bool isDisposed;
232-
private readonly IMemoryOwner<float> amountBuffer;
233-
private readonly IMemoryOwner<TPixel> overlayBuffer;
234-
235-
public ThreadContextData(MemoryAllocator allocator, int scanlineLength)
236-
{
237-
this.amountBuffer = allocator.Allocate<float>(scanlineLength);
238-
this.overlayBuffer = allocator.Allocate<TPixel>(scanlineLength);
239-
}
240-
241-
public Span<float> AmountSpan => this.amountBuffer.Memory.Span;
242-
243-
public Span<TPixel> OverlaySpan => this.overlayBuffer.Memory.Span;
244-
245-
public void Dispose()
246-
{
247-
if (!this.isDisposed)
248-
{
249-
this.isDisposed = true;
250-
this.amountBuffer.Dispose();
251-
this.overlayBuffer.Dispose();
252-
}
253-
}
254-
}
255221
}
256222
}
257223
}

0 commit comments

Comments
 (0)