From f4ffb13ece1f06234e75bf538b4668fc81060ded Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 24 Jul 2022 10:59:24 -0700 Subject: [PATCH] Render dim bg in all renderers Fixes #3534 --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 43 ++++++++++++++++++- src/browser/renderer/TextRenderLayer.ts | 9 ++++ .../renderer/dom/DomRendererRowFactory.ts | 7 +++ src/common/Color.ts | 5 +++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 1e385b33..1e255a03 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -12,7 +12,7 @@ import { RectangleRenderer } from './RectangleRenderer'; import { IWebGL2RenderingContext } from './Types'; import { RenderModel, COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel'; import { Disposable } from 'common/Lifecycle'; -import { Attributes, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants'; +import { Attributes, BgFlags, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants'; import { Terminal, IEvent } from 'xterm'; import { IRenderLayer } from './renderLayer/Types'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types'; @@ -24,6 +24,7 @@ import { ICharacterJoinerService } from 'browser/services/Services'; import { CharData, ICellData } from 'common/Types'; import { AttributeData } from 'common/buffer/AttributeData'; import { IDecorationService } from 'common/services/Services'; +import { color, rgba as rgbaNs } from 'common/Color'; export class WebglRenderer extends Disposable implements IRenderer { private _renderLayers: IRenderLayer[]; @@ -418,6 +419,46 @@ export class WebglRenderer extends Disposable implements IRenderer { } } + // Apply dim if there is no override yet as it's the default color, this requires resolving the + // attribute color ahead of time because it's a derivative of it + if (this._workColors.bg & BgFlags.DIM) { + // TODO: Share logic + let rgba: number | undefined; + if (this._workColors.fg & FgFlags.INVERSE) { + switch (this._workColors.fg & Attributes.CM_MASK) { + case Attributes.CM_P16: + case Attributes.CM_P256: + rgba = this._colors.ansi[this._workColors.fg & Attributes.PCOLOR_MASK].rgba; + break; + case Attributes.CM_RGB: + rgba = (this._workColors.fg & Attributes.RGB_MASK) << 8; + break; + case Attributes.CM_DEFAULT: + default: + rgba = this._colors.foreground.rgba; + } + } else { + switch (this._workColors.bg& Attributes.CM_MASK) { + case Attributes.CM_P16: + case Attributes.CM_P256: + rgba = this._colors.ansi[this._workColors.bg& Attributes.PCOLOR_MASK].rgba; + break; + case Attributes.CM_RGB: + rgba = (this._workColors.bg& Attributes.RGB_MASK) << 8; + break; + case Attributes.CM_DEFAULT: + default: + rgba = this._colors.background.rgba; + } + } + bgOverride = color.blend(this._colors.background, rgbaNs.toColor( + (rgba >> 24) & 0xFF, + (rgba >> 16) & 0xFF, + (rgba >> 8) & 0xFF, + 0x80 // 50% opacity + )).rgba >> 8 & 0xFFFFFF; + } + // Convert any overrides from rgba to the fg/bg packed format. This resolves the inverse flag // ahead of time in order to use the correct cache key if (bgOverride !== undefined) { diff --git a/src/browser/renderer/TextRenderLayer.ts b/src/browser/renderer/TextRenderLayer.ts index ef5a9b62..f62819d0 100644 --- a/src/browser/renderer/TextRenderLayer.ts +++ b/src/browser/renderer/TextRenderLayer.ts @@ -14,6 +14,7 @@ import { CellData } from 'common/buffer/CellData'; import { IOptionsService, IBufferService, IDecorationService } from 'common/services/Services'; import { ICharacterJoinerService } from 'browser/services/Services'; import { JoinedCellData } from 'browser/services/CharacterJoinerService'; +import { color, css } from 'common/Color'; /** * This CharData looks like a null character, which will forc a clear and render @@ -177,6 +178,14 @@ export class TextRenderLayer extends BaseRenderLayer { nextFillStyle = this._colors.ansi[cell.getBgColor()].css; } + // Apply dim to the background, this is relatively slow as the CSS is re-parsed but dim is + // rarely used + if (nextFillStyle && cell.isDim()) { + console.log('old', nextFillStyle); + nextFillStyle = color.multiplyOpacity(css.toColor(nextFillStyle), 0.5).css; + console.log('new', nextFillStyle); + } + // Get any decoration foreground/background overrides, this must be fetched before the early // exist but applied after inverse let isTop = false; diff --git a/src/browser/renderer/dom/DomRendererRowFactory.ts b/src/browser/renderer/dom/DomRendererRowFactory.ts index fadf5032..c9e1ff2b 100644 --- a/src/browser/renderer/dom/DomRendererRowFactory.ts +++ b/src/browser/renderer/dom/DomRendererRowFactory.ts @@ -249,6 +249,13 @@ export class DomRendererRowFactory { } } + // If there is no background override by now it's the original color, so apply dim if needed + if (!bgOverride) { + if (cell.isDim()) { + bgOverride = color.multiplyOpacity(resolvedBg, 0.5); + } + } + // Foreground switch (fgColorMode) { case Attributes.CM_P16: diff --git a/src/common/Color.ts b/src/common/Color.ts index e5c7e3eb..f564d66d 100644 --- a/src/common/Color.ts +++ b/src/common/Color.ts @@ -84,6 +84,11 @@ export namespace color { }; } + export function multiplyOpacity(color: IColor, factor: number): IColor { + const a = color.rgba & 0xFF; + return opacity(color, (a * factor) / 0xFF); + } + export function toColorRGB(color: IColor): IColorRGB { return [(color.rgba >> 24) & 0xFF, (color.rgba >> 16) & 0xFF, (color.rgba >> 8) & 0xFF]; }