From 9cabb93b8b11e41f6eeac45943b597cbd0d0f691 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 2 Sep 2017 11:08:43 -0700 Subject: [PATCH] Organize temporary color handling code --- src/Terminal.ts | 210 +++++++++++--------------- src/renderer/BaseRenderLayer.ts | 5 +- src/renderer/ColorManager.ts | 2 +- src/renderer/ForegroundRenderLayer.ts | 1 - 4 files changed, 95 insertions(+), 123 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index c572fefb..59d39e5a 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -41,6 +41,7 @@ import { getRawByteCoords } from './utils/Mouse'; import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme } from './Interfaces'; import { BellSound } from './utils/Sounds'; +import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; // Declare for RequireJS in loadAddon declare var define: any; @@ -61,80 +62,6 @@ const WRITE_BUFFER_PAUSE_THRESHOLD = 5; */ const WRITE_BATCH_SIZE = 300; -// TODO: Most of the color code should be removed after truecolor is implemented -// Colors 0-15 -const tangoColors: string[] = [ - // dark: - '#2e3436', - '#cc0000', - '#4e9a06', - '#c4a000', - '#3465a4', - '#75507b', - '#06989a', - '#d3d7cf', - // bright: - '#555753', - '#ef2929', - '#8ae234', - '#fce94f', - '#729fcf', - '#ad7fa8', - '#34e2e2', - '#eeeeec' -]; - -// Colors 0-15 + 16-255 -// Much thanks to TooTallNate for writing this. -const defaultColors: string[] = (function(): string[] { - let colors = tangoColors.slice(); - let r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; - let i; - - // 16-231 - i = 0; - for (; i < 216; i++) { - out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]); - } - - // 232-255 (grey) - i = 0; - let c: number; - for (; i < 24; i++) { - c = 8 + i * 10; - out(c, c, c); - } - - function out(r: number, g: number, b: number): void { - colors.push('#' + hex(r) + hex(g) + hex(b)); - } - - function hex(c: number): string { - let s = c.toString(16); - return s.length < 2 ? '0' + s : s; - } - - return colors; -})(); - -const _colors: string[] = defaultColors.slice(); - -const vcolors: number[][] = (function(): number[][] { - const out: number[][] = []; - let color; - - for (let i = 0; i < 256; i++) { - color = parseInt(defaultColors[i].substring(1), 16); - out.push([ - (color >> 16) & 0xff, - (color >> 8) & 0xff, - color & 0xff - ]); - } - - return out; -})(); - const DEFAULT_OPTIONS: ITerminalOptions = { convertEol: false, termName: 'xterm', @@ -2139,44 +2066,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT return false; } - // Expose to InputHandler - // TODO: Revise when truecolor is introduced. + // TODO: Remove when true color is implemented public matchColor(r1: number, g1: number, b1: number): number { - const hash = (r1 << 16) | (g1 << 8) | b1; - - if (matchColorCache[hash] != null) { - return matchColorCache[hash]; - } - - let ldiff = Infinity; - let li = -1; - let i = 0; - let c: number[]; - let r2: number; - let g2: number; - let b2: number; - let diff: number; - - for (; i < vcolors.length; i++) { - c = vcolors[i]; - r2 = c[0]; - g2 = c[1]; - b2 = c[2]; - - diff = matchColorDistance(r1, g1, b1, r2, g2, b2); - - if (diff === 0) { - li = i; - break; - } - - if (diff < ldiff) { - ldiff = diff; - li = i; - } - } - - return matchColorCache[hash] = li; + return matchColor_(r1, g1, b1); } private visualBell(): boolean { @@ -2235,17 +2127,95 @@ function isThirdLevelShift(browser: IBrowser, ev: KeyboardEvent): boolean { return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47); } -const matchColorCache: {[colorRGBHash: number]: number} = {}; - -// http://stackoverflow.com/questions/1633828 -const matchColorDistance = function(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number): number { - return Math.pow(30 * (r1 - r2), 2) - + Math.pow(59 * (g1 - g2), 2) - + Math.pow(11 * (b1 - b2), 2); -}; - function wasMondifierKeyOnlyEvent(ev: KeyboardEvent): boolean { return ev.keyCode === 16 || // Shift ev.keyCode === 17 || // Ctrl ev.keyCode === 18; // Alt } + +/** + * TODO: + * The below color-related code can be removed when true color is implemented. + * It's only purpose is to match true color requests with the closest matching + * ANSI color code. + */ + +// Colors 0-15 + 16-255 +// Much thanks to TooTallNate for writing this. +const vcolors: number[][] = (function(): number[][] { + const result = DEFAULT_ANSI_COLORS.map(c => { + c = c.substring(1); + return [ + parseInt(c.substring(0, 2), 16), + parseInt(c.substring(2, 4), 16), + parseInt(c.substring(4, 6), 16) + ]; + }); + const r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + + // 16-231 + for (let i = 0; i < 216; i++) { + result.push([ + r[(i / 36) % 6 | 0], + r[(i / 6) % 6 | 0], + r[i % 6] + ]); + } + + // 232-255 (grey) + let c: number; + for (let i = 0; i < 24; i++) { + c = 8 + i * 10; + result.push([c, c, c]); + } + + return result; +})(); + +const matchColorCache: {[colorRGBHash: number]: number} = {}; + +// http://stackoverflow.com/questions/1633828 +function matchColorDistance(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number): number { + return Math.pow(30 * (r1 - r2), 2) + + Math.pow(59 * (g1 - g2), 2) + + Math.pow(11 * (b1 - b2), 2); +}; + + +function matchColor_(r1: number, g1: number, b1: number): number { + const hash = (r1 << 16) | (g1 << 8) | b1; + + if (matchColorCache[hash] != null) { + return matchColorCache[hash]; + } + + let ldiff = Infinity; + let li = -1; + let i = 0; + let c: number[]; + let r2: number; + let g2: number; + let b2: number; + let diff: number; + + for (; i < vcolors.length; i++) { + c = vcolors[i]; + r2 = c[0]; + g2 = c[1]; + b2 = c[2]; + + diff = matchColorDistance(r1, g1, b1, r2, g2, b2); + + if (diff === 0) { + li = i; + break; + } + + if (diff < ldiff) { + ldiff = diff; + li = i; + } + } + + return matchColorCache[hash] = li; +} diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 20768c8a..57427122 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -128,7 +128,10 @@ export abstract class BaseRenderLayer implements IRenderLayer { if (fg < 256) { colorIndex = fg + 1; } - if (code < 256 && (colorIndex > 0 || fg >= 256)) { + const isAscii = code < 256; + const isBasicColor = (colorIndex > 0 && fg < 16); + const isDefaultColor = fg >= 256; + if (isAscii && (isBasicColor || isDefaultColor)) { // ImageBitmap's draw about twice as fast as from a canvas const charAtlasCellWidth = this.scaledCharWidth + CHAR_ATLAS_CELL_SPACING; const charAtlasCellHeight = this.scaledCharHeight + CHAR_ATLAS_CELL_SPACING; diff --git a/src/renderer/ColorManager.ts b/src/renderer/ColorManager.ts index 341e4ca5..6b7f88c1 100644 --- a/src/renderer/ColorManager.ts +++ b/src/renderer/ColorManager.ts @@ -23,7 +23,7 @@ export enum COLOR_CODES { BRIGHT_WHITE = 15 } -const DEFAULT_ANSI_COLORS = [ +export const DEFAULT_ANSI_COLORS = [ // dark: '#2e3436', '#cc0000', diff --git a/src/renderer/ForegroundRenderLayer.ts b/src/renderer/ForegroundRenderLayer.ts index 182c9ead..1f579f91 100644 --- a/src/renderer/ForegroundRenderLayer.ts +++ b/src/renderer/ForegroundRenderLayer.ts @@ -101,7 +101,6 @@ export class ForegroundRenderLayer extends BaseRenderLayer { } const width: number = charData[CHAR_DATA_WIDTH_INDEX]; - this.drawChar(terminal, char, code, width, x, y, fg); this._ctx.restore();