@xterm/addon-webgl 0.20.0-beta.20 → 0.20.0-beta.201
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/addon-webgl.js +1 -1
- package/lib/addon-webgl.js.map +1 -1
- package/lib/addon-webgl.mjs +5 -31
- package/lib/addon-webgl.mjs.map +4 -4
- package/package.json +4 -4
- package/src/CellColorResolver.ts +5 -2
- package/src/CharAtlasCache.ts +3 -1
- package/src/CursorBlinkStateManager.ts +67 -8
- package/src/DevicePixelObserver.ts +1 -1
- package/src/GlyphRenderer.ts +3 -3
- package/src/RectangleRenderer.ts +1 -1
- package/src/TextureAtlas.ts +76 -55
- package/src/Types.ts +3 -3
- package/src/WebglAddon.ts +8 -14
- package/src/WebglRenderer.ts +62 -10
- package/src/customGlyphs/CustomGlyphDefinitions.ts +181 -31
- package/src/customGlyphs/CustomGlyphRasterizer.ts +44 -16
- package/src/renderLayer/BaseRenderLayer.ts +1 -1
- package/typings/addon-webgl.d.ts +12 -7
package/src/WebglRenderer.ts
CHANGED
|
@@ -13,7 +13,8 @@ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeS
|
|
|
13
13
|
import { CharData, IBufferLine, ICellData } from 'common/Types';
|
|
14
14
|
import { AttributeData } from 'common/buffer/AttributeData';
|
|
15
15
|
import { CellData } from 'common/buffer/CellData';
|
|
16
|
-
import { Attributes, Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
|
|
16
|
+
import { Attributes, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
|
|
17
|
+
import { TextBlinkStateManager } from 'browser/renderer/shared/TextBlinkStateManager';
|
|
17
18
|
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
|
|
18
19
|
import { Terminal } from '@xterm/xterm';
|
|
19
20
|
import { GlyphRenderer } from './GlyphRenderer';
|
|
@@ -22,14 +23,15 @@ import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET
|
|
|
22
23
|
import { IWebGL2RenderingContext, type ITextureAtlas } from './Types';
|
|
23
24
|
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
|
|
24
25
|
import { IRenderLayer } from './renderLayer/Types';
|
|
25
|
-
import { Emitter,
|
|
26
|
-
import { addDisposableListener } from '
|
|
27
|
-
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from '
|
|
26
|
+
import { Emitter, EventUtils } from 'common/Event';
|
|
27
|
+
import { addDisposableListener } from 'browser/Dom';
|
|
28
|
+
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
28
29
|
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
|
|
29
30
|
|
|
30
31
|
export class WebglRenderer extends Disposable implements IRenderer {
|
|
31
32
|
private _renderLayers: IRenderLayer[];
|
|
32
|
-
private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = new MutableDisposable();
|
|
33
|
+
private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = this._register(new MutableDisposable());
|
|
34
|
+
private _textBlinkStateManager: TextBlinkStateManager;
|
|
33
35
|
private _charAtlasDisposable = this._register(new MutableDisposable());
|
|
34
36
|
private _charAtlas: ITextureAtlas | undefined;
|
|
35
37
|
private _devicePixelRatio: number;
|
|
@@ -37,8 +39,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
37
39
|
private _observerDisposable = this._register(new MutableDisposable());
|
|
38
40
|
|
|
39
41
|
private _model: RenderModel = new RenderModel();
|
|
42
|
+
private _rowHasBlinkingCells: boolean[] = [];
|
|
43
|
+
private _rowHasBlinkingCellsCount: number = 0;
|
|
40
44
|
private _workCell: ICellData = new CellData();
|
|
41
|
-
private _workCell2: ICellData = new CellData();
|
|
42
45
|
private _cellColorResolver: CellColorResolver;
|
|
43
46
|
|
|
44
47
|
private _canvas: HTMLCanvasElement;
|
|
@@ -105,6 +108,12 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
105
108
|
this._updateDimensions();
|
|
106
109
|
this._updateCursorBlink();
|
|
107
110
|
this._register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
|
|
111
|
+
this._textBlinkStateManager = this._register(new TextBlinkStateManager(
|
|
112
|
+
() => this._requestRedrawViewport(),
|
|
113
|
+
this._coreBrowserService,
|
|
114
|
+
this._optionsService
|
|
115
|
+
));
|
|
116
|
+
this._resetBlinkingRowState();
|
|
108
117
|
|
|
109
118
|
this._deviceMaxTextureSize = this._gl.getParameter(this._gl.MAX_TEXTURE_SIZE);
|
|
110
119
|
|
|
@@ -136,6 +145,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
136
145
|
this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, w, (w, h) => this._setCanvasDevicePixelDimensions(w, h));
|
|
137
146
|
}));
|
|
138
147
|
|
|
148
|
+
this._register(addDisposableListener(this._coreBrowserService.mainDocument, 'mousedown', () => this._cursorBlinkStateManager.value?.restartBlinkAnimation()));
|
|
149
|
+
|
|
139
150
|
this._core.screenElement!.appendChild(this._canvas);
|
|
140
151
|
|
|
141
152
|
[this._rectangleRenderer.value, this._glyphRenderer.value] = this._initializeWebGLState();
|
|
@@ -176,6 +187,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
176
187
|
this._updateDimensions();
|
|
177
188
|
|
|
178
189
|
this._model.resize(this._terminal.cols, this._terminal.rows);
|
|
190
|
+
this._resetBlinkingRowState();
|
|
179
191
|
|
|
180
192
|
// Resize all render layers
|
|
181
193
|
for (const l of this._renderLayers) {
|
|
@@ -202,6 +214,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
202
214
|
// Force a full refresh. Resizing `_glyphRenderer` should clear it already,
|
|
203
215
|
// so there is no need to clear it again here.
|
|
204
216
|
this._clearModel(false);
|
|
217
|
+
|
|
218
|
+
// Render synchronously to avoid flicker when the canvas is cleared
|
|
219
|
+
this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1, sync: true });
|
|
205
220
|
}
|
|
206
221
|
|
|
207
222
|
public handleCharSizeChanged(): void {
|
|
@@ -226,6 +241,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
226
241
|
this._requestRedrawViewport();
|
|
227
242
|
}
|
|
228
243
|
|
|
244
|
+
public handleViewportVisibilityChange(isVisible: boolean): void {
|
|
245
|
+
this._textBlinkStateManager.setViewportVisible(isVisible);
|
|
246
|
+
}
|
|
247
|
+
|
|
229
248
|
public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
|
|
230
249
|
for (const l of this._renderLayers) {
|
|
231
250
|
l.handleSelectionChanged(this._terminal, start, end, columnSelectMode);
|
|
@@ -285,8 +304,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
285
304
|
if (this._charAtlas !== atlas) {
|
|
286
305
|
this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);
|
|
287
306
|
this._charAtlasDisposable.value = combinedDisposable(
|
|
288
|
-
|
|
289
|
-
|
|
307
|
+
EventUtils.forward(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
|
|
308
|
+
EventUtils.forward(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
|
|
290
309
|
);
|
|
291
310
|
}
|
|
292
311
|
this._charAtlas = atlas;
|
|
@@ -318,6 +337,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
318
337
|
l.reset(this._terminal);
|
|
319
338
|
}
|
|
320
339
|
|
|
340
|
+
this._resetBlinkingRowState();
|
|
341
|
+
this._textBlinkStateManager.setNeedsBlinkInViewport(false);
|
|
342
|
+
|
|
321
343
|
this._cursorBlinkStateManager.value?.restartBlinkAnimation();
|
|
322
344
|
this._updateCursorBlink();
|
|
323
345
|
}
|
|
@@ -415,6 +437,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
415
437
|
for (y = start; y <= end; y++) {
|
|
416
438
|
row = y + terminal.buffer.ydisp;
|
|
417
439
|
line = terminal.buffer.lines.get(row)!;
|
|
440
|
+
let rowHasBlinkingCells = false;
|
|
418
441
|
this._model.lineLengths[y] = 0;
|
|
419
442
|
isCursorRow = cursorY === row;
|
|
420
443
|
skipJoinedCheckUntilX = 0;
|
|
@@ -472,8 +495,12 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
472
495
|
code = cell.getCode();
|
|
473
496
|
i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
|
|
474
497
|
|
|
498
|
+
if (!rowHasBlinkingCells && cell.isBlink()) {
|
|
499
|
+
rowHasBlinkingCells = true;
|
|
500
|
+
}
|
|
501
|
+
|
|
475
502
|
// Load colors/resolve overrides into work colors
|
|
476
|
-
this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width);
|
|
503
|
+
this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width, this.dimensions.device.cell.height);
|
|
477
504
|
|
|
478
505
|
// Override colors for cursor cell
|
|
479
506
|
if (isCursorVisible && row === cursorY) {
|
|
@@ -501,6 +528,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
501
528
|
}
|
|
502
529
|
}
|
|
503
530
|
|
|
531
|
+
if (this._textBlinkStateManager.isEnabled && !this._textBlinkStateManager.isBlinkOn && cell.isBlink()) {
|
|
532
|
+
this._cellColorResolver.result.fg |= FgFlags.INVISIBLE;
|
|
533
|
+
}
|
|
534
|
+
|
|
504
535
|
if (code !== NULL_CELL_CODE) {
|
|
505
536
|
this._model.lineLengths[y] = x + 1;
|
|
506
537
|
}
|
|
@@ -547,11 +578,31 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
547
578
|
x--; // Go back to the previous update cell for next iteration
|
|
548
579
|
}
|
|
549
580
|
}
|
|
581
|
+
this._setRowBlinkState(y, rowHasBlinkingCells);
|
|
550
582
|
}
|
|
551
583
|
if (modelUpdated) {
|
|
552
584
|
this._rectangleRenderer.value!.updateBackgrounds(this._model);
|
|
553
585
|
}
|
|
554
586
|
this._rectangleRenderer.value!.updateCursor(this._model);
|
|
587
|
+
this._updateTextBlinkState();
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
private _resetBlinkingRowState(): void {
|
|
591
|
+
this._rowHasBlinkingCells = new Array(this._terminal.rows).fill(false);
|
|
592
|
+
this._rowHasBlinkingCellsCount = 0;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
private _setRowBlinkState(row: number, hasBlinkingCells: boolean): void {
|
|
596
|
+
const previous = this._rowHasBlinkingCells[row];
|
|
597
|
+
if (previous === hasBlinkingCells) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
this._rowHasBlinkingCells[row] = hasBlinkingCells;
|
|
601
|
+
this._rowHasBlinkingCellsCount += hasBlinkingCells ? 1 : -1;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
private _updateTextBlinkState(): void {
|
|
605
|
+
this._textBlinkStateManager.setNeedsBlinkInViewport(this._rowHasBlinkingCellsCount > 0);
|
|
555
606
|
}
|
|
556
607
|
|
|
557
608
|
/**
|
|
@@ -617,7 +668,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
|
|
|
617
668
|
// the change as it's an exact multiple of the cell sizes.
|
|
618
669
|
this._canvas.width = width;
|
|
619
670
|
this._canvas.height = height;
|
|
620
|
-
|
|
671
|
+
// Render synchronously to avoid flicker when the canvas is cleared
|
|
672
|
+
this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1, sync: true });
|
|
621
673
|
}
|
|
622
674
|
|
|
623
675
|
private _requestRedrawViewport(): void {
|
|
@@ -3,10 +3,64 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphPathDrawFunctionDefinition } from './Types';
|
|
6
|
+
import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphDefinitionPart, type CustomGlyphPathDrawFunctionDefinition } from './Types';
|
|
7
7
|
|
|
8
8
|
/* eslint-disable max-len */
|
|
9
9
|
|
|
10
|
+
const enum Shapes {
|
|
11
|
+
/** │ */ TOP_TO_BOTTOM = 'M.5,0 L.5,1',
|
|
12
|
+
/** ─ */ LEFT_TO_RIGHT = 'M0,.5 L1,.5',
|
|
13
|
+
|
|
14
|
+
/** └ */ TOP_TO_RIGHT = 'M.5,0 L.5,.5 L1,.5',
|
|
15
|
+
/** ┘ */ TOP_TO_LEFT = 'M.5,0 L.5,.5 L0,.5',
|
|
16
|
+
/** ┐ */ LEFT_TO_BOTTOM = 'M0,.5 L.5,.5 L.5,1',
|
|
17
|
+
/** ┌ */ RIGHT_TO_BOTTOM = 'M0.5,1 L.5,.5 L1,.5',
|
|
18
|
+
|
|
19
|
+
/** ╵ */ MIDDLE_TO_TOP = 'M.5,.5 L.5,0',
|
|
20
|
+
/** ╴ */ MIDDLE_TO_LEFT = 'M.5,.5 L0,.5',
|
|
21
|
+
/** ╶ */ MIDDLE_TO_RIGHT = 'M.5,.5 L1,.5',
|
|
22
|
+
/** ╷ */ MIDDLE_TO_BOTTOM = 'M.5,.5 L.5,1',
|
|
23
|
+
|
|
24
|
+
/** ┴ */ T_TOP = 'M0,.5 L1,.5 M.5,.5 L.5,0',
|
|
25
|
+
/** ┤ */ T_LEFT = 'M.5,0 L.5,1 M.5,.5 L0,.5',
|
|
26
|
+
/** ├ */ T_RIGHT = 'M.5,0 L.5,1 M.5,.5 L1,.5',
|
|
27
|
+
/** ┬ */ T_BOTTOM = 'M0,.5 L1,.5 M.5,.5 L.5,1',
|
|
28
|
+
|
|
29
|
+
/** ┼ */ CROSS = 'M0,.5 L1,.5 M.5,0 L.5,1',
|
|
30
|
+
|
|
31
|
+
/** ╌ */ TWO_DASHES_HORIZONTAL = 'M.1,.5 L.4,.5 M.6,.5 L.9,.5', // .2 empty, .3 filled
|
|
32
|
+
/** ┄ */ THREE_DASHES_HORIZONTAL = 'M.0667,.5 L.2667,.5 M.4,.5 L.6,.5 M.7333,.5 L.9333,.5', // .1333 empty, .2 filled
|
|
33
|
+
/** ┉ */ FOUR_DASHES_HORIZONTAL = 'M.05,.5 L.2,.5 M.3,.5 L.45,.5 M.55,.5 L.7,.5 M.8,.5 L.95,.5', // .1 empty, .15 filled
|
|
34
|
+
/** ╎ */ TWO_DASHES_VERTICAL = 'M.5,.1 L.5,.4 M.5,.6 L.5,.9',
|
|
35
|
+
/** ┆ */ THREE_DASHES_VERTICAL = 'M.5,.0667 L.5,.2667 M.5,.4 L.5,.6 M.5,.7333 L.5,.9333',
|
|
36
|
+
/** ┊ */ FOUR_DASHES_VERTICAL = 'M.5,.05 L.5,.2 M.5,.3 L.5,.45 L.5,.55 M.5,.7 L.5,.95',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
namespace GitBranchSymbolsParts {
|
|
40
|
+
// Lines
|
|
41
|
+
export const LINE_H: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 });
|
|
42
|
+
export const LINE_V: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 });
|
|
43
|
+
|
|
44
|
+
// Fading lines
|
|
45
|
+
export const FADE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: 'M0,.5 L.28,.5 M.32,.5 L.52,.5 M.60,.5 L.72,.5 M.84,.5 L.90,.5', strokeWidth: 1 });
|
|
46
|
+
export const FADE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: 'M.10,.5 L.16,.5 M.28,.5 L.40,.5 M.48,.5 L.68,.5 M.72,.5 L1,.5', strokeWidth: 1 });
|
|
47
|
+
export const FADE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: 'M.5,0 L.5,.28 M.5,.32 L.5,.52 M.5,.60 L.5,.72 M.5,.84 L.5,.90', strokeWidth: 1 });
|
|
48
|
+
export const FADE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: 'M.5,.10 L.5,.16 M.5,.28 L.5,.40 M.5,.48 L.5,.68 M.5,.72 L.5,1', strokeWidth: 1 });
|
|
49
|
+
|
|
50
|
+
// Curved corners
|
|
51
|
+
export const CURVE_DOWN_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp: number, yp: number) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 });
|
|
52
|
+
export const CURVE_DOWN_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp: number, yp: number) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 });
|
|
53
|
+
export const CURVE_UP_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp: number, yp: number) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 });
|
|
54
|
+
export const CURVE_UP_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp: number, yp: number) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 });
|
|
55
|
+
|
|
56
|
+
// Node parts
|
|
57
|
+
export const NODE_FILL: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' });
|
|
58
|
+
export const NODE_STROKE: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5', strokeWidth: 1 });
|
|
59
|
+
export const NODE_LINE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 });
|
|
60
|
+
export const NODE_LINE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 });
|
|
61
|
+
export const NODE_LINE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 });
|
|
62
|
+
export const NODE_LINE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 });
|
|
63
|
+
}
|
|
10
64
|
|
|
11
65
|
export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } = {
|
|
12
66
|
// #region Box Drawing (2500-257F)
|
|
@@ -299,6 +353,109 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi
|
|
|
299
353
|
|
|
300
354
|
// #endregion
|
|
301
355
|
|
|
356
|
+
// #region Progress Indicators (EE00-EE0B)
|
|
357
|
+
|
|
358
|
+
// initially added in Fira Code and later Nerd Fonts
|
|
359
|
+
// https://github.com/ryanoasis/nerd-fonts/pull/1733
|
|
360
|
+
|
|
361
|
+
// Progress bars (EE00-EE05)
|
|
362
|
+
'\u{EE00}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,.05 L.1,.05 L.1,.95 L1,.95 L1,1 L0,1 Z' }, // PROGRESS BAR EMPTY START
|
|
363
|
+
'\u{EE01}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,.05 L0,.05 Z M0,.95 L1,.95 L1,1 L0,1 Z' }, // PROGRESS BAR EMPTY MIDDLE
|
|
364
|
+
'\u{EE02}': { type: CustomGlyphDefinitionType.PATH, data: 'M1,0 L0,0 L0,.05 L.9,.05 L.9,.95 L0,.95 L0,1 L1,1 Z' }, // PROGRESS BAR EMPTY END
|
|
365
|
+
'\u{EE03}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,.05 L.1,.05 L.1,.95 L1,.95 L1,1 L0,1 Z M.25,.15 L1,.15 L1,.85 L.25,.85 Z' }, // PROGRESS BAR FILLED START
|
|
366
|
+
'\u{EE04}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,.05 L0,.05 Z M0,.95 L1,.95 L1,1 L0,1 Z M0,.15 L1,.15 L1,.85 L0,.85 Z' }, // PROGRESS BAR FILLED MIDDLE
|
|
367
|
+
'\u{EE05}': { type: CustomGlyphDefinitionType.PATH, data: 'M1,0 L0,0 L0,.05 L.9,.05 L.9,.95 L0,.95 L0,1 L1,1 Z M0,.15 L.75,.15 L.75,.85 L0,.85 Z' }, // PROGRESS BAR FILLED END
|
|
368
|
+
|
|
369
|
+
// Progress spinners (EE06-EE0B) - 6-frame spinner animation using stroked arcs
|
|
370
|
+
'\u{EE06}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0.6574,0.303 Q0.623,0.291,0.5852,0.285 T0.5082,0.279 T0.4311,0.285 T0.359,0.303 L0.3082,0.248 Q0.3525,0.232,0.4041,0.2235 T0.5082,0.215 T0.6123,0.2235 T0.7082,0.248 Z', type: CustomGlyphVectorType.FILL }, scaleType: CustomGlyphScaleType.CHAR }, // SPINNER FRAME 1 (12 o'clock)
|
|
371
|
+
'\u{EE07}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0.8557,0.582 L0.7656,0.551 Q0.7852,0.53,0.7951,0.507 T0.8049,0.46 Q0.8049,0.424,0.782,0.3905 T0.718,0.332 T0.6221,0.293 T0.5082,0.279 L0.5082,0.215 Q0.5607,0.215,0.6123,0.2235 T0.709,0.248 T0.7918,0.287 T0.8557,0.3375 T0.8959,0.3965 T0.9098,0.46 T0.8959,0.5235 T0.8557,0.582 Z', type: CustomGlyphVectorType.FILL }, scaleType: CustomGlyphScaleType.CHAR }, // SPINNER FRAME 2 (2 o'clock)
|
|
372
|
+
'\u{EE08}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0.5082,0.705 Q0.482,0.705,0.4557,0.703 T0.4049,0.697 L0.4311,0.635 Q0.4508,0.638,0.4697,0.6395 T0.5082,0.641 Q0.5672,0.641,0.6221,0.627 T0.718,0.588 T0.782,0.5295 T0.8049,0.46 Q0.8049,0.436,0.7951,0.413 T0.7656,0.369 L0.8557,0.338 Q0.882,0.365,0.8959,0.3965 T0.9098,0.46 T0.8959,0.5235 T0.8557,0.5825 T0.7918,0.633 T0.709,0.672 T0.6123,0.6965 T0.5082,0.705 Z', type: CustomGlyphVectorType.FILL }, scaleType: CustomGlyphScaleType.CHAR }, // SPINNER FRAME 3 (4 o'clock)
|
|
373
|
+
'\u{EE09}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0.5082,0.705 Q0.4557,0.705,0.4041,0.6965 T0.3074,0.672 T0.2246,0.633 T0.1607,0.5825 T0.1205,0.5235 T0.1066,0.46 L0.2115,0.46 Q0.2115,0.496,0.2344,0.5295 T0.2984,0.588 T0.3943,0.627 T0.5082,0.641 T0.6221,0.627 T0.718,0.588 T0.782,0.5295 T0.8049,0.46 L0.9098,0.46 Q0.9098,0.492,0.8959,0.5235 T0.8557,0.5825 T0.7918,0.633 T0.709,0.672 T0.6123,0.6965 T0.5082,0.705 Z', type: CustomGlyphVectorType.FILL }, scaleType: CustomGlyphScaleType.CHAR }, // SPINNER FRAME 4 (6 o'clock)
|
|
374
|
+
'\u{EE0A}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0.5082,0.705 Q0.4557,0.705,0.4041,0.6965 T0.3074,0.672 T0.2246,0.633 T0.1607,0.5825 T0.1205,0.5235 T0.1066,0.46 T0.1205,0.3965 T0.1607,0.338 L0.2508,0.369 Q0.2311,0.39,0.2213,0.413 T0.2115,0.46 Q0.2115,0.496,0.2344,0.5295 T0.2984,0.588 T0.3943,0.627 T0.5082,0.641 Q0.5279,0.641,0.5467,0.6395 T0.5852,0.635 L0.6115,0.697 Q0.5869,0.701,0.5607,0.703 T0.5082,0.705 Z', type: CustomGlyphVectorType.FILL }, scaleType: CustomGlyphScaleType.CHAR }, // SPINNER FRAME 5 (8 o'clock)
|
|
375
|
+
'\u{EE0B}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0.1607,0.582 Q0.1344,0.555,0.1205,0.5235 T0.1066,0.46 T0.1205,0.3965 T0.1607,0.3375 T0.2246,0.287 T0.3074,0.248 T0.4041,0.2235 T0.5082,0.215 L0.5082,0.279 Q0.4492,0.279,0.3943,0.293 T0.2984,0.332 T0.2344,0.3905 T0.2115,0.46 Q0.2115,0.484,0.2213,0.507 T0.2508,0.551 Z', type: CustomGlyphVectorType.FILL }, scaleType: CustomGlyphScaleType.CHAR }, // SPINNER FRAME 6 (10 o'clock)
|
|
376
|
+
|
|
377
|
+
// #endregion
|
|
378
|
+
|
|
379
|
+
// #region Git Branch Symbols (F5D0-F60D)
|
|
380
|
+
|
|
381
|
+
// Initially added in Kitty (https://github.com/kovidgoyal/kitty/pull/7681)
|
|
382
|
+
// then in Wezterm (https://github.com/wezterm/wezterm/issues/6328).
|
|
383
|
+
|
|
384
|
+
// Straight lines (F5D0-F5D9)
|
|
385
|
+
'\u{F5D0}': GitBranchSymbolsParts.LINE_H, // Same as 2500
|
|
386
|
+
'\u{F5D1}': GitBranchSymbolsParts.LINE_V, // Same as 2502
|
|
387
|
+
'\u{F5D2}': GitBranchSymbolsParts.FADE_RIGHT,
|
|
388
|
+
'\u{F5D3}': GitBranchSymbolsParts.FADE_LEFT,
|
|
389
|
+
'\u{F5D4}': GitBranchSymbolsParts.FADE_DOWN,
|
|
390
|
+
'\u{F5D5}': GitBranchSymbolsParts.FADE_UP,
|
|
391
|
+
|
|
392
|
+
// Curved lines (F5D6-F5D9)
|
|
393
|
+
'\u{F5D6}': GitBranchSymbolsParts.CURVE_DOWN_RIGHT, // Same as 256D)
|
|
394
|
+
'\u{F5D7}': GitBranchSymbolsParts.CURVE_DOWN_LEFT, // Same as 256E)
|
|
395
|
+
'\u{F5D8}': GitBranchSymbolsParts.CURVE_UP_RIGHT, // Same as 2570)
|
|
396
|
+
'\u{F5D9}': GitBranchSymbolsParts.CURVE_UP_LEFT, // Same as 256F)
|
|
397
|
+
|
|
398
|
+
// Branching lines (F5DA-F5ED)
|
|
399
|
+
'\u{F5DA}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
400
|
+
'\u{F5DB}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_RIGHT],
|
|
401
|
+
'\u{F5DC}': [GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
402
|
+
'\u{F5DD}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_UP_LEFT],
|
|
403
|
+
'\u{F5DE}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_LEFT],
|
|
404
|
+
'\u{F5DF}': [GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_LEFT],
|
|
405
|
+
'\u{F5E0}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_LEFT],
|
|
406
|
+
'\u{F5E1}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_RIGHT],
|
|
407
|
+
'\u{F5E2}': [GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_DOWN_RIGHT],
|
|
408
|
+
'\u{F5E3}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_UP_LEFT],
|
|
409
|
+
'\u{F5E4}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
410
|
+
'\u{F5E5}': [GitBranchSymbolsParts.CURVE_UP_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
411
|
+
'\u{F5E6}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_UP_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
412
|
+
'\u{F5E7}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_DOWN_RIGHT],
|
|
413
|
+
'\u{F5E8}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_LEFT],
|
|
414
|
+
'\u{F5E9}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
415
|
+
'\u{F5EA}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_LEFT],
|
|
416
|
+
'\u{F5EB}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
417
|
+
'\u{F5EC}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_LEFT],
|
|
418
|
+
'\u{F5ED}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT],
|
|
419
|
+
|
|
420
|
+
// Nodes (F5EE-F5FB)
|
|
421
|
+
'\u{F5EE}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE],
|
|
422
|
+
'\u{F5EF}': GitBranchSymbolsParts.NODE_STROKE,
|
|
423
|
+
'\u{F5F0}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
424
|
+
'\u{F5F1}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
425
|
+
'\u{F5F2}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
426
|
+
'\u{F5F3}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
427
|
+
'\u{F5F4}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
428
|
+
'\u{F5F5}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
429
|
+
'\u{F5F6}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN],
|
|
430
|
+
'\u{F5F7}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN],
|
|
431
|
+
'\u{F5F8}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP],
|
|
432
|
+
'\u{F5F9}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP],
|
|
433
|
+
'\u{F5FA}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_UP],
|
|
434
|
+
'\u{F5FB}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_UP],
|
|
435
|
+
|
|
436
|
+
// Extended Nodes (F5FC-F60D)
|
|
437
|
+
// These were added a little later https://github.com/kovidgoyal/kitty/pull/7805
|
|
438
|
+
'\u{F5FC}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
439
|
+
'\u{F5FD}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
440
|
+
'\u{F5FE}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
441
|
+
'\u{F5FF}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
442
|
+
'\u{F600}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
443
|
+
'\u{F601}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
444
|
+
'\u{F602}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
445
|
+
'\u{F603}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
446
|
+
'\u{F604}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
447
|
+
'\u{F605}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
448
|
+
'\u{F606}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
449
|
+
'\u{F607}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT],
|
|
450
|
+
'\u{F608}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
451
|
+
'\u{F609}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
452
|
+
'\u{F60A}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
453
|
+
'\u{F60B}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
454
|
+
'\u{F60C}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
455
|
+
'\u{F60D}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT],
|
|
456
|
+
|
|
457
|
+
// #endregion
|
|
458
|
+
|
|
302
459
|
// #region Symbols for Legacy Computing (1FB00-1FB3B)
|
|
303
460
|
|
|
304
461
|
// https://www.unicode.org/charts/PDF/U1FB00.pdf
|
|
@@ -516,8 +673,8 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi
|
|
|
516
673
|
] },
|
|
517
674
|
|
|
518
675
|
// Diagonal fill characters (1FB98-1FB99)
|
|
519
|
-
'\u{1FB98}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: '
|
|
520
|
-
'\u{1FB99}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: '
|
|
676
|
+
'\u{1FB98}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: 'M-0.25,-0.25 L1.25,1.25 M-0.25,0 L1,1.25 M-0.25,0.25 L0.75,1.25 M-0.25,0.5 L0.5,1.25 M0,-0.25 L1.25,1 M0.25,-0.25 L1.25,0.75 M0.5,-0.25 L1.25,0.5 M-0.25,0.75 L0.25,1.25 M0.75,-0.25 L1.25,0.25', strokeWidth: 1 }, // UPPER LEFT TO LOWER RIGHT FILL
|
|
677
|
+
'\u{1FB99}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: 'M-0.25,0.5 L0.5,-0.25 M-0.25,0.75 L0.75,-0.25 M-0.25,1 L1,-0.25 M-0.25,1.25 L1.25,-0.25 M0,1.25 L1.25,0 M0.25,1.25 L1.25,0.25 M0.5,1.25 L1.25,0.5 M-0.25,0.25 L0.25,-0.25 M0.75,1.25 L1.25,0.75', strokeWidth: 1 }, // UPPER RIGHT TO LOWER LEFT FILL
|
|
521
678
|
|
|
522
679
|
// Smooth mosaic terminal graphic characters (1FB9A-1FB9B)
|
|
523
680
|
'\u{1FB9A}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0,0 L.5,.5 L0,1 L1,1 L.5,.5 L1,0', type: CustomGlyphVectorType.FILL } }, // UPPER AND LOWER TRIANGULAR HALF BLOCK
|
|
@@ -692,6 +849,27 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi
|
|
|
692
849
|
// #endregion
|
|
693
850
|
};
|
|
694
851
|
|
|
852
|
+
export const blockPatternCodepoints = new Set<number>([
|
|
853
|
+
// Shade characters (2591-2593)
|
|
854
|
+
0x2591,
|
|
855
|
+
0x2592,
|
|
856
|
+
0x2593,
|
|
857
|
+
// Rectangular shade characters (1FB8C-1FB94)
|
|
858
|
+
0x1FB8C,
|
|
859
|
+
0x1FB8D,
|
|
860
|
+
0x1FB8E,
|
|
861
|
+
0x1FB8F,
|
|
862
|
+
0x1FB90,
|
|
863
|
+
0x1FB91,
|
|
864
|
+
0x1FB92,
|
|
865
|
+
0x1FB94,
|
|
866
|
+
// Triangular shade characters (1FB9C-1FB9F)
|
|
867
|
+
0x1FB9C,
|
|
868
|
+
0x1FB9D,
|
|
869
|
+
0x1FB9E,
|
|
870
|
+
0x1FB9F
|
|
871
|
+
]);
|
|
872
|
+
|
|
695
873
|
/**
|
|
696
874
|
* Generates a drawing function for sextant characters. Sextants are a 2x3 grid where each cell
|
|
697
875
|
* can be on or off.
|
|
@@ -839,31 +1017,3 @@ function segmentedDigit(pattern: number): string {
|
|
|
839
1017
|
return paths.join(' ');
|
|
840
1018
|
}
|
|
841
1019
|
|
|
842
|
-
const enum Shapes {
|
|
843
|
-
/** │ */ TOP_TO_BOTTOM = 'M.5,0 L.5,1',
|
|
844
|
-
/** ─ */ LEFT_TO_RIGHT = 'M0,.5 L1,.5',
|
|
845
|
-
|
|
846
|
-
/** └ */ TOP_TO_RIGHT = 'M.5,0 L.5,.5 L1,.5',
|
|
847
|
-
/** ┘ */ TOP_TO_LEFT = 'M.5,0 L.5,.5 L0,.5',
|
|
848
|
-
/** ┐ */ LEFT_TO_BOTTOM = 'M0,.5 L.5,.5 L.5,1',
|
|
849
|
-
/** ┌ */ RIGHT_TO_BOTTOM = 'M0.5,1 L.5,.5 L1,.5',
|
|
850
|
-
|
|
851
|
-
/** ╵ */ MIDDLE_TO_TOP = 'M.5,.5 L.5,0',
|
|
852
|
-
/** ╴ */ MIDDLE_TO_LEFT = 'M.5,.5 L0,.5',
|
|
853
|
-
/** ╶ */ MIDDLE_TO_RIGHT = 'M.5,.5 L1,.5',
|
|
854
|
-
/** ╷ */ MIDDLE_TO_BOTTOM = 'M.5,.5 L.5,1',
|
|
855
|
-
|
|
856
|
-
/** ┴ */ T_TOP = 'M0,.5 L1,.5 M.5,.5 L.5,0',
|
|
857
|
-
/** ┤ */ T_LEFT = 'M.5,0 L.5,1 M.5,.5 L0,.5',
|
|
858
|
-
/** ├ */ T_RIGHT = 'M.5,0 L.5,1 M.5,.5 L1,.5',
|
|
859
|
-
/** ┬ */ T_BOTTOM = 'M0,.5 L1,.5 M.5,.5 L.5,1',
|
|
860
|
-
|
|
861
|
-
/** ┼ */ CROSS = 'M0,.5 L1,.5 M.5,0 L.5,1',
|
|
862
|
-
|
|
863
|
-
/** ╌ */ TWO_DASHES_HORIZONTAL = 'M.1,.5 L.4,.5 M.6,.5 L.9,.5', // .2 empty, .3 filled
|
|
864
|
-
/** ┄ */ THREE_DASHES_HORIZONTAL = 'M.0667,.5 L.2667,.5 M.4,.5 L.6,.5 M.7333,.5 L.9333,.5', // .1333 empty, .2 filled
|
|
865
|
-
/** ┉ */ FOUR_DASHES_HORIZONTAL = 'M.05,.5 L.2,.5 M.3,.5 L.45,.5 M.55,.5 L.7,.5 M.8,.5 L.95,.5', // .1 empty, .15 filled
|
|
866
|
-
/** ╎ */ TWO_DASHES_VERTICAL = 'M.5,.1 L.5,.4 M.5,.6 L.5,.9',
|
|
867
|
-
/** ┆ */ THREE_DASHES_VERTICAL = 'M.5,.0667 L.5,.2667 M.5,.4 L.5,.6 M.5,.7333 L.5,.9333',
|
|
868
|
-
/** ┊ */ FOUR_DASHES_VERTICAL = 'M.5,.05 L.5,.2 M.5,.3 L.5,.45 L.5,.55 M.5,.7 L.5,.95',
|
|
869
|
-
}
|
|
@@ -22,14 +22,15 @@ export function tryDrawCustomGlyph(
|
|
|
22
22
|
deviceCharHeight: number,
|
|
23
23
|
fontSize: number,
|
|
24
24
|
devicePixelRatio: number,
|
|
25
|
-
backgroundColor?: string
|
|
25
|
+
backgroundColor?: string,
|
|
26
|
+
variantOffset: number = 0
|
|
26
27
|
): boolean {
|
|
27
28
|
const unifiedCharDefinition = customGlyphDefinitions[c];
|
|
28
29
|
if (unifiedCharDefinition) {
|
|
29
30
|
// Normalize to array for uniform handling
|
|
30
31
|
const parts = Array.isArray(unifiedCharDefinition) ? unifiedCharDefinition : [unifiedCharDefinition];
|
|
31
32
|
for (const part of parts) {
|
|
32
|
-
drawDefinitionPart(ctx, part, xOffset, yOffset, deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, fontSize, devicePixelRatio, backgroundColor);
|
|
33
|
+
drawDefinitionPart(ctx, part, xOffset, yOffset, deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, fontSize, devicePixelRatio, backgroundColor, variantOffset);
|
|
33
34
|
}
|
|
34
35
|
return true;
|
|
35
36
|
}
|
|
@@ -48,7 +49,8 @@ function drawDefinitionPart(
|
|
|
48
49
|
deviceCharHeight: number,
|
|
49
50
|
fontSize: number,
|
|
50
51
|
devicePixelRatio: number,
|
|
51
|
-
backgroundColor?: string
|
|
52
|
+
backgroundColor?: string,
|
|
53
|
+
variantOffset: number = 0
|
|
52
54
|
): void {
|
|
53
55
|
// Handle scaleType - adjust dimensions and offset when scaling to character area
|
|
54
56
|
let drawWidth = deviceCellWidth;
|
|
@@ -74,13 +76,13 @@ function drawDefinitionPart(
|
|
|
74
76
|
drawBlockVectorChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
|
|
75
77
|
break;
|
|
76
78
|
case CustomGlyphDefinitionType.BLOCK_PATTERN:
|
|
77
|
-
drawPatternChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
|
|
79
|
+
drawPatternChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, variantOffset);
|
|
78
80
|
break;
|
|
79
81
|
case CustomGlyphDefinitionType.PATH_FUNCTION:
|
|
80
82
|
drawPathFunctionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth);
|
|
81
83
|
break;
|
|
82
84
|
case CustomGlyphDefinitionType.PATH:
|
|
83
|
-
drawPathDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
|
|
85
|
+
drawPathDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth);
|
|
84
86
|
break;
|
|
85
87
|
case CustomGlyphDefinitionType.PATH_NEGATIVE:
|
|
86
88
|
drawPathNegativeDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, backgroundColor);
|
|
@@ -171,7 +173,9 @@ function drawPathDefinitionCharacter(
|
|
|
171
173
|
xOffset: number,
|
|
172
174
|
yOffset: number,
|
|
173
175
|
deviceCellWidth: number,
|
|
174
|
-
deviceCellHeight: number
|
|
176
|
+
deviceCellHeight: number,
|
|
177
|
+
devicePixelRatio: number,
|
|
178
|
+
strokeWidth?: number
|
|
175
179
|
): void {
|
|
176
180
|
const instructions = typeof charDefinition === 'string' ? charDefinition : charDefinition(0, 0);
|
|
177
181
|
ctx.beginPath();
|
|
@@ -272,7 +276,13 @@ function drawPathDefinitionCharacter(
|
|
|
272
276
|
}
|
|
273
277
|
lastCommand = type;
|
|
274
278
|
}
|
|
275
|
-
|
|
279
|
+
if (strokeWidth !== undefined) {
|
|
280
|
+
ctx.strokeStyle = ctx.fillStyle;
|
|
281
|
+
ctx.lineWidth = devicePixelRatio * strokeWidth;
|
|
282
|
+
ctx.stroke();
|
|
283
|
+
} else {
|
|
284
|
+
ctx.fill();
|
|
285
|
+
}
|
|
276
286
|
}
|
|
277
287
|
|
|
278
288
|
/**
|
|
@@ -429,7 +439,8 @@ function drawPatternChar(
|
|
|
429
439
|
xOffset: number,
|
|
430
440
|
yOffset: number,
|
|
431
441
|
deviceCellWidth: number,
|
|
432
|
-
deviceCellHeight: number
|
|
442
|
+
deviceCellHeight: number,
|
|
443
|
+
variantOffset: number = 0
|
|
433
444
|
): void {
|
|
434
445
|
let patternSet = cachedPatterns.get(charDefinition);
|
|
435
446
|
if (!patternSet) {
|
|
@@ -478,6 +489,15 @@ function drawPatternChar(
|
|
|
478
489
|
pattern = throwIfFalsy(ctx.createPattern(tmpCanvas, null));
|
|
479
490
|
patternSet.set(fillStyle, pattern);
|
|
480
491
|
}
|
|
492
|
+
// Apply pattern offset to ensure seamless tiling across cells when cell dimensions are odd.
|
|
493
|
+
// variantOffset encodes: bit 1 = x pixel shift, bit 0 = y pixel shift.
|
|
494
|
+
const dx = (variantOffset >> 1) & 1;
|
|
495
|
+
const dy = variantOffset & 1;
|
|
496
|
+
if (dx !== 0 || dy !== 0) {
|
|
497
|
+
pattern.setTransform(new DOMMatrix().translateSelf(-dx, -dy));
|
|
498
|
+
} else {
|
|
499
|
+
pattern.setTransform(new DOMMatrix());
|
|
500
|
+
}
|
|
481
501
|
ctx.fillStyle = pattern;
|
|
482
502
|
ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
|
|
483
503
|
}
|
|
@@ -492,6 +512,11 @@ function drawPathFunctionCharacter(
|
|
|
492
512
|
devicePixelRatio: number,
|
|
493
513
|
strokeWidth?: number
|
|
494
514
|
): void {
|
|
515
|
+
ctx.save();
|
|
516
|
+
ctx.beginPath();
|
|
517
|
+
ctx.rect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
|
|
518
|
+
ctx.clip();
|
|
519
|
+
|
|
495
520
|
ctx.beginPath();
|
|
496
521
|
let actualInstructions: string;
|
|
497
522
|
if (typeof charDefinition === 'function') {
|
|
@@ -518,7 +543,7 @@ function drawPathFunctionCharacter(
|
|
|
518
543
|
if (!args[0] || !args[1]) {
|
|
519
544
|
continue;
|
|
520
545
|
}
|
|
521
|
-
f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio), state);
|
|
546
|
+
f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio, 0, 0, false), state);
|
|
522
547
|
state.lastCommand = type;
|
|
523
548
|
}
|
|
524
549
|
if (strokeWidth !== undefined) {
|
|
@@ -529,6 +554,7 @@ function drawPathFunctionCharacter(
|
|
|
529
554
|
ctx.fill();
|
|
530
555
|
}
|
|
531
556
|
ctx.closePath();
|
|
557
|
+
ctx.restore();
|
|
532
558
|
}
|
|
533
559
|
|
|
534
560
|
/**
|
|
@@ -677,7 +703,7 @@ const svgToCanvasInstructionMap: { [index: string]: (ctx: CanvasRenderingContext
|
|
|
677
703
|
}
|
|
678
704
|
};
|
|
679
705
|
|
|
680
|
-
function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number, doClamp: boolean, devicePixelRatio: number, leftPadding: number = 0, rightPadding: number = 0): number[] {
|
|
706
|
+
function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number, doClamp: boolean, devicePixelRatio: number, leftPadding: number = 0, rightPadding: number = 0, clampToCell: boolean = true): number[] {
|
|
681
707
|
const result = args.map(e => parseFloat(e) || parseInt(e));
|
|
682
708
|
|
|
683
709
|
if (result.length < 2) {
|
|
@@ -687,10 +713,11 @@ function translateArgs(args: string[], cellWidth: number, cellHeight: number, xO
|
|
|
687
713
|
for (let x = 0; x < result.length; x += 2) {
|
|
688
714
|
// Translate from 0-1 to 0-cellWidth
|
|
689
715
|
result[x] *= cellWidth - (leftPadding * devicePixelRatio) - (rightPadding * devicePixelRatio);
|
|
690
|
-
//
|
|
691
|
-
//
|
|
716
|
+
// Round to the nearest 0.5 to ensure a crisp line at 100% devicePixelRatio, and optionally
|
|
717
|
+
// clamp to the cell bounds.
|
|
692
718
|
if (doClamp && result[x] !== 0) {
|
|
693
|
-
|
|
719
|
+
const rounded = Math.round(result[x] + 0.5) - 0.5;
|
|
720
|
+
result[x] = clampToCell ? clamp(rounded, cellWidth, 0) : rounded;
|
|
694
721
|
}
|
|
695
722
|
// Apply the cell's offset (ie. x*cellWidth)
|
|
696
723
|
result[x] += xOffset + (leftPadding * devicePixelRatio);
|
|
@@ -699,10 +726,11 @@ function translateArgs(args: string[], cellWidth: number, cellHeight: number, xO
|
|
|
699
726
|
for (let y = 1; y < result.length; y += 2) {
|
|
700
727
|
// Translate from 0-1 to 0-cellHeight
|
|
701
728
|
result[y] *= cellHeight;
|
|
702
|
-
//
|
|
703
|
-
//
|
|
729
|
+
// Round to the nearest 0.5 to ensure a crisp line at 100% devicePixelRatio, and optionally
|
|
730
|
+
// clamp to the cell bounds.
|
|
704
731
|
if (doClamp && result[y] !== 0) {
|
|
705
|
-
|
|
732
|
+
const rounded = Math.round(result[y] + 0.5) - 0.5;
|
|
733
|
+
result[y] = clampToCell ? clamp(rounded, cellHeight, 0) : rounded;
|
|
706
734
|
}
|
|
707
735
|
// Apply the cell's offset (ie. x*cellHeight)
|
|
708
736
|
result[y] += yOffset;
|
|
@@ -7,7 +7,7 @@ import { ReadonlyColorSet } from 'browser/Types';
|
|
|
7
7
|
import { acquireTextureAtlas } from '../CharAtlasCache';
|
|
8
8
|
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
|
9
9
|
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
|
10
|
-
import { Disposable, toDisposable } from '
|
|
10
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
11
11
|
import { CellData } from 'common/buffer/CellData';
|
|
12
12
|
import { IOptionsService } from 'common/services/Services';
|
|
13
13
|
import { Terminal } from '@xterm/xterm';
|
package/typings/addon-webgl.d.ts
CHANGED
|
@@ -57,21 +57,26 @@ declare module '@xterm/addon-webgl' {
|
|
|
57
57
|
* unicode ranges:
|
|
58
58
|
*
|
|
59
59
|
* - Box Drawing (U+2500-U+257F)
|
|
60
|
-
* -
|
|
60
|
+
* - Block Elements (U+2580-U+259F)
|
|
61
61
|
* - Braille Patterns (U+2800-U+28FF)
|
|
62
|
-
* - Powerline Symbols (U+E0A0
|
|
63
|
-
*
|
|
62
|
+
* - Powerline Symbols (U+E0A0-U+E0D4, Private Use Area with widespread
|
|
63
|
+
* adoption)
|
|
64
|
+
* - Progress Indicators (U+EE00-U+EE0B, Private Use Area initially added in
|
|
65
|
+
* [Fira Code](https://github.com/tonsky/FiraCode) and later
|
|
66
|
+
* [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts/pull/1733)).
|
|
67
|
+
* - Git Branch Symbols (U+F5D0-U+F60D, Private Use Area initially adopted
|
|
68
|
+
* in [Kitty in 2024](https://github.com/kovidgoyal/kitty/pull/7681) by
|
|
69
|
+
* author of [vim-flog](https://github.com/rbong/vim-flog))
|
|
70
|
+
* - Symbols for Legacy Computing (U+1FB00-U+1FBFF)
|
|
64
71
|
*
|
|
65
72
|
* This will typically result in better rendering with continuous lines,
|
|
66
|
-
* even when line height and letter spacing is used.
|
|
67
|
-
* work with the DOM renderer which renders all characters using the font.
|
|
68
|
-
* The default is true.
|
|
73
|
+
* even when line height and letter spacing is used. The default is true.
|
|
69
74
|
*/
|
|
70
75
|
customGlyphs?: boolean;
|
|
71
76
|
|
|
72
77
|
/**
|
|
73
78
|
* Whether to enable the preserveDrawingBuffer flag when creating the WebGL
|
|
74
|
-
* context. This may be useful in tests. This
|
|
79
|
+
* context. This may be useful in tests. This default is false.
|
|
75
80
|
*/
|
|
76
81
|
preserveDrawingBuffer?: boolean
|
|
77
82
|
}
|