Browse Source

provide graphics options for drawing methods

this allows enabling/disabling the antailising
af/merge-core
Scott Williams 10 years ago
parent
commit
8d85a75ced
  1. 299
      src/ImageSharp/Drawing/Draw.cs
  2. 77
      src/ImageSharp/Drawing/Fill.cs
  3. 32
      src/ImageSharp/Drawing/GraphicsOptions.cs
  4. 9
      src/ImageSharp/Drawing/Paths/IPath.cs
  5. 4
      src/ImageSharp/Drawing/Paths/Path.cs
  6. 39
      src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs
  7. 12
      src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs
  8. 5
      src/ImageSharp/Drawing/Shapes/BezierPolygon.cs
  9. 9
      src/ImageSharp/Drawing/Shapes/ComplexPolygon.cs
  10. 11
      src/ImageSharp/Drawing/Shapes/IShape.cs
  11. 5
      src/ImageSharp/Drawing/Shapes/LinearPolygon.cs
  12. 11
      src/ImageSharp/Drawing/Shapes/Polygon.cs
  13. 2
      tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
  14. 30
      tests/ImageSharp.Tests/Drawing/LineTests.cs
  15. 31
      tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs

299
src/ImageSharp/Drawing/Draw.cs

@ -19,6 +19,25 @@ namespace ImageSharp
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, IPen<TColor, TPacked> pen, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(new DrawPathProcessor<TColor, TPacked>(pen, shape, options));
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
@ -32,7 +51,27 @@ namespace ImageSharp
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(new DrawPathProcessor<TColor, TPacked>(pen, shape));
return source.DrawPolygon(pen, shape, GraphicsOptions.Default);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, float thickness, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPolygon(new Pen<TColor, TPacked>(brush, thickness), shape, options);
}
/// <summary>
@ -52,6 +91,26 @@ namespace ImageSharp
return source.DrawPolygon(new Pen<TColor, TPacked>(brush, thickness), shape);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, float thickness, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPolygon(new SolidBrush<TColor, TPacked>(color), thickness, shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
@ -69,6 +128,26 @@ namespace ImageSharp
return source.DrawPolygon(new SolidBrush<TColor, TPacked>(color), thickness, shape);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPolygon(new Pen<TColor, TPacked>(brush, thickness), new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
@ -103,6 +182,44 @@ namespace ImageSharp
return source.DrawPolygon(new SolidBrush<TColor, TPacked>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPolygon(new SolidBrush<TColor, TPacked>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, IPen<TColor, TPacked> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPolygon(pen, new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
@ -119,6 +236,25 @@ namespace ImageSharp
return source.DrawPolygon(pen, new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the path with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPath<TColor, TPacked>(this Image<TColor, TPacked> source, IPen<TColor, TPacked> pen, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(new DrawPathProcessor<TColor, TPacked>(pen, path, options));
}
/// <summary>
/// Draws the path with the provided pen.
/// </summary>
@ -132,7 +268,27 @@ namespace ImageSharp
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(new DrawPathProcessor<TColor, TPacked>(pen, path));
return source.Process(new DrawPathProcessor<TColor, TPacked>(pen, path, GraphicsOptions.Default));
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPath<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, float thickness, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPath(new Pen<TColor, TPacked>(brush, thickness), path, options);
}
/// <summary>
@ -152,6 +308,26 @@ namespace ImageSharp
return source.DrawPath(new Pen<TColor, TPacked>(brush, thickness), path);
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawPath<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, float thickness, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPath(new SolidBrush<TColor, TPacked>(color), thickness, path, options);
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
@ -169,6 +345,26 @@ namespace ImageSharp
return source.DrawPath(new SolidBrush<TColor, TPacked>(color), thickness, path);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawLines<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPath(new Pen<TColor, TPacked>(brush, thickness), new Path(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
@ -203,6 +399,45 @@ namespace ImageSharp
return source.DrawLines(new SolidBrush<TColor, TPacked>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawLines<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawLines(new SolidBrush<TColor, TPacked>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawLines<TColor, TPacked>(this Image<TColor, TPacked> source, IPen<TColor, TPacked> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPath(pen, new Path(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
@ -218,7 +453,26 @@ namespace ImageSharp
{
return source.DrawPath(pen, new Path(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawBeziers<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPath(new Pen<TColor, TPacked>(brush, thickness), new Path(new BezierLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
@ -254,6 +508,45 @@ namespace ImageSharp
return source.DrawBeziers(new SolidBrush<TColor, TPacked>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawBeziers<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawBeziers(new SolidBrush<TColor, TPacked>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> DrawBeziers<TColor, TPacked>(this Image<TColor, TPacked> source, IPen<TColor, TPacked> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.DrawPath(pen, new Path(new BezierLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>

77
src/ImageSharp/Drawing/Fill.cs

@ -48,6 +48,22 @@ namespace ImageSharp
return source.Fill(new SolidBrush<TColor, TPacked>(color));
}
/// <summary>
/// Flood fills the image in the shape o fhte provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor, TPacked> Fill<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(new FillShapeProcessor<TColor, TPacked>(brush, shape, options));
}
/// <summary>
/// Flood fills the image in the shape o fhte provided polygon with the specified brush..
/// </summary>
@ -61,7 +77,26 @@ namespace ImageSharp
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(new FillShapeProcessor<TColor, TPacked>(brush, shape));
return source.Process(new FillShapeProcessor<TColor, TPacked>(brush, shape, GraphicsOptions.Default));
}
/// <summary>
/// Flood fills the image in the shape o fhte provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> Fill<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Fill(new SolidBrush<TColor, TPacked>(color), shape, options);
}
/// <summary>
@ -80,6 +115,26 @@ namespace ImageSharp
return source.Fill(new SolidBrush<TColor, TPacked>(color), shape);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> FillPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, IBrush<TColor, TPacked> brush, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
// using Polygon directly instead of LinearPolygon as its will have less indirection
return source.Fill(brush, new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
@ -97,6 +152,26 @@ namespace ImageSharp
return source.Fill(brush, new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPacked">The type of the packed.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor, TPacked> FillPolygon<TColor, TPacked>(this Image<TColor, TPacked> source, TColor color, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
// using Polygon directly instead of LinearPolygon as its will have less indirection
return source.Fill(new SolidBrush<TColor, TPacked>(color), new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>

32
src/ImageSharp/Drawing/GraphicsOptions.cs

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ImageSharp.Drawing
{
/// <summary>
/// Options for influancing the drawing functions.
/// </summary>
public struct GraphicsOptions
{
/// <summary>
/// Represents the default <see cref="GraphicsOptions"/>.
/// </summary>
public static readonly GraphicsOptions Default = new GraphicsOptions(true);
/// <summary>
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
/// </summary>
/// <param name="enableAntialiasing">if set to <c>true</c> [enable antialiasing].</param>
public GraphicsOptions(bool enableAntialiasing)
{
Antialias = enableAntialiasing;
}
/// <summary>
/// Should antialias be applied.
/// </summary>
public bool Antialias;
}
}

9
src/ImageSharp/Drawing/Paths/IPath.cs

@ -43,9 +43,10 @@ namespace ImageSharp.Drawing.Paths
/// <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>
PointInfo Distance(int x, int y);
/// <param name="point">The point.</param>
/// <returns>
/// Returns details about the point and its distance away from the path.
/// </returns>
PointInfo Distance(Vector2 point);
}
}

4
src/ImageSharp/Drawing/Paths/Path.cs

@ -73,9 +73,9 @@ namespace ImageSharp.Drawing.Paths
/// <returns>
/// Returns details about the point and its distance away from the path.
/// </returns>
public PointInfo Distance(int x, int y)
public PointInfo Distance(Vector2 point)
{
return this.innerPath.DistanceFromPath(new Vector2(x, y));
return this.innerPath.DistanceFromPath(point);
}
}
}

39
src/ImageSharp/Drawing/Processors/DrawPathProcessor.cs

@ -33,14 +33,16 @@ namespace ImageSharp.Drawing.Processors
private readonly IPen<TColor, TPacked> pen;
private readonly IPath[] paths;
private readonly RectangleF region;
private readonly GraphicsOptions options;
/// <summary>
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor, TPacked}" /> class.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
public DrawPathProcessor(IPen<TColor, TPacked> pen, IShape shape)
: this(pen, shape.ToArray())
/// <param name="options">The options.</param>
public DrawPathProcessor(IPen<TColor, TPacked> pen, IShape shape, GraphicsOptions options)
: this(pen, shape.ToArray(), options)
{
}
@ -48,11 +50,24 @@ namespace ImageSharp.Drawing.Processors
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
public DrawPathProcessor(IPen<TColor, TPacked> pen, IPath path, GraphicsOptions options)
: this(pen, new[] { path }, options)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor, TPacked}" /> class.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="paths">The paths.</param>
public DrawPathProcessor(IPen<TColor, TPacked> pen, params IPath[] paths)
/// <param name="options">The options.</param>
public DrawPathProcessor(IPen<TColor, TPacked> pen, IPath[] paths, GraphicsOptions options)
{
this.paths = paths;
this.pen = pen;
this.options = options;
if (paths.Length != 1)
{
@ -112,15 +127,17 @@ namespace ImageSharp.Drawing.Processors
y =>
{
int offsetY = y - polyStartY;
var currentPoint = default(Vector2);
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
currentPoint.X = offsetX;
currentPoint.Y = offsetY;
var dist = Closest(offsetX, offsetY);
var dist = Closest(currentPoint);
var color = applicator.GetColor(dist);
var opacity = this.Opacity(color.DistanceFromElement);
if (opacity > Epsilon)
@ -143,14 +160,14 @@ namespace ImageSharp.Drawing.Processors
}
}
private PointInfo Closest(int x, int y)
private PointInfo Closest(Vector2 point)
{
PointInfo result = default(PointInfo);
float distance = float.MaxValue;
for (int i = 0; i < this.paths.Length; i++)
{
var p = this.paths[i].Distance(x, y);
var p = this.paths[i].Distance(point);
if (p.DistanceFromPath < distance)
{
distance = p.DistanceFromPath;
@ -167,7 +184,7 @@ namespace ImageSharp.Drawing.Processors
{
return 1;
}
else if (distance < AntialiasFactor)
else if (this.options.Antialias && distance < AntialiasFactor)
{
return 1 - (distance / AntialiasFactor);
}

12
src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs

@ -28,16 +28,18 @@ namespace ImageSharp.Drawing.Processors
private const int DrawPadding = 1;
private readonly IBrush<TColor, TPacked> fillColor;
private readonly IShape poly;
private readonly GraphicsOptions options;
/// <summary>
/// Initializes a new instance of the <see cref="FillShapeProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
public FillShapeProcessor(IBrush<TColor, TPacked> brush, IShape shape)
public FillShapeProcessor(IBrush<TColor, TPacked> brush, IShape shape, GraphicsOptions options)
{
this.poly = shape;
this.fillColor = brush;
this.options = options;
}
/// <inheritdoc/>
@ -71,7 +73,7 @@ namespace ImageSharp.Drawing.Processors
{
polyStartY = 0;
}
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (IBrushApplicator<TColor, TPacked> applicator = this.fillColor.CreateApplicator(rect))
{
@ -84,13 +86,13 @@ namespace ImageSharp.Drawing.Processors
int offsetY = y - polyStartY;
Vector2 currentPoint = default(Vector2);
Vector2 currentPointOffset = default(Vector2);
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
currentPoint.X = offsetX;
currentPoint.Y = offsetY;
var dist = this.poly.Distance(offsetX, offsetY);
var dist = this.poly.Distance(currentPoint);
var opacity = this.Opacity(dist);
if (opacity > Epsilon)
@ -118,7 +120,7 @@ namespace ImageSharp.Drawing.Processors
{
return 1;
}
else if (distance < AntialiasFactor)
else if (this.options.Antialias && distance < AntialiasFactor)
{
return 1 - (distance / AntialiasFactor);
}

5
src/ImageSharp/Drawing/Shapes/BezierPolygon.cs

@ -37,12 +37,11 @@ namespace ImageSharp.Drawing.Shapes
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="point">The point.</param>
/// <returns>
/// The distance from the shape.
/// </returns>
public float Distance(int x, int y) => this.innerPolygon.Distance(x, y);
public float Distance(Vector2 point) => this.innerPolygon.Distance(point);
/// <summary>
/// Returns an enumerator that iterates through the collection.

9
src/ImageSharp/Drawing/Shapes/ComplexPolygon.cs

@ -65,24 +65,23 @@ namespace ImageSharp.Drawing.Shapes
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from thr shape to the point
/// </returns>
float IShape.Distance(int x, int y)
float IShape.Distance(Vector2 point)
{
// get the outline we are closest to the center of
// by rights we should only be inside 1 outline
// othersie we will start returning the distanct to the nearest shape
var dist = this.outlines.Select(o => o.Distance(x, y)).OrderBy(p => p).First();
var dist = this.outlines.Select(o => o.Distance(point)).OrderBy(p => p).First();
if (dist <= 0)
{
// inside poly
foreach (var hole in this.holes)
{
var distFromHole = hole.Distance(x, y);
var distFromHole = hole.Distance(point);
// less than zero we are inside shape
if (distFromHole <= 0)

11
src/ImageSharp/Drawing/Shapes/IShape.cs

@ -6,7 +6,7 @@
namespace ImageSharp.Drawing.Shapes
{
using System.Collections.Generic;
using System.Numerics;
using Paths;
/// <summary>
@ -25,9 +25,10 @@ namespace ImageSharp.Drawing.Shapes
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>Returns the distance from the shape to the point</returns>
float Distance(int x, int y);
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from the shape to the point
/// </returns>
float Distance(Vector2 point);
}
}

5
src/ImageSharp/Drawing/Shapes/LinearPolygon.cs

@ -37,12 +37,11 @@ namespace ImageSharp.Drawing.Shapes
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from the shape to the point
/// </returns>
public float Distance(int x, int y) => this.innerPolygon.Distance(x, y);
public float Distance(Vector2 point) => this.innerPolygon.Distance(point);
/// <summary>
/// Returns an enumerator that iterates through the collection.

11
src/ImageSharp/Drawing/Shapes/Polygon.cs

@ -56,15 +56,12 @@ namespace ImageSharp.Drawing.Shapes
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="point">The point.</param>
/// <returns>
/// The distance of the point away from the shape
/// </returns>
public float Distance(int x, int y)
public float Distance(Vector2 point)
{
var point = new Vector2(x, y);
bool isInside = this.innerPath.PointInPolygon(point);
var distance = this.innerPath.DistanceFromPath(point).DistanceFromPath;
@ -106,9 +103,9 @@ namespace ImageSharp.Drawing.Shapes
/// <returns>
/// distance metadata about the point.
/// </returns>
PointInfo IPath.Distance(int x, int y)
PointInfo IPath.Distance(Vector2 point)
{
return this.innerPath.DistanceFromPath(new Vector2(x, y));
return this.innerPath.DistanceFromPath(point);
}
/// <summary>

2
tests/ImageSharp.Tests/Drawing/DrawPathTests.cs

@ -17,8 +17,6 @@ namespace ImageSharp.Tests.Drawing
public class DrawPathTests : FileTestBase
{
[Fact]
public void ImageShouldBeOverlayedByPath()
{

30
tests/ImageSharp.Tests/Drawing/LineTests.cs

@ -16,8 +16,6 @@ namespace ImageSharp.Tests.Drawing
public class LineTests : FileTestBase
{
[Fact]
public void ImageShouldBeOverlayedByPath()
{
@ -44,9 +42,35 @@ namespace ImageSharp.Tests.Drawing
Assert.Equal(Color.Blue, sourcePixels[50, 50]);
}
}
[Fact]
public void ImageShouldBeOverlayedByPath_NoAntialias()
{
string path = CreateOutputDirectory("Drawing", "Lines");
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Simple_noantialias.png"))
{
image
.BackgroundColor(Color.Blue)
.DrawLines(Color.HotPink, 5, new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
}, new GraphicsOptions(false))
.Save(output);
}
using (var sourcePixels = image.Lock())
{
Assert.Equal(Color.HotPink, sourcePixels[9, 9]);
Assert.Equal(Color.HotPink, sourcePixels[199, 149]);
Assert.Equal(Color.Blue, sourcePixels[50, 50]);
}
}
[Fact]
public void ImageShouldBeOverlayedByPathDashed()

31
tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs

@ -46,6 +46,37 @@ namespace ImageSharp.Tests.Drawing
}
}
[Fact]
public void ImageShouldBeOverlayedByFilledPolygon_NoAntialias()
{
string path = CreateOutputDirectory("Drawing", "FilledPolygons");
var simplePath = new[] {
new Vector2(10, 10),
new Vector2(200, 150),
new Vector2(50, 300)
};
var image = new Image(500, 500);
using (FileStream output = File.OpenWrite($"{path}/Simple_NoAntialias.png"))
{
image
.BackgroundColor(Color.Blue)
.FillPolygon(Color.HotPink, simplePath, new GraphicsOptions(false))
.Save(output);
}
using (var sourcePixels = image.Lock())
{
Assert.Equal(Color.HotPink, sourcePixels[11, 11]);
Assert.Equal(Color.HotPink, sourcePixels[200, 150]);
Assert.Equal(Color.HotPink, sourcePixels[50, 50]);
Assert.Equal(Color.Blue, sourcePixels[2, 2]);
}
}
[Fact]
public void ImageShouldBeOverlayedByFilledPolygonOpacity()
{

Loading…
Cancel
Save