diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index a7f4a700fc..689b847a24 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -70,13 +70,11 @@ const INDICES_PER_CELL = 10; const BYTES_PER_CELL = INDICES_PER_CELL * Float32Array.BYTES_PER_ELEMENT; const CELL_POSITION_INDICES = 2; -/** Work variables to avoid garbage collection. */ -const w: { i: number, glyph: IRasterizedGlyph | undefined, leftCellPadding: number, clippedPixels: number } = { - i: 0, - glyph: undefined, - leftCellPadding: 0, - clippedPixels: 0 -}; +// Work variables to avoid garbage collection +let $i = 0; +let $glyph: IRasterizedGlyph | undefined = undefined; +let $leftCellPadding = 0; +let $clippedPixels = 0; export class GlyphRenderer extends Disposable { private _atlas: WebglCharAtlas | undefined; @@ -186,12 +184,12 @@ export class GlyphRenderer extends Disposable { } private _updateCell(array: Float32Array, x: number, y: number, code: number | undefined, bg: number, fg: number, ext: number, chars: string, lastBg: number): void { - w.i = (y * this._terminal.cols + x) * INDICES_PER_CELL; + $i = (y * this._terminal.cols + x) * INDICES_PER_CELL; // Exit early if this is a null character, allow space character to continue as it may have // underline/strikethrough styles if (code === NULL_CELL_CODE || code === undefined/* This is used for the right side of wide chars */) { - fill(array, 0, w.i, w.i + INDICES_PER_CELL - 1 - CELL_POSITION_INDICES); + fill(array, 0, $i, $i + INDICES_PER_CELL - 1 - CELL_POSITION_INDICES); return; } @@ -201,39 +199,39 @@ export class GlyphRenderer extends Disposable { // Get the glyph if (chars && chars.length > 1) { - w.glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext); + $glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext); } else { - w.glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext); + $glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext); } - w.leftCellPadding = Math.floor((this._dimensions.scaledCellWidth - this._dimensions.scaledCharWidth) / 2); - if (bg !== lastBg && w.glyph.offset.x > w.leftCellPadding) { - w.clippedPixels = w.glyph.offset.x - w.leftCellPadding; + $leftCellPadding = Math.floor((this._dimensions.scaledCellWidth - this._dimensions.scaledCharWidth) / 2); + if (bg !== lastBg && $glyph.offset.x > $leftCellPadding) { + $clippedPixels = $glyph.offset.x - $leftCellPadding; // a_origin - array[w.i ] = -(w.glyph.offset.x - w.clippedPixels) + this._dimensions.scaledCharLeft; - array[w.i + 1] = -w.glyph.offset.y + this._dimensions.scaledCharTop; + array[$i ] = -($glyph.offset.x - $clippedPixels) + this._dimensions.scaledCharLeft; + array[$i + 1] = -$glyph.offset.y + this._dimensions.scaledCharTop; // a_size - array[w.i + 2] = (w.glyph.size.x - w.clippedPixels) / this._dimensions.scaledCanvasWidth; - array[w.i + 3] = w.glyph.size.y / this._dimensions.scaledCanvasHeight; + array[$i + 2] = ($glyph.size.x - $clippedPixels) / this._dimensions.scaledCanvasWidth; + array[$i + 3] = $glyph.size.y / this._dimensions.scaledCanvasHeight; // a_texcoord - array[w.i + 4] = w.glyph.texturePositionClipSpace.x + w.clippedPixels / this._atlas.cacheCanvas.width; - array[w.i + 5] = w.glyph.texturePositionClipSpace.y; + array[$i + 4] = $glyph.texturePositionClipSpace.x + $clippedPixels / this._atlas.cacheCanvas.width; + array[$i + 5] = $glyph.texturePositionClipSpace.y; // a_texsize - array[w.i + 6] = w.glyph.sizeClipSpace.x - w.clippedPixels / this._atlas.cacheCanvas.width; - array[w.i + 7] = w.glyph.sizeClipSpace.y; + array[$i + 6] = $glyph.sizeClipSpace.x - $clippedPixels / this._atlas.cacheCanvas.width; + array[$i + 7] = $glyph.sizeClipSpace.y; } else { // a_origin - array[w.i ] = -w.glyph.offset.x + this._dimensions.scaledCharLeft; - array[w.i + 1] = -w.glyph.offset.y + this._dimensions.scaledCharTop; + array[$i ] = -$glyph.offset.x + this._dimensions.scaledCharLeft; + array[$i + 1] = -$glyph.offset.y + this._dimensions.scaledCharTop; // a_size - array[w.i + 2] = w.glyph.size.x / this._dimensions.scaledCanvasWidth; - array[w.i + 3] = w.glyph.size.y / this._dimensions.scaledCanvasHeight; + array[$i + 2] = $glyph.size.x / this._dimensions.scaledCanvasWidth; + array[$i + 3] = $glyph.size.y / this._dimensions.scaledCanvasHeight; // a_texcoord - array[w.i + 4] = w.glyph.texturePositionClipSpace.x; - array[w.i + 5] = w.glyph.texturePositionClipSpace.y; + array[$i + 4] = $glyph.texturePositionClipSpace.x; + array[$i + 5] = $glyph.texturePositionClipSpace.y; // a_texsize - array[w.i + 6] = w.glyph.sizeClipSpace.x; - array[w.i + 7] = w.glyph.sizeClipSpace.y; + array[$i + 6] = $glyph.sizeClipSpace.x; + array[$i + 7] = $glyph.sizeClipSpace.y; } // a_cellpos only changes on resize } diff --git a/addons/xterm-addon-webgl/src/RectangleRenderer.ts b/addons/xterm-addon-webgl/src/RectangleRenderer.ts index ef08fb7c2c..dccc7f6a9c 100644 --- a/addons/xterm-addon-webgl/src/RectangleRenderer.ts +++ b/addons/xterm-addon-webgl/src/RectangleRenderer.ts @@ -58,17 +58,15 @@ const BYTES_PER_RECTANGLE = INDICES_PER_RECTANGLE * Float32Array.BYTES_PER_ELEME const INITIAL_BUFFER_RECTANGLE_CAPACITY = 20 * INDICES_PER_RECTANGLE; -/** Work variables to avoid garbage collection. */ -const w: { rgba: number, isDefault: boolean, x1: number, y1: number, r: number, g: number, b: number, a: number } = { - rgba: 0, - isDefault: false, - x1: 0, - y1: 0, - r: 0, - g: 0, - b: 0, - a: 0 -}; +// Work variables to avoid garbage collection +let $rgba = 0; +let $isDefault = false; +let $x1 = 0; +let $y1 = 0; +let $r = 0; +let $g = 0; +let $b = 0; +let $a = 0; export class RectangleRenderer extends Disposable { @@ -232,47 +230,47 @@ export class RectangleRenderer extends Disposable { } private _updateRectangle(vertices: IVertices, offset: number, fg: number, bg: number, startX: number, endX: number, y: number): void { - w.isDefault = false; + $isDefault = false; if (fg & FgFlags.INVERSE) { switch (fg & Attributes.CM_MASK) { case Attributes.CM_P16: case Attributes.CM_P256: - w.rgba = this._colors.ansi[fg & Attributes.PCOLOR_MASK].rgba; + $rgba = this._colors.ansi[fg & Attributes.PCOLOR_MASK].rgba; break; case Attributes.CM_RGB: - w.rgba = (fg & Attributes.RGB_MASK) << 8; + $rgba = (fg & Attributes.RGB_MASK) << 8; break; case Attributes.CM_DEFAULT: default: - w.rgba = this._colors.foreground.rgba; + $rgba = this._colors.foreground.rgba; } } else { switch (bg & Attributes.CM_MASK) { case Attributes.CM_P16: case Attributes.CM_P256: - w.rgba = this._colors.ansi[bg & Attributes.PCOLOR_MASK].rgba; + $rgba = this._colors.ansi[bg & Attributes.PCOLOR_MASK].rgba; break; case Attributes.CM_RGB: - w.rgba = (bg & Attributes.RGB_MASK) << 8; + $rgba = (bg & Attributes.RGB_MASK) << 8; break; case Attributes.CM_DEFAULT: default: - w.rgba = this._colors.background.rgba; - w.isDefault = true; + $rgba = this._colors.background.rgba; + $isDefault = true; } } if (vertices.attributes.length < offset + 4) { vertices.attributes = expandFloat32Array(vertices.attributes, this._terminal.rows * this._terminal.cols * INDICES_PER_RECTANGLE); } - w.x1 = startX * this._dimensions.scaledCellWidth; - w.y1 = y * this._dimensions.scaledCellHeight; - w.r = ((w.rgba >> 24) & 0xFF) / 255; - w.g = ((w.rgba >> 16) & 0xFF) / 255; - w.b = ((w.rgba >> 8 ) & 0xFF) / 255; - w.a = (!w.isDefault && bg & BgFlags.DIM) ? DIM_OPACITY : 1; - - this._addRectangle(vertices.attributes, offset, w.x1, w.y1, (endX - startX) * this._dimensions.scaledCellWidth, this._dimensions.scaledCellHeight, w.r, w.g, w.b, w.a); + $x1 = startX * this._dimensions.scaledCellWidth; + $y1 = y * this._dimensions.scaledCellHeight; + $r = (($rgba >> 24) & 0xFF) / 255; + $g = (($rgba >> 16) & 0xFF) / 255; + $b = (($rgba >> 8 ) & 0xFF) / 255; + $a = (!$isDefault && bg & BgFlags.DIM) ? DIM_OPACITY : 1; + + this._addRectangle(vertices.attributes, offset, $x1, $y1, (endX - startX) * this._dimensions.scaledCellWidth, this._dimensions.scaledCellHeight, $r, $g, $b, $a); } private _addRectangle(array: Float32Array, offset: number, x1: number, y1: number, width: number, height: number, r: number, g: number, b: number, a: number): void { diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index d8daa0d187..b276cd0534 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -26,14 +26,12 @@ import { CharData, IBufferLine, ICellData } from 'common/Types'; import { AttributeData } from 'common/buffer/AttributeData'; import { ICoreService, IDecorationService } from 'common/services/Services'; -/** Work variables to avoid garbage collection. */ -const w: { fg: number, bg: number, hasFg: boolean, hasBg: boolean, isSelected: boolean } = { - fg: 0, - bg: 0, - hasFg: false, - hasBg: false, - isSelected: false -}; +// Work variables to avoid garbage collection +let $fg = 0; +let $bg = 0; +let $hasFg = false; +let $hasBg = false; +let $isSelected = false; export class WebglRenderer extends Disposable implements IRenderer { private _renderLayers: IRenderLayer[]; @@ -475,89 +473,89 @@ export class WebglRenderer extends Disposable implements IRenderer { // override logic throughout the different sub-renderers // Reset overrides work variables - w.bg = 0; - w.fg = 0; - w.hasBg = false; - w.hasFg = false; - w.isSelected = false; + $bg = 0; + $fg = 0; + $hasBg = false; + $hasFg = false; + $isSelected = false; // Apply decorations on the bottom layer this._decorationService.forEachDecorationAtCell(x, y, 'bottom', d => { if (d.backgroundColorRGB) { - w.bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF; - w.hasBg = true; + $bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF; + $hasBg = true; } if (d.foregroundColorRGB) { - w.fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF; - w.hasFg = true; + $fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF; + $hasFg = true; } }); // Apply the selection color if needed - w.isSelected = this._isCellSelected(x, y); - if (w.isSelected) { - w.bg = (this._coreBrowserService.isFocused ? this._colors.selectionBackgroundOpaque : this._colors.selectionInactiveBackgroundOpaque).rgba >> 8 & 0xFFFFFF; - w.hasBg = true; + $isSelected = this._isCellSelected(x, y); + if ($isSelected) { + $bg = (this._coreBrowserService.isFocused ? this._colors.selectionBackgroundOpaque : this._colors.selectionInactiveBackgroundOpaque).rgba >> 8 & 0xFFFFFF; + $hasBg = true; if (this._colors.selectionForeground) { - w.fg = this._colors.selectionForeground.rgba >> 8 & 0xFFFFFF; - w.hasFg = true; + $fg = this._colors.selectionForeground.rgba >> 8 & 0xFFFFFF; + $hasFg = true; } } // Apply decorations on the top layer this._decorationService.forEachDecorationAtCell(x, y, 'top', d => { if (d.backgroundColorRGB) { - w.bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF; - w.hasBg = true; + $bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF; + $hasBg = true; } if (d.foregroundColorRGB) { - w.fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF; - w.hasFg = true; + $fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF; + $hasFg = true; } }); // 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 (w.hasBg) { - if (w.isSelected) { + if ($hasBg) { + if ($isSelected) { // Non-RGB attributes from model + force non-dim + override + force RGB color mode - w.bg = (this._workCell.bg & ~Attributes.RGB_MASK & ~BgFlags.DIM) | w.bg | Attributes.CM_RGB; + $bg = (this._workCell.bg & ~Attributes.RGB_MASK & ~BgFlags.DIM) | $bg | Attributes.CM_RGB; } else { // Non-RGB attributes from model + override + force RGB color mode - w.bg = (this._workCell.bg & ~Attributes.RGB_MASK) | w.bg | Attributes.CM_RGB; + $bg = (this._workCell.bg & ~Attributes.RGB_MASK) | $bg | Attributes.CM_RGB; } } - if (w.hasFg) { + if ($hasFg) { // Non-RGB attributes from model + force disable inverse + override + force RGB color mode - w.fg = (this._workCell.fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | w.fg | Attributes.CM_RGB; + $fg = (this._workCell.fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | $fg | Attributes.CM_RGB; } // Handle case where inverse was specified by only one of bg override or fg override was set, // resolving the other inverse color and setting the inverse flag if needed. if (this._workColors.fg & FgFlags.INVERSE) { - if (w.hasBg && !w.hasFg) { + if ($hasBg && !$hasFg) { // Resolve bg color type (default color has a different meaning in fg vs bg) if ((this._workColors.bg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) { - w.fg = (this._workColors.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | ((this._colors.background.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB; + $fg = (this._workColors.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | ((this._colors.background.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB; } else { - w.fg = (this._workColors.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | this._workColors.bg & (Attributes.RGB_MASK | Attributes.CM_MASK); + $fg = (this._workColors.fg & ~(Attributes.RGB_MASK | FgFlags.INVERSE | Attributes.CM_MASK)) | this._workColors.bg & (Attributes.RGB_MASK | Attributes.CM_MASK); } - w.hasFg = true; + $hasFg = true; } - if (!w.hasBg && w.hasFg) { + if (!$hasBg && $hasFg) { // Resolve bg color type (default color has a different meaning in fg vs bg) if ((this._workColors.fg & Attributes.CM_MASK) === Attributes.CM_DEFAULT) { - w.bg = (this._workColors.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | ((this._colors.foreground.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB; + $bg = (this._workColors.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | ((this._colors.foreground.rgba >> 8 & 0xFFFFFF) & Attributes.RGB_MASK) | Attributes.CM_RGB; } else { - w.bg = (this._workColors.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | this._workColors.fg & (Attributes.RGB_MASK | Attributes.CM_MASK); + $bg = (this._workColors.bg & ~(Attributes.RGB_MASK | Attributes.CM_MASK)) | this._workColors.fg & (Attributes.RGB_MASK | Attributes.CM_MASK); } - w.hasBg = true; + $hasBg = true; } } // Use the override if it exists - this._workColors.bg = w.hasBg ? w.bg : this._workColors.bg; - this._workColors.fg = w.hasFg ? w.fg : this._workColors.fg; + this._workColors.bg = $hasBg ? $bg : this._workColors.bg; + this._workColors.fg = $hasFg ? $fg : this._workColors.fg; } private _isCellSelected(x: number, y: number): boolean { diff --git a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts index 4764ede4e4..dee1e02c56 100644 --- a/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts +++ b/addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts @@ -54,10 +54,8 @@ interface ICharAtlasActiveRow { height: number; } -/** Work variables to avoid garbage collection. */ -const w: { glyph: IRasterizedGlyph | undefined } = { - glyph: undefined -}; +// Work variables to avoid garbage collection +let $glyph = undefined; export class WebglCharAtlas implements IDisposable { private _didWarmUp: boolean = false; @@ -184,12 +182,12 @@ export class WebglCharAtlas implements IDisposable { fg: number, ext: number ): IRasterizedGlyph { - w.glyph = cacheMap.get(key, bg, fg, ext); - if (!w.glyph) { - w.glyph = this._drawToCache(key, bg, fg, ext); - cacheMap.set(key, bg, fg, ext, w.glyph); + $glyph = cacheMap.get(key, bg, fg, ext); + if (!$glyph) { + $glyph = this._drawToCache(key, bg, fg, ext); + cacheMap.set(key, bg, fg, ext, $glyph); } - return w.glyph; + return $glyph; } private _getColorFromAnsiIndex(idx: number): IColor { diff --git a/src/common/buffer/BufferLine.ts b/src/common/buffer/BufferLine.ts index 43e8983927..875ac6c974 100644 --- a/src/common/buffer/BufferLine.ts +++ b/src/common/buffer/BufferLine.ts @@ -37,10 +37,8 @@ const enum Cell { export const DEFAULT_ATTR_DATA = Object.freeze(new AttributeData()); -/** Work variables to avoid garbage collection. */ -const w: { startIndex: number } = { - startIndex: 0 -}; +// Work variables to avoid garbage collection +let $startIndex = 0; /** * Typed array based bufferline implementation. @@ -178,10 +176,10 @@ export class BufferLine implements IBufferLine { * to GC as it significantly reduced the amount of new objects/references needed. */ public loadCell(index: number, cell: ICellData): ICellData { - w.startIndex = index * CELL_SIZE; - cell.content = this._data[w.startIndex + Cell.CONTENT]; - cell.fg = this._data[w.startIndex + Cell.FG]; - cell.bg = this._data[w.startIndex + Cell.BG]; + $startIndex = index * CELL_SIZE; + cell.content = this._data[$startIndex + Cell.CONTENT]; + cell.fg = this._data[$startIndex + Cell.FG]; + cell.bg = this._data[$startIndex + Cell.BG]; if (cell.content & Content.IS_COMBINED_MASK) { cell.combinedData = this._combined[index]; } diff --git a/src/common/services/DecorationService.ts b/src/common/services/DecorationService.ts index e5d115a14a..dae801518a 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -11,11 +11,9 @@ import { SortedList } from 'common/SortedList'; import { IColor } from 'common/Types'; import { IDecorationOptions, IDecoration, IMarker, IEvent } from 'xterm'; -/** Work variables to avoid garbage collection. */ -const w = { - xmin: 0, - xmax: 0 -}; +// Work variables to avoid garbage collection +let $xmin = 0; +let $xmax = 0; export class DecorationService extends Disposable implements IDecorationService { public serviceBrand: any; @@ -76,9 +74,9 @@ export class DecorationService extends Disposable implements IDecorationService public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void { this._decorations.forEachByKey(line, d => { - w.xmin = d.options.x ?? 0; - w.xmax = w.xmin + (d.options.width ?? 1); - if (x >= w.xmin && x < w.xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) { + $xmin = d.options.x ?? 0; + $xmax = $xmin + (d.options.width ?? 1); + if (x >= $xmin && x < $xmax && (!layer || (d.options.layer ?? 'bottom') === layer)) { callback(d); } });