| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- using System;
- using System.Windows.Media;
- namespace TeamAAS.Theme
- {
- /// <summary>
- /// 颜色派生工具:HSL 空间的明度/饱和度调整与对比度计算。
- /// 供 ThemeOverlay 做主色派生(hover 变体、暗色提亮、文字对比色),保证专业配色的可读性。
- /// </summary>
- internal static class ColorUtility
- {
- /// <summary>降低明度(0~1,如 0.12 = 深 12%),用于 hover/pressed 变体。</summary>
- public static Color Darken(Color c, double amount)
- {
- RgbToHsl(c, out double h, out double s, out double l);
- l = Clamp(l - amount);
- return HslToRgb(h, s, l, c.A);
- }
- /// <summary>提高明度(0~1),用于暗色主题下提亮主色保证对比度。</summary>
- public static Color Lighten(Color c, double amount)
- {
- RgbToHsl(c, out double h, out double s, out double l);
- l = Clamp(l + amount);
- return HslToRgb(h, s, l, c.A);
- }
- /// <summary>WCAG 相对亮度(0~1),用于对比度判定。</summary>
- public static double RelativeLuminance(Color c)
- {
- double R = Channel(c.R);
- double G = Channel(c.G);
- double B = Channel(c.B);
- return 0.2126 * R + 0.7152 * G + 0.0722 * B;
- }
- /// <summary>
- /// 按背景亮度返回可读的文字色(WCAG AA):亮背景配深字 #212121,暗背景配白字。
- /// 用于主色背景上的文字(ReverseTextColor),避免"浅色主色 + 白字"看不清。
- /// </summary>
- public static Color ContrastText(Color background)
- {
- return RelativeLuminance(background) > 0.55
- ? Color.FromRgb(0x21, 0x21, 0x21)
- : Colors.White;
- }
- private static double Channel(byte v)
- {
- double d = v / 255.0;
- return d <= 0.03928 ? d / 12.92 : Math.Pow((d + 0.055) / 1.055, 2.4);
- }
- private static void RgbToHsl(Color c, out double h, out double s, out double l)
- {
- double r = c.R / 255.0;
- double g = c.G / 255.0;
- double b = c.B / 255.0;
- double max = Math.Max(r, Math.Max(g, b));
- double min = Math.Min(r, Math.Min(g, b));
- l = (max + min) / 2.0;
- if (max - min < 1e-9)
- {
- h = 0; s = 0;
- return;
- }
- double d = max - min;
- s = l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
- if (max == r) h = (g - b) / d + (g < b ? 6.0 : 0.0);
- else if (max == g) h = (b - r) / d + 2.0;
- else h = (r - g) / d + 4.0;
- h /= 6.0;
- }
- private static Color HslToRgb(double h, double s, double l, byte alpha)
- {
- if (s < 1e-9)
- {
- byte gray = (byte)Math.Round(Clamp(l) * 255.0);
- return Color.FromArgb(alpha, gray, gray, gray);
- }
- double q = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
- double p = 2.0 * l - q;
- double r = HueToRgb(p, q, h + 1.0 / 3.0);
- double g = HueToRgb(p, q, h);
- double b = HueToRgb(p, q, h - 1.0 / 3.0);
- return Color.FromArgb(
- alpha,
- (byte)Math.Round(r * 255.0),
- (byte)Math.Round(g * 255.0),
- (byte)Math.Round(b * 255.0));
- }
- private static double HueToRgb(double p, double q, double t)
- {
- if (t < 0.0) t += 1.0;
- if (t > 1.0) t -= 1.0;
- if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;
- if (t < 1.0 / 2.0) return q;
- if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
- return p;
- }
- private static double Clamp(double v)
- {
- return v < 0.0 ? 0.0 : (v > 1.0 ? 1.0 : v);
- }
- }
- }
|