@xterm/addon-webgl 0.20.0-beta.28 → 0.20.0-beta.281

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.
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
7
+ import type { ILogService } from 'common/services/Services';
7
8
  import { customGlyphDefinitions } from './CustomGlyphDefinitions';
8
9
  import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphDefinitionPart, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from './Types';
9
10
 
@@ -22,14 +23,16 @@ export function tryDrawCustomGlyph(
22
23
  deviceCharHeight: number,
23
24
  fontSize: number,
24
25
  devicePixelRatio: number,
25
- backgroundColor?: string
26
+ logService: ILogService,
27
+ backgroundColor?: string,
28
+ variantOffset: number = 0
26
29
  ): boolean {
27
30
  const unifiedCharDefinition = customGlyphDefinitions[c];
28
31
  if (unifiedCharDefinition) {
29
32
  // Normalize to array for uniform handling
30
33
  const parts = Array.isArray(unifiedCharDefinition) ? unifiedCharDefinition : [unifiedCharDefinition];
31
34
  for (const part of parts) {
32
- drawDefinitionPart(ctx, part, xOffset, yOffset, deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, fontSize, devicePixelRatio, backgroundColor);
35
+ drawDefinitionPart(ctx, part, xOffset, yOffset, deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, fontSize, devicePixelRatio, logService, backgroundColor, variantOffset);
33
36
  }
34
37
  return true;
35
38
  }
@@ -48,7 +51,9 @@ function drawDefinitionPart(
48
51
  deviceCharHeight: number,
49
52
  fontSize: number,
50
53
  devicePixelRatio: number,
51
- backgroundColor?: string
54
+ logService: ILogService,
55
+ backgroundColor?: string,
56
+ variantOffset: number = 0
52
57
  ): void {
53
58
  // Handle scaleType - adjust dimensions and offset when scaling to character area
54
59
  let drawWidth = deviceCellWidth;
@@ -74,10 +79,10 @@ function drawDefinitionPart(
74
79
  drawBlockVectorChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
75
80
  break;
76
81
  case CustomGlyphDefinitionType.BLOCK_PATTERN:
77
- drawPatternChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
82
+ drawPatternChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, variantOffset);
78
83
  break;
79
84
  case CustomGlyphDefinitionType.PATH_FUNCTION:
80
- drawPathFunctionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth);
85
+ drawPathFunctionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, logService, part.strokeWidth);
81
86
  break;
82
87
  case CustomGlyphDefinitionType.PATH:
83
88
  drawPathDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth);
@@ -86,7 +91,7 @@ function drawDefinitionPart(
86
91
  drawPathNegativeDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, backgroundColor);
87
92
  break;
88
93
  case CustomGlyphDefinitionType.VECTOR_SHAPE:
89
- drawVectorShape(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, fontSize, devicePixelRatio);
94
+ drawVectorShape(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, fontSize, devicePixelRatio, logService);
90
95
  break;
91
96
  case CustomGlyphDefinitionType.BRAILLE:
92
97
  drawBrailleCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
@@ -216,8 +221,8 @@ function drawPathDefinitionCharacter(
216
221
  const rx = parseFloat(args[0]) * deviceCellWidth;
217
222
  const ry = parseFloat(args[1]) * deviceCellHeight;
218
223
  const xAxisRotation = parseFloat(args[2]) * Math.PI / 180;
219
- const largeArcFlag = parseInt(args[3]);
220
- const sweepFlag = parseInt(args[4]);
224
+ const largeArcFlag = parseInt(args[3], 10);
225
+ const sweepFlag = parseInt(args[4], 10);
221
226
  const x = xOffset + parseFloat(args[5]) * deviceCellWidth;
222
227
  const y = yOffset + parseFloat(args[6]) * deviceCellHeight;
223
228
  drawSvgArc(ctx, currentX, currentY, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y);
@@ -437,7 +442,8 @@ function drawPatternChar(
437
442
  xOffset: number,
438
443
  yOffset: number,
439
444
  deviceCellWidth: number,
440
- deviceCellHeight: number
445
+ deviceCellHeight: number,
446
+ variantOffset: number = 0
441
447
  ): void {
442
448
  let patternSet = cachedPatterns.get(charDefinition);
443
449
  if (!patternSet) {
@@ -486,6 +492,15 @@ function drawPatternChar(
486
492
  pattern = throwIfFalsy(ctx.createPattern(tmpCanvas, null));
487
493
  patternSet.set(fillStyle, pattern);
488
494
  }
495
+ // Apply pattern offset to ensure seamless tiling across cells when cell dimensions are odd.
496
+ // variantOffset encodes: bit 1 = x pixel shift, bit 0 = y pixel shift.
497
+ const dx = (variantOffset >> 1) & 1;
498
+ const dy = variantOffset & 1;
499
+ if (dx !== 0 || dy !== 0) {
500
+ pattern.setTransform(new DOMMatrix().translateSelf(-dx, -dy));
501
+ } else {
502
+ pattern.setTransform(new DOMMatrix());
503
+ }
489
504
  ctx.fillStyle = pattern;
490
505
  ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
491
506
  }
@@ -498,8 +513,14 @@ function drawPathFunctionCharacter(
498
513
  deviceCellWidth: number,
499
514
  deviceCellHeight: number,
500
515
  devicePixelRatio: number,
516
+ logService: ILogService,
501
517
  strokeWidth?: number
502
518
  ): void {
519
+ ctx.save();
520
+ ctx.beginPath();
521
+ ctx.rect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
522
+ ctx.clip();
523
+
503
524
  ctx.beginPath();
504
525
  let actualInstructions: string;
505
526
  if (typeof charDefinition === 'function') {
@@ -519,14 +540,14 @@ function drawPathFunctionCharacter(
519
540
  }
520
541
  const f = svgToCanvasInstructionMap[type];
521
542
  if (!f) {
522
- console.error(`Could not find drawing instructions for "${type}"`);
543
+ logService.error(`Could not find drawing instructions for "${type}"`);
523
544
  continue;
524
545
  }
525
546
  const args: string[] = instruction.substring(1).split(',');
526
547
  if (!args[0] || !args[1]) {
527
548
  continue;
528
549
  }
529
- f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio), state);
550
+ f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio, 0, 0, false), state);
530
551
  state.lastCommand = type;
531
552
  }
532
553
  if (strokeWidth !== undefined) {
@@ -537,6 +558,7 @@ function drawPathFunctionCharacter(
537
558
  ctx.fill();
538
559
  }
539
560
  ctx.closePath();
561
+ ctx.restore();
540
562
  }
541
563
 
542
564
  /**
@@ -580,7 +602,8 @@ function drawVectorShape(
580
602
  deviceCellWidth: number,
581
603
  deviceCellHeight: number,
582
604
  fontSize: number,
583
- devicePixelRatio: number
605
+ devicePixelRatio: number,
606
+ logService: ILogService
584
607
  ): void {
585
608
  // Clip the cell to make sure drawing doesn't occur beyond bounds
586
609
  const clipRegion = new Path2D();
@@ -601,7 +624,7 @@ function drawVectorShape(
601
624
  }
602
625
  const f = svgToCanvasInstructionMap[type];
603
626
  if (!f) {
604
- console.error(`Could not find drawing instructions for "${type}"`);
627
+ logService.error(`Could not find drawing instructions for "${type}"`);
605
628
  continue;
606
629
  }
607
630
  const args: string[] = instruction.substring(1).split(',');
@@ -685,7 +708,7 @@ const svgToCanvasInstructionMap: { [index: string]: (ctx: CanvasRenderingContext
685
708
  }
686
709
  };
687
710
 
688
- function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number, doClamp: boolean, devicePixelRatio: number, leftPadding: number = 0, rightPadding: number = 0): number[] {
711
+ 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[] {
689
712
  const result = args.map(e => parseFloat(e) || parseInt(e));
690
713
 
691
714
  if (result.length < 2) {
@@ -695,10 +718,11 @@ function translateArgs(args: string[], cellWidth: number, cellHeight: number, xO
695
718
  for (let x = 0; x < result.length; x += 2) {
696
719
  // Translate from 0-1 to 0-cellWidth
697
720
  result[x] *= cellWidth - (leftPadding * devicePixelRatio) - (rightPadding * devicePixelRatio);
698
- // Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
699
- // line at 100% devicePixelRatio
721
+ // Round to the nearest 0.5 to ensure a crisp line at 100% devicePixelRatio, and optionally
722
+ // clamp to the cell bounds.
700
723
  if (doClamp && result[x] !== 0) {
701
- result[x] = clamp(Math.round(result[x] + 0.5) - 0.5, cellWidth, 0);
724
+ const rounded = Math.round(result[x] + 0.5) - 0.5;
725
+ result[x] = clampToCell ? clamp(rounded, cellWidth, 0) : rounded;
702
726
  }
703
727
  // Apply the cell's offset (ie. x*cellWidth)
704
728
  result[x] += xOffset + (leftPadding * devicePixelRatio);
@@ -707,10 +731,11 @@ function translateArgs(args: string[], cellWidth: number, cellHeight: number, xO
707
731
  for (let y = 1; y < result.length; y += 2) {
708
732
  // Translate from 0-1 to 0-cellHeight
709
733
  result[y] *= cellHeight;
710
- // Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
711
- // line at 100% devicePixelRatio
734
+ // Round to the nearest 0.5 to ensure a crisp line at 100% devicePixelRatio, and optionally
735
+ // clamp to the cell bounds.
712
736
  if (doClamp && result[y] !== 0) {
713
- result[y] = clamp(Math.round(result[y] + 0.5) - 0.5, cellHeight, 0);
737
+ const rounded = Math.round(result[y] + 0.5) - 0.5;
738
+ result[y] = clampToCell ? clamp(rounded, cellHeight, 0) : rounded;
714
739
  }
715
740
  // Apply the cell's offset (ie. x*cellHeight)
716
741
  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 'vs/base/common/lifecycle';
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';
@@ -23,12 +23,12 @@ declare module '@xterm/addon-webgl' {
23
23
  public readonly onChangeTextureAtlas: IEvent<HTMLCanvasElement>;
24
24
 
25
25
  /**
26
- * An event that is fired when the a new page is added to the texture atlas.
26
+ * An event that is fired when a new page is added to the texture atlas.
27
27
  */
28
28
  public readonly onAddTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
29
29
 
30
30
  /**
31
- * An event that is fired when the a page is removed from the texture atlas.
31
+ * An event that is fired when a page is removed from the texture atlas.
32
32
  */
33
33
  public readonly onRemoveTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
34
34
 
@@ -61,6 +61,9 @@ declare module '@xterm/addon-webgl' {
61
61
  * - Braille Patterns (U+2800-U+28FF)
62
62
  * - Powerline Symbols (U+E0A0-U+E0D4, Private Use Area with widespread
63
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)).
64
67
  * - Git Branch Symbols (U+F5D0-U+F60D, Private Use Area initially adopted
65
68
  * in [Kitty in 2024](https://github.com/kovidgoyal/kitty/pull/7681) by
66
69
  * author of [vim-flog](https://github.com/rbong/vim-flog))