Browse Source

Style👮

af/merge-core
James Jackson-South 10 years ago
parent
commit
0bad55ab2d
  1. 4
      ImageSharp.sln.DotSettings
  2. 10
      README.md
  3. 2
      Settings.StyleCop
  4. 147
      src/ImageSharp/Drawing/Brushes/Brushes.cs
  5. 166
      src/ImageSharp/Drawing/Brushes/Brushes`2.cs
  6. 13
      src/ImageSharp/Drawing/Brushes/IBrush.cs
  7. 90
      src/ImageSharp/Drawing/Brushes/ImageBrush.cs
  8. 108
      src/ImageSharp/Drawing/Brushes/ImageBrush`2.cs
  9. 146
      src/ImageSharp/Drawing/Brushes/PatternBrush.cs
  10. 158
      src/ImageSharp/Drawing/Brushes/PatternBrush`2.cs
  11. 6
      src/ImageSharp/Drawing/Brushes/Processors/IBrushApplicator.cs
  12. 87
      src/ImageSharp/Drawing/Brushes/SolidBrush.cs
  13. 87
      src/ImageSharp/Drawing/Brushes/SolidBrush`2.cs
  14. 24
      src/ImageSharp/Drawing/GraphicsOptions.cs
  15. 42
      src/ImageSharp/Drawing/Paths/BezierLineSegment.cs
  16. 6
      src/ImageSharp/Drawing/Paths/ILineSegment.cs
  17. 8
      src/ImageSharp/Drawing/Paths/IPath.cs
  18. 139
      src/ImageSharp/Drawing/Paths/InternalPath.cs
  19. 15
      src/ImageSharp/Drawing/Paths/LinearLineSegment.cs
  20. 50
      src/ImageSharp/Drawing/Paths/Path.cs
  21. 6
      src/ImageSharp/Drawing/Paths/PointInfo.cs

4
ImageSharp.sln.DotSettings

@ -365,4 +365,8 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

10
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.

2
Settings.StyleCop

@ -34,6 +34,8 @@
<Value>cmyk</Value>
<Value>Paeth</Value>
<Value>th</Value>
<Value>bool</Value>
<Value>bools</Value>
<Value>desensitivity</Value>
<Value>premultiplied</Value>
</CollectionProperty>

147
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;
/// <summary>
/// A collection of methods for creating brushes
/// A collection of methods for creating brushes. Brushes use <see cref="Color"/> for painting.
/// </summary>
public class Brushes
{
@ -156,142 +151,4 @@ namespace ImageSharp.Drawing.Brushes
public static PatternBrush BackwardDiagonal(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color, uint>.BackwardDiagonal(foreColor, backColor));
}
/// <summary>
/// A collection of methods for creating brushes.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <returns>A Brush</returns>
public partial class Brushes<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
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 }
};
/// <summary>
/// Create as brush that will paint a solid color
/// </summary>
/// <param name="color">The color.</param>
/// <returns>A Brush</returns>
public static SolidBrush<TColor, TPacked> Solid(TColor color)
=> new SolidBrush<TColor, TPacked>(color);
/// <summary>
/// Create as brush that will paint a Percent10 Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Percent10(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, Percent10Pattern);
/// <summary>
/// Create as brush that will paint a Percent20 Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Percent20(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, Percent20Pattern);
/// <summary>
/// Create as brush that will paint a Horizontal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Horizontal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, HorizontalPattern);
/// <summary>
/// Create as brush that will paint a Min Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Min(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, MinPattern);
/// <summary>
/// Create as brush that will paint a Vertical Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Vertical(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, VerticalPattern);
/// <summary>
/// Create as brush that will paint a Forward Diagonal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> ForwardDiagonal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, ForwardDiagonalPattern);
/// <summary>
/// Create as brush that will paint a Backward Diagonal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> BackwardDiagonal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, BackwardDiagonalPattern);
}
}
}

