diff options
Diffstat (limited to 'Xamarin.Forms.Core/Color.cs')
-rw-r--r-- | Xamarin.Forms.Core/Color.cs | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Color.cs b/Xamarin.Forms.Core/Color.cs new file mode 100644 index 00000000..e9f2987d --- /dev/null +++ b/Xamarin.Forms.Core/Color.cs @@ -0,0 +1,375 @@ +using System; +using System.Diagnostics; +using System.Globalization; + +namespace Xamarin.Forms +{ + [DebuggerDisplay("R={R}, G={G}, B={B}, A={A}, Hue={Hue}, Saturation={Saturation}, Luminosity={Luminosity}")] + [TypeConverter(typeof(ColorTypeConverter))] + public struct Color + { + readonly Mode _mode; + + enum Mode + { + Default, + Rgb, + Hsl + } + + public static Color Default + { + get { return new Color(-1d, -1d, -1d, -1d, Mode.Default); } + } + + internal bool IsDefault + { + get { return _mode == Mode.Default; } + } + + public static Color Accent { get; internal set; } + + readonly float _a; + + public double A + { + get { return _a; } + } + + readonly float _r; + + public double R + { + get { return _r; } + } + + readonly float _g; + + public double G + { + get { return _g; } + } + + readonly float _b; + + public double B + { + get { return _b; } + } + + readonly float _hue; + + public double Hue + { + get { return _hue; } + } + + readonly float _saturation; + + public double Saturation + { + get { return _saturation; } + } + + readonly float _luminosity; + + public double Luminosity + { + get { return _luminosity; } + } + + public Color(double r, double g, double b, double a) : this(r, g, b, a, Mode.Rgb) + { + } + + Color(double w, double x, double y, double z, Mode mode) + { + _mode = mode; + switch (mode) + { + default: + case Mode.Default: + _r = _g = _b = _a = -1; + _hue = _saturation = _luminosity = -1; + break; + case Mode.Rgb: + _r = (float)w.Clamp(0, 1); + _g = (float)x.Clamp(0, 1); + _b = (float)y.Clamp(0, 1); + _a = (float)z.Clamp(0, 1); + ConvertToHsl(_r, _g, _b, mode, out _hue, out _saturation, out _luminosity); + break; + case Mode.Hsl: + _hue = (float)w.Clamp(0, 1); + _saturation = (float)x.Clamp(0, 1); + _luminosity = (float)y.Clamp(0, 1); + _a = (float)z.Clamp(0, 1); + ConvertToRgb(_hue, _saturation, _luminosity, mode, out _r, out _g, out _b); + break; + } + } + + public Color(double r, double g, double b) : this(r, g, b, 1) + { + } + + public Color(double value) : this(value, value, value, 1) + { + } + + public Color MultiplyAlpha(double alpha) + { + switch (_mode) + { + default: + case Mode.Default: + throw new InvalidOperationException("Invalid on Color.Default"); + case Mode.Rgb: + return new Color(_r, _g, _b, _a * alpha, Mode.Rgb); + case Mode.Hsl: + return new Color(_hue, _saturation, _luminosity, _a * alpha, Mode.Hsl); + } + } + + public Color AddLuminosity(double delta) + { + if (_mode == Mode.Default) + throw new InvalidOperationException("Invalid on Color.Default"); + + return new Color(_hue, _saturation, _luminosity + delta, _a, Mode.Hsl); + } + + public Color WithHue(double hue) + { + if (_mode == Mode.Default) + throw new InvalidOperationException("Invalid on Color.Default"); + return new Color(hue, _saturation, _luminosity, _a, Mode.Hsl); + } + + public Color WithSaturation(double saturation) + { + if (_mode == Mode.Default) + throw new InvalidOperationException("Invalid on Color.Default"); + return new Color(_hue, saturation, _luminosity, _a, Mode.Hsl); + } + + public Color WithLuminosity(double luminosity) + { + if (_mode == Mode.Default) + throw new InvalidOperationException("Invalid on Color.Default"); + return new Color(_hue, _saturation, luminosity, _a, Mode.Hsl); + } + + static void ConvertToRgb(float hue, float saturation, float luminosity, Mode mode, out float r, out float g, out float b) + { + if (mode != Mode.Hsl) + throw new InvalidOperationException(); + + if (luminosity == 0) + { + r = g = b = 0; + return; + } + + if (saturation == 0) + { + r = g = b = luminosity; + return; + } + float temp2 = luminosity <= 0.5f ? luminosity * (1.0f + saturation) : luminosity + saturation - luminosity * saturation; + float temp1 = 2.0f * luminosity - temp2; + + var t3 = new[] { hue + 1.0f / 3.0f, hue, hue - 1.0f / 3.0f }; + var clr = new float[] { 0, 0, 0 }; + for (var i = 0; i < 3; i++) + { + if (t3[i] < 0) + t3[i] += 1.0f; + if (t3[i] > 1) + t3[i] -= 1.0f; + if (6.0 * t3[i] < 1.0) + clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0f; + else if (2.0 * t3[i] < 1.0) + clr[i] = temp2; + else if (3.0 * t3[i] < 2.0) + clr[i] = temp1 + (temp2 - temp1) * (2.0f / 3.0f - t3[i]) * 6.0f; + else + clr[i] = temp1; + } + + r = clr[0]; + g = clr[1]; + b = clr[2]; + } + + static void ConvertToHsl(float r, float g, float b, Mode mode, out float h, out float s, out float l) + { + float v = Math.Max(r, g); + v = Math.Max(v, b); + + float m = Math.Min(r, g); + m = Math.Min(m, b); + + l = (m + v) / 2.0f; + if (l <= 0.0) + { + h = s = l = 0; + return; + } + float vm = v - m; + s = vm; + + if (s > 0.0) + { + s /= l <= 0.5f ? v + m : 2.0f - v - m; + } + else + { + h = 0; + s = 0; + return; + } + + float r2 = (v - r) / vm; + float g2 = (v - g) / vm; + float b2 = (v - b) / vm; + + if (r == v) + { + h = g == m ? 5.0f + b2 : 1.0f - g2; + } + else if (g == v) + { + h = b == m ? 1.0f + r2 : 3.0f - b2; + } + else + { + h = r == m ? 3.0f + g2 : 5.0f - r2; + } + h /= 6.0f; + } + + public static bool operator ==(Color color1, Color color2) + { + return EqualsInner(color1, color2); + } + + public static bool operator !=(Color color1, Color color2) + { + return !EqualsInner(color1, color2); + } + + public override int GetHashCode() + { + unchecked + { + int hashcode = _r.GetHashCode(); + hashcode = (hashcode * 397) ^ _g.GetHashCode(); + hashcode = (hashcode * 397) ^ _b.GetHashCode(); + hashcode = (hashcode * 397) ^ _a.GetHashCode(); + return hashcode; + } + } + + public override bool Equals(object obj) + { + if (obj is Color) + { + return EqualsInner(this, (Color)obj); + } + return base.Equals(obj); + } + + static bool EqualsInner(Color color1, Color color2) + { + if (color1._mode == Mode.Default && color2._mode == Mode.Default) + return true; + if (color1._mode == Mode.Default || color2._mode == Mode.Default) + return false; + if (color1._mode == Mode.Hsl && color2._mode == Mode.Hsl) + return color1._hue == color2._hue && color1._saturation == color2._saturation && color1._luminosity == color2._luminosity && color1._a == color2._a; + return color1._r == color2._r && color1._g == color2._g && color1._b == color2._b && color1._a == color2._a; + } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "[Color: A={0}, R={1}, G={2}, B={3}, Hue={4}, Saturation={5}, Luminosity={6}]", A, R, G, B, Hue, Saturation, Luminosity); + } + + public static Color FromHex(string hex) + { + hex = hex.Replace("#", ""); + switch (hex.Length) + { + case 3: //#rgb => ffrrggbb + hex = string.Format("ff{0}{1}{2}{3}{4}{5}", hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]); + break; + case 4: //#argb => aarrggbb + hex = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", hex[0], hex[0], hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]); + break; + case 6: //#rrggbb => ffrrggbb + hex = string.Format("ff{0}", hex); + break; + } + return FromUint(Convert.ToUInt32(hex.Replace("#", ""), 16)); + } + + public static Color FromUint(uint argb) + { + return FromRgba((byte)((argb & 0x00ff0000) >> 0x10), (byte)((argb & 0x0000ff00) >> 0x8), (byte)(argb & 0x000000ff), (byte)((argb & 0xff000000) >> 0x18)); + } + + public static Color FromRgba(int r, int g, int b, int a) + { + double red = (double)r / 255; + double green = (double)g / 255; + double blue = (double)b / 255; + double alpha = (double)a / 255; + return new Color(red, green, blue, alpha, Mode.Rgb); + } + + public static Color FromRgb(int r, int g, int b) + { + return FromRgba(r, g, b, 255); + } + + public static Color FromRgba(double r, double g, double b, double a) + { + return new Color(r, g, b, a); + } + + public static Color FromRgb(double r, double g, double b) + { + return new Color(r, g, b, 1d, Mode.Rgb); + } + + public static Color FromHsla(double h, double s, double l, double a = 1d) + { + return new Color(h, s, l, a, Mode.Hsl); + } + + #region Color Definitions + + public static readonly Color Transparent = FromRgba(0, 0, 0, 0); + public static readonly Color Aqua = FromRgb(0, 255, 255); + public static readonly Color Black = FromRgb(0, 0, 0); + public static readonly Color Blue = FromRgb(0, 0, 255); + public static readonly Color Fuchsia = FromRgb(255, 0, 255); + [Obsolete("Fuschia is obsolete as of version 1.3, please use the correct spelling of Fuchsia")] public static readonly Color Fuschia = FromRgb(255, 0, 255); + public static readonly Color Gray = FromRgb(128, 128, 128); + public static readonly Color Green = FromRgb(0, 128, 0); + public static readonly Color Lime = FromRgb(0, 255, 0); + public static readonly Color Maroon = FromRgb(128, 0, 0); + public static readonly Color Navy = FromRgb(0, 0, 128); + public static readonly Color Olive = FromRgb(128, 128, 0); + public static readonly Color Purple = FromRgb(128, 0, 128); + public static readonly Color Pink = FromRgb(255, 102, 255); + public static readonly Color Red = FromRgb(255, 0, 0); + public static readonly Color Silver = FromRgb(192, 192, 192); + public static readonly Color Teal = FromRgb(0, 128, 128); + public static readonly Color White = FromRgb(255, 255, 255); + public static readonly Color Yellow = FromRgb(255, 255, 0); + + #endregion + } +}
\ No newline at end of file |