Skip to content

Commit 1db1770

Browse files
authored
Merge pull request #1739 from Tyriar/1737_inverse_dynamic_cache
Allow inverse colors to be stored in glyph keys, fix inverted colors in DOM renderer
2 parents 929d722 + c6f1de7 commit 1db1770

File tree

11 files changed

+47
-29
lines changed

11 files changed

+47
-29
lines changed

src/Buffer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import { CharData, ITerminal, IBuffer, IBufferLine, BufferIndex, IBufferStringIt
88
import { EventEmitter } from './common/EventEmitter';
99
import { IMarker } from 'xterm';
1010
import { BufferLine, BufferLineTypedArray } from './BufferLine';
11+
import { DEFAULT_COLOR } from './renderer/atlas/Types';
1112

12-
export const DEFAULT_ATTR = (0 << 18) | (257 << 9) | (256 << 0);
13+
export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0);
1314
export const CHAR_DATA_ATTR_INDEX = 0;
1415
export const CHAR_DATA_CHAR_INDEX = 1;
1516
export const CHAR_DATA_WIDTH_INDEX = 2;

src/renderer/BaseRenderLayer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { DIM_OPACITY, INVERTED_DEFAULT_COLOR, IGlyphIdentifier } from './atlas/T
99
import BaseCharAtlas from './atlas/BaseCharAtlas';
1010
import { acquireCharAtlas } from './atlas/CharAtlasCache';
1111
import { CHAR_DATA_CHAR_INDEX } from '../Buffer';
12+
import { is256Color } from './atlas/CharAtlasUtils';
1213

