141 lines
3.7 KiB
TypeScript
141 lines
3.7 KiB
TypeScript
class Colour {
|
|
private static readonly FLAG_INHERIT: number = 0x40000000;
|
|
|
|
private static readonly READABILITY_THRESHOLD: number = 186;
|
|
private static readonly LUMINANCE_WEIGHT_RED: number = .299;
|
|
private static readonly LUMINANCE_WEIGHT_GREEN: number = .587;
|
|
private static readonly LUMINANCE_WEIGHT_BLUE: number = .114;
|
|
|
|
private raw: number = 0;
|
|
|
|
public constructor(raw: number = 0) {
|
|
this.SetRaw(raw);
|
|
}
|
|
|
|
public static None(): Colour {
|
|
return new Colour(Colour.FLAG_INHERIT);
|
|
}
|
|
|
|
public static FromRgb(red: number, green: number, blue: number): Colour {
|
|
return (new Colour).SetRed(red).SetGreen(green).SetBlue(blue);
|
|
}
|
|
public static FromHex(hex: string): Colour {
|
|
return (new Colour).SetHex(hex);
|
|
}
|
|
|
|
public GetRaw(): number {
|
|
return this.raw;
|
|
}
|
|
public SetRaw(raw: number): Colour {
|
|
if(raw < 0 || raw > 0x7FFFFFFF)
|
|
throw 'Invalid raw colour.';
|
|
this.raw = raw;
|
|
return this;
|
|
}
|
|
|
|
public GetInherit(): boolean {
|
|
return (this.GetRaw() & Colour.FLAG_INHERIT) > 0;
|
|
}
|
|
public SetInherit(inherit: boolean): Colour {
|
|
let raw: number = this.GetRaw();
|
|
|
|
if(inherit)
|
|
raw |= Colour.FLAG_INHERIT;
|
|
else
|
|
raw &= ~Colour.FLAG_INHERIT;
|
|
|
|
this.SetRaw(raw);
|
|
return this;
|
|
}
|
|
|
|
public GetRed(): number {
|
|
return (this.GetRaw() & 0xFF0000) >> 16;
|
|
}
|
|
public SetRed(red: number): Colour {
|
|
if(red < 0 || red > 0xFF)
|
|
throw 'Invalid red value.';
|
|
|
|
let raw: number = this.GetRaw();
|
|
raw &= ~0xFF0000;
|
|
raw |= red << 16;
|
|
this.SetRaw(raw);
|
|
|
|
return this;
|
|
}
|
|
|
|
public GetGreen(): number {
|
|
return (this.GetRaw() & 0xFF00) >> 8;
|
|
}
|
|
public SetGreen(green: number): Colour {
|
|
if(green < 0 || green > 0xFF)
|
|
throw 'Invalid green value.';
|
|
|
|
let raw: number = this.GetRaw();
|
|
raw &= ~0xFF00;
|
|
raw |= green << 8;
|
|
this.SetRaw(raw);
|
|
|
|
return this;
|
|
}
|
|
|
|
public GetBlue(): number {
|
|
return (this.GetRaw() & 0xFF);
|
|
}
|
|
public SetBlue(blue: number): Colour {
|
|
if(blue < 0 || blue > 0xFF)
|
|
throw 'Invalid blue value.';
|
|
|
|
let raw: number = this.GetRaw();
|
|
raw &= ~0xFF;
|
|
raw |= blue;
|
|
this.SetRaw(raw);
|
|
|
|
return this;
|
|
}
|
|
|
|
public GetLuminance(): number {
|
|
return Colour.LUMINANCE_WEIGHT_RED * this.GetRed()
|
|
+ Colour.LUMINANCE_WEIGHT_GREEN * this.GetGreen()
|
|
+ Colour.LUMINANCE_WEIGHT_BLUE * this.GetBlue();
|
|
}
|
|
|
|
public GetHex(): string {
|
|
let hex: string = (this.GetRaw() & 0xFFFFFF).toString(16);
|
|
|
|
if(hex.length < 6)
|
|
hex = '000000'.substring(0, 6 - hex.length) + hex;
|
|
|
|
return hex;
|
|
}
|
|
public SetHex(hex: string): Colour {
|
|
if(hex[0] === '#')
|
|
hex = hex.substring(1);
|
|
|
|
if(/[^A-Fa-f0-9]/g.test(hex))
|
|
throw 'Argument contains invalid characters.';
|
|
|
|
if(hex.length === 3) {
|
|
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
} else if(hex.length !== 6) {
|
|
throw 'Argument is not a hex string.';
|
|
}
|
|
|
|
return this.SetRaw(parseInt(hex, 16));
|
|
}
|
|
|
|
public GetCSS(): string {
|
|
if(this.GetInherit())
|
|
return 'inherit';
|
|
|
|
return '#' + this.GetHex();
|
|
}
|
|
|
|
public extractCSSContract(
|
|
dark: string = 'dark', light: string = 'light', inheritIsDark: boolean = true
|
|
): string {
|
|
if(this.GetInherit())
|
|
return inheritIsDark ? dark : light;
|
|
|
|
return this.GetLuminance() > Colour.READABILITY_THRESHOLD ? dark : light;
|
|
}
|
|
}
|