-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use variants for underline dotted. #4703
Changes from 3 commits
32da1d8
cb175e5
c81dfee
fe7f17f
5f0647f
68ded1a
25afc19
f5d128b
1f3143c
2b0106f
e09ed98
564371e
edfacbb
52c87bc
6ace416
f1f0191
f488187
d15abd7
08f7b4c
bec1642
810e626
42d6c2b
7fa56fd
bfa6f65
390e4f3
6214f4c
2f074b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import { AttributeData } from 'common/buffer/AttributeData'; | |
import { NULL_CELL_CODE, Content, UnderlineStyle } from 'common/buffer/Constants'; | ||
import { IColorSet, ReadonlyColorSet } from 'browser/Types'; | ||
import { CellData } from 'common/buffer/CellData'; | ||
import { IOptionsService, IBufferService, IDecorationService } from 'common/services/Services'; | ||
import { IOptionsService, IBufferService, IDecorationService, IUnicodeService } from 'common/services/Services'; | ||
import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services'; | ||
import { JoinedCellData } from 'browser/services/CharacterJoinerService'; | ||
import { color, css } from 'common/Color'; | ||
|
@@ -41,7 +41,8 @@ export class TextRenderLayer extends BaseRenderLayer { | |
private readonly _characterJoinerService: ICharacterJoinerService, | ||
decorationService: IDecorationService, | ||
coreBrowserService: ICoreBrowserService, | ||
themeService: IThemeService | ||
themeService: IThemeService, | ||
private readonly _unicodeService: IUnicodeService | ||
) { | ||
super(terminal, container, 'text', zIndex, alpha, themeService, bufferService, optionsService, decorationService, coreBrowserService); | ||
this._state = new GridCache<CharData>(); | ||
|
@@ -74,13 +75,20 @@ export class TextRenderLayer extends BaseRenderLayer { | |
callback: ( | ||
cell: ICellData, | ||
x: number, | ||
y: number | ||
y: number, | ||
variantOffset: number | ||
) => void | ||
): void { | ||
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(); | ||
let variantOffset: number = -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can all this logic live inside CellColorResolver? |
||
for (let y = firstRow; y <= lastRow; y++) { | ||
const row = y + this._bufferService.buffer.ydisp; | ||
const line = this._bufferService.buffer.lines.get(row); | ||
const joinedRanges = this._characterJoinerService.getJoinedCharacters(row); | ||
variantOffset = 0; | ||
for (let x = 0; x < this._bufferService.cols; x++) { | ||
line!.loadCell(x, this._workCell); | ||
let cell = this._workCell; | ||
|
@@ -92,9 +100,20 @@ export class TextRenderLayer extends BaseRenderLayer { | |
// The character to the left is a wide character, drawing is owned by | ||
// the char at x-1 | ||
if (cell.getWidth() === 0) { | ||
if (cell.extended.underlineStyle !== UnderlineStyle.DOTTED) { | ||
variantOffset = 0; | ||
} | ||
continue; | ||
} | ||
|
||
const code = cell.getCode(); | ||
let chWidth: number; | ||
if (typeof code === 'number') { | ||
chWidth = this._unicodeService.wcwidth(code); | ||
} else { | ||
chWidth = this._unicodeService.getStringCellWidth(code); | ||
} | ||
|
||
// exit early for NULL and SP | ||
// NOTE: commented out due to #4120 (needs a more clever patch to keep things performant) | ||
// const code = cell.getCode(); | ||
|
@@ -148,9 +167,18 @@ export class TextRenderLayer extends BaseRenderLayer { | |
callback( | ||
cell, | ||
x, | ||
y | ||
y, | ||
variantOffset | ||
); | ||
|
||
if (cell.extended.underlineStyle === UnderlineStyle.DOTTED) { | ||
if (code !== NULL_CELL_CODE) { | ||
variantOffset = ((deviceCellWidth! * chWidth) - ((lineWidth * 2) - variantOffset)) % (lineWidth * 2); | ||
} | ||
} else { | ||
variantOffset = 0; | ||
} | ||
|
||
x = lastCharX; | ||
} | ||
} | ||
|
@@ -235,7 +263,7 @@ export class TextRenderLayer extends BaseRenderLayer { | |
} | ||
|
||
private _drawForeground(firstRow: number, lastRow: number): void { | ||
this._forEachCell(firstRow, lastRow, (cell, x, y) => this._drawChars(cell, x, y)); | ||
this._forEachCell(firstRow, lastRow, (cell, x, y, variantOffset) => this._drawChars(cell, x, y, variantOffset ?? 0)); | ||
} | ||
|
||
public handleGridChanged(firstRow: number, lastRow: number): void { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same; can this be shared inside CellColorResolver? |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should be able to pull device cell width off `this.dimensions`` |
||
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; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should live inside CellColorResolver.result. It would be ideal if calculating
variantOffset
was inside that function as well.