diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 0fff23ed..b5658509 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -98,7 +98,12 @@ export class DomRenderer extends Disposable implements IRenderer { })); this._widthCache = new WidthCache(document); - this._widthCache.setFont(this._optionsService.rawOptions.fontFamily, this._optionsService.rawOptions.fontSize); + this._widthCache.setFont( + this._optionsService.rawOptions.fontFamily, + this._optionsService.rawOptions.fontSize, + this._optionsService.rawOptions.fontWeight, + this._optionsService.rawOptions.fontWeightBold + ); this._setDefaultSpacing(); } @@ -373,7 +378,12 @@ export class DomRenderer extends Disposable implements IRenderer { // Refresh CSS this._injectCss(this._themeService.colors); // update spacing cache - this._widthCache.setFont(this._optionsService.rawOptions.fontFamily, this._optionsService.rawOptions.fontSize); + this._widthCache.setFont( + this._optionsService.rawOptions.fontFamily, + this._optionsService.rawOptions.fontSize, + this._optionsService.rawOptions.fontWeight, + this._optionsService.rawOptions.fontWeightBold + ); this._setDefaultSpacing(); } diff --git a/src/browser/renderer/dom/WidthCache.ts b/src/browser/renderer/dom/WidthCache.ts index 1b0fd1d7..a5a8c0bf 100644 --- a/src/browser/renderer/dom/WidthCache.ts +++ b/src/browser/renderer/dom/WidthCache.ts @@ -4,6 +4,7 @@ */ import { IDisposable } from 'common/Types'; +import { FontWeight } from 'common/services/Services'; const enum CacheSettings { @@ -14,13 +15,18 @@ const enum CacheSettings { export class WidthCache implements IDisposable { - // flat cache for regular + // flat cache for regular variant up to CacheSettings.FLAT_SIZE + // NOTE: ~4x faster access than holey (serving >>80% of terminal content) private _flat = new Float32Array(CacheSettings.FLAT_SIZE); + // holey cache for bold, italic and bold&italic for any string + // FIXME: can grow really big over time, so a shared API across terminals is needed private _holey = new Map(); private _font = ''; private _fontSize = 0; + private _weight: FontWeight = 'normal'; + private _weightBold: FontWeight = 'bold'; private _container: HTMLDivElement; private _measureElements: HTMLSpanElement[] = []; @@ -31,6 +37,7 @@ export class WidthCache implements IDisposable { this._container.style.position = 'absolute'; this._container.style.top = '-50000px'; this._container.style.width = '50000px'; + // SP should stack in spans this._container.style.whiteSpace = 'pre'; // avoid undercuts in non-monospace fonts from kerning this._container.style.fontKerning = 'none'; @@ -62,11 +69,11 @@ export class WidthCache implements IDisposable { public dispose(): void { this._container.remove(); this._measureElements.length = 0; - this._holey.clear(); + this._holey.clear(); // also free memory } /** - * Clear the spacing cache. + * Clear the width cache. */ public clear(): void { this._flat.fill(CacheSettings.FLAT_UNSET); @@ -75,18 +82,32 @@ export class WidthCache implements IDisposable { /** * Set the font for measuring. - * Must be called for any fontFamily or fontSize changes. + * Must be called for any changes on font settings. * Also clears the cache. */ - public setFont(font: string, fontSize: number): void { - if (font !== this._font || fontSize !== this._fontSize) { - this._font = font; - this._fontSize = fontSize; - this.clear(); - - this._container.style.fontFamily = this._font; - this._container.style.fontSize = `${this._fontSize}px`; + public setFont(font: string, fontSize: number, weight: FontWeight, weightBold: FontWeight): void { + // skip if nothing changed + if (font === this._font + && fontSize === this._fontSize + && weight === this._weight + && weightBold === this._weightBold + ) { + return; } + + this._font = font; + this._fontSize = fontSize; + this._weight = weight; + this._weightBold = weightBold; + + this._container.style.fontFamily = this._font; + this._container.style.fontSize = `${this._fontSize}px`; + this._measureElements[0].style.fontWeight = `${weight}`; // regular + this._measureElements[1].style.fontWeight = `${weightBold}`; // bold + this._measureElements[2].style.fontWeight = `${weight}`; // italic + this._measureElements[3].style.fontWeight = `${weightBold}`; // boldItalic + + this.clear(); } /**