166
src/ImageSharp/Drawing/Brushes/Brushes`2.cs

@ -0,0 +1,166 @@
// <copyright file="Brushes`2.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
/// <summary>
/// A collection of methods for creating generic brushes.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <returns>A Brush</returns>
public class Brushes<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Percent10 Hatch Pattern
/// </summary>
/// 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 }
};
/// <summary>
/// Percent20 pattern.
/// </summary>
private static readonly bool[,] Percent20Pattern =
{
{ true, false, true, false },
{ false, false, false, false },
{ false, true, false, true },
{ false, false, false, false }
};
/// <summary>
/// Horizontal Hatch Pattern
/// </summary>
private static readonly bool[,] HorizontalPattern =
{
{ false, true, false, false },
};
/// <summary>
/// Min Pattern
/// </summary>
private static readonly bool[,] MinPattern =
{
{ false, false, false, true },
};
/// <summary>
/// Vertical Pattern
/// </summary>
private static readonly bool[,] VerticalPattern =
{
{ false },
{ true },
{ false },
{ false }
};
/// <summary>
/// Forward Diagonal Pattern
/// </summary>
private static readonly bool[,] ForwardDiagonalPattern =
{
{ true, false, false, false },
{ false, true, false, false },
{ false, false, true, false },
{ false, false, false, true }
};
/// <summary>
/// Backward Diagonal Pattern
/// </summary>
private static readonly bool[,] BackwardDiagonalPattern =
{
{ false, false, false, true },
{ false, false, true, false },
{ false, true, false, false },
{ true, false, false, false }
};
/// <summary>
/// Create as brush that will paint a solid color
/// </summary>
/// <param name="color">The color.</param>
/// <returns>A Brush</returns>
public static SolidBrush<TColor, TPacked> Solid(TColor color)
=> new SolidBrush<TColor, TPacked>(color);
/// <summary>
/// Create as brush that will paint a Percent10 Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Percent10(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, Percent10Pattern);
/// <summary>
/// Create as brush that will paint a Percent20 Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Percent20(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, Percent20Pattern);
/// <summary>
/// Create as brush that will paint a Horizontal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Horizontal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, HorizontalPattern);
/// <summary>
/// Create as brush that will paint a Min Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Min(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, MinPattern);
/// <summary>
/// Create as brush that will paint a Vertical Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> Vertical(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, VerticalPattern);
/// <summary>
/// Create as brush that will paint a Forward Diagonal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> ForwardDiagonal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, ForwardDiagonalPattern);
/// <summary>
/// Create as brush that will paint a Backward Diagonal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor, TPacked> BackwardDiagonal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor, TPacked>(foreColor, backColor, BackwardDiagonalPattern);
}
}

13
src/ImageSharp/Drawing/Brushes/IBrush.cs

@ -5,21 +5,20 @@
namespace ImageSharp.Drawing
{
using System;
using Processors;
/// <summary>
/// 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
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <remarks>
/// A brush is a simple class that will return an <see cref="IBrushApplicator{TColor, TPacked}" /> that will perform the
/// logic for converting a pixel location to a <typeparamref name="TColor"/>.
/// </remarks>
public interface IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Creates the applicator for this brush.
@ -32,4 +31,4 @@ namespace ImageSharp.Drawing
/// </remarks>
IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region);
}
}
}

90
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;
/// <summary>
/// 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 <see cref="Color"/> for painting.
/// </summary>
public class ImageBrush : ImageBrush<Color, uint>
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrush" /> class.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="image">The image to paint.</param>
public ImageBrush(IImageBase<Color, uint> image)
: base(image)
{
}
}
/// <summary>
/// Provides an implementaion of a solid brush for painting solid color areas.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
public class ImageBrush<TColor, TPacked> : IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
private readonly IImageBase<TColor, TPacked> image;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="color">The color.</param>
public ImageBrush(IImageBase<TColor, TPacked> image)
{
this.image = image;
}
/// <summary>
/// Creates the applicator for this brush.
/// </summary>
/// <param name="region">The region the brush will be applied to.</param>
/// <returns>
/// The brush applicator for this brush
/// </returns>
/// <remarks>
/// The <paramref name="region" /> when being applied to things like shapes would ussually be the
/// bounding box of the shape not necessarily the bounds of the whole image
/// </remarks>
public IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region)
{
return new ImageBrushApplicator(this.image, region);
}
private class ImageBrushApplicator : IBrushApplicator<TColor, TPacked>
{
private readonly PixelAccessor<TColor, TPacked> source;
private readonly int yLength;
private readonly int xLength;
private readonly Vector2 offset;
private readonly float YOffset;
public ImageBrushApplicator(IImageBase<TColor, TPacked> 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));
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The color
/// </returns>
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];
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
source.Dispose();
}
}
}
}

