diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj
index 743e2d55..a7318f27 100644
--- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj
+++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj
@@ -4,6 +4,12 @@
+
+ $(TargetFrameworks);net6.0
+ $(DefineConstants);RECORD_STRUCT_SUPPORT
+
+
+
CSF.Screenplay.Selenium
$(MSBuildProjectDirectory)\bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
diff --git a/CSF.Screenplay.Selenium/Color.cs b/CSF.Screenplay.Selenium/Color.cs
new file mode 100644
index 00000000..624c3615
--- /dev/null
+++ b/CSF.Screenplay.Selenium/Color.cs
@@ -0,0 +1,314 @@
+using System;
+using SysColor = System.Drawing.Color;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// Immutable type represents a color on the web, in a manner which may be converted and compared between web-supported formats.
+ ///
+ ///
+ ///
+ /// An uninitialized instance of this type will represent "fully-transparent black".
+ /// Internally, this type stores color as three unsigned values (Red, Green, Blue) and a
+ /// representing the transparency (Alpha). The Alpha value must be between 0 (fully transparent)
+ /// and 1 (fully opaque).
+ ///
+ ///
+ /// This struct contains functionality to compare equality with, and convert to/from the .NET built-in .
+ /// It also contains parsing logic to parse/format an instance from/to string representations of color which are used by web browsers.
+ /// See the MDN writeup of web color for
+ /// more information about the valid formats.
+ ///
+ ///
+#if RECORD_STRUCT_SUPPORT
+ public readonly record struct Color
+#else
+ public struct Color
+#endif
+ : IEquatable, IEquatable, IEquatable
+ {
+ readonly double alpha;
+
+ ///
+ /// Gets the red component in the sRGB color space.
+ ///
+#if RECORD_STRUCT_SUPPORT
+ public readonly byte Red { get; init; }
+#else
+ public byte Red { get; private set; }
+#endif
+
+ ///
+ /// Gets the green component in the sRGB color space.
+ ///
+#if RECORD_STRUCT_SUPPORT
+ public readonly byte Green { get; init; }
+#else
+ public byte Green { get; private set; }
+#endif
+
+ ///
+ /// Gets the blue component in the sRGB color space.
+ ///
+#if RECORD_STRUCT_SUPPORT
+ public readonly byte Blue { get; init; }
+#else
+ public byte Blue { get; private set; }
+#endif
+
+ ///
+ /// Gets the alpha (transparency) component in the sRGB color space.
+ ///
+ ///
+ /// The value of this property will always be between zero (fully transparent) and one (fully opaque).
+ ///
+#if RECORD_STRUCT_SUPPORT
+ public readonly double Alpha
+ {
+ get => alpha;
+ init => this.alpha = SanitizeAlpha(value);
+ }
+#else
+ public double Alpha { get => alpha; }
+#endif
+
+ ///
+ /// Gets a representation of , as a byte.
+ ///
+ public byte AlphaAsByte => (byte) Math.Floor(Math.Round(Alpha * 255, 0, MidpointRounding.AwayFromZero));
+
+ ///
+ /// Converts this color to a .
+ ///
+ ///
+ ///
+ /// In some situations, it might be useful to convert to/from the .NET built-in
+ /// type. Use this method and to do so.
+ ///
+ ///
+ /// A representation of this color.
+ public SysColor ToSystemDrawingColor() => SysColor.FromArgb(AlphaAsByte, Red, Green, Blue);
+
+ ///
+ public bool Equals(SysColor other) => ToSystemDrawingColor().Equals(other);
+
+ ///
+ public bool Equals(Color other) => other.Red == Red
+ && other.Green == Green
+ && other.Blue == Blue
+ && other.AlphaAsByte == AlphaAsByte;
+
+ ///
+ public bool Equals(string other) => TryParse(other, out var color) && Equals(color);
+
+#if !RECORD_STRUCT_SUPPORT
+ ///
+ public override bool Equals(object obj)
+ {
+ if(obj is Color color) return Equals(color);
+ if(obj is SysColor sysColor) return Equals(sysColor);
+ if(obj is string strColor) return Equals(strColor);
+ return false;
+ }
+#endif
+
+ ///
+ public override int GetHashCode() => HashCode.Combine(Red, Green, Blue, Alpha);
+
+ ///
+ /// Creates a new instance of from the specified RGBA values.
+ ///
+ ///
+ ///
+ /// The byte data type for the R, G and B components of the color ensure that it is impossible to specify
+ /// values outside the permitted range. As for the , if a value of less than zero is specified
+ /// here then it is treated as zero. Likewise if a value of greater than one is specified then it will be treated as one.
+ ///
+ ///
+ /// The red component in the sRGB color space
+ /// The green component in the sRGB color space
+ /// The blue component in the sRGB color space
+ /// The alpha (transparency) component, which must be between zero and one.
+ public Color(byte red, byte green, byte blue, double alpha)
+ {
+ Red = red;
+ Green = green;
+ Blue = blue;
+ this.alpha = SanitizeAlpha(alpha);
+ }
+
+ ///
+ /// Sanitizes a value intended for .
+ ///
+ ///
+ /// If is less than zero then this method returns zero.
+ /// If is more than one then this method returns one.
+ /// Otherwise, this method returns .
+ ///
+ /// The alpha value.
+ /// A sanitized alpha value.
+ static double SanitizeAlpha(double alpha) => alpha < 0 ? 0 : alpha > 1 ? 1 : alpha;
+
+ ///
+ /// Converts a into a .
+ ///
+ ///
+ ///
+ /// In some situations, it might be useful to convert to/from the .NET built-in
+ /// type. Use this method and to do so.
+ ///
+ ///
+ /// A representation of the specified color.
+ public static Color FromSystemDrawingColour(SysColor color)
+ => new Color(color.R, color.G, color.B, color.A / 255);
+
+ ///
+ /// Gets a value indicating whether the specified is a valid string representation
+ /// for a . If this returns then exposes the parsed
+ /// value.
+ ///
+ ///
+ ///
+ /// If this method returns then the output parameter will contain
+ /// the color parsed from the specified string. If this method returns then the output parameter
+ /// has an undefined value and must not be used.
+ ///
+ /// This method will not raise an exception and it is safe to use with unknown strings, including those which
+ /// might be .
+ ///
+ /// A string containing a color value which is compatible with the web.
+ /// See the MDN writeup on
+ /// web colors for more information.
+ /// If this method returns , then this parameter exposes the parsed color value.
+ /// If this method returns then the value of this parameter must be ignored.
+ /// if parsing is successful (the contains a valid &
+ /// recognized color representation); if not
+ public static bool TryParse(string webColorValue, out Color color)
+ {
+ color = default;
+ if(string.IsNullOrWhiteSpace(webColorValue)) return false;
+
+ var allParsers = new IParsesColor[]
+ {
+ new RgbColorParser(),
+ new RgbPercentageColorParser(),
+ new RgbaColorParser(),
+ new RgbaPercentageColorParser(),
+ new Hex6ColorParser(),
+ new Hex3ColorParser(),
+ new HslColorParser(),
+ new HslaColorParser(),
+ new NamedColorParser(),
+ };
+
+ foreach(var parser in allParsers)
+ if(parser.TryParseColor(webColorValue, out color)) return true;
+
+ color = default;
+ return false;
+ }
+
+ ///
+ /// Parses a from a string representation of a color.
+ ///
+ ///
+ ///
+ /// If is a valid representation of a web-compatible color value then this method will
+ /// return that color as an instance of . If not, this method will throw an exception.
+ ///
+ /// If you are not certain that the represents a valid colour then use
+ /// instead.
+ ///
+ /// A string containing a color value which is compatible with the web.
+ /// See the MDN writeup on
+ /// web colors for more information.
+ /// The parsed color.
+ /// If is .
+ /// If is not a recognized representation of a color.
+ public static Color Parse(string webColorValue)
+ {
+ if (webColorValue is null)
+ throw new ArgumentNullException(nameof(webColorValue));
+
+ return TryParse(webColorValue, out var color)
+ ? color
+ : throw new FormatException("The string color representation must be a in a web-compatible recognized format.");
+ }
+
+ ///
+ /// Gets a value indicating whether the specified and
+ /// are equal.
+ ///
+ ///
+ /// Despite the type differences, two colors are equal if they represent the same sRGB color.
+ ///
+ /// The
+ /// The
+ /// if the two different colors represent the same sRGB color; if not.
+ public static bool operator ==(Color color, SysColor sysColor) => color.Equals(sysColor);
+
+ ///
+ /// Gets a value indicating whether the specified and
+ /// are not equal.
+ ///
+ ///
+ /// Despite the type differences, two colors are equal if they represent the same sRGB color.
+ ///
+ /// The
+ /// The
+ /// if the two different colors represent the same sRGB color; if not.
+ public static bool operator !=(Color color, SysColor sysColor) => !(color == sysColor);
+
+ ///
+ /// Gets a value indicating whether the specified and representation of a color
+ /// are equal.
+ ///
+ ///
+ /// A color is equal to a string if the result of is
+ /// and if the resulting parsed instance is equal to the current color.
+ /// Note that this means that a color is never equal to a string which is not a valid color representation, or which is .
+ ///
+ /// The
+ /// The string which represents a color
+ /// if the current color and the string color representation indicate the same sRGB color; if not.
+ public static bool operator ==(Color color, string stringColor) => color.Equals(stringColor);
+
+ ///
+ /// Gets a value indicating whether the specified and representation of a color
+ /// are not equal.
+ ///
+ ///
+ /// A color is equal to a string if the result of is
+ /// and if the resulting parsed instance is equal to the current color.
+ /// Note that this means that a color is never equal to a string which is not a valid color representation, or which is .
+ ///
+ /// The
+ /// The string which represents a color
+ /// if the current color and the string color representation indicate the same sRGB color; if not.
+ public static bool operator !=(Color color, string stringColor) => !(color == stringColor);
+
+ #if !RECORD_STRUCT_SUPPORT
+ ///
+ /// Gets a value indicating whether the two specified instances are equal.
+ ///
+ ///
+ /// Two colors are equal if they represent the same sRGB color.
+ ///
+ /// The first
+ /// The second
+ /// if the two colors represent the same sRGB color; if not.
+ public static bool operator ==(Color first, Color second) => first.Equals(second);
+
+ ///
+ /// Gets a value indicating whether the two specified instances are not equal.
+ ///
+ ///
+ /// Two colors are equal if they represent the same sRGB color.
+ ///
+ /// The first
+ /// The second
+ /// if the two colors represent the same sRGB color; if not.
+ public static bool operator !=(Color first, Color second) => !(first == second);
+#endif
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/ColorParser.cs b/CSF.Screenplay.Selenium/ColorParser.cs
new file mode 100644
index 00000000..4eb3c946
--- /dev/null
+++ b/CSF.Screenplay.Selenium/ColorParser.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// An object which can get an instance of .
+ ///
+ internal interface IParsesColor
+ {
+ ///
+ /// Attempts to parse an instance of from the specified .
+ ///
+ ///
+ ///
+ /// If the parsing is successful then this method will return and the
+ /// will contain the parsed color value.
+ /// Otherwise it will return and the parameter must be ignored.
+ ///
+ ///
+ /// A string representing a color.
+ /// If this method returns then this parameter exposes the parsed
+ /// color; if not then this value must be ignored.
+ /// if the parsing was a success; if not.
+ bool TryParseColor(string colorValue, out Color color);
+ }
+
+ internal abstract class NumericColorParser : IParsesColor
+ {
+ protected static readonly string
+ BytePart = @"\s*(\d{1,3})\s*",
+ DecimalAlphaPart = @"\s*(0|1|0\.\d+)\s*",
+ PercentDecimalPart = @"\s*(\d{1,3}|\d{1,2}\.\d+)%\s*",
+ PercentPart = @"\s*(\d{1,3})%\s*",
+ Hex2Part = @"\s*[1-9a-f]{2}\s*",
+ Hex1Part = @"\s*[1-9a-f]\s*";
+
+ ///
+ public virtual bool TryParseColor(string colorValue, out Color color)
+ {
+ color = default;
+ var match = GetParsingRegex(out var includesAlpha).Match(colorValue);
+ if(!match.Success) return false;
+
+ color = new Color(GetByte(match.Groups[1]),
+ GetByte(match.Groups[2]),
+ GetByte(match.Groups[3]),
+ includesAlpha ? double.Parse(match.Groups[4].Value) : 1);
+ return true;
+ }
+
+ ///
+ /// Gets a regex which parses a string color representation.
+ ///
+ /// if this regex includes a value for the alpha channel; if not.
+ /// A regex
+ protected virtual Regex GetParsingRegex(out bool includesAlpha)
+ => new Regex(GetParsingPattern(out includesAlpha),
+ RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase,
+ TimeSpan.FromMilliseconds(500));
+
+ ///
+ /// Gets a regex pattern which parses a string color representation.
+ ///
+ /// if this regex includes a value for the alpha channel; if not.
+ /// A regex
+ protected abstract string GetParsingPattern(out bool includesAlpha);
+
+ ///
+ /// Parses a byte value from the value of the match group.
+ ///
+ /// A regex match group
+ /// A byte value
+ protected virtual byte GetByte(Group matchGroup) => byte.Parse(matchGroup.Value);
+ }
+
+ internal class RgbColorParser : NumericColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = false;
+ return @$"^\s*rgb\({BytePart},{BytePart},{BytePart}\)\s*$";
+ }
+ }
+
+ internal class RgbaColorParser : NumericColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = true;
+ return @$"^\s*rgba\({BytePart},{BytePart},{BytePart},{DecimalAlphaPart}\)\s*$";
+ }
+ }
+
+ internal class RgbPercentageColorParser : NumericColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = false;
+ return @$"^\s*rgb\({PercentDecimalPart},{PercentDecimalPart},{PercentDecimalPart}\)\s*$";
+ }
+
+ ///
+ protected override byte GetByte(Group matchGroup) => (byte) (double.Parse(matchGroup.Value) / 100D * 255D);
+ }
+
+ internal class RgbaPercentageColorParser : RgbPercentageColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = true;
+ return @$"^\s*rgb\({PercentDecimalPart},{PercentDecimalPart},{PercentDecimalPart},{DecimalAlphaPart}\)\s*$";
+ }
+ }
+
+ internal class Hex3ColorParser : NumericColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = false;
+ return @$"^\s*#{Hex1Part}{Hex1Part}{Hex1Part}\s*$";
+ }
+
+ ///
+ protected override byte GetByte(Group matchGroup) => Convert.ToByte(matchGroup.Value + matchGroup.Value, 16);
+ }
+
+ internal class Hex6ColorParser : NumericColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = false;
+ return @$"^\s*#{Hex2Part}{Hex2Part}{Hex2Part}\s*$";
+ }
+
+ ///
+ protected override byte GetByte(Group matchGroup) => Convert.ToByte(matchGroup.Value, 16);
+ }
+
+ internal class HslColorParser : NumericColorParser
+ {
+ ///
+ public override bool TryParseColor(string colorValue, out Color color)
+ {
+ color = default;
+ var match = GetParsingRegex(out var includesAlpha).Match(colorValue);
+ if(!match.Success) return false;
+
+ color = HslToRgb(short.Parse(match.Groups[1].Value),
+ byte.Parse(match.Groups[2].Value),
+ byte.Parse(match.Groups[3].Value),
+ includesAlpha ? double.Parse(match.Groups[4].Value) : 1);
+ return true;
+ }
+
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = false;
+ return @$"^\s*hsl\({BytePart},{PercentPart},{PercentPart}\s*$";
+ }
+
+ ///
+ /// Converts an HSL color to the sRGB color space.
+ ///
+ ///
+ ///
+ /// This is based upon the algorithms available at
+ /// The
+ /// Selenium 4.40.0 HSL converter for Java.
+ ///
+ ///
+ /// The hue value in degrees (0 to 360)
+ /// The saturation percentage (0 to 100)
+ /// The lightness percentage (0 to 100)
+ /// The alpha (transparency) value (0 to 1)
+ /// An instance of in the sRGB color space
+ static Color HslToRgb(short h, byte s, byte l, double alpha)
+ {
+ var hue = h / 360D;
+ var saturation = s / 100D;
+ var lightness = l / 100D;
+
+ // FYI: Saturation = zero means gray, making hue irrelevant
+ if(s == 0)
+ {
+ var allChannels = (byte) Math.Round(lightness * 255D, MidpointRounding.AwayFromZero);
+ return new Color(allChannels, allChannels, allChannels, alpha);
+ }
+
+ var luminosity2 = (lightness < 0.5)
+ ? lightness * (saturation + 1D)
+ : lightness + saturation - lightness * saturation;
+ var luminosity1 = 2D * lightness - luminosity2;
+
+ return new Color(HueValueToRgbByte(luminosity1, luminosity2, hue + 1D / 3D),
+ HueValueToRgbByte(luminosity1, luminosity2, hue),
+ HueValueToRgbByte(luminosity1, luminosity2, hue - 1D / 3D),
+ alpha);
+ }
+
+ static byte HueValueToRgbByte(double luminosity1,
+ double luminosity2,
+ double hueValue)
+ => (byte) Math.Round(HueValueToRgb(luminosity1, luminosity2, hueValue) * 255D, MidpointRounding.AwayFromZero);
+
+ static double HueValueToRgb(double luminosity1,
+ double luminosity2,
+ double hueValue)
+ {
+ if (hueValue < 0D) hueValue += 1;
+ if (hueValue > 1D) hueValue -= 1.0;
+ if (hueValue < 1D / 6D) return luminosity1 + (luminosity2 - luminosity1) * 6D * hueValue;
+ if (hueValue < 1D / 2D) return luminosity2;
+ if (hueValue < 2D / 3D) return luminosity1 + (luminosity2 - luminosity1) * (2D / 3D - hueValue) * 6D;
+ return luminosity1;
+ }
+ }
+
+ internal class HslaColorParser : HslColorParser
+ {
+ ///
+ protected override string GetParsingPattern(out bool includesAlpha)
+ {
+ includesAlpha = true;
+ return @$"^\s*hsla\({BytePart},{PercentPart},{PercentPart},{DecimalAlphaPart}\s*$";
+ }
+ }
+
+ internal class NamedColorParser : IParsesColor
+ {
+ ///
+ public bool TryParseColor(string colorValue, out Color color)
+ => Colors.TryGetNamedColor(colorValue, out color);
+ }
+
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Colors.cs b/CSF.Screenplay.Selenium/Colors.cs
new file mode 100644
index 00000000..c391381f
--- /dev/null
+++ b/CSF.Screenplay.Selenium/Colors.cs
@@ -0,0 +1,239 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reflection;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// Static type containing the pre-defined colors for the web.
+ ///
+ ///
+ ///
+ /// Each static property of this type corresponds to a well-known pre-defined color, according to
+ /// the W3C HTML4 spec.
+ ///
+ ///
+ public static class Colors
+ {
+ ///
+ /// Caches the named colors and their names, for performance reasons when using and/or
+ /// .
+ ///
+ static readonly ReadOnlyDictionary namedColors = GetNamedColorCache();
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+ public static Color TRANSPARENT => new Color(0, 0, 0, 0);
+ public static Color ALICEBLUE => new Color(240, 248, 255, 1);
+ public static Color ANTIQUEWHITE => new Color(250, 235, 215, 1);
+ public static Color AQUA => new Color(0, 255, 255, 1);
+ public static Color AQUAMARINE => new Color(127, 255, 212, 1);
+ public static Color AZURE => new Color(240, 255, 255, 1);
+ public static Color BEIGE => new Color(245, 245, 220, 1);
+ public static Color BISQUE => new Color(255, 228, 196, 1);
+ public static Color BLACK => new Color(0, 0, 0, 1);
+ public static Color BLANCHEDALMOND => new Color(255, 235, 205, 1);
+ public static Color BLUE => new Color(0, 0, 255, 1);
+ public static Color BLUEVIOLET => new Color(138, 43, 226, 1);
+ public static Color BROWN => new Color(165, 42, 42, 1);
+ public static Color BURLYWOOD => new Color(222, 184, 135, 1);
+ public static Color CADETBLUE => new Color(95, 158, 160, 1);
+ public static Color CHARTREUSE => new Color(127, 255, 0, 1);
+ public static Color CHOCOLATE => new Color(210, 105, 30, 1);
+ public static Color CORAL => new Color(255, 127, 80, 1);
+ public static Color CORNFLOWERBLUE => new Color(100, 149, 237, 1);
+ public static Color CORNSILK => new Color(255, 248, 220, 1);
+ public static Color CRIMSON => new Color(220, 20, 60, 1);
+ public static Color CYAN => new Color(0, 255, 255, 1);
+ public static Color DARKBLUE => new Color(0, 0, 139, 1);
+ public static Color DARKCYAN => new Color(0, 139, 139, 1);
+ public static Color DARKGOLDENROD => new Color(184, 134, 11, 1);
+ public static Color DARKGRAY => new Color(169, 169, 169, 1);
+ public static Color DARKGREEN => new Color(0, 100, 0, 1);
+ public static Color DARKGREY => new Color(169, 169, 169, 1);
+ public static Color DARKKHAKI => new Color(189, 183, 107, 1);
+ public static Color DARKMAGENTA => new Color(139, 0, 139, 1);
+ public static Color DARKOLIVEGREEN => new Color(85, 107, 47, 1);
+ public static Color DARKORANGE => new Color(255, 140, 0, 1);
+ public static Color DARKORCHID => new Color(153, 50, 204, 1);
+ public static Color DARKRED => new Color(139, 0, 0, 1);
+ public static Color DARKSALMON => new Color(233, 150, 122, 1);
+ public static Color DARKSEAGREEN => new Color(143, 188, 143, 1);
+ public static Color DARKSLATEBLUE => new Color(72, 61, 139, 1);
+ public static Color DARKSLATEGRAY => new Color(47, 79, 79, 1);
+ public static Color DARKSLATEGREY => new Color(47, 79, 79, 1);
+ public static Color DARKTURQUOISE => new Color(0, 206, 209, 1);
+ public static Color DARKVIOLET => new Color(148, 0, 211, 1);
+ public static Color DEEPPINK => new Color(255, 20, 147, 1);
+ public static Color DEEPSKYBLUE => new Color(0, 191, 255, 1);
+ public static Color DIMGRAY => new Color(105, 105, 105, 1);
+ public static Color DIMGREY => new Color(105, 105, 105, 1);
+ public static Color DODGERBLUE => new Color(30, 144, 255, 1);
+ public static Color FIREBRICK => new Color(178, 34, 34, 1);
+ public static Color FLORALWHITE => new Color(255, 250, 240, 1);
+ public static Color FORESTGREEN => new Color(34, 139, 34, 1);
+ public static Color FUCHSIA => new Color(255, 0, 255, 1);
+ public static Color GAINSBORO => new Color(220, 220, 220, 1);
+ public static Color GHOSTWHITE => new Color(248, 248, 255, 1);
+ public static Color GOLD => new Color(255, 215, 0, 1);
+ public static Color GOLDENROD => new Color(218, 165, 32, 1);
+ public static Color GRAY => new Color(128, 128, 128, 1);
+ public static Color GREY => new Color(128, 128, 128, 1);
+ public static Color GREEN => new Color(0, 128, 0, 1);
+ public static Color GREENYELLOW => new Color(173, 255, 47, 1);
+ public static Color HONEYDEW => new Color(240, 255, 240, 1);
+ public static Color HOTPINK => new Color(255, 105, 180, 1);
+ public static Color INDIANRED => new Color(205, 92, 92, 1);
+ public static Color INDIGO => new Color(75, 0, 130, 1);
+ public static Color IVORY => new Color(255, 255, 240, 1);
+ public static Color KHAKI => new Color(240, 230, 140, 1);
+ public static Color LAVENDER => new Color(230, 230, 250, 1);
+ public static Color LAVENDERBLUSH => new Color(255, 240, 245, 1);
+ public static Color LAWNGREEN => new Color(124, 252, 0, 1);
+ public static Color LEMONCHIFFON => new Color(255, 250, 205, 1);
+ public static Color LIGHTBLUE => new Color(173, 216, 230, 1);
+ public static Color LIGHTCORAL => new Color(240, 128, 128, 1);
+ public static Color LIGHTCYAN => new Color(224, 255, 255, 1);
+ public static Color LIGHTGOLDENRODYELLOW => new Color(250, 250, 210, 1);
+ public static Color LIGHTGRAY => new Color(211, 211, 211, 1);
+ public static Color LIGHTGREEN => new Color(144, 238, 144, 1);
+ public static Color LIGHTGREY => new Color(211, 211, 211, 1);
+ public static Color LIGHTPINK => new Color(255, 182, 193, 1);
+ public static Color LIGHTSALMON => new Color(255, 160, 122, 1);
+ public static Color LIGHTSEAGREEN => new Color(32, 178, 170, 1);
+ public static Color LIGHTSKYBLUE => new Color(135, 206, 250, 1);
+ public static Color LIGHTSLATEGRAY => new Color(119, 136, 153, 1);
+ public static Color LIGHTSLATEGREY => new Color(119, 136, 153, 1);
+ public static Color LIGHTSTEELBLUE => new Color(176, 196, 222, 1);
+ public static Color LIGHTYELLOW => new Color(255, 255, 224, 1);
+ public static Color LIME => new Color(0, 255, 0, 1);
+ public static Color LIMEGREEN => new Color(50, 205, 50, 1);
+ public static Color LINEN => new Color(250, 240, 230, 1);
+ public static Color MAGENTA => new Color(255, 0, 255, 1);
+ public static Color MAROON => new Color(128, 0, 0, 1);
+ public static Color MEDIUMAQUAMARINE => new Color(102, 205, 170, 1);
+ public static Color MEDIUMBLUE => new Color(0, 0, 205, 1);
+ public static Color MEDIUMORCHID => new Color(186, 85, 211, 1);
+ public static Color MEDIUMPURPLE => new Color(147, 112, 219, 1);
+ public static Color MEDIUMSEAGREEN => new Color(60, 179, 113, 1);
+ public static Color MEDIUMSLATEBLUE => new Color(123, 104, 238, 1);
+ public static Color MEDIUMSPRINGGREEN => new Color(0, 250, 154, 1);
+ public static Color MEDIUMTURQUOISE => new Color(72, 209, 204, 1);
+ public static Color MEDIUMVIOLETRED => new Color(199, 21, 133, 1);
+ public static Color MIDNIGHTBLUE => new Color(25, 25, 112, 1);
+ public static Color MINTCREAM => new Color(245, 255, 250, 1);
+ public static Color MISTYROSE => new Color(255, 228, 225, 1);
+ public static Color MOCCASIN => new Color(255, 228, 181, 1);
+ public static Color NAVAJOWHITE => new Color(255, 222, 173, 1);
+ public static Color NAVY => new Color(0, 0, 128, 1);
+ public static Color OLDLACE => new Color(253, 245, 230, 1);
+ public static Color OLIVE => new Color(128, 128, 0, 1);
+ public static Color OLIVEDRAB => new Color(107, 142, 35, 1);
+ public static Color ORANGE => new Color(255, 165, 0, 1);
+ public static Color ORANGERED => new Color(255, 69, 0, 1);
+ public static Color ORCHID => new Color(218, 112, 214, 1);
+ public static Color PALEGOLDENROD => new Color(238, 232, 170, 1);
+ public static Color PALEGREEN => new Color(152, 251, 152, 1);
+ public static Color PALETURQUOISE => new Color(175, 238, 238, 1);
+ public static Color PALEVIOLETRED => new Color(219, 112, 147, 1);
+ public static Color PAPAYAWHIP => new Color(255, 239, 213, 1);
+ public static Color PEACHPUFF => new Color(255, 218, 185, 1);
+ public static Color PERU => new Color(205, 133, 63, 1);
+ public static Color PINK => new Color(255, 192, 203, 1);
+ public static Color PLUM => new Color(221, 160, 221, 1);
+ public static Color POWDERBLUE => new Color(176, 224, 230, 1);
+ public static Color PURPLE => new Color(128, 0, 128, 1);
+ public static Color REBECCAPURPLE => new Color(102, 51, 153, 1);
+ public static Color RED => new Color(255, 0, 0, 1);
+ public static Color ROSYBROWN => new Color(188, 143, 143, 1);
+ public static Color ROYALBLUE => new Color(65, 105, 225, 1);
+ public static Color SADDLEBROWN => new Color(139, 69, 19, 1);
+ public static Color SALMON => new Color(250, 128, 114, 1);
+ public static Color SANDYBROWN => new Color(244, 164, 96, 1);
+ public static Color SEAGREEN => new Color(46, 139, 87, 1);
+ public static Color SEASHELL => new Color(255, 245, 238, 1);
+ public static Color SIENNA => new Color(160, 82, 45, 1);
+ public static Color SILVER => new Color(192, 192, 192, 1);
+ public static Color SKYBLUE => new Color(135, 206, 235, 1);
+ public static Color SLATEBLUE => new Color(106, 90, 205, 1);
+ public static Color SLATEGRAY => new Color(112, 128, 144, 1);
+ public static Color SLATEGREY => new Color(112, 128, 144, 1);
+ public static Color SNOW => new Color(255, 250, 250, 1);
+ public static Color SPRINGGREEN => new Color(0, 255, 127, 1);
+ public static Color STEELBLUE => new Color(70, 130, 180, 1);
+ public static Color TAN => new Color(210, 180, 140, 1);
+ public static Color TEAL => new Color(0, 128, 128, 1);
+ public static Color THISTLE => new Color(216, 191, 216, 1);
+ public static Color TOMATO => new Color(255, 99, 71, 1);
+ public static Color TURQUOISE => new Color(64, 224, 208, 1);
+ public static Color VIOLET => new Color(238, 130, 238, 1);
+ public static Color WHEAT => new Color(245, 222, 179, 1);
+ public static Color WHITE => new Color(255, 255, 255, 1);
+ public static Color WHITESMOKE => new Color(245, 245, 245, 1);
+ public static Color YELLOW => new Color(255, 255, 0, 1);
+ public static Color YELLOWGREEN => new Color(154, 205, 50, 1);
+ #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
+
+ ///
+ /// Gets a instance which matches the specified color-name.
+ ///
+ ///
+ ///
+ /// This method will throw an exception if does not correspond to a well-known color
+ /// name. This is a case-insensitive match.
+ /// If you are uncertain whether the is a well-known color name or not then consider
+ /// instead.
+ ///
+ ///
+ /// A named color (case insensitive)
+ /// A which corresponds to the specified named color.
+ /// If is
+ /// If does not correspond to a well-known named color
+ public static Color GetNamedColor(string colorName)
+ {
+ if (colorName is null) throw new ArgumentNullException(nameof(colorName));
+ if(namedColors.TryGetValue(colorName, out var color)) return color;
+ throw new ArgumentException($"'{colorName}' is not a well-known named color.");
+ }
+
+ ///
+ /// Gets a value indicating whether is a well-known color name.
+ /// Exposes a instance which corresponds to that name if it is.
+ ///
+ ///
+ ///
+ /// This method will never throw an exception for any value of .
+ /// Note that match with a well-known color name is performed in a case-insensitive manner.
+ ///
+ ///
+ /// A string which might correspond to a well-known color name.
+ /// If this method returns then this is a
+ /// which corresponds to the color indicated by ; if it returns
+ /// then this value is undefined and must be ignored.
+ /// if is a well-known color name; if not.
+ public static bool TryGetNamedColor(string colorName, out Color color)
+ {
+ color = BLACK;
+ if (colorName is null) return false;
+ return namedColors.TryGetValue(colorName, out color);
+ }
+
+ ///
+ /// Gets a dictionary of the names/instances of the well-known colors.
+ ///
+ ///
+ ///
+ /// The keys of this dictionary are case insensitive and correspond to the names of the static properties of this type.
+ /// The values are instances of the that the corresponding property returns.
+ ///
+ ///
+ /// A cache of the named color values.
+ static ReadOnlyDictionary GetNamedColorCache()
+ {
+ var namedColorValues = typeof(Colors)
+ .GetProperties(BindingFlags.Static)
+ .ToDictionary(k => k.Name, v => (Color) v.GetValue(null), StringComparer.InvariantCultureIgnoreCase);
+ return new ReadOnlyDictionary(namedColorValues);
+ }
+ }
+}
\ No newline at end of file