From 7e06b63420dea2ca51ecaad108d182ff2bc7919e Mon Sep 17 00:00:00 2001 From: Xavier Cho Date: Thu, 12 Sep 2019 19:37:07 +0900 Subject: [PATCH] Accept points instead of line segments as constructor argument Note that this is a breaking change. --- .../Processing/PathGradientBrush.cs | 43 +++++----- .../Drawing/FillPathGradientBrushTests.cs | 86 ++++--------------- 2 files changed, 39 insertions(+), 90 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs index 636551b64..7315dc5a3 100644 --- a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs @@ -18,8 +18,6 @@ namespace SixLabors.ImageSharp.Processing /// public sealed class PathGradientBrush : IBrush { - private readonly Polygon path; - private readonly IList edges; private readonly Color centerColor; @@ -27,20 +25,20 @@ namespace SixLabors.ImageSharp.Processing /// /// Initializes a new instance of the class. /// - /// Line segments of a polygon that represents the gradient area. + /// Points that constitute a polygon that represents the gradient area. /// Array of colors that correspond to each point in the polygon. /// Color at the center of the gradient area to which the other colors converge. - 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(); } /// /// Initializes a new instance of the class. /// - /// Line segments of a polygon that represents the gradient area. + /// Points that constitute a polygon that represents the gradient area. /// Array of colors that correspond to each point in the polygon. - 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 { - return new PathGradientBrushApplicator(source, this.path, this.edges, this.centerColor, options); + return new PathGradientBrushApplicator(source, this.edges, this.centerColor, options); } private static Color CalculateCenterColor(Color[] colors) @@ -182,8 +188,6 @@ namespace SixLabors.ImageSharp.Processing private class PathGradientBrushApplicator : BrushApplicator where TPixel : struct, IPixel { - 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 class. /// /// The source image. - /// A polygon that represents the gradient area. /// Edges of the polygon. /// Color at the center of the gradient area to which the other colors converge. /// The options. public PathGradientBrushApplicator( ImageFrame source, - Path path, IList 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(); diff --git a/tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs index d76893108..1ab747baf 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPathGradientBrushTests.cs +++ b/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 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(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(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(Create); }