diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 9fb0e1e8da..15b7df2a22 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -39,8 +39,8 @@ All - - + + ..\..\ImageSharp.ruleset diff --git a/src/ImageSharp.Drawing/Text/DrawText.cs b/src/ImageSharp.Drawing/Text/DrawText.cs index 876d17aca0..1e87fd0084 100644 --- a/src/ImageSharp.Drawing/Text/DrawText.cs +++ b/src/ImageSharp.Drawing/Text/DrawText.cs @@ -181,7 +181,8 @@ namespace ImageSharp { ApplyKerning = options.ApplyKerning, TabWidth = options.TabWidth, - WrappingWidth = options.WrapTextWidth + WrappingWidth = options.WrapTextWidth, + Alignment = options.TextAlignment }; renderer.RenderText(text, style); diff --git a/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs index 6b09f23951..388b39bcc5 100644 --- a/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs @@ -2,9 +2,11 @@ // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // - namespace ImageSharp.Drawing { + using ImageSharp.PixelFormats; + using SixLabors.Fonts; + /// /// Options for influencing the drawing functions. /// @@ -15,50 +17,94 @@ namespace ImageSharp.Drawing /// public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + + private bool? applyKerning; + + private float? tabWidth; + + private PixelBlenderMode blenderMode; + + private bool? useImageResolution; + + private float wrapTextWidth; + + private SixLabors.Fonts.TextAlignment? textAlignment; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public TextGraphicsOptions(bool enableAntialiasing) + { + this.applyKerning = true; + this.tabWidth = 4; + this.useImageResolution = false; + this.wrapTextWidth = 0; + this.textAlignment = SixLabors.Fonts.TextAlignment.Left; + + this.antialiasSubpixelDepth = 16; + this.blenderMode = PixelBlenderMode.Normal; + this.blendPercentage = 1; + this.antialias = enableAntialiasing; + } + + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } + /// - /// Whether antialiasing should be applied. + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation /// - public bool Antialias; + public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. /// - /// The number of subpixels to use while rendering with antialiasing enabled. + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation /// - public int AntialiasSubpixelDepth; + public PixelBlenderMode BlenderMode { get => this.blenderMode; set => this.blenderMode = value; } /// - /// Whether the text should be drawing with kerning enabled. + /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. /// - public bool ApplyKerning; + public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } /// - /// The number of space widths a tab should lock to. + /// Gets or sets a value indicating the number of space widths a tab should lock to. /// - public float TabWidth; + public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } /// - /// Flag weather to use the current image resultion to for point size scaling. + /// Gets or sets a value indicating whether to use the current image resultion to for point size scaling. /// If this is [false] the text renders at 72dpi otherwise it renders at Image resolution /// - public bool UseImageResolution; + public bool UseImageResolution { get => this.useImageResolution ?? false; set => this.useImageResolution = value; } /// - /// If greater than zero determine the width at which text should wrap. + /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. /// - public float WrapTextWidth; + public float WrapTextWidth { get => this.wrapTextWidth; set => this.wrapTextWidth = value; } /// - /// Initializes a new instance of the struct. + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// If is greater than zero it will align relative to the space + /// defined by the location and width, if equals zero, and thus + /// wrapping disabled, then the alignment is relative to the drawing location. /// - /// If set to true [enable antialiasing]. - public TextGraphicsOptions(bool enableAntialiasing) - { - this.Antialias = enableAntialiasing; - this.ApplyKerning = true; - this.TabWidth = 4; - this.AntialiasSubpixelDepth = 16; - this.UseImageResolution = false; - this.WrapTextWidth = 0; - } + public TextAlignment TextAlignment { get => this.textAlignment ?? TextAlignment.Left; set => this.textAlignment = value; } /// /// Performs an implicit conversion from to . @@ -71,7 +117,9 @@ namespace ImageSharp.Drawing { return new TextGraphicsOptions(options.Antialias) { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, + blendPercentage = options.BlendPercentage, + blenderMode = options.BlenderMode }; } @@ -86,7 +134,9 @@ namespace ImageSharp.Drawing { return new GraphicsOptions(options.Antialias) { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, + BlenderMode = options.BlenderMode, + BlendPercentage = options.BlendPercentage }; } } diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index bc6a11955c..cff9fc04e0 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -182,7 +182,7 @@ namespace ImageSharp break; } - Func, int> getMinY = pixels => + int GetMinY(PixelAccessor pixels) { for (int y = 0; y < height; y++) { @@ -196,9 +196,9 @@ namespace ImageSharp } return 0; - }; + } - Func, int> getMaxY = pixels => + int GetMaxY(PixelAccessor pixels) { for (int y = height - 1; y > -1; y--) { @@ -212,9 +212,9 @@ namespace ImageSharp } return height; - }; + } - Func, int> getMinX = pixels => + int GetMinX(PixelAccessor pixels) { for (int x = 0; x < width; x++) { @@ -228,9 +228,9 @@ namespace ImageSharp } return 0; - }; + } - Func, int> getMaxX = pixels => + int GetMaxX(PixelAccessor pixels) { for (int x = width - 1; x > -1; x--) { @@ -244,14 +244,14 @@ namespace ImageSharp } return height; - }; + } using (PixelAccessor bitmapPixels = bitmap.Lock()) { - topLeft.Y = getMinY(bitmapPixels); - topLeft.X = getMinX(bitmapPixels); - bottomRight.Y = (getMaxY(bitmapPixels) + 1).Clamp(0, height); - bottomRight.X = (getMaxX(bitmapPixels) + 1).Clamp(0, width); + topLeft.Y = GetMinY(bitmapPixels); + topLeft.X = GetMinX(bitmapPixels); + bottomRight.Y = (GetMaxY(bitmapPixels) + 1).Clamp(0, height); + bottomRight.X = (GetMaxX(bitmapPixels) + 1).Clamp(0, width); } return GetBoundingRectangle(topLeft, bottomRight); diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs index 5a6eebf405..ac2627701f 100644 --- a/src/ImageSharp/PixelFormats/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/Alpha8.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing a single 8 bit normalized W values. + /// /// Ranges from <0, 0, 0, 0> to <0, 0, 0, 1> in vector form. + /// /// public struct Alpha8 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs index 2798c4c5ad..61e860aeee 100644 --- a/src/ImageSharp/PixelFormats/Argb32.cs +++ b/src/ImageSharp/PixelFormats/Argb32.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in alpha, red, green, and blue order. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// /// /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs index 78442a3cef..813b6fe857 100644 --- a/src/ImageSharp/PixelFormats/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/Bgr565.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x and z components use 5 bits, and the y component uses 6 bits. + /// /// Ranges from <0, 0, 0, 1> to <1, 1, 1, 1> in vector form. + /// /// public struct Bgr565 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs index 9138e25ca5..8fb2d0c260 100644 --- a/src/ImageSharp/PixelFormats/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/Bgra4444.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing unsigned normalized values, ranging from 0 to 1, using 4 bits each for x, y, z, and w. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// public struct Bgra4444 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs index 9ff571243e..26cfa6b8c0 100644 --- a/src/ImageSharp/PixelFormats/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/Bgra5551.cs @@ -11,6 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x , y and z components use 5 bits, and the w component uses 1 bit. + /// + /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// public struct Bgra5551 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs index b27952ce4d..951b7c3cb5 100644 --- a/src/ImageSharp/PixelFormats/Byte4.cs +++ b/src/ImageSharp/PixelFormats/Byte4.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit unsigned integer values, ranging from 0 to 255. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// public struct Byte4 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs index 2a686f5356..e9f02d34eb 100644 --- a/src/ImageSharp/PixelFormats/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/HalfSingle.cs @@ -10,7 +10,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing a single 16 bit floating point value. + /// /// Ranges from <0, 0, 0, 1> to <1, 0, 0, 1> in vector form. + /// /// public struct HalfSingle : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs index ef9676b562..8813fd455f 100644 --- a/src/ImageSharp/PixelFormats/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/HalfVector2.cs @@ -10,7 +10,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit floating-point values. + /// /// Ranges from <0, 0, 0, 1> to <1, 0, 0, 1> in vector form. + /// /// public struct HalfVector2 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs index 8b284509f7..e8c78047ea 100644 --- a/src/ImageSharp/PixelFormats/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/HalfVector4.cs @@ -10,7 +10,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit floating-point values. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// public struct HalfVector4 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs index c5b6eff6bb..93226342ed 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed packed pixel type containing two 8-bit signed normalized values, ranging from −1 to 1. + /// /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form. + /// /// public struct NormalizedByte2 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs index 9e36766601..66a79fefc6 100644 --- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit signed normalized values, ranging from −1 to 1. + /// /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form. + /// /// public struct NormalizedByte4 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs index 01a2d99547..99e5a98c00 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs @@ -10,7 +10,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit signed normalized values, ranging from −1 to 1. + /// /// Ranges from <-1, -1, 0, 1> to <1, 1, 0, 1> in vector form. + /// /// public struct NormalizedShort2 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs index 3e4535fdf1..932ab97cf8 100644 --- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs @@ -10,7 +10,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit signed normalized values, ranging from −1 to 1. + /// /// Ranges from <-1, -1, -1, -1> to <1, 1, 1, 1> in vector form. + /// /// public struct NormalizedShort4 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs index 4d1f0fecfd..3e23777f68 100644 --- a/src/ImageSharp/PixelFormats/Rg32.cs +++ b/src/ImageSharp/PixelFormats/Rg32.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit unsigned normalized values ranging from 0 to 1. + /// /// Ranges from <0, 0, 0, 1> to <1, 1, 0, 1> in vector form. + /// /// public struct Rg32 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs index 96f7af7732..747112fd80 100644 --- a/src/ImageSharp/PixelFormats/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs @@ -12,7 +12,9 @@ namespace ImageSharp.PixelFormats /// /// Packed vector type containing unsigned normalized values ranging from 0 to 1. /// The x, y and z components use 10 bits, and the w component uses 2 bits. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// public struct Rgba1010102 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs index 31eae8abe5..f58150e2e0 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.cs @@ -14,7 +14,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255. /// The color components are stored in red, green, blue, and alpha order. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// /// /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs index b7ff143a95..296c17a4e1 100644 --- a/src/ImageSharp/PixelFormats/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/Rgba64.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit unsigned normalized values ranging from 0 to 1. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// public struct Rgba64 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs index 25eaa97117..a92b794efb 100644 --- a/src/ImageSharp/PixelFormats/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/RgbaVector.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Unpacked pixel type containing four 16-bit floating-point values typically ranging from 0 to 1. /// The color components are stored in red, green, blue, and alpha order. + /// /// Ranges from <0, 0, 0, 0> to <1, 1, 1, 1> in vector form. + /// /// /// /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs index d681e27b78..6c871ecb67 100644 --- a/src/ImageSharp/PixelFormats/Short2.cs +++ b/src/ImageSharp/PixelFormats/Short2.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing two 16-bit signed integer values. + /// /// Ranges from <-32767, -32767, 0, 1> to <32767, 32767, 0, 1> in vector form. + /// /// public struct Short2 : IPixel, IPackedVector { diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs index f58949a720..de110c7d3b 100644 --- a/src/ImageSharp/PixelFormats/Short4.cs +++ b/src/ImageSharp/PixelFormats/Short4.cs @@ -11,7 +11,9 @@ namespace ImageSharp.PixelFormats /// /// Packed pixel type containing four 16-bit signed integer values. + /// /// Ranges from <-37267, -37267, -37267, -37267> to <37267, 37267, 37267, 37267> in vector form. + /// /// public struct Short4 : IPixel, IPackedVector {