108
src/ImageSharp/Drawing/Brushes/ImageBrush`2.cs

@ -0,0 +1,108 @@
// <copyright file="ImageBrush`2.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
using System;
using System.Numerics;
using Processors;
/// <summary>
/// Provides an implementation of an image brush for painting images within areas.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class ImageBrush<TColor, TPacked> : IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// The image to paint.
/// </summary>
private readonly IImageBase<TColor, TPacked> image;
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrush{TColor,TPacked}"/> class.
/// </summary>
/// <param name="image">The image.</param>
public ImageBrush(IImageBase<TColor, TPacked> image)
{
this.image = image;
}
/// <inheritdoc />
public IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region)
{
return new ImageBrushApplicator(this.image, region);
}
/// <summary>
/// The image brush applicator.
/// </summary>
private class ImageBrushApplicator : IBrushApplicator<TColor, TPacked>
{
/// <summary>
/// The source pixel accessor.
/// </summary>
private readonly PixelAccessor<TColor, TPacked> source;
/// <summary>
/// The y-length.
/// </summary>
private readonly int yLength;
/// <summary>
/// The x-length.
/// </summary>
private readonly int xLength;
/// <summary>
/// The offset.
/// </summary>
private readonly Vector2 offset;
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrushApplicator"/> class.
/// </summary>
/// <param name="image">
/// The image.
/// </param>
/// <param name="region">
/// The region.
/// </param>
public ImageBrushApplicator(IImageBase<TColor, TPacked> 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));
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The color
/// </returns>
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];
}
/// <inheritdoc />
public void Dispose()
{
this.source.Dispose();
}
}
}
}

146
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;
/// <summary>
/// Provides an implementaion of a pattern brush for painting patterns.
/// Provides an implementation of a pattern brush for painting patterns. The brush use <see cref="Color"/> for painting.
/// </summary>
/// <remarks>
/// 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
/// </remarks>
public class PatternBrush : PatternBrush<Color, uint>
{
/// <summary>
@ -62,116 +30,4 @@ namespace ImageSharp.Drawing.Brushes
{
}
}
/// <summary>
/// Provides an implementaion of a pattern brush for painting patterns.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
public partial class PatternBrush<TColor, TPacked> : IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
private readonly TColor[][] pattern;
private readonly int stride;
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="backColor">Color of the back.</param>
/// <param name="pattern">The pattern.</param>
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;
}
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
internal PatternBrush(PatternBrush<TColor, TPacked> brush)
{
this.pattern = brush.pattern;
this.stride = brush.stride;
}
/// <summary>
/// Creates the applicator for this bursh.
/// </summary>
/// <param name="region">The region the brush will be applied to.</param>
/// <returns>
/// The brush applicator for this brush
/// </returns>
/// <remarks>
/// The <paramref name="region" /> when being applied to things like shapes would ussually be the
/// bounding box of the shape not necessarily the bounds of the whole image
/// </remarks>
public IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region)
{
return new PatternBrushApplicator(this.pattern, this.stride);
}
private class PatternBrushApplicator : IBrushApplicator<TColor, TPacked>
{
private readonly int xLength;
private readonly int stride;
private readonly TColor[][] pattern;
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrushApplicator" /> class.
/// </summary>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="backColor">Color of the back.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="stride">The stride.</param>
public PatternBrushApplicator(TColor[][] pattern, int stride)
{
this.pattern = pattern;
this.xLength = pattern.Length;
this.stride = stride;
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The color
/// </returns>
public TColor GetColor(Vector2 point)
{
var x = (int)point.X % this.xLength;
var y = (int)point.Y % this.stride;
return this.pattern[x][y];
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
// noop
}
}
}
}

158
src/ImageSharp/Drawing/Brushes/PatternBrush`2.cs

@ -0,0 +1,158 @@
// <copyright file="PatternBrush`2.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
using System.Numerics;
using Processors;
/// <summary>
/// Provides an implementation of a pattern brush for painting patterns.
/// </summary>
/// <remarks>
/// 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
/// <para>
/// 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
/// </para>
/// <para>
/// or you want a horizontal stripe which is 3 pixels apart you would use a pattern like
/// 1
/// 0
/// 0
/// </para>
/// 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
/// </remarks>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class PatternBrush<TColor, TPacked> : IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// The pattern.
/// </summary>
private readonly TColor[][] pattern;
/// <summary>
/// The stride width.
/// </summary>
private readonly int stride;
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="backColor">Color of the back.</param>
/// <param name="pattern">The pattern.</param>
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;
}
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
internal PatternBrush(PatternBrush<TColor, TPacked> brush)
{
this.pattern = brush.pattern;
this.stride = brush.stride;
}
/// <inheritdoc />
public IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region)
{
return new PatternBrushApplicator(this.pattern, this.stride);
}
/// <summary>
/// The pattern brush applicator.
/// </summary>
private class PatternBrushApplicator : IBrushApplicator<TColor, TPacked>
{
/// <summary>
/// The patter x-length.
/// </summary>
private readonly int xLength;
/// <summary>
/// The stride width.
/// </summary>
private readonly int stride;
/// <summary>
/// The pattern.
/// </summary>
private readonly TColor[][] pattern;
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrushApplicator" /> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="stride">The stride.</param>
public PatternBrushApplicator(TColor[][] pattern, int stride)
{
this.pattern = pattern;
this.xLength = pattern.Length;
this.stride = stride;
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The color
/// </returns>
public TColor GetColor(Vector2 point)
{
int x = (int)point.X % this.xLength;
int y = (int)point.Y % this.stride;
return this.pattern[x][y];
}
/// <inheritdoc />
public void Dispose()
{
// noop
}
}
}
}

6
src/ImageSharp/Drawing/Brushes/Processors/IBrushApplicator.cs

@ -9,10 +9,10 @@ namespace ImageSharp.Drawing.Processors
using System.Numerics;
/// <summary>
/// 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
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <seealso cref="System.IDisposable" />
public interface IBrushApplicator<TColor, TPacked> : IDisposable // disposable will be required if/when there is an ImageBrush
where TColor : struct, IPackedPixel<TPacked>

87
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;
/// <summary>
/// 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 <see cref="Color"/> for painting.
/// </summary>
public class SolidBrush : SolidBrush<Color, uint>
{
@ -25,83 +19,4 @@ namespace ImageSharp.Drawing.Brushes
{
}
}
/// <summary>
/// Provides an implementaion of a solid brush for painting solid color areas.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
public class SolidBrush<TColor, TPacked> : IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
private readonly TColor color;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrush(TColor color)
{
this.color = color;
}
/// <summary>
/// Gets the color.
/// </summary>
/// <value>
/// The color.
/// </value>
public TColor Color => this.color;
/// <summary>
/// Creates the applicator for this brush.
/// </summary>
/// <param name="region">The region the brush will be applied to.</param>
/// <returns>
/// The brush applicator for this brush
/// </returns>
/// <remarks>
/// The <paramref name="region" /> when being applied to things like shapes would ussually be the
/// bounding box of the shape not necessarily the bounds of the whole image
/// </remarks>
public IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region)
{
return new SolidBrushApplicator(this.color);
}
private class SolidBrushApplicator : IBrushApplicator<TColor, TPacked>
{
private TColor color;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrushApplicator"/> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrushApplicator(TColor color)
{
this.color = color;
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The color
/// </returns>
public TColor GetColor(Vector2 point)
{
return this.color;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
// noop
}
}
}
}

87
src/ImageSharp/Drawing/Brushes/SolidBrush`2.cs

@ -0,0 +1,87 @@
// <copyright file="SolidBrush`2.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
using System.Numerics;
using Processors;
/// <summary>
/// Provides an implementation of a solid brush for painting solid color areas.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class SolidBrush<TColor, TPacked> : IBrush<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// The color to paint.
/// </summary>
private readonly TColor color;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrush{TColor, TPacked}"/> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrush(TColor color)
{
this.color = color;
}
/// <summary>
/// Gets the color.
/// </summary>
/// <value>
/// The color.
/// </value>
public TColor Color => this.color;
/// <inheritdoc />
public IBrushApplicator<TColor, TPacked> CreateApplicator(RectangleF region)
{
return new SolidBrushApplicator(this.color);
}
/// <summary>
/// The solid brush applicator.
/// </summary>
private class SolidBrushApplicator : IBrushApplicator<TColor, TPacked>
{
/// <summary>
/// The solid color.
/// </summary>
private readonly TColor color;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrushApplicator"/> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrushApplicator(TColor color)
{
this.color = color;
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The color
/// </returns>
public TColor GetColor(Vector2 point)
{
return this.color;
}
/// <inheritdoc />
public void Dispose()
{
// noop
}
}
}
}

