diff --git a/src/Uno.UI/UI/ColorHelper.cs b/src/Uno.UI/UI/ColorHelper.cs
index 26c8e53f18f8..c2cec4bf8a6f 100644
--- a/src/Uno.UI/UI/ColorHelper.cs
+++ b/src/Uno.UI/UI/ColorHelper.cs
@@ -73,4 +73,347 @@ public static WindowsColor FromARGB(byte a, byte r, byte g, byte b)
/// The generated Color value.
public static WindowsColor FromArgb(byte a, byte r, byte g, byte b)
=> WindowsColor.FromArgb(a, r, g, b);
+
+ #region Resource IDs Lookup Tables
+ private static ReadOnlySpan HueLimitsForSatLevel4 =>
+ [
+ 0,
+ 11,
+ 26,
+ 0,
+ 0,
+ 38,
+ 45,
+ 0,
+ 0,
+ 56,
+ 100,
+ 121,
+ 129,
+ 0,
+ 140,
+ 0,
+ 180,
+ 0,
+ 0,
+ 224,
+ 241,
+ 0,
+ 256
+ ];
+
+ private static ReadOnlySpan HueLimitsForSatLevel5 =>
+ [
+ 0,
+ 13,
+ 27,
+ 0,
+ 0,
+ 36,
+ 45,
+ 0,
+ 0,
+ 59,
+ 118,
+ 0,
+ 127,
+ 136,
+ 142,
+ 0,
+ 185,
+ 0,
+ 0,
+ 216,
+ 239,
+ 0,
+ 256
+ ];
+
+ private static ReadOnlySpan HueLimitsForSatLevel3 =>
+ [
+ 0,
+ 8,
+ 0,
+ 0,
+ 39,
+ 46,
+ 0,
+ 0,
+ 0,
+ 71,
+ 120,
+ 0,
+ 131,
+ 144,
+ 0,
+ 0,
+ 163,
+ 0,
+ 177,
+ 211,
+ 249,
+ 0,
+ 256
+ ];
+
+ private static ReadOnlySpan HueLimitsForSatLevel2 =>
+ [
+ 0,
+ 10,
+ 0,
+ 32,
+ 46,
+ 0,
+ 0,
+ 0,
+ 61,
+ 0,
+ 106,
+ 0,
+ 136,
+ 144,
+ 0,
+ 0,
+ 0,
+ 158,
+ 166,
+ 241,
+ 0,
+ 0,
+ 256
+ ];
+
+ private static ReadOnlySpan HueLimitsForSatLevel1 =>
+ [
+ 8,
+ 0,
+ 0,
+ 44,
+ 0,
+ 0,
+ 0,
+ 63,
+ 0,
+ 0,
+ 122,
+ 0,
+ 134,
+ 0,
+ 0,
+ 0,
+ 0,
+ 166,
+ 176,
+ 241,
+ 0,
+ 256,
+ 0
+ ];
+
+ private static ReadOnlySpan LumLimitsForHueIndexHigh =>
+ [
+ 170,
+ 170,
+ 170,
+ 155,
+ 170,
+ 170,
+ 170,
+ 170,
+ 170,
+ 115,
+ 170,
+ 170,
+ 170,
+ 170,
+ 170,
+ 170,
+ 170,
+ 170,
+ 150,
+ 150,
+ 170,
+ 140,
+ 165
+ ];
+
+ private static ReadOnlySpan LumLimitsForHueIndexLow =>
+ [
+ 130,
+ 100,
+ 115,
+ 100,
+ 100,
+ 100,
+ 110,
+ 75,
+ 100,
+ 90,
+ 100,
+ 100,
+ 100,
+ 100,
+ 80,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100,
+ 100
+ ];
+
+ private static ReadOnlySpan ColorNamesMid =>
+ [
+ 5119,
+ 5135,
+ 5136,
+ 5137,
+ 5122,
+ 5138,
+ 5139,
+ 5140,
+ 5140,
+ 5141,
+ 5141,
+ 5142,
+ 5143,
+ 5126,
+ 5144,
+ 5129,
+ 5145,
+ 5146,
+ 5147,
+ 5148,
+ 5134,
+ 5137,
+ 5135
+ ];
+
+ private static ReadOnlySpan ColorNamesDark =>
+ [
+ 5137,
+ 5149,
+ 5137,
+ 5137,
+ 5137,
+ 5150,
+ 5150,
+ 5137,
+ 5151,
+ 5151,
+ 5151,
+ 5151,
+ 5152,
+ 5152,
+ 5152,
+ 5153,
+ 5153,
+ 5146,
+ 5147,
+ 5154,
+ 5155,
+ 5137,
+ 5149
+ ];
+
+ private static ReadOnlySpan ColorNamesLight =>
+ [
+ 5119,
+ 5120,
+ 5121,
+ 5122,
+ 5122,
+ 5123,
+ 5123,
+ 5122,
+ 5124,
+ 5125,
+ 5124,
+ 5124,
+ 5126,
+ 5127,
+ 5128,
+ 5129,
+ 5130,
+ 5131,
+ 5132,
+ 5133,
+ 5134,
+ 5122,
+ 5120
+ ];
+ #endregion
+
+ private unsafe static uint GetColorNameResourceId(WindowsColor color)
+ {
+ var hsl = color.ToHsl();
+ double h = hsl.H * 255.0;
+ double s = hsl.S * 255.0;
+ double l = hsl.L * 255.0;
+
+ if (l > 240.0)
+ {
+ return 5114;
+ }
+
+ if (l < 20.0)
+ {
+ return 5118;
+ }
+
+ if (s > 20.0)
+ {
+ ReadOnlySpan hueLimits;
+
+ if (s > 240.0)
+ {
+ hueLimits = HueLimitsForSatLevel5;
+ }
+ else if (s > 150.0)
+ {
+ hueLimits = HueLimitsForSatLevel4;
+ }
+ else if (s > 115.0)
+ {
+ hueLimits = HueLimitsForSatLevel3;
+ }
+ else if (s > 75.0)
+ {
+ hueLimits = HueLimitsForSatLevel2;
+ }
+ else
+ {
+ hueLimits = HueLimitsForSatLevel1;
+ }
+
+ var hueIndex = 0;
+ while (hueIndex < 23 && hueLimits[hueIndex] <= h)
+ {
+ hueIndex++;
+ }
+
+ if (l > LumLimitsForHueIndexHigh[hueIndex])
+ {
+ return ColorNamesLight[hueIndex];
+ }
+ else if (l >= LumLimitsForHueIndexLow[hueIndex])
+ {
+ return ColorNamesMid[hueIndex];
+ }
+ else
+ {
+ return ColorNamesDark[hueIndex];
+ }
+ }
+ else if (l <= 170.0)
+ {
+ return (l <= 100.0) ? (uint)5117 : 5116;
+ }
+ else
+ {
+ return 5115;
+ }
+ }
}
diff --git a/src/Uno.UWP/UI/Color.cs b/src/Uno.UWP/UI/Color.cs
index 79b5be8f4df6..f18f100218bc 100644
--- a/src/Uno.UWP/UI/Color.cs
+++ b/src/Uno.UWP/UI/Color.cs
@@ -81,6 +81,53 @@ public bool Equals(Color color) =>
internal uint AsUInt32() => _color;
+ internal HslColor ToHsl()
+ {
+ double r = R / 255.0;
+ double g = G / 255.0;
+ double b = B / 255.0;
+
+ double max = Math.Max(Math.Max(r, g), b);
+ double min = Math.Min(Math.Min(r, g), b);
+
+ double h = 0, s = 0, l = (max + min) / 2;
+ double delta = max - min;
+
+ if (Math.Abs(delta) > double.Epsilon)
+ {
+ s = delta / (l > 0.5 ? (2.0 - max - min) : (max + min));
+
+ double deltaR = (((max - r) / 6) + (delta / 2)) / delta;
+ double deltaG = (((max - g) / 6) + (delta / 2)) / delta;
+ double deltaB = (((max - b) / 6) + (delta / 2)) / delta;
+
+ if (Math.Abs(r - max) < double.Epsilon)
+ {
+ h = deltaB - deltaG;
+ }
+ else if (Math.Abs(g - max) < double.Epsilon)
+ {
+ h = (1.0 / 3.0) + deltaR - deltaB;
+ }
+ else
+ {
+ h = (2.0 / 3.0) + deltaG - deltaR;
+ }
+
+ if (h < 0)
+ {
+ h += 1;
+ }
+
+ if (h > 1)
+ {
+ h -= 1;
+ }
+ }
+
+ return new(h, s, l);
+ }
+
string IFormattable.ToString(string format, IFormatProvider formatProvider) => ToString(format, formatProvider);
private string ToString(string format, IFormatProvider formatProvider) => string.Format(formatProvider, "#{0:X2}{1:X2}{2:X2}{3:X2}", _a, _r, _g, _b);
diff --git a/src/Uno.UWP/UI/HslColor.cs b/src/Uno.UWP/UI/HslColor.cs
new file mode 100644
index 000000000000..dd43acca9c23
--- /dev/null
+++ b/src/Uno.UWP/UI/HslColor.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Windows.UI;
+
+internal struct HslColor(double h, double s, double l)
+{
+ public double H { get; set; } = h;
+ public double S { get; set; } = s;
+ public double L { get; set; } = l;
+}