From 5d374db9ef46ac98a812d24a64be621b245de1df Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 25 Feb 2019 21:25:09 +0100 Subject: [PATCH] Moved comparison, blending and conversion from color to a behavior-class to make it exchangeable --- .../Color/Behaviors/DefaultColorBehavior.cs | 80 +++++++++++++++++++ .../Color/Behaviors/IColorBehavior.cs | 13 +++ RGB.NET.Core/Color/Color.cs | 61 +++++--------- RGB.NET.Core/RGB.NET.Core.csproj.DotSettings | 1 + 4 files changed, 113 insertions(+), 42 deletions(-) create mode 100644 RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs create mode 100644 RGB.NET.Core/Color/Behaviors/IColorBehavior.cs diff --git a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs new file mode 100644 index 0000000..e666f6f --- /dev/null +++ b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs @@ -0,0 +1,80 @@ +namespace RGB.NET.Core +{ + public class DefaultColorBehavior : IColorBehavior + { + #region Properties & Fields + + private static DefaultColorBehavior _instance = new DefaultColorBehavior(); + /// + /// Gets the singleton instance of . + /// + public static DefaultColorBehavior Instance { get; } = _instance; + + #endregion + + #region Constructors + + private DefaultColorBehavior() + { } + + #endregion + + #region Methods + + /// + /// Converts the individual byte values of this to a human-readable string. + /// + /// A string that contains the individual byte values of this . For example "[A: 255, R: 255, G: 0, B: 0]". + public virtual string ToString(Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]"; + + /// + /// Tests whether the specified object is a and is equivalent to this . + /// + /// The object to test. + /// true if is a equivalent to this ; otherwise, false. + public virtual bool Equals(Color color, object obj) + { + if (!(obj is Color)) return false; + + (double a, double r, double g, double b) = ((Color)obj).GetRGB(); + return color.A.EqualsInTolerance(a) && color.R.EqualsInTolerance(r) && color.G.EqualsInTolerance(g) && color.B.EqualsInTolerance(b); + } + + /// + /// Returns a hash code for this . + /// + /// An integer value that specifies the hash code for this . + public virtual int GetHashCode(Color color) + { + unchecked + { + int hashCode = color.A.GetHashCode(); + hashCode = (hashCode * 397) ^ color.R.GetHashCode(); + hashCode = (hashCode * 397) ^ color.G.GetHashCode(); + hashCode = (hashCode * 397) ^ color.B.GetHashCode(); + return hashCode; + } + } + + /// + /// Blends a over this color. + /// + /// The to blend. + public virtual Color Blend(Color baseColor, Color blendColor) + { + if (blendColor.A.EqualsInTolerance(0)) return baseColor; + + if (blendColor.A.EqualsInTolerance(1)) + return blendColor; + + double resultA = (1.0 - ((1.0 - blendColor.A) * (1.0 - baseColor.A))); + double resultR = (((blendColor.R * blendColor.A) / resultA) + ((baseColor.R * baseColor.A * (1.0 - blendColor.A)) / resultA)); + double resultG = (((blendColor.G * blendColor.A) / resultA) + ((baseColor.G * baseColor.A * (1.0 - blendColor.A)) / resultA)); + double resultB = (((blendColor.B * blendColor.A) / resultA) + ((baseColor.B * baseColor.A * (1.0 - blendColor.A)) / resultA)); + + return new Color(resultA, resultR, resultG, resultB); + } + + #endregion + } +} diff --git a/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs new file mode 100644 index 0000000..630aca5 --- /dev/null +++ b/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs @@ -0,0 +1,13 @@ +namespace RGB.NET.Core +{ + public interface IColorBehavior + { + string ToString(Color color); + + bool Equals(Color color, object obj); + + int GetHashCode(Color color); + + Color Blend(Color baseColor, Color blendColor); + } +} diff --git a/RGB.NET.Core/Color/Color.cs b/RGB.NET.Core/Color/Color.cs index 0d5a028..81a3a33 100644 --- a/RGB.NET.Core/Color/Color.cs +++ b/RGB.NET.Core/Color/Color.cs @@ -25,6 +25,16 @@ namespace RGB.NET.Core #region Properties & Fields + private static IColorBehavior _behavior = DefaultColorBehavior.Instance; + /// + /// Gets or sets the used to perform operations on colors. + /// + public static IColorBehavior Behavior + { + get => _behavior; + set => _behavior = value ?? DefaultColorBehavior.Instance; + } + /// /// Gets the alpha component value of this as percentage in the range [0..1]. /// @@ -179,62 +189,29 @@ namespace RGB.NET.Core #region Methods /// - /// Converts the individual byte values of this to a human-readable string. + /// Gets a human-readable string, as defined by the current . /// - /// A string that contains the individual byte values of this . For example "[A: 255, R: 255, G: 0, B: 0]". - public override string ToString() => $"[A: {this.GetA()}, R: {this.GetR()}, G: {this.GetG()}, B: {this.GetB()}]"; + /// A string that contains the individual byte values of this . Default format: "[A: 255, R: 255, G: 0, B: 0]". + public override string ToString() => Behavior.ToString(this); /// - /// Tests whether the specified object is a and is equivalent to this . + /// Tests whether the specified object is a and is equivalent to this , as defined by the current . /// /// The object to test. /// true if is a equivalent to this ; otherwise, false. - public override bool Equals(object obj) - { - if (!(obj is Color)) return false; - - (double a, double r, double g, double b) = ((Color)obj).GetRGB(); - return A.EqualsInTolerance(a) && R.EqualsInTolerance(r) && G.EqualsInTolerance(g) && B.EqualsInTolerance(b); - } + public override bool Equals(object obj) => Behavior.Equals(this, obj); /// - /// Returns a hash code for this . + /// Returns a hash code for this , as defined by the current . /// /// An integer value that specifies the hash code for this . - public override int GetHashCode() - { - unchecked - { - int hashCode = A.GetHashCode(); - hashCode = (hashCode * 397) ^ R.GetHashCode(); - hashCode = (hashCode * 397) ^ G.GetHashCode(); - hashCode = (hashCode * 397) ^ B.GetHashCode(); - return hashCode; - } - } - - #region Manipulation + public override int GetHashCode() => Behavior.GetHashCode(this); /// - /// Blends a over this color. + /// Blends a over this color, as defined by the current . /// /// The to blend. - public Color Blend(Color color) - { - if (color.A.EqualsInTolerance(0)) return this; - - if (color.A.EqualsInTolerance(1)) - return color; - - double resultA = (1.0 - ((1.0 - color.A) * (1.0 - A))); - double resultR = (((color.R * color.A) / resultA) + ((R * A * (1.0 - color.A)) / resultA)); - double resultG = (((color.G * color.A) / resultA) + ((G * A * (1.0 - color.A)) / resultA)); - double resultB = (((color.B * color.A) / resultA) + ((B * A * (1.0 - color.A)) / resultA)); - - return new Color(resultA, resultR, resultG, resultB); - } - - #endregion + public Color Blend(Color color) => Behavior.Blend(this, color); #endregion diff --git a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings index 739bd7f..d216495 100644 --- a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings +++ b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings @@ -2,6 +2,7 @@ True True True + True True True True