diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index c42c0067..5d853f0f 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -392,19 +392,14 @@ export class WebglRenderer extends Disposable implements IRenderer { // Get any decoration foreground/background overrides, this happens on the model to avoid // spreading decoration override logic throughout the different sub-renderers - const decorations = this._decorationService.getDecorationsOnLine(y); let bgOverride: number | undefined; let fgOverride: number | undefined; - for (const d of decorations) { - const xmin = d.options.x ?? 0; - const xmax = xmin + (d.options.width ?? 1); - if (x >= xmin && x < xmax) { - if (d.backgroundColorRGB) { - bgOverride = (d.backgroundColorRGB.rgba >> 8) >>> 0 & 0xFFFFFF; - } - if (d.foregroundColorRGB) { - fgOverride = (d.foregroundColorRGB.rgba >> 8) >>> 0 & 0xFFFFFF; - } + for (const d of this._decorationService.getDecorationsAtCell(x, y)) { + if (d.backgroundColorRGB) { + bgOverride = (d.backgroundColorRGB.rgba >> 8) >>> 0 & 0xFFFFFF; + } + if (d.foregroundColorRGB) { + fgOverride = (d.foregroundColorRGB.rgba >> 8) >>> 0 & 0xFFFFFF; } } diff --git a/src/browser/renderer/BaseRenderLayer.ts b/src/browser/renderer/BaseRenderLayer.ts index f30d95a7..e0f3566c 100644 --- a/src/browser/renderer/BaseRenderLayer.ts +++ b/src/browser/renderer/BaseRenderLayer.ts @@ -329,15 +329,10 @@ export abstract class BaseRenderLayer implements IRenderLayer { // Don't try cache the glyph if it uses any decoration foreground/background override. let hasOverrides = false; - const decorations = this._decorationService.getDecorationsOnLine(y); - for (const d of decorations) { - const xmin = d.options.x ?? 0; - const xmax = xmin + (d.options.width ?? 1); - if (x >= xmin && x < xmax) { - if (d.backgroundColorRGB || d.foregroundColorRGB) { - hasOverrides = true; - break; - } + for (const d of this._decorationService.getDecorationsAtCell(x, y)) { + if (d.backgroundColorRGB || d.foregroundColorRGB) { + hasOverrides = true; + break; } } @@ -446,19 +441,14 @@ export abstract class BaseRenderLayer implements IRenderLayer { private _getContrastColor(cell: CellData, x: number, y: number): IColor | undefined { // Get any decoration foreground/background overrides, this must be fetched before the early // exist but applied after inverse - const decorations = this._decorationService.getDecorationsOnLine(y); let bgOverride: number | undefined; let fgOverride: number | undefined; - for (const d of decorations) { - const xmin = d.options.x ?? 0; - const xmax = xmin + (d.options.width ?? 1); - if (x >= xmin && x < xmax) { - if (d.backgroundColorRGB) { - bgOverride = d.backgroundColorRGB.rgba; - } - if (d.foregroundColorRGB) { - fgOverride = d.foregroundColorRGB.rgba; - } + for (const d of this._decorationService.getDecorationsAtCell(x, y)) { + if (d.backgroundColorRGB) { + bgOverride = d.backgroundColorRGB.rgba; + } + if (d.foregroundColorRGB) { + fgOverride = d.foregroundColorRGB.rgba; } } diff --git a/src/browser/renderer/TextRenderLayer.ts b/src/browser/renderer/TextRenderLayer.ts index e94b53e0..193d891d 100644 --- a/src/browser/renderer/TextRenderLayer.ts +++ b/src/browser/renderer/TextRenderLayer.ts @@ -179,14 +179,9 @@ export class TextRenderLayer extends BaseRenderLayer { // Get any decoration foreground/background overrides, this must be fetched before the early // exist but applied after inverse - const decorations = this._decorationService.getDecorationsOnLine(this._bufferService.buffer.ydisp + y); - for (const d of decorations) { - const xmin = d.options.x ?? 0; - const xmax = xmin + (d.options.width ?? 1); - if (x >= xmin && x < xmax) { - if (d.backgroundColorRGB) { - nextFillStyle = d.backgroundColorRGB.css; - } + for (const d of this._decorationService.getDecorationsAtCell(x, this._bufferService.buffer.ydisp + y)) { + if (d.backgroundColorRGB) { + nextFillStyle = d.backgroundColorRGB.css; } } diff --git a/src/browser/renderer/dom/DomRendererRowFactory.ts b/src/browser/renderer/dom/DomRendererRowFactory.ts index 24a7b2c6..c92f82c6 100644 --- a/src/browser/renderer/dom/DomRendererRowFactory.ts +++ b/src/browser/renderer/dom/DomRendererRowFactory.ts @@ -175,23 +175,18 @@ export class DomRendererRowFactory { // Apply any decoration foreground/background overrides, this must happen after inverse has // been applied - const decorations = this._decorationService.getDecorationsOnLine(row); let bgOverride: IColor | undefined; let fgOverride: IColor | undefined; - for (const d of decorations) { - const xmin = d.options.x ?? 0; - const xmax = xmin + (d.options.width ?? 1); - if (x >= xmin && x < xmax) { - if (d.backgroundColorRGB) { - bgColorMode = Attributes.CM_RGB; - bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF; - bgOverride = d.backgroundColorRGB; - } - if (d.foregroundColorRGB) { - fgColorMode = Attributes.CM_RGB; - fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF; - fgOverride = d.foregroundColorRGB; - } + for (const d of this._decorationService.getDecorationsAtCell(x, row)) { + if (d.backgroundColorRGB) { + bgColorMode = Attributes.CM_RGB; + bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF; + bgOverride = d.backgroundColorRGB; + } + if (d.foregroundColorRGB) { + fgColorMode = Attributes.CM_RGB; + fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF; + fgOverride = d.foregroundColorRGB; } } diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 10b6b5ef..11d9a8c5 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -167,6 +167,7 @@ export class MockDecorationService implements IDecorationService { public onDecorationRemoved = new EventEmitter().event; public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined { return undefined; } public reset(): void { } - public *getDecorationsOnLine(line: number): IterableIterator { } + public *getDecorationsAtLine(line: number): IterableIterator { } + public *getDecorationsAtCell(x: number, line: number): IterableIterator { } public dispose(): void { } } diff --git a/src/common/services/DecorationService.ts b/src/common/services/DecorationService.ts index 3c646501..ed58c813 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -56,7 +56,7 @@ export class DecorationService extends Disposable implements IDecorationService this._decorations.length = 0; } - public *getDecorationsOnLine(line: number): IterableIterator { + public *getDecorationsAtLine(line: number): IterableIterator { // TODO: This could be made much faster if _decorations was sorted by line (and col?) for (const d of this.decorations) { if (d.marker.line === line) { @@ -65,6 +65,20 @@ export class DecorationService extends Disposable implements IDecorationService } } + public *getDecorationsAtCell(x: number, line: number): IterableIterator { + let xmin = 0; + let xmax = 0; + for (const d of this.decorations) { + if (d.marker.line === line) { + xmin = d.options.x ?? 0; + xmax = xmin + (d.options.width ?? 1); + if (x >= xmin && x < xmax) { + yield d; + } + } + } + } + public dispose(): void { for (const decoration of this._decorations) { this._onDecorationRemoved.fire(decoration); diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index c6d47816..82492eb4 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -309,8 +309,10 @@ export interface IDecorationService extends IDisposable { readonly onDecorationRemoved: IEvent; registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined; reset(): void; - /** Iterates over the decorations on a line (in no particular order). */ - getDecorationsOnLine(line: number): IterableIterator; + /** Iterates over the decorations at a line (in no particular order). */ + getDecorationsAtLine(line: number): IterableIterator; + /** Iterates over the decorations at a cell (in no particular order). */ + getDecorationsAtCell(x: number, line: number): IterableIterator; } export interface IInternalDecoration extends IDecoration { readonly options: IDecorationOptions;