diff --git a/src/ImageSharp.Drawing.Paths/ShapePath.cs b/src/ImageSharp.Drawing.Paths/ShapePath.cs index 8c9500e55f..34e77b8074 100644 --- a/src/ImageSharp.Drawing.Paths/ShapePath.cs +++ b/src/ImageSharp.Drawing.Paths/ShapePath.cs @@ -101,8 +101,8 @@ namespace ImageSharp.Drawing /// public override int ScanY(int y, float[] buffer, int length, int offset) { - Vector2 start = new Vector2(float.MinValue, y); - Vector2 end = new Vector2(float.MaxValue, y); + Vector2 start = new Vector2(this.Bounds.Left - 1, y); + Vector2 end = new Vector2(this.Bounds.Right + 1, y); Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); try { diff --git a/src/ImageSharp.Drawing.Paths/ShapeRegion.cs b/src/ImageSharp.Drawing.Paths/ShapeRegion.cs index a1fdd7b8c0..5adec67908 100644 --- a/src/ImageSharp.Drawing.Paths/ShapeRegion.cs +++ b/src/ImageSharp.Drawing.Paths/ShapeRegion.cs @@ -81,8 +81,8 @@ namespace ImageSharp.Drawing /// public override int ScanY(int y, float[] buffer, int length, int offset) { - Vector2 start = new Vector2(float.MinValue, y); - Vector2 end = new Vector2(float.MaxValue, y); + Vector2 start = new Vector2(this.Bounds.Left - 1, y); + Vector2 end = new Vector2(this.Bounds.Right + 1, y); Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); try { diff --git a/src/ImageSharp.Drawing.Paths/project.json b/src/ImageSharp.Drawing.Paths/project.json index a186f362c7..1bd998ea79 100644 --- a/src/ImageSharp.Drawing.Paths/project.json +++ b/src/ImageSharp.Drawing.Paths/project.json @@ -44,7 +44,7 @@ "ImageSharp.Drawing": { "target": "project" }, - "SixLabors.Shapes": "0.1.0-alpha0002", + "SixLabors.Shapes": "0.1.0-alpha0003", "StyleCop.Analyzers": { "version": "1.0.0", "type": "build" diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs index 6a37a1ae5b..4f1ee34ac1 100644 --- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs @@ -57,7 +57,7 @@ namespace ImageSharp.Drawing.Processors /// protected override void OnApply(ImageBase source, Rectangle sourceRectangle) { - Rectangle rect = RectangleF.Ceiling(this.Region.Bounds); // rounds the points out away from the center + Rectangle rect = this.Region.Bounds; int polyStartY = sourceRectangle.Y - DrawPadding; int polyEndY = sourceRectangle.Bottom + DrawPadding; @@ -102,6 +102,13 @@ namespace ImageSharp.Drawing.Processors return; } + if (pointsFound == 1 && maxIntersections > 1) + { + // we must have clipped a corner lets just duplicate it into point 2 and continue :) + buffer[1] = buffer[0]; + pointsFound++; + } + if (pointsFound % 2 == 1) { // we seem to have just clipped a corner lets just skip it @@ -246,6 +253,13 @@ namespace ImageSharp.Drawing.Processors return; } + if (pointsFound == 1 && maxIntersections > 1) + { + // we must have clipped a corner lets just duplicate it into point 2 and continue :) + buffer[1] = buffer[0]; + pointsFound++; + } + if (pointsFound % 2 == 1) { // we seem to have just clipped a corner lets just skip it diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs index 5533fbc0a5..a41afd3334 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs @@ -13,6 +13,7 @@ namespace ImageSharp.Tests.Drawing using System.Numerics; using Xunit; using ImageSharp.Drawing.Brushes; + using SixLabors.Shapes; public class SolidPolygonTests : FileTestBase { @@ -151,7 +152,7 @@ namespace ImageSharp.Tests.Drawing { image .BackgroundColor(Color.Blue) - .Fill(Color.HotPink, new SixLabors.Shapes.Rectangle(10,10, 190, 140)) + .Fill(Color.HotPink, new SixLabors.Shapes.Rectangle(10, 10, 190, 140)) .Save(output); } @@ -169,5 +170,78 @@ namespace ImageSharp.Tests.Drawing } } } + + [Fact] + public void ImageShouldBeOverlayedByFilledTriangle() + { + string path = this.CreateOutputDirectory("Drawing", "FilledPolygons"); + + using (Image image = new Image(100, 100)) + { + using (FileStream output = File.OpenWrite($"{path}/Triangle.png")) + { + image + .BackgroundColor(Color.Blue) + .Fill(Color.HotPink, new RegularPolygon(50, 50, 3, 30)) + .Save(output); + } + + using (PixelAccessor sourcePixels = image.Lock()) + { + Assert.Equal(Color.HotPink, sourcePixels[25, 35]); + + Assert.Equal(Color.HotPink, sourcePixels[50, 79]); + + Assert.Equal(Color.HotPink, sourcePixels[75, 35]); + + Assert.Equal(Color.HotPink, sourcePixels[50, 50]); + + Assert.Equal(Color.Blue, sourcePixels[2, 2]); + + Assert.Equal(Color.Blue, sourcePixels[28, 60]); + + Assert.Equal(Color.Blue, sourcePixels[67, 67]); + } + } + } + + [Fact] + public void ImageShouldBeOverlayedByFilledSeptagon() + { + string path = this.CreateOutputDirectory("Drawing", "FilledPolygons"); + + var config = Configuration.CreateDefaultInstance(); + config.ParallelOptions.MaxDegreeOfParallelism = 1; + using (Image image = new Image(100, 100, config)) + { + using (FileStream output = File.OpenWrite($"{path}/Septagon.png")) + { + image + .BackgroundColor(Color.Blue) + .Fill(Color.HotPink, new RegularPolygon(50, 50, 7, 30, -(float)Math.PI)) + .Save(output); + } + } + } + + [Fact] + public void ImageShouldBeOverlayedByFilledEllipse() + { + string path = this.CreateOutputDirectory("Drawing", "FilledPolygons"); + + var config = Configuration.CreateDefaultInstance(); + config.ParallelOptions.MaxDegreeOfParallelism = 1; + using (Image image = new Image(100, 100, config)) + { + using (FileStream output = File.OpenWrite($"{path}/ellipse.png")) + { + image + .BackgroundColor(Color.Blue) + .Fill(Color.HotPink, new Ellipse(50, 50, 30, 50) + .Rotate((float)(Math.PI / 3))) + .Save(output); + } + } + } } }