Browse Source

Accept points instead of line segments as constructor argument

Note that this is a breaking change.
af/merge-core
Xavier Cho 7 years ago
parent
commit
7e06b63420
  1. 43
      src/ImageSharp.Drawing/Processing/PathGradientBrush.cs
  2. 86
      tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs

43
src/ImageSharp.Drawing/Processing/PathGradientBrush.cs

@ -18,8 +18,6 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
public sealed class PathGradientBrush : IBrush
{
private readonly Polygon path;
private readonly IList<Edge> edges;
private readonly Color centerColor;
@ -27,20 +25,20 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Initializes a new instance of the <see cref="PathGradientBrush"/> class.
/// </summary>
/// <param name="lines">Line segments of a polygon that represents the gradient area.</param>
/// <param name="points">Points that constitute a polygon that represents the gradient area.</param>
/// <param name="colors">Array of colors that correspond to each point in the polygon.</param>
/// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param>
public PathGradientBrush(ILineSegment[] lines, Color[] colors, Color centerColor)
public PathGradientBrush(PointF[] points, Color[] colors, Color centerColor)
{
if (lines == null)
if (points == null)
{
throw new ArgumentNullException(nameof(lines));
throw new ArgumentNullException(nameof(points));
}
if (lines.Length < 3)
if (points.Length < 3)
{
throw new ArgumentOutOfRangeException(
nameof(lines),
nameof(points),
"There must be at least 3 lines to construct a path gradient brush.");
}
@ -56,22 +54,30 @@ namespace SixLabors.ImageSharp.Processing
"One or more color is needed to construct a path gradient brush.");
}
this.path = new Polygon(lines);
int size = points.Length;
var lines = new ILineSegment[size];
for (int i = 0; i < size; i++)
{
lines[i] = new LinearLineSegment(points[i % size], points[(i + 1) % size]);
}
this.centerColor = centerColor;
Color ColorAt(int index) => colors[index % colors.Length];
this.edges = this.path.LineSegments.Select(s => new Path(s))
this.edges = lines.Select(s => new Path(s))
.Select((path, i) => new Edge(path, ColorAt(i), ColorAt(i + 1))).ToList();
}
/// <summary>
/// Initializes a new instance of the <see cref="PathGradientBrush"/> class.
/// </summary>
/// <param name="lines">Line segments of a polygon that represents the gradient area.</param>
/// <param name="points">Points that constitute a polygon that represents the gradient area.</param>
/// <param name="colors">Array of colors that correspond to each point in the polygon.</param>
public PathGradientBrush(ILineSegment[] lines, Color[] colors)
: this(lines, colors, CalculateCenterColor(colors))
public PathGradientBrush(PointF[] points, Color[] colors)
: this(points, colors, CalculateCenterColor(colors))
{
}
@ -82,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing
GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return new PathGradientBrushApplicator<TPixel>(source, this.path, this.edges, this.centerColor, options);
return new PathGradientBrushApplicator<TPixel>(source, this.edges, this.centerColor, options);
}
private static Color CalculateCenterColor(Color[] colors)
@ -182,8 +188,6 @@ namespace SixLabors.ImageSharp.Processing
private class PathGradientBrushApplicator<TPixel> : BrushApplicator<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private readonly Path path;
private readonly PointF center;
private readonly Vector4 centerColor;
@ -196,24 +200,21 @@ namespace SixLabors.ImageSharp.Processing
/// Initializes a new instance of the <see cref="PathGradientBrushApplicator{TPixel}"/> class.
/// </summary>
/// <param name="source">The source image.</param>
/// <param name="path">A polygon that represents the gradient area.</param>
/// <param name="edges">Edges of the polygon.</param>
/// <param name="centerColor">Color at the center of the gradient area to which the other colors converge.</param>
/// <param name="options">The options.</param>
public PathGradientBrushApplicator(
ImageFrame<TPixel> source,
Path path,
IList<Edge> edges,
Color centerColor,
GraphicsOptions options)
: base(source, options)
{
this.path = path;
this.edges = edges;
PointF[] points = path.LineSegments.Select(s => s.EndPoint).ToArray();
PointF[] points = edges.Select(s => s.Start).ToArray();
this.center = points.Aggregate((p1, p2) => p1 + p2) / points.Length;
this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count;
this.centerColor = centerColor.ToVector4();
this.maxDistance = points.Select(p => (Vector2)(p - this.center)).Select(d => d.Length()).Max();

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

@ -7,7 +7,6 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using SixLabors.Shapes;
using Xunit;
@ -27,17 +26,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing
TolerantComparer,
image =>
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(0, 0))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) };
Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green };
var brush = new PathGradientBrush(path, colors);
var brush = new PathGradientBrush(points, colors);
image.Mutate(x => x.Fill(brush));
image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
@ -53,16 +45,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing
TolerantComparer,
image =>
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(5, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(5, 0))
};
PointF[] points = { new PointF(5, 0), new PointF(10, 10), new PointF(0, 10) };
Color[] colors = { Color.Red, Color.Green, Color.Blue };
var brush = new PathGradientBrush(path, colors);
var brush = new PathGradientBrush(points, colors);
image.Mutate(x => x.Fill(brush));
image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
@ -76,17 +62,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing
{
using (Image<TPixel> image = provider.GetImage())
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(0, 0))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) };
Color[] colors = { Color.Red };
var brush = new PathGradientBrush(path, colors);
var brush = new PathGradientBrush(points, colors);
image.Mutate(x => x.Fill(brush));
@ -103,17 +82,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing
TolerantComparer,
image =>
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(0, 0))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) };
Color[] colors = { Color.Red, Color.Yellow };
var brush = new PathGradientBrush(path, colors);
var brush = new PathGradientBrush(points, colors);
image.Mutate(x => x.Fill(brush));
image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
@ -129,17 +101,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing
TolerantComparer,
image =>
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(0, 0))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) };
Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green };
var brush = new PathGradientBrush(path, colors, Color.White);
var brush = new PathGradientBrush(points, colors, Color.White);
image.Mutate(x => x.Fill(brush));
image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
@ -157,17 +122,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}
[Fact]
public void ShouldThrowArgumentOutOfRangeExceptionWhenLessThan3LinesAreGiven()
public void ShouldThrowArgumentOutOfRangeExceptionWhenLessThan3PointsAreGiven()
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0) };
Color[] colors = { Color.Black, Color.Red, Color.Yellow, Color.Green };
PathGradientBrush Create() => new PathGradientBrush(path, colors, Color.White);
PathGradientBrush Create() => new PathGradientBrush(points, colors, Color.White);
Assert.Throws<ArgumentOutOfRangeException>(Create);
}
@ -175,15 +135,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
[Fact]
public void ShouldThrowArgumentNullExceptionWhenColorsAreNull()
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(0, 0))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) };
PathGradientBrush Create() => new PathGradientBrush(path, null, Color.White);
PathGradientBrush Create() => new PathGradientBrush(points, null, Color.White);
Assert.Throws<ArgumentNullException>(Create);
}
@ -191,17 +145,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing
[Fact]
public void ShouldThrowArgumentOutOfRangeExceptionWhenEmptyColorArrayIsGiven()
{
ILineSegment[] path =
{
new LinearLineSegment(new PointF(0, 0), new PointF(10, 0)),
new LinearLineSegment(new PointF(10, 0), new PointF(10, 10)),
new LinearLineSegment(new PointF(10, 10), new PointF(0, 10)),
new LinearLineSegment(new PointF(0, 10), new PointF(0, 0))
};
PointF[] points = { new PointF(0, 0), new PointF(10, 0), new PointF(10, 10), new PointF(0, 10) };
var colors = new Color[0];
PathGradientBrush Create() => new PathGradientBrush(path, colors, Color.White);
PathGradientBrush Create() => new PathGradientBrush(points, colors, Color.White);
Assert.Throws<ArgumentOutOfRangeException>(Create);
}

Loading…
Cancel
Save