diff --git a/src/CharMeasure.test.ts b/src/CharMeasure.test.ts deleted file mode 100644 index 5fd17eb2..00000000 --- a/src/CharMeasure.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2016 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import jsdom = require('jsdom'); -import { ICharMeasure } from './Types'; -import { assert } from 'chai'; -import { CharMeasure } from './CharMeasure'; - -describe('CharMeasure', () => { - let dom: jsdom.JSDOM; - let window: Window; - let document: Document; - let container: HTMLElement; - let charMeasure: ICharMeasure; - - beforeEach(() => { - dom = new jsdom.JSDOM(''); - window = dom.window; - document = window.document; - container = document.createElement('div'); - document.body.appendChild(container); - charMeasure = new CharMeasure(document, container); - }); - - describe('measure', () => { - it('should have _measureElement', () => { - assert.isDefined((charMeasure)._measureElement, 'new CharMeasure() should have created _measureElement'); - }); - - it('should be performed sync', () => { - // Mock getBoundingClientRect since jsdom doesn't have a layout engine - (charMeasure)._measureElement.getBoundingClientRect = () => { - return { width: 1, height: 1 }; - }; - charMeasure.measure({}); - assert.equal(charMeasure.height, 1); - assert.equal(charMeasure.width, 1); - }); - - it('should NOT do a measure when the parent is hidden', done => { - charMeasure.measure({}); - setTimeout(() => { - const firstWidth = charMeasure.width; - container.style.display = 'none'; - container.style.fontSize = '2em'; - charMeasure.measure({}); - assert.equal(charMeasure.width, firstWidth); - done(); - }, 0); - }); - }); -}); diff --git a/src/CharMeasure.ts b/src/CharMeasure.ts deleted file mode 100644 index 9ef22b63..00000000 --- a/src/CharMeasure.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2016 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { ICharMeasure, ITerminalOptions } from './Types'; -import { EventEmitter2, IEvent } from 'common/EventEmitter2'; - -/** - * Utility class that measures the size of a character. Measurements are done in - * the DOM rather than with a canvas context because support for extracting the - * height of characters is patchy across browsers. - */ -export class CharMeasure implements ICharMeasure { - private _document: Document; - private _parentElement: HTMLElement; - private _measureElement: HTMLElement; - private _width: number; - private _height: number; - - private _onCharSizeChanged = new EventEmitter2(); - public get onCharSizeChanged(): IEvent { return this._onCharSizeChanged.event; } - - constructor(document: Document, parentElement: HTMLElement) { - this._document = document; - this._parentElement = parentElement; - this._measureElement = this._document.createElement('span'); - this._measureElement.classList.add('xterm-char-measure-element'); - this._measureElement.textContent = 'W'; - this._measureElement.setAttribute('aria-hidden', 'true'); - this._parentElement.appendChild(this._measureElement); - } - - public get width(): number { - return this._width; - } - - public get height(): number { - return this._height; - } - - public measure(options: ITerminalOptions): void { - this._measureElement.style.fontFamily = options.fontFamily; - this._measureElement.style.fontSize = `${options.fontSize}px`; - const geometry = this._measureElement.getBoundingClientRect(); - // The element is likely currently display:none, we should retain the - // previous value. - if (geometry.width === 0 || geometry.height === 0) { - return; - } - const adjustedHeight = Math.ceil(geometry.height); - if (this._width !== geometry.width || this._height !== adjustedHeight) { - this._width = geometry.width; - this._height = adjustedHeight; - this._onCharSizeChanged.fire(); - } - } -} diff --git a/src/Terminal.ts b/src/Terminal.ts index 85594fb7..1a02fe2a 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -34,7 +34,6 @@ import { InputHandler } from './InputHandler'; import { Renderer } from './renderer/Renderer'; import { Linkifier } from './Linkifier'; import { SelectionManager } from './SelectionManager'; -import { CharMeasure } from './CharMeasure'; import * as Browser from 'common/Platform'; import { addDisposableDomListener } from 'ui/Lifecycle'; import * as Strings from './Strings'; @@ -180,7 +179,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II public buffers: BufferSet; public viewport: IViewport; private _compositionHelper: ICompositionHelper; - public charMeasure: CharMeasure; private _mouseZoneManager: IMouseZoneManager; public mouseHelper: MouseHelper; private _accessibilityManager: AccessibilityManager; @@ -365,7 +363,9 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // When the font changes the size of the cells may change which requires a renderer clear if (this._renderCoordinator) { this._renderCoordinator.clear(); - this.charMeasure.measure(this.options); + } + if (this._charSizeService) { + this._charSizeService.measure(); } break; case 'drawBoldTextInBrightColors': @@ -614,7 +614,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.register(addDisposableDomListener(this.textarea, 'blur', () => this._onTextAreaBlur())); this._helperContainer.appendChild(this.textarea); - this.charMeasure = new CharMeasure(document, this._helperContainer); this._charSizeService = new CharSizeService(this._document, this._helperContainer, this.optionsService); this._compositionView = document.createElement('div'); @@ -643,7 +642,8 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.register(this.onResize(() => this._renderCoordinator.onResize(this.cols, this.rows))); this.register(this.addDisposableListener('blur', () => this._renderCoordinator.onBlur())); this.register(this.addDisposableListener('focus', () => this._renderCoordinator.onFocus())); - this.register(this.charMeasure.onCharSizeChanged(() => this._renderCoordinator.onCharSizeChanged())); + // TODO: Move to RenderCoordinator + this.register(this._charSizeService.onCharSizeChange(() => this._renderCoordinator.onCharSizeChanged())); this.register(this._renderCoordinator.onDimensionsChange(() => this.viewport.syncScrollArea())); this.selectionManager = new SelectionManager(this, this._charSizeService); @@ -681,7 +681,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II } // Measure the character size - this.charMeasure.measure(this.options); + this._charSizeService.measure(); // Setup loop that draws to screen this.refresh(0, this.rows - 1); @@ -1737,8 +1737,8 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II if (x === this.cols && y === this.rows) { // Check if we still need to measure the char size (fixes #785). - if (this.charMeasure && (!this.charMeasure.width || !this.charMeasure.height)) { - this.charMeasure.measure(this.options); + if (this._charSizeService && !this._charSizeService.hasValidSize) { + this._charSizeService.measure(); } return; } @@ -1752,8 +1752,8 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.rows = y; this.buffers.setupTabStops(this.cols); - if (this.charMeasure) { - this.charMeasure.measure(this.options); + if (this._charSizeService) { + this._charSizeService.measure(); } this.refresh(0, this.rows - 1); diff --git a/src/TestUtils.test.ts b/src/TestUtils.test.ts index 32b7a65c..490a1707 100644 --- a/src/TestUtils.test.ts +++ b/src/TestUtils.test.ts @@ -4,7 +4,7 @@ */ import { IRenderer, IRenderDimensions } from './renderer/Types'; -import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types'; +import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferStringIterator } from './Types'; import { IBufferLine, ICellData, IAttributeData } from 'core/Types'; import { ICircularList, XtermListener } from 'common/Types'; import { Buffer } from './Buffer'; @@ -129,7 +129,6 @@ export class MockTerminal implements ITerminal { rowContainer: HTMLElement; selectionContainer: HTMLElement; selectionManager: ISelectionManager; - charMeasure: ICharMeasure; textarea: HTMLTextAreaElement; rows: number; cols: number; diff --git a/src/Types.ts b/src/Types.ts index 0aecdc96..2225ef3f 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -199,7 +199,6 @@ export interface ILinkifierEvent { export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAccessor, ILinkifierAccessor { screenElement: HTMLElement; selectionManager: ISelectionManager; - charMeasure: ICharMeasure; browser: IBrowser; writeBuffer: string[]; cursorHidden: boolean; @@ -288,15 +287,6 @@ export interface IMouseHelper { getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number }; } -export interface ICharMeasure { - width: number; - height: number; - - onCharSizeChanged: IEvent; - - measure(options: ITerminalOptions): void; -} - // TODO: The options that are not in the public API should be reviewed export interface ITerminalOptions extends IPublicTerminalOptions { [key: string]: any;