From fd868044fd4c6eb819a3dbdf429bd61b2aa59b59 Mon Sep 17 00:00:00 2001 From: ivanwonder Date: Tue, 12 Nov 2019 10:06:51 +0800 Subject: [PATCH] add a helper to make color opaque --- src/browser/Color.test.ts | 24 ++++++++++++++++++- src/browser/Color.ts | 9 +++++++ .../renderer/atlas/DynamicCharAtlas.ts | 12 +++------- src/browser/renderer/dom/DomRenderer.ts | 5 ++-- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/browser/Color.test.ts b/src/browser/Color.test.ts index 005e73768..7dea98e2e 100644 --- a/src/browser/Color.test.ts +++ b/src/browser/Color.test.ts @@ -4,7 +4,7 @@ */ import { assert } from 'chai'; -import { blend, fromCss, toPaddedHex, toCss, toRgba, fromRgba } from 'browser/Color'; +import { blend, fromCss, toPaddedHex, toCss, toRgba, fromRgba, opaque } from 'browser/Color'; describe('Color', () => { describe('blend', () => { @@ -157,4 +157,26 @@ describe('Color', () => { assert.deepEqual(fromRgba(0xffffffff), [0xff, 0xff, 0xff, 0xff]); }); }); + + describe('opaque', () => { + it('should make the color opaque', () => { + assert.deepEqual(opaque({ css: '#00000000', rgba: 0x00000000 }), { css: '#000000', rgba: 0x000000FF }); + assert.deepEqual(opaque({ css: '#10101010', rgba: 0x10101010 }), { css: '#101010', rgba: 0x101010FF }); + assert.deepEqual(opaque({ css: '#20202020', rgba: 0x20202020 }), { css: '#202020', rgba: 0x202020FF }); + assert.deepEqual(opaque({ css: '#30303030', rgba: 0x30303030 }), { css: '#303030', rgba: 0x303030FF }); + assert.deepEqual(opaque({ css: '#40404040', rgba: 0x40404040 }), { css: '#404040', rgba: 0x404040FF }); + assert.deepEqual(opaque({ css: '#50505050', rgba: 0x50505050 }), { css: '#505050', rgba: 0x505050FF }); + assert.deepEqual(opaque({ css: '#60606060', rgba: 0x60606060 }), { css: '#606060', rgba: 0x606060FF }); + assert.deepEqual(opaque({ css: '#70707070', rgba: 0x70707070 }), { css: '#707070', rgba: 0x707070FF }); + assert.deepEqual(opaque({ css: '#80808080', rgba: 0x80808080 }), { css: '#808080', rgba: 0x808080FF }); + assert.deepEqual(opaque({ css: '#90909090', rgba: 0x90909090 }), { css: '#909090', rgba: 0x909090FF }); + assert.deepEqual(opaque({ css: '#a0a0a0a0', rgba: 0xa0a0a0a0 }), { css: '#a0a0a0', rgba: 0xa0a0a0FF }); + assert.deepEqual(opaque({ css: '#b0b0b0b0', rgba: 0xb0b0b0b0 }), { css: '#b0b0b0', rgba: 0xb0b0b0FF }); + assert.deepEqual(opaque({ css: '#c0c0c0c0', rgba: 0xc0c0c0c0 }), { css: '#c0c0c0', rgba: 0xc0c0c0FF }); + assert.deepEqual(opaque({ css: '#d0d0d0d0', rgba: 0xd0d0d0d0 }), { css: '#d0d0d0', rgba: 0xd0d0d0FF }); + assert.deepEqual(opaque({ css: '#e0e0e0e0', rgba: 0xe0e0e0e0 }), { css: '#e0e0e0', rgba: 0xe0e0e0FF }); + assert.deepEqual(opaque({ css: '#f0f0f0f0', rgba: 0xf0f0f0f0 }), { css: '#f0f0f0', rgba: 0xf0f0f0FF }); + assert.deepEqual(opaque({ css: '#ffffffff', rgba: 0xffffffff }), { css: '#ffffff', rgba: 0xffffffFF }); + }); + }); }); diff --git a/src/browser/Color.ts b/src/browser/Color.ts index a9db22155..bc4f7d139 100644 --- a/src/browser/Color.ts +++ b/src/browser/Color.ts @@ -51,3 +51,12 @@ export function toRgba(r: number, g: number, b: number, a: number = 0xFF): numbe export function fromRgba(value: number): [number, number, number, number] { return [(value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF]; } + +export function opaque(color: IColor): IColor { + const rgba = (color.rgba | 0xFF) >>> 0; + const [r, g, b] = fromRgba(rgba); + return { + css: toCss(r, g, b), + rgba + }; +} diff --git a/src/browser/renderer/atlas/DynamicCharAtlas.ts b/src/browser/renderer/atlas/DynamicCharAtlas.ts index 4ddaf2bde..84a501602 100644 --- a/src/browser/renderer/atlas/DynamicCharAtlas.ts +++ b/src/browser/renderer/atlas/DynamicCharAtlas.ts @@ -11,7 +11,7 @@ import { LRUMap } from 'browser/renderer/atlas/LRUMap'; import { isFirefox, isSafari } from 'common/Platform'; import { IColor } from 'browser/Types'; import { throwIfFalsy } from 'browser/renderer/RendererUtils'; -import { fromRgba, toCss } from 'browser/Color'; +import { opaque } 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. @@ -223,7 +223,7 @@ export class DynamicCharAtlas extends BaseCharAtlas { private _getForegroundColor(glyph: IGlyphIdentifier): IColor { if (glyph.fg === INVERTED_DEFAULT_COLOR) { - return this._config.colors.background; + return opaque(this._config.colors.background); } else if (glyph.fg < 256) { // 256 color support return this._getColorFromAnsiIndex(glyph.fg); @@ -254,13 +254,7 @@ export class DynamicCharAtlas extends BaseCharAtlas { `${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`; this._tmpCtx.textBaseline = 'middle'; - const fgColor = this._getForegroundColor(glyph); - this._tmpCtx.fillStyle = fgColor.css; - - if (glyph.fg === INVERTED_DEFAULT_COLOR) { - const rgba = fromRgba(fgColor.rgba); - this._tmpCtx.fillStyle = toCss(rgba[0], rgba[1], rgba[2]); - } + this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css; // Apply alpha to dim the character if (glyph.dim) { diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index e11a413d7..d776f608f 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -11,7 +11,7 @@ import { IColorSet, ILinkifierEvent, ILinkifier } from 'browser/Types'; import { ICharSizeService } from 'browser/services/Services'; import { IOptionsService, IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { fromRgba, toCss } from 'browser/Color'; +import { opaque } from 'browser/Color'; const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-'; const ROW_CONTAINER_CLASS = 'xterm-rows'; @@ -230,9 +230,8 @@ export class DomRenderer extends Disposable implements IRenderer { `${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` + `${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`; }); - const rgba = fromRgba(this._colors.background.rgba); styles += - `${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${toCss(rgba[0], rgba[1], rgba[2])}; }` + + `${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${opaque(this._colors.background).css}; }` + `${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${this._colors.foreground.css}; }`; this._themeStyleElement.innerHTML = styles;