diff --git a/src/Terminal.ts b/src/Terminal.ts index ba1fff3d..05781b96 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -103,6 +103,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = { cursorStyle: 'block', bellSound: DEFAULT_BELL_SOUND, bellStyle: 'none', + drawBoldTextInBrightColors: true, enableBold: true, fontFamily: 'courier-new, courier, monospace', fontSize: 15, diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 7a655163..ca848b73 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -243,23 +243,20 @@ export abstract class BaseRenderLayer implements IRenderLayer { * @param bold Whether the text is bold. */ protected drawChar(terminal: ITerminal, char: string, code: number, width: number, x: number, y: number, fg: number, bg: number, bold: boolean, dim: boolean, italic: boolean): void { - let colorIndex = 0; - if (fg < 256) { - colorIndex = fg + 2; - } else { - // If default color and bold - if (bold && terminal.options.enableBold) { - colorIndex = 1; - } - } const isAscii = code < 256; - // A color is basic if it is one of the standard normal or bold weight - // colors of the characters held in the char atlas. Note that this excludes - // the normal weight _light_ color characters. - const isBasicColor = (colorIndex > 1 && fg < 16) && (fg < 8 || bold); + // A color is basic if it is one of the 4 bit ANSI colors. + const isBasicColor = fg < 16; const isDefaultColor = fg >= 256; const isDefaultBackground = bg >= 256; + const drawInBrightColor = (terminal.options.drawBoldTextInBrightColors && bold && fg < 8); if (this._charAtlas && isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground && !italic) { + let colorIndex: number; + if (isDefaultColor) { + colorIndex = (bold && terminal.options.enableBold ? 1 : 0); + } else { + colorIndex = 2 + fg + (bold && terminal.options.enableBold ? 16 : 0) + (drawInBrightColor ? 8 : 0); + } + // 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; @@ -269,14 +266,6 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._ctx.globalAlpha = DIM_OPACITY; } - // Draw the non-bold version of the same color if bold is not enabled - if (bold && !terminal.options.enableBold) { - // Ignore default color as it's not touched above - if (colorIndex > 1) { - colorIndex -= 8; - } - } - this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, colorIndex * charAtlasCellHeight, @@ -287,7 +276,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { charAtlasCellWidth, this._scaledCharHeight); } else { - this._drawUncachedChar(terminal, char, width, fg, x, y, bold && terminal.options.enableBold, dim, italic); + this._drawUncachedChar(terminal, char, width, fg + (drawInBrightColor ? 8 : 0), x, y, bold && terminal.options.enableBold, dim, italic); } // This draws the atlas (for debugging purposes) // this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 8d8d6d4d..0dca11b2 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -116,13 +116,6 @@ export class TextRenderLayer extends BaseRenderLayer { } } - if (flags & FLAGS.BOLD) { - // Convert the FG color to the bold variant - if (fg < 8) { - fg += 8; - } - } - callback(code, char, width, x, y, fg, bg, flags); } } diff --git a/src/shared/atlas/CharAtlasGenerator.ts b/src/shared/atlas/CharAtlasGenerator.ts index fc83c7ce..ba9b0d27 100644 --- a/src/shared/atlas/CharAtlasGenerator.ts +++ b/src/shared/atlas/CharAtlasGenerator.ts @@ -27,7 +27,7 @@ export function generateCharAtlas(context: Window, canvasFactory: (width: number const cellHeight = config.scaledCharHeight + CHAR_ATLAS_CELL_SPACING; const canvas = canvasFactory( /*255 ascii chars*/255 * cellWidth, - (/*default+default bold*/2 + /*0-15*/16) * cellHeight + (/*default+default bold*/2 + /*0-15*/16 + /*0-15 bold*/16) * cellHeight ); const ctx = canvas.getContext('2d', {alpha: config.allowTransparency}); @@ -64,10 +64,6 @@ export function generateCharAtlas(context: Window, canvasFactory: (width: number // Colors 0-15 ctx.font = getFont(config.fontWeight, config); for (let colorIndex = 0; colorIndex < 16; colorIndex++) { - // colors 8-15 are bold - if (colorIndex === 8) { - ctx.font = getFont(config.fontWeightBold, config); - } const y = (colorIndex + 2) * cellHeight; // Draw ascii characters for (let i = 0; i < 256; i++) { @@ -80,6 +76,22 @@ export function generateCharAtlas(context: Window, canvasFactory: (width: number ctx.restore(); } } + + // Colors 0-15 bold + ctx.font = getFont(config.fontWeightBold, config); + for (let colorIndex = 0; colorIndex < 16; colorIndex++) { + const y = (colorIndex + 2 + 16) * cellHeight; + // Draw ascii characters + for (let i = 0; i < 256; i++) { + ctx.save(); + ctx.beginPath(); + ctx.rect(i * cellWidth, y, cellWidth, cellHeight); + ctx.clip(); + ctx.fillStyle = config.colors.ansi[colorIndex].css; + ctx.fillText(String.fromCharCode(i), i * cellWidth, y); + ctx.restore(); + } + } ctx.restore(); // Support is patchy for createImageBitmap at the moment, pass a canvas back diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 65d533de..3107589e 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -54,6 +54,11 @@ declare module 'xterm' { */ disableStdin?: boolean; + /** + * Whether to draw bold text in bright colors. The default is true. + */ + drawBoldTextInBrightColors?: boolean; + /** * Whether to enable the rendering of bold text. *