Skip to content

Commit dc4ebfd

Browse files
committed
Use offset variants for some custom glyphs
Part of #5668
1 parent 8f9045e commit dc4ebfd

4 files changed

Lines changed: 26 additions & 8 deletions

File tree

addons/addon-webgl/src/CellColorResolver.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class CellColorResolver {
4242
* Resolves colors for the cell, putting the result into the shared {@link result}. This resolves
4343
* overrides, inverse and selection for the cell which can then be used to feed into the renderer.
4444
*/
45-
public resolve(cell: ICellData, x: number, y: number, deviceCellWidth: number): void {
45+
public resolve(cell: ICellData, x: number, y: number, deviceCellWidth: number, deviceCellHeight: number): void {
4646
this.result.bg = cell.bg;
4747
this.result.fg = cell.fg;
4848
this.result.ext = cell.bg & BgFlags.HAS_EXTENDED ? cell.extended.ext : 0;
@@ -63,6 +63,11 @@ export class CellColorResolver {
6363
const lineWidth = Math.max(1, Math.floor(this._optionService.rawOptions.fontSize * this._coreBrowserService.dpr / 15));
6464
$variantOffset = x * deviceCellWidth % (Math.round(lineWidth) * 2);
6565
}
66+
if ($variantOffset === 0) {
67+
if ((code >= 0x2591 && code <= 0x2593) || (code >= 0x1FB8C && code <= 0x1FB94)) {
68+
$variantOffset = ((x * deviceCellWidth) % 2) * 2 + ((y * deviceCellHeight) % 2);
69+
}
70+
}
6671

6772
// Apply decorations on the bottom layer
6873
this._decorationService.forEachDecorationAtCell(x, y, 'bottom', d => {

addons/addon-webgl/src/TextureAtlas.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ export class TextureAtlas implements ITextureAtlas {
525525
// Draw custom characters if applicable
526526
let customGlyph = false;
527527
if (this._config.customGlyphs !== false) {
528-
customGlyph = tryDrawCustomGlyph(this._tmpCtx, chars, padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight, this._config.deviceCharWidth, this._config.deviceCharHeight, this._config.fontSize, this._config.devicePixelRatio, backgroundColor.css);
528+
const variantOffset = this._workAttributeData.getUnderlineVariantOffset();
529+
customGlyph = tryDrawCustomGlyph(this._tmpCtx, chars, padding, padding, this._config.deviceCellWidth, this._config.deviceCellHeight, this._config.deviceCharWidth, this._config.deviceCharHeight, this._config.fontSize, this._config.devicePixelRatio, backgroundColor.css, variantOffset);
529530
}
530531

531532
// Whether to clear pixels based on a threshold difference between the glyph color and the

addons/addon-webgl/src/WebglRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
478478
i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
479479

480480
// Load colors/resolve overrides into work colors
481-
this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width);
481+
this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width, this.dimensions.device.cell.height);
482482

483483
// Override colors for cursor cell
484484
if (isCursorVisible && row === cursorY) {

addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ export function tryDrawCustomGlyph(
2222
deviceCharHeight: number,
2323
fontSize: number,
2424
devicePixelRatio: number,
25-
backgroundColor?: string
25+
backgroundColor?: string,
26+
variantOffset: number = 0
2627
): boolean {
2728
const unifiedCharDefinition = customGlyphDefinitions[c];
2829
if (unifiedCharDefinition) {
2930
// Normalize to array for uniform handling
3031
const parts = Array.isArray(unifiedCharDefinition) ? unifiedCharDefinition : [unifiedCharDefinition];
3132
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);
3334
}
3435
return true;
3536
}
@@ -48,7 +49,8 @@ function drawDefinitionPart(
4849
deviceCharHeight: number,
4950
fontSize: number,
5051
devicePixelRatio: number,
51-
backgroundColor?: string
52+
backgroundColor?: string,
53+
variantOffset: number = 0
5254
): void {
5355
// Handle scaleType - adjust dimensions and offset when scaling to character area
5456
let drawWidth = deviceCellWidth;
@@ -74,7 +76,7 @@ function drawDefinitionPart(
7476
drawBlockVectorChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
7577
break;
7678
case CustomGlyphDefinitionType.BLOCK_PATTERN:
77-
drawPatternChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight);
79+
drawPatternChar(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, variantOffset);
7880
break;
7981
case CustomGlyphDefinitionType.PATH_FUNCTION:
8082
drawPathFunctionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth);
@@ -437,7 +439,8 @@ function drawPatternChar(
437439
xOffset: number,
438440
yOffset: number,
439441
deviceCellWidth: number,
440-
deviceCellHeight: number
442+
deviceCellHeight: number,
443+
variantOffset: number = 0
441444
): void {
442445
let patternSet = cachedPatterns.get(charDefinition);
443446
if (!patternSet) {
@@ -486,6 +489,15 @@ function drawPatternChar(
486489
pattern = throwIfFalsy(ctx.createPattern(tmpCanvas, null));
487490
patternSet.set(fillStyle, pattern);
488491
}
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+
}
489501
ctx.fillStyle = pattern;
490502
ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
491503
}

0 commit comments

Comments
 (0)