1314
export abstract class BaseRenderLayer implements IRenderLayer {
1415
private _canvas: HTMLCanvasElement;
@@ -298,7 +299,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
298299

299300
if (fg === INVERTED_DEFAULT_COLOR) {
300301
this._ctx.fillStyle = this._colors.background.css;
301-
} else if (fg < 256) {
302+
} else if (is256Color(fg)) {
302303
// 256 color support
303304
this._ctx.fillStyle = this._colors.ansi[fg].css;
304305
} else {

src/renderer/LinkRenderLayer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ILinkHoverEvent, ITerminal, ILinkifierAccessor, LinkHoverEventTypes } f
77
import { IColorSet, IRenderDimensions } from './Types';
88
import { BaseRenderLayer } from './BaseRenderLayer';
99
import { INVERTED_DEFAULT_COLOR } from './atlas/Types';
10+
import { is256Color } from './atlas/CharAtlasUtils';
1011

1112
export class LinkRenderLayer extends BaseRenderLayer {
1213
private _state: ILinkHoverEvent = null;
@@ -42,7 +43,7 @@ export class LinkRenderLayer extends BaseRenderLayer {
4243
private _onLinkHover(e: ILinkHoverEvent): void {
4344
if (e.fg === INVERTED_DEFAULT_COLOR) {
4445
this._ctx.fillStyle = this._colors.background.css;
45-
} else if (e.fg < 256) {
46+
} else if (is256Color(e.fg)) {
4647
// 256 color support
4748
this._ctx.fillStyle = this._colors.ansi[e.fg].css;
4849
} else {

src/renderer/TextRenderLayer.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, NULL_CELL_CODE } from '../Buffer';
77
import { FLAGS, IColorSet, IRenderDimensions, ICharacterJoinerRegistry } from './Types';
88
import { CharData, ITerminal } from '../Types';
9-
import { INVERTED_DEFAULT_COLOR } from './atlas/Types';
9+
import { INVERTED_DEFAULT_COLOR, DEFAULT_COLOR } from './atlas/Types';
1010
import { GridCache } from './GridCache';
1111
import { BaseRenderLayer } from './BaseRenderLayer';
12+
import { is256Color } from './atlas/CharAtlasUtils';
1213

1314
/**
1415
* This CharData looks like a null character, which will forc a clear and render
@@ -143,10 +144,10 @@ export class TextRenderLayer extends BaseRenderLayer {
143144
const temp = bg;
144145
bg = fg;
145146
fg = temp;
146-
if (fg === 256) {
147+
if (fg === DEFAULT_COLOR) {
147148
fg = INVERTED_DEFAULT_COLOR;
148149
}
149-
if (bg === 257) {
150+
if (bg === DEFAULT_COLOR) {
150151
bg = INVERTED_DEFAULT_COLOR;
151152
}
152153
}
@@ -186,7 +187,7 @@ export class TextRenderLayer extends BaseRenderLayer {
186187
let nextFillStyle = null; // null represents default background color
187188
if (bg === INVERTED_DEFAULT_COLOR) {
188189
nextFillStyle = this._colors.foreground.css;
189-
} else if (bg < 256) {
190+
} else if (is256Color(bg)) {
190191
nextFillStyle = this._colors.ansi[bg].css;
191192
}
192193

@@ -230,7 +231,7 @@ export class TextRenderLayer extends BaseRenderLayer {
230231
this._ctx.save();
231232
if (fg === INVERTED_DEFAULT_COLOR) {
232233
this._ctx.fillStyle = this._colors.background.css;
233-
} else if (fg < 256) {
234+
} else if (is256Color(fg)) {
234235
// 256 color support
235236
this._ctx.fillStyle = this._colors.ansi[fg].css;
236237
} else {

src/renderer/atlas/CharAtlasUtils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { ITerminal } from '../../Types';
77
import { IColorSet } from '../Types';
88
import { ICharAtlasConfig } from '../../shared/atlas/Types';
9+
import { DEFAULT_COLOR } from './Types';
910

1011
export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig {
1112
// null out some fields that don't matter
@@ -51,3 +52,7 @@ export function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean
5152
a.colors.foreground === b.colors.foreground &&
5253
a.colors.background === b.colors.background;
5354
}
55+
56+
export function is256Color(colorCode: number): boolean {
57+
return colorCode < DEFAULT_COLOR;
58+
}

src/renderer/atlas/DynamicCharAtlas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ interface IGlyphCacheValue {
4242
inBitmap: boolean;
4343
}
4444

45-
function getGlyphCacheKey(glyph: IGlyphIdentifier): number {
45+
export function getGlyphCacheKey(glyph: IGlyphIdentifier): number {
4646
// Note that this only returns a valid key when code < 256
4747
// Layout:
4848
// 0b00000000000000000000000000000001: italic (1)

src/renderer/atlas/StaticCharAtlas.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
* @license MIT
44
*/
55

6-
import { DIM_OPACITY, IGlyphIdentifier } from './Types';
6+
import { DIM_OPACITY, IGlyphIdentifier, DEFAULT_COLOR } from './Types';
77
import { CHAR_ATLAS_CELL_SPACING, ICharAtlasConfig } from '../../shared/atlas/Types';
88
import { generateStaticCharAtlasTexture } from '../../shared/atlas/CharAtlasGenerator';
99
import BaseCharAtlas from './BaseCharAtlas';
10+
import { is256Color } from './CharAtlasUtils';
1011

1112
export default class StaticCharAtlas extends BaseCharAtlas {
1213
private _texture: HTMLCanvasElement | ImageBitmap;
@@ -41,8 +42,8 @@ export default class StaticCharAtlas extends BaseCharAtlas {
4142
const isAscii = glyph.code < 256;
4243
// A color is basic if it is one of the 4 bit ANSI colors.
4344
const isBasicColor = glyph.fg < 16;
44-
const isDefaultColor = glyph.fg >= 256;
45-
const isDefaultBackground = glyph.bg >= 256;
45+
const isDefaultColor = glyph.fg === DEFAULT_COLOR;
46+
const isDefaultBackground = glyph.bg === DEFAULT_COLOR;
4647
return isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground && !glyph.italic;
4748
}
4849

@@ -58,9 +59,9 @@ export default class StaticCharAtlas extends BaseCharAtlas {
5859
}
5960

6061
let colorIndex = 0;
61-
if (glyph.fg < 256) {
62+
if (is256Color(glyph.fg)) {
6263
colorIndex = 2 + glyph.fg + (glyph.bold ? 16 : 0);
63-
} else {
64+
} else if (glyph.fg === DEFAULT_COLOR) {
6465
// If default color and bold
6566
if (glyph.bold) {
6667
colorIndex = 1;

src/renderer/atlas/Types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* @license MIT
44
*/
55

6-
export const INVERTED_DEFAULT_COLOR = -1;
6+
export const DEFAULT_COLOR = 256;
7+
export const INVERTED_DEFAULT_COLOR = 257;
78
export const DIM_OPACITY = 0.5;
89

910
export interface IGlyphIdentifier {

src/renderer/dom/DomRenderer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { EventEmitter } from '../../common/EventEmitter';
1010
import { ColorManager } from '../ColorManager';
1111
import { RenderDebouncer } from '../../ui/RenderDebouncer';
1212
import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from './DomRendererRowFactory';
13+
import { INVERTED_DEFAULT_COLOR } from '../atlas/Types';
1314

1415
const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
1516
const ROW_CONTAINER_CLASS = 'xterm-rows';
@@ -199,6 +200,9 @@ export class DomRenderer extends EventEmitter implements IRenderer {
199200
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
200201
`${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;
201202
});
203+
styles +=
204+
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${this.colorManager.colors.background.css}; }` +
205+
`${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${this.colorManager.colors.foreground.css}; }`;
202206

203207
this._themeStyleElement.innerHTML = styles;
204208
return this.colorManager.colors;

src/renderer/dom/DomRendererRowFactory.test.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { DEFAULT_ATTR, NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR } from '.
1010
import { FLAGS } from '../Types';
1111
import { BufferLine } from '../../BufferLine';
1212
import { IBufferLine } from '../../Types';
13+
import { DEFAULT_COLOR } from '../atlas/Types';
1314

1415
describe('DomRendererRowFactory', () => {
1516
let dom: jsdom.JSDOM;
@@ -76,7 +77,7 @@ describe('DomRendererRowFactory', () => {
7677
});
7778

7879
it('should add classes for 256 foreground colors', () => {
79-
const defaultAttrNoFgColor = (0 << 9) | (256 << 0);
80+
const defaultAttrNoFgColor = (0 << 9) | (DEFAULT_COLOR << 0);
8081
for (let i = 0; i < 256; i++) {
8182
lineData.set(0, [defaultAttrNoFgColor | (i << 9), 'a', 1, 'a'.charCodeAt(0)]);
8283
const fragment = rowFactory.createRow(lineData, false, undefined, 0, 5, 20);
@@ -87,7 +88,7 @@ describe('DomRendererRowFactory', () => {
8788
});
8889

8990
it('should add classes for 256 background colors', () => {
90-
const defaultAttrNoBgColor = (257 << 9) | (0 << 0);
91+
const defaultAttrNoBgColor = (DEFAULT_ATTR << 9) | (0 << 0);
9192
for (let i = 0; i < 256; i++) {
9293
lineData.set(0, [defaultAttrNoBgColor | (i << 0), 'a', 1, 'a'.charCodeAt(0)]);
9394
const fragment = rowFactory.createRow(lineData, false, undefined, 0, 5, 20);
@@ -106,24 +107,24 @@ describe('DomRendererRowFactory', () => {
106107
});
107108

108109
it('should correctly invert default fg color', () => {
109-
lineData.set(0, [(FLAGS.INVERSE << 18) | (257 << 9) | (1 << 0), 'a', 1, 'a'.charCodeAt(0)]);
110+
lineData.set(0, [(FLAGS.INVERSE << 18) | (DEFAULT_ATTR << 9) | (1 << 0), 'a', 1, 'a'.charCodeAt(0)]);
110111
const fragment = rowFactory.createRow(lineData, false, undefined, 0, 5, 20);
111112
assert.equal(getFragmentHtml(fragment),
112-
'<span class="xterm-fg-1 xterm-bg-15">a</span>'
113+
'<span class="xterm-fg-1 xterm-bg-257">a</span>'
113114
);
114115
});
115116

116117
it('should correctly invert default bg color', () => {
117-
lineData.set(0, [(FLAGS.INVERSE << 18) | (1 << 9) | (256 << 0), 'a', 1, 'a'.charCodeAt(0)]);
118+
lineData.set(0, [(FLAGS.INVERSE << 18) | (1 << 9) | (DEFAULT_COLOR << 0), 'a', 1, 'a'.charCodeAt(0)]);
118119
const fragment = rowFactory.createRow(lineData, false, undefined, 0, 5, 20);
119120
assert.equal(getFragmentHtml(fragment),
120-
'<span class="xterm-fg-0 xterm-bg-1">a</span>'
121+
'<span class="xterm-fg-257 xterm-bg-1">a</span>'
121122
);
122123
});
123124

124125
it('should turn bold fg text bright', () => {
125126
for (let i = 0; i < 8; i++) {
126-
lineData.set(0, [(FLAGS.BOLD << 18) | (i << 9) | (256 << 0), 'a', 1, 'a'.charCodeAt(0)]);
127+
lineData.set(0, [(FLAGS.BOLD << 18) | (i << 9) | (DEFAULT_COLOR << 0), 'a', 1, 'a'.charCodeAt(0)]);
127128
const fragment = rowFactory.createRow(lineData, false, undefined, 0, 5, 20);
128129
assert.equal(getFragmentHtml(fragment),
129130
`<span class="xterm-bold xterm-fg-${i + 8}">a</span>`

0 commit comments

Comments
 (0)