diff --git a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts index b40c27cc9..e1b0474f4 100644 --- a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts +++ b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts @@ -11,6 +11,7 @@ import { throwIfFalsy } from '../WebglUtils'; import { IColor } from 'browser/Types'; import { IDisposable } from 'xterm'; import { AttributeData } from 'common/buffer/AttributeData'; +import { toCss, ensureContrastRatioRgba } from 'browser/Color'; // In practice we're probably never going to exhaust a texture this large. For debugging purposes, // however, it can be useful to set this to a really tiny value, to verify that LRU eviction works. @@ -543,120 +544,3 @@ function getBgColor(bg: number): number { default: return -1; // CM_DEFAULT defaults to -1 } } - -export function toCss(r: number, g: number, b: number): string { - return `#${toPaddedHex(r)}${toPaddedHex(g)}${toPaddedHex(b)}`; -} - -export function toRgba(r: number, g: number, b: number, a: number = 0xFF): number { - // >>> 0 forces an unsigned int - return (r << 24 | g << 16 | b << 8 | a) >>> 0; -} - -/** - * Gets the relative luminance of an RGB color, this is useful in determining the contrast ratio - * between two colors. - * @param rgb The color to use. - * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef - */ -export function rgbRelativeLuminance(rgb: number): number { - return rgbRelativeLuminance2( - (rgb >> 16) & 0xFF, - (rgb >> 8 ) & 0xFF, - (rgb ) & 0xFF); -} - -export function rgbRelativeLuminance2(r: number, g: number, b: number): number { - const rs = r / 255; - const gs = g / 255; - const bs = b / 255; - const rr = rs <= 0.03928 ? rs / 12.92 : Math.pow((rs + 0.055) / 1.055, 2.4); - const rg = gs <= 0.03928 ? gs / 12.92 : Math.pow((gs + 0.055) / 1.055, 2.4); - const rb = bs <= 0.03928 ? bs / 12.92 : Math.pow((bs + 0.055) / 1.055, 2.4); - return rr * 0.2126 + rg * 0.7152 + rb * 0.0722; -} - -/** - * Gets the contrast ratio between two relative luminance values. - * @param l1 The first relative luminance. - * @param l2 The first relative luminance. - * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef - */ -export function contrastRatio(l1: number, l2: number): number { - if (l1 < l2) { - return (l2 + 0.05) / (l1 + 0.05); - } - return (l1 + 0.05) / (l2 + 0.05); -} - -function rgbaToColor(r: number, g: number, b: number): IColor { - return { - css: toCss(r, g, b), - rgba: toRgba(r, g, b) - }; -} - -export function ensureContrastRatioRgba(bgRgba: number, fgRgba: number, ratio: number): number | undefined { - const bgL = rgbRelativeLuminance(bgRgba >> 8); - const fgL = rgbRelativeLuminance(fgRgba >> 8); - const cr = contrastRatio(bgL, fgL); - if (cr < ratio) { - if (fgL < bgL) { - return reduceLuminance(bgRgba, fgRgba, ratio); - } - return increaseLuminance(bgRgba, fgRgba, ratio); - } - return undefined; -} - -export function ensureContrastRatio(bg: IColor, fg: IColor, ratio: number): IColor | undefined { - const result = ensureContrastRatioRgba(bg.rgba, fg.rgba, ratio); - if (!result) { - return undefined; - } - return rgbaToColor( - (result >> 24 & 0xFF), - (result >> 16 & 0xFF), - (result >> 8 & 0xFF) - ); -} - -export function reduceLuminance(bgRgba: number, fgRgba: number, ratio: number): number { - // This is a naive but fast approach to reducing luminance as converting to - // HSL and back is expensive - const bgR = (bgRgba >> 24) & 0xFF; - const bgG = (bgRgba >> 16) & 0xFF; - const bgB = (bgRgba >> 8) & 0xFF; - let fgR = (fgRgba >> 24) & 0xFF; - let fgG = (fgRgba >> 16) & 0xFF; - let fgB = (fgRgba >> 8) & 0xFF; - let cr = contrastRatio(rgbRelativeLuminance2(fgR, fgB, fgG), rgbRelativeLuminance2(bgR, bgG, bgB)); - while (cr < ratio && (fgR > 0 || fgG > 0 || fgB > 0)) { - // Reduce by 10% until the ratio is hit - fgR -= Math.max(0, Math.ceil(fgR * 0.1)); - fgG -= Math.max(0, Math.ceil(fgG * 0.1)); - fgB -= Math.max(0, Math.ceil(fgB * 0.1)); - cr = contrastRatio(rgbRelativeLuminance2(fgR, fgB, fgG), rgbRelativeLuminance2(bgR, bgG, bgB)); - } - return fgR << 24 | fgG << 16 | fgB << 8 | 0xFF; -} - -export function increaseLuminance(bgRgba: number, fgRgba: number, ratio: number): number { - // This is a naive but fast approach to increasing luminance as converting to - // HSL and back is expensive - const bgR = (bgRgba >> 24) & 0xFF; - const bgG = (bgRgba >> 16) & 0xFF; - const bgB = (bgRgba >> 8) & 0xFF; - let fgR = (fgRgba >> 24) & 0xFF; - let fgG = (fgRgba >> 16) & 0xFF; - let fgB = (fgRgba >> 8) & 0xFF; - let cr = contrastRatio(rgbRelativeLuminance2(fgR, fgB, fgG), rgbRelativeLuminance2(bgR, bgG, bgB)); - while (cr < ratio && (fgR < 0xFF || fgG < 0xFF || fgB < 0xFF)) { - // Increase by 10% until the ratio is hit - fgR = Math.min(0xFF, fgR + Math.ceil((255 - fgR) * 0.1)); - fgG = Math.min(0xFF, fgG + Math.ceil((255 - fgG) * 0.1)); - fgB = Math.min(0xFF, fgB + Math.ceil((255 - fgB) * 0.1)); - cr = contrastRatio(rgbRelativeLuminance2(fgR, fgB, fgG), rgbRelativeLuminance2(bgR, bgG, bgB)); - } - return fgR << 24 | fgG << 16 | fgB << 8 | 0xFF; -}