24
src/ImageSharp/Drawing/GraphicsOptions.cs

@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
// <copyright file="GraphicsOptions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
/// <summary>
/// Options for influancing the drawing functions.
/// Options for influencing the drawing functions.
/// </summary>
public struct GraphicsOptions
{
@ -15,18 +15,18 @@ namespace ImageSharp.Drawing
/// </summary>
public static readonly GraphicsOptions Default = new GraphicsOptions(true);
/// <summary>
/// Whether antialiasing should be applied.
/// </summary>
public bool Antialias;
/// <summary>
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
/// </summary>
/// <param name="enableAntialiasing">if set to <c>true</c> [enable antialiasing].</param>
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
public GraphicsOptions(bool enableAntialiasing)
{
Antialias = enableAntialiasing;
this.Antialias = enableAntialiasing;
}
/// <summary>
/// Should antialias be applied.
/// </summary>
public bool Antialias;
}
}

42
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;
/// <summary>
/// Represents a line segment that conistst of control points that will be rendered as a cubic bezier curve
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Paths.ILineSegment" />
public class BezierLineSegment : ILineSegment
{
// code for this taken from http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/
/// <summary>
/// The segments per curve.
/// code for this taken from <see href="http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/"/>
/// </summary>
private const int SegmentsPerCurve = 50;
private Vector2[] linePoints;
/// <summary>
/// The line points.
/// </summary>
private readonly Vector2[] linePoints;
/// <summary>
/// Initializes a new instance of the <see cref="BezierLineSegment"/> class.
@ -46,18 +47,24 @@ namespace ImageSharp.Drawing.Paths
return this.linePoints;
}
/// <summary>
/// Returns the drawing points along the line.
/// </summary>
/// <param name="controlPoints">The control points.</param>
/// <returns>
/// The <see cref="T:Vector2[]"/>.
/// </returns>
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;
}
/// <summary>
/// Calculates the bezier point along the line.
/// </summary>
/// <param name="t">The position within the line.</param>
/// <param name="p0">The p 0.</param>
/// <param name="p1">The p 1.</param>
/// <param name="p2">The p 2.</param>
/// <param name="p3">The p 3.</param>
/// <returns>
/// The <see cref="Vector2"/>.
/// </returns>
private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
{
float u = 1 - t;

6
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;
/// <summary>
/// Represents a simple path segment
@ -20,6 +16,6 @@ namespace ImageSharp.Drawing.Paths
/// Converts the <see cref="ILineSegment" /> into a simple linear path..
/// </summary>
/// <returns>Returns the current <see cref="ILineSegment" /> as simple linear path.</returns>
Vector2[] AsSimpleLinearPath(); // TODO move this over to ReadonlySpan<Vector2> once availible
Vector2[] AsSimpleLinearPath(); // TODO move this over to ReadonlySpan<Vector2> once available
}
}

8
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;
/// <summary>
/// Represents a logic path that can be drawn
@ -41,9 +37,9 @@ namespace ImageSharp.Drawing.Paths
float Length { get; }
/// <summary>
/// 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.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="point">The point along the path.</param>
/// <returns>
/// Returns details about the point and its distance away from the path.
/// </returns>

