From e59f2206f3f6b3e92cfe7db53b3018a34e5871d9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 9 Nov 2019 21:26:48 +1100 Subject: [PATCH] Convert options into classes. --- .../Processing/GradientBrush.cs | 3 - .../Processing/TextGraphicsOptions.cs | 140 ++++++++++++------ src/ImageSharp/GraphicsOptions.cs | 120 ++++++++------- .../Drawing/Paths/DrawPathCollection.cs | 2 +- .../Drawing/Paths/FillPath.cs | 2 +- .../Drawing/Paths/FillPathCollection.cs | 2 +- .../Drawing/Paths/FillPolygon.cs | 2 +- .../Drawing/Paths/FillRectangle.cs | 4 +- .../PorterDuffCompositorTests.cs | 11 +- 9 files changed, 174 insertions(+), 112 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/GradientBrush.cs b/src/ImageSharp.Drawing/Processing/GradientBrush.cs index 69659431d..f17adf633 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrush.cs @@ -118,9 +118,6 @@ namespace SixLabors.ImageSharp.Processing else { float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio); - - // TODO: this should be changeble for different gradienting functions. - // TODO: Is the comment above still relevent? return new Color(Vector4.Lerp((Vector4)from.Color, (Vector4)to.Color, onLocalGradient)).ToPixel(); } } diff --git a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs index 13c7f4bdf..23d7aebf5 100644 --- a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.Fonts; using SixLabors.ImageSharp.PixelFormats; @@ -9,68 +10,87 @@ namespace SixLabors.ImageSharp.Processing /// /// Options for influencing the drawing functions. /// - public struct TextGraphicsOptions + public class TextGraphicsOptions { + private static readonly Lazy Lazy = new Lazy(); + private int antialiasSubpixelDepth; + private float blendPercentage; + private float tabWidth; + private float dpiX; + private float dpiY; + /// - /// Represents the default . + /// Initializes a new instance of the class. /// - public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); - - private const int DefaultTextDpi = 72; - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - - private bool? applyKerning; - - private float? tabWidth; - - private float? dpiX; - - private float? dpiY; - - private HorizontalAlignment? horizontalAlignment; - - private VerticalAlignment? verticalAlignment; + public TextGraphicsOptions() + : this(true) + { + } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the class. /// /// If set to true [enable antialiasing]. public TextGraphicsOptions(bool enableAntialiasing) { - this.applyKerning = true; - this.tabWidth = 4; + this.ApplyKerning = true; + this.TabWidth = 4F; this.WrapTextWidth = 0; - this.horizontalAlignment = HorizontalAlignment.Left; - this.verticalAlignment = VerticalAlignment.Top; + this.HorizontalAlignment = HorizontalAlignment.Left; + this.VerticalAlignment = VerticalAlignment.Top; this.antialiasSubpixelDepth = 16; this.ColorBlendingMode = PixelColorBlendingMode.Normal; this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; this.blendPercentage = 1F; - this.antialias = enableAntialiasing; - this.dpiX = DefaultTextDpi; - this.dpiY = DefaultTextDpi; + this.Antialias = enableAntialiasing; + this.dpiX = 72F; + this.dpiY = 72F; } + /// + /// Gets the default instance. + /// + public static TextGraphicsOptions Default { get; } = Lazy.Value; + /// /// Gets or sets a value indicating whether antialiasing should be applied. /// - public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } + public bool Antialias { get; set; } /// /// 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; } + public int AntialiasSubpixelDepth + { + get + { + return this.antialiasSubpixelDepth; + } + + set + { + Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.AntialiasSubpixelDepth)); + this.antialiasSubpixelDepth = value; + } + } /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation. /// - public float BlendPercentage { get => this.blendPercentage ?? 1F; set => this.blendPercentage = NumberUtils.ClampFloat(value, 0, 1F); } + public float BlendPercentage + { + get + { + return this.blendPercentage; + } + + set + { + Guard.MustBeBetweenOrEqualTo(value, 0, 1F, nameof(this.BlendPercentage)); + 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 @@ -89,27 +109,63 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. /// - public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } + public bool ApplyKerning { get; set; } /// /// Gets or sets a value indicating the number of space widths a tab should lock to. /// - public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } + public float TabWidth + { + get + { + return this.tabWidth; + } + + set + { + Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.TabWidth)); + this.tabWidth = value; + } + } /// - /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. + /// Gets or sets a value, if greater than 0, indicating the width at which text should wrap. /// public float WrapTextWidth { get; set; } /// /// Gets or sets a value indicating the DPI to render text along the X axis. /// - public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } + public float DpiX + { + get + { + return this.dpiX; + } + + set + { + Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.DpiX)); + this.dpiX = value; + } + } /// /// Gets or sets a value indicating the DPI to render text along the Y axis. /// - public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } + public float DpiY + { + get + { + return this.dpiY; + } + + set + { + Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.DpiY)); + this.dpiY = value; + } + } /// /// Gets or sets a value indicating how to align the text relative to the rendering space. @@ -117,12 +173,12 @@ namespace SixLabors.ImageSharp.Processing /// defined by the location and width, if equals zero, and thus /// wrapping disabled, then the alignment is relative to the drawing location. /// - public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } + public HorizontalAlignment HorizontalAlignment { get; set; } /// /// Gets or sets a value indicating how to align the text relative to the rendering space. /// - public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } + public VerticalAlignment VerticalAlignment { get; set; } /// /// Performs an implicit conversion from to . diff --git a/src/ImageSharp/GraphicsOptions.cs b/src/ImageSharp/GraphicsOptions.cs index 644bde1cf..1e18edb4a 100644 --- a/src/ImageSharp/GraphicsOptions.cs +++ b/src/ImageSharp/GraphicsOptions.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp @@ -8,108 +9,115 @@ namespace SixLabors.ImageSharp /// /// Options for influencing the drawing functions. /// - public struct GraphicsOptions + public class GraphicsOptions { + private static readonly Lazy Lazy = new Lazy(); + private int antialiasSubpixelDepth; + private float blendPercentage; + /// - /// Represents the default . + /// Initializes a new instance of the class. /// - public static readonly GraphicsOptions Default = new GraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; + public GraphicsOptions() + : this(true) + { + } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the class. /// /// If set to true [enable antialiasing]. public GraphicsOptions(bool enableAntialiasing) + : this(enableAntialiasing, 1F) { - this.ColorBlendingMode = PixelColorBlendingMode.Normal; - this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the class. /// /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, float opacity) + /// The blending percentage to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, float blendPercentage) + : this(enableAntialiasing, PixelColorBlendingMode.Normal, blendPercentage) { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.ColorBlendingMode = PixelColorBlendingMode.Normal; - this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the class. /// /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - /// color blending mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) + /// The color blending mode to apply to the drawing operation + /// The blending percentage to apply to the drawing operation + public GraphicsOptions( + bool enableAntialiasing, + PixelColorBlendingMode blending, + float blendPercentage) + : this(enableAntialiasing, blending, PixelAlphaCompositionMode.SrcOver, blendPercentage) { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.ColorBlendingMode = blending; - this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the class. /// /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - /// color blending mode to apply to the drawing operation - /// alpha composition mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) + /// The color blending mode to apply to the drawing operation + /// The alpha composition mode to apply to the drawing operation + /// The blending percentage to apply to the drawing operation + public GraphicsOptions( + bool enableAntialiasing, + PixelColorBlendingMode blending, + PixelAlphaCompositionMode composition, + float blendPercentage) { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - this.ColorBlendingMode = blending; this.AlphaCompositionMode = composition; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.BlendPercentage = blendPercentage; + this.AntialiasSubpixelDepth = 16; + this.Antialias = enableAntialiasing; } + /// + /// Gets the default instance. + /// + public static GraphicsOptions Default { get; } = Lazy.Value; + /// /// Gets or sets a value indicating whether antialiasing should be applied. /// - public bool Antialias - { - get => this.antialias ?? true; - set => this.antialias = value; - } + public bool Antialias { get; set; } /// /// 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; + get + { + return this.antialiasSubpixelDepth; + } + + set + { + Guard.MustBeGreaterThanOrEqualTo(value, 0, nameof(this.AntialiasSubpixelDepth)); + this.antialiasSubpixelDepth = value; + } } /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation. /// public float BlendPercentage { - get => (this.blendPercentage ?? 1).Clamp(0, 1); - set => this.blendPercentage = value; + get + { + return this.blendPercentage; + } + + set + { + Guard.MustBeBetweenOrEqualTo(value, 0, 1F, nameof(this.BlendPercentage)); + this.blendPercentage = value; + } } // In the future we could expose a PixelBlender directly on here diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs index 3691b54ce..5d309d299 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { public class DrawPathCollection : BaseImageOperationsExtensionTest { - GraphicsOptions noneDefault = new GraphicsOptions(); + GraphicsOptions noneDefault = new GraphicsOptions(false); Color color = Color.HotPink; Pen pen = Pens.Solid(Rgba32.HotPink, 1); IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs index 160ff22a3..cb247ac03 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { public class FillPath : BaseImageOperationsExtensionTest { - GraphicsOptions noneDefault = new GraphicsOptions(); + GraphicsOptions noneDefault = new GraphicsOptions(false); Color color = Color.HotPink; SolidBrush brush = Brushes.Solid(Rgba32.HotPink); IPath path = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs index b76ee8ffc..0c4d6ca3c 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { public class FillPathCollection : BaseImageOperationsExtensionTest { - GraphicsOptions noneDefault = new GraphicsOptions(); + GraphicsOptions noneDefault = new GraphicsOptions(false); Color color = Color.HotPink; SolidBrush brush = Brushes.Solid(Rgba32.HotPink); IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs index c62a87148..06a734842 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { public class FillPolygon : BaseImageOperationsExtensionTest { - GraphicsOptions noneDefault = new GraphicsOptions(); + GraphicsOptions noneDefault = new GraphicsOptions(false); Color color = Color.HotPink; SolidBrush brush = Brushes.Solid(Rgba32.HotPink); SixLabors.Primitives.PointF[] path = { diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs index 17a2b87c0..c1ad059a8 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { public class FillRectangle : BaseImageOperationsExtensionTest { - GraphicsOptions noneDefault = new GraphicsOptions(); + GraphicsOptions noneDefault = new GraphicsOptions(false); Color color = Color.HotPink; SolidBrush brush = Brushes.Solid(Rgba32.HotPink); SixLabors.Primitives.Rectangle rectangle = new SixLabors.Primitives.Rectangle(10, 10, 77, 76); diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs index 09a78a6aa..693dd6bd8 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders @@ -36,9 +36,10 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders using (Image src = srcFile.CreateRgba32Image()) using (Image dest = provider.GetImage()) { - GraphicsOptions options = new GraphicsOptions - { - AlphaCompositionMode = mode + var options = new GraphicsOptions + { + Antialias = false, + AlphaCompositionMode = mode }; using (Image res = dest.Clone(x => x.DrawImage(src, options))) @@ -53,4 +54,4 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders } } } -} \ No newline at end of file +}