diff --git a/src/ImageSharp.Drawing/Primitives/Region.cs b/src/ImageSharp.Drawing/Primitives/Region.cs deleted file mode 100644 index 408c8d91..00000000 --- a/src/ImageSharp.Drawing/Primitives/Region.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; - -namespace SixLabors.ImageSharp.Drawing -{ - /// - /// Represents a region of an image. - /// - public abstract class Region - { - /// - /// Gets the bounding box that entirely surrounds this region. - /// - public abstract Rectangle Bounds { get; } - - // We should consider removing Region, so keeping this internal for now. - internal abstract IPath Shape { get; } - } -} diff --git a/src/ImageSharp.Drawing/Primitives/ShapePath.cs b/src/ImageSharp.Drawing/Primitives/ShapePath.cs deleted file mode 100644 index 083d1351..00000000 --- a/src/ImageSharp.Drawing/Primitives/ShapePath.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Drawing.Processing; - -namespace SixLabors.ImageSharp.Drawing -{ - /// - /// A mapping between a and a region. - /// - internal class ShapePath : ShapeRegion - { - /// - /// Initializes a new instance of the class. - /// - /// The shape. - /// The pen to apply to the shape. - public ShapePath(IPath shape, IPen pen) - : base(shape.GenerateOutline(pen.StrokeWidth, pen.StrokePattern)) - { - } - } -} diff --git a/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs b/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs deleted file mode 100644 index 2b39567d..00000000 --- a/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; - -namespace SixLabors.ImageSharp.Drawing -{ - /// - /// A mapping between a and a region. - /// - internal class ShapeRegion : Region - { - /// - /// Initializes a new instance of the class. - /// - /// The shape. - public ShapeRegion(IPath shape) - { - IPath closedPath = shape.AsClosedPath(); - this.Shape = closedPath; - int left = (int)MathF.Floor(shape.Bounds.Left); - int top = (int)MathF.Floor(shape.Bounds.Top); - - int right = (int)MathF.Ceiling(shape.Bounds.Right); - int bottom = (int)MathF.Ceiling(shape.Bounds.Bottom); - this.Bounds = Rectangle.FromLTRB(left, top, right, bottom); - } - - /// - /// Gets the fillable shape - /// - internal override IPath Shape { get; } - - /// - public override Rectangle Bounds { get; } - } -} diff --git a/src/ImageSharp.Drawing/Processing/Extensions/ClearExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/ClearExtensions.cs index 4fc1ef41..0296601f 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/ClearExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/ClearExtensions.cs @@ -1,72 +1,66 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Drawing.Processing { /// - /// Adds extensions that allow the clearing of regions with various brushes to the type. + /// Adds extensions that allow the flood filling of images without blending. /// public static class ClearExtensions { /// - /// Clones the graphic options and applies changes required to force clearing. + /// Flood fills the image with the specified color without any blending. /// - /// The options to clone - /// A clone of option with ColorBlendingMode, AlphaCompositionMode, and BlendPercentage set - internal static GraphicsOptions CloneForClearOperation(this GraphicsOptions options) - { - options = options.DeepClone(); - options.ColorBlendingMode = PixelFormats.PixelColorBlendingMode.Normal; - options.AlphaCompositionMode = PixelFormats.PixelAlphaCompositionMode.Src; - options.BlendPercentage = 1; - return options; - } + /// The image processing context. + /// The color. + /// The to allow chaining of operations. + public static IImageProcessingContext Clear(this IImageProcessingContext source, Color color) + => source.Clear(new SolidBrush(color)); /// - /// Flood fills the image with the specified brush without any blending. + /// Flood fills the image with the specified color without any blending. /// - /// The image this method extends. - /// The graphics options. - /// The details how to fill the region of interest. + /// The image processing context. + /// The drawing options. + /// The color. /// The to allow chaining of operations. - public static IImageProcessingContext Clear( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush) - => source.Fill(options.CloneForClearOperation(), brush); + public static IImageProcessingContext Clear(this IImageProcessingContext source, DrawingOptions options, Color color) + => source.Clear(options, new SolidBrush(color)); /// /// Flood fills the image with the specified brush without any blending. /// - /// The image this method extends. - /// The details how to fill the region of interest. + /// The image processing context. + /// The brush. /// The to allow chaining of operations. public static IImageProcessingContext Clear(this IImageProcessingContext source, IBrush brush) => - source.Clear(source.GetGraphicsOptions(), brush); + source.Clear(source.GetDrawingOptions(), brush); /// - /// Flood fills the image with the specified color without any blending. + /// Flood fills the image with the specified brush without any blending. /// - /// The image this method extends. - /// The graphics options. - /// The color. + /// The image processing context. + /// The drawing options. + /// The brush. /// The to allow chaining of operations. - public static IImageProcessingContext Clear( - this IImageProcessingContext source, - GraphicsOptions options, - Color color) => - source.Clear(options, new SolidBrush(color)); + public static IImageProcessingContext Clear(this IImageProcessingContext source, DrawingOptions options, IBrush brush) + => source.Fill(options.CloneForClearOperation(), brush); /// - /// Flood fills the image with the specified color without any blending. + /// Clones the path graphic options and applies changes required to force clearing. /// - /// The image this method extends. - /// The color. - /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, Color color) => - source.Clear(new SolidBrush(color)); + /// The drawing options to clone + /// A clone of shapeOptions with ColorBlendingMode, AlphaCompositionMode, and BlendPercentage set + internal static DrawingOptions CloneForClearOperation(this DrawingOptions drawingOptions) + { + GraphicsOptions options = drawingOptions.GraphicsOptions.DeepClone(); + options.ColorBlendingMode = PixelFormats.PixelColorBlendingMode.Normal; + options.AlphaCompositionMode = PixelFormats.PixelAlphaCompositionMode.Src; + options.BlendPercentage = 1F; + + return new DrawingOptions(options, drawingOptions.ShapeOptions, drawingOptions.TextOptions, drawingOptions.Transform); + } } } diff --git a/src/ImageSharp.Drawing/Processing/Extensions/ClearPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/ClearPathExtensions.cs index 49da2bd3..56d80d38 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/ClearPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/ClearPathExtensions.cs @@ -1,79 +1,73 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Drawing.Processing { /// - /// Adds extensions that allow the filling of polygon outlines to the type. + /// Adds extensions that allow the flood filling of polygon outlines without blending. /// public static class ClearPathExtensions { /// - /// Clones the shape graphic options and applies changes required to force clearing. + /// Flood fills the image within the provided region defined by an using the specified + /// color without any blending. /// - /// The options to clone - /// A clone of shapeOptions with ColorBlendingMode, AlphaCompositionMode, and BlendPercentage set - internal static DrawingOptions CloneForClearOperation(this DrawingOptions shapeOptions) - { - GraphicsOptions options = shapeOptions.GraphicsOptions.DeepClone(); - options.ColorBlendingMode = PixelFormats.PixelColorBlendingMode.Normal; - options.AlphaCompositionMode = PixelFormats.PixelAlphaCompositionMode.Src; - options.BlendPercentage = 1; - - return new DrawingOptions(options, shapeOptions.ShapeOptions, shapeOptions.TextOptions, shapeOptions.Transform); - } + /// The image processing context. + /// The color. + /// The defining the region to fill. + /// The to allow chaining of operations. + public static IImageProcessingContext Clear( + this IImageProcessingContext source, + Color color, + IPath region) + => source.Clear(new SolidBrush(color), region); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush without any blending. + /// Flood fills the image within the provided region defined by an using the specified color + /// without any blending. /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The shape. + /// The image processing context. + /// The drawing options. + /// The color. + /// The defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Clear( this IImageProcessingContext source, DrawingOptions options, - IBrush brush, - IPath path) => - source.Fill(options.CloneForClearOperation(), brush, path); + Color color, + IPath region) + => source.Clear(options, new SolidBrush(color), region); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush without any blending. + /// Flood fills the image within the provided region defined by an using the specified brush + /// without any blending. /// - /// The image this method extends. + /// The image processing context. /// The brush. - /// The path. + /// The defining the region to fill. /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, IBrush brush, IPath path) => - source.Clear(source.GetDrawingOptions(), brush, path); + public static IImageProcessingContext Clear( + this IImageProcessingContext source, + IBrush brush, + IPath region) + => source.Clear(source.GetDrawingOptions(), brush, region); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush without any blending. + /// Flood fills the image within the provided region defined by an using the specified brush + /// without any blending. /// - /// The image this method extends. - /// The options. - /// The color. - /// The path. + /// The image processing context. + /// The drawing options. + /// The brush. + /// The defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Clear( this IImageProcessingContext source, DrawingOptions options, - Color color, - IPath path) => - source.Clear(options, new SolidBrush(color), path); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush without any blending. - /// - /// The image this method extends. - /// The color. - /// The path. - /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, Color color, IPath path) => - source.Clear(new SolidBrush(color), path); + IBrush brush, + IPath region) + => source.Fill(options.CloneForClearOperation(), brush, region); } } diff --git a/src/ImageSharp.Drawing/Processing/Extensions/ClearRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/ClearRectangleExtensions.cs index 31e31a61..c3d2142c 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/ClearRectangleExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/ClearRectangleExtensions.cs @@ -6,58 +6,61 @@ namespace SixLabors.ImageSharp.Drawing.Processing { /// - /// Adds extensions that allow the filling of rectangles to the type. + /// Adds extensions that allow the flood filling of rectangle outlines without blending. /// public static class ClearRectangleExtensions { /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush without any blending. + /// Flood fills the image in the rectangle of the provided rectangle with the specified color without any blending. /// /// The image this method extends. - /// The options. - /// The brush. - /// The shape. + /// The color. + /// The rectangle defining the region to fill. /// The to allow chaining of operations. - public static IImageProcessingContext Clear( - this IImageProcessingContext source, - DrawingOptions options, - IBrush brush, - RectangleF shape) => - source.Clear(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext Clear(this IImageProcessingContext source, Color color, RectangleF rectangle) + => source.Clear(new SolidBrush(color), rectangle); /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush without any blending. + /// Flood fills the image in the rectangle of the provided rectangle with the specified color without any blending. /// /// The image this method extends. - /// The brush. - /// The shape. + /// The drawing options. + /// The color. + /// The rectangle defining the region to fill. /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, IBrush brush, RectangleF shape) => - source.Clear(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext Clear( + this IImageProcessingContext source, + DrawingOptions options, + Color color, + RectangleF rectangle) + => source.Clear(options, new SolidBrush(color), rectangle); /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush without any blending. + /// Flood fills the image in the rectangle of the provided rectangle with the specified brush without any blending. /// /// The image this method extends. - /// The options. - /// The color. - /// The shape. + /// The brush. + /// The rectangle defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Clear( this IImageProcessingContext source, - DrawingOptions options, - Color color, - RectangleF shape) => - source.Clear(options, new SolidBrush(color), shape); + IBrush brush, + RectangleF rectangle) + => source.Clear(brush, new RectangularPolygon(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height)); /// - /// Flood fills the image in the shape of the provided rectangle with the specified brush without any blending. + /// Flood fills the image at the given rectangle bounds with the specified brush without any blending. /// /// The image this method extends. - /// The color. - /// The shape. + /// The drawing options. + /// The brush. + /// The rectangle defining the region to fill. /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, Color color, RectangleF shape) => - source.Clear(new SolidBrush(color), shape); + public static IImageProcessingContext Clear( + this IImageProcessingContext source, + DrawingOptions options, + IBrush brush, + RectangleF rectangle) + => source.Clear(options, brush, new RectangularPolygon(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height)); } } diff --git a/src/ImageSharp.Drawing/Processing/Extensions/ClearRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/ClearRegionExtensions.cs deleted file mode 100644 index 3f5a2604..00000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/ClearRegionExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Drawing.Processing -{ - /// - /// Adds extensions that allow the filling of regions with various brushes to the type. - /// - public static class ClearRegionExtensions - { - /// - /// Flood fills the image with in the region with the specified brush without any blending. - /// - /// The image this method extends. - /// The brush. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, IBrush brush, Region region) => - source.Clear(source.GetDrawingOptions(), brush, region); - - /// - /// Flood fills the image with in the region with the specified brush without any blending. - /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Clear( - this IImageProcessingContext source, - DrawingOptions options, - IBrush brush, - Region region) => - source.Fill(options.CloneForClearOperation(), brush, region); - - /// - /// Flood fills the image with in the region with the specified color without any blending. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Clear( - this IImageProcessingContext source, - DrawingOptions options, - Color color, - Region region) => - source.Clear(options, new SolidBrush(color), region); - - /// - /// Flood fills the image with in the region with the specified color without any blending. - /// - /// The image this method extends. - /// The color. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Clear(this IImageProcessingContext source, Color color, Region region) => - source.Clear(new SolidBrush(color), region); - } -} diff --git a/src/ImageSharp.Drawing/Processing/Extensions/ClipPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/ClipPathExtensions.cs new file mode 100644 index 00000000..ce217220 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Extensions/ClipPathExtensions.cs @@ -0,0 +1,28 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; +using SixLabors.ImageSharp.Processing; + +namespace SixLabors.ImageSharp.Drawing.Processing +{ + /// + /// Adds extensions that allow the application of processors within a clipped path. + /// + public static class ClipPathExtensions + { + /// + /// Applies the processing operation within the provided region defined by an . + /// + /// The image processing context. + /// The defining the region to operation within. + /// The operation to perform. + /// The to allow chaining of operations. + public static IImageProcessingContext Clip( + this IImageProcessingContext source, + IPath region, + Action operation) + => source.ApplyProcessor(new ClipPathProcessor(source.GetDrawingOptions(), region, operation)); + } +} diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillExtensions.cs index ae12ebcc..ea26849c 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillExtensions.cs @@ -7,52 +7,46 @@ namespace SixLabors.ImageSharp.Drawing.Processing { /// - /// Adds extensions that allow the filling of regions with various brushes to the type. + /// Adds extensions that allow the flood filling of images. /// public static class FillExtensions { /// - /// Flood fills the image with the specified brush. + /// Flood fills the image with the specified color. /// - /// The image this method extends. - /// The graphics options. - /// The details how to fill the region of interest. + /// The image processing context. + /// The color. /// The to allow chaining of operations. - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - IBrush brush) => - source.ApplyProcessor(new FillProcessor(options, brush)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) + => source.Fill(new SolidBrush(color)); /// - /// Flood fills the image with the specified brush. + /// Flood fills the image with the specified color. /// - /// The image this method extends. - /// The details how to fill the region of interest. + /// The image processing context. + /// The drawing options. + /// The color. /// The to allow chaining of operations. - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) => - source.Fill(source.GetGraphicsOptions(), brush); + public static IImageProcessingContext Fill(this IImageProcessingContext source, DrawingOptions options, Color color) + => source.Fill(options, new SolidBrush(color)); /// - /// Flood fills the image with the specified color. + /// Flood fills the image with the specified brush. /// - /// The image this method extends. - /// The graphics options. - /// The color. + /// The image processing context. + /// The brush. /// The to allow chaining of operations. - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - GraphicsOptions options, - Color color) => - source.Fill(options, new SolidBrush(color)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) + => source.Fill(source.GetDrawingOptions(), brush); /// - /// Flood fills the image with the specified color. + /// Flood fills the image with the specified brush. /// - /// The image this method extends. - /// The color. + /// The image processing context. + /// The drawing options. + /// The brush. /// The to allow chaining of operations. - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) => - source.Fill(new SolidBrush(color)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, DrawingOptions options, IBrush brush) + => source.ApplyProcessor(new FillProcessor(options, brush)); } } diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs index f705b68c..a6b4e63d 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs @@ -7,69 +7,73 @@ namespace SixLabors.ImageSharp.Drawing.Processing { /// - /// Adds extensions that allow the filling of polygons with various brushes to the type. + /// Adds extensions that allow the flood filling of polygon outlines. /// public static class FillPathBuilderExtensions { /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// Flood fills the image within the provided region defined by an method + /// using the specified color. /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The shape. + /// The image processing context. + /// The color. + /// The method defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Fill( this IImageProcessingContext source, - DrawingOptions options, - IBrush brush, - Action path) - { - var pb = new PathBuilder(); - path(pb); - - return source.Fill(options, brush, pb.Build()); - } + Color color, + Action region) + => source.Fill(new SolidBrush(color), region); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// Flood fills the image within the provided region defined by an method + /// using the specified color. /// - /// The image this method extends. - /// The brush. - /// The path. + /// The image processing context. + /// The drawing options. + /// The color. + /// The method defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Fill( this IImageProcessingContext source, - IBrush brush, - Action path) => - source.Fill(source.GetDrawingOptions(), brush, path); + DrawingOptions options, + Color color, + Action region) + => source.Fill(options, new SolidBrush(color), region); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// Flood fills the image within the provided region defined by an method + /// using the specified brush. /// - /// The image this method extends. - /// The options. - /// The color. - /// The path. + /// The image processing context. + /// The brush. + /// The method defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Fill( this IImageProcessingContext source, - DrawingOptions options, - Color color, - Action path) => - source.Fill(options, new SolidBrush(color), path); + IBrush brush, + Action region) + => source.Fill(source.GetDrawingOptions(), brush, region); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// Flood fills the image within the provided region defined by an method + /// using the specified brush. /// - /// The image this method extends. - /// The color. - /// The path. + /// The image processing context. + /// The graphics options. + /// The brush. + /// The method defining the region to fill. /// The to allow chaining of operations. public static IImageProcessingContext Fill( this IImageProcessingContext source, - Color color, - Action path) => - source.Fill(new SolidBrush(color), path); + DrawingOptions options, + IBrush brush, + Action region) + { + var pb = new PathBuilder(); + region(pb); + + return source.Fill(options, brush, pb.Build()); + } } } diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs index 201a1b96..90b4b77c 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs @@ -7,42 +7,30 @@ namespace SixLabors.ImageSharp.Drawing.Processing { /// - /// Adds extensions that allow the filling of polygon outlines to the type. + /// Adds extensions that allow the filling of polygon outlines. /// public static class FillPathExtensions { /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The shape. + /// The image processing context. + /// The color. + /// The logic path. /// The to allow chaining of operations. public static IImageProcessingContext Fill( this IImageProcessingContext source, - DrawingOptions options, - IBrush brush, + Color color, IPath path) => - source.ApplyProcessor(new FillPathProcessor(options, brush, path)); + source.Fill(new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. - /// The brush. - /// The path. - /// The to allow chaining of operations. - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) => - source.Fill(source.GetDrawingOptions(), brush, path); - - /// - /// Flood fills the image in the shape of the provided polygon with the specified brush.. - /// - /// The image this method extends. - /// The options. + /// The image processing context. + /// The drawing options. /// The color. - /// The path. + /// The logic path. /// The to allow chaining of operations. public static IImageProcessingContext Fill( this IImageProcessingContext source, @@ -52,13 +40,31 @@ public static IImageProcessingContext Fill( source.Fill(options, new SolidBrush(color), path); /// - /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. - /// The color. - /// The path. + /// The image processing context. + /// The brush. + /// The logic path. /// The to allow chaining of operations. - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) => - source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + IBrush brush, + IPath path) => + source.Fill(source.GetDrawingOptions(), brush, path); + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// + /// The image processing context. + /// The drawing options. + /// The brush. + /// The shape. + /// The to allow chaining of operations. + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + DrawingOptions options, + IBrush brush, + IPath path) => + source.ApplyProcessor(new FillPathProcessor(options, brush, path)); } } diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs deleted file mode 100644 index 146519f7..00000000 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Processing; - -namespace SixLabors.ImageSharp.Drawing.Processing -{ - /// - /// Adds extensions that allow the filling of regions with various brushes to the type. - /// - public static class FillRegionExtensions - { - /// - /// Flood fills the image with in the region with the specified brush. - /// - /// The image this method extends. - /// The brush. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) => - source.Fill(source.GetDrawingOptions(), brush, region); - - /// - /// Flood fills the image with in the region with the specified brush. - /// - /// The image this method extends. - /// The graphics options. - /// The brush. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - DrawingOptions options, - IBrush brush, - Region region) => - source.ApplyProcessor(new FillRegionProcessor(options, brush, region)); - - /// - /// Flood fills the image with in the region with the specified color. - /// - /// The image this method extends. - /// The options. - /// The color. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Fill( - this IImageProcessingContext source, - DrawingOptions options, - Color color, - Region region) => - source.Fill(options, new SolidBrush(color), region); - - /// - /// Flood fills the image with in the region with the specified color. - /// - /// The image this method extends. - /// The color. - /// The region. - /// The to allow chaining of operations. - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) => - source.Fill(new SolidBrush(color), region); - } -} diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs index c8887c02..a823acb0 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -18,13 +18,32 @@ public class ImageBrush : IBrush /// private readonly Image image; + /// + /// The region of the source image we will be using to paint. + /// + private readonly RectangleF region; + /// /// Initializes a new instance of the class. /// /// The image. public ImageBrush(Image image) + : this(image, image.Bounds()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The image. + /// + /// The region of interest. + /// This overrides any region used to intitialize the brush applicator. + /// + internal ImageBrush(Image image, RectangleF region) { this.image = image; + this.region = region; } /// @@ -37,17 +56,17 @@ public BrushApplicator CreateApplicator( { if (this.image is Image specificImage) { - return new ImageBrushApplicator(configuration, options, source, specificImage, region, false); + return new ImageBrushApplicator(configuration, options, source, specificImage, region, this.region, false); } specificImage = this.image.CloneAs(); - - return new ImageBrushApplicator(configuration, options, source, specificImage, region, true); + return new ImageBrushApplicator(configuration, options, source, specificImage, region, this.region, true); } /// /// The image brush applicator. /// + /// The pixel format. private class ImageBrushApplicator : BrushApplicator where TPixel : unmanaged, IPixel { @@ -58,14 +77,9 @@ private class ImageBrushApplicator : BrushApplicator private readonly bool shouldDisposeImage; /// - /// The y-length. + /// The region of the source image we will be using to draw from. /// - private readonly int yLength; - - /// - /// The x-length. - /// - private readonly int xLength; + private readonly Rectangle sourceRegion; /// /// The Y offset. @@ -76,7 +90,6 @@ private class ImageBrushApplicator : BrushApplicator /// The X offset. /// private readonly int offsetX; - private bool isDisposed; /// @@ -86,32 +99,35 @@ private class ImageBrushApplicator : BrushApplicator /// The graphics options. /// The target image. /// The image. - /// The region. + /// The region of the target image we will be drawing to. + /// The region of the source image we will be using to source pixels to draw from. /// Whether to dispose the image on disposal of the applicator. public ImageBrushApplicator( Configuration configuration, GraphicsOptions options, ImageFrame target, Image image, - RectangleF region, + RectangleF targetRegion, + RectangleF sourceRegion, bool shouldDisposeImage) : base(configuration, options, target) { this.sourceImage = image; this.sourceFrame = image.Frames.RootFrame; this.shouldDisposeImage = shouldDisposeImage; - this.xLength = image.Width; - this.yLength = image.Height; - this.offsetY = (int)MathF.Max(MathF.Floor(region.Top), 0); - this.offsetX = (int)MathF.Max(MathF.Floor(region.Left), 0); + + this.sourceRegion = Rectangle.Intersect(image.Bounds(), (Rectangle)sourceRegion); + + this.offsetY = (int)MathF.Max(MathF.Floor(targetRegion.Top), 0); + this.offsetX = (int)MathF.Max(MathF.Floor(targetRegion.Left), 0); } internal TPixel this[int x, int y] { get { - int srcX = (x - this.offsetX) % this.xLength; - int srcY = (y - this.offsetY) % this.yLength; + int srcX = ((x - this.offsetX) % this.sourceRegion.Width) + this.sourceRegion.X; + int srcY = ((y - this.offsetY) % this.sourceRegion.Width) + this.sourceRegion.Y; return this.sourceFrame[srcX, srcY]; } } @@ -139,32 +155,31 @@ public override void Apply(Span scanline, int x, int y) { // Create a span for colors MemoryAllocator allocator = this.Configuration.MemoryAllocator; - using (IMemoryOwner amountBuffer = allocator.Allocate(scanline.Length)) - using (IMemoryOwner overlay = allocator.Allocate(scanline.Length)) + using IMemoryOwner amountBuffer = allocator.Allocate(scanline.Length); + using IMemoryOwner overlay = allocator.Allocate(scanline.Length); + Span amountSpan = amountBuffer.Memory.Span; + Span overlaySpan = overlay.Memory.Span; + + int offsetX = x - this.offsetX; + int sourceY = ((y - this.offsetY) % this.sourceRegion.Width) + this.sourceRegion.Y; + Span sourceRow = this.sourceFrame.GetPixelRowSpan(sourceY); + + for (int i = 0; i < scanline.Length; i++) { - Span amountSpan = amountBuffer.Memory.Span; - Span overlaySpan = overlay.Memory.Span; - - int sourceY = (y - this.offsetY) % this.yLength; - int offsetX = x - this.offsetX; - Span sourceRow = this.sourceFrame.GetPixelRowSpan(sourceY); - - for (int i = 0; i < scanline.Length; i++) - { - amountSpan[i] = scanline[i] * this.Options.BlendPercentage; - - int sourceX = (i + offsetX) % this.xLength; - overlaySpan[i] = sourceRow[sourceX]; - } - - Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); - this.Blender.Blend( - this.Configuration, - destinationRow, - destinationRow, - overlaySpan, - amountSpan); + amountSpan[i] = scanline[i] * this.Options.BlendPercentage; + + int sourceX = ((i + offsetX) % this.sourceRegion.Width) + this.sourceRegion.X; + + overlaySpan[i] = sourceRow[sourceX]; } + + Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); + this.Blender.Blend( + this.Configuration, + destinationRow, + destinationRow, + overlaySpan, + amountSpan); } } } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/ClipPathProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/ClipPathProcessor.cs new file mode 100644 index 00000000..a137c1dd --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/ClipPathProcessor.cs @@ -0,0 +1,52 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; + +namespace SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing +{ + /// + /// Allows the recursive application of processing operations against an image within a given region. + /// + public class ClipPathProcessor : IImageProcessor + { + /// + /// Initializes a new instance of the class. + /// + /// The drawing options. + /// The defining the region to operate within. + /// The operation to perform on the source. + public ClipPathProcessor(DrawingOptions options, IPath path, Action operation) + { + this.Options = options; + this.Region = path; + this.Operation = operation; + } + + /// + /// Gets the drawing options. + /// + public DrawingOptions Options { get; } + + /// + /// Gets the defining the region to operate within. + /// + public IPath Region { get; } + + /// + /// Gets the operation to perform on the source. + /// + public Action Operation { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor( + Configuration configuration, + Image source, + Rectangle sourceRectangle) + where TPixel : unmanaged, IPixel + => new ClipPathProcessor(this, source, configuration, sourceRectangle); + } +} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/ClipPathProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/ClipPathProcessor{TPixel}.cs new file mode 100644 index 00000000..5bb08e32 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/ClipPathProcessor{TPixel}.cs @@ -0,0 +1,54 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; + +namespace SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing +{ + /// + /// The main workhorse class. This has access to the pixel buffer but + /// in an abstract/generic way. + /// + /// The type of pixel. + internal class ClipPathProcessor : IImageProcessor + where TPixel : unmanaged, IPixel + { + private readonly ClipPathProcessor definition; + private readonly Image source; + private readonly Configuration configuration; + private readonly Rectangle sourceRectangle; + + public ClipPathProcessor(ClipPathProcessor definition, Image source, Configuration configuration, Rectangle sourceRectangle) + { + this.definition = definition; + this.source = source; + this.configuration = configuration; + this.sourceRectangle = sourceRectangle; + } + + public void Dispose() + { + } + + public void Execute() + { + // Clone out our source image so we can apply various effects to it without mutating + // the original yet. + using Image clone = this.source.Clone(this.definition.Operation); + + // Use an image brush to apply cloned image as the source for filling the shape. + // We pass explicit bounds to avoid the need to crop the clone; + RectangleF bounds = this.definition.Region.Bounds; + var brush = new ImageBrush(clone, bounds); + + // Grab hold of an image processor that can fill paths with a brush to allow it to do the hard pixel pushing for us + var processor = new FillPathProcessor(this.definition.Options, brush, this.definition.Region); + using IImageProcessor p = processor.CreatePixelSpecificProcessor(this.configuration, this.source, this.sourceRectangle); + + // Fill the shape using the image brush + p.Execute(); + } + } +} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawPathProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawPathProcessor.cs index 806174ef..ee434b87 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawPathProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawPathProcessor.cs @@ -18,10 +18,10 @@ public class DrawPathProcessor : IImageProcessor /// /// The graphics options. /// The details how to outline the region of interest. - /// The shape to be filled. - public DrawPathProcessor(DrawingOptions options, IPen pen, IPath shape) + /// The path to be filled. + public DrawPathProcessor(DrawingOptions options, IPen pen, IPath path) { - this.Shape = shape; + this.Path = path; this.Pen = pen; this.Options = options; } @@ -32,9 +32,9 @@ public DrawPathProcessor(DrawingOptions options, IPen pen, IPath shape) public IPen Pen { get; } /// - /// Gets the region that this processor applies to. + /// Gets the path that this processor applies to. /// - public IPath Shape { get; } + public IPath Path { get; } /// /// Gets the defining how to blend the brush pixels over the image pixels. @@ -45,10 +45,14 @@ public DrawPathProcessor(DrawingOptions options, IPen pen, IPath shape) public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel { - // offset drawlines to align drawing outlines to pixel centers, and apply global transform - Matrix3x2 transform = Matrix3x2.CreateTranslation(0.5f, 0.5f) * this.Options.Transform; - IPath shape = this.Shape.Transform(transform); - return new FillRegionProcessor(this.Options, this.Pen.StrokeFill, new ShapePath(shape, this.Pen)).CreatePixelSpecificProcessor(configuration, source, sourceRectangle); + // Offset drawlines to align drawing outlines to pixel centers. + // The global transform is applied in the FillPathProcessor. + IPath outline = this.Path + .Transform(Matrix3x2.CreateTranslation(0.5F, 0.5F)) + .GenerateOutline(this.Pen.StrokeWidth, this.Pen.StrokePattern); + + return new FillPathProcessor(this.Options, this.Pen.StrokeFill, outline) + .CreatePixelSpecificProcessor(configuration, source, sourceRectangle); } } } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor.cs index 3744935d..133298a7 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; @@ -13,15 +12,20 @@ namespace SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing /// public class FillPathProcessor : IImageProcessor { + /// + /// Minimum subpixel count for rasterization, being applied even if antialiasing is off. + /// + internal const int MinimumSubpixelCount = 8; + /// /// Initializes a new instance of the class. /// /// The graphics options. /// The details how to fill the region of interest. - /// The shape to be filled. - public FillPathProcessor(DrawingOptions options, IBrush brush, IPath shape) + /// The logic path to be filled. + public FillPathProcessor(DrawingOptions options, IBrush brush, IPath path) { - this.Shape = shape; + this.Region = path; this.Brush = brush; this.Options = options; } @@ -32,9 +36,9 @@ public FillPathProcessor(DrawingOptions options, IBrush brush, IPath shape) public IBrush Brush { get; } /// - /// Gets the region that this processor applies to. + /// Gets the logic path that this processor applies to. /// - public IPath Shape { get; } + public IPath Region { get; } /// /// Gets the defining how to blend the brush pixels over the image pixels. @@ -45,22 +49,25 @@ public FillPathProcessor(DrawingOptions options, IBrush brush, IPath shape) public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel { - IPath shape = this.Shape.Transform(this.Options.Transform); + IPath shape = this.Region.Transform(this.Options.Transform); if (shape is RectangularPolygon rectPoly) { var rectF = new RectangleF(rectPoly.Location, rectPoly.Size); var rect = (Rectangle)rectF; - if (this.Options.GraphicsOptions.Antialias == false || rectF == rect) + if (!this.Options.GraphicsOptions.Antialias || rectF == rect) { var interest = Rectangle.Intersect(sourceRectangle, rect); - // cast as in and back are the same or we are using anti-aliasing - return new FillProcessor(this.Options.GraphicsOptions, this.Brush).CreatePixelSpecificProcessor(configuration, source, interest); + // Cast as in and back are the same or we are using anti-aliasing + return new FillProcessor(this.Options, this.Brush) + .CreatePixelSpecificProcessor(configuration, source, interest); } } - return new FillRegionProcessor(this.Options, this.Brush, new ShapeRegion(shape)).CreatePixelSpecificProcessor(configuration, source, sourceRectangle); + // Clone the definition so we can pass the transformed path. + var definition = new FillPathProcessor(this.Options, this.Brush, shape); + return new FillPathProcessor(configuration, definition, source, sourceRectangle); } } } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor{TPixel}.cs similarity index 72% rename from src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor{TPixel}.cs index 99a42517..625ba03b 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillPathProcessor{TPixel}.cs @@ -3,7 +3,6 @@ using System; using System.Buffers; -using SixLabors.ImageSharp.Drawing.Shapes; using SixLabors.ImageSharp.Drawing.Shapes.Rasterization; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -12,18 +11,32 @@ namespace SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing { /// - /// Using a brush and a shape fills shape with contents of brush the + /// Uses a brush and a shape to fill the shape with contents of the brush. /// /// The type of the color. /// - internal class FillRegionProcessor : ImageProcessor + internal class FillPathProcessor : ImageProcessor where TPixel : unmanaged, IPixel { - private readonly FillRegionProcessor definition; - - public FillRegionProcessor(Configuration configuration, FillRegionProcessor definition, Image source, Rectangle sourceRectangle) + private readonly FillPathProcessor definition; + private readonly IPath path; + private readonly Rectangle bounds; + + public FillPathProcessor( + Configuration configuration, + FillPathProcessor definition, + Image source, + Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) { + IPath path = definition.Region; + int left = (int)MathF.Floor(path.Bounds.Left); + int top = (int)MathF.Floor(path.Bounds.Top); + int right = (int)MathF.Ceiling(path.Bounds.Right); + int bottom = (int)MathF.Ceiling(path.Bounds.Bottom); + + this.bounds = Rectangle.FromLTRB(left, top, right, bottom); + this.path = path.AsClosedPath(); this.definition = definition; } @@ -34,30 +47,20 @@ protected override void OnFrameApply(ImageFrame source) ShapeOptions shapeOptions = this.definition.Options.ShapeOptions; GraphicsOptions graphicsOptions = this.definition.Options.GraphicsOptions; IBrush brush = this.definition.Brush; - Region region = this.definition.Region; - Rectangle rect = region.Bounds; - - bool isSolidBrushWithoutBlending = IsSolidBrushWithoutBlending(graphicsOptions, this.definition.Brush, out SolidBrush solidBrush); + bool isSolidBrushWithoutBlending = IsSolidBrushWithoutBlending(graphicsOptions, brush, out SolidBrush solidBrush); TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; // Align start/end positions. - int minX = Math.Max(0, rect.Left); - int maxX = Math.Min(source.Width, rect.Right); - int minY = Math.Max(0, rect.Top); - int maxY = Math.Min(source.Height, rect.Bottom); - if (minX >= maxX) - { - return; // no effect inside image; - } - - if (minY >= maxY) + var interest = Rectangle.Intersect(this.bounds, source.Bounds()); + if (interest.Equals(Rectangle.Empty)) { - return; // no effect inside image; + return; // No effect inside image; } - int subpixelCount = FillRegionProcessor.MinimumSubpixelCount; + int minX = interest.Left; + int subpixelCount = FillPathProcessor.MinimumSubpixelCount; - // we need to offset the pixel grid to account for when we outline a path. + // We need to offset the pixel grid to account for when we outline a path. // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# // region to align with the pixel grid. @@ -66,15 +69,15 @@ protected override void OnFrameApply(ImageFrame source) subpixelCount = Math.Max(subpixelCount, graphicsOptions.AntialiasSubpixelDepth); } - using BrushApplicator applicator = brush.CreateApplicator(configuration, graphicsOptions, source, rect); - int scanlineWidth = maxX - minX; + using BrushApplicator applicator = brush.CreateApplicator(configuration, graphicsOptions, source, interest); + int scanlineWidth = interest.Width; MemoryAllocator allocator = this.Configuration.MemoryAllocator; bool scanlineDirty = true; var scanner = PolygonScanner.Create( - region.Shape, - minY, - maxY, + this.path, + interest.Top, + interest.Bottom, subpixelCount, shapeOptions.IntersectionRule, configuration.MemoryAllocator); @@ -91,7 +94,7 @@ protected override void OnFrameApply(ImageFrame source) scanline.Clear(); } - scanlineDirty = scanner.ScanCurrentPixelLineInto(minX, 0, scanline); + scanlineDirty = scanner.ScanCurrentPixelLineInto(minX, 0F, scanline); if (scanlineDirty) { @@ -102,14 +105,14 @@ protected override void OnFrameApply(ImageFrame source) bool hasZeros = false; for (int x = 0; x < scanline.Length; x++) { - if (scanline[x] >= 0.5) + if (scanline[x] >= 0.5F) { - scanline[x] = 1; + scanline[x] = 1F; hasOnes = true; } else { - scanline[x] = 0; + scanline[x] = 0F; hasZeros = true; } } @@ -131,7 +134,6 @@ protected override void OnFrameApply(ImageFrame source) } finally { - // ref structs can't implement interfaces so technically PolygonScanner is not IDisposable scanner.Dispose(); } } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs index 62c82239..3fc9e02a 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs @@ -17,7 +17,7 @@ public class FillProcessor : IImageProcessor /// /// The defining how to blend the brush pixels over the image pixels. /// The brush to use for filling. - public FillProcessor(GraphicsOptions options, IBrush brush) + public FillProcessor(DrawingOptions options, IBrush brush) { this.Brush = brush; this.Options = options; @@ -29,9 +29,9 @@ public FillProcessor(GraphicsOptions options, IBrush brush) public IBrush Brush { get; } /// - /// Gets the defining how to blend the brush pixels over the image pixels. + /// Gets the defining how to blend the brush pixels over the image pixels. /// - public GraphicsOptions Options { get; } + public DrawingOptions Options { get; } /// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs index afdffd6d..79f1662a 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs @@ -22,9 +22,7 @@ internal class FillProcessor : ImageProcessor public FillProcessor(Configuration configuration, FillProcessor definition, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } + => this.definition = definition; /// protected override void OnFrameApply(ImageFrame source) @@ -37,7 +35,7 @@ protected override void OnFrameApply(ImageFrame source) Configuration configuration = this.Configuration; IBrush brush = this.definition.Brush; - GraphicsOptions options = this.definition.Options; + GraphicsOptions options = this.definition.Options.GraphicsOptions; // If there's no reason for blending, then avoid it. if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) @@ -81,7 +79,7 @@ private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) return false; } - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + return this.definition.Options.GraphicsOptions.IsOpaqueColorWithoutBlending(solidBrush.Color); } private readonly struct SolidBrushRowIntervalOperation : IRowIntervalOperation diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs deleted file mode 100644 index 93490db5..00000000 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; - -namespace SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing -{ - /// - /// Defines a processor to fill pixels withing a given - /// with the given and blending defined by the given . - /// - public class FillRegionProcessor : IImageProcessor - { - /// - /// Minimum subpixel count for rasterization, being applied even if antialiasing is off. - /// - internal const int MinimumSubpixelCount = 8; - - /// - /// Initializes a new instance of the class. - /// - /// The graphics options. - /// The details how to fill the region of interest. - /// The region of interest to be filled. - public FillRegionProcessor(DrawingOptions options, IBrush brush, Region region) - { - this.Region = region; - this.Brush = brush; - this.Options = options; - } - - /// - /// Gets the used for filling the destination image. - /// - public IBrush Brush { get; } - - /// - /// Gets the region that this processor applies to. - /// - public Region Region { get; } - - /// - /// Gets the defining how to blend the brush pixels over the image pixels. - /// - public DrawingOptions Options { get; } - - /// - public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) - where TPixel : unmanaged, IPixel => new FillRegionProcessor(configuration, this, source, sourceRectangle); - } -} diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs index 2f43ad94..c2e36520 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs @@ -389,7 +389,7 @@ private Buffer2D Render(IPath path) size = new Size(size.Width + (this.offset * 2), size.Height + (this.offset * 2)); - int subpixelCount = FillRegionProcessor.MinimumSubpixelCount; + int subpixelCount = FillPathProcessor.MinimumSubpixelCount; float xOffset = 0.5f; GraphicsOptions graphicsOptions = this.Options.GraphicsOptions; if (graphicsOptions.Antialias) diff --git a/src/ImageSharp.Drawing/Shapes/IPath.cs b/src/ImageSharp.Drawing/Shapes/IPath.cs index 14f0be28..0d3eb10e 100644 --- a/src/ImageSharp.Drawing/Shapes/IPath.cs +++ b/src/ImageSharp.Drawing/Shapes/IPath.cs @@ -37,7 +37,7 @@ public interface IPath /// /// Returns this path with all figures closed. /// - /// Returns the path as a closed path. + /// A new close . IPath AsClosedPath(); } } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/ClipTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/ClipTests.cs new file mode 100644 index 00000000..4d5d37fb --- /dev/null +++ b/tests/ImageSharp.Drawing.Tests/Drawing/ClipTests.cs @@ -0,0 +1,40 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using Xunit; + +namespace SixLabors.ImageSharp.Drawing.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class ClipTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, 0, 0, 0.5)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, -20, -20, 0.5)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, 20, 20, 0.5)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, 40, 60, 0.2)] + public void Clip(TestImageProvider provider, float dx, float dy, float sizeMult) + where TPixel : unmanaged, IPixel + { + FormattableString testDetails = $"offset_x{dx}_y{dy}"; + provider.RunValidatingProcessorTest( + x => + { + Size size = x.GetCurrentSize(); + int outerRadii = (int)(Math.Min(size.Width, size.Height) * sizeMult); + var star = new Star(new PointF(size.Width / 2, size.Height / 2), 5, outerRadii / 2, outerRadii); + + var builder = Matrix3x2.CreateTranslation(new Vector2(dx, dy)); + x.Clip(star.Transform(builder), x => x.DetectEdges()); + }, + testOutputDetails: testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } +} diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawPolygonTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawPolygonTests.cs index 924e3aec..18cb69ec 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawPolygonTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawPolygonTests.cs @@ -55,7 +55,7 @@ public void DrawPolygon_Transformed(TestImageProvider provider) [Theory] [WithBasicTestPatternImages(100, 100, PixelTypes.Rgba32)] public void DrawRectangularPolygon_Transformed(TestImageProvider provider) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, IPixel { var polygon = new RectangularPolygon(25, 25, 50, 50); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillPolygonTests.cs index 534d1737..abb1aec3 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillPolygonTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillPolygonTests.cs @@ -78,7 +78,7 @@ public void FillPolygon_Solid_Transformed(TestImageProvider prov [Theory] [WithBasicTestPatternImages(100, 100, PixelTypes.Rgba32)] public void Fill_RectangularPolygon_Solid_Transformed(TestImageProvider provider) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, IPixel { var polygon = new RectangularPolygon(25, 25, 50, 50); @@ -90,7 +90,7 @@ public void Fill_RectangularPolygon_Solid_Transformed(TestImageProvider< [Theory] [WithBasicTestPatternImages(100, 100, PixelTypes.Rgba32)] public void Fill_RectangularPolygon_Solid_TransformedUsingConfiguration(TestImageProvider provider) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, IPixel { var polygon = new RectangularPolygon(25, 25, 50, 50); provider.Configuration.SetDrawingTransform(Matrix3x2.CreateRotation((float)Math.PI / 4, new PointF(50, 50))); @@ -224,6 +224,33 @@ public void FillPolygon_ImageBrush(TestImageProvider provider, s } } + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Png.Ducky)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Bmp.Car)] + public void FillPolygon_ImageBrush_Rect(TestImageProvider provider, string brushImageName) + where TPixel : unmanaged, IPixel + { + PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 50), new Vector2(50, 200) + }; + + using (var brushImage = Image.Load(TestFile.Create(brushImageName).Bytes)) + { + float top = brushImage.Height / 4; + float left = brushImage.Width / 4; + float height = top * 2; + float width = left * 2; + + var brush = new ImageBrush(brushImage, new RectangleF(left, top, width, height)); + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(brush, simplePath), + System.IO.Path.GetFileNameWithoutExtension(brushImageName) + "_rect", + appendSourceFileOrDescription: false); + } + } + [Theory] [WithBasicTestPatternImages(250, 250, PixelTypes.Rgba32)] public void Fill_RectangularPolygon(TestImageProvider provider) diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillRegionProcessorTests.cs deleted file mode 100644 index 2178c0d9..00000000 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillRegionProcessorTests.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; -using Moq; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors; -using Xunit; - -namespace SixLabors.ImageSharp.Drawing.Tests.Drawing -{ - public class FillRegionProcessorTests - { - [Fact] - public void FillOffCanvas() - { - var bounds = new Rectangle(-100, -10, 10, 10); - var brush = new Mock(); - var options = new GraphicsOptions { Antialias = true }; - var processor = new FillRegionProcessor(new DrawingOptions() { GraphicsOptions = options }, brush.Object, new MockRegion1()); - var img = new Image(10, 10); - processor.Execute(img.GetConfiguration(), img, bounds); - } - - [Fact] - public void DrawOffCanvas() - { - using (var img = new Image(10, 10)) - { - img.Mutate(x => x.DrawLines( - new Pen(Color.Black, 10), - new Vector2(-10, 5), - new Vector2(20, 5))); - } - } - - [Fact] - public void DoesNotThrowForIssue928() - { - var rectText = new RectangleF(0, 0, 2000, 2000); - using (var img = new Image((int)rectText.Width, (int)rectText.Height)) - { - img.Mutate(x => x.Fill(Color.Transparent)); - - img.Mutate( - ctx => ctx.DrawLines( - Color.Red, - 0.984252f, - new PointF(104.762581f, 1074.99365f), - new PointF(104.758667f, 1075.01721f), - new PointF(104.757675f, 1075.04114f), - new PointF(104.759628f, 1075.065f), - new PointF(104.764488f, 1075.08838f), - new PointF(104.772186f, 1075.111f), - new PointF(104.782608f, 1075.13245f), - new PointF(104.782608f, 1075.13245f))); - } - } - - [Fact] - public void DoesNotThrowFillingTriangle() - { - using (var image = new Image(28, 28)) - { - var path = new Polygon( - new LinearLineSegment(new PointF(17.11f, 13.99659f), new PointF(14.01433f, 27.06201f)), - new LinearLineSegment(new PointF(14.01433f, 27.06201f), new PointF(13.79267f, 14.00023f)), - new LinearLineSegment(new PointF(13.79267f, 14.00023f), new PointF(17.11f, 13.99659f))); - - image.Mutate(ctx => ctx.Fill(Color.White, path)); - } - } - - // Mocking the region throws an error in netcore2.0 - private class MockRegion1 : Region - { - public override Rectangle Bounds => new Rectangle(-100, -10, 10, 10); - - internal override IPath Shape => throw new NotImplementedException(); - } - - private class MockRegion2 : Region - { - public MockRegion2(Rectangle bounds) - => this.Bounds = bounds; - - public override Rectangle Bounds { get; } - - internal override IPath Shape => throw new NotImplementedException(); - } - } -} diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillSolidBrushTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillSolidBrushTests.cs index 79cc6345..aa5132fd 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillSolidBrushTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillSolidBrushTests.cs @@ -150,18 +150,20 @@ public void BlendFillColorOverBackground( { TPixel bgColor = image[0, 0]; - var options = new GraphicsOptions + var options = new DrawingOptions { - Antialias = false, - ColorBlendingMode = blenderMode, - BlendPercentage = blendPercentage + GraphicsOptions = new GraphicsOptions + { + Antialias = false, + ColorBlendingMode = blenderMode, + BlendPercentage = blendPercentage + } }; if (triggerFillRegion) { - var region = new ShapeRegion(new RectangularPolygon(0, 0, 16, 16)); - - image.Mutate(c => c.SetGraphicsOptions(options).Fill(new SolidBrush(fillColor), region)); + var path = new RectangularPolygon(0, 0, 16, 16); + image.Mutate(c => c.SetGraphicsOptions(options.GraphicsOptions).Fill(new SolidBrush(fillColor), path)); } else { diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Clear.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Clear.cs index 92ae1093..9ff6a82b 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Clear.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Clear.cs @@ -1,25 +1,24 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System.Numerics; -using System.Runtime.InteropServices.ComTypes; using SixLabors.ImageSharp.Drawing.Processing; using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; using SixLabors.ImageSharp.Drawing.Tests.Processing; -using SixLabors.ImageSharp.Drawing.Tests.TestUtilities; using Xunit; namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths { public class Clear : BaseImageOperationsExtensionTest { - private readonly GraphicsOptionsComparer clearComparer = new GraphicsOptionsComparer() { SkipClearOptions = true }; - private readonly GraphicsOptions nonDefaultOptions = new GraphicsOptions() + private readonly DrawingOptions nonDefaultOptions = new DrawingOptions() { - AlphaCompositionMode = PixelFormats.PixelAlphaCompositionMode.Clear, - BlendPercentage = 0.5f, - ColorBlendingMode = PixelFormats.PixelColorBlendingMode.Darken, - AntialiasSubpixelDepth = 99 + GraphicsOptions = + { + AlphaCompositionMode = PixelFormats.PixelAlphaCompositionMode.Clear, + BlendPercentage = 0.5f, + ColorBlendingMode = PixelFormats.PixelColorBlendingMode.Darken, + AntialiasSubpixelDepth = 99 + } }; private readonly IBrush brush = new SolidBrush(Color.HotPink); @@ -31,8 +30,11 @@ public void Brush() FillProcessor processor = this.Verify(); - Assert.Equal(this.nonDefaultOptions, processor.Options, this.clearComparer); - Assert.NotEqual(this.options, processor.Options, this.clearComparer); + DrawingOptions expectedOptions = this.nonDefaultOptions; + Assert.Equal(expectedOptions.ShapeOptions, processor.Options.ShapeOptions); + Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); Assert.Equal(this.brush, processor.Brush); } @@ -44,7 +46,11 @@ public void BrushDefaultOptions() FillProcessor processor = this.Verify(); - Assert.Equal(this.options, processor.Options, this.clearComparer); + ShapeOptions expectedOptions = this.shapeOptions; + Assert.Equal(expectedOptions, processor.Options.ShapeOptions); + Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); Assert.Equal(this.brush, processor.Brush); } @@ -56,10 +62,15 @@ public void ColorSet() FillProcessor processor = this.Verify(); - Assert.Equal(this.nonDefaultOptions, processor.Options, this.clearComparer); + ShapeOptions expectedOptions = this.shapeOptions; + Assert.NotEqual(expectedOptions, processor.Options.ShapeOptions); - SolidBrush solidBrush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, solidBrush.Color); + Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); + Assert.NotEqual(this.brush, processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } [Fact] @@ -69,10 +80,15 @@ public void ColorSetDefaultOptions() FillProcessor processor = this.Verify(); - Assert.Equal(this.options, processor.Options, this.clearComparer); + ShapeOptions expectedOptions = this.shapeOptions; + Assert.Equal(expectedOptions, processor.Options.ShapeOptions); + Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - SolidBrush solidBrush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, solidBrush.Color); + Assert.NotEqual(this.brush, processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } } } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearPath.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearPath.cs index 7ddc7cf2..7b28fdbd 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearPath.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearPath.cs @@ -4,14 +4,12 @@ using SixLabors.ImageSharp.Drawing.Processing; using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; using SixLabors.ImageSharp.Drawing.Tests.Processing; -using SixLabors.ImageSharp.Drawing.Tests.TestUtilities; using Xunit; namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths { public class ClearPath : BaseImageOperationsExtensionTest { - private readonly GraphicsOptionsComparer clearComparer = new GraphicsOptionsComparer() { SkipClearOptions = true }; private readonly DrawingOptions nonDefaultOptions = new DrawingOptions() { GraphicsOptions = @@ -32,13 +30,13 @@ public void Brush() FillPathProcessor processor = this.Verify(); - DrawingOptions expectedOptions = this.nonDefaultOptions; - Assert.Equal(expectedOptions.ShapeOptions, processor.Options.ShapeOptions); + ShapeOptions expectedOptions = this.shapeOptions; + Assert.NotEqual(expectedOptions, processor.Options.ShapeOptions); Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -55,7 +53,7 @@ public void BrushDefaultOptions() Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -66,13 +64,13 @@ public void ColorSet() FillPathProcessor processor = this.Verify(); - DrawingOptions expectedOptions = this.nonDefaultOptions; - Assert.Equal(expectedOptions.ShapeOptions, processor.Options.ShapeOptions); + ShapeOptions expectedOptions = this.shapeOptions; + Assert.NotEqual(expectedOptions, processor.Options.ShapeOptions); Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); @@ -91,7 +89,7 @@ public void ColorAndThicknessDefaultOptions() Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRectangle.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRectangle.cs index 86aecf99..354932cc 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRectangle.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRectangle.cs @@ -24,7 +24,7 @@ public void Brush() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.Equal(this.brush, processor.Brush); } @@ -36,7 +36,7 @@ public void BrushDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.Equal(this.brush, processor.Brush); } @@ -48,7 +48,7 @@ public void ColorSet() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); @@ -62,7 +62,7 @@ public void ColorAndThicknessDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRegion.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRegion.cs deleted file mode 100644 index 710ec771..00000000 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ClearRegion.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Drawing.Tests.Processing; -using Xunit; - -namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths -{ - public class ClearRegion : BaseImageOperationsExtensionTest - { - private readonly DrawingOptions nonDefaultOptions = new DrawingOptions() - { - GraphicsOptions = - { - AlphaCompositionMode = PixelFormats.PixelAlphaCompositionMode.Clear, - BlendPercentage = 0.5f, - ColorBlendingMode = PixelFormats.PixelColorBlendingMode.Darken - } - }; - - private readonly IBrush brush = Brushes.Solid(Color.HotPink); - private readonly Region path = new ShapeRegion(new EllipsePolygon(10, 10, 100)); - - [Fact] - public void Brush() - { - this.operations.Clear(this.nonDefaultOptions, this.brush, this.path); - - FillRegionProcessor processor = this.Verify(); - - DrawingOptions expectedOptions = this.nonDefaultOptions; - Assert.Equal(expectedOptions.ShapeOptions, processor.Options.ShapeOptions); - Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); - Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); - Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - - Assert.Equal(this.path, processor.Region); - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void BrushDefaultOptions() - { - this.operations.Clear(this.brush, this.path); - - FillRegionProcessor processor = this.Verify(); - - ShapeOptions expectedOptions = this.shapeOptions; - Assert.Equal(expectedOptions, processor.Options.ShapeOptions); - Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); - Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); - Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - - Assert.Equal(this.path, processor.Region); - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void ColorSet() - { - this.operations.Clear(this.nonDefaultOptions, Color.Red, this.path); - - FillRegionProcessor processor = this.Verify(); - - DrawingOptions expectedOptions = this.nonDefaultOptions; - Assert.Equal(expectedOptions.ShapeOptions, processor.Options.ShapeOptions); - - Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); - Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); - Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - Assert.Equal(this.path, processor.Region); - Assert.NotEqual(this.brush, processor.Brush); - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, brush.Color); - } - - [Fact] - public void ColorAndThicknessDefaultOptions() - { - this.operations.Clear(Color.Red, this.path); - - FillRegionProcessor processor = this.Verify(); - - ShapeOptions expectedOptions = this.shapeOptions; - Assert.Equal(expectedOptions, processor.Options.ShapeOptions); - Assert.Equal(1, processor.Options.GraphicsOptions.BlendPercentage); - Assert.Equal(PixelFormats.PixelAlphaCompositionMode.Src, processor.Options.GraphicsOptions.AlphaCompositionMode); - Assert.Equal(PixelFormats.PixelColorBlendingMode.Normal, processor.Options.GraphicsOptions.ColorBlendingMode); - - Assert.Equal(this.path, processor.Region); - Assert.NotEqual(this.brush, processor.Brush); - SolidBrush brush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, brush.Color); - } - } -} diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawBezier.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawBezier.cs index 56210ed8..42d0471f 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawBezier.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawBezier.cs @@ -39,7 +39,7 @@ public void Pen() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -51,7 +51,7 @@ public void PenDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -63,7 +63,7 @@ public void BrushAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -76,7 +76,7 @@ public void BrushAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -89,7 +89,7 @@ public void ColorAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); @@ -103,7 +103,7 @@ public void ColorAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawLine.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawLine.cs index 95817bea..87fcf0eb 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawLine.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawLine.cs @@ -34,7 +34,7 @@ public void Pen() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -46,7 +46,7 @@ public void PenDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -58,7 +58,7 @@ public void BrushAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -71,7 +71,7 @@ public void BrushAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -84,7 +84,7 @@ public void ColorAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); @@ -98,7 +98,7 @@ public void ColorAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPath.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPath.cs index d4496cef..d4c3511d 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPath.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPath.cs @@ -21,7 +21,7 @@ public void Pen() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -33,7 +33,7 @@ public void PenDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -45,7 +45,7 @@ public void BrushAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -58,7 +58,7 @@ public void BrushAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -71,7 +71,7 @@ public void ColorAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); @@ -85,7 +85,7 @@ public void ColorAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPathCollection.cs index 5ddccf86..9d538340 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPathCollection.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPathCollection.cs @@ -53,8 +53,8 @@ public void Pen() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Path), + p => Assert.Equal(this.path2, p.Path)); } [Fact] @@ -71,8 +71,8 @@ public void PenDefaultOptions() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Path), + p => Assert.Equal(this.path2, p.Path)); } [Fact] @@ -90,8 +90,8 @@ public void BrushAndThickness() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Path), + p => Assert.Equal(this.path2, p.Path)); } [Fact] @@ -109,8 +109,8 @@ public void BrushAndThicknessDefaultOptions() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Path), + p => Assert.Equal(this.path2, p.Path)); } [Fact] @@ -129,8 +129,8 @@ public void ColorAndThickness() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Path), + p => Assert.Equal(this.path2, p.Path)); } [Fact] @@ -149,8 +149,8 @@ public void ColorAndThicknessDefaultOptions() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Path), + p => Assert.Equal(this.path2, p.Path)); } } } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPolygon.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPolygon.cs index 537f5974..add817af 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPolygon.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawPolygon.cs @@ -35,7 +35,7 @@ public void Pen() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -47,7 +47,7 @@ public void PenDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen, processor.Pen); } @@ -59,7 +59,7 @@ public void BrushAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -72,7 +72,7 @@ public void BrushAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); } @@ -85,7 +85,7 @@ public void ColorAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); @@ -99,7 +99,7 @@ public void ColorAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.points, processor.Shape); + this.VerifyPoints(this.points, processor.Path); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); Assert.Equal(10, processor.Pen.StrokeWidth); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawRectangle.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawRectangle.cs index ea758a67..b5bc2c48 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawRectangle.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/DrawRectangle.cs @@ -24,7 +24,7 @@ public void CorrectlySetsPenAndPath() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Path)); Assert.Equal(this.pen, processor.Pen); } @@ -36,7 +36,7 @@ public void CorrectlySetsPenAndPathDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Path)); Assert.Equal(this.pen, processor.Pen); } @@ -48,7 +48,7 @@ public void BrushAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Path)); Assert.NotEqual(this.pen, processor.Pen); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); @@ -62,7 +62,7 @@ public void BrushAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Path)); Assert.NotEqual(this.pen, processor.Pen); Assert.Equal(this.pen.StrokeFill, processor.Pen.StrokeFill); Assert.Equal(10, processor.Pen.StrokeWidth); @@ -76,7 +76,7 @@ public void ColorAndThickness() DrawPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Path)); Assert.NotEqual(this.pen, processor.Pen); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); @@ -91,7 +91,7 @@ public void ColorAndThicknessDefaultOptions() DrawPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Path)); Assert.NotEqual(this.pen, processor.Pen); SolidBrush brush = Assert.IsType(processor.Pen.StrokeFill); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Fill.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Fill.cs index 90775923..81fdf578 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Fill.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/Fill.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths { public class Fill : BaseImageOperationsExtensionTest { - private readonly GraphicsOptions nonDefaultOptions = new GraphicsOptions(); + private readonly DrawingOptions nonDefaultOptions = new DrawingOptions(); private readonly IBrush brush = new SolidBrush(Color.HotPink); [Fact] @@ -20,11 +20,11 @@ public void Brush() FillProcessor processor = this.Verify(); - GraphicsOptions expectedOptions = this.nonDefaultOptions; + DrawingOptions expectedOptions = this.nonDefaultOptions; Assert.Equal(expectedOptions, processor.Options); - Assert.Equal(expectedOptions.BlendPercentage, processor.Options.BlendPercentage); - Assert.Equal(expectedOptions.AlphaCompositionMode, processor.Options.AlphaCompositionMode); - Assert.Equal(expectedOptions.ColorBlendingMode, processor.Options.ColorBlendingMode); + Assert.Equal(expectedOptions.GraphicsOptions.BlendPercentage, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(expectedOptions.GraphicsOptions.AlphaCompositionMode, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(expectedOptions.GraphicsOptions.ColorBlendingMode, processor.Options.GraphicsOptions.ColorBlendingMode); Assert.Equal(this.brush, processor.Brush); } @@ -36,11 +36,11 @@ public void BrushDefaultOptions() FillProcessor processor = this.Verify(); - GraphicsOptions expectedOptions = this.options; - Assert.Equal(expectedOptions, processor.Options); - Assert.Equal(expectedOptions.BlendPercentage, processor.Options.BlendPercentage); - Assert.Equal(expectedOptions.AlphaCompositionMode, processor.Options.AlphaCompositionMode); - Assert.Equal(expectedOptions.ColorBlendingMode, processor.Options.ColorBlendingMode); + GraphicsOptions expectedOptions = this.graphicsOptions; + Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); + Assert.Equal(expectedOptions.BlendPercentage, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(expectedOptions.AlphaCompositionMode, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(expectedOptions.ColorBlendingMode, processor.Options.GraphicsOptions.ColorBlendingMode); Assert.Equal(this.brush, processor.Brush); } @@ -52,14 +52,15 @@ public void ColorSet() FillProcessor processor = this.Verify(); - GraphicsOptions expectedOptions = this.nonDefaultOptions; + DrawingOptions expectedOptions = this.nonDefaultOptions; Assert.Equal(expectedOptions, processor.Options); - Assert.Equal(expectedOptions.BlendPercentage, processor.Options.BlendPercentage); - Assert.Equal(expectedOptions.AlphaCompositionMode, processor.Options.AlphaCompositionMode); - Assert.Equal(expectedOptions.ColorBlendingMode, processor.Options.ColorBlendingMode); - SolidBrush solidBrush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, solidBrush.Color); + Assert.Equal(expectedOptions.GraphicsOptions.BlendPercentage, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(expectedOptions.GraphicsOptions.AlphaCompositionMode, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(expectedOptions.GraphicsOptions.ColorBlendingMode, processor.Options.GraphicsOptions.ColorBlendingMode); + Assert.NotEqual(this.brush, processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } [Fact] @@ -69,14 +70,15 @@ public void ColorSetDefaultOptions() FillProcessor processor = this.Verify(); - GraphicsOptions expectedOptions = this.options; - Assert.Equal(expectedOptions, processor.Options); - Assert.Equal(expectedOptions.BlendPercentage, processor.Options.BlendPercentage); - Assert.Equal(expectedOptions.AlphaCompositionMode, processor.Options.AlphaCompositionMode); - Assert.Equal(expectedOptions.ColorBlendingMode, processor.Options.ColorBlendingMode); + GraphicsOptions expectedOptions = this.graphicsOptions; + Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); + Assert.Equal(expectedOptions.BlendPercentage, processor.Options.GraphicsOptions.BlendPercentage); + Assert.Equal(expectedOptions.AlphaCompositionMode, processor.Options.GraphicsOptions.AlphaCompositionMode); + Assert.Equal(expectedOptions.ColorBlendingMode, processor.Options.GraphicsOptions.ColorBlendingMode); - SolidBrush solidBrush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, solidBrush.Color); + Assert.NotEqual(this.brush, processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } } } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPath.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPath.cs index 95a130aa..d931db4c 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPath.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPath.cs @@ -21,7 +21,7 @@ public void Brush() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -33,7 +33,7 @@ public void BrushDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -45,7 +45,7 @@ public void ColorSet() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); @@ -59,7 +59,7 @@ public void ColorAndThicknessDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.path, processor.Shape); + Assert.Equal(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathBuilder.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathBuilder.cs index 1734396f..c635552b 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathBuilder.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathBuilder.cs @@ -47,7 +47,7 @@ public void Brush() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -59,7 +59,7 @@ public void BrushDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -71,7 +71,7 @@ public void ColorSet() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); @@ -85,7 +85,7 @@ public void ColorAndThicknessDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathCollection.cs index 5788dd22..3ca3dda5 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathCollection.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPathCollection.cs @@ -51,8 +51,8 @@ public void Brush() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Region), + p => Assert.Equal(this.path2, p.Region)); } [Fact] @@ -69,8 +69,8 @@ public void BrushWithDefault() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Region), + p => Assert.Equal(this.path2, p.Region)); } [Fact] @@ -88,8 +88,8 @@ public void ColorSet() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Region), + p => Assert.Equal(this.path2, p.Region)); } [Fact] @@ -107,8 +107,8 @@ public void ColorWithDefault() Assert.Collection( processors, - p => Assert.Equal(this.path1, p.Shape), - p => Assert.Equal(this.path2, p.Shape)); + p => Assert.Equal(this.path1, p.Region), + p => Assert.Equal(this.path2, p.Region)); } } } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPolygon.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPolygon.cs index 8946bd47..11f050dc 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPolygon.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillPolygon.cs @@ -35,7 +35,7 @@ public void Brush() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -47,7 +47,7 @@ public void BrushDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.Equal(this.brush, processor.Brush); } @@ -59,7 +59,7 @@ public void ColorSet() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); @@ -73,7 +73,7 @@ public void ColorAndThicknessDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - this.VerifyPoints(this.path, processor.Shape); + this.VerifyPoints(this.path, processor.Region); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRectangle.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRectangle.cs index 018331b4..224f2b2c 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRectangle.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRectangle.cs @@ -25,7 +25,7 @@ public void Brush() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.Equal(this.brush, processor.Brush); } @@ -37,7 +37,7 @@ public void BrushDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.Equal(this.brush, processor.Brush); } @@ -49,7 +49,7 @@ public void ColorSet() FillPathProcessor processor = this.Verify(); Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); @@ -63,7 +63,7 @@ public void ColorAndThicknessDefaultOptions() FillPathProcessor processor = this.Verify(); Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Shape)); + Assert.True(RectangularPolygonValueComparer.Equals(this.RectanglePolygon, processor.Region)); Assert.NotEqual(this.brush, processor.Brush); SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRegion.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRegion.cs deleted file mode 100644 index 026a2a47..00000000 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/FillRegion.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; -using SixLabors.ImageSharp.Drawing.Tests.Processing; -using Xunit; - -namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths -{ - public class FillRegion : BaseImageOperationsExtensionTest - { - private readonly IBrush brush = new SolidBrush(Color.HotPink); - private readonly Region region = new ShapeRegion(new RectangularPolygon(10, 10, 10, 10)); - - [Fact] - public void Brush() - { - this.operations.Fill(new DrawingOptions(), this.brush, this.region); - - FillRegionProcessor processor = this.Verify(); - - Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.region, processor.Region); - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void BrushDefaultOptions() - { - this.operations.Fill(this.brush, this.region); - - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.region, processor.Region); - Assert.Equal(this.brush, processor.Brush); - } - - [Fact] - public void ColorSet() - { - this.operations.Fill(new DrawingOptions(), Color.Red, this.region); - - FillRegionProcessor processor = this.Verify(); - - Assert.NotEqual(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.region, processor.Region); - SolidBrush solidBrush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, solidBrush.Color); - } - - [Fact] - public void ColorSetDefaultOptions() - { - this.operations.Fill(Color.Red, this.region); - - FillRegionProcessor processor = this.Verify(); - - Assert.Equal(this.shapeOptions, processor.Options.ShapeOptions); - Assert.Equal(this.region, processor.Region); - SolidBrush solidBrush = Assert.IsType(processor.Brush); - Assert.Equal(Color.Red, solidBrush.Color); - } - } -} diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ShapePathTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ShapePathTests.cs deleted file mode 100644 index d6ffb042..00000000 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ShapePathTests.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths -{ - public class ShapePathTests - { - // TODO read these back in - } -} diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ShapeRegionTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ShapeRegionTests.cs deleted file mode 100644 index bd5f2e3d..00000000 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Paths/ShapeRegionTests.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Generic; -using System.Numerics; -using Moq; -using Xunit; - -namespace SixLabors.ImageSharp.Drawing.Tests.Drawing.Paths -{ - public class ShapeRegionTests - { - public abstract class MockPath : IPath, IPathInternals - { - public abstract RectangleF Bounds { get; } - - public IPath AsClosedPath() => this; - - public abstract SegmentInfo PointAlongPath(float distance); - - public abstract IEnumerable Flatten(); - - public abstract bool Contains(PointF point); - - public abstract IPath Transform(Matrix3x2 matrix); - - public abstract PathTypes PathType { get; } - - public int TestFindIntersectionsInvocationCounter { get; private set; } - - public virtual int TestYToScan => 10; - - public virtual int TestFindIntersectionsResult => 3; - } - - private readonly Mock pathMock; - - private readonly RectangleF bounds; - - public ShapeRegionTests() - { - this.pathMock = new Mock { CallBase = true }; - - this.bounds = new RectangleF(10.5f, 10, 10, 10); - this.pathMock.Setup(x => x.Bounds).Returns(this.bounds); - } - - [Fact] - public void ShapeRegionWithPathRetainsShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - Assert.Equal(this.pathMock.Object, region.Shape); - } - - [Fact] - public void ShapeRegionFromPathConvertsBoundsProxyToShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - Assert.Equal(Math.Floor(this.bounds.Left), region.Bounds.Left); - Assert.Equal(Math.Ceiling(this.bounds.Right), region.Bounds.Right); - - this.pathMock.Verify(x => x.Bounds); - } - - [Fact] - public void ShapeRegionFromShapeConvertsBoundsProxyToShape() - { - var region = new ShapeRegion(this.pathMock.Object); - - Assert.Equal(Math.Floor(this.bounds.Left), region.Bounds.Left); - Assert.Equal(Math.Ceiling(this.bounds.Right), region.Bounds.Right); - - this.pathMock.Verify(x => x.Bounds); - } - } -} diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawText.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawText.cs index 42160858..e7083a90 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawText.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawText.cs @@ -40,7 +40,7 @@ public void FillsForEachACharacterWhenBrushSetAndNotPen() DrawTextProcessor processor = this.Verify(0); Assert.NotEqual(this.textOptions, processor.Options.TextOptions); - Assert.NotEqual(this.options, processor.Options.GraphicsOptions); + Assert.NotEqual(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -50,7 +50,7 @@ public void FillsForEachACharacterWhenBrushSetAndNotPenDefaultOptions() DrawTextProcessor processor = this.Verify(0); Assert.Equal(this.textOptions, processor.Options.TextOptions); - Assert.Equal(this.options, processor.Options.GraphicsOptions); + Assert.Equal(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -60,7 +60,7 @@ public void FillsForEachACharacterWhenBrushSet() DrawTextProcessor processor = this.Verify(0); Assert.NotEqual(this.textOptions, processor.Options.TextOptions); - Assert.NotEqual(this.options, processor.Options.GraphicsOptions); + Assert.NotEqual(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -70,7 +70,7 @@ public void FillsForEachACharacterWhenBrushSetDefaultOptions() DrawTextProcessor processor = this.Verify(0); Assert.Equal(this.textOptions, processor.Options.TextOptions); - Assert.Equal(this.options, processor.Options.GraphicsOptions); + Assert.Equal(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -83,7 +83,7 @@ public void FillsForEachACharacterWhenColorSet() SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); Assert.NotEqual(this.textOptions, processor.Options.TextOptions); - Assert.NotEqual(this.options, processor.Options.GraphicsOptions); + Assert.NotEqual(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -96,7 +96,7 @@ public void FillsForEachACharacterWhenColorSetDefaultOptions() SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(Color.Red, brush.Color); Assert.Equal(this.textOptions, processor.Options.TextOptions); - Assert.Equal(this.options, processor.Options.GraphicsOptions); + Assert.Equal(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -112,7 +112,7 @@ public void DrawForEachACharacterWhenPenSetAndNotBrush() DrawTextProcessor processor = this.Verify(0); Assert.NotEqual(this.textOptions, processor.Options.TextOptions); - Assert.NotEqual(this.options, processor.Options.GraphicsOptions); + Assert.NotEqual(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -122,7 +122,7 @@ public void DrawForEachACharacterWhenPenSetAndNotBrushDefaultOptions() DrawTextProcessor processor = this.Verify(0); Assert.Equal(this.textOptions, processor.Options.TextOptions); - Assert.Equal(this.options, processor.Options.GraphicsOptions); + Assert.Equal(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -132,7 +132,7 @@ public void DrawForEachACharacterWhenPenSet() DrawTextProcessor processor = this.Verify(0); Assert.NotEqual(this.textOptions, processor.Options.TextOptions); - Assert.NotEqual(this.options, processor.Options.GraphicsOptions); + Assert.NotEqual(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -149,7 +149,7 @@ public void DrawForEachACharacterWhenPenSetDefaultOptions() Assert.Equal(1, processor.Pen.StrokeWidth); Assert.Equal(PointF.Empty, processor.Location); Assert.Equal(this.textOptions, processor.Options.TextOptions); - Assert.Equal(this.options, processor.Options.GraphicsOptions); + Assert.Equal(this.graphicsOptions, processor.Options.GraphicsOptions); } [Fact] @@ -174,7 +174,7 @@ public void DrawForEachACharacterWhenPenSetAndFillFroEachWhenBrushSet() Assert.Equal(Color.Red, penBrush.Color); Assert.Equal(1, processor.Pen.StrokeWidth); Assert.NotEqual(this.textOptions, processor.Options.TextOptions); - Assert.NotEqual(this.options, processor.Options.GraphicsOptions); + Assert.NotEqual(this.graphicsOptions, processor.Options.GraphicsOptions); } } } diff --git a/tests/ImageSharp.Drawing.Tests/Processing/BaseImageOperationsExtensionTest.cs b/tests/ImageSharp.Drawing.Tests/Processing/BaseImageOperationsExtensionTest.cs index 2237e320..f4bca44e 100644 --- a/tests/ImageSharp.Drawing.Tests/Processing/BaseImageOperationsExtensionTest.cs +++ b/tests/ImageSharp.Drawing.Tests/Processing/BaseImageOperationsExtensionTest.cs @@ -16,7 +16,7 @@ public abstract class BaseImageOperationsExtensionTest protected readonly IImageProcessingContext operations; private readonly FakeImageOperationsProvider.FakeImageOperations internalOperations; protected readonly Rectangle rect; - protected readonly GraphicsOptions options; + protected readonly GraphicsOptions graphicsOptions; protected readonly TextOptions textOptions; protected readonly ShapeOptions shapeOptions; private readonly Image source; @@ -25,7 +25,7 @@ public abstract class BaseImageOperationsExtensionTest public BaseImageOperationsExtensionTest() { - this.options = new GraphicsOptions + this.graphicsOptions = new GraphicsOptions { AntialiasSubpixelDepth = 99, Antialias = false, @@ -43,7 +43,7 @@ public BaseImageOperationsExtensionTest() this.internalOperations = new FakeImageOperationsProvider.FakeImageOperations(this.source.GetConfiguration(), this.source, false); this.internalOperations.SetShapeOptions(this.shapeOptions); this.internalOperations.SetTextOptions(this.textOptions); - this.internalOperations.SetGraphicsOptions(this.options); + this.internalOperations.SetGraphicsOptions(this.graphicsOptions); this.operations = this.internalOperations; } diff --git a/tests/ImageSharp.Drawing.Tests/Processing/FillPathProcessorTests.cs b/tests/ImageSharp.Drawing.Tests/Processing/FillPathProcessorTests.cs index 329a5dc6..f337a9fe 100644 --- a/tests/ImageSharp.Drawing.Tests/Processing/FillPathProcessorTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Processing/FillPathProcessorTests.cs @@ -1,14 +1,15 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Reflection; -using System.Text; +using Moq; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Drawing.Processing; using SixLabors.ImageSharp.Drawing.Processing.Processors.Drawing; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; using Xunit; @@ -16,6 +17,39 @@ namespace SixLabors.ImageSharp.Drawing.Tests.Processing { public class FillPathProcessorTests { + [Fact] + public void FillOffCanvas() + { + var bounds = new Rectangle(-100, -10, 10, 10); + + // Specifically not using RectangularPolygon here to ensure the FillPathProcessor is used. + var points = new LinearLineSegment[] + { + new LinearLineSegment(new PointF(bounds.Left, bounds.Top), new PointF(bounds.Right, bounds.Top)), + new LinearLineSegment(new PointF(bounds.Right, bounds.Top), new PointF(bounds.Right, bounds.Bottom)), + new LinearLineSegment(new PointF(bounds.Right, bounds.Bottom), new PointF(bounds.Left, bounds.Bottom)), + new LinearLineSegment(new PointF(bounds.Left, bounds.Bottom), new PointF(bounds.Left, bounds.Top)) + }; + var path = new Path(points); + var brush = new Mock(); + var options = new GraphicsOptions { Antialias = true }; + var processor = new FillPathProcessor(new DrawingOptions() { GraphicsOptions = options }, brush.Object, path); + var img = new Image(10, 10); + processor.Execute(img.GetConfiguration(), img, bounds); + } + + [Fact] + public void DrawOffCanvas() + { + using (var img = new Image(10, 10)) + { + img.Mutate(x => x.DrawLines( + new Pen(Color.Black, 10), + new Vector2(-10, 5), + new Vector2(20, 5))); + } + } + [Fact] public void OtherShape() { @@ -31,7 +65,7 @@ public void OtherShape() IImageProcessor pixelProcessor = processor.CreatePixelSpecificProcessor(null, null, imageSize); - Assert.IsType>(pixelProcessor); + Assert.IsType>(pixelProcessor); } [Fact] @@ -51,7 +85,7 @@ public void RectangleFloatAndAntialias() IImageProcessor pixelProcessor = processor.CreatePixelSpecificProcessor(null, null, imageSize); - Assert.IsType>(pixelProcessor); + Assert.IsType>(pixelProcessor); } [Fact] @@ -94,6 +128,43 @@ public void FloatRectAntialiasingOff() Assert.Equal(expectedRect, fill.GetProtectedValue("SourceRectangle")); } + + [Fact] + public void DoesNotThrowForIssue928() + { + var rectText = new RectangleF(0, 0, 2000, 2000); + using (var img = new Image((int)rectText.Width, (int)rectText.Height)) + { + img.Mutate(x => x.Fill(Color.Transparent)); + + img.Mutate( + ctx => ctx.DrawLines( + Color.Red, + 0.984252f, + new PointF(104.762581f, 1074.99365f), + new PointF(104.758667f, 1075.01721f), + new PointF(104.757675f, 1075.04114f), + new PointF(104.759628f, 1075.065f), + new PointF(104.764488f, 1075.08838f), + new PointF(104.772186f, 1075.111f), + new PointF(104.782608f, 1075.13245f), + new PointF(104.782608f, 1075.13245f))); + } + } + + [Fact] + public void DoesNotThrowFillingTriangle() + { + using (var image = new Image(28, 28)) + { + var path = new Polygon( + new LinearLineSegment(new PointF(17.11f, 13.99659f), new PointF(14.01433f, 27.06201f)), + new LinearLineSegment(new PointF(14.01433f, 27.06201f), new PointF(13.79267f, 14.00023f)), + new LinearLineSegment(new PointF(13.79267f, 14.00023f), new PointF(17.11f, 13.99659f))); + + image.Mutate(ctx => ctx.Fill(Color.White, path)); + } + } } internal static class ReflectionHelpers diff --git a/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x-20_y-20.png b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x-20_y-20.png new file mode 100644 index 00000000..1d55c599 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x-20_y-20.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cba43d7b20b634630515c4be65b2e3adbfbfed0d824f649e166856abf385761c +size 4140 diff --git a/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x0_y0.png b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x0_y0.png new file mode 100644 index 00000000..cc0d01fc --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x0_y0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2521a16b8378a6a9da1a1e2af9506c62a5f149c9a04f8f4fa0efcaa3030ed7e +size 4643 diff --git a/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x20_y20.png b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x20_y20.png new file mode 100644 index 00000000..76c34f9d --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x20_y20.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:141c0538433a547e09a34690915b1bd84fb2c35f8f71e39075cbcc2db8a12336 +size 4585 diff --git a/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x40_y60.png b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x40_y60.png new file mode 100644 index 00000000..d4e811f5 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/ClipTests/Clip_offset_x40_y60.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a30ca888127436a977aef4672d5cc4af3e6fd636a05844fcc08430ccf7ebdd9 +size 4515 diff --git a/tests/Images/ReferenceOutput/Drawing/DrawPolygonTests/DrawPolygon_Transformed_Rgba32_BasicTestPattern250x350.png b/tests/Images/ReferenceOutput/Drawing/DrawPolygonTests/DrawPolygon_Transformed_Rgba32_BasicTestPattern250x350.png index 1923336b..b1fff021 100644 --- a/tests/Images/ReferenceOutput/Drawing/DrawPolygonTests/DrawPolygon_Transformed_Rgba32_BasicTestPattern250x350.png +++ b/tests/Images/ReferenceOutput/Drawing/DrawPolygonTests/DrawPolygon_Transformed_Rgba32_BasicTestPattern250x350.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e842b418b79e7ab78b9bfb351b2cecea91256e8eab36857d3a48c3d9a1da7a0e -size 8962 +oid sha256:56441a7aa111218915395fa26f381027f3823316bf28c5280fa03f6a9995f200 +size 8015 diff --git a/tests/Images/ReferenceOutput/Drawing/FillPolygonTests/FillPolygon_ImageBrush_Rect_Rgba32_Car_rect.png b/tests/Images/ReferenceOutput/Drawing/FillPolygonTests/FillPolygon_ImageBrush_Rect_Rgba32_Car_rect.png new file mode 100644 index 00000000..b14af1fd --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/FillPolygonTests/FillPolygon_ImageBrush_Rect_Rgba32_Car_rect.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f72faff5b4d42f008e149912e32c5b017417c78057def3d8950fa3fdde0c8b2 +size 48547 diff --git a/tests/Images/ReferenceOutput/Drawing/FillPolygonTests/FillPolygon_ImageBrush_Rect_Rgba32_ducky_rect.png b/tests/Images/ReferenceOutput/Drawing/FillPolygonTests/FillPolygon_ImageBrush_Rect_Rgba32_ducky_rect.png new file mode 100644 index 00000000..5e10d9b6 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/FillPolygonTests/FillPolygon_ImageBrush_Rect_Rgba32_ducky_rect.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31bc372733f303b5732dda94f920464394703b7b3e13358ccc2fc9a50e186ae4 +size 30815