Browse Source

Add ToString/Parse to HslColor

pull/7951/head
robloo 5 years ago
parent
commit
8569d527ac
  1. 140
      src/Avalonia.Visuals/Media/HslColor.cs

140
src/Avalonia.Visuals/Media/HslColor.cs

@ -169,6 +169,146 @@ namespace Avalonia.Media
return HslColor.ToRgb(H, S, L, A); return HslColor.ToRgb(H, S, L, A);
} }
/// <inheritdoc/>
public override string ToString()
{
var sb = new StringBuilder();
// Use a format similar to CSS. However:
// - To ensure precision is never lost, allow decimal places.
// This is especially important for round-trip serialization.
// - To maintain numerical consistency, do not use percent.
//
// Example:
//
// hsla(hue, saturation, lightness, alpha)
// hsla(230, 1.0, 0.5, 1.0)
//
sb.Append("hsva(");
sb.Append(H.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(S.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(L.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(A.ToString(CultureInfo.InvariantCulture));
sb.Append(')');
return sb.ToString();
}
/// <summary>
/// Parses an HSL color string.
/// </summary>
/// <param name="s">The HSL color string to parse.</param>
/// <returns>The parsed <see cref="HslColor"/>.</returns>
public static HslColor Parse(string s)
{
if (s is null)
{
throw new ArgumentNullException(nameof(s));
}
if (TryParse(s, out HslColor hslColor))
{
return hslColor;
}
throw new FormatException($"Invalid HSL color string: '{s}'.");
}
/// <summary>
/// Parses an HSL color string.
/// </summary>
/// <param name="s">The HSL color string to parse.</param>
/// <param name="hslColor">The parsed <see cref="HslColor"/>.</param>
/// <returns>True if parsing was successful; otherwise, false.</returns>
public static bool TryParse(string s, out HslColor hslColor)
{
hslColor = default;
if (s is null)
{
return false;
}
string workingString = s.Trim();
if (workingString.Length == 0 ||
workingString.IndexOf(",", StringComparison.Ordinal) < 0)
{
return false;
}
if (workingString.Length > 6 &&
workingString.StartsWith("hsla(", StringComparison.OrdinalIgnoreCase) &&
workingString.EndsWith(")", StringComparison.Ordinal))
{
workingString = workingString.Substring(5, workingString.Length - 6);
}
if (workingString.Length > 5 &&
workingString.StartsWith("hsl(", StringComparison.OrdinalIgnoreCase) &&
workingString.EndsWith(")", StringComparison.Ordinal))
{
workingString = workingString.Substring(4, workingString.Length - 5);
}
string[] components = workingString.Split(',');
if (components.Length == 3) // HSL
{
if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
TryInternalParse(components[1], out double saturation) &&
TryInternalParse(components[2], out double lightness))
{
hslColor = new HslColor(1.0, hue, saturation, lightness);
return true;
}
}
else if (components.Length == 4) // HSLA
{
if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
TryInternalParse(components[1], out double saturation) &&
TryInternalParse(components[2], out double lightness) &&
TryInternalParse(components[3], out double alpha))
{
hslColor = new HslColor(alpha, hue, saturation, lightness);
return true;
}
}
// Local function to specially parse a double value with an optional percentage sign
bool TryInternalParse(string inString, out double outDouble)
{
// The percent sign, if it exists, must be at the end of the number
int percentIndex = inString.IndexOf("%", StringComparison.Ordinal);
if (percentIndex >= 0)
{
var result = double.TryParse(
inString.Substring(0, percentIndex),
NumberStyles.Number,
CultureInfo.InvariantCulture,
out double percentage);
outDouble = percentage / 100.0;
return result;
}
else
{
return double.TryParse(
inString,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out outDouble);
}
}
return false;
}
/// <summary> /// <summary>
/// Creates a new <see cref="HslColor"/> from individual color component values. /// Creates a new <see cref="HslColor"/> from individual color component values.
/// </summary> /// </summary>

Loading…
Cancel
Save