//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using JetBrains.Annotations;
using SysVector3 = System.Numerics.Vector3;
using SysVector4 = System.Numerics.Vector4;
#if NETCOREAPP
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
namespace Robust.Shared.Maths
{
///
/// Represents a color with 4 floating-point components (R, G, B, A).
///
[Serializable]
public struct Color : IEquatable
{
///
/// The red component of this Color4 structure.
///
public float R;
///
/// The green component of this Color4 structure.
///
public float G;
///
/// The blue component of this Color4 structure.
///
public float B;
///
/// The alpha component of this Color4 structure.
///
public float A;
public readonly byte RByte => (byte) (R * byte.MaxValue);
public readonly byte GByte => (byte) (G * byte.MaxValue);
public readonly byte BByte => (byte) (B * byte.MaxValue);
public readonly byte AByte => (byte) (A * byte.MaxValue);
///
/// Constructs a new Color4 structure from the specified components.
///
/// The red component of the new Color4 structure.
/// The green component of the new Color4 structure.
/// The blue component of the new Color4 structure.
/// The alpha component of the new Color4 structure.
public Color(float r, float g, float b, float a = 1)
{
R = r;
G = g;
B = b;
A = a;
}
///
/// Constructs a new Color4 structure from the specified components.
///
/// The red component of the new Color4 structure.
/// The green component of the new Color4 structure.
/// The blue component of the new Color4 structure.
/// The alpha component of the new Color4 structure.
public Color(byte r, byte g, byte b, byte a = 255)
{
R = r / (float) byte.MaxValue;
G = g / (float) byte.MaxValue;
B = b / (float) byte.MaxValue;
A = a / (float) byte.MaxValue;
}
///
/// Converts this color to an integer representation with 8 bits per channel.
///
/// A that represents this instance.
///
/// This method is intended only for compatibility with System.Drawing. It compresses the color into 8 bits per
/// channel, which means color information is lost.
///
public readonly int ToArgb()
{
var value =
((uint) (A * byte.MaxValue) << 24) |
((uint) (R * byte.MaxValue) << 16) |
((uint) (G * byte.MaxValue) << 8) |
(uint) (B * byte.MaxValue);
return unchecked((int) value);
}
///
/// Compares the specified Color4 structures for equality.
///
/// The left-hand side of the comparison.
/// The right-hand side of the comparison.
/// True if left is equal to right; false otherwise.
public static bool operator ==(Color left, Color right)
{
return left.Equals(right);
}
///
/// Compares the specified Color4 structures for inequality.
///
/// The left-hand side of the comparison.
/// The right-hand side of the comparison.
/// True if left is not equal to right; false otherwise.
public static bool operator !=(Color left, Color right)
{
return !left.Equals(right);
}
///
/// Converts the specified System.Drawing.Color to a Color4 structure.
///
/// The System.Drawing.Color to convert.
/// A new Color4 structure containing the converted components.
public static implicit operator Color(System.Drawing.Color color)
{
return new(color.R, color.G, color.B, color.A);
}
public static implicit operator Color((float r, float g, float b, float a) tuple)
{
return new(tuple.r, tuple.g, tuple.b, tuple.a);
}
public static implicit operator Color((float r, float g, float b) tuple)
{
return new(tuple.r, tuple.g, tuple.b);
}
public readonly void Deconstruct(out float r, out float g, out float b, out float a)
{
r = R;
g = G;
b = B;
a = A;
}
public readonly void Deconstruct(out float r, out float g, out float b)
{
r = R;
g = G;
b = B;
}
///
/// Converts the specified Color4 to a System.Drawing.Color structure.
///
/// The Color4 to convert.
/// A new System.Drawing.Color structure containing the converted components.
public static explicit operator System.Drawing.Color(Color color)
{
return System.Drawing.Color.FromArgb(
(int) (color.A * byte.MaxValue),
(int) (color.R * byte.MaxValue),
(int) (color.G * byte.MaxValue),
(int) (color.B * byte.MaxValue));
}
public static Color FromName(string colorname)
{
return DefaultColors[colorname.ToLower()];
}
public static bool TryFromName(string colorName, out Color color)
{
return DefaultColors.TryGetValue(colorName.ToLower(), out color);
}
public static IEnumerable> GetAllDefaultColors()
{
return DefaultColors;
}
///
/// Compares whether this Color4 structure is equal to the specified object.
///
/// An object to compare to.
/// True obj is a Color4 structure with the same components as this Color4; false otherwise.
public override readonly bool Equals(object? obj)
{
if (!(obj is Color))
return false;
return Equals((Color) obj);
}
///
/// Calculates the hash code for this Color4 structure.
///
/// A System.Int32 containing the hash code of this Color4 structure.
public override readonly int GetHashCode()
{
return ToArgb();
}
///
/// Creates a System.String that describes this Color4 structure.
///
/// A System.String that describes this Color4 structure.
public override readonly string ToString()
{
return $"{{(R, G, B, A) = ({R}, {G}, {B}, {A})}}";
}
public readonly Color WithRed(float newR)
{
return new(newR, G, B, A);
}
public readonly Color WithGreen(float newG)
{
return new(R, newG, B, A);
}
public readonly Color WithBlue(float newB)
{
return new(R, G, newB, A);
}
public readonly Color WithAlpha(float newA)
{
return new(R, G, B, newA);
}
public readonly Color WithRed(byte newR)
{
return new((float) newR / byte.MaxValue, G, B, A);
}
public readonly Color WithGreen(byte newG)
{
return new(R, (float) newG / byte.MaxValue, B, A);
}
public readonly Color WithBlue(byte newB)
{
return new(R, G, (float) newB / byte.MaxValue, A);
}
public readonly Color WithAlpha(byte newA)
{
return new(R, G, B, (float) newA / byte.MaxValue);
}
///
/// Converts sRGB color values to linear RGB color values.
///
///
/// Returns the converted color value.
///
///
/// Color value to convert in sRGB.
///
public static Color FromSrgb(Color srgb)
{
float r, g, b;
#if NETCOREAPP
if (srgb.R <= 0.04045f)
r = srgb.R / 12.92f;
else
r = MathF.Pow((srgb.R + 0.055f) / (1.0f + 0.055f), 2.4f);
if (srgb.G <= 0.04045f)
g = srgb.G / 12.92f;
else
g = MathF.Pow((srgb.G + 0.055f) / (1.0f + 0.055f), 2.4f);
if (srgb.B <= 0.04045f)
b = srgb.B / 12.92f;
else
b = MathF.Pow((srgb.B + 0.055f) / (1.0f + 0.055f), 2.4f);
#else
if (srgb.R <= 0.04045f)
r = srgb.R / 12.92f;
else
r = (float) Math.Pow((srgb.R + 0.055f) / (1.0f + 0.055f), 2.4f);
if (srgb.G <= 0.04045f)
g = srgb.G / 12.92f;
else
g = (float) Math.Pow((srgb.G + 0.055f) / (1.0f + 0.055f), 2.4f);
if (srgb.B <= 0.04045f)
b = srgb.B / 12.92f;
else
b = (float) Math.Pow((srgb.B + 0.055f) / (1.0f + 0.055f), 2.4f);
#endif
return new Color(r, g, b, srgb.A);
}
///
/// Converts linear RGB color values to sRGB color values.
///
///
/// Returns the converted color value.
///
/// Color value to convert.
public static Color ToSrgb(Color rgb)
{
float r, g, b;
#if NETCOREAPP
if (rgb.R <= 0.0031308)
r = 12.92f * rgb.R;
else
r = (1.0f + 0.055f) * MathF.Pow(rgb.R, 1.0f / 2.4f) - 0.055f;
if (rgb.G <= 0.0031308)
g = 12.92f * rgb.G;
else
g = (1.0f + 0.055f) * MathF.Pow(rgb.G, 1.0f / 2.4f) - 0.055f;
if (rgb.B <= 0.0031308)
b = 12.92f * rgb.B;
else
b = (1.0f + 0.055f) * MathF.Pow(rgb.B, 1.0f / 2.4f) - 0.055f;
#else
if (rgb.R <= 0.0031308)
r = 12.92f * rgb.R;
else
r = (1.0f + 0.055f) * (float) Math.Pow(rgb.R, 1.0f / 2.4f) - 0.055f;
if (rgb.G <= 0.0031308)
g = 12.92f * rgb.G;
else
g = (1.0f + 0.055f) * (float) Math.Pow(rgb.G, 1.0f / 2.4f) - 0.055f;
if (rgb.B <= 0.0031308)
b = 12.92f * rgb.B;
else
b = (1.0f + 0.055f) * (float) Math.Pow(rgb.B, 1.0f / 2.4f) - 0.055f;
#endif
return new Color(r, g, b, rgb.A);
}
///
/// Converts HSL color values to RGB color values.
///
///
/// Returns the converted color value.
///
///
/// Color value to convert in hue, saturation, lightness (HSL).
/// The X element is Hue (H), the Y element is Saturation (S), the Z element is Lightness (L), and the W element is
/// Alpha (which is copied to the output's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
public static Color FromHsl(Vector4 hsl)
{
var hue = hsl.X * 360.0f;
var saturation = hsl.Y;
var lightness = hsl.Z;
var c = (1.0f - MathF.Abs(2.0f * lightness - 1.0f)) * saturation;
var h = hue / 60.0f;
var X = c * (1.0f - MathF.Abs(h % 2.0f - 1.0f));
float r, g, b;
if (0.0f <= h && h < 1.0f)
{
r = c;
g = X;
b = 0.0f;
}
else if (1.0f <= h && h < 2.0f)
{
r = X;
g = c;
b = 0.0f;
}
else if (2.0f <= h && h < 3.0f)
{
r = 0.0f;
g = c;
b = X;
}
else if (3.0f <= h && h < 4.0f)
{
r = 0.0f;
g = X;
b = c;
}
else if (4.0f <= h && h < 5.0f)
{
r = X;
g = 0.0f;
b = c;
}
else if (5.0f <= h && h < 6.0f)
{
r = c;
g = 0.0f;
b = X;
}
else
{
r = 0.0f;
g = 0.0f;
b = 0.0f;
}
var m = lightness - c / 2.0f;
return new Color(r + m, g + m, b + m, hsl.W);
}
///
/// Converts RGB color values to HSL color values.
///
///
/// Returns the converted color value.
/// The X element is Hue (H), the Y element is Saturation (S), the Z element is Lightness (L), and the W element is
/// Alpha (a copy of the input's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
/// Color value to convert.
public static Vector4 ToHsl(Color rgb)
{
var max = MathF.Max(rgb.R, MathF.Max(rgb.G, rgb.B));
var min = MathF.Min(rgb.R, MathF.Min(rgb.G, rgb.B));
var c = max - min;
var h = 0.0f;
if (max == rgb.R)
h = (rgb.G - rgb.B) / c;
else if (max == rgb.G)
h = (rgb.B - rgb.R) / c + 2.0f;
else if (max == rgb.B)
h = (rgb.R - rgb.G) / c + 4.0f;
var hue = h / 6.0f;
if (hue < 0.0f)
hue += 1.0f;
var lightness = (max + min) / 2.0f;
var saturation = 0.0f;
if (0.0f != lightness && lightness != 1.0f)
saturation = c / (1.0f - MathF.Abs(2.0f * lightness - 1.0f));
return new Vector4(hue, saturation, lightness, rgb.A);
}
///
/// Converts HSV color values to RGB color values.
///
///
/// Returns the converted color value.
///
///
/// Color value to convert in hue, saturation, value (HSV).
/// The X element is Hue (H), the Y element is Saturation (S), the Z element is Value (V), and the W element is Alpha
/// (which is copied to the output's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
public static Color FromHsv(Vector4 hsv)
{
var hue = hsv.X * 360.0f;
var saturation = hsv.Y;
var value = hsv.Z;
var c = value * saturation;
var h = hue / 60.0f;
var x = c * (1.0f - MathF.Abs(h % 2.0f - 1.0f));
float r, g, b;
if (0.0f <= h && h < 1.0f)
{
r = c;
g = x;
b = 0.0f;
}
else if (1.0f <= h && h < 2.0f)
{
r = x;
g = c;
b = 0.0f;
}
else if (2.0f <= h && h < 3.0f)
{
r = 0.0f;
g = c;
b = x;
}
else if (3.0f <= h && h < 4.0f)
{
r = 0.0f;
g = x;
b = c;
}
else if (4.0f <= h && h < 5.0f)
{
r = x;
g = 0.0f;
b = c;
}
else if (5.0f <= h && h < 6.0f)
{
r = c;
g = 0.0f;
b = x;
}
else
{
r = 0.0f;
g = 0.0f;
b = 0.0f;
}
var m = value - c;
return new Color(r + m, g + m, b + m, hsv.W);
}
///
/// Converts RGB color values to HSV color values.
///
///
/// Returns the converted color value.
/// The X element is Hue (H), the Y element is Saturation (S), the Z element is Value (V), and the W element is Alpha
/// (a copy of the input's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
/// Color value to convert.
public static Vector4 ToHsv(Color rgb)
{
var max = MathF.Max(rgb.R, MathF.Max(rgb.G, rgb.B));
var min = MathF.Min(rgb.R, MathF.Min(rgb.G, rgb.B));
var c = max - min;
var h = 0.0f;
if (max == rgb.R)
h = (rgb.G - rgb.B) / c % 6.0f;
else if (max == rgb.G)
h = (rgb.B - rgb.R) / c + 2.0f;
else if (max == rgb.B)
h = (rgb.R - rgb.G) / c + 4.0f;
var hue = h * 60.0f / 360.0f;
var saturation = 0.0f;
if (0.0f != max)
saturation = c / max;
return new Vector4(hue, saturation, max, rgb.A);
}
///
/// Converts XYZ color values to RGB color values.
///
///
/// Returns the converted color value.
///
///
/// Color value to convert with the trisimulus values of X, Y, and Z in the corresponding element, and the W element
/// with Alpha (which is copied to the output's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
/// Uses the CIE XYZ colorspace.
public static Color FromXyz(Vector4 xyz)
{
var r = 0.41847f * xyz.X + -0.15866f * xyz.Y + -0.082835f * xyz.Z;
var g = -0.091169f * xyz.X + 0.25243f * xyz.Y + 0.015708f * xyz.Z;
var b = 0.00092090f * xyz.X + -0.0025498f * xyz.Y + 0.17860f * xyz.Z;
return new Color(r, g, b, xyz.W);
}
///
/// Converts RGB color values to XYZ color values.
///
///
/// Returns the converted color value with the trisimulus values of X, Y, and Z in the corresponding element, and the W
/// element with Alpha (a copy of the input's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
/// Color value to convert.
/// Uses the CIE XYZ colorspace.
public static Vector4 ToXyz(Color rgb)
{
var x = (0.49f * rgb.R + 0.31f * rgb.G + 0.20f * rgb.B) / 0.17697f;
var y = (0.17697f * rgb.R + 0.81240f * rgb.G + 0.01063f * rgb.B) / 0.17697f;
var z = (0.00f * rgb.R + 0.01f * rgb.G + 0.99f * rgb.B) / 0.17697f;
return new Vector4(x, y, z, rgb.A);
}
///
/// Converts YCbCr color values to RGB color values.
///
///
/// Returns the converted color value.
///
///
/// Color value to convert in Luma-Chrominance (YCbCr) aka YUV.
/// The X element contains Luma (Y, 0.0 to 1.0), the Y element contains Blue-difference chroma (U, -0.5 to 0.5), the Z
/// element contains the Red-difference chroma (V, -0.5 to 0.5), and the W element contains the Alpha (which is copied
/// to the output's Alpha value).
///
/// Converts using ITU-R BT.601/CCIR 601 W(r) = 0.299 W(b) = 0.114 U(max) = 0.436 V(max) = 0.615.
public static Color FromYcbcr(Vector4 ycbcr)
{
var r = 1.0f * ycbcr.X + 0.0f * ycbcr.Y + 1.402f * ycbcr.Z;
var g = 1.0f * ycbcr.X + -0.344136f * ycbcr.Y + -0.714136f * ycbcr.Z;
var b = 1.0f * ycbcr.X + 1.772f * ycbcr.Y + 0.0f * ycbcr.Z;
return new Color(r, g, b, ycbcr.W);
}
///
/// Converts RGB color values to YUV color values.
///
///
/// Returns the converted color value in Luma-Chrominance (YCbCr) aka YUV.
/// The X element contains Luma (Y, 0.0 to 1.0), the Y element contains Blue-difference chroma (U, -0.5 to 0.5), the Z
/// element contains the Red-difference chroma (V, -0.5 to 0.5), and the W element contains the Alpha (a copy of the
/// input's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
/// Color value to convert.
/// Converts using ITU-R BT.601/CCIR 601 W(r) = 0.299 W(b) = 0.114 U(max) = 0.436 V(max) = 0.615.
public static Vector4 ToYcbcr(Color rgb)
{
var y = 0.299f * rgb.R + 0.587f * rgb.G + 0.114f * rgb.B;
var u = -0.168736f * rgb.R + -0.331264f * rgb.G + 0.5f * rgb.B;
var v = 0.5f * rgb.R + -0.418688f * rgb.G + -0.081312f * rgb.B;
return new Vector4(y, u, v, rgb.A);
}
///
/// Converts HCY color values to RGB color values.
///
///
/// Returns the converted color value.
///
///
/// Color value to convert in hue, chroma, luminance (HCY).
/// The X element is Hue (H), the Y element is Chroma (C), the Z element is luminance (Y), and the W element is Alpha
/// (which is copied to the output's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
public static Color FromHcy(Vector4 hcy)
{
var hue = hcy.X * 360.0f;
var c = hcy.Y;
var luminance = hcy.Z;
var h = hue / 60.0f;
var x = c * (1.0f - MathF.Abs(h % 2.0f - 1.0f));
float r, g, b;
if (0.0f <= h && h < 1.0f)
{
r = c;
g = x;
b = 0.0f;
}
else if (1.0f <= h && h < 2.0f)
{
r = x;
g = c;
b = 0.0f;
}
else if (2.0f <= h && h < 3.0f)
{
r = 0.0f;
g = c;
b = x;
}
else if (3.0f <= h && h < 4.0f)
{
r = 0.0f;
g = x;
b = c;
}
else if (4.0f <= h && h < 5.0f)
{
r = x;
g = 0.0f;
b = c;
}
else if (5.0f <= h && h < 6.0f)
{
r = c;
g = 0.0f;
b = x;
}
else
{
r = 0.0f;
g = 0.0f;
b = 0.0f;
}
var m = luminance - (0.30f * r + 0.59f * g + 0.11f * b);
return new Color(r + m, g + m, b + m, hcy.W);
}
///
/// Converts RGB color values to HCY color values.
///
///
/// Returns the converted color value.
/// The X element is Hue (H), the Y element is Chroma (C), the Z element is luminance (Y), and the W element is Alpha
/// (a copy of the input's Alpha value).
/// Each has a range of 0.0 to 1.0.
///
/// Color value to convert.
public static Vector4 ToHcy(Color rgb)
{
var max = MathF.Max(rgb.R, MathF.Max(rgb.G, rgb.B));
var min = MathF.Min(rgb.R, MathF.Min(rgb.G, rgb.B));
var c = max - min;
var h = 0.0f;
if (max == rgb.R)
h = (rgb.G - rgb.B) / c % 6.0f;
else if (max == rgb.G)
h = (rgb.B - rgb.R) / c + 2.0f;
else if (max == rgb.B)
h = (rgb.R - rgb.G) / c + 4.0f;
var hue = h * 60.0f / 360.0f;
var luminance = 0.30f * rgb.R + 0.59f * rgb.G + 0.11f * rgb.B;
return new Vector4(hue, c, luminance, rgb.A);
}
public static Vector4 ToCmyk(Color rgb)
{
var (r, g, b) = rgb;
var k = 1 - MathF.Max(r, MathF.Max(g, b));
var c = (1 - r - k) / (1 - k);
var m = (1 - g - k) / (1 - k);
var y = (1 - b - k) / (1 - k);
return (c, m, y, k);
}
public static Color FromCmyk(Vector4 cmyk)
{
var (c, m, y, k) = cmyk;
var r = (1 - c) * (1 - k);
var g = (1 - m) * (1 - k);
var b = (1 - y) * (1 - k);
return (r, g, b);
}
///
/// Interpolate two colors with a lambda, AKA returning the two colors combined with a ratio of
/// .
///
///
///
///
/// A value ranging from 0-1. The higher the value the more is taken from ,
/// with 0.5 being 50% of both colors, 0.25 being 25% of and 75%
/// .
///
#if NETCOREAPP
public static Color InterpolateBetween(Color α, Color β, float λ)
{
if (Sse.IsSupported && Fma.IsSupported)
{
var vecA = Unsafe.As>(ref α);
var vecB = Unsafe.As>(ref β);
vecB = Fma.MultiplyAdd(Sse.Subtract(vecB, vecA), Vector128.Create(λ), vecA);
return Unsafe.As, Color>(ref vecB);
}
ref var svA = ref Unsafe.As(ref α);
ref var svB = ref Unsafe.As(ref β);
var res = SysVector4.Lerp(svA, svB, λ);
return Unsafe.As(ref res);
}
#else
public static Color InterpolateBetween(in Color α, in Color β, float λ)
{
return new Color(
(β.R - α.R) * λ + α.R,
(β.G - α.G) * λ + α.G,
(β.B - α.B) * λ + α.B,
(β.A - α.A) * λ + α.A
);
}
#endif
public static Color? TryFromHex(ReadOnlySpan hexColor)
{
if (hexColor.Length <= 0 || hexColor[0] != '#') return null;
if (hexColor.Length == 9)
{
if (!byte.TryParse(hexColor[1..3], NumberStyles.HexNumber, null, out var r)) return null;
if (!byte.TryParse(hexColor[3..5], NumberStyles.HexNumber, null, out var g)) return null;
if (!byte.TryParse(hexColor[5..7], NumberStyles.HexNumber, null, out var b)) return null;
if (!byte.TryParse(hexColor[7..9], NumberStyles.HexNumber, null, out var a)) return null;
return new Color(r, g, b, a);
}
if (hexColor.Length == 7)
{
if (!byte.TryParse(hexColor[1..3], NumberStyles.HexNumber, null, out var r)) return null;
if (!byte.TryParse(hexColor[3..5], NumberStyles.HexNumber, null, out var g)) return null;
if (!byte.TryParse(hexColor[5..7], NumberStyles.HexNumber, null, out var b)) return null;
return new Color(r, g, b);
}
static bool ParseDup(char chr, out byte value)
{
Span buf = stackalloc char[2];
buf[0] = chr;
buf[1] = chr;
return byte.TryParse(buf, NumberStyles.HexNumber, null, out value);
}
if (hexColor.Length == 5)
{
if (!ParseDup(hexColor[1], out var rByte)) return null;
if (!ParseDup(hexColor[2], out var gByte)) return null;
if (!ParseDup(hexColor[3], out var bByte)) return null;
if (!ParseDup(hexColor[4], out var aByte)) return null;
return new Color(rByte, gByte, bByte, aByte);
}
if (hexColor.Length == 4)
{
if (!ParseDup(hexColor[1], out var rByte)) return null;
if (!ParseDup(hexColor[2], out var gByte)) return null;
if (!ParseDup(hexColor[3], out var bByte)) return null;
return new Color(rByte, gByte, bByte);
}
return null;
}
public static Color FromHex(ReadOnlySpan hexColor, Color? fallback = null)
{
var color = TryFromHex(hexColor);
if (color.HasValue)
return color.Value;
if (fallback.HasValue)
return fallback.Value;
throw new ArgumentException($"Invalid color code \"{new string(hexColor)}\" and no fallback provided.", nameof(hexColor));
}
public static Color FromXaml(string name)
{
var color = TryFromHex(name);
if (color != null)
return color.Value;
if (TryFromName(name, out var namedColor))
return namedColor;
throw new ArgumentException($"Invalid XAML color name: '{name}'");
}
public static Color Blend(Color dstColor, Color srcColor, BlendFactor dstFactor, BlendFactor srcFactor)
{
var dst = new SysVector3(dstColor.R, dstColor.G, dstColor.B);
var src = new SysVector3(srcColor.R, srcColor.G, srcColor.B);
var ret = new SysVector3();
switch (dstFactor)
{
case BlendFactor.Zero:
break;
case BlendFactor.One:
ret = dst;
break;
case BlendFactor.SrcColor:
ret = dst * src;
break;
case BlendFactor.OneMinusSrcColor:
ret = dst * (SysVector3.One - src);
break;
case BlendFactor.DstColor:
ret = dst * dst;
break;
case BlendFactor.OneMinusDstColor:
ret = dst * (SysVector3.One - dst);
break;
case BlendFactor.SrcAlpha:
ret = dst * srcColor.A;
break;
case BlendFactor.OneMinusSrcAlpha:
ret = dst * (1 - srcColor.A);
break;
case BlendFactor.DstAlpha:
ret = dst * dstColor.A;
break;
case BlendFactor.OneMinusDstAlpha:
ret = dst * (1 - dstColor.A);
break;
default:
throw new NotImplementedException();
}
switch (srcFactor)
{
case BlendFactor.Zero:
break;
case BlendFactor.One:
ret += src;
break;
case BlendFactor.SrcColor:
ret += src * src;
break;
case BlendFactor.OneMinusSrcColor:
ret += src * (SysVector3.One - src);
break;
case BlendFactor.DstColor:
ret += src * dst;
break;
case BlendFactor.OneMinusDstColor:
ret += src * (SysVector3.One - dst);
break;
case BlendFactor.SrcAlpha:
ret += src * srcColor.A;
break;
case BlendFactor.OneMinusSrcAlpha:
ret += src * (1 - srcColor.A);
break;
case BlendFactor.DstAlpha:
ret += src * dstColor.A;
break;
case BlendFactor.OneMinusDstAlpha:
ret += src * (1 - dstColor.A);
break;
default:
throw new NotImplementedException();
}
return new Color(ret.X, ret.Y, ret.Z, MathF.Min(1, dstColor.A + dstColor.A * srcColor.A));
}
///
/// Component wise multiplication of two colors.
///
///
///
///
public static Color operator *(Color a, Color b)
{
return new(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);
}
public readonly string ToHex()
{
var hexColor = 0;
hexColor += RByte << 24;
hexColor += GByte << 16;
hexColor += BByte << 8;
hexColor += AByte;
return $"#{hexColor:X8}";
}
public readonly string ToHexNoAlpha()
{
var hexColor = 0;
hexColor += RByte << 16;
hexColor += GByte << 8;
hexColor += BByte;
return $"#{hexColor:X6}";
}
///
/// Compares whether this Color4 structure is equal to the specified Color4.
///
/// The Color4 structure to compare to.
/// True if both Color4 structures contain the same components; false otherwise.
public readonly bool Equals(Color other)
{
return
MathHelper.CloseToPercent(R, other.R) &&
MathHelper.CloseToPercent(G, other.G) &&
MathHelper.CloseToPercent(B, other.B) &&
MathHelper.CloseToPercent(A, other.A);
}
[PublicAPI]
public enum BlendFactor : byte
{
Zero,
One,
SrcColor,
OneMinusSrcColor,
DstColor,
OneMinusDstColor,
SrcAlpha,
OneMinusSrcAlpha,
DstAlpha,
OneMinusDstAlpha,
}
#region Static Colors
///
/// Gets the system color with (R, G, B, A) = (255, 255, 255, 0).
///
public static Color Transparent => new(255, 255, 255, 0);
///
/// Gets the system color with (R, G, B, A) = (240, 248, 255, 255).
///
public static Color AliceBlue => new(240, 248, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (250, 235, 215, 255).
///
public static Color AntiqueWhite => new(250, 235, 215, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 255, 255, 255).
///
public static Color Aqua => new(0, 255, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (127, 255, 212, 255).
///
public static Color Aquamarine => new(127, 255, 212, 255);
///
/// Gets the system color with (R, G, B, A) = (240, 255, 255, 255).
///
public static Color Azure => new(240, 255, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (245, 245, 220, 255).
///
public static Color Beige => new(245, 245, 220, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 228, 196, 255).
///
public static Color Bisque => new(255, 228, 196, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 0, 0, 255).
///
public static Color Black => new(0, 0, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 235, 205, 255).
///
public static Color BlanchedAlmond => new(255, 235, 205, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 0, 255, 255).
///
public static Color Blue => new(0, 0, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (138, 43, 226, 255).
///
public static Color BlueViolet => new(138, 43, 226, 255);
///
/// Gets the system color with (R, G, B, A) = (165, 42, 42, 255).
///
public static Color Brown => new(165, 42, 42, 255);
///
/// Gets the system color with (R, G, B, A) = (222, 184, 135, 255).
///
public static Color BurlyWood => new(222, 184, 135, 255);
///
/// Gets the system color with (R, G, B, A) = (95, 158, 160, 255).
///
public static Color CadetBlue => new(95, 158, 160, 255);
///
/// Gets the system color with (R, G, B, A) = (127, 255, 0, 255).
///
public static Color Chartreuse => new(127, 255, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (210, 105, 30, 255).
///
public static Color Chocolate => new(210, 105, 30, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 127, 80, 255).
///
public static Color Coral => new(255, 127, 80, 255);
///
/// Gets the system color with (R, G, B, A) = (100, 149, 237, 255).
///
public static Color CornflowerBlue => new(100, 149, 237, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 248, 220, 255).
///
public static Color Cornsilk => new(255, 248, 220, 255);
///
/// Gets the system color with (R, G, B, A) = (220, 20, 60, 255).
///
public static Color Crimson => new(220, 20, 60, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 255, 255, 255).
///
public static Color Cyan => new(0, 255, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 0, 139, 255).
///
public static Color DarkBlue => new(0, 0, 139, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 139, 139, 255).
///
public static Color DarkCyan => new(0, 139, 139, 255);
///
/// Gets the system color with (R, G, B, A) = (184, 134, 11, 255).
///
public static Color DarkGoldenrod => new(184, 134, 11, 255);
///
/// Gets the system color with (R, G, B, A) = (169, 169, 169, 255).
///
public static Color DarkGray => new(169, 169, 169, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 100, 0, 255).
///
public static Color DarkGreen => new(0, 100, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (189, 183, 107, 255).
///
public static Color DarkKhaki => new(189, 183, 107, 255);
///
/// Gets the system color with (R, G, B, A) = (139, 0, 139, 255).
///
public static Color DarkMagenta => new(139, 0, 139, 255);
///
/// Gets the system color with (R, G, B, A) = (85, 107, 47, 255).
///
public static Color DarkOliveGreen => new(85, 107, 47, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 140, 0, 255).
///
public static Color DarkOrange => new(255, 140, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (153, 50, 204, 255).
///
public static Color DarkOrchid => new(153, 50, 204, 255);
///
/// Gets the system color with (R, G, B, A) = (139, 0, 0, 255).
///
public static Color DarkRed => new(139, 0, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (233, 150, 122, 255).
///
public static Color DarkSalmon => new(233, 150, 122, 255);
///
/// Gets the system color with (R, G, B, A) = (143, 188, 143, 255).
/// Previously (R, G, B, A) = (143, 188, 139, 255) before .NET 5.
///
public static Color DarkSeaGreen => new(143, 188, 143, 255);
///
/// Gets the system color with (R, G, B, A) = (72, 61, 139, 255).
///
public static Color DarkSlateBlue => new(72, 61, 139, 255);
///
/// Gets the system color with (R, G, B, A) = (47, 79, 79, 255).
///
public static Color DarkSlateGray => new(47, 79, 79, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 206, 209, 255).
///
public static Color DarkTurquoise => new(0, 206, 209, 255);
///
/// Gets the system color with (R, G, B, A) = (148, 0, 211, 255).
///
public static Color DarkViolet => new(148, 0, 211, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 20, 147, 255).
///
public static Color DeepPink => new(255, 20, 147, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 191, 255, 255).
///
public static Color DeepSkyBlue => new(0, 191, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (105, 105, 105, 255).
///
public static Color DimGray => new(105, 105, 105, 255);
///
/// Gets the system color with (R, G, B, A) = (30, 144, 255, 255).
///
public static Color DodgerBlue => new(30, 144, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (178, 34, 34, 255).
///
public static Color Firebrick => new(178, 34, 34, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 250, 240, 255).
///
public static Color FloralWhite => new(255, 250, 240, 255);
///
/// Gets the system color with (R, G, B, A) = (34, 139, 34, 255).
///
public static Color ForestGreen => new(34, 139, 34, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 0, 255, 255).
///
public static Color Fuchsia => new(255, 0, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (220, 220, 220, 255).
///
public static Color Gainsboro => new(220, 220, 220, 255);
///
/// Gets the system color with (R, G, B, A) = (248, 248, 255, 255).
///
public static Color GhostWhite => new(248, 248, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 215, 0, 255).
///
public static Color Gold => new(255, 215, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (218, 165, 32, 255).
///
public static Color Goldenrod => new(218, 165, 32, 255);
///
/// Gets the system color with (R, G, B, A) = (128, 128, 128, 255).
///
public static Color Gray => new(128, 128, 128, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 128, 0, 255).
///
public static Color Green => new(0, 128, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (173, 255, 47, 255).
///
public static Color GreenYellow => new(173, 255, 47, 255);
///
/// Gets the system color with (R, G, B, A) = (240, 255, 240, 255).
///
public static Color Honeydew => new(240, 255, 240, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 105, 180, 255).
///
public static Color HotPink => new(255, 105, 180, 255);
///
/// Gets the system color with (R, G, B, A) = (205, 92, 92, 255).
///
public static Color IndianRed => new(205, 92, 92, 255);
///
/// Gets the system color with (R, G, B, A) = (75, 0, 130, 255).
///
public static Color Indigo => new(75, 0, 130, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 255, 240, 255).
///
public static Color Ivory => new(255, 255, 240, 255);
///
/// Gets the system color with (R, G, B, A) = (240, 230, 140, 255).
///
public static Color Khaki => new(240, 230, 140, 255);
///
/// Gets the system color with (R, G, B, A) = (230, 230, 250, 255).
///
public static Color Lavender => new(230, 230, 250, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 240, 245, 255).
///
public static Color LavenderBlush => new(255, 240, 245, 255);
///
/// Gets the system color with (R, G, B, A) = (124, 252, 0, 255).
///
public static Color LawnGreen => new(124, 252, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 250, 205, 255).
///
public static Color LemonChiffon => new(255, 250, 205, 255);
///
/// Gets the system color with (R, G, B, A) = (173, 216, 230, 255).
///
public static Color LightBlue => new(173, 216, 230, 255);
///
/// Gets the system color with (R, G, B, A) = (240, 128, 128, 255).
///
public static Color LightCoral => new(240, 128, 128, 255);
///
/// Gets the system color with (R, G, B, A) = (224, 255, 255, 255).
///
public static Color LightCyan => new(224, 255, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (250, 250, 210, 255).
///
public static Color LightGoldenrodYellow => new(250, 250, 210, 255);
///
/// Gets the system color with (R, G, B, A) = (144, 238, 144, 255).
///
public static Color LightGreen => new(144, 238, 144, 255);
///
/// Gets the system color with (R, G, B, A) = (211, 211, 211, 255).
///
public static Color LightGray => new(211, 211, 211, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 182, 193, 255).
///
public static Color LightPink => new(255, 182, 193, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 160, 122, 255).
///
public static Color LightSalmon => new(255, 160, 122, 255);
///
/// Gets the system color with (R, G, B, A) = (32, 178, 170, 255).
///
public static Color LightSeaGreen => new(32, 178, 170, 255);
///
/// Gets the system color with (R, G, B, A) = (135, 206, 250, 255).
///
public static Color LightSkyBlue => new(135, 206, 250, 255);
///
/// Gets the system color with (R, G, B, A) = (119, 136, 153, 255).
///
public static Color LightSlateGray => new(119, 136, 153, 255);
///
/// Gets the system color with (R, G, B, A) = (176, 196, 222, 255).
///
public static Color LightSteelBlue => new(176, 196, 222, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 255, 224, 255).
///
public static Color LightYellow => new(255, 255, 224, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 255, 0, 255).
///
public static Color Lime => new(0, 255, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (50, 205, 50, 255).
///
public static Color LimeGreen => new(50, 205, 50, 255);
///
/// Gets the system color with (R, G, B, A) = (250, 240, 230, 255).
///
public static Color Linen => new(250, 240, 230, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 0, 255, 255).
///
public static Color Magenta => new(255, 0, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (128, 0, 0, 255).
///
public static Color Maroon => new(128, 0, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (102, 205, 170, 255).
///
public static Color MediumAquamarine => new(102, 205, 170, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 0, 205, 255).
///
public static Color MediumBlue => new(0, 0, 205, 255);
///
/// Gets the system color with (R, G, B, A) = (186, 85, 211, 255).
///
public static Color MediumOrchid => new(186, 85, 211, 255);
///
/// Gets the system color with (R, G, B, A) = (147, 112, 219, 255).
///
public static Color MediumPurple => new(147, 112, 219, 255);
///
/// Gets the system color with (R, G, B, A) = (60, 179, 113, 255).
///
public static Color MediumSeaGreen => new(60, 179, 113, 255);
///
/// Gets the system color with (R, G, B, A) = (123, 104, 238, 255).
///
public static Color MediumSlateBlue => new(123, 104, 238, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 250, 154, 255).
///
public static Color MediumSpringGreen => new(0, 250, 154, 255);
///
/// Gets the system color with (R, G, B, A) = (72, 209, 204, 255).
///
public static Color MediumTurquoise => new(72, 209, 204, 255);
///
/// Gets the system color with (R, G, B, A) = (199, 21, 133, 255).
///
public static Color MediumVioletRed => new(199, 21, 133, 255);
///
/// Gets the system color with (R, G, B, A) = (25, 25, 112, 255).
///
public static Color MidnightBlue => new(25, 25, 112, 255);
///
/// Gets the system color with (R, G, B, A) = (245, 255, 250, 255).
///
public static Color MintCream => new(245, 255, 250, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 228, 225, 255).
///
public static Color MistyRose => new(255, 228, 225, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 228, 181, 255).
///
public static Color Moccasin => new(255, 228, 181, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 222, 173, 255).
///
public static Color NavajoWhite => new(255, 222, 173, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 0, 128, 255).
///
public static Color Navy => new(0, 0, 128, 255);
///
/// Gets the system color with (R, G, B, A) = (253, 245, 230, 255).
///
public static Color OldLace => new(253, 245, 230, 255);
///
/// Gets the system color with (R, G, B, A) = (128, 128, 0, 255).
///
public static Color Olive => new(128, 128, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (107, 142, 35, 255).
///
public static Color OliveDrab => new(107, 142, 35, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 165, 0, 255).
///
public static Color Orange => new(255, 165, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 69, 0, 255).
///
public static Color OrangeRed => new(255, 69, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (218, 112, 214, 255).
///
public static Color Orchid => new(218, 112, 214, 255);
///
/// Gets the system color with (R, G, B, A) = (238, 232, 170, 255).
///
public static Color PaleGoldenrod => new(238, 232, 170, 255);
///
/// Gets the system color with (R, G, B, A) = (152, 251, 152, 255).
///
public static Color PaleGreen => new(152, 251, 152, 255);
///
/// Gets the system color with (R, G, B, A) = (175, 238, 238, 255).
///
public static Color PaleTurquoise => new(175, 238, 238, 255);
///
/// Gets the system color with (R, G, B, A) = (219, 112, 147, 255).
///
public static Color PaleVioletRed => new(219, 112, 147, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 239, 213, 255).
///
public static Color PapayaWhip => new(255, 239, 213, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 218, 185, 255).
///
public static Color PeachPuff => new(255, 218, 185, 255);
///
/// Gets the system color with (R, G, B, A) = (205, 133, 63, 255).
///
public static Color Peru => new(205, 133, 63, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 192, 203, 255).
///
public static Color Pink => new(255, 192, 203, 255);
///
/// Gets the system color with (R, G, B, A) = (221, 160, 221, 255).
///
public static Color Plum => new(221, 160, 221, 255);
///
/// Gets the system color with (R, G, B, A) = (176, 224, 230, 255).
///
public static Color PowderBlue => new(176, 224, 230, 255);
///
/// Gets the system color with (R, G, B, A) = (128, 0, 128, 255).
///
public static Color Purple => new(128, 0, 128, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 0, 0, 255).
///
public static Color Red => new(255, 0, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (188, 143, 143, 255).
///
public static Color RosyBrown => new(188, 143, 143, 255);
///
/// Gets the system color with (R, G, B, A) = (65, 105, 225, 255).
///
public static Color RoyalBlue => new(65, 105, 225, 255);
///
/// Gets the system color with (R, G, B, A) = (139, 69, 19, 255).
///
public static Color SaddleBrown => new(139, 69, 19, 255);
///
/// Gets the system color with (R, G, B, A) = (250, 128, 114, 255).
///
public static Color Salmon => new(250, 128, 114, 255);
///
/// Gets the system color with (R, G, B, A) = (244, 164, 96, 255).
///
public static Color SandyBrown => new(244, 164, 96, 255);
///
/// Gets the system color with (R, G, B, A) = (46, 139, 87, 255).
///
public static Color SeaGreen => new(46, 139, 87, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 245, 238, 255).
///
public static Color SeaShell => new(255, 245, 238, 255);
///
/// Gets the system color with (R, G, B, A) = (160, 82, 45, 255).
///
public static Color Sienna => new(160, 82, 45, 255);
///
/// Gets the system color with (R, G, B, A) = (192, 192, 192, 255).
///
public static Color Silver => new(192, 192, 192, 255);
///
/// Gets the system color with (R, G, B, A) = (135, 206, 235, 255).
///
public static Color SkyBlue => new(135, 206, 235, 255);
///
/// Gets the system color with (R, G, B, A) = (106, 90, 205, 255).
///
public static Color SlateBlue => new(106, 90, 205, 255);
///
/// Gets the system color with (R, G, B, A) = (112, 128, 144, 255).
///
public static Color SlateGray => new(112, 128, 144, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 250, 250, 255).
///
public static Color Snow => new(255, 250, 250, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 255, 127, 255).
///
public static Color SpringGreen => new(0, 255, 127, 255);
///
/// Gets the system color with (R, G, B, A) = (70, 130, 180, 255).
///
public static Color SteelBlue => new(70, 130, 180, 255);
///
/// Gets the system color with (R, G, B, A) = (210, 180, 140, 255).
///
public static Color Tan => new(210, 180, 140, 255);
///
/// Gets the system color with (R, G, B, A) = (0, 128, 128, 255).
///
public static Color Teal => new(0, 128, 128, 255);
///
/// Gets the system color with (R, G, B, A) = (216, 191, 216, 255).
///
public static Color Thistle => new(216, 191, 216, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 99, 71, 255).
///
public static Color Tomato => new(255, 99, 71, 255);
///
/// Gets the system color with (R, G, B, A) = (64, 224, 208, 255).
///
public static Color Turquoise => new(64, 224, 208, 255);
///
/// Gets the system color with (R, G, B, A) = (238, 130, 238, 255).
///
public static Color Violet => new(238, 130, 238, 255);
///
/// Gets the system color with (R, G, B, A) = (245, 222, 179, 255).
///
public static Color Wheat => new(245, 222, 179, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 255, 255, 255).
///
public static Color White => new(255, 255, 255, 255);
///
/// Gets the system color with (R, G, B, A) = (245, 245, 245, 255).
///
public static Color WhiteSmoke => new(245, 245, 245, 255);
///
/// Gets the system color with (R, G, B, A) = (255, 255, 0, 255).
///
public static Color Yellow => new(255, 255, 0, 255);
///
/// Gets the system color with (R, G, B, A) = (154, 205, 50, 255).
///
public static Color YellowGreen => new(154, 205, 50, 255);
private static readonly Dictionary DefaultColors = new()
{
["transparent"] = Transparent,
["aliceblue"] = AliceBlue,
["antiquewhite"] = AntiqueWhite,
["aqua"] = Aqua,
["aquamarine"] = Aquamarine,
["azure"] = Azure,
["beige"] = Beige,
["bisque"] = Bisque,
["black"] = Black,
["blanchedalmond"] = BlanchedAlmond,
["blue"] = Blue,
["blueviolet"] = BlueViolet,
["brown"] = Brown,
["burlywood"] = BurlyWood,
["cadetblue"] = CadetBlue,
["chartreuse"] = Chartreuse,
["chocolate"] = Chocolate,
["coral"] = Coral,
["cornflowerblue"] = CornflowerBlue,
["cornsilk"] = Cornsilk,
["crimson"] = Crimson,
["cyan"] = Cyan,
["darkblue"] = DarkBlue,
["darkcyan"] = DarkCyan,
["darkgoldenrod"] = DarkGoldenrod,
["darkgray"] = DarkGray,
["darkgreen"] = DarkGreen,
["darkkhaki"] = DarkKhaki,
["darkmagenta"] = DarkMagenta,
["darkolivegreen"] = DarkOliveGreen,
["darkorange"] = DarkOrange,
["darkorchid"] = DarkOrchid,
["darkred"] = DarkRed,
["darksalmon"] = DarkSalmon,
["darkseagreen"] = DarkSeaGreen,
["darkslateblue"] = DarkSlateBlue,
["darkslategray"] = DarkSlateGray,
["darkturquoise"] = DarkTurquoise,
["darkviolet"] = DarkViolet,
["deeppink"] = DeepPink,
["deepskyblue"] = DeepSkyBlue,
["dimgray"] = DimGray,
["dodgerblue"] = DodgerBlue,
["firebrick"] = Firebrick,
["floralwhite"] = FloralWhite,
["forestgreen"] = ForestGreen,
["fuchsia"] = Fuchsia,
["gainsboro"] = Gainsboro,
["ghostwhite"] = GhostWhite,
["gold"] = Gold,
["goldenrod"] = Goldenrod,
["gray"] = Gray,
["green"] = Green,
["greenyellow"] = GreenYellow,
["honeydew"] = Honeydew,
["hotpink"] = HotPink,
["indianred"] = IndianRed,
["indigo"] = Indigo,
["ivory"] = Ivory,
["khaki"] = Khaki,
["lavender"] = Lavender,
["lavenderblush"] = LavenderBlush,
["lawngreen"] = LawnGreen,
["lemonchiffon"] = LemonChiffon,
["lightblue"] = LightBlue,
["lightcoral"] = LightCoral,
["lightcyan"] = LightCyan,
["lightgoldenrodyellow"] = LightGoldenrodYellow,
["lightgreen"] = LightGreen,
["lightgray"] = LightGray,
["lightpink"] = LightPink,
["lightsalmon"] = LightSalmon,
["lightseagreen"] = LightSeaGreen,
["lightskyblue"] = LightSkyBlue,
["lightslategray"] = LightSlateGray,
["lightsteelblue"] = LightSteelBlue,
["lightyellow"] = LightYellow,
["lime"] = Lime,
["limegreen"] = LimeGreen,
["linen"] = Linen,
["magenta"] = Magenta,
["maroon"] = Maroon,
["mediumaquamarine"] = MediumAquamarine,
["mediumblue"] = MediumBlue,
["mediumorchid"] = MediumOrchid,
["mediumpurple"] = MediumPurple,
["mediumseagreen"] = MediumSeaGreen,
["mediumslateblue"] = MediumSlateBlue,
["mediumspringgreen"] = MediumSpringGreen,
["mediumturquoise"] = MediumTurquoise,
["mediumvioletred"] = MediumVioletRed,
["midnightblue"] = MidnightBlue,
["mintcream"] = MintCream,
["mistyrose"] = MistyRose,
["moccasin"] = Moccasin,
["navajowhite"] = NavajoWhite,
["navy"] = Navy,
["oldlace"] = OldLace,
["olive"] = Olive,
["olivedrab"] = OliveDrab,
["orange"] = Orange,
["orangered"] = OrangeRed,
["orchid"] = Orchid,
["palegoldenrod"] = PaleGoldenrod,
["palegreen"] = PaleGreen,
["paleturquoise"] = PaleTurquoise,
["palevioletred"] = PaleVioletRed,
["papayawhip"] = PapayaWhip,
["peachpuff"] = PeachPuff,
["peru"] = Peru,
["pink"] = Pink,
["plum"] = Plum,
["powderblue"] = PowderBlue,
["purple"] = Purple,
["red"] = Red,
["rosybrown"] = RosyBrown,
["royalblue"] = RoyalBlue,
["saddlebrown"] = SaddleBrown,
["salmon"] = Salmon,
["sandybrown"] = SandyBrown,
["seagreen"] = SeaGreen,
["seashell"] = SeaShell,
["sienna"] = Sienna,
["silver"] = Silver,
["skyblue"] = SkyBlue,
["slateblue"] = SlateBlue,
["slategray"] = SlateGray,
["snow"] = Snow,
["springgreen"] = SpringGreen,
["steelblue"] = SteelBlue,
["tan"] = Tan,
["teal"] = Teal,
["thistle"] = Thistle,
["tomato"] = Tomato,
["turquoise"] = Turquoise,
["violet"] = Violet,
["wheat"] = Wheat,
["white"] = White,
["whitesmoke"] = WhiteSmoke,
["yellow"] = Yellow,
["yellowgreen"] = YellowGreen,
};
#endregion
private static readonly Dictionary DefaultColorsInverted =
DefaultColors.ToLookup(pair => pair.Value).ToDictionary(i => i.Key, i => i.First().Key);
public readonly string? Name()
{
return DefaultColorsInverted.TryGetValue(this, out var name) ? name : null;
}
}
}