From b6c886837f7fddd75de2a0b320ec448c34193810 Mon Sep 17 00:00:00 2001 From: Thomas Zilz Date: Wed, 11 Oct 2017 20:24:26 +0200 Subject: [PATCH] Add support for dimmed characters (faint) (#1043) * Add support for dimmed character style --- src/InputHandler.ts | 28 +++++++++++++++++----------- src/renderer/BaseRenderLayer.ts | 15 ++++++++++++--- src/renderer/TextRenderLayer.ts | 2 +- src/renderer/Types.ts | 3 ++- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 000e58eaef..c953a2505d 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -9,6 +9,7 @@ import { C0 } from './EscapeSequences'; import { DEFAULT_CHARSET } from './Charsets'; import { CharData } from './Types'; import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer'; +import { FLAGS } from './renderer/Types'; /** * The terminal's standard implementation of IInputHandler, this handles all @@ -1107,6 +1108,7 @@ export class InputHandler implements IInputHandler { * CSI Pm m Character Attributes (SGR). * Ps = 0 -> Normal (default). * Ps = 1 -> Bold. + * Ps = 2 -> Faint, decreased intensity (ISO 6429). * Ps = 4 -> Underlined. * Ps = 5 -> Blink (appears as Bold). * Ps = 7 -> Inverse. @@ -1206,35 +1208,39 @@ export class InputHandler implements IInputHandler { // bg = 0x1ff; } else if (p === 1) { // bold text - flags |= 1; + flags |= FLAGS.BOLD; } else if (p === 4) { // underlined text - flags |= 2; + flags |= FLAGS.UNDERLINE; } else if (p === 5) { // blink - flags |= 4; + flags |= FLAGS.BLINK; } else if (p === 7) { // inverse and positive // test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m' - flags |= 8; + flags |= FLAGS.INVERSE; } else if (p === 8) { // invisible - flags |= 16; + flags |= FLAGS.INVISIBLE; + } else if (p === 2) { + // dimmed text + flags |= FLAGS.DIM; } else if (p === 22) { - // not bold - flags &= ~1; + // not bold nor faint + flags &= ~FLAGS.BOLD; + flags &= ~FLAGS.DIM; } else if (p === 24) { // not underlined - flags &= ~2; + flags &= ~FLAGS.UNDERLINE; } else if (p === 25) { // not blink - flags &= ~4; + flags &= ~FLAGS.BLINK; } else if (p === 27) { // not inverse - flags &= ~8; + flags &= ~FLAGS.INVERSE; } else if (p === 28) { // not invisible - flags &= ~16; + flags &= ~FLAGS.INVISIBLE; } else if (p === 39) { // reset fg fg = (this._terminal.defAttr >> 9) & 0x1ff; diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index a167b3b164..67c704d07e 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -10,6 +10,7 @@ import { CharData } from '../Types'; import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; export const INVERTED_DEFAULT_COLOR = -1; +const DIM_OPACITY = 0.5; export abstract class BaseRenderLayer implements IRenderLayer { private _canvas: HTMLCanvasElement; @@ -223,7 +224,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { * This is used to validate whether a cached image can be used. * @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): void { + protected drawChar(terminal: ITerminal, char: string, code: number, width: number, x: number, y: number, fg: number, bg: number, bold: boolean, dim: boolean): void { let colorIndex = 0; if (fg < 256) { colorIndex = fg + 2; @@ -241,11 +242,15 @@ export abstract class BaseRenderLayer implements IRenderLayer { // 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; + // Apply alpha to dim the character + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, colorIndex * charAtlasCellHeight, charAtlasCellWidth, this._scaledCharHeight, x * this._scaledCharWidth, y * this._scaledLineHeight + this._scaledLineDrawY, charAtlasCellWidth, this._scaledCharHeight); } else { - this._drawUncachedChar(terminal, char, width, fg, x, y, bold); + this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim); } // This draws the atlas (for debugging purposes) // this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); @@ -263,7 +268,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { * @param x The column to draw at. * @param y The row to draw at. */ - private _drawUncachedChar(terminal: ITerminal, char: string, width: number, fg: number, x: number, y: number, bold: boolean): void { + private _drawUncachedChar(terminal: ITerminal, char: string, width: number, fg: number, x: number, y: number, bold: boolean, dim: boolean): void { this._ctx.save(); this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; if (bold) { @@ -288,6 +293,10 @@ export abstract class BaseRenderLayer implements IRenderLayer { this._ctx.rect(0, y * this._scaledLineHeight + this._scaledLineDrawY, terminal.cols * this._scaledCharWidth, this._scaledCharHeight); this._ctx.clip(); + // Apply alpha to dim the character + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } // Draw the character this._ctx.fillText(char, x * this._scaledCharWidth, y * this._scaledLineHeight + this._scaledLineDrawY); this._ctx.restore(); diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 996e17286d..2ecb6ec6e8 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -185,7 +185,7 @@ export class TextRenderLayer extends BaseRenderLayer { this.fillBottomLineAtCells(x, y); } - this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & FLAGS.BOLD)); + this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & FLAGS.BOLD), !!(flags & FLAGS.DIM)); this._ctx.restore(); } diff --git a/src/renderer/Types.ts b/src/renderer/Types.ts index b1a930f9d0..31705a3f89 100644 --- a/src/renderer/Types.ts +++ b/src/renderer/Types.ts @@ -11,5 +11,6 @@ export enum FLAGS { UNDERLINE = 2, BLINK = 4, INVERSE = 8, - INVISIBLE = 16 + INVISIBLE = 16, + DIM = 32 };