Prepare Color for use in critical perf code

This commit is contained in:
Alex Dima
2017-02-17 12:52:05 +01:00
parent 19043a75de
commit 6c88aec2b9
3 changed files with 372 additions and 267 deletions
+262 -157
View File
@@ -3,10 +3,104 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as Object from 'vs/base/common/objects';
export class RGBA {
_rgbaBrand: void;
export interface RGBA { r: number; g: number; b: number; a: number; }
export interface HSLA { h: number; s: number; l: number; a: number; }
/**
* Red: integer in [0-255]
*/
public readonly r: number;
/**
* Green: integer in [0-255]
*/
public readonly g: number;
/**
* Blue: integer in [0-255]
*/
public readonly b: number;
/**
* Alpha: float in [0-1]
*/
public readonly a: number;
constructor(r: number, g: number, b: number, a: number) {
this.r = RGBA._clampColorComponent(r);
this.g = RGBA._clampColorComponent(g);
this.b = RGBA._clampColorComponent(b);
this.a = RGBA._clampAlphaComponent(a);
}
private static _clampColorComponent(c: number): number {
if (c < 0) {
return 0;
}
if (c > 255) {
return 255;
}
return c | 0;
}
private static _clampAlphaComponent(alpha: number): number {
if (alpha < 0) {
return 0.0;
}
if (alpha > 1) {
return 1.0;
}
return alpha;
}
}
/**
* http://en.wikipedia.org/wiki/HSL_color_space
*/
export class HSLA {
_hslaBrand: void;
/**
* Hue: float in [0, 360]
*/
public readonly h: number;
/**
* Saturation: float in [0, 1]
*/
public readonly s: number;
/**
* Luminosity: float in [0, 1]
*/
public readonly l: number;
/**
* Alpha: float in [0, 1]
*/
public readonly a: number;
constructor(h: number, s: number, l: number, a: number) {
this.h = HSLA._clampHue(h);
this.s = HSLA._clamp01(s);
this.l = HSLA._clamp01(l);
this.a = HSLA._clamp01(a);
}
private static _clampHue(hue: number): number {
if (hue < 0) {
return 0.0;
}
if (hue > 360) {
return 360.0;
}
return hue;
}
private static _clamp01(n: number): number {
if (n < 0) {
return 0.0;
}
if (n > 1) {
return 1.0;
}
return n;
}
}
/**
* Converts an Hex color value to RGB.
@@ -17,13 +111,13 @@ function hex2rgba(hex: string): RGBA {
return parseInt('0x' + str);
}
if (hex.charAt(0) === '#' && hex.length >= 7) {
let r = parseHex(hex.substr(1, 2));
let g = parseHex(hex.substr(3, 2));
let b = parseHex(hex.substr(5, 2));
let a = hex.length === 9 ? parseHex(hex.substr(7, 2)) / 0xff : 1;
return { r, g, b, a };
const r = parseHex(hex.substr(1, 2));
const g = parseHex(hex.substr(3, 2));
const b = parseHex(hex.substr(5, 2));
const a = hex.length === 9 ? parseHex(hex.substr(7, 2)) / 0xff : 1;
return new RGBA(r, g, b, a);
}
return { r: 255, g: 0, b: 0, a: 1 };
return new RGBA(255, 0, 0, 1);
}
/**
@@ -33,13 +127,17 @@ function hex2rgba(hex: string): RGBA {
* returns h in the set [0, 360], s, and l in the set [0, 1].
*/
function rgba2hsla(rgba: RGBA): HSLA {
let r = rgba.r / 255;
let g = rgba.g / 255;
let b = rgba.b / 255;
let a = rgba.a === void 0 ? rgba.a : 1;
const r = rgba.r / 255;
const g = rgba.g / 255;
const b = rgba.b / 255;
const a = rgba.a;
let max = Math.max(r, g, b), min = Math.min(r, g, b);
let h = 0, s = 0, l = Math.round(((min + max) / 2) * 1000) / 1000, chroma = max - min;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h = 0;
let s = 0;
const l = Math.round(((min + max) / 2) * 1000) / 1000;
const chroma = max - min;
if (chroma > 0) {
s = Math.min(Math.round((l <= 0.5 ? chroma / (2 * l) : chroma / (2 - (2 * l))) * 1000) / 1000, 1);
@@ -51,7 +149,7 @@ function rgba2hsla(rgba: RGBA): HSLA {
h *= 60;
h = Math.round(h);
}
return { h, s, l, a };
return new HSLA(h, s, l, a);
}
/**
@@ -61,42 +159,42 @@ function rgba2hsla(rgba: RGBA): HSLA {
* returns r, g, and b in the set [0, 255].
*/
function hsla2rgba(hsla: HSLA): RGBA {
let h = hsla.h / 360;
let s = Math.min(hsla.s, 1);
let l = Math.min(hsla.l, 1);
let a = hsla.a === void 0 ? hsla.a : 1;
const h = hsla.h / 360;
const s = Math.min(hsla.s, 1);
const l = Math.min(hsla.l, 1);
const a = hsla.a;
let r: number, g: number, b: number;
if (s === 0) {
r = g = b = l; // achromatic
} else {
let hue2rgb = function hue2rgb(p: number, q: number, t: number) {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1 / 2) {
return q;
}
if (t < 2 / 3) {
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
};
let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
let p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = _hue2rgb(p, q, h + 1 / 3);
g = _hue2rgb(p, q, h);
b = _hue2rgb(p, q, h - 1 / 3);
}
return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255), a };
return new RGBA(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a);
}
function _hue2rgb(p: number, q: number, t: number) {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1 / 2) {
return q;
}
if (t < 2 / 3) {
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
}
export function hexToCSS(hex: string) {
@@ -112,119 +210,13 @@ function toCSSColor(rgba: RGBA): string {
export class Color {
private rgba: RGBA;
private hsla: HSLA;
private str: string;
constructor(arg: string | RGBA) {
this.rgba = typeof arg === 'string' ? hex2rgba(arg) : <RGBA>arg;
this.str = null;
}
/**
* http://www.w3.org/TR/WCAG20/#relativeluminancedef
* Returns the number in the set [0, 1]. O => Darkest Black. 1 => Lightest white.
*/
public getLuminosity(): number {
let luminosityFor = function (color: number): number {
let c = color / 255;
return (c <= 0.03928) ? c / 12.92 : Math.pow(((c + 0.055) / 1.055), 2.4);
};
let R = luminosityFor(this.rgba.r);
let G = luminosityFor(this.rgba.g);
let B = luminosityFor(this.rgba.b);
let luminosity = 0.2126 * R + 0.7152 * G + 0.0722 * B;
return Math.round(luminosity * 10000) / 10000;
}
/**
* http://www.w3.org/TR/WCAG20/#contrast-ratiodef
* Returns the contrast ration number in the set [1, 21].
*/
public getContrast(another: Color): number {
let lum1 = this.getLuminosity();
let lum2 = another.getLuminosity();
return lum1 > lum2 ? (lum1 + 0.05) / (lum2 + 0.05) : (lum2 + 0.05) / (lum1 + 0.05);
}
/**
* http://24ways.org/2010/calculating-color-contrast
* Return 'true' if darker color otherwise 'false'
*/
public isDarker(): boolean {
var yiq = (this.rgba.r * 299 + this.rgba.g * 587 + this.rgba.b * 114) / 1000;
return yiq < 128;
}
/**
* http://24ways.org/2010/calculating-color-contrast
* Return 'true' if lighter color otherwise 'false'
*/
public isLighter(): boolean {
var yiq = (this.rgba.r * 299 + this.rgba.g * 587 + this.rgba.b * 114) / 1000;
return yiq >= 128;
}
public isLighterThan(another: Color): boolean {
let lum1 = this.getLuminosity();
let lum2 = another.getLuminosity();
return lum1 > lum2;
}
public isDarkerThan(another: Color): boolean {
let lum1 = this.getLuminosity();
let lum2 = another.getLuminosity();
return lum1 < lum2;
}
public lighten(factor: number): Color {
let hsl = this.toHSLA();
hsl.l += hsl.l * factor;
return new Color(hsla2rgba(hsl));
}
public darken(factor: number): Color {
let hsl = this.toHSLA();
hsl.l -= hsl.l * factor;
return new Color(hsla2rgba(hsl));
}
public transparent(factor: number): Color {
let p = this.rgba;
return new Color({ r: p.r, g: p.g, b: p.b, a: p.a * factor });
}
public opposite(): Color {
return new Color({
r: 255 - this.rgba.r,
g: 255 - this.rgba.g,
b: 255 - this.rgba.b,
a: this.rgba.a
});
}
public toString(): string {
if (!this.str) {
this.str = toCSSColor(this.rgba);
}
return this.str;
}
public toHSLA(): HSLA {
if (!this.hsla) {
this.hsla = rgba2hsla(this.rgba);
}
return Object.clone(this.hsla);
}
public toRGBA(): RGBA {
return Object.clone(this.rgba);
}
public static fromRGBA(rgba: RGBA): Color {
return new Color(rgba);
}
/**
* Creates a color from a hex string (#RRGGBB or #RRGGBBAA).
*/
public static fromHex(hex: string): Color {
return new Color(hex);
}
@@ -233,12 +225,124 @@ export class Color {
return new Color(hsla2rgba(hsla));
}
private readonly rgba: RGBA;
private hsla: HSLA;
private str: string;
private constructor(arg: string | RGBA) {
this.rgba = typeof arg === 'string' ? hex2rgba(arg) : <RGBA>arg;
this.hsla = null;
this.str = null;
}
/**
* http://www.w3.org/TR/WCAG20/#relativeluminancedef
* Returns the number in the set [0, 1]. O => Darkest Black. 1 => Lightest white.
*/
public getLuminosity(): number {
const R = Color._luminosityFor(this.rgba.r);
const G = Color._luminosityFor(this.rgba.g);
const B = Color._luminosityFor(this.rgba.b);
const luminosity = 0.2126 * R + 0.7152 * G + 0.0722 * B;
return Math.round(luminosity * 10000) / 10000;
}
private static _luminosityFor(color: number): number {
const c = color / 255;
return (c <= 0.03928) ? c / 12.92 : Math.pow(((c + 0.055) / 1.055), 2.4);
}
/**
* http://www.w3.org/TR/WCAG20/#contrast-ratiodef
* Returns the contrast ration number in the set [1, 21].
*/
public getContrast(another: Color): number {
const lum1 = this.getLuminosity();
const lum2 = another.getLuminosity();
return lum1 > lum2 ? (lum1 + 0.05) / (lum2 + 0.05) : (lum2 + 0.05) / (lum1 + 0.05);
}
/**
* http://24ways.org/2010/calculating-color-contrast
* Return 'true' if darker color otherwise 'false'
*/
public isDarker(): boolean {
const yiq = (this.rgba.r * 299 + this.rgba.g * 587 + this.rgba.b * 114) / 1000;
return yiq < 128;
}
/**
* http://24ways.org/2010/calculating-color-contrast
* Return 'true' if lighter color otherwise 'false'
*/
public isLighter(): boolean {
const yiq = (this.rgba.r * 299 + this.rgba.g * 587 + this.rgba.b * 114) / 1000;
return yiq >= 128;
}
public isLighterThan(another: Color): boolean {
const lum1 = this.getLuminosity();
const lum2 = another.getLuminosity();
return lum1 > lum2;
}
public isDarkerThan(another: Color): boolean {
const lum1 = this.getLuminosity();
const lum2 = another.getLuminosity();
return lum1 < lum2;
}
public lighten(factor: number): Color {
const hsl = this.toHSLA();
const result = new HSLA(hsl.h, hsl.s, hsl.l + hsl.l * factor, hsl.a);
return new Color(hsla2rgba(result));
}
public darken(factor: number): Color {
const hsl = this.toHSLA();
const result = new HSLA(hsl.h, hsl.s, hsl.l - hsl.l * factor, hsl.a);
return new Color(hsla2rgba(result));
}
public transparent(factor: number): Color {
const p = this.rgba;
return new Color(new RGBA(p.r, p.g, p.b, p.a * factor));
}
public opposite(): Color {
return new Color(new RGBA(
255 - this.rgba.r,
255 - this.rgba.g,
255 - this.rgba.b,
this.rgba.a
));
}
public toString(): string {
if (this.str === null) {
this.str = toCSSColor(this.rgba);
}
return this.str;
}
public toHSLA(): HSLA {
if (this.hsla === null) {
this.hsla = rgba2hsla(this.rgba);
}
return this.hsla;
}
public toRGBA(): RGBA {
return this.rgba;
}
public static getLighterColor(of: Color, relative: Color, factor?: number): Color {
if (of.isLighterThan(relative)) {
return of;
}
factor = factor ? factor : 0.5;
let lum1 = of.getLuminosity(), lum2 = relative.getLuminosity();
const lum1 = of.getLuminosity();
const lum2 = relative.getLuminosity();
factor = factor * (lum2 - lum1) / lum2;
return of.lighten(factor);
}
@@ -248,8 +352,9 @@ export class Color {
return of;
}
factor = factor ? factor : 0.5;
let lum1 = of.getLuminosity(), lum2 = relative.getLuminosity();
const lum1 = of.getLuminosity();
const lum2 = relative.getLuminosity();
factor = factor * (lum1 - lum2) / lum1;
return of.darken(factor);
}
}
}
+94 -94
View File
@@ -5,82 +5,82 @@
'use strict';
import { Color } from 'vs/base/common/color';
import * as assert from 'assert';
import { Color, RGBA, HSLA } from 'vs/base/common/color';
suite('Color', () => {
test('rgba2hsla', function () {
assert.deepEqual({ h: 0, s: 0, l: 0, a: 1 }, Color.fromRGBA({ r: 0, g: 0, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 1, a: 1 }, Color.fromRGBA({ r: 255, g: 255, b: 255, a: 1 }).toHSLA());
assert.deepEqual(new HSLA(0, 0, 0, 1), Color.fromRGBA(new RGBA(0, 0, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(0, 0, 1, 1), Color.fromRGBA(new RGBA(255, 255, 255, 1)).toHSLA());
assert.deepEqual({ h: 0, s: 1, l: 0.5, a: 1 }, Color.fromRGBA({ r: 255, g: 0, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 120, s: 1, l: 0.5, a: 1 }, Color.fromRGBA({ r: 0, g: 255, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 240, s: 1, l: 0.5, a: 1 }, Color.fromRGBA({ r: 0, g: 0, b: 255, a: 1 }).toHSLA());
assert.deepEqual(new HSLA(0, 1, 0.5, 1), Color.fromRGBA(new RGBA(255, 0, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(120, 1, 0.5, 1), Color.fromRGBA(new RGBA(0, 255, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(240, 1, 0.5, 1), Color.fromRGBA(new RGBA(0, 0, 255, 1)).toHSLA());
assert.deepEqual({ h: 60, s: 1, l: 0.5, a: 1 }, Color.fromRGBA({ r: 255, g: 255, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 180, s: 1, l: 0.5, a: 1 }, Color.fromRGBA({ r: 0, g: 255, b: 255, a: 1 }).toHSLA());
assert.deepEqual({ h: 300, s: 1, l: 0.5, a: 1 }, Color.fromRGBA({ r: 255, g: 0, b: 255, a: 1 }).toHSLA());
assert.deepEqual(new HSLA(60, 1, 0.5, 1), Color.fromRGBA(new RGBA(255, 255, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(180, 1, 0.5, 1), Color.fromRGBA(new RGBA(0, 255, 255, 1)).toHSLA());
assert.deepEqual(new HSLA(300, 1, 0.5, 1), Color.fromRGBA(new RGBA(255, 0, 255, 1)).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 0.753, a: 1 }, Color.fromRGBA({ r: 192, g: 192, b: 192, a: 1 }).toHSLA());
assert.deepEqual(new HSLA(0, 0, 0.753, 1), Color.fromRGBA(new RGBA(192, 192, 192, 1)).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 0.502, a: 1 }, Color.fromRGBA({ r: 128, g: 128, b: 128, a: 1 }).toHSLA());
assert.deepEqual({ h: 0, s: 1, l: 0.251, a: 1 }, Color.fromRGBA({ r: 128, g: 0, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 60, s: 1, l: 0.251, a: 1 }, Color.fromRGBA({ r: 128, g: 128, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 120, s: 1, l: 0.251, a: 1 }, Color.fromRGBA({ r: 0, g: 128, b: 0, a: 1 }).toHSLA());
assert.deepEqual({ h: 300, s: 1, l: 0.251, a: 1 }, Color.fromRGBA({ r: 128, g: 0, b: 128, a: 1 }).toHSLA());
assert.deepEqual({ h: 180, s: 1, l: 0.251, a: 1 }, Color.fromRGBA({ r: 0, g: 128, b: 128, a: 1 }).toHSLA());
assert.deepEqual({ h: 240, s: 1, l: 0.251, a: 1 }, Color.fromRGBA({ r: 0, g: 0, b: 128, a: 1 }).toHSLA());
assert.deepEqual(new HSLA(0, 0, 0.502, 1), Color.fromRGBA(new RGBA(128, 128, 128, 1)).toHSLA());
assert.deepEqual(new HSLA(0, 1, 0.251, 1), Color.fromRGBA(new RGBA(128, 0, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(60, 1, 0.251, 1), Color.fromRGBA(new RGBA(128, 128, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(120, 1, 0.251, 1), Color.fromRGBA(new RGBA(0, 128, 0, 1)).toHSLA());
assert.deepEqual(new HSLA(300, 1, 0.251, 1), Color.fromRGBA(new RGBA(128, 0, 128, 1)).toHSLA());
assert.deepEqual(new HSLA(180, 1, 0.251, 1), Color.fromRGBA(new RGBA(0, 128, 128, 1)).toHSLA());
assert.deepEqual(new HSLA(240, 1, 0.251, 1), Color.fromRGBA(new RGBA(0, 0, 128, 1)).toHSLA());
});
test('hsla2rgba', function () {
assert.deepEqual({ r: 0, g: 0, b: 0, a: 1 }, Color.fromHSLA({ h: 0, s: 0, l: 0, a: 1 }).toRGBA());
assert.deepEqual({ r: 255, g: 255, b: 255, a: 1 }, Color.fromHSLA({ h: 0, s: 0, l: 1, a: 1 }).toRGBA());
assert.deepEqual(new RGBA(0, 0, 0, 1), Color.fromHSLA(new HSLA(0, 0, 0, 1)).toRGBA());
assert.deepEqual(new RGBA(255, 255, 255, 1), Color.fromHSLA(new HSLA(0, 0, 1, 1)).toRGBA());
assert.deepEqual({ r: 255, g: 0, b: 0, a: 1 }, Color.fromHSLA({ h: 0, s: 1, l: 0.5, a: 1 }).toRGBA());
assert.deepEqual({ r: 0, g: 255, b: 0, a: 1 }, Color.fromHSLA({ h: 120, s: 1, l: 0.5, a: 1 }).toRGBA());
assert.deepEqual({ r: 0, g: 0, b: 255, a: 1 }, Color.fromHSLA({ h: 240, s: 1, l: 0.5, a: 1 }).toRGBA());
assert.deepEqual(new RGBA(255, 0, 0, 1), Color.fromHSLA(new HSLA(0, 1, 0.5, 1)).toRGBA());
assert.deepEqual(new RGBA(0, 255, 0, 1), Color.fromHSLA(new HSLA(120, 1, 0.5, 1)).toRGBA());
assert.deepEqual(new RGBA(0, 0, 255, 1), Color.fromHSLA(new HSLA(240, 1, 0.5, 1)).toRGBA());
assert.deepEqual({ r: 255, g: 255, b: 0, a: 1 }, Color.fromHSLA({ h: 60, s: 1, l: 0.5, a: 1 }).toRGBA());
assert.deepEqual({ r: 0, g: 255, b: 255, a: 1 }, Color.fromHSLA({ h: 180, s: 1, l: 0.5, a: 1 }).toRGBA());
assert.deepEqual({ r: 255, g: 0, b: 255, a: 1 }, Color.fromHSLA({ h: 300, s: 1, l: 0.5, a: 1 }).toRGBA());
assert.deepEqual(new RGBA(255, 255, 0, 1), Color.fromHSLA(new HSLA(60, 1, 0.5, 1)).toRGBA());
assert.deepEqual(new RGBA(0, 255, 255, 1), Color.fromHSLA(new HSLA(180, 1, 0.5, 1)).toRGBA());
assert.deepEqual(new RGBA(255, 0, 255, 1), Color.fromHSLA(new HSLA(300, 1, 0.5, 1)).toRGBA());
assert.deepEqual({ r: 192, g: 192, b: 192, a: 1 }, Color.fromHSLA({ h: 0, s: 0, l: 0.753, a: 1 }).toRGBA());
assert.deepEqual(new RGBA(192, 192, 192, 1), Color.fromHSLA(new HSLA(0, 0, 0.753, 1)).toRGBA());
assert.deepEqual({ r: 128, g: 128, b: 128, a: 1 }, Color.fromHSLA({ h: 0, s: 0, l: 0.502, a: 1 }).toRGBA());
assert.deepEqual({ r: 128, g: 0, b: 0, a: 1 }, Color.fromHSLA({ h: 0, s: 1, l: 0.251, a: 1 }).toRGBA());
assert.deepEqual({ r: 128, g: 128, b: 0, a: 1 }, Color.fromHSLA({ h: 60, s: 1, l: 0.251, a: 1 }).toRGBA());
assert.deepEqual({ r: 0, g: 128, b: 0, a: 1 }, Color.fromHSLA({ h: 120, s: 1, l: 0.251, a: 1 }).toRGBA());
assert.deepEqual({ r: 128, g: 0, b: 128, a: 1 }, Color.fromHSLA({ h: 300, s: 1, l: 0.251, a: 1 }).toRGBA());
assert.deepEqual({ r: 0, g: 128, b: 128, a: 1 }, Color.fromHSLA({ h: 180, s: 1, l: 0.251, a: 1 }).toRGBA());
assert.deepEqual({ r: 0, g: 0, b: 128, a: 1 }, Color.fromHSLA({ h: 240, s: 1, l: 0.251, a: 1 }).toRGBA());
assert.deepEqual(new RGBA(128, 128, 128, 1), Color.fromHSLA(new HSLA(0, 0, 0.502, 1)).toRGBA());
assert.deepEqual(new RGBA(128, 0, 0, 1), Color.fromHSLA(new HSLA(0, 1, 0.251, 1)).toRGBA());
assert.deepEqual(new RGBA(128, 128, 0, 1), Color.fromHSLA(new HSLA(60, 1, 0.251, 1)).toRGBA());
assert.deepEqual(new RGBA(0, 128, 0, 1), Color.fromHSLA(new HSLA(120, 1, 0.251, 1)).toRGBA());
assert.deepEqual(new RGBA(128, 0, 128, 1), Color.fromHSLA(new HSLA(300, 1, 0.251, 1)).toRGBA());
assert.deepEqual(new RGBA(0, 128, 128, 1), Color.fromHSLA(new HSLA(180, 1, 0.251, 1)).toRGBA());
assert.deepEqual(new RGBA(0, 0, 128, 1), Color.fromHSLA(new HSLA(240, 1, 0.251, 1)).toRGBA());
});
test('hex2rgba', function () {
assert.deepEqual({ r: 0, g: 0, b: 0, a: 1 }, Color.fromHex('#000000').toRGBA());
assert.deepEqual({ r: 255, g: 255, b: 255, a: 1 }, Color.fromHex('#FFFFFF').toRGBA());
assert.deepEqual(new RGBA(0, 0, 0, 1), Color.fromHex('#000000').toRGBA());
assert.deepEqual(new RGBA(255, 255, 255, 1), Color.fromHex('#FFFFFF').toRGBA());
assert.deepEqual({ r: 255, g: 0, b: 0, a: 1 }, Color.fromHex('#FF0000').toRGBA());
assert.deepEqual({ r: 0, g: 255, b: 0, a: 1 }, Color.fromHex('#00FF00').toRGBA());
assert.deepEqual({ r: 0, g: 0, b: 255, a: 1 }, Color.fromHex('#0000FF').toRGBA());
assert.deepEqual(new RGBA(255, 0, 0, 1), Color.fromHex('#FF0000').toRGBA());
assert.deepEqual(new RGBA(0, 255, 0, 1), Color.fromHex('#00FF00').toRGBA());
assert.deepEqual(new RGBA(0, 0, 255, 1), Color.fromHex('#0000FF').toRGBA());
assert.deepEqual({ r: 255, g: 255, b: 0, a: 1 }, Color.fromHex('#FFFF00').toRGBA());
assert.deepEqual({ r: 0, g: 255, b: 255, a: 1 }, Color.fromHex('#00FFFF').toRGBA());
assert.deepEqual({ r: 255, g: 0, b: 255, a: 1 }, Color.fromHex('#FF00FF').toRGBA());
assert.deepEqual(new RGBA(255, 255, 0, 1), Color.fromHex('#FFFF00').toRGBA());
assert.deepEqual(new RGBA(0, 255, 255, 1), Color.fromHex('#00FFFF').toRGBA());
assert.deepEqual(new RGBA(255, 0, 255, 1), Color.fromHex('#FF00FF').toRGBA());
assert.deepEqual({ r: 192, g: 192, b: 192, a: 1 }, Color.fromHex('#C0C0C0').toRGBA());
assert.deepEqual(new RGBA(192, 192, 192, 1), Color.fromHex('#C0C0C0').toRGBA());
assert.deepEqual({ r: 128, g: 128, b: 128, a: 1 }, Color.fromHex('#808080').toRGBA());
assert.deepEqual({ r: 128, g: 0, b: 0, a: 1 }, Color.fromHex('#800000').toRGBA());
assert.deepEqual({ r: 128, g: 128, b: 0, a: 1 }, Color.fromHex('#808000').toRGBA());
assert.deepEqual({ r: 0, g: 128, b: 0, a: 1 }, Color.fromHex('#008000').toRGBA());
assert.deepEqual({ r: 128, g: 0, b: 128, a: 1 }, Color.fromHex('#800080').toRGBA());
assert.deepEqual({ r: 0, g: 128, b: 128, a: 1 }, Color.fromHex('#008080').toRGBA());
assert.deepEqual({ r: 0, g: 0, b: 128, a: 1 }, Color.fromHex('#000080').toRGBA());
assert.deepEqual(new RGBA(128, 128, 128, 1), Color.fromHex('#808080').toRGBA());
assert.deepEqual(new RGBA(128, 0, 0, 1), Color.fromHex('#800000').toRGBA());
assert.deepEqual(new RGBA(128, 128, 0, 1), Color.fromHex('#808000').toRGBA());
assert.deepEqual(new RGBA(0, 128, 0, 1), Color.fromHex('#008000').toRGBA());
assert.deepEqual(new RGBA(128, 0, 128, 1), Color.fromHex('#800080').toRGBA());
assert.deepEqual(new RGBA(0, 128, 128, 1), Color.fromHex('#008080').toRGBA());
assert.deepEqual(new RGBA(0, 0, 128, 1), Color.fromHex('#000080').toRGBA());
});
test('isLighterColor', function () {
let color1 = Color.fromHSLA({ h: 60, s: 1, l: 0.5, a: 1 }), color2 = Color.fromHSLA({ h: 0, s: 0, l: 0.753, a: 1 });
let color1 = Color.fromHSLA(new HSLA(60, 1, 0.5, 1)), color2 = Color.fromHSLA(new HSLA(0, 0, 0.753, 1));
assert.ok(color1.isLighterThan(color2));
@@ -89,80 +89,80 @@ suite('Color', () => {
});
test('getLighterColor', function () {
let color1 = Color.fromHSLA({ h: 60, s: 1, l: 0.5, a: 1 }), color2 = Color.fromHSLA({ h: 0, s: 0, l: 0.753, a: 1 });
let color1 = Color.fromHSLA(new HSLA(60, 1, 0.5, 1)), color2 = Color.fromHSLA(new HSLA(0, 0, 0.753, 1));
assert.deepEqual(color1.toHSLA(), Color.getLighterColor(color1, color2).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 0.914, a: 1 }, Color.getLighterColor(color2, color1).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 0.851, a: 1 }, Color.getLighterColor(color2, color1, 0.3).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 0.98, a: 1 }, Color.getLighterColor(color2, color1, 0.7).toHSLA());
assert.deepEqual({ h: 0, s: 0, l: 1, a: 1 }, Color.getLighterColor(color2, color1, 1).toHSLA());
assert.deepEqual(new HSLA(0, 0, 0.914, 1), Color.getLighterColor(color2, color1).toHSLA());
assert.deepEqual(new HSLA(0, 0, 0.851, 1), Color.getLighterColor(color2, color1, 0.3).toHSLA());
assert.deepEqual(new HSLA(0, 0, 0.98, 1), Color.getLighterColor(color2, color1, 0.7).toHSLA());
assert.deepEqual(new HSLA(0, 0, 1, 1), Color.getLighterColor(color2, color1, 1).toHSLA());
});
test('isDarkerColor', function () {
let color1 = Color.fromHSLA({ h: 60, s: 1, l: 0.5, a: 1 }), color2 = Color.fromHSLA({ h: 0, s: 0, l: 0.753, a: 1 });
let color1 = Color.fromHSLA(new HSLA(60, 1, 0.5, 1)), color2 = Color.fromHSLA(new HSLA(0, 0, 0.753, 1));
assert.ok(color2.isDarkerThan(color1));
});
test('getDarkerColor', function () {
let color1 = Color.fromHSLA({ h: 60, s: 1, l: 0.5, a: 1 }), color2 = Color.fromHSLA({ h: 0, s: 0, l: 0.753, a: 1 });
let color1 = Color.fromHSLA(new HSLA(60, 1, 0.5, 1)), color2 = Color.fromHSLA(new HSLA(0, 0, 0.753, 1));
assert.deepEqual(color2.toHSLA(), Color.getDarkerColor(color2, color1).toHSLA());
assert.deepEqual({ h: 60, s: 1, l: 0.392, a: 1 }, Color.getDarkerColor(color1, color2).toHSLA());
assert.deepEqual({ h: 60, s: 1, l: 0.435, a: 1 }, Color.getDarkerColor(color1, color2, 0.3).toHSLA());
assert.deepEqual({ h: 60, s: 1, l: 0.349, a: 1 }, Color.getDarkerColor(color1, color2, 0.7).toHSLA());
assert.deepEqual({ h: 60, s: 1, l: 0.284, a: 1 }, Color.getDarkerColor(color1, color2, 1).toHSLA());
assert.deepEqual(new HSLA(60, 1, 0.392, 1), Color.getDarkerColor(color1, color2).toHSLA());
assert.deepEqual(new HSLA(60, 1, 0.435, 1), Color.getDarkerColor(color1, color2, 0.3).toHSLA());
assert.deepEqual(new HSLA(60, 1, 0.349, 1), Color.getDarkerColor(color1, color2, 0.7).toHSLA());
assert.deepEqual(new HSLA(60, 1, 0.284, 1), Color.getDarkerColor(color1, color2, 1).toHSLA());
// Abyss theme
assert.deepEqual({ h: 355, s: 0.874, l: 0.157, a: 1 }, Color.getDarkerColor(Color.fromHex('#770811'), Color.fromHex('#000c18'), 0.4).toHSLA());
assert.deepEqual(new HSLA(355, 0.874, 0.157, 1), Color.getDarkerColor(Color.fromHex('#770811'), Color.fromHex('#000c18'), 0.4).toHSLA());
});
test('luminosity', function () {
assert.deepEqual(0, Color.fromRGBA({ r: 0, g: 0, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(1, Color.fromRGBA({ r: 255, g: 255, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0, Color.fromRGBA(new RGBA(0, 0, 0, 1)).getLuminosity());
assert.deepEqual(1, Color.fromRGBA(new RGBA(255, 255, 255, 1)).getLuminosity());
assert.deepEqual(0.2126, Color.fromRGBA({ r: 255, g: 0, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.7152, Color.fromRGBA({ r: 0, g: 255, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.0722, Color.fromRGBA({ r: 0, g: 0, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0.2126, Color.fromRGBA(new RGBA(255, 0, 0, 1)).getLuminosity());
assert.deepEqual(0.7152, Color.fromRGBA(new RGBA(0, 255, 0, 1)).getLuminosity());
assert.deepEqual(0.0722, Color.fromRGBA(new RGBA(0, 0, 255, 1)).getLuminosity());
assert.deepEqual(0.9278, Color.fromRGBA({ r: 255, g: 255, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.7874, Color.fromRGBA({ r: 0, g: 255, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0.2848, Color.fromRGBA({ r: 255, g: 0, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0.9278, Color.fromRGBA(new RGBA(255, 255, 0, 1)).getLuminosity());
assert.deepEqual(0.7874, Color.fromRGBA(new RGBA(0, 255, 255, 1)).getLuminosity());
assert.deepEqual(0.2848, Color.fromRGBA(new RGBA(255, 0, 255, 1)).getLuminosity());
assert.deepEqual(0.5271, Color.fromRGBA({ r: 192, g: 192, b: 192, a: 1 }).getLuminosity());
assert.deepEqual(0.5271, Color.fromRGBA(new RGBA(192, 192, 192, 1)).getLuminosity());
assert.deepEqual(0.2159, Color.fromRGBA({ r: 128, g: 128, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.0459, Color.fromRGBA({ r: 128, g: 0, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.2003, Color.fromRGBA({ r: 128, g: 128, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.1544, Color.fromRGBA({ r: 0, g: 128, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.0615, Color.fromRGBA({ r: 128, g: 0, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.17, Color.fromRGBA({ r: 0, g: 128, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.0156, Color.fromRGBA({ r: 0, g: 0, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.2159, Color.fromRGBA(new RGBA(128, 128, 128, 1)).getLuminosity());
assert.deepEqual(0.0459, Color.fromRGBA(new RGBA(128, 0, 0, 1)).getLuminosity());
assert.deepEqual(0.2003, Color.fromRGBA(new RGBA(128, 128, 0, 1)).getLuminosity());
assert.deepEqual(0.1544, Color.fromRGBA(new RGBA(0, 128, 0, 1)).getLuminosity());
assert.deepEqual(0.0615, Color.fromRGBA(new RGBA(128, 0, 128, 1)).getLuminosity());
assert.deepEqual(0.17, Color.fromRGBA(new RGBA(0, 128, 128, 1)).getLuminosity());
assert.deepEqual(0.0156, Color.fromRGBA(new RGBA(0, 0, 128, 1)).getLuminosity());
});
test('contrast', function () {
assert.deepEqual(0, Color.fromRGBA({ r: 0, g: 0, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(1, Color.fromRGBA({ r: 255, g: 255, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0, Color.fromRGBA(new RGBA(0, 0, 0, 1)).getLuminosity());
assert.deepEqual(1, Color.fromRGBA(new RGBA(255, 255, 255, 1)).getLuminosity());
assert.deepEqual(0.2126, Color.fromRGBA({ r: 255, g: 0, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.7152, Color.fromRGBA({ r: 0, g: 255, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.0722, Color.fromRGBA({ r: 0, g: 0, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0.2126, Color.fromRGBA(new RGBA(255, 0, 0, 1)).getLuminosity());
assert.deepEqual(0.7152, Color.fromRGBA(new RGBA(0, 255, 0, 1)).getLuminosity());
assert.deepEqual(0.0722, Color.fromRGBA(new RGBA(0, 0, 255, 1)).getLuminosity());
assert.deepEqual(0.9278, Color.fromRGBA({ r: 255, g: 255, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.7874, Color.fromRGBA({ r: 0, g: 255, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0.2848, Color.fromRGBA({ r: 255, g: 0, b: 255, a: 1 }).getLuminosity());
assert.deepEqual(0.9278, Color.fromRGBA(new RGBA(255, 255, 0, 1)).getLuminosity());
assert.deepEqual(0.7874, Color.fromRGBA(new RGBA(0, 255, 255, 1)).getLuminosity());
assert.deepEqual(0.2848, Color.fromRGBA(new RGBA(255, 0, 255, 1)).getLuminosity());
assert.deepEqual(0.5271, Color.fromRGBA({ r: 192, g: 192, b: 192, a: 1 }).getLuminosity());
assert.deepEqual(0.5271, Color.fromRGBA(new RGBA(192, 192, 192, 1)).getLuminosity());
assert.deepEqual(0.2159, Color.fromRGBA({ r: 128, g: 128, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.0459, Color.fromRGBA({ r: 128, g: 0, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.2003, Color.fromRGBA({ r: 128, g: 128, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.1544, Color.fromRGBA({ r: 0, g: 128, b: 0, a: 1 }).getLuminosity());
assert.deepEqual(0.0615, Color.fromRGBA({ r: 128, g: 0, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.17, Color.fromRGBA({ r: 0, g: 128, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.0156, Color.fromRGBA({ r: 0, g: 0, b: 128, a: 1 }).getLuminosity());
assert.deepEqual(0.2159, Color.fromRGBA(new RGBA(128, 128, 128, 1)).getLuminosity());
assert.deepEqual(0.0459, Color.fromRGBA(new RGBA(128, 0, 0, 1)).getLuminosity());
assert.deepEqual(0.2003, Color.fromRGBA(new RGBA(128, 128, 0, 1)).getLuminosity());
assert.deepEqual(0.1544, Color.fromRGBA(new RGBA(0, 128, 0, 1)).getLuminosity());
assert.deepEqual(0.0615, Color.fromRGBA(new RGBA(128, 0, 128, 1)).getLuminosity());
assert.deepEqual(0.17, Color.fromRGBA(new RGBA(0, 128, 128, 1)).getLuminosity());
assert.deepEqual(0.0156, Color.fromRGBA(new RGBA(0, 0, 128, 1)).getLuminosity());
});
});
@@ -122,7 +122,7 @@ export class SearchViewStylesContribution {
let theme = new Theme(themeId, themeSettings);
if (theme.hasGlobalSettings()) {
if (theme.getGlobalSettings().findMatchHighlight) {
let color = new Color(theme.getGlobalSettings().findMatchHighlight);
let color = Color.fromHex(theme.getGlobalSettings().findMatchHighlight);
cssRules.push(`.${theme.getSelector()} .search-viewlet .findInFileMatch { background-color: ${color}; }`);
cssRules.push(`.${theme.getSelector()} .search-viewlet .highlight { background-color: ${color}; }`);
}
@@ -185,7 +185,7 @@ abstract class EditorStyleRules extends StyleRules {
protected addBackgroundColorRule(theme: Theme, selector: string, color: string | Color, rules: string[]): void {
if (color) {
color = color instanceof Color ? color : new Color(color);
color = color instanceof Color ? color : Color.fromHex(color);
rules.push(`.monaco-editor.${theme.getSelector()} ${selector} { background-color: ${color}; }`);
}
}
@@ -196,7 +196,7 @@ class EditorBackgroundStyleRules extends EditorStyleRules {
public getCssRules(theme: Theme, cssRules: string[]): void {
let themeSelector = theme.getSelector();
if (theme.getGlobalSettings().background) {
let background = new Color(theme.getGlobalSettings().background);
let background = Color.fromHex(theme.getGlobalSettings().background);
this.addBackgroundColorRule(theme, '.monaco-editor-background', background, cssRules);
this.addBackgroundColorRule(theme, '.glyph-margin', background, cssRules);
cssRules.push(`.${themeSelector} .monaco-workbench .monaco-editor-background { background-color: ${background}; }`);
@@ -213,11 +213,11 @@ class EditorHoverHighlightStyleRules extends EditorStyleRules {
class EditorLinkStyleRules extends EditorStyleRules {
public getCssRules(theme: Theme, cssRules: string[]): void {
if (theme.getGlobalSettings().activeLinkForeground) {
cssRules.push(`.monaco-editor.${theme.getSelector()} .detected-link-active { color: ${new Color(theme.getGlobalSettings().activeLinkForeground)} !important; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .goto-definition-link { color: ${new Color(theme.getGlobalSettings().activeLinkForeground)} !important; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .detected-link-active { color: ${Color.fromHex(theme.getGlobalSettings().activeLinkForeground)} !important; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .goto-definition-link { color: ${Color.fromHex(theme.getGlobalSettings().activeLinkForeground)} !important; }`);
}
if (theme.getGlobalSettings().linkForeground) {
cssRules.push(`.monaco-editor.${theme.getSelector()} .detected-link { color: ${new Color(theme.getGlobalSettings().linkForeground)} !important; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .detected-link { color: ${Color.fromHex(theme.getGlobalSettings().linkForeground)} !important; }`);
}
}
}
@@ -231,7 +231,7 @@ class EditorSelectionStyleRules extends EditorStyleRules {
if (theme.getGlobalSettings().inactiveSelection) {
this.addBackgroundColorRule(theme, '.selected-text', theme.getGlobalSettings().inactiveSelection, cssRules);
} else if (theme.getGlobalSettings().selection) {
let selection = new Color(theme.getGlobalSettings().selection);
let selection = Color.fromHex(theme.getGlobalSettings().selection);
this.addBackgroundColorRule(theme, '.selected-text', selection.transparent(0.5), cssRules);
}
@@ -244,12 +244,12 @@ class EditorSelectionStyleRules extends EditorStyleRules {
private getSelectionHighlightColor(theme: Theme) {
if (theme.getGlobalSettings().selectionHighlight) {
return new Color(theme.getGlobalSettings().selectionHighlight);
return Color.fromHex(theme.getGlobalSettings().selectionHighlight);
}
if (theme.getGlobalSettings().selection && theme.getGlobalSettings().background) {
let selection = new Color(theme.getGlobalSettings().selection);
let background = new Color(theme.getGlobalSettings().background);
let selection = Color.fromHex(theme.getGlobalSettings().selection);
let background = Color.fromHex(theme.getGlobalSettings().background);
return deriveLessProminentColor(selection, background);
}
@@ -282,8 +282,8 @@ class EditorReferenceSearchStyleRules extends EditorStyleRules {
class EditorLineHighlightStyleRules extends EditorStyleRules {
public getCssRules(theme: Theme, cssRules: string[]): void {
if (theme.getGlobalSettings().lineHighlight) {
cssRules.push(`.monaco-editor.${theme.getSelector()} .view-overlays .current-line { background-color: ${new Color(theme.getGlobalSettings().lineHighlight)}; border: none; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .margin-view-overlays .current-line-margin { background-color: ${new Color(theme.getGlobalSettings().lineHighlight)}; border: none; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .view-overlays .current-line { background-color: ${Color.fromHex(theme.getGlobalSettings().lineHighlight)}; border: none; }`);
cssRules.push(`.monaco-editor.${theme.getSelector()} .margin-view-overlays .current-line-margin { background-color: ${Color.fromHex(theme.getGlobalSettings().lineHighlight)}; border: none; }`);
}
this.addBackgroundColorRule(theme, '.rangeHighlight', theme.getGlobalSettings().rangeHighlight, cssRules);
}
@@ -293,7 +293,7 @@ class EditorCursorStyleRules extends EditorStyleRules {
public getCssRules(theme: Theme, cssRules: string[]): void {
let themeSelector = theme.getSelector();
if (theme.getGlobalSettings().caret) {
let caret = new Color(theme.getGlobalSettings().caret);
let caret = Color.fromHex(theme.getGlobalSettings().caret);
let oppositeCaret = caret.opposite();
cssRules.push(`.monaco-editor.${themeSelector} .cursor { background-color: ${caret}; border-color: ${caret}; color: ${oppositeCaret}; }`);
}
@@ -303,7 +303,7 @@ class EditorCursorStyleRules extends EditorStyleRules {
class EditorWhiteSpaceStyleRules extends EditorStyleRules {
public getCssRules(theme: Theme, cssRules: string[]): void {
if (theme.getGlobalSettings().invisibles) {
let invisibles = new Color(theme.getGlobalSettings().invisibles);
let invisibles = Color.fromHex(theme.getGlobalSettings().invisibles);
cssRules.push(`.vs-whitespace { color: ${invisibles} !important; }`);
}
}
@@ -320,10 +320,10 @@ class EditorIndentGuidesStyleRules extends EditorStyleRules {
private getColor(theme: ThemeGlobalSettings): Color {
if (theme.guide) {
return new Color(theme.guide);
return Color.fromHex(theme.guide);
}
if (theme.invisibles) {
return new Color(theme.invisibles);
return Color.fromHex(theme.invisibles);
}
return null;
}