csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
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.
779 lines
30 KiB
779 lines
30 KiB
using System;
|
|
using System.Globalization;
|
|
using Avalonia.Media;
|
|
using Xunit;
|
|
|
|
namespace Avalonia.Base.UnitTests.Media
|
|
{
|
|
public class ColorTests
|
|
{
|
|
[Fact]
|
|
public void Parse_Parses_RGB_Hash_Color()
|
|
{
|
|
var result = Color.Parse("#ff8844");
|
|
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_Parses_RGB_Hash_Color()
|
|
{
|
|
var success = Color.TryParse("#ff8844", out Color result);
|
|
|
|
Assert.True(success);
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Parses_RGB_Hash_Shorthand_Color()
|
|
{
|
|
var result = Color.Parse("#f84");
|
|
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_Parses_RGB_Hash_Shorthand_Color()
|
|
{
|
|
var success = Color.TryParse("#f84", out Color result);
|
|
|
|
Assert.True(success);
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Parses_ARGB_Hash_Color()
|
|
{
|
|
var result = Color.Parse("#40ff8844");
|
|
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0x40, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_Parses_ARGB_Hash_Color()
|
|
{
|
|
var success = Color.TryParse("#40ff8844", out Color result);
|
|
|
|
Assert.True(success);
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0x40, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Parses_ARGB_Hash_Shorthand_Color()
|
|
{
|
|
var result = Color.Parse("#4f84");
|
|
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0x44, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_Parses_ARGB_Hash_Shorthand_Color()
|
|
{
|
|
var success = Color.TryParse("#4f84", out Color result);
|
|
|
|
Assert.True(success);
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x88, result.G);
|
|
Assert.Equal(0x44, result.B);
|
|
Assert.Equal(0x44, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Parses_Named_Color_Lowercase()
|
|
{
|
|
var result = Color.Parse("red");
|
|
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x00, result.G);
|
|
Assert.Equal(0x00, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParse_Parses_Named_Color_Lowercase()
|
|
{
|
|
var success = Color.TryParse("red", out Color result);
|
|
|
|
Assert.True(success);
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x00, result.G);
|
|
Assert.Equal(0x00, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Parses_Named_Color_Uppercase()
|
|
{
|
|
var result = Color.Parse("RED");
|
|
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x00, result.G);
|
|
Assert.Equal(0x00, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParse_Parses_Named_Color_Uppercase()
|
|
{
|
|
var success = Color.TryParse("RED", out Color result);
|
|
|
|
Assert.True(success);
|
|
Assert.Equal(0xff, result.R);
|
|
Assert.Equal(0x00, result.G);
|
|
Assert.Equal(0x00, result.B);
|
|
Assert.Equal(0xff, result.A);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Hex_Value_Doesnt_Accept_Too_Few_Chars()
|
|
{
|
|
Assert.Throws<FormatException>(() => Color.Parse("#ff"));
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParse_Hex_Value_Doesnt_Accept_Too_Few_Chars()
|
|
{
|
|
Assert.False(Color.TryParse("#ff", out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Hex_Value_Doesnt_Accept_Too_Many_Chars()
|
|
{
|
|
Assert.Throws<FormatException>(() => Color.Parse("#ff5555555"));
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParse_Hex_Value_Doesnt_Accept_Too_Many_Chars()
|
|
{
|
|
Assert.False(Color.TryParse("#ff5555555", out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Hex_Value_Doesnt_Accept_Invalid_Number()
|
|
{
|
|
Assert.Throws<FormatException>(() => Color.Parse("#ff808g80"));
|
|
}
|
|
|
|
[Fact]
|
|
public void TryParse_Hex_Value_Doesnt_Accept_Invalid_Number()
|
|
{
|
|
Assert.False(Color.TryParse("#ff808g80", out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Throws_ArgumentNullException_For_Null_Input()
|
|
{
|
|
Assert.Throws<ArgumentNullException>(() => Color.Parse(null!));
|
|
}
|
|
|
|
[Fact]
|
|
public void Parse_Throws_FormatException_For_Invalid_Input()
|
|
{
|
|
Assert.Throws<FormatException>(() => Color.Parse(string.Empty));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("")]
|
|
[InlineData(null)]
|
|
public void TryParse_Returns_False_For_Invalid_Input(string? input)
|
|
{
|
|
Assert.False(Color.TryParse(input, out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_HslColor()
|
|
{
|
|
// Inline data requires constants, so the data is handled internally here
|
|
var data = new Tuple<string, HslColor>[]
|
|
{
|
|
// HSV
|
|
Tuple.Create("hsl(0, 0, 0)", new HslColor(1, 0, 0, 0)),
|
|
Tuple.Create("hsl(0, 0%, 0%)", new HslColor(1, 0, 0, 0)),
|
|
Tuple.Create("hsl(180, 0.5, 0.5)", new HslColor(1, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsl(180, 50%, 50%)", new HslColor(1, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsl(360, 1.0, 1.0)", new HslColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
Tuple.Create("hsl(360, 100%, 100%)", new HslColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
|
|
Tuple.Create("hsl(-1000, -1000, -1000)", new HslColor(1, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsl(-1000, -1000%, -1000%)", new HslColor(1, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsl(1000, 1000, 1000)", new HslColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
Tuple.Create("hsl(1000, 1000%, 1000%)", new HslColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
|
|
Tuple.Create("hsl(300, 0.8, 0.2)", new HslColor(1.0, 300, 0.8, 0.2)),
|
|
Tuple.Create("hsl(300, 80%, 20%)", new HslColor(1.0, 300, 0.8, 0.2)),
|
|
|
|
// HSVA
|
|
Tuple.Create("hsla(0, 0, 0, 0)", new HslColor(0, 0, 0, 0)),
|
|
Tuple.Create("hsla(0, 0%, 0%, 0%)", new HslColor(0, 0, 0, 0)),
|
|
Tuple.Create("hsla(180, 0.5, 0.5, 0.5)", new HslColor(0.5, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsla(180, 50%, 50%, 50%)", new HslColor(0.5, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsla(360, 1.0, 1.0, 1.0)", new HslColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
Tuple.Create("hsla(360, 100%, 100%, 100%)", new HslColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
|
|
Tuple.Create("hsla(-1000, -1000, -1000, -1000)", new HslColor(0, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsla(-1000, -1000%, -1000%, -1000%)", new HslColor(0, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsla(1000, 1000, 1000, 1000)", new HslColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
Tuple.Create("hsla(1000, 1000%, 1000%, 1000%)", new HslColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
|
|
Tuple.Create("hsla(300, 0.9, 0.2, 0.8)", new HslColor(0.8, 300, 0.9, 0.2)),
|
|
Tuple.Create("hsla(300, 90%, 20%, 0.8)", new HslColor(0.8, 300, 0.9, 0.2)),
|
|
};
|
|
|
|
foreach (var dataPoint in data)
|
|
{
|
|
Assert.True(HslColor.TryParse(dataPoint.Item1, out HslColor parsedHslColor));
|
|
Assert.True(dataPoint.Item2 == parsedHslColor);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_HsvColor()
|
|
{
|
|
// Inline data requires constants, so the data is handled internally here
|
|
var data = new Tuple<string, HsvColor>[]
|
|
{
|
|
// HSV
|
|
Tuple.Create("hsv(0, 0, 0)", new HsvColor(1, 0, 0, 0)),
|
|
Tuple.Create("hsv(0, 0%, 0%)", new HsvColor(1, 0, 0, 0)),
|
|
Tuple.Create("hsv(180, 0.5, 0.5)", new HsvColor(1, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsv(180, 50%, 50%)", new HsvColor(1, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsv(360, 1.0, 1.0)", new HsvColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
Tuple.Create("hsv(360, 100%, 100%)", new HsvColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
|
|
Tuple.Create("hsv(-1000, -1000, -1000)", new HsvColor(1, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsv(-1000, -1000%, -1000%)", new HsvColor(1, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsv(1000, 1000, 1000)", new HsvColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
Tuple.Create("hsv(1000, 1000%, 1000%)", new HsvColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
|
|
Tuple.Create("hsv(300, 0.8, 0.2)", new HsvColor(1.0, 300, 0.8, 0.2)),
|
|
Tuple.Create("hsv(300, 80%, 20%)", new HsvColor(1.0, 300, 0.8, 0.2)),
|
|
|
|
// HSVA
|
|
Tuple.Create("hsva(0, 0, 0, 0)", new HsvColor(0, 0, 0, 0)),
|
|
Tuple.Create("hsva(0, 0%, 0%, 0%)", new HsvColor(0, 0, 0, 0)),
|
|
Tuple.Create("hsva(180, 0.5, 0.5, 0.5)", new HsvColor(0.5, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsva(180, 50%, 50%, 50%)", new HsvColor(0.5, 180, 0.5, 0.5)),
|
|
Tuple.Create("hsva(360, 1.0, 1.0, 1.0)", new HsvColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
Tuple.Create("hsva(360, 100%, 100%, 100%)", new HsvColor(1, 0, 1, 1)), // Wraps Hue to zero
|
|
|
|
Tuple.Create("hsva(-1000, -1000, -1000, -1000)", new HsvColor(0, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsva(-1000, -1000%, -1000%, -1000%)", new HsvColor(0, 0, 0, 0)), // Clamps to min
|
|
Tuple.Create("hsva(1000, 1000, 1000, 1000)", new HsvColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
Tuple.Create("hsva(1000, 1000%, 1000%, 1000%)", new HsvColor(1, 0, 1, 1)), // Clamps to max (Hue wraps to zero)
|
|
|
|
Tuple.Create("hsva(300, 0.9, 0.2, 0.8)", new HsvColor(0.8, 300, 0.9, 0.2)),
|
|
Tuple.Create("hsva(300, 90%, 20%, 0.8)", new HsvColor(0.8, 300, 0.9, 0.2)),
|
|
};
|
|
|
|
foreach (var dataPoint in data)
|
|
{
|
|
Assert.True(HsvColor.TryParse(dataPoint.Item1, out HsvColor parsedHsvColor));
|
|
Assert.True(dataPoint.Item2 == parsedHsvColor);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Try_Parse_All_Formats_With_Conversion()
|
|
{
|
|
// Inline data requires constants, so the data is handled internally here
|
|
var data = new Tuple<string, Color>[]
|
|
{
|
|
// RGB
|
|
Tuple.Create("White", new Color(0xff, 0xff, 0xff, 0xff)),
|
|
Tuple.Create("#123456", new Color(0xff, 0x12, 0x34, 0x56)),
|
|
|
|
Tuple.Create("rgb(100, 30, 45)", new Color(255, 100, 30, 45)),
|
|
Tuple.Create("rgba(100, 30, 45, 0.9)", new Color(230, 100, 30, 45)),
|
|
Tuple.Create("rgba(100, 30, 45, 90%)", new Color(230, 100, 30, 45)),
|
|
|
|
Tuple.Create("rgb(255,0,0)", new Color(255, 255, 0, 0)),
|
|
Tuple.Create("rgb(0,255,0)", new Color(255, 0, 255, 0)),
|
|
Tuple.Create("rgb(0,0,255)", new Color(255, 0, 0, 255)),
|
|
|
|
Tuple.Create("rgb(100%, 0, 0)", new Color(255, 255, 0, 0)),
|
|
Tuple.Create("rgb(0, 100%, 0)", new Color(255, 0, 255, 0)),
|
|
Tuple.Create("rgb(0, 0, 100%)", new Color(255, 0, 0, 255)),
|
|
|
|
Tuple.Create("rgba(0, 0, 100%, 50%)", new Color(128, 0, 0, 255)),
|
|
Tuple.Create("rgba(50%, 10%, 80%, 50%)", new Color(128, 128, 26, 204)),
|
|
Tuple.Create("rgba(50%, 10%, 80%, 0.5)", new Color(128, 128, 26, 204)),
|
|
|
|
// HSL
|
|
Tuple.Create("hsl(296, 85%, 12%)", new Color(255, 53, 5, 57)),
|
|
Tuple.Create("hsla(296, 0.85, 0.12, 0.9)", new Color(230, 53, 5, 57)),
|
|
Tuple.Create("hsla(296, 85%, 12%, 90%)", new Color(230, 53, 5, 57)),
|
|
|
|
// HSV
|
|
Tuple.Create("hsv(240, 83%, 78%)", new Color(255, 34, 34, 199)),
|
|
Tuple.Create("hsva(240, 0.83, 0.78, 0.9)", new Color(230, 34, 34, 199)),
|
|
Tuple.Create("hsva(240, 83%, 78%, 90%)", new Color(230, 34, 34, 199)),
|
|
};
|
|
|
|
foreach (var dataPoint in data)
|
|
{
|
|
Assert.True(Color.TryParse(dataPoint.Item1, out Color parsedColor));
|
|
Assert.True(dataPoint.Item2 == parsedColor);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Hsv_To_From_Hsl_Conversion()
|
|
{
|
|
// Note that conversion of values more representative of actual colors is not done due to rounding error
|
|
// It would be necessary to introduce a different equality comparison that accounts for rounding differences in values
|
|
// This is a result of the math in the conversion itself
|
|
// RGB doesn't have this problem because it uses whole numbers
|
|
var data = new Tuple<HsvColor, HslColor>[]
|
|
{
|
|
Tuple.Create(new HsvColor(1.0, 0.0, 0.0, 0.0), new HslColor(1.0, 0.0, 0.0, 0.0)),
|
|
Tuple.Create(new HsvColor(1.0, 359.0, 1.0, 1.0), new HslColor(1.0, 359.0, 1.0, 0.5)),
|
|
|
|
Tuple.Create(new HsvColor(1.0, 128.0, 0.0, 0.0), new HslColor(1.0, 128.0, 0.0, 0.0)),
|
|
Tuple.Create(new HsvColor(1.0, 128.0, 0.0, 1.0), new HslColor(1.0, 128.0, 0.0, 1.0)),
|
|
Tuple.Create(new HsvColor(1.0, 128.0, 1.0, 1.0), new HslColor(1.0, 128.0, 1.0, 0.5)),
|
|
|
|
Tuple.Create(new HsvColor(0.23, 0.5, 1.0, 1.0), new HslColor(0.23, 0.5, 1.0, 0.5)),
|
|
};
|
|
|
|
foreach (var dataPoint in data)
|
|
{
|
|
var convertedHsl = dataPoint.Item1.ToHsl();
|
|
var convertedHsv = dataPoint.Item2.ToHsv();
|
|
|
|
Assert.Equal(convertedHsv, dataPoint.Item1);
|
|
Assert.Equal(convertedHsl, dataPoint.Item2);
|
|
}
|
|
}
|
|
// =====================================================================
|
|
// IFormattable unified format specifier tests
|
|
//
|
|
// All three color types (Color, HslColor, HsvColor) support ALL
|
|
// format specifiers. Cross-model formats auto-convert.
|
|
//
|
|
// Convention:
|
|
// Uppercase = include alpha, a-suffixed prefix (rgba, hsla, hsva)
|
|
// Lowercase = exclude alpha, plain prefix (rgb, hsl, hsv)
|
|
// "%" suffix = percent mode
|
|
// =====================================================================
|
|
|
|
[Fact]
|
|
public void Color_ToString_Default_Returns_KnownName()
|
|
{
|
|
var red = new Color(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
Assert.Equal("Red", red.ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_Default_Returns_Hex_For_Unknown()
|
|
{
|
|
var color = new Color(0x40, 0xFF, 0x88, 0x44);
|
|
|
|
Assert.Equal("#40ff8844", color.ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_Null_Format_Matches_Default()
|
|
{
|
|
var color = new Color(0x40, 0xFF, 0x88, 0x44);
|
|
|
|
Assert.Equal(color.ToString(), color.ToString(null, null));
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_Empty_Format_Matches_Default()
|
|
{
|
|
var color = new Color(0x40, 0xFF, 0x88, 0x44);
|
|
|
|
Assert.Equal(color.ToString(), color.ToString("", null));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_Null_Format_Matches_Default()
|
|
{
|
|
var color = new HslColor(0.8, 200, 0.6, 0.4);
|
|
|
|
Assert.Equal(color.ToString(), color.ToString(null, null));
|
|
}
|
|
|
|
[Fact]
|
|
public void HsvColor_ToString_Null_Format_Matches_Default()
|
|
{
|
|
var color = new HsvColor(0.8, 200, 0.6, 0.4);
|
|
|
|
Assert.Equal(color.ToString(), color.ToString(null, null));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x88, 0x44, "#FFFF8844")]
|
|
[InlineData(0x40, 0xFF, 0x88, 0x44, "#40FF8844")]
|
|
[InlineData(0xFF, 0x00, 0x00, 0x00, "#FF000000")]
|
|
[InlineData(0x00, 0x00, 0x00, 0x00, "#00000000")]
|
|
public void Color_ToString_X_Returns_Xaml_Hex_With_Alpha(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("X", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x88, 0x44, "#FF8844")]
|
|
[InlineData(0x40, 0xFF, 0x88, 0x44, "#FF8844")]
|
|
[InlineData(0x00, 0x00, 0x00, 0x00, "#000000")]
|
|
public void Color_ToString_x_Returns_Hex_Without_Alpha(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("x", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x88, 0x44, "#FF8844FF")]
|
|
[InlineData(0x40, 0xFF, 0x88, 0x44, "#FF884440")]
|
|
[InlineData(0x00, 0x00, 0x00, 0x00, "#00000000")]
|
|
public void Color_ToString_H_Returns_Html_Hex_With_Alpha(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("H", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_X_Converts_To_Rgb_Hex()
|
|
{
|
|
// Pure red: HSL(0, 1, 0.5) = RGB(255, 0, 0)
|
|
var hsl = new HslColor(1.0, 0, 1.0, 0.5);
|
|
|
|
Assert.Equal("#FFFF0000", hsl.ToString("X", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_x_Converts_To_Rgb_Hex()
|
|
{
|
|
var hsl = new HslColor(1.0, 0, 1.0, 0.5);
|
|
|
|
Assert.Equal("#FF0000", hsl.ToString("x", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HsvColor_ToString_X_Converts_To_Rgb_Hex()
|
|
{
|
|
// Pure red: HSV(0, 1, 1) = RGB(255, 0, 0)
|
|
var hsv = new HsvColor(1.0, 0, 1.0, 1.0);
|
|
|
|
Assert.Equal("#FFFF0000", hsv.ToString("X", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HsvColor_ToString_x_Converts_To_Rgb_Hex()
|
|
{
|
|
var hsv = new HsvColor(1.0, 0, 1.0, 1.0);
|
|
|
|
Assert.Equal("#FF0000", hsv.ToString("x", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x88, 0x44, "rgba(255, 136, 68, 1.00)")]
|
|
[InlineData(0x80, 0xFF, 0x88, 0x44, "rgba(255, 136, 68, 0.50)")]
|
|
[InlineData(0x00, 0x00, 0x00, 0x00, "rgba(0, 0, 0, 0.00)")]
|
|
public void Color_ToString_R_Returns_Rgba_With_Alpha(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("R", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x88, 0x44, "rgb(255, 136, 68)")]
|
|
[InlineData(0x80, 0xFF, 0x88, 0x44, "rgb(255, 136, 68)")]
|
|
[InlineData(0xFF, 0x00, 0x00, 0x00, "rgb(0, 0, 0)")]
|
|
public void Color_ToString_r_Returns_Rgb_Without_Alpha(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("r", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_R_Converts_To_Rgba()
|
|
{
|
|
// Pure blue: HSL(240, 1, 0.5) = RGB(0, 0, 255)
|
|
var hsl = new HslColor(1.0, 240, 1.0, 0.5);
|
|
|
|
Assert.Equal("rgba(0, 0, 255, 1.00)", hsl.ToString("R", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HsvColor_ToString_r_Converts_To_Rgb()
|
|
{
|
|
// Pure red: HSV(0, 1, 1) = RGB(255, 0, 0)
|
|
var hsv = new HsvColor(1.0, 0, 1.0, 1.0);
|
|
|
|
Assert.Equal("rgb(255, 0, 0)", hsv.ToString("r", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x80, 0x00, "rgba(100%, 50%, 0%, 100%)")]
|
|
[InlineData(0x80, 0xFF, 0x80, 0x00, "rgba(100%, 50%, 0%, 50%)")]
|
|
[InlineData(0x00, 0x00, 0x00, 0x00, "rgba(0%, 0%, 0%, 0%)")]
|
|
public void Color_ToString_RPct_Returns_Rgba_Percent(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("R%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0xFF, 0xFF, 0x80, 0x00, "rgb(100%, 50%, 0%)")]
|
|
[InlineData(0x80, 0xFF, 0x80, 0x00, "rgb(100%, 50%, 0%)")]
|
|
[InlineData(0xFF, 0x00, 0x00, 0x00, "rgb(0%, 0%, 0%)")]
|
|
public void Color_ToString_rPct_Returns_Rgb_Percent(byte a, byte r, byte g, byte b, string expected)
|
|
{
|
|
var color = new Color(a, r, g, b);
|
|
|
|
Assert.Equal(expected, color.ToString("r%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_RPct_Converts_To_Rgba_Percent()
|
|
{
|
|
// Pure red: HSL(0, 1, 0.5) = RGB(255, 0, 0)
|
|
var hsl = new HslColor(1.0, 0, 1.0, 0.5);
|
|
|
|
Assert.Equal("rgba(100%, 0%, 0%, 100%)", hsl.ToString("R%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsla(180, 50%, 50%, 1.00)")]
|
|
[InlineData(0.5, 240, 0.8, 0.2, "hsla(240, 80%, 20%, 0.50)")]
|
|
[InlineData(0.0, 0, 0.0, 0.0, "hsla(0, 0%, 0%, 0.00)")]
|
|
public void HslColor_ToString_L_Returns_Hsla_With_Alpha(double a, double h, double s, double l, string expected)
|
|
{
|
|
var color = new HslColor(a, h, s, l);
|
|
|
|
Assert.Equal(expected, color.ToString("L", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsl(180, 50%, 50%)")]
|
|
[InlineData(0.5, 240, 0.8, 0.2, "hsl(240, 80%, 20%)")]
|
|
[InlineData(0.0, 0, 0.0, 0.0, "hsl(0, 0%, 0%)")]
|
|
public void HslColor_ToString_l_Returns_Hsl_Without_Alpha(double a, double h, double s, double l, string expected)
|
|
{
|
|
var color = new HslColor(a, h, s, l);
|
|
|
|
Assert.Equal(expected, color.ToString("l", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_L_Converts_To_Hsla()
|
|
{
|
|
// Pure red: RGB(255, 0, 0) = HSL(0, 100%, 50%)
|
|
var color = new Color(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
Assert.Equal("hsla(0, 100%, 50%, 1.00)", color.ToString("L", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_l_Converts_To_Hsl()
|
|
{
|
|
var color = new Color(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
Assert.Equal("hsl(0, 100%, 50%)", color.ToString("l", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HsvColor_ToString_L_Converts_To_Hsla()
|
|
{
|
|
// Pure red: HSV(0, 1, 1) = HSL(0, 100%, 50%)
|
|
var hsv = new HsvColor(1.0, 0, 1.0, 1.0);
|
|
|
|
Assert.Equal("hsla(0, 100%, 50%, 1.00)", hsv.ToString("L", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsla(50%, 50%, 50%, 100%)")]
|
|
[InlineData(0.5, 90, 1.0, 1.0, "hsla(25%, 100%, 100%, 50%)")]
|
|
[InlineData(1.0, 0, 0.0, 0.0, "hsla(0%, 0%, 0%, 100%)")]
|
|
public void HslColor_ToString_LPct_Returns_Hsla_All_Percent(double a, double h, double s, double l, string expected)
|
|
{
|
|
var color = new HslColor(a, h, s, l);
|
|
|
|
Assert.Equal(expected, color.ToString("L%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsl(50%, 50%, 50%)")]
|
|
[InlineData(0.5, 90, 1.0, 1.0, "hsl(25%, 100%, 100%)")]
|
|
[InlineData(1.0, 0, 0.0, 0.0, "hsl(0%, 0%, 0%)")]
|
|
public void HslColor_ToString_lPct_Returns_Hsl_All_Percent(double a, double h, double s, double l, string expected)
|
|
{
|
|
var color = new HslColor(a, h, s, l);
|
|
|
|
Assert.Equal(expected, color.ToString("l%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsva(180, 50%, 50%, 1.00)")]
|
|
[InlineData(0.5, 240, 0.8, 0.2, "hsva(240, 80%, 20%, 0.50)")]
|
|
[InlineData(0.0, 0, 0.0, 0.0, "hsva(0, 0%, 0%, 0.00)")]
|
|
public void HsvColor_ToString_V_Returns_Hsva_With_Alpha(double a, double h, double s, double v, string expected)
|
|
{
|
|
var color = new HsvColor(a, h, s, v);
|
|
|
|
Assert.Equal(expected, color.ToString("V", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsv(180, 50%, 50%)")]
|
|
[InlineData(0.5, 240, 0.8, 0.2, "hsv(240, 80%, 20%)")]
|
|
[InlineData(0.0, 0, 0.0, 0.0, "hsv(0, 0%, 0%)")]
|
|
public void HsvColor_ToString_v_Returns_Hsv_Without_Alpha(double a, double h, double s, double v, string expected)
|
|
{
|
|
var color = new HsvColor(a, h, s, v);
|
|
|
|
Assert.Equal(expected, color.ToString("v", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_V_Converts_To_Hsva()
|
|
{
|
|
// Pure red: RGB(255, 0, 0) = HSV(0, 100%, 100%)
|
|
var color = new Color(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
Assert.Equal("hsva(0, 100%, 100%, 1.00)", color.ToString("V", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_V_Converts_To_Hsva()
|
|
{
|
|
// Pure red: HSL(0, 1, 0.5) = HSV(0, 100%, 100%)
|
|
var hsl = new HslColor(1.0, 0, 1.0, 0.5);
|
|
|
|
Assert.Equal("hsva(0, 100%, 100%, 1.00)", hsl.ToString("V", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsva(50%, 50%, 50%, 100%)")]
|
|
[InlineData(0.5, 90, 1.0, 1.0, "hsva(25%, 100%, 100%, 50%)")]
|
|
[InlineData(1.0, 0, 0.0, 0.0, "hsva(0%, 0%, 0%, 100%)")]
|
|
public void HsvColor_ToString_VPct_Returns_Hsva_All_Percent(double a, double h, double s, double v, string expected)
|
|
{
|
|
var color = new HsvColor(a, h, s, v);
|
|
|
|
Assert.Equal(expected, color.ToString("V%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1.0, 180, 0.5, 0.5, "hsv(50%, 50%, 50%)")]
|
|
[InlineData(0.5, 90, 1.0, 1.0, "hsv(25%, 100%, 100%)")]
|
|
[InlineData(1.0, 0, 0.0, 0.0, "hsv(0%, 0%, 0%)")]
|
|
public void HsvColor_ToString_vPct_Returns_Hsv_All_Percent(double a, double h, double s, double v, string expected)
|
|
{
|
|
var color = new HsvColor(a, h, s, v);
|
|
|
|
Assert.Equal(expected, color.ToString("v%", CultureInfo.InvariantCulture));
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_Invalid_Format_Throws()
|
|
{
|
|
var color = new Color(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
Assert.Throws<FormatException>(() => color.ToString("Z", null));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_Invalid_Format_Throws()
|
|
{
|
|
var color = new HslColor(1.0, 0, 0, 0);
|
|
|
|
Assert.Throws<FormatException>(() => color.ToString("Z", null));
|
|
}
|
|
|
|
[Fact]
|
|
public void HsvColor_ToString_Invalid_Format_Throws()
|
|
{
|
|
var color = new HsvColor(1.0, 0, 0, 0);
|
|
|
|
Assert.Throws<FormatException>(() => color.ToString("Z", null));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("C")]
|
|
[InlineData("c")]
|
|
[InlineData("A")]
|
|
[InlineData("a")]
|
|
[InlineData("P")]
|
|
[InlineData("h")]
|
|
public void Color_ToString_Reserved_And_Removed_Specifiers_Throw(string format)
|
|
{
|
|
var color = new Color(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
Assert.Throws<FormatException>(() => color.ToString(format, null));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("C")]
|
|
[InlineData("c")]
|
|
public void HslColor_ToString_Reserved_C_Throws(string format)
|
|
{
|
|
var color = new HslColor(1.0, 0, 1.0, 0.5);
|
|
|
|
Assert.Throws<FormatException>(() => color.ToString(format, null));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("C")]
|
|
[InlineData("c")]
|
|
public void HsvColor_ToString_Reserved_C_Throws(string format)
|
|
{
|
|
var color = new HsvColor(1.0, 0, 1.0, 1.0);
|
|
|
|
Assert.Throws<FormatException>(() => color.ToString(format, null));
|
|
}
|
|
|
|
[Fact]
|
|
public void Color_ToString_IFormatProvider_Is_Ignored()
|
|
{
|
|
var color = new Color(0x80, 0xFF, 0x88, 0x44);
|
|
var french = CultureInfo.GetCultureInfo("fr-FR");
|
|
|
|
Assert.Equal(
|
|
color.ToString("R", CultureInfo.InvariantCulture),
|
|
color.ToString("R", french));
|
|
}
|
|
|
|
[Fact]
|
|
public void HslColor_ToString_IFormatProvider_Is_Ignored()
|
|
{
|
|
var color = new HslColor(0.5, 180, 0.5, 0.5);
|
|
var french = CultureInfo.GetCultureInfo("fr-FR");
|
|
|
|
Assert.Equal(
|
|
color.ToString("L", CultureInfo.InvariantCulture),
|
|
color.ToString("L", french));
|
|
}
|
|
}
|
|
}
|
|
|