mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Use variants for underline dotted.
webgl
This commit is contained in:
@@ -375,9 +375,9 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
|
||||
|
||||
let glyph: IRasterizedGlyph;
|
||||
if (chars && chars.length > 1) {
|
||||
glyph = this._charAtlas.getRasterizedGlyphCombinedChar(chars, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext, true);
|
||||
glyph = this._charAtlas.getRasterizedGlyphCombinedChar(chars, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext, 0, true);
|
||||
} else {
|
||||
glyph = this._charAtlas.getRasterizedGlyph(cell.getCode() || WHITESPACE_CELL_CODE, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext, true);
|
||||
glyph = this._charAtlas.getRasterizedGlyph(cell.getCode() || WHITESPACE_CELL_CODE, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext, 0, true);
|
||||
}
|
||||
if (!glyph.size.x || !glyph.size.y) {
|
||||
return;
|
||||
|
||||
@@ -215,15 +215,15 @@ export class GlyphRenderer extends Disposable {
|
||||
}
|
||||
|
||||
@traceCall
|
||||
public updateCell(x: number, y: number, code: number, bg: number, fg: number, ext: number, chars: string, lastBg: number): void {
|
||||
public updateCell(x: number, y: number, code: number, bg: number, fg: number, ext: number, chars: string, lastBg: number, variantOffset: number): void {
|
||||
// Since this function is called for every cell (`rows*cols`), it must be very optimized. It
|
||||
// should not instantiate any variables unless a new glyph is drawn to the cache where the
|
||||
// slight slowdown is acceptable for the developer ergonomics provided as it's a once of for
|
||||
// each glyph.
|
||||
this._updateCell(this._vertices.attributes, x, y, code, bg, fg, ext, chars, lastBg);
|
||||
this._updateCell(this._vertices.attributes, x, y, code, bg, fg, ext, chars, lastBg, variantOffset);
|
||||
}
|
||||
|
||||
private _updateCell(array: Float32Array, x: number, y: number, code: number | undefined, bg: number, fg: number, ext: number, chars: string, lastBg: number): void {
|
||||
private _updateCell(array: Float32Array, x: number, y: number, code: number | undefined, bg: number, fg: number, ext: number, chars: string, lastBg: number, variantOffset: number): void {
|
||||
$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
|
||||
@@ -239,9 +239,9 @@ export class GlyphRenderer extends Disposable {
|
||||
|
||||
// Get the glyph
|
||||
if (chars && chars.length > 1) {
|
||||
$glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext, false);
|
||||
$glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext, variantOffset, false);
|
||||
} else {
|
||||
$glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext, false);
|
||||
$glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext, variantOffset, false);
|
||||
}
|
||||
|
||||
$leftCellPadding = Math.floor((this._dimensions.device.cell.width - this._dimensions.device.char.width) / 2);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ITerminal } from 'browser/Types';
|
||||
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { getSafariVersion, isSafari } from 'common/Platform';
|
||||
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
|
||||
import { ICoreService, IDecorationService, ILogService, IOptionsService, IUnicodeService } from 'common/services/Services';
|
||||
import { ITerminalAddon, Terminal } from 'xterm';
|
||||
import { WebglRenderer } from './WebglRenderer';
|
||||
import { setTraceLogger } from 'common/services/LogService';
|
||||
@@ -54,6 +54,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon {
|
||||
const decorationService: IDecorationService = unsafeCore._decorationService;
|
||||
const logService: ILogService = unsafeCore._logService;
|
||||
const themeService: IThemeService = unsafeCore._themeService;
|
||||
const unicodeService: IUnicodeService = unsafeCore.unicodeService;
|
||||
|
||||
// Set trace logger just in case it hasn't been yet which could happen when the addon is
|
||||
// bundled separately to the core module
|
||||
@@ -68,6 +69,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon {
|
||||
decorationService,
|
||||
optionsService,
|
||||
themeService,
|
||||
unicodeService,
|
||||
this._preserveDrawingBuffer
|
||||
));
|
||||
this.register(forwardEvent(this._renderer.onContextLoss, this._onContextLoss));
|
||||
|
||||
@@ -14,10 +14,10 @@ import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IThemeS
|
||||
import { ITerminal } from 'browser/Types';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { Attributes, Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
|
||||
import { Attributes, Content, ExtFlags, NULL_CELL_CHAR, NULL_CELL_CODE, UnderlineStyle } from 'common/buffer/Constants';
|
||||
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
|
||||
import { Disposable, MutableDisposable, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
|
||||
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
|
||||
import { ICoreService, IDecorationService, ILogService, IOptionsService, IUnicodeService } from 'common/services/Services';
|
||||
import { CharData, IBufferLine, ICellData } from 'common/Types';
|
||||
import { IDisposable, Terminal } from 'xterm';
|
||||
import { GlyphRenderer } from './GlyphRenderer';
|
||||
@@ -71,6 +71,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
private readonly _decorationService: IDecorationService,
|
||||
private readonly _optionsService: IOptionsService,
|
||||
private readonly _themeService: IThemeService,
|
||||
private readonly _unicodeService: IUnicodeService,
|
||||
preserveDrawingBuffer?: boolean
|
||||
) {
|
||||
super();
|
||||
@@ -395,6 +396,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
let i: number;
|
||||
let x: number;
|
||||
let j: number;
|
||||
let variantOffset: number = -1;
|
||||
start = clamp(start, terminal.rows - 1, 0);
|
||||
end = clamp(end, terminal.rows - 1, 0);
|
||||
|
||||
@@ -409,11 +411,18 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
this._model.cursor = undefined;
|
||||
let modelUpdated = false;
|
||||
|
||||
const fontSize = this._optionsService.rawOptions.fontSize;
|
||||
const drp = this._coreBrowserService.dpr;
|
||||
const lineWidth = Math.max(1, Math.floor(fontSize * drp / 15));
|
||||
const deviceCellWidth = this._charAtlas?.getDeviceCellWidth();
|
||||
|
||||
for (y = start; y <= end; y++) {
|
||||
row = y + terminal.buffer.ydisp;
|
||||
line = terminal.buffer.lines.get(row)!;
|
||||
this._model.lineLengths[y] = 0;
|
||||
joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
|
||||
// row start variant init
|
||||
variantOffset = 0;
|
||||
for (x = 0; x < terminal.cols; x++) {
|
||||
lastBg = this._cellColorResolver.result.bg;
|
||||
line.loadCell(x, cell);
|
||||
@@ -447,6 +456,14 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
|
||||
chars = cell.getChars();
|
||||
code = cell.getCode();
|
||||
|
||||
let chWidth: number;
|
||||
if (typeof code === 'number') {
|
||||
chWidth = this._unicodeService.wcwidth(code);
|
||||
} else {
|
||||
chWidth = this._unicodeService.getStringCellWidth(code);
|
||||
}
|
||||
|
||||
i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
|
||||
|
||||
// Load colors/resolve overrides into work colors
|
||||
@@ -480,13 +497,27 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
|
||||
if (code !== NULL_CELL_CODE) {
|
||||
this._model.lineLengths[y] = x + 1;
|
||||
} else {
|
||||
if (cell.extended.underlineStyle !== UnderlineStyle.DOTTED) {
|
||||
variantOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this._cellColorResolver.result.ext &= ~ExtFlags.VARIANT_OFFSET;
|
||||
this._cellColorResolver.result.ext |= (variantOffset << 29) & ExtFlags.VARIANT_OFFSET;
|
||||
|
||||
// Nothing has changed, no updates needed
|
||||
if (this._model.cells[i] === code &&
|
||||
this._model.cells[i + RENDER_MODEL_BG_OFFSET] === this._cellColorResolver.result.bg &&
|
||||
this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._cellColorResolver.result.fg &&
|
||||
this._model.cells[i + RENDER_MODEL_EXT_OFFSET] === this._cellColorResolver.result.ext) {
|
||||
if (cell.extended.underlineStyle === UnderlineStyle.DOTTED) {
|
||||
if (code !== NULL_CELL_CODE) {
|
||||
variantOffset = ((deviceCellWidth! * chWidth) - ((lineWidth * 2) - variantOffset)) % (lineWidth * 2);
|
||||
}
|
||||
} else {
|
||||
variantOffset = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -503,7 +534,14 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
this._model.cells[i + RENDER_MODEL_FG_OFFSET] = this._cellColorResolver.result.fg;
|
||||
this._model.cells[i + RENDER_MODEL_EXT_OFFSET] = this._cellColorResolver.result.ext;
|
||||
|
||||
this._glyphRenderer!.updateCell(x, y, code, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext, chars, lastBg);
|
||||
this._glyphRenderer!.updateCell(x, y, code, this._cellColorResolver.result.bg, this._cellColorResolver.result.fg, this._cellColorResolver.result.ext, chars, lastBg, variantOffset);
|
||||
if (cell.extended.underlineStyle === UnderlineStyle.DOTTED) {
|
||||
if (code !== NULL_CELL_CODE) {
|
||||
variantOffset = ((deviceCellWidth! * chWidth) - ((lineWidth * 2) - variantOffset)) % (lineWidth * 2);
|
||||
}
|
||||
} else {
|
||||
variantOffset = 0;
|
||||
}
|
||||
|
||||
if (isJoined) {
|
||||
// Restore work cell
|
||||
@@ -512,7 +550,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
||||
// Null out non-first cells
|
||||
for (x++; x < lastCharX; x++) {
|
||||
j = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
|
||||
this._glyphRenderer!.updateCell(x, y, NULL_CELL_CODE, 0, 0, 0, NULL_CELL_CHAR, 0);
|
||||
this._glyphRenderer!.updateCell(x, y, NULL_CELL_CODE, 0, 0, 0, NULL_CELL_CHAR, 0, 0);
|
||||
this._model.cells[j] = NULL_CELL_CODE;
|
||||
this._model.cells[j + RENDER_MODEL_BG_OFFSET] = this._cellColorResolver.result.bg;
|
||||
this._model.cells[j + RENDER_MODEL_FG_OFFSET] = this._cellColorResolver.result.fg;
|
||||
|
||||
Reference in New Issue
Block a user