mirror of https://github.com/SixLabors/ImageSharp
229 changed files with 6801 additions and 5462 deletions
@ -1,51 +0,0 @@ |
|||
// <copyright file="Drawable.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>
|
|||
/// Represents a path or set of paths that can be drawn as an outline.
|
|||
/// </summary>
|
|||
public abstract class Drawable |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the maximum number of intersections to could be returned.
|
|||
/// </summary>
|
|||
public abstract int MaxIntersections { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the bounds.
|
|||
/// </summary>
|
|||
public abstract Rectangle Bounds { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the point information for the specified x and y location.
|
|||
/// </summary>
|
|||
/// <param name="x">The x.</param>
|
|||
/// <param name="y">The y.</param>
|
|||
/// <returns>Information about the point in relation to a drawable edge</returns>
|
|||
public abstract PointInfo GetPointInfo(int x, int y); |
|||
|
|||
/// <summary>
|
|||
/// Scans the X axis for intersections.
|
|||
/// </summary>
|
|||
/// <param name="x">The x.</param>
|
|||
/// <param name="buffer">The buffer.</param>
|
|||
/// <param name="length">The length.</param>
|
|||
/// <param name="offset">The offset.</param>
|
|||
/// <returns>The number of intersections found.</returns>
|
|||
public abstract int ScanX(int x, float[] buffer, int length, int offset); |
|||
|
|||
/// <summary>
|
|||
/// Scans the Y axis for intersections.
|
|||
/// </summary>
|
|||
/// <param name="y">The position along the y axis to find intersections.</param>
|
|||
/// <param name="buffer">The buffer.</param>
|
|||
/// <param name="length">The length.</param>
|
|||
/// <param name="offset">The offset.</param>
|
|||
/// <returns>The number of intersections found.</returns>
|
|||
public abstract int ScanY(int y, float[] buffer, int length, int offset); |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
// <copyright file="FillPaths.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using Drawing; |
|||
using Drawing.Brushes; |
|||
using ImageSharp.PixelFormats; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush..
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="paths">The shapes.</param>
|
|||
/// <param name="options">The graphics options.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, IPathCollection paths, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
foreach (IPath s in paths) |
|||
{ |
|||
source.Fill(brush, s, options); |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="paths">The paths.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, IPathCollection paths) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.Fill(brush, paths, GraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush..
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="paths">The paths.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, IPathCollection paths, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.Fill(new SolidBrush<TPixel>(color), paths, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush..
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="paths">The paths.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, IPathCollection paths) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.Fill(new SolidBrush<TPixel>(color), paths); |
|||
} |
|||
} |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
// <copyright file="ColoredPointInfo.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing.Processors |
|||
{ |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Returns details about how far away from the inside of a shape and the color the pixel could be.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
public struct ColoredPointInfo<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// The color
|
|||
/// </summary>
|
|||
public TPixel Color; |
|||
|
|||
/// <summary>
|
|||
/// The distance from element
|
|||
/// </summary>
|
|||
public float DistanceFromElement; |
|||
} |
|||
} |
|||
@ -1,40 +0,0 @@ |
|||
// <copyright file="PenApplicator.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing.Processors |
|||
{ |
|||
using System; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// primitive that converts a <see cref="PointInfo"/> into a color and a distance away from the drawable part of the path.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
public abstract class PenApplicator<TPixel> : IDisposable |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the required region.
|
|||
/// </summary>
|
|||
/// <value>
|
|||
/// The required region.
|
|||
/// </value>
|
|||
public abstract RectangleF RequiredRegion { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public abstract void Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Gets a <see cref="ColoredPointInfo{TPixel}" /> from a point represented by a <see cref="PointInfo" />.
|
|||
/// </summary>
|
|||
/// <param name="x">The x.</param>
|
|||
/// <param name="y">The y.</param>
|
|||
/// <param name="info">The information to extract color details about.</param>
|
|||
/// <returns>
|
|||
/// Returns the color details and distance from a solid bit of the line.
|
|||
/// </returns>
|
|||
public abstract ColoredPointInfo<TPixel> GetColor(int x, int y, PointInfo info); |
|||
} |
|||
} |
|||
@ -1,142 +0,0 @@ |
|||
// <copyright file="DrawPathProcessor.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing.Processors |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Threading.Tasks; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
using ImageSharp.Processing; |
|||
using Pens; |
|||
|
|||
/// <summary>
|
|||
/// Draws a path using the processor pipeline
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <seealso cref="ImageSharp.Processing.ImageProcessor{TPixel}" />
|
|||
internal class DrawPathProcessor<TPixel> : ImageProcessor<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
private const float AntialiasFactor = 1f; |
|||
private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawPathProcessor{TPixel}" /> class.
|
|||
/// </summary>
|
|||
/// <param name="pen">The details how to draw the outline/path.</param>
|
|||
/// <param name="drawable">The details of the paths and outlines to draw.</param>
|
|||
/// <param name="options">The drawing configuration options.</param>
|
|||
public DrawPathProcessor(IPen<TPixel> pen, Drawable drawable, GraphicsOptions options) |
|||
{ |
|||
this.Path = drawable; |
|||
this.Pen = pen; |
|||
this.Options = options; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the graphics options.
|
|||
/// </summary>
|
|||
public GraphicsOptions Options { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the pen.
|
|||
/// </summary>
|
|||
public IPen<TPixel> Pen { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the path.
|
|||
/// </summary>
|
|||
public Drawable Path { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle) |
|||
{ |
|||
using (PixelAccessor<TPixel> sourcePixels = source.Lock()) |
|||
using (PenApplicator<TPixel> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds, this.Options)) |
|||
{ |
|||
Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion); |
|||
|
|||
int polyStartY = rect.Y - PaddingFactor; |
|||
int polyEndY = rect.Bottom + PaddingFactor; |
|||
int startX = rect.X - PaddingFactor; |
|||
int endX = rect.Right + PaddingFactor; |
|||
|
|||
int minX = Math.Max(sourceRectangle.Left, startX); |
|||
int maxX = Math.Min(sourceRectangle.Right, endX); |
|||
int minY = Math.Max(sourceRectangle.Top, polyStartY); |
|||
int maxY = Math.Min(sourceRectangle.Bottom, polyEndY); |
|||
|
|||
// Align start/end positions.
|
|||
minX = Math.Max(0, minX); |
|||
maxX = Math.Min(source.Width, maxX); |
|||
minY = Math.Max(0, minY); |
|||
maxY = Math.Min(source.Height, maxY); |
|||
|
|||
// Reset offset if necessary.
|
|||
if (minX > 0) |
|||
{ |
|||
startX = 0; |
|||
} |
|||
|
|||
if (minY > 0) |
|||
{ |
|||
polyStartY = 0; |
|||
} |
|||
|
|||
int width = maxX - minX; |
|||
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.Options.BlenderMode); |
|||
|
|||
Parallel.For( |
|||
minY, |
|||
maxY, |
|||
this.ParallelOptions, |
|||
y => |
|||
{ |
|||
int offsetY = y - polyStartY; |
|||
|
|||
using (Buffer<float> amount = new Buffer<float>(width)) |
|||
using (Buffer<TPixel> colors = new Buffer<TPixel>(width)) |
|||
{ |
|||
for (int i = 0; i < width; i++) |
|||
{ |
|||
int x = i + minX; |
|||
int offsetX = x - startX; |
|||
PointInfo info = this.Path.GetPointInfo(offsetX, offsetY); |
|||
ColoredPointInfo<TPixel> color = applicator.GetColor(offsetX, offsetY, info); |
|||
amount[i] = (this.Opacity(color.DistanceFromElement) * this.Options.BlendPercentage).Clamp(0, 1); |
|||
colors[i] = color.Color; |
|||
} |
|||
|
|||
Span<TPixel> destination = sourcePixels.GetRowSpan(offsetY).Slice(minX - startX, width); |
|||
blender.Blend(destination, destination, colors, amount); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct opacity for the given distance.
|
|||
/// </summary>
|
|||
/// <param name="distance">Thw distance from the central point.</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
private float Opacity(float distance) |
|||
{ |
|||
if (distance <= 0) |
|||
{ |
|||
return 1; |
|||
} |
|||
|
|||
if (this.Options.Antialias && distance < AntialiasFactor) |
|||
{ |
|||
return 1 - (distance / AntialiasFactor); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,200 @@ |
|||
// <copyright file="DrawText.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Drawing; |
|||
using Drawing.Brushes; |
|||
using Drawing.Pens; |
|||
using ImageSharp.PixelFormats; |
|||
using SixLabors.Fonts; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, TPixel color, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, color, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, TPixel color, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, Brushes.Solid(color), null, path, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="path">The location.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, brush, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, brush, null, path, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IPen<TPixel> pen, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, pen, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IPen<TPixel> pen, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, null, pen, path, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush then outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPen<TPixel> pen, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, brush, pen, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush then outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPen<TPixel> pen, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
Vector2 dpi = DefaultTextDpi; |
|||
if (options.UseImageResolution) |
|||
{ |
|||
dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); |
|||
} |
|||
|
|||
var style = new FontSpan(font, dpi) |
|||
{ |
|||
ApplyKerning = options.ApplyKerning, |
|||
TabWidth = options.TabWidth, |
|||
WrappingWidth = options.WrapTextWidth, |
|||
HorizontalAlignment = options.HorizontalAlignment, |
|||
VerticalAlignment = options.VerticalAlignment |
|||
}; |
|||
|
|||
IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, path, style); |
|||
|
|||
var pathOptions = (GraphicsOptions)options; |
|||
if (brush != null) |
|||
{ |
|||
source.Fill(brush, glyphs, pathOptions); |
|||
} |
|||
|
|||
if (pen != null) |
|||
{ |
|||
source.Draw(pen, glyphs, pathOptions); |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
} |
|||
} |
|||
@ -1,127 +0,0 @@ |
|||
// <copyright file="GlyphBuilder.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing |
|||
{ |
|||
using System.Collections.Generic; |
|||
using System.Numerics; |
|||
|
|||
using SixLabors.Fonts; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// rendering surface that Fonts can use to generate Shapes.
|
|||
/// </summary>
|
|||
internal class GlyphBuilder : IGlyphRenderer |
|||
{ |
|||
private readonly PathBuilder builder = new PathBuilder(); |
|||
private readonly List<IPath> paths = new List<IPath>(); |
|||
private Vector2 currentPoint = default(Vector2); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlyphBuilder"/> class.
|
|||
/// </summary>
|
|||
public GlyphBuilder() |
|||
: this(Vector2.Zero) |
|||
{ |
|||
// glyphs are renderd realative to bottom left so invert the Y axis to allow it to render on top left origin surface
|
|||
this.builder = new PathBuilder(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlyphBuilder"/> class.
|
|||
/// </summary>
|
|||
/// <param name="origin">The origin.</param>
|
|||
public GlyphBuilder(Vector2 origin) |
|||
{ |
|||
this.builder = new PathBuilder(); |
|||
this.builder.SetOrigin(origin); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the paths that have been rendered by this.
|
|||
/// </summary>
|
|||
public IEnumerable<IPath> Paths => this.paths; |
|||
|
|||
/// <summary>
|
|||
/// Begins the glyph.
|
|||
/// </summary>
|
|||
/// <param name="location">The offset that the glyph will be rendered at.</param>
|
|||
void IGlyphRenderer.BeginGlyph(Vector2 location) |
|||
{ |
|||
this.builder.Clear(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Begins the figure.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.BeginFigure() |
|||
{ |
|||
this.builder.StartFigure(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a cubic bezier from the current point to the <paramref name="point"/>
|
|||
/// </summary>
|
|||
/// <param name="secondControlPoint">The second control point.</param>
|
|||
/// <param name="thirdControlPoint">The third control point.</param>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.CubicBezierTo(Vector2 secondControlPoint, Vector2 thirdControlPoint, Vector2 point) |
|||
{ |
|||
this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends the glyph.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.EndGlyph() |
|||
{ |
|||
this.paths.Add(this.builder.Build()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends the figure.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.EndFigure() |
|||
{ |
|||
this.builder.CloseFigure(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a line from the current point to the <paramref name="point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.LineTo(Vector2 point) |
|||
{ |
|||
this.builder.AddLine(this.currentPoint, point); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Moves to current point to the supplied vector.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.MoveTo(Vector2 point) |
|||
{ |
|||
this.builder.StartFigure(); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a quadratics bezier from the current point to the <paramref name="point"/>
|
|||
/// </summary>
|
|||
/// <param name="secondControlPoint">The second control point.</param>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.QuadraticBezierTo(Vector2 secondControlPoint, Vector2 point) |
|||
{ |
|||
Vector2 c1 = (((secondControlPoint - this.currentPoint) * 2) / 3) + this.currentPoint; |
|||
Vector2 c2 = (((secondControlPoint - point) * 2) / 3) + point; |
|||
|
|||
this.builder.AddBezier(this.currentPoint, c1, c2, point); |
|||
this.currentPoint = point; |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
@ -0,0 +1,79 @@ |
|||
// <copyright file="Image.LoadPixelData.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Threading.Tasks; |
|||
using Formats; |
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <content>
|
|||
/// Adds static methods allowing the creation of new image from raw pixel data.
|
|||
/// </content>
|
|||
public static partial class Image |
|||
{ |
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
|
|||
/// </summary>
|
|||
/// <param name="data">The byte array containing image data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Span<TPixel> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
=> LoadPixelData(Configuration.Default, data, width, height); |
|||
|
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
|
|||
/// </summary>
|
|||
/// <param name="data">The byte array containing image data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Span<byte> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
=> LoadPixelData<TPixel>(Configuration.Default, data, width, height); |
|||
|
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
|
|||
/// </summary>
|
|||
/// <param name="config">The config for the decoder.</param>
|
|||
/// <param name="data">The byte array containing image data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, Span<byte> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
=> LoadPixelData(config, data.NonPortableCast<byte, TPixel>(), width, height); |
|||
|
|||
/// <summary>
|
|||
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
|
|||
/// </summary>
|
|||
/// <param name="config">The config for the decoder.</param>
|
|||
/// <param name="data">The Span containing the image Pixel data.</param>
|
|||
/// <param name="width">The width of the final image.</param>
|
|||
/// <param name="height">The height of the final image.</param>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, Span<TPixel> data, int width, int height) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
int count = width * height; |
|||
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); |
|||
|
|||
var image = new Image<TPixel>(config, width, height); |
|||
SpanHelper.Copy(data, image.Pixels, count); |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// <copyright file="Matrix3x2Extensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Matrix3x2"/> struct
|
|||
/// </summary>
|
|||
public static class Matrix3x2Extensions |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a rotation matrix for the given rotation in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degree">The angle in degrees</param>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateRotation(float degree, Point centerPoint) |
|||
{ |
|||
float radian = MathF.DegreeToRadian(degree); |
|||
return Matrix3x2.CreateRotation(radian, new Vector2(centerPoint.X, centerPoint.Y)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a rotation matrix for the given rotation in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degree">The angle in degrees</param>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateRotation(float degree, PointF centerPoint) |
|||
{ |
|||
float radian = MathF.DegreeToRadian(degree); |
|||
return Matrix3x2.CreateRotation(radian, centerPoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix for the given angle in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degreesX">The x-angle in degrees</param>
|
|||
/// <param name="degreesY">The y-angle in degrees</param>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateSkew(float degreesX, float degreesY, Point centerPoint) |
|||
{ |
|||
float radiansX = MathF.DegreeToRadian(degreesX); |
|||
float radiansY = MathF.DegreeToRadian(degreesY); |
|||
return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix for the given angle in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degreesX">The x-angle in degrees</param>
|
|||
/// <param name="degreesY">The y-angle in degrees</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateSkew(float degreesX, float degreesY, PointF centerPoint) |
|||
{ |
|||
float radiansX = MathF.DegreeToRadian(degreesX); |
|||
float radiansY = MathF.DegreeToRadian(degreesY); |
|||
return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,233 @@ |
|||
// <copyright file="PointF.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an ordered pair of single precision floating point x- and y-coordinates that defines a point in
|
|||
/// a two-dimensional plane.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct PointF : IEquatable<PointF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="PointF"/> that has X and Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly PointF Empty = default(PointF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PointF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The horizontal position of the point.</param>
|
|||
/// <param name="y">The vertical position of the point.</param>
|
|||
public PointF(float x, float y) |
|||
: this() |
|||
{ |
|||
this.X = x; |
|||
this.Y = y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PointF"/> struct from the given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public PointF(SizeF size) |
|||
{ |
|||
this.X = size.Width; |
|||
this.Y = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the x-coordinate of this <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
public float X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the y-coordinate of this <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
public float Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="PointF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Point"/> with the coordinates of the specified <see cref="PointF"/> by truncating each of the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Point"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Point(PointF point) => Point.Truncate(point); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="PointF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF operator +(PointF point, SizeF size) => Add(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF operator -(PointF point, SizeF size) => Subtract(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PointF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PointF"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PointF"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(PointF left, PointF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PointF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PointF"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PointF"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(PointF left, PointF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Rotates a point around the given rotation matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="rotation">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Rotate(PointF point, Matrix3x2 rotation) => Vector2.Transform(new Vector2(point.X, point.Y), rotation); |
|||
|
|||
/// <summary>
|
|||
/// Skews a point using the given skew matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="skew">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Skew(PointF point, Matrix3x2 skew) => Vector2.Transform(new Vector2(point.X, point.Y), skew); |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="PointF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="dx">The amount to offset the x-coordinate.</param>
|
|||
/// <param name="dy">The amount to offset the y-coordinate.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(float dx, float dy) |
|||
{ |
|||
this.X += dx; |
|||
this.Y += dy; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="PointF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="point">The <see cref="PointF"/> used offset this <see cref="PointF"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(PointF point) => this.Offset(point.X, point.Y); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "PointF [ Empty ]"; |
|||
} |
|||
|
|||
return $"PointF [ X={this.X}, Y={this.Y} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y); |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="point">
|
|||
/// The instance of <see cref="PointF"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private int GetHashCode(PointF point) => point.X.GetHashCode() ^ point.Y.GetHashCode(); |
|||
} |
|||
} |
|||
@ -0,0 +1,179 @@ |
|||
// <copyright file="SizeF.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Stores an ordered pair of single precision floating points, which specify a height and width.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct SizeF : IEquatable<SizeF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="SizeF"/> that has Width and Height values set to zero.
|
|||
/// </summary>
|
|||
public static readonly SizeF Empty = default(SizeF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="width">The width of the size.</param>
|
|||
/// <param name="height">The height of the size.</param>
|
|||
public SizeF(float width, float height) |
|||
{ |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public SizeF(SizeF size) |
|||
: this() |
|||
{ |
|||
this.Width = size.Width; |
|||
this.Height = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct from the given <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
public SizeF(PointF point) |
|||
{ |
|||
this.Width = point.X; |
|||
this.Height = point.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width of this <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
public float Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height of this <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
public float Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="SizeF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Size"/> with the dimensions of the specified <see cref="SizeF"/> by truncating each of the dimensions.
|
|||
/// </summary>
|
|||
/// <param name="size">The size.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Size"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Size(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Converts the given <see cref="SizeF"/> into a <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator PointF(SizeF size) => new PointF(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of adding two sizes.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SizeF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF operator +(SizeF left, SizeF right) => Add(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Computes the difference left by subtracting one size from another.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SizeF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF operator -(SizeF left, SizeF right) => Subtract(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="SizeF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(SizeF left, SizeF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="SizeF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(SizeF left, SizeF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Performs vector addition of two <see cref="SizeF"/> objects.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="SizeF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF Add(SizeF left, SizeF right) => new SizeF(left.Width + right.Width, left.Height + right.Height); |
|||
|
|||
/// <summary>
|
|||
/// Contracts a <see cref="SizeF"/> by another <see cref="SizeF"/>
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="SizeF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF Subtract(SizeF left, SizeF right) => new SizeF(left.Width - right.Width, left.Height - right.Height); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "SizeF [ Empty ]"; |
|||
} |
|||
|
|||
return $"SizeF [ Width={this.Width}, Height={this.Height} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is SizeF && this.Equals((SizeF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height); |
|||
|
|||
private int GetHashCode(SizeF size) => size.Width.GetHashCode() ^ size.Height.GetHashCode(); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue