A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

223 lines
6.5 KiB

using System;
using System.Globalization;
using Avalonia.Animation.Animators;
namespace Avalonia.Media
{
/// <summary>
/// An ARGB color.
/// </summary>
public readonly struct Color : IEquatable<Color>
{
static Color()
{
Animation.Animation.RegisterAnimator<ColorAnimator>(prop => typeof(Color).IsAssignableFrom(prop.PropertyType));
}
/// <summary>
/// Gets the Alpha component of the color.
/// </summary>
public byte A { get; }
/// <summary>
/// Gets the Red component of the color.
/// </summary>
public byte R { get; }
/// <summary>
/// Gets the Green component of the color.
/// </summary>
public byte G { get; }
/// <summary>
/// Gets the Blue component of the color.
/// </summary>
public byte B { get; }
public Color(byte a, byte r, byte g, byte b)
{
A = a;
R = r;
G = g;
B = b;
}
/// <summary>
/// Creates a <see cref="Color"/> from alpha, red, green and blue components.
/// </summary>
/// <param name="a">The alpha component.</param>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The color.</returns>
public static Color FromArgb(byte a, byte r, byte g, byte b)
{
return new Color(a, r, g, b);
}
/// <summary>
/// Creates a <see cref="Color"/> from red, green and blue components.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The color.</returns>
public static Color FromRgb(byte r, byte g, byte b)
{
return new Color(0xff, r, g, b);
}
/// <summary>
/// Creates a <see cref="Color"/> from an integer.
/// </summary>
/// <param name="value">The integer value.</param>
/// <returns>The color.</returns>
public static Color FromUInt32(uint value)
{
return new Color(
(byte)((value >> 24) & 0xff),
(byte)((value >> 16) & 0xff),
(byte)((value >> 8) & 0xff),
(byte)(value & 0xff)
);
}
/// <summary>
/// Parses a color string.
/// </summary>
/// <param name="s">The color string.</param>
/// <returns>The <see cref="Color"/>.</returns>
public static Color Parse(string s)
{
if (s == null) throw new ArgumentNullException(nameof(s));
if (s.Length == 0) throw new FormatException();
if (s[0] == '#')
{
var or = 0u;
if (s.Length == 7)
{
or = 0xff000000;
}
else if (s.Length != 9)
{
throw new FormatException($"Invalid color string: '{s}'.");
}
return FromUInt32(uint.Parse(s.Substring(1), NumberStyles.HexNumber, CultureInfo.InvariantCulture) | or);
}
var knownColor = KnownColors.GetKnownColor(s);
if (knownColor != KnownColor.None)
{
return knownColor.ToColor();
}
throw new FormatException($"Invalid color string: '{s}'.");
}
/// <summary>
/// Parses a color string.
/// </summary>
/// <param name="s">The color string.</param>
/// <param name="color">The parsed color</param>
/// <returns>The status of the operation.</returns>
public static bool TryParse(ReadOnlySpan<char> s, out Color color)
{
color = default;
if (s == null)
return false;
if (s.Length == 0)
return false;
if (s[0] == '#')
{
var or = 0u;
if (s.Length == 7)
{
or = 0xff000000;
}
else if (s.Length != 9)
{
return false;
}
if(!uint.TryParse(s.Slice(1).ToString(), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var parsed))
return false;
color = FromUInt32(parsed| or);
return true;
}
var knownColor = KnownColors.GetKnownColor(s.ToString());
if (knownColor != KnownColor.None)
{
color = knownColor.ToColor();
return true;
}
return false;
}
/// <summary>
/// Returns the string representation of the color.
/// </summary>
/// <returns>
/// The string representation of the color.
/// </returns>
public override string ToString()
{
uint rgb = ToUint32();
return KnownColors.GetKnownColorName(rgb) ?? $"#{rgb:x8}";
}
/// <summary>
/// Returns the integer representation of the color.
/// </summary>
/// <returns>
/// The integer representation of the color.
/// </returns>
public uint ToUint32()
{
return ((uint)A << 24) | ((uint)R << 16) | ((uint)G << 8) | (uint)B;
}
/// <summary>
/// Check if two colors are equal.
/// </summary>
public bool Equals(Color other)
{
return A == other.A && R == other.R && G == other.G && B == other.B;
}
public override bool Equals(object obj)
{
return obj is Color other && Equals(other);
}
public override int GetHashCode()
{
unchecked
{
int hashCode = A.GetHashCode();
hashCode = (hashCode * 397) ^ R.GetHashCode();
hashCode = (hashCode * 397) ^ G.GetHashCode();
hashCode = (hashCode * 397) ^ B.GetHashCode();
return hashCode;
}
}
public static bool operator ==(Color left, Color right)
{
return left.Equals(right);
}
public static bool operator !=(Color left, Color right)
{
return !left.Equals(right);
}
}
}