Skip to content

Commit 3368bf9

Browse files
committed
Add special case for a different center color. Fix edge test.
1 parent d0c5554 commit 3368bf9

7 files changed

Lines changed: 38 additions & 11 deletions

File tree

src/ImageSharp.Drawing/Processing/PathGradientBrush.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ public sealed class PathGradientBrush : IBrush
2020
private readonly IList<Edge> edges;
2121

2222
private readonly Color centerColor;
23+
private readonly bool hasSpecialCenterColor;
2324

2425
/// <summary>
2526
/// Initializes a new instance of the <see cref="PathGradientBrush"/> class.
2627
/// </summary>
2728
/// <param name="points">Points that constitute a polygon that represents the gradient area.</param>
2829
/// <param name="colors">Array of colors that correspond to each point in the polygon.</param>
29-
/// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param>
30-
public PathGradientBrush(PointF[] points, Color[] colors, Color centerColor)
30+
public PathGradientBrush(PointF[] points, Color[] colors)
3131
{
3232
if (points == null)
3333
{
@@ -62,7 +62,7 @@ public PathGradientBrush(PointF[] points, Color[] colors, Color centerColor)
6262
lines[i] = new LinearLineSegment(points[i % size], points[(i + 1) % size]);
6363
}
6464

65-
this.centerColor = centerColor;
65+
this.centerColor = CalculateCenterColor(colors);
6666

6767
Color ColorAt(int index) => colors[index % colors.Length];
6868

@@ -75,9 +75,12 @@ public PathGradientBrush(PointF[] points, Color[] colors, Color centerColor)
7575
/// </summary>
7676
/// <param name="points">Points that constitute a polygon that represents the gradient area.</param>
7777
/// <param name="colors">Array of colors that correspond to each point in the polygon.</param>
78-
public PathGradientBrush(PointF[] points, Color[] colors)
79-
: this(points, colors, CalculateCenterColor(colors))
78+
/// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param>
79+
public PathGradientBrush(PointF[] points, Color[] colors, Color centerColor)
80+
: this(points, colors)
8081
{
82+
this.centerColor = centerColor;
83+
this.hasSpecialCenterColor = true;
8184
}
8285

8386
/// <inheritdoc />
@@ -88,7 +91,7 @@ public BrushApplicator<TPixel> CreateApplicator<TPixel>(
8891
RectangleF region)
8992
where TPixel : unmanaged, IPixel<TPixel>
9093
{
91-
return new PathGradientBrushApplicator<TPixel>(configuration, options, source, this.edges, this.centerColor);
94+
return new PathGradientBrushApplicator<TPixel>(configuration, options, source, this.edges, this.centerColor, this.hasSpecialCenterColor);
9295
}
9396

9497
private static Color CalculateCenterColor(Color[] colors)
@@ -209,6 +212,8 @@ private class PathGradientBrushApplicator<TPixel> : BrushApplicator<TPixel>
209212

210213
private readonly Vector4 centerColor;
211214

215+
private readonly bool hasSpecialCenterColor;
216+
212217
private readonly float maxDistance;
213218

214219
private readonly IList<Edge> edges;
@@ -230,14 +235,16 @@ public PathGradientBrushApplicator(
230235
GraphicsOptions options,
231236
ImageFrame<TPixel> source,
232237
IList<Edge> edges,
233-
Color centerColor)
238+
Color centerColor,
239+
bool hasSpecialCenterColor)
234240
: base(configuration, options, source)
235241
{
236242
this.edges = edges;
237243
PointF[] points = edges.Select(s => s.Start).ToArray();
238244

239245
this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count;
240246
this.centerColor = (Vector4)centerColor;
247+
this.hasSpecialCenterColor = hasSpecialCenterColor;
241248
this.centerPixel = centerColor.ToPixel<TPixel>();
242249

243250
this.maxDistance = points.Select(p => (Vector2)(p - this.center)).Max(d => d.Length());
@@ -257,7 +264,7 @@ public PathGradientBrushApplicator(
257264
return this.centerPixel;
258265
}
259266

260-
if (this.edges.Count == 3)
267+
if (this.edges.Count == 3 && !this.hasSpecialCenterColor)
261268
{
262269
if (!FindPointOnTriangle(
263270
this.edges[0].Start,
@@ -335,7 +342,7 @@ private static bool FindPointOnTriangle(PointF v1, PointF v2, PointF v3, PointF
335342
var d2 = Vector3.Cross(new Vector3(e2.X, e2.Y, 0), new Vector3(pv2.X, pv2.Y, 0));
336343
var d3 = Vector3.Cross(new Vector3(e3.X, e3.Y, 0), new Vector3(pv3.X, pv3.Y, 0));
337344

338-
if (Math.Sign(Vector3.Dot(d1, d2)) != Math.Sign(Vector3.Dot(d1, d3)) || Math.Sign(Vector3.Dot(d1, d2)) != Math.Sign(Vector3.Dot(d2, d3)))
345+
if (Math.Sign(Vector3.Dot(d1, d2)) * Math.Sign(Vector3.Dot(d1, d3)) == -1 || Math.Sign(Vector3.Dot(d1, d2)) * Math.Sign(Vector3.Dot(d2, d3)) == -1)
339346
{
340347
u = 0;
341348
v = 0;

tests/ImageSharp.Drawing.Tests/Drawing/FillPathGradientBrushTests.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ public void FillRectangleWithDifferentColors<TPixel>(TestImageProvider<TPixel> p
3535
}
3636

3737
[Theory]
38-
[WithBlankImages(10, 10, PixelTypes.Rgba32)]
38+
[WithBlankImages(20, 20, PixelTypes.Rgba32)]
3939
public void FillTriangleWithDifferentColors<TPixel>(TestImageProvider<TPixel> provider)
4040
where TPixel : unmanaged, IPixel<TPixel>
4141
{
4242
provider.VerifyOperation(
4343
TolerantComparer,
4444
image =>
4545
{
46-
PointF[] points = { new PointF(5, 0), new PointF(10, 10), new PointF(0, 10) };
46+
PointF[] points = { new PointF(10, 0), new PointF(20, 20), new PointF(0, 20) };
4747
Color[] colors = { Color.Red, Color.Green, Color.Blue };
4848

4949
var brush = new PathGradientBrush(points, colors);
@@ -53,6 +53,26 @@ public void FillTriangleWithDifferentColors<TPixel>(TestImageProvider<TPixel> pr
5353
});
5454
}
5555

56+
[Theory]
57+
[WithBlankImages(20, 20, PixelTypes.Rgba32)]
58+
public void FillTriangleWithDifferentColorsCenter<TPixel>(TestImageProvider<TPixel> provider)
59+
where TPixel : unmanaged, IPixel<TPixel>
60+
{
61+
provider.VerifyOperation(
62+
TolerantComparer,
63+
image =>
64+
{
65+
PointF[] points = { new PointF(10, 0), new PointF(20, 20), new PointF(0, 20) };
66+
Color[] colors = { Color.Red, Color.Green, Color.Blue };
67+
68+
var brush = new PathGradientBrush(points, colors, Color.White);
69+
70+
image.Mutate(x => x.Fill(brush));
71+
image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
72+
});
73+
}
74+
75+
5676
[Theory]
5777
[WithBlankImages(10, 10, PixelTypes.Rgba32)]
5878
public void FillRectangleWithSingleColor<TPixel>(TestImageProvider<TPixel> provider)
455 Bytes
Loading
724 Bytes
Loading
Loading
729 Bytes
Loading

0 commit comments

Comments
 (0)