using System.Drawing; using System.Numerics; using System.Runtime.CompilerServices; namespace Peridot; /// /// Provides static methods to manipulation. /// public partial struct ColorF { #region Cast operators /// /// Cast a to . /// /// The color to cast. public static implicit operator Vector4(ColorF color) => color.m_rgba; /// /// Cast a to . /// /// public static implicit operator ColorF(Vector4 color) => new(color); /// /// Cast a to . /// /// public static implicit operator Color(ColorF color) { color = Vector4.Clamp(color, Vector4.Zero, Vector4.One) * 255f; return Color.FromArgb((byte)color.A, (byte)color.R, (byte)color.G, (byte)color.B); } /// /// Cast a to . /// /// public static implicit operator ColorF(Color color) { return (ColorF)Vector4.Clamp(new Vector4(color.R, color.G, color.B, color.A) * (1f / 255f), Vector4.Zero, Vector4.One); } #endregion #region Math public static ColorF Blend(ColorF dst, ColorF src) { var dstA = dst.A; var srcA = src.A; var res = dst * (1 - srcA) + src * srcA; res.A = dstA * (1 - srcA) + srcA; return res; } /// /// Negates the specified color. /// /// The color to negate. /// The negated vector. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Negate(ColorF color) => -color.m_rgba; /// /// Adds two colors together. /// /// The first color. /// The second color. /// The summed color. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Add(ColorF left, ColorF right) => left.m_rgba + right.m_rgba; /// /// Subtracts the second color from the first. /// /// The first color. /// The second color. /// The color that results from subracting from . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Subtract(ColorF left, ColorF right) => left.m_rgba - right.m_rgba; /// /// Multiplies two colors together. /// /// The first color. /// The second color. /// The product color. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Multiply(ColorF left, ColorF right) => left.m_rgba * right.m_rgba; /// /// Divides the first color by the second. /// /// The first color. /// The second color. /// The color that results from dividing by . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Divide(ColorF left, ColorF right) => left.m_rgba / right.m_rgba; /// /// Multiples the specified color by the specified scalar value. /// /// The color. /// The scalar value. /// The scaled color. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Multiply(ColorF left, float right) => left.m_rgba * right; /// /// Divides the specified color by a specified scalar value. /// /// The color. /// The scalar value. /// The result of the division. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Divide(ColorF left, float right) => left.m_rgba / right; /// /// Multiples the specified color by the specified scalar value. /// /// The scalar value. /// The color. /// The scaled color. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Multiply(float left, ColorF right) => left * right.m_rgba; /// /// Linearly interpolates between two colors. /// /// The first color. /// The second color. /// Influence of the second color on the final result. /// * (1f - ) + * . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorF Lerp(in ColorF a, in ColorF b, float t) => a + (b - a) * t; #endregion #region Operators /// /// Element-wise equality. /// /// The first value. /// The second value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(ColorF left, ColorF right) => left.Equals(right); /// /// Element-wise inequality. /// /// The first value. /// The second value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(ColorF left, ColorF right) => !left.Equals(right); /// /// Negates the specified color. /// /// The color to negate. /// The negated vector. public static ColorF operator -(ColorF color) => Negate(color); /// /// Adds two colors together. /// /// The first color. /// The second color. /// The summed color. public static ColorF operator +(ColorF left, ColorF right) => Add(left, right); /// /// Subtracts the second color from the first. /// /// The first color. /// The second color. /// The color that results from subracting from . public static ColorF operator -(ColorF left, ColorF right) => Subtract(left, right); /// /// Multiplies two colors together. /// /// The first color. /// The second color. /// The product color. public static ColorF operator *(ColorF left, ColorF right) => Multiply(left, right); /// /// Divides the first color by the second. /// /// The first color. /// The second color. /// The color that results from dividing by . public static ColorF operator /(ColorF left, ColorF right) => Divide(left, right); /// /// Multiples the specified color by the specified scalar value. /// /// The color. /// The scalar value. /// The scaled color. public static ColorF operator *(ColorF left, float right) => Multiply(left, right); /// /// Divides the specified color by a specified scalar value. /// /// The color. /// The scalar value. /// The result of the division. public static ColorF operator /(ColorF left, float right) => Divide(left, right); /// /// Multiples the specified color by the specified scalar value. /// /// The scalar value. /// The color. /// The scaled color. public static ColorF operator *(float left, ColorF right) => Multiply(left, right); #endregion #region Colors /// /// Red (1, 0, 0, 1) /// public static readonly ColorF Red = new(1f, 0f, 0f, 1f); /// /// Dark Red (139f / 255f, 0f, 0f, 1f) /// public static readonly ColorF DarkRed = new(139f / 255f, 0f, 0f, 1f); /// /// Green (0f, 1f, 0f, 1f) /// public static readonly ColorF Green = new(0f, 1f, 0f, 1f); /// /// Blue (0f, 0f, 1f, 1f) /// public static readonly ColorF Blue = new(0f, 0f, 1f, 1f); /// /// Yellow (1f, 1f, 0f, 1f) /// public static readonly ColorF Yellow = new(1f, 1f, 0f, 1f); /// /// Grey (128f / 255f, 128f / 255f, 128 / 255f, 1f) /// public static readonly ColorF Grey = new(128f / 255f, 128f / 255f, 128f / 255f, 1f); /// /// Light Grey (211f / 255f, 211f / 255f, 211f / 255f, 1f) /// public static readonly ColorF LightGrey = new(211f / 255f, 211f / 255f, 211f / 255f, 1f); /// /// Cyan (0f, 1f, 1f, 1f) /// public static readonly ColorF Cyan = new(0f, 1f, 1f, 1f); /// /// White (1f, 1f, 1f, 1f) /// public static readonly ColorF White = new(1f, 1f, 1f, 1f); /// /// Cornflower Blue (100f / 255f, 149f / 255f, 237f / 255f, 1f) /// public static readonly ColorF CornflowerBlue = new(100f / 255f, 149f / 255f, 237f / 255f, 1f); /// /// Clear (0f, 0f, 0f, 0f) /// public static readonly ColorF Clear = new(0f, 0f, 0f, 0f); /// /// Black (0f, 0f, 0f, 1f) /// public static readonly ColorF Black = new(0f, 0f, 0f, 1f); /// /// Pink (1f, 192f / 255f, 203f / 255f, 1f) /// public static readonly ColorF Pink = new(1f, 192f / 255f, 203f / 255f, 1f); /// /// Orange (1f, 165f / 255f, 0f, 1f) /// public static readonly ColorF Orange = new(1f, 165f / 255f, 0f, 1f); #endregion }