Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addons/addon-webgl/src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface ICharAtlasConfig {
devicePixelRatio: number;
deviceMaxTextureSize: number;
letterSpacing: number;
lineHeight: number;
lineHeight: number | string;
fontSize: number;
fontFamily: string;
fontWeight: FontWeight;
Expand Down
13 changes: 8 additions & 5 deletions addons/addon-webgl/src/WebglRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,14 +623,17 @@ export class WebglRenderer extends Disposable implements IRenderer {
// cell.
this.dimensions.device.char.height = Math.ceil(this._charSizeService.height * this._devicePixelRatio);

// Calculate the device cell height, if lineHeight is _not_ 1, the resulting value will be
// floored since lineHeight can never be lower then 1, this guarentees the device cell height
// will always be larger than device char height.
this.dimensions.device.cell.height = Math.floor(this.dimensions.device.char.height * this._optionsService.rawOptions.lineHeight);
// Calculate the device cell height, if lineHeight is _not_ 1 (or is a px string), the
// resulting value will be floored since lineHeight can never be lower than 1, this guarantees
// the device cell height will always be larger than device char height.
const lineHeight = this._optionsService.rawOptions.lineHeight;
this.dimensions.device.cell.height = typeof lineHeight === 'string'
? Math.max(Math.floor(parseFloat(lineHeight) * this._devicePixelRatio), this.dimensions.device.char.height)
: Math.floor(this.dimensions.device.char.height * lineHeight);

// Calculate the y offset within a cell that glyph should draw at in order for it to be centered
// correctly within the cell.
this.dimensions.device.char.top = this._optionsService.rawOptions.lineHeight === 1 ? 0 : Math.round((this.dimensions.device.cell.height - this.dimensions.device.char.height) / 2);
this.dimensions.device.char.top = this.dimensions.device.cell.height === this.dimensions.device.char.height ? 0 : Math.round((this.dimensions.device.cell.height - this.dimensions.device.char.height) / 2);

// Calculate the device cell width, taking the letterSpacing into account.
this.dimensions.device.cell.width = this.dimensions.device.char.width + Math.round(this._optionsService.rawOptions.letterSpacing);
Expand Down
5 changes: 4 additions & 1 deletion src/browser/renderer/dom/DomRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ export class DomRenderer extends Disposable implements IRenderer {
this.dimensions.device.char.width = this._charSizeService.width * dpr;
this.dimensions.device.char.height = Math.ceil(this._charSizeService.height * dpr);
this.dimensions.device.cell.width = this.dimensions.device.char.width + Math.round(this._optionsService.rawOptions.letterSpacing);
this.dimensions.device.cell.height = Math.floor(this.dimensions.device.char.height * this._optionsService.rawOptions.lineHeight);
const lineHeight = this._optionsService.rawOptions.lineHeight;
this.dimensions.device.cell.height = typeof lineHeight === 'string'
? Math.max(Math.floor(parseFloat(lineHeight) * dpr), this.dimensions.device.char.height)
: Math.floor(this.dimensions.device.char.height * lineHeight);
this.dimensions.device.char.left = 0;
this.dimensions.device.char.top = 0;
this.dimensions.device.canvas.width = this.dimensions.device.cell.width * this._bufferService.cols;
Expand Down
16 changes: 15 additions & 1 deletion src/common/services/OptionsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,26 @@ export class OptionsService extends Disposable implements IOptionsService {
case 'cursorWidth':
value = Math.floor(value);
// Fall through for bounds check
case 'lineHeight':
case 'tabStopWidth':
if (value < 1) {
throw new Error(`${key} cannot be less than 1, value: ${value}`);
}
break;
case 'lineHeight':
if (typeof value === 'string') {
if (!value.endsWith('px')) {
throw new Error(`${key} string value must end with 'px', value: ${value}`);
}
const parsed = parseFloat(value);
if (isNaN(parsed) || parsed < 1) {
throw new Error(`${key} must be a number >= 1 when using px format, value: ${value}`);
}
} else if (typeof value === 'number') {
if (value < 1) {
throw new Error(`${key} cannot be less than 1, value: ${value}`);
}
}
break;
case 'minimumContrastRatio':
value = Math.max(1, Math.min(21, Math.round(value * 10) / 10));
break;
Expand Down
2 changes: 1 addition & 1 deletion src/common/services/Services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export interface ITerminalOptions {
fontWeightBold?: FontWeight;
ignoreBracketedPasteMode?: boolean;
letterSpacing?: number;
lineHeight?: number;
lineHeight?: number | string;
linkHandler?: ILinkHandler | null;
logLevel?: LogLevel;
logger?: ILogger | null;
Expand Down
7 changes: 5 additions & 2 deletions typings/xterm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,12 @@ declare module '@xterm/xterm' {
letterSpacing?: number;

/**
* The line height used to render text.
* The line height used to render text. When a number is given, it is used
* as a multiplier of the character height (must be >= 1). When a string
* ending in `'px'` is given (e.g. `'23px'`), it sets an absolute pixel
* line height (the parsed value must be >= 1).
*/
lineHeight?: number;
lineHeight?: number | string;

/**
* The handler for OSC 8 hyperlinks. Links will use the `confirm` browser
Expand Down