diff --git a/assets/typescript/Colour.ts b/assets/typescript/Colour.ts index 20de2675..b5569fcf 100644 --- a/assets/typescript/Colour.ts +++ b/assets/typescript/Colour.ts @@ -1,70 +1,9 @@ -const MSZ_COLOUR_INHERIT = 0x40000000, - MSZ_COLOUR_READABILITY_THRESHOLD = 186, - MSZ_COLOUR_LUMINANCE_WEIGHT_RED = 0.299, - MSZ_COLOUR_LUMINANCE_WEIGHT_GREEN = 0.587, - MSZ_COLOUR_LUMINANCE_WEIGHT_BLUE = 0.114; - -function colourCreate(): number { - return 0; -} - -function colourNone(): number { - return MSZ_COLOUR_INHERIT; -} - -function colourSetInherit(colour: number, enabled: boolean): number { - if(enabled) { - colour |= MSZ_COLOUR_INHERIT; - } else { - colour &= ~MSZ_COLOUR_INHERIT; - } - - return colour; -} +const MSZ_COLOUR_INHERIT = 0x40000000; function colourGetInherit(colour: number): boolean { return colour === null || (colour & MSZ_COLOUR_INHERIT) > 0; } -function colourGetRed(colour: number): number { - return (colour >> 16) & 0xFF; -} - -function colourSetRed(colour: number, red: number): number { - red = red & 0xFF; - colour &= ~0xFF0000; - colour |= red << 16; - return colour; -} - -function colourGetGreen(colour: number): number { - return (colour >> 8) & 0xFF; -} - -function colourSetGreen(colour: number, green: number): number { - green = green & 0xFF; - colour &= ~0xFF00; - colour |= green << 8; - return colour; -} - -function colourGetBlue(colour: number): number { - return colour & 0xFF; -} - -function colourSetBlue(colour: number, blue: number): number { - blue = blue & 0xFF; - colour &= ~0xFF; - colour |= blue; - return colour; -} - -function colourGetLuminance(colour: number): number { - return MSZ_COLOUR_LUMINANCE_WEIGHT_RED * colourGetRed(colour) - + MSZ_COLOUR_LUMINANCE_WEIGHT_GREEN * colourGetGreen(colour) - + MSZ_COLOUR_LUMINANCE_WEIGHT_BLUE * colourGetBlue(colour); -} - function colourGetHex(colour: number): string { return '#' + (colour & 0xFFFFFF).toString(16); } @@ -77,58 +16,144 @@ function colourGetCSS(colour: number): string { return colourGetHex(colour); } -function colourGetCSSContrast( - colour: number, - dark: string = 'dark', - light: string = 'light', - inheritIsDark: boolean = true -): string { - if(colourGetInherit(colour)) { - return inheritIsDark ? dark : light; +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); } - return colourGetLuminance(colour) > MSZ_COLOUR_READABILITY_THRESHOLD - ? dark - : light; -} - -function colourFromRGB(red: number, green: number, blue: number): number { - let colour: number = colourCreate(); - colour = colourSetRed(colour, red); - colour = colourSetGreen(colour, green); - colour = colourSetBlue(colour, blue); - return colour; -} - -function colourFromHex(hex: string): number { - if(hex.indexOf('#') === 0) - hex = hex.substr(1); - - const length: number = hex.length; - - if(length === 3) { - hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; - } else if(length !== 6) { - return 0; + public static None(): Colour { + return new Colour(Colour.FLAG_INHERIT); } - return parseInt(hex, 16); -} + 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); + } -class ColourProperties { - red: number; - green: number; - blue: number; - inherit: boolean; - luminance: number; -} + 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; + } -function colourGetProperties(colour: number): ColourProperties { - const props: ColourProperties = new ColourProperties; - props.red = colourGetRed(colour); - props.green = colourGetGreen(colour); - props.blue = colourGetBlue(colour); - props.inherit = colourGetInherit(colour); - props.luminance = colourGetLuminance(colour); - return props; + 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; + } } diff --git a/assets/typescript/Comments.tsx b/assets/typescript/Comments.tsx index d310178b..9487cb3a 100644 --- a/assets/typescript/Comments.tsx +++ b/assets/typescript/Comments.tsx @@ -200,7 +200,8 @@ function commentConstruct(comment: CommentPostInfo, layer: number = 0): HTMLElem href="javascript:void(0);" onClick={commentVoteEventHandler}>Dislike); } - const commentText: HTMLDivElement =
; + const commentText: HTMLDivElement = , + commentColour: Colour = new Colour(comment.user_colour); if(comment.comment_html) commentText.innerHTML = comment.comment_html; @@ -218,7 +219,7 @@ function commentConstruct(comment: CommentPostInfo, layer: number = 0): HTMLElem