diff --git a/ImageSharp.sln.DotSettings b/ImageSharp.sln.DotSettings index 3b5d019fac..22f46979a3 100644 --- a/ImageSharp.sln.DotSettings +++ b/ImageSharp.sln.DotSettings @@ -365,4 +365,8 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True \ No newline at end of file diff --git a/README.md b/README.md index f6fd4a508f..4a40d324ab 100644 --- a/README.md +++ b/README.md @@ -154,9 +154,13 @@ git clone https://github.com/JimBobSquarePants/ImageSharp - [x] Glow - [x] Threshold - Drawing - - [ ] Path brush (Need help) - - [ ] Hatch brush (Need help) - - [ ] Elliptical brush (Need help) + - [x] Image brush + - [x] Pattern brush + - [x] Solid brush + - [X] Hatch brush (Partial copy of System.Drawing brushes) + - [x] Pen (Solid, Dash, Custom) + - [x] Line drawing + - [x] Complex Polygons (Fill, draw) - [ ] Gradient brush (Need help) - Other stuff I haven't thought of. diff --git a/Settings.StyleCop b/Settings.StyleCop index dbff3379a8..30c78e19f2 100644 --- a/Settings.StyleCop +++ b/Settings.StyleCop @@ -34,6 +34,8 @@ cmyk Paeth th + bool + bools desensitivity premultiplied diff --git a/src/ImageSharp/Drawing/Brushes/Brushes.cs b/src/ImageSharp/Drawing/Brushes/Brushes.cs index 5de4287b73..26ac1fc001 100644 --- a/src/ImageSharp/Drawing/Brushes/Brushes.cs +++ b/src/ImageSharp/Drawing/Brushes/Brushes.cs @@ -5,13 +5,8 @@ namespace ImageSharp.Drawing.Brushes { - using System; - using System.Collections.Generic; - using System.Numerics; - using System.Threading.Tasks; - /// - /// A collection of methods for creating brushes + /// A collection of methods for creating brushes. Brushes use for painting. /// public class Brushes { @@ -156,142 +151,4 @@ namespace ImageSharp.Drawing.Brushes public static PatternBrush BackwardDiagonal(Color foreColor, Color backColor) => new PatternBrush(Brushes.BackwardDiagonal(foreColor, backColor)); } - - /// - /// A collection of methods for creating brushes. - /// - /// The type of the color. - /// The type of the packed. - /// A Brush - public partial class Brushes - where TColor : struct, IPackedPixel - where TPacked : struct - { - // note 2d arrays when configured using initalizer look inverted - // ---> Y axis - // ^ - // | X - axis - // | - // see PatternBrush for details about how to make new patterns work - private static readonly bool[,] Percent10Pattern = new bool[,] - { - { true, false, false, false }, - { false, false, false, false }, - { false, false, true, false }, - { false, false, false, false } - }; - - private static readonly bool[,] Percent20Pattern = new bool[,] - { - { true, false, true, false }, - { false, false, false, false }, - { false, true, false, true }, - { false, false, false, false } - }; - - private static readonly bool[,] HorizontalPattern = new bool[,] - { - { false, true, false, false }, - }; - - private static readonly bool[,] MinPattern = new bool[,] - { - { false, false, false, true }, - }; - - private static readonly bool[,] VerticalPattern = new bool[,] - { - { false }, - { true }, - { false }, - { false } - }; - - private static readonly bool[,] ForwardDiagonalPattern = new bool[,] - { - { true, false, false, false }, - { false, true, false, false }, - { false, false, true, false }, - { false, false, false, true } - }; - - private static readonly bool[,] BackwardDiagonalPattern = new bool[,] - { - { false, false, false, true }, - { false, false, true, false }, - { false, true, false, false }, - { true, false, false, false } - }; - - /// - /// Create as brush that will paint a solid color - /// - /// The color. - /// A Brush - public static SolidBrush Solid(TColor color) - => new SolidBrush(color); - - /// - /// Create as brush that will paint a Percent10 Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush Percent10(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, Percent10Pattern); - - /// - /// Create as brush that will paint a Percent20 Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush Percent20(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, Percent20Pattern); - - /// - /// Create as brush that will paint a Horizontal Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush Horizontal(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, HorizontalPattern); - - /// - /// Create as brush that will paint a Min Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush Min(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, MinPattern); - - /// - /// Create as brush that will paint a Vertical Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush Vertical(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, VerticalPattern); - - /// - /// Create as brush that will paint a Forward Diagonal Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush ForwardDiagonal(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); - - /// - /// Create as brush that will paint a Backward Diagonal Hatch Pattern within the specified colors - /// - /// Color of the foreground. - /// Color of the background. - /// A Brush - public static PatternBrush BackwardDiagonal(TColor foreColor, TColor backColor) - => new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); - } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Brushes/Brushes`2.cs b/src/ImageSharp/Drawing/Brushes/Brushes`2.cs new file mode 100644 index 0000000000..65097f9e40 --- /dev/null +++ b/src/ImageSharp/Drawing/Brushes/Brushes`2.cs @@ -0,0 +1,166 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Drawing.Brushes +{ + /// + /// A collection of methods for creating generic brushes. + /// + /// The pixel format. + /// The packed format. uint, long, float. + /// A Brush + public class Brushes + where TColor : struct, IPackedPixel + where TPacked : struct + { + /// + /// Percent10 Hatch Pattern + /// + /// note 2d arrays when configured using initalizer look inverted + /// ---> Y axis + /// ^ + /// | X - axis + /// | + /// see PatternBrush for details about how to make new patterns work + private static readonly bool[,] Percent10Pattern = + { + { true, false, false, false }, + { false, false, false, false }, + { false, false, true, false }, + { false, false, false, false } + }; + + /// + /// Percent20 pattern. + /// + private static readonly bool[,] Percent20Pattern = + { + { true, false, true, false }, + { false, false, false, false }, + { false, true, false, true }, + { false, false, false, false } + }; + + /// + /// Horizontal Hatch Pattern + /// + private static readonly bool[,] HorizontalPattern = + { + { false, true, false, false }, + }; + + /// + /// Min Pattern + /// + private static readonly bool[,] MinPattern = + { + { false, false, false, true }, + }; + + /// + /// Vertical Pattern + /// + private static readonly bool[,] VerticalPattern = + { + { false }, + { true }, + { false }, + { false } + }; + + /// + /// Forward Diagonal Pattern + /// + private static readonly bool[,] ForwardDiagonalPattern = + { + { true, false, false, false }, + { false, true, false, false }, + { false, false, true, false }, + { false, false, false, true } + }; + + /// + /// Backward Diagonal Pattern + /// + private static readonly bool[,] BackwardDiagonalPattern = + { + { false, false, false, true }, + { false, false, true, false }, + { false, true, false, false }, + { true, false, false, false } + }; + + /// + /// Create as brush that will paint a solid color + /// + /// The color. + /// A Brush + public static SolidBrush Solid(TColor color) + => new SolidBrush(color); + + /// + /// Create as brush that will paint a Percent10 Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush Percent10(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, Percent10Pattern); + + /// + /// Create as brush that will paint a Percent20 Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush Percent20(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, Percent20Pattern); + + /// + /// Create as brush that will paint a Horizontal Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush Horizontal(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, HorizontalPattern); + + /// + /// Create as brush that will paint a Min Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush Min(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, MinPattern); + + /// + /// Create as brush that will paint a Vertical Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush Vertical(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, VerticalPattern); + + /// + /// Create as brush that will paint a Forward Diagonal Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush ForwardDiagonal(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); + + /// + /// Create as brush that will paint a Backward Diagonal Hatch Pattern within the specified colors + /// + /// Color of the foreground. + /// Color of the background. + /// A Brush + public static PatternBrush BackwardDiagonal(TColor foreColor, TColor backColor) + => new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); + } +} diff --git a/src/ImageSharp/Drawing/Brushes/IBrush.cs b/src/ImageSharp/Drawing/Brushes/IBrush.cs index fc48bb2f1d..fc7e14ed67 100644 --- a/src/ImageSharp/Drawing/Brushes/IBrush.cs +++ b/src/ImageSharp/Drawing/Brushes/IBrush.cs @@ -5,21 +5,20 @@ namespace ImageSharp.Drawing { - using System; using Processors; /// - /// Brush represents a logical configuration of a brush whcih can be used to source pixel colors + /// Brush represents a logical configuration of a brush which can be used to source pixel colors /// - /// The type of the color. - /// The type of the packed. + /// The pixel format. + /// The packed format. uint, long, float. /// /// A brush is a simple class that will return an that will perform the /// logic for converting a pixel location to a . /// public interface IBrush - where TColor : struct, IPackedPixel - where TPacked : struct + where TColor : struct, IPackedPixel + where TPacked : struct { /// /// Creates the applicator for this brush. @@ -32,4 +31,4 @@ namespace ImageSharp.Drawing /// IBrushApplicator CreateApplicator(RectangleF region); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Brushes/ImageBrush.cs b/src/ImageSharp/Drawing/Brushes/ImageBrush.cs index 8ac4f43d29..c76d8657a0 100644 --- a/src/ImageSharp/Drawing/Brushes/ImageBrush.cs +++ b/src/ImageSharp/Drawing/Brushes/ImageBrush.cs @@ -5,104 +5,18 @@ namespace ImageSharp.Drawing.Brushes { - using System; - using System.Collections.Generic; - using System.Numerics; - using System.Threading.Tasks; - using Processors; - /// - /// Provides an implementaion of a solid brush for painting with repeating images. + /// Provides an implementation of a solid brush for painting with repeating images. The brush uses for painting. /// public class ImageBrush : ImageBrush { /// /// Initializes a new instance of the class. /// - /// The color. + /// The image to paint. public ImageBrush(IImageBase image) : base(image) { } } - - /// - /// Provides an implementaion of a solid brush for painting solid color areas. - /// - /// The type of the color. - /// The type of the packed. - public class ImageBrush : IBrush - where TColor : struct, IPackedPixel - where TPacked : struct - { - private readonly IImageBase image; - - /// - /// Initializes a new instance of the class. - /// - /// The color. - public ImageBrush(IImageBase image) - { - this.image = image; - } - - /// - /// Creates the applicator for this brush. - /// - /// The region the brush will be applied to. - /// - /// The brush applicator for this brush - /// - /// - /// The when being applied to things like shapes would ussually be the - /// bounding box of the shape not necessarily the bounds of the whole image - /// - public IBrushApplicator CreateApplicator(RectangleF region) - { - return new ImageBrushApplicator(this.image, region); - } - - private class ImageBrushApplicator : IBrushApplicator - { - private readonly PixelAccessor source; - private readonly int yLength; - private readonly int xLength; - private readonly Vector2 offset; - private readonly float YOffset; - - public ImageBrushApplicator(IImageBase image, RectangleF region) - { - this.source = image.Lock(); - this.xLength = image.Width; - this.yLength = image.Height; - this.offset = new Vector2((float)Math.Max(Math.Floor(region.Top), 0), - (float)Math.Max(Math.Floor(region.Left), 0)); - } - - /// - /// Gets the color for a single pixel. - /// - /// The point. - /// - /// The color - /// - public TColor GetColor(Vector2 point) - { - //offset the requested pixel by the value in the rectangle (the shapes position) - point = point - offset; - var x = (int)point.X % this.xLength; - var y = (int)point.Y % this.yLength; - - return source[x, y]; - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - source.Dispose(); - } - } - } } diff --git a/src/ImageSharp/Drawing/Brushes/ImageBrush`2.cs b/src/ImageSharp/Drawing/Brushes/ImageBrush`2.cs new file mode 100644 index 0000000000..c6cf7837f1 --- /dev/null +++ b/src/ImageSharp/Drawing/Brushes/ImageBrush`2.cs @@ -0,0 +1,108 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Drawing.Brushes +{ + using System; + using System.Numerics; + + using Processors; + + /// + /// Provides an implementation of an image brush for painting images within areas. + /// + /// The pixel format. + /// The packed format. uint, long, float. + public class ImageBrush : IBrush + where TColor : struct, IPackedPixel + where TPacked : struct + { + /// + /// The image to paint. + /// + private readonly IImageBase image; + + /// + /// Initializes a new instance of the class. + /// + /// The image. + public ImageBrush(IImageBase image) + { + this.image = image; + } + + /// + public IBrushApplicator CreateApplicator(RectangleF region) + { + return new ImageBrushApplicator(this.image, region); + } + + /// + /// The image brush applicator. + /// + private class ImageBrushApplicator : IBrushApplicator + { + /// + /// The source pixel accessor. + /// + private readonly PixelAccessor source; + + /// + /// The y-length. + /// + private readonly int yLength; + + /// + /// The x-length. + /// + private readonly int xLength; + + /// + /// The offset. + /// + private readonly Vector2 offset; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The image. + /// + /// + /// The region. + /// + public ImageBrushApplicator(IImageBase image, RectangleF region) + { + this.source = image.Lock(); + this.xLength = image.Width; + this.yLength = image.Height; + this.offset = new Vector2((float)Math.Max(Math.Floor(region.Top), 0), (float)Math.Max(Math.Floor(region.Left), 0)); + } + + /// + /// Gets the color for a single pixel. + /// + /// The point. + /// + /// The color + /// + public TColor GetColor(Vector2 point) + { + // Offset the requested pixel by the value in the rectangle (the shapes position) + point = point - this.offset; + int x = (int)point.X % this.xLength; + int y = (int)point.Y % this.yLength; + + return this.source[x, y]; + } + + /// + public void Dispose() + { + this.source.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Brushes/PatternBrush.cs b/src/ImageSharp/Drawing/Brushes/PatternBrush.cs index c9e4d5bc7f..bd812e1c83 100644 --- a/src/ImageSharp/Drawing/Brushes/PatternBrush.cs +++ b/src/ImageSharp/Drawing/Brushes/PatternBrush.cs @@ -5,41 +5,9 @@ namespace ImageSharp.Drawing.Brushes { - using System; - using System.Collections.Generic; - using System.Numerics; - using System.Threading.Tasks; - using Processors; - /// - /// Provides an implementaion of a pattern brush for painting patterns. + /// Provides an implementation of a pattern brush for painting patterns. The brush use for painting. /// - /// - /// The patterns that are used to create a custom pattern brush are made up of a repeating matrix of flags, - /// where each flag denotes weather to draw the foregound color or the background color. - /// so to create a new bool[,] with your flags - /// - /// For example if you wated to create a diagonal line that repeat every 4 pixels you would use a pattern like so - /// 1000 - /// 0100 - /// 0010 - /// 0001 - /// - /// or you want a horrizontal stripe which is 3 pixels apart you would use a pattern like - /// 1 - /// 0 - /// 0 - /// - /// warning when use array initallzer across multiple lines the bools look inverted i.e. - /// new bool[,]{ - /// {true, false, false}, - /// {false,true, false} - /// } - /// would be - /// 10 - /// 01 - /// 00 - /// public class PatternBrush : PatternBrush { /// @@ -62,116 +30,4 @@ namespace ImageSharp.Drawing.Brushes { } } - - /// - /// Provides an implementaion of a pattern brush for painting patterns. - /// - /// The type of the color. - /// The type of the packed. - public partial class PatternBrush : IBrush - where TColor : struct, IPackedPixel - where TPacked : struct - { - private readonly TColor[][] pattern; - private readonly int stride; - - /// - /// Initializes a new instance of the class. - /// - /// Color of the fore. - /// Color of the back. - /// The pattern. - public PatternBrush(TColor foreColor, TColor backColor, bool[,] pattern) - { - this.stride = pattern.GetLength(1); - - // convert the multidimension array into a jagged one. - var height = pattern.GetLength(0); - this.pattern = new TColor[height][]; - for (var x = 0; x < height; x++) - { - this.pattern[x] = new TColor[stride]; - for (var y = 0; y < stride; y++) - { - if (pattern[x, y]) - { - this.pattern[x][y] = foreColor; - }else - { - this.pattern[x][y] = backColor; - } - } - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The brush. - internal PatternBrush(PatternBrush brush) - { - this.pattern = brush.pattern; - this.stride = brush.stride; - } - - /// - /// Creates the applicator for this bursh. - /// - /// The region the brush will be applied to. - /// - /// The brush applicator for this brush - /// - /// - /// The when being applied to things like shapes would ussually be the - /// bounding box of the shape not necessarily the bounds of the whole image - /// - public IBrushApplicator CreateApplicator(RectangleF region) - { - return new PatternBrushApplicator(this.pattern, this.stride); - } - - private class PatternBrushApplicator : IBrushApplicator - { - private readonly int xLength; - private readonly int stride; - private readonly TColor[][] pattern; - - /// - /// Initializes a new instance of the class. - /// - /// Color of the fore. - /// Color of the back. - /// The pattern. - /// The stride. - public PatternBrushApplicator(TColor[][] pattern, int stride) - { - this.pattern = pattern; - this.xLength = pattern.Length; - this.stride = stride; - } - - /// - /// Gets the color for a single pixel. - /// - /// The point. - /// - /// The color - /// - public TColor GetColor(Vector2 point) - { - var x = (int)point.X % this.xLength; - var y = (int)point.Y % this.stride; - - return this.pattern[x][y]; - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - // noop - } - } - } } \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Brushes/PatternBrush`2.cs b/src/ImageSharp/Drawing/Brushes/PatternBrush`2.cs new file mode 100644 index 0000000000..0cf96460a5 --- /dev/null +++ b/src/ImageSharp/Drawing/Brushes/PatternBrush`2.cs @@ -0,0 +1,158 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Drawing.Brushes +{ + using System.Numerics; + + using Processors; + + /// + /// Provides an implementation of a pattern brush for painting patterns. + /// + /// + /// The patterns that are used to create a custom pattern brush are made up of a repeating matrix of flags, + /// where each flag denotes whether to draw the foreground color or the background color. + /// so to create a new bool[,] with your flags + /// + /// For example if you wanted to create a diagonal line that repeat every 4 pixels you would use a pattern like so + /// 1000 + /// 0100 + /// 0010 + /// 0001 + /// + /// + /// or you want a horizontal stripe which is 3 pixels apart you would use a pattern like + /// 1 + /// 0 + /// 0 + /// + /// Warning when use array initializer across multiple lines the bools look inverted i.e. + /// new bool[,]{ + /// {true, false, false}, + /// {false,true, false} + /// } + /// would be + /// 10 + /// 01 + /// 00 + /// + /// The pixel format. + /// The packed format. uint, long, float. + public class PatternBrush : IBrush + where TColor : struct, IPackedPixel + where TPacked : struct + { + /// + /// The pattern. + /// + private readonly TColor[][] pattern; + + /// + /// The stride width. + /// + private readonly int stride; + + /// + /// Initializes a new instance of the class. + /// + /// Color of the fore. + /// Color of the back. + /// The pattern. + public PatternBrush(TColor foreColor, TColor backColor, bool[,] pattern) + { + this.stride = pattern.GetLength(1); + + // Convert the multidimension array into a jagged one. + int height = pattern.GetLength(0); + this.pattern = new TColor[height][]; + for (int x = 0; x < height; x++) + { + this.pattern[x] = new TColor[this.stride]; + for (int y = 0; y < this.stride; y++) + { + if (pattern[x, y]) + { + this.pattern[x][y] = foreColor; + } + else + { + this.pattern[x][y] = backColor; + } + } + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The brush. + internal PatternBrush(PatternBrush brush) + { + this.pattern = brush.pattern; + this.stride = brush.stride; + } + + /// + public IBrushApplicator CreateApplicator(RectangleF region) + { + return new PatternBrushApplicator(this.pattern, this.stride); + } + + /// + /// The pattern brush applicator. + /// + private class PatternBrushApplicator : IBrushApplicator + { + /// + /// The patter x-length. + /// + private readonly int xLength; + + /// + /// The stride width. + /// + private readonly int stride; + + /// + /// The pattern. + /// + private readonly TColor[][] pattern; + + /// + /// Initializes a new instance of the class. + /// + /// The pattern. + /// The stride. + public PatternBrushApplicator(TColor[][] pattern, int stride) + { + this.pattern = pattern; + this.xLength = pattern.Length; + this.stride = stride; + } + + /// + /// Gets the color for a single pixel. + /// + /// The point. + /// + /// The color + /// + public TColor GetColor(Vector2 point) + { + int x = (int)point.X % this.xLength; + int y = (int)point.Y % this.stride; + + return this.pattern[x][y]; + } + + /// + public void Dispose() + { + // noop + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Brushes/Processors/IBrushApplicator.cs b/src/ImageSharp/Drawing/Brushes/Processors/IBrushApplicator.cs index 834bbde870..fa23c52d5a 100644 --- a/src/ImageSharp/Drawing/Brushes/Processors/IBrushApplicator.cs +++ b/src/ImageSharp/Drawing/Brushes/Processors/IBrushApplicator.cs @@ -9,10 +9,10 @@ namespace ImageSharp.Drawing.Processors using System.Numerics; /// - /// primitive that converts a point in to a color for discoving the fill color based on an implmentation + /// primitive that converts a point in to a color for discovering the fill color based on an implementation /// - /// The type of the color. - /// The type of the packed. + /// The pixel format. + /// The packed format. uint, long, float. /// public interface IBrushApplicator : IDisposable // disposable will be required if/when there is an ImageBrush where TColor : struct, IPackedPixel diff --git a/src/ImageSharp/Drawing/Brushes/SolidBrush.cs b/src/ImageSharp/Drawing/Brushes/SolidBrush.cs index 8e64ad6e23..7cac3fa65e 100644 --- a/src/ImageSharp/Drawing/Brushes/SolidBrush.cs +++ b/src/ImageSharp/Drawing/Brushes/SolidBrush.cs @@ -5,14 +5,8 @@ namespace ImageSharp.Drawing.Brushes { - using System; - using System.Collections.Generic; - using System.Numerics; - using System.Threading.Tasks; - using Processors; - /// - /// Provides an implementaion of a solid brush for painting solid color areas. + /// Provides an implementation of a solid brush for painting solid color areas. The brush uses for painting. /// public class SolidBrush : SolidBrush { @@ -25,83 +19,4 @@ namespace ImageSharp.Drawing.Brushes { } } - - /// - /// Provides an implementaion of a solid brush for painting solid color areas. - /// - /// The type of the color. - /// The type of the packed. - public class SolidBrush : IBrush - where TColor : struct, IPackedPixel - where TPacked : struct - { - private readonly TColor color; - - /// - /// Initializes a new instance of the class. - /// - /// The color. - public SolidBrush(TColor color) - { - this.color = color; - } - - /// - /// Gets the color. - /// - /// - /// The color. - /// - public TColor Color => this.color; - - /// - /// Creates the applicator for this brush. - /// - /// The region the brush will be applied to. - /// - /// The brush applicator for this brush - /// - /// - /// The when being applied to things like shapes would ussually be the - /// bounding box of the shape not necessarily the bounds of the whole image - /// - public IBrushApplicator CreateApplicator(RectangleF region) - { - return new SolidBrushApplicator(this.color); - } - - private class SolidBrushApplicator : IBrushApplicator - { - private TColor color; - - /// - /// Initializes a new instance of the class. - /// - /// The color. - public SolidBrushApplicator(TColor color) - { - this.color = color; - } - - /// - /// Gets the color for a single pixel. - /// - /// The point. - /// - /// The color - /// - public TColor GetColor(Vector2 point) - { - return this.color; - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - // noop - } - } - } } diff --git a/src/ImageSharp/Drawing/Brushes/SolidBrush`2.cs b/src/ImageSharp/Drawing/Brushes/SolidBrush`2.cs new file mode 100644 index 0000000000..8a17a0c076 --- /dev/null +++ b/src/ImageSharp/Drawing/Brushes/SolidBrush`2.cs @@ -0,0 +1,87 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Drawing.Brushes +{ + using System.Numerics; + + using Processors; + + /// + /// Provides an implementation of a solid brush for painting solid color areas. + /// + /// The pixel format. + /// The packed format. uint, long, float. + public class SolidBrush : IBrush + where TColor : struct, IPackedPixel + where TPacked : struct + { + /// + /// The color to paint. + /// + private readonly TColor color; + + /// + /// Initializes a new instance of the class. + /// + /// The color. + public SolidBrush(TColor color) + { + this.color = color; + } + + /// + /// Gets the color. + /// + /// + /// The color. + /// + public TColor Color => this.color; + + /// + public IBrushApplicator CreateApplicator(RectangleF region) + { + return new SolidBrushApplicator(this.color); + } + + /// + /// The solid brush applicator. + /// + private class SolidBrushApplicator : IBrushApplicator + { + /// + /// The solid color. + /// + private readonly TColor color; + + /// + /// Initializes a new instance of the class. + /// + /// The color. + public SolidBrushApplicator(TColor color) + { + this.color = color; + } + + /// + /// Gets the color for a single pixel. + /// + /// The point. + /// + /// The color + /// + public TColor GetColor(Vector2 point) + { + return this.color; + } + + /// + public void Dispose() + { + // noop + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Drawing/GraphicsOptions.cs b/src/ImageSharp/Drawing/GraphicsOptions.cs index 774f84520c..7e569c9a5f 100644 --- a/src/ImageSharp/Drawing/GraphicsOptions.cs +++ b/src/ImageSharp/Drawing/GraphicsOptions.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// namespace ImageSharp.Drawing { /// - /// Options for influancing the drawing functions. + /// Options for influencing the drawing functions. /// public struct GraphicsOptions { @@ -15,18 +15,18 @@ namespace ImageSharp.Drawing /// public static readonly GraphicsOptions Default = new GraphicsOptions(true); + /// + /// Whether antialiasing should be applied. + /// + public bool Antialias; + /// /// Initializes a new instance of the struct. /// - /// if set to true [enable antialiasing]. + /// If set to true [enable antialiasing]. public GraphicsOptions(bool enableAntialiasing) { - Antialias = enableAntialiasing; + this.Antialias = enableAntialiasing; } - - /// - /// Should antialias be applied. - /// - public bool Antialias; } } \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Paths/BezierLineSegment.cs b/src/ImageSharp/Drawing/Paths/BezierLineSegment.cs index edd6bbeea5..647f97f1e9 100644 --- a/src/ImageSharp/Drawing/Paths/BezierLineSegment.cs +++ b/src/ImageSharp/Drawing/Paths/BezierLineSegment.cs @@ -5,23 +5,24 @@ namespace ImageSharp.Drawing.Paths { - using System; - using System.Collections.Generic; - using System.Linq; using System.Numerics; - using Brushes; - /// /// Represents a line segment that conistst of control points that will be rendered as a cubic bezier curve /// /// public class BezierLineSegment : ILineSegment { - // code for this taken from http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/ + /// + /// The segments per curve. + /// code for this taken from + /// private const int SegmentsPerCurve = 50; - private Vector2[] linePoints; + /// + /// The line points. + /// + private readonly Vector2[] linePoints; /// /// Initializes a new instance of the class. @@ -46,18 +47,24 @@ namespace ImageSharp.Drawing.Paths return this.linePoints; } + /// + /// Returns the drawing points along the line. + /// + /// The control points. + /// + /// The . + /// private Vector2[] GetDrawingPoints(Vector2[] controlPoints) { // TODO we need to calculate an optimal SegmentsPerCurve value // depending on the calcualted length of this curve + int curveCount = (controlPoints.Length - 1) / 3; + int finalPointCount = (SegmentsPerCurve * curveCount) + 1; // we have SegmentsPerCurve for each curve plus the origon point; - var curveCount = (controlPoints.Length - 1) / 3; - var finalPointCount = (SegmentsPerCurve * curveCount) + 1; // we have SegmentsPerCurve for each curve plus the origon point; - - var drawingPoints = new Vector2[finalPointCount]; + Vector2[] drawingPoints = new Vector2[finalPointCount]; int position = 0; - var targetPoint = controlPoints.Length - 3; + int targetPoint = controlPoints.Length - 3; for (int i = 0; i < targetPoint; i += 3) { Vector2 p0 = controlPoints[i]; @@ -81,6 +88,17 @@ namespace ImageSharp.Drawing.Paths return drawingPoints; } + /// + /// Calculates the bezier point along the line. + /// + /// The position within the line. + /// The p 0. + /// The p 1. + /// The p 2. + /// The p 3. + /// + /// The . + /// private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) { float u = 1 - t; diff --git a/src/ImageSharp/Drawing/Paths/ILineSegment.cs b/src/ImageSharp/Drawing/Paths/ILineSegment.cs index 24794442f3..380f0bf40c 100644 --- a/src/ImageSharp/Drawing/Paths/ILineSegment.cs +++ b/src/ImageSharp/Drawing/Paths/ILineSegment.cs @@ -5,11 +5,7 @@ namespace ImageSharp.Drawing.Paths { - using System; - using System.Collections.Generic; - using System.Linq; using System.Numerics; - using System.Threading.Tasks; /// /// Represents a simple path segment @@ -20,6 +16,6 @@ namespace ImageSharp.Drawing.Paths /// Converts the into a simple linear path.. /// /// Returns the current as simple linear path. - Vector2[] AsSimpleLinearPath(); // TODO move this over to ReadonlySpan once availible + Vector2[] AsSimpleLinearPath(); // TODO move this over to ReadonlySpan once available } } diff --git a/src/ImageSharp/Drawing/Paths/IPath.cs b/src/ImageSharp/Drawing/Paths/IPath.cs index eaa6b84d23..278d972511 100644 --- a/src/ImageSharp/Drawing/Paths/IPath.cs +++ b/src/ImageSharp/Drawing/Paths/IPath.cs @@ -5,11 +5,7 @@ namespace ImageSharp.Drawing.Paths { - using System; - using System.Collections.Generic; - using System.Linq; using System.Numerics; - using System.Threading.Tasks; /// /// Represents a logic path that can be drawn @@ -41,9 +37,9 @@ namespace ImageSharp.Drawing.Paths float Length { get; } /// - /// Calcualtes the distance along and away from the path for a specified point. + /// Calculates the distance along and away from the path for a specified point. /// - /// The point. + /// The point along the path. /// /// Returns details about the point and its distance away from the path. /// diff --git a/src/ImageSharp/Drawing/Paths/InternalPath.cs b/src/ImageSharp/Drawing/Paths/InternalPath.cs index 7fefd83a6c..b347022534 100644 --- a/src/ImageSharp/Drawing/Paths/InternalPath.cs +++ b/src/ImageSharp/Drawing/Paths/InternalPath.cs @@ -2,29 +2,56 @@ // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // - namespace ImageSharp.Drawing.Paths { using System; using System.Collections.Generic; - using System.Collections.ObjectModel; using System.Linq; using System.Numerics; - using System.Threading.Tasks; /// - /// Internal logic for interigating linear paths. + /// Internal logic for integrating linear paths. /// internal class InternalPath { + /// + /// The locker. + /// + private static readonly object Locker = new object(); + + /// + /// The points. + /// private readonly Vector2[] points; + + /// + /// The closed path. + /// private readonly bool closedPath; + + /// + /// The total distance. + /// private readonly Lazy totalDistance; + /// + /// The constant. + /// private float[] constant; + + /// + /// The multiples. + /// private float[] multiple; + + /// + /// The distances. + /// private float[] distance; - private object locker = new object(); + + /// + /// The calculated. + /// private bool calculated = false; /// @@ -39,10 +66,10 @@ namespace ImageSharp.Drawing.Paths this.points = this.Simplify(segments); this.closedPath = isClosedPath; - var minX = this.points.Min(x => x.X); - var maxX = this.points.Max(x => x.X); - var minY = this.points.Min(x => x.Y); - var maxY = this.points.Max(x => x.Y); + float minX = this.points.Min(x => x.X); + float maxX = this.points.Max(x => x.X); + float minY = this.points.Min(x => x.Y); + float maxY = this.points.Max(x => x.Y); this.Bounds = new RectangleF(minX, minY, maxX - minX, maxY - minY); this.totalDistance = new Lazy(this.CalculateLength); @@ -84,10 +111,10 @@ namespace ImageSharp.Drawing.Paths { this.CalculateConstants(); - var internalInfo = default(PointInfoInternal); - internalInfo.DistanceSquared = float.MaxValue; // set it to max so that CalculateShorterDistance can reduce it back down + PointInfoInternal internalInfo = default(PointInfoInternal); + internalInfo.DistanceSquared = float.MaxValue; // Set it to max so that CalculateShorterDistance can reduce it back down - var polyCorners = this.points.Length; + int polyCorners = this.points.Length; if (!this.closedPath) { @@ -95,9 +122,9 @@ namespace ImageSharp.Drawing.Paths } int closestPoint = 0; - for (var i = 0; i < polyCorners; i++) + for (int i = 0; i < polyCorners; i++) { - var next = i + 1; + int next = i + 1; if (this.closedPath && next == polyCorners) { next = 0; @@ -125,7 +152,7 @@ namespace ImageSharp.Drawing.Paths /// Returns true if the point is inside the closed path. public bool PointInPolygon(Vector2 point) { - // you can only be inside a path if its "closed" + // You can only be inside a path if its "closed" if (!this.closedPath) { return false; @@ -138,13 +165,13 @@ namespace ImageSharp.Drawing.Paths this.CalculateConstants(); - var poly = this.points; - var polyCorners = poly.Length; + Vector2[] poly = this.points; + int polyCorners = poly.Length; - var j = polyCorners - 1; + int j = polyCorners - 1; bool oddNodes = false; - for (var i = 0; i < polyCorners; i++) + for (int i = 0; i < polyCorners; i++) { if ((poly[i].Y < point.Y && poly[j].Y >= point.Y) || (poly[j].Y < point.Y && poly[i].Y >= point.Y)) @@ -158,30 +185,43 @@ namespace ImageSharp.Drawing.Paths return oddNodes; } + /// + /// Simplifies the collection of segments. + /// + /// The segments. + /// + /// The . + /// private Vector2[] Simplify(ILineSegment[] segments) { - List points = new List(); - foreach(var seg in segments) + List simplified = new List(); + foreach (ILineSegment seg in segments) { - points.AddRange(seg.AsSimpleLinearPath()); + simplified.AddRange(seg.AsSimpleLinearPath()); } - return points.ToArray(); + return simplified.ToArray(); } + /// + /// Returns the length of the path. + /// + /// + /// The . + /// private float CalculateLength() { float length = 0; - var polyCorners = this.points.Length; + int polyCorners = this.points.Length; if (!this.closedPath) { polyCorners -= 1; } - for (var i = 0; i < polyCorners; i++) + for (int i = 0; i < polyCorners; i++) { - var next = i + 1; + int next = i + 1; if (this.closedPath && next == polyCorners) { next = 0; @@ -193,6 +233,9 @@ namespace ImageSharp.Drawing.Paths return length; } + /// + /// Calculate the constants. + /// private void CalculateConstants() { // http://alienryderflex.com/polygon/ source for point in polygon logic @@ -201,15 +244,15 @@ namespace ImageSharp.Drawing.Paths return; } - lock (this.locker) + lock (Locker) { if (this.calculated) { return; } - var poly = this.points; - var polyCorners = poly.Length; + Vector2[] poly = this.points; + int polyCorners = poly.Length; this.constant = new float[polyCorners]; this.multiple = new float[polyCorners]; this.distance = new float[polyCorners]; @@ -227,7 +270,7 @@ namespace ImageSharp.Drawing.Paths } else { - var subtracted = poly[j] - poly[i]; + Vector2 subtracted = poly[j] - poly[i]; this.constant[i] = (poly[i].X - ((poly[i].Y * poly[j].X) / subtracted.Y)) + ((poly[i].Y * poly[i].X) / subtracted.Y); this.multiple[i] = subtracted.X / subtracted.Y; } @@ -239,15 +282,25 @@ namespace ImageSharp.Drawing.Paths } } + /// + /// Calculate any shorter distances along the path. + /// + /// The start position. + /// The end position. + /// The current point. + /// The info. + /// + /// The . + /// private bool CalculateShorterDistance(Vector2 start, Vector2 end, Vector2 point, ref PointInfoInternal info) { - var diffEnds = end - start; + Vector2 diffEnds = end - start; float lengthSquared = diffEnds.LengthSquared(); - var diff = point - start; + Vector2 diff = point - start; - var multiplied = diff * diffEnds; - var u = (multiplied.X + multiplied.Y) / lengthSquared; + Vector2 multiplied = diff * diffEnds; + float u = (multiplied.X + multiplied.Y) / lengthSquared; if (u > 1) { @@ -258,13 +311,13 @@ namespace ImageSharp.Drawing.Paths u = 0; } - var multipliedByU = diffEnds * u; + Vector2 multipliedByU = diffEnds * u; - var pointOnLine = start + multipliedByU; + Vector2 pointOnLine = start + multipliedByU; - var d = pointOnLine - point; + Vector2 d = pointOnLine - point; - var dist = d.LengthSquared(); + float dist = d.LengthSquared(); if (info.DistanceSquared > dist) { @@ -276,9 +329,19 @@ namespace ImageSharp.Drawing.Paths return false; } + /// + /// Contains information about the current point. + /// private struct PointInfoInternal { + /// + /// The distance squared. + /// public float DistanceSquared; + + /// + /// The point on the current line. + /// public Vector2 PointOnLine; } } diff --git a/src/ImageSharp/Drawing/Paths/LinearLineSegment.cs b/src/ImageSharp/Drawing/Paths/LinearLineSegment.cs index 3275c7883a..6942ce5a5a 100644 --- a/src/ImageSharp/Drawing/Paths/LinearLineSegment.cs +++ b/src/ImageSharp/Drawing/Paths/LinearLineSegment.cs @@ -5,20 +5,19 @@ namespace ImageSharp.Drawing.Paths { - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; using System.Linq; using System.Numerics; - using System.Threading.Tasks; /// - /// Represents a seriese of control points that will be joined by staight lines + /// Represents a series of control points that will be joined by straight lines /// - /// + /// public class LinearLineSegment : ILineSegment { - private Vector2[] points; + /// + /// The collection of points. + /// + private readonly Vector2[] points; /// /// Initializes a new instance of the class. @@ -53,4 +52,4 @@ namespace ImageSharp.Drawing.Paths return this.points; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Drawing/Paths/Path.cs b/src/ImageSharp/Drawing/Paths/Path.cs index ce7cb57e7b..eb2ab5e854 100644 --- a/src/ImageSharp/Drawing/Paths/Path.cs +++ b/src/ImageSharp/Drawing/Paths/Path.cs @@ -5,20 +5,17 @@ namespace ImageSharp.Drawing.Paths { - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; using System.Numerics; - using System.Threading.Tasks; /// - /// A aggragate of s making a single logical path + /// A aggregate of s making a single logical path /// - /// + /// public class Path : IPath { + /// + /// The inner path. + /// private readonly InternalPath innerPath; /// @@ -30,49 +27,22 @@ namespace ImageSharp.Drawing.Paths this.innerPath = new InternalPath(segment, false); } - /// - /// Gets the bounds enclosing the path - /// - /// - /// The bounds. - /// + /// public RectangleF Bounds => this.innerPath.Bounds; - /// - /// Gets a value indicating whether this instance is closed. - /// - /// - /// true if this instance is closed; otherwise, false. - /// + /// public bool IsClosed => false; - /// - /// Gets the length of the path - /// - /// - /// The length. - /// + /// public float Length => this.innerPath.Length; - /// - /// Returns the current a simple linear path. - /// - /// - /// Returns the current as simple linear path. - /// + /// public Vector2[] AsSimpleLinearPath() { return this.innerPath.Points; } - /// - /// Calcualtes the distance along and away from the path for a specified point. - /// - /// The x. - /// The y. - /// - /// Returns details about the point and its distance away from the path. - /// + /// public PointInfo Distance(Vector2 point) { return this.innerPath.DistanceFromPath(point); diff --git a/src/ImageSharp/Drawing/Paths/PointInfo.cs b/src/ImageSharp/Drawing/Paths/PointInfo.cs index 3bae73e22f..a2cbf1e73c 100644 --- a/src/ImageSharp/Drawing/Paths/PointInfo.cs +++ b/src/ImageSharp/Drawing/Paths/PointInfo.cs @@ -5,14 +5,10 @@ namespace ImageSharp.Drawing.Paths { - using System; - using System.Collections.Generic; - using System.Linq; using System.Numerics; - using System.Threading.Tasks; /// - /// Returns some meta data about the nearest point on a path from a vector + /// Returns meta data about the nearest point on a path from a vector /// public struct PointInfo {