139
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.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
/// <summary>
/// Internal logic for interigating linear paths.
/// Internal logic for integrating linear paths.
/// </summary>
internal class InternalPath
{
/// <summary>
/// The locker.
/// </summary>
private static readonly object Locker = new object();
/// <summary>
/// The points.
/// </summary>
private readonly Vector2[] points;
/// <summary>
/// The closed path.
/// </summary>
private readonly bool closedPath;
/// <summary>
/// The total distance.
/// </summary>
private readonly Lazy<float> totalDistance;
/// <summary>
/// The constant.
/// </summary>
private float[] constant;
/// <summary>
/// The multiples.
/// </summary>
private float[] multiple;
/// <summary>
/// The distances.
/// </summary>
private float[] distance;
private object locker = new object();
/// <summary>
/// The calculated.
/// </summary>
private bool calculated = false;
/// <summary>
@ -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<float>(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>Returns true if the point is inside the closed path.</returns>
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;
}
/// <summary>
/// Simplifies the collection of segments.
/// </summary>
/// <param name="segments">The segments.</param>
/// <returns>
/// The <see cref="T:Vector2[]"/>.
/// </returns>
private Vector2[] Simplify(ILineSegment[] segments)
{
List<Vector2> points = new List<Vector2>();
foreach(var seg in segments)
List<Vector2> simplified = new List<Vector2>();
foreach (ILineSegment seg in segments)
{
points.AddRange(seg.AsSimpleLinearPath());
simplified.AddRange(seg.AsSimpleLinearPath());
}
return points.ToArray();
return simplified.ToArray();
}
/// <summary>
/// Returns the length of the path.
/// </summary>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
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;
}
/// <summary>
/// Calculate the constants.
/// </summary>
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
}
}
/// <summary>
/// Calculate any shorter distances along the path.
/// </summary>
/// <param name="start">The start position.</param>
/// <param name="end">The end position.</param>
/// <param name="point">The current point.</param>
/// <param name="info">The info.</param>
/// <returns>
/// The <see cref="bool"/>.
/// </returns>
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;
}
/// <summary>
/// Contains information about the current point.
/// </summary>
private struct PointInfoInternal
{
/// <summary>
/// The distance squared.
/// </summary>
public float DistanceSquared;
/// <summary>
/// The point on the current line.
/// </summary>
public Vector2 PointOnLine;
}
}

15
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;
/// <summary>
/// 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
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Paths.ILineSegment" />
/// <seealso cref="ILineSegment" />
public class LinearLineSegment : ILineSegment
{
private Vector2[] points;
/// <summary>
/// The collection of points.
/// </summary>
private readonly Vector2[] points;
/// <summary>
/// Initializes a new instance of the <see cref="LinearLineSegment"/> class.
@ -53,4 +52,4 @@ namespace ImageSharp.Drawing.Paths
return this.points;
}
}
}
}

50
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;
/// <summary>
/// A aggragate of <see cref="ILineSegment"/>s making a single logical path
/// A aggregate of <see cref="ILineSegment"/>s making a single logical path
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Paths.IPath" />
/// <seealso cref="IPath" />
public class Path : IPath
{
/// <summary>
/// The inner path.
/// </summary>
private readonly InternalPath innerPath;
/// <summary>
@ -30,49 +27,22 @@ namespace ImageSharp.Drawing.Paths
this.innerPath = new InternalPath(segment, false);
}
/// <summary>
/// Gets the bounds enclosing the path
/// </summary>
/// <value>
/// The bounds.
/// </value>
/// <inheritdoc />
public RectangleF Bounds => this.innerPath.Bounds;
/// <summary>
/// Gets a value indicating whether this instance is closed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is closed; otherwise, <c>false</c>.
/// </value>
/// <inheritdoc />
public bool IsClosed => false;
/// <summary>
/// Gets the length of the path
/// </summary>
/// <value>
/// The length.
/// </value>
/// <inheritdoc />
public float Length => this.innerPath.Length;
/// <summary>
/// Returns the current <see cref="ILineSegment" /> a simple linear path.
/// </summary>
/// <returns>
/// Returns the current <see cref="ILineSegment" /> as simple linear path.
/// </returns>
/// <inheritdoc />
public Vector2[] AsSimpleLinearPath()
{
return this.innerPath.Points;
}
/// <summary>
/// Calcualtes the distance along and away from the path for a specified point.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// Returns details about the point and its distance away from the path.
/// </returns>
/// <inheritdoc />
public PointInfo Distance(Vector2 point)
{
return this.innerPath.DistanceFromPath(point);

6
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;
/// <summary>
/// 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
/// </summary>
public struct PointInfo
{

Loading…
Cancel
Save