using System;
using System.Drawing;
namespace Microsoft.Windows.Forms
{
public static partial class RenderEngine
{
///
/// 色调,亮度,饱和度颜色
///
private struct HLSColor
{
private const int ShadowAdj = -333;
private const int HilightAdj = 500;
private const int WatermarkAdj = -50;
private const int Range = 240;
private const int HLSMax = Range;
private const int RGBMax = 255;
private const int Undefined = HLSMax * 2 / 3;
private int hue;
private int saturation;
private int luminosity;
private bool isSystemColors_Control;
///
/// 构造函数
///
/// RGBA颜色
public HLSColor(Color color)
{
isSystemColors_Control = (color.ToKnownColor() == SystemColors.Control.ToKnownColor());
int r = color.R;
int g = color.G;
int b = color.B;
int max, min; /* max and min RGB values */
int sum, dif;
int Rdelta, Gdelta, Bdelta; /* intermediate value: % of spread from max */
/* calculate lightness */
max = Math.Max(Math.Max(r, g), b);
min = Math.Min(Math.Min(r, g), b);
sum = max + min;
luminosity = (((sum * HLSMax) + RGBMax) / (2 * RGBMax));
dif = max - min;
if (dif == 0)
{ /* r=g=b --> achromatic case */
saturation = 0; /* saturation */
hue = Undefined; /* hue */
}
else
{ /* chromatic case */
/* saturation */
if (luminosity <= (HLSMax / 2))
saturation = (int)(((dif * (int)HLSMax) + (sum / 2)) / sum);
else
saturation = (int)((int)((dif * (int)HLSMax) + (int)((2 * RGBMax - sum) / 2))
/ (2 * RGBMax - sum));
/* hue */
Rdelta = (int)((((max - r) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
Gdelta = (int)((((max - g) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
Bdelta = (int)((((max - b) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
if ((int)r == max)
hue = Bdelta - Gdelta;
else if ((int)g == max)
hue = (HLSMax / 3) + Rdelta - Bdelta;
else /* B == cMax */
hue = ((2 * HLSMax) / 3) + Gdelta - Rdelta;
if (hue < 0)
hue += HLSMax;
if (hue > HLSMax)
hue -= HLSMax;
}
}
///
/// 色调
///
public int Hue
{
get
{
return hue;
}
}
///
/// 亮度
///
public int Luminosity
{
get
{
return luminosity;
}
}
///
/// 饱和度
///
public int Saturation
{
get
{
return saturation;
}
}
///
/// 获取减小指定亮度后的颜色
///
/// 要减小的亮度
/// 新的颜色
public Color Darker(float percDarker)
{
if (isSystemColors_Control)
{
// With the usual color scheme, ControlDark/DarkDark is not exactly
// what we would otherwise calculate
if (percDarker == 0.0f)
{
return SystemColors.ControlDark;
}
else if (percDarker == 1.0f)
{
return SystemColors.ControlDarkDark;
}
else
{
Color dark = SystemColors.ControlDark;
Color darkDark = SystemColors.ControlDarkDark;
int dr = dark.R - darkDark.R;
int dg = dark.G - darkDark.G;
int db = dark.B - darkDark.B;
return Color.FromArgb((byte)(dark.R - (byte)(dr * percDarker)),
(byte)(dark.G - (byte)(dg * percDarker)),
(byte)(dark.B - (byte)(db * percDarker)));
}
}
else
{
int oneLum = 0;
int zeroLum = NewLuma(ShadowAdj, true);
return ColorFromHLS(hue, zeroLum - (int)((zeroLum - oneLum) * percDarker), saturation);
}
}
///
/// 是否相等
///
/// 要比较的对象
/// 相等返回true,否则返回false
public override bool Equals(object o)
{
if (!(o is HLSColor))
{
return false;
}
HLSColor c = (HLSColor)o;
return hue == c.hue &&
saturation == c.saturation &&
luminosity == c.luminosity &&
isSystemColors_Control == c.isSystemColors_Control;
}
///
/// 是否相等
///
/// 颜色a
/// 颜色b
/// 相等返回true,否则返回false
public static bool operator ==(HLSColor a, HLSColor b)
{
return a.Equals(b);
}
///
/// 是否不等
///
/// 颜色a
/// 颜色b
/// 不等返回true,否则返回false
public static bool operator !=(HLSColor a, HLSColor b)
{
return !a.Equals(b);
}
///
/// 获取哈希码
///
/// 哈希码
public override int GetHashCode()
{
return hue << 6 | saturation << 2 | luminosity;
}
///
/// 获取增加指定亮度后的颜色
///
/// 要增加的亮度
/// 新的颜色
public Color Lighter(float percLighter)
{
if (isSystemColors_Control)
{
// With the usual color scheme, ControlLight/LightLight is not exactly
// what we would otherwise calculate
if (percLighter == 0.0f)
{
return SystemColors.ControlLight;
}
else if (percLighter == 1.0f)
{
return SystemColors.ControlLightLight;
}
else
{
Color light = SystemColors.ControlLight;
Color lightLight = SystemColors.ControlLightLight;
int dr = light.R - lightLight.R;
int dg = light.G - lightLight.G;
int db = light.B - lightLight.B;
return Color.FromArgb((byte)(light.R - (byte)(dr * percLighter)),
(byte)(light.G - (byte)(dg * percLighter)),
(byte)(light.B - (byte)(db * percLighter)));
}
}
else
{
int zeroLum = luminosity;
int oneLum = NewLuma(HilightAdj, true);
return ColorFromHLS(hue, zeroLum + (int)((oneLum - zeroLum) * percLighter), saturation);
}
}
private int NewLuma(int n, bool scale)
{
return NewLuma(luminosity, n, scale);
}
private int NewLuma(int luminosity, int n, bool scale)
{
if (n == 0)
return luminosity;
if (scale)
{
if (n > 0)
{
return (int)(((int)luminosity * (1000 - n) + (Range + 1L) * n) / 1000);
}
else
{
return (int)(((int)luminosity * (n + 1000)) / 1000);
}
}
int newLum = luminosity;
newLum += (int)((long)n * Range / 1000);
if (newLum < 0)
newLum = 0;
if (newLum > HLSMax)
newLum = HLSMax;
return newLum;
}
private Color ColorFromHLS(int hue, int luminosity, int saturation)
{
byte r, g, b; /* RGB component values */
int magic1, magic2; /* calculated magic numbers (really!) */
if (saturation == 0)
{ /* achromatic case */
r = g = b = (byte)((luminosity * RGBMax) / HLSMax);
if (hue != Undefined)
{
/* ERROR */
}
}
else
{ /* chromatic case */
/* set up magic numbers */
if (luminosity <= (HLSMax / 2))
magic2 = (int)((luminosity * ((int)HLSMax + saturation) + (HLSMax / 2)) / HLSMax);
else
magic2 = luminosity + saturation - (int)(((luminosity * saturation) + (int)(HLSMax / 2)) / HLSMax);
magic1 = 2 * luminosity - magic2;
/* get RGB, change units from HLSMax to RGBMax */
r = (byte)(((HueToRGB(magic1, magic2, (int)(hue + (int)(HLSMax / 3))) * (int)RGBMax + (HLSMax / 2))) / (int)HLSMax);
g = (byte)(((HueToRGB(magic1, magic2, hue) * (int)RGBMax + (HLSMax / 2))) / HLSMax);
b = (byte)(((HueToRGB(magic1, magic2, (int)(hue - (int)(HLSMax / 3))) * (int)RGBMax + (HLSMax / 2))) / (int)HLSMax);
}
return Color.FromArgb(r, g, b);
}
private int HueToRGB(int n1, int n2, int hue)
{
/* range check: note values passed add/subtract thirds of range */
/* The following is redundant for WORD (unsigned int) */
if (hue < 0)
hue += HLSMax;
if (hue > HLSMax)
hue -= HLSMax;
/* return r,g, or b value from this tridrant */
if (hue < (HLSMax / 6))
return (n1 + (((n2 - n1) * hue + (HLSMax / 12)) / (HLSMax / 6)));
if (hue < (HLSMax / 2))
return (n2);
if (hue < ((HLSMax * 2) / 3))
return (n1 + (((n2 - n1) * (((HLSMax * 2) / 3) - hue) + (HLSMax / 12)) / (HLSMax / 6)));
else
return (n1);
}
}
}
}