From 4a8d8bd247e46c2b91c910fc819dd568c6cd0270 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:32:03 -0800 Subject: [PATCH 1/8] Partially implement git branch symbols Part of #5477 --- .../customGlyphs/CustomGlyphDefinitions.ts | 196 ++++++++++++++++++ .../src/customGlyphs/CustomGlyphRasterizer.ts | 14 +- addons/addon-webgl/typings/addon-webgl.d.ts | 6 +- demo/client.ts | 6 + 4 files changed, 218 insertions(+), 4 deletions(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 465b675a..366fb6ae 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -299,6 +299,202 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi // #endregion + // #region Git Branch Symbols (F5D0-F5FB) + + // Initially added in https://github.com/kovidgoyal/kitty/pull/7681 then in + // [Wezterm](https://github.com/wezterm/wezterm/issues/6328). + + // TODO: These should be composed of common shapes instead of repeating the path data. + + // Line without branches + '\u{F5D0}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, // HORIZONTAL LINE (Same as 2500) + '\u{F5D1}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, // VERTICAL LINE (Same as 2502) + '\u{F5D2}': { 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 }, // HORIZONTAL LINE FADE TO RIGHT + '\u{F5D3}': { 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 }, // HORIZONTAL LINE FADE TO LEFT + '\u{F5D4}': { 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 }, // VERTICAL LINE FADE TO BOTTOM + '\u{F5D5}': { 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 }, // VERTICAL LINE FADE TO TOP + '\u{F5D6}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE BOTTOM TO RIGHT (Same as 256D) + '\u{F5D7}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE BOTTOM TO LEFT (Same as 256E) + '\u{F5D8}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO LEFT (Same as 256F) + '\u{F5D9}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO RIGHT (Same as 2570) + + // Vertical and branching to the right + '\u{F5DA}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5DB}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5DC}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + + // Vertical and branching to the left + '\u{F5DD}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5DE}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5DF}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + + // Horizontal and branching down + '\u{F5E0}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5E1}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5E2}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + + // Horizontal and branching up + '\u{F5E3}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5E4}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5E5}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + + // Branching in all four directions + '\u{F5E6}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5E7}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5E8}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5E9}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5EA}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5EB}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + '\u{F5EC}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + ], + '\u{F5ED}': [ + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, + ], + + // Node (circle filling ~70% of cell, assumes 2:1 height:width aspect ratio) + '\u{F5EE}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, // Stroke as well to ensure it's the same outline as empty circle + ], + '\u{F5EF}': { 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 }, + + // Node branching to right + '\u{F5F0}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, + ], + '\u{F5F1}': [ + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, + ], + + // Node branching to left + '\u{F5F2}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, + ], + '\u{F5F3}': [ + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, + ], + + // Node branching horizontally + '\u{F5F4}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, + ], + '\u{F5F5}': [ + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, + ], + + // Node branching down + '\u{F5F6}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, + ], + '\u{F5F7}': [ + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, + ], + + // Node branching up + '\u{F5F8}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, + ], + '\u{F5F9}': [ + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, + ], + + // Node branching vertically + '\u{F5FA}': [ + { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, + ], + '\u{F5FB}': [ + { 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 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, + { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, + ], + + // #endregion + // #region Symbols for Legacy Computing (1FB00-1FB3B) // https://www.unicode.org/charts/PDF/U1FB00.pdf diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts index df4e106b..6302757f 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts @@ -80,7 +80,7 @@ function drawDefinitionPart( drawPathFunctionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth); break; case CustomGlyphDefinitionType.PATH: - drawPathDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight); + drawPathDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, part.strokeWidth); break; case CustomGlyphDefinitionType.PATH_NEGATIVE: drawPathNegativeDefinitionCharacter(ctx, part.data, drawXOffset, drawYOffset, drawWidth, drawHeight, devicePixelRatio, backgroundColor); @@ -171,7 +171,9 @@ function drawPathDefinitionCharacter( xOffset: number, yOffset: number, deviceCellWidth: number, - deviceCellHeight: number + deviceCellHeight: number, + devicePixelRatio: number, + strokeWidth?: number ): void { const instructions = typeof charDefinition === 'string' ? charDefinition : charDefinition(0, 0); ctx.beginPath(); @@ -272,7 +274,13 @@ function drawPathDefinitionCharacter( } lastCommand = type; } - ctx.fill(); + if (strokeWidth !== undefined) { + ctx.strokeStyle = ctx.fillStyle; + ctx.lineWidth = devicePixelRatio * strokeWidth; + ctx.stroke(); + } else { + ctx.fill(); + } } /** diff --git a/addons/addon-webgl/typings/addon-webgl.d.ts b/addons/addon-webgl/typings/addon-webgl.d.ts index 1f09776f..eff6e424 100644 --- a/addons/addon-webgl/typings/addon-webgl.d.ts +++ b/addons/addon-webgl/typings/addon-webgl.d.ts @@ -59,7 +59,11 @@ declare module '@xterm/addon-webgl' { * - Box Drawing (U+2500-U+257F) * - Box Elements (U+2580-U+259F) * - Braille Patterns (U+2800-U+28FF) - * - Powerline Symbols (U+E0A0–U+E0D4) + * - Powerline Symbols (U+E0A0–U+E0D4, Private Use Area with widespread + * adoption) + * - Git Branch Symbols (U+F5D0-U+F5FB, Private Use Area initially adopted + * in [Kitty in 2024](https://github.com/kovidgoyal/kitty/pull/7681) by + * author of [vim-flog](https://github.com/rbong/vim-flog)) * - Symbols for Legacy Computing (U+1FB00–U+1FBFF) * * This will typically result in better rendering with continuous lines, diff --git a/demo/client.ts b/demo/client.ts index 644d82f1..68d9dbd1 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -955,6 +955,12 @@ function customGlyphRangesHandler(): void { ['Powerline Symbols', 0xE0A0, 0xE0B3, [0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF]], ['Powerline Extra Symbols', 0xE0B4, 0xE0D4, [0xE0C9, 0xE0CB, 0xE0D3]], ]); + // Git Branch Symbols + // F5D0-F5FB + // https://github.com/xtermjs/xterm.js/issues/5477 + writeUnicodeTable(term, 'Git Branch Symbols', 0xF5D0, 0xF5FB, [ + ['Git Branch Symbols', 0xF5D0, 0xF5FB], + ]); // Symbols for Legacy Computing // Range: 1FB00–1FBFF // https://www.unicode.org/charts/PDF/U1FB00.pdf From e87e0f54438e4d46ca6a9fdaa4f4d1d82f2ec2f9 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 15:27:30 -0800 Subject: [PATCH 2/8] Add git branch symbol alignment tests --- demo/client.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index 68d9dbd1..f22f7cc2 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -830,16 +830,6 @@ function customGlyphAlignmentHandler(): void { term.write('╰─╯ ╱ ╲ ╹╵╎╏┆┇┊┋\n\r'); term.write('\n\r'); - term.write('All box drawing characters:\n\r'); - term.write('─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏\n\r'); - term.write('┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟\n\r'); - term.write('┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯\n\r'); - term.write('┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿\n\r'); - term.write('╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏\n\r'); - term.write('═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟\n\r'); - term.write('╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯\n\r'); - term.write('╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿\n\r'); - term.write('Box drawing alignment tests:\x1b[31m █\n\r'); term.write(' ▉\n\r'); term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r'); @@ -911,6 +901,16 @@ function customGlyphAlignmentHandler(): void { for (const char of powerlineRightChars) { term.write(`\x1b[41m \x1b[0;31m${char}\x1b[0m `); } + term.write('\n\r'); + + term.write('\x1b[0mGit Branch Symbols alignment tests:\n\r'); + term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7}\n\r'); + term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1}\n\r'); + term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D9}\u{F5D0}\u{F5D8}\n\r'); + term.write(' \u{F5DC}\u{F5DF} \u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\n\r'); + term.write('\u{F5F1}\u{F5E6}\u{F5E7}\u{F5F3} \u{F5D3}\u{F5D0}\u{F5E0}\u{F5E1}\u{F5E2}\u{F5E3}\u{F5E4}\u{F5E5}\u{F5E8}\u{F5E9}\u{F5EC}\u{F5ED}\u{F5D2}\n\r'); + term.write('\u{F5F1}\u{F5EA}\u{F5EB}\u{F5F3} \u{F5F9}\u{F5F9}\u{F5F9} \u{F5F9}\u{F5F9}\u{F5F9}\u{F5F9}\n\r'); + term.write(' \u{F5F9}\u{F5F9} \n\r'); term.write('\x1b[0m'); term.write('\n\r'); From ce1ab6fdc4eeb2bbd26d58a1e4399e0f859f04f8 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 15:31:49 -0800 Subject: [PATCH 3/8] Correct order or curved glyphs --- addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts | 4 ++-- demo/client.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 366fb6ae..dd5a4cd5 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -315,8 +315,8 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi '\u{F5D5}': { 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 }, // VERTICAL LINE FADE TO TOP '\u{F5D6}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE BOTTOM TO RIGHT (Same as 256D) '\u{F5D7}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE BOTTOM TO LEFT (Same as 256E) - '\u{F5D8}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO LEFT (Same as 256F) - '\u{F5D9}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO RIGHT (Same as 2570) + '\u{F5D8}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO RIGHT (Same as 2570) + '\u{F5D9}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO LEFT (Same as 256F) // Vertical and branching to the right '\u{F5DA}': [ diff --git a/demo/client.ts b/demo/client.ts index f22f7cc2..a12bbfc3 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -903,7 +903,7 @@ function customGlyphAlignmentHandler(): void { } term.write('\n\r'); - term.write('\x1b[0mGit Branch Symbols alignment tests:\n\r'); + term.write('\x1b[0mGit Branch Symbols alignment tests:\x1b[32m\n\r'); term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7}\n\r'); term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1}\n\r'); term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D9}\u{F5D0}\u{F5D8}\n\r'); From 98f4c3128c3b410851f6175165622f64be22bad3 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 15:35:46 -0800 Subject: [PATCH 4/8] Stub second batch of glyphs --- .../customGlyphs/CustomGlyphDefinitions.ts | 20 +++++++++++++++++++ demo/client.ts | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index dd5a4cd5..8be6eee8 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -493,6 +493,26 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, ], + // TODO: Implement rest + // NODE FILLED BRANCHING DOWN RIGHT + // NODE EMPTY BRANCHING DOWN RIGHT + // NODE FILLED BRANCHING DOWN LEFT + // NODE EMPTY BRANCHING DOWN LEFT + // NODE FILLED BRANCHING UP RIGHT + // NODE EMPTY BRANCHING UP RIGHT + // NODE FILLED BRANCHING UP LEFT + // NODE EMPTY BRANCHING UP LEFT + // NODE FILLED BRANCHING UP DOWN RIGHT + // NODE EMPTY BRANCHING UP DOWN RIGHT + // NODE FILLED BRANCHING UP DOWN LEFT + // NODE EMPTY BRANCHING UP DOWN LEFT + // NODE FILLED BRANCHING DOWN LEFT RIGHT + // NODE EMPTY BRANCHING DOWN LEFT RIGHT + // NODE FILLED BRANCHING UP LEFT RIGHT + // NODE EMPTY BRANCHING UP LEFT RIGHT + // NODE FILLED BRANCHING UP DOWN LEFT RIGHT + // NODE EMPTY BRANCHING UP DOWN LEFT RIGHT + // #endregion // #region Symbols for Legacy Computing (1FB00-1FB3B) diff --git a/demo/client.ts b/demo/client.ts index a12bbfc3..2da5f368 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -906,7 +906,7 @@ function customGlyphAlignmentHandler(): void { term.write('\x1b[0mGit Branch Symbols alignment tests:\x1b[32m\n\r'); term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7}\n\r'); term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1}\n\r'); - term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D9}\u{F5D0}\u{F5D8}\n\r'); + term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D8}\u{F5D0}\u{F5D9}\n\r'); term.write(' \u{F5DC}\u{F5DF} \u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\n\r'); term.write('\u{F5F1}\u{F5E6}\u{F5E7}\u{F5F3} \u{F5D3}\u{F5D0}\u{F5E0}\u{F5E1}\u{F5E2}\u{F5E3}\u{F5E4}\u{F5E5}\u{F5E8}\u{F5E9}\u{F5EC}\u{F5ED}\u{F5D2}\n\r'); term.write('\u{F5F1}\u{F5EA}\u{F5EB}\u{F5F3} \u{F5F9}\u{F5F9}\u{F5F9} \u{F5F9}\u{F5F9}\u{F5F9}\u{F5F9}\n\r'); From 96aa97ce11821e530312bd597c84e01c30617f18 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 15:51:00 -0800 Subject: [PATCH 5/8] Add extended symbols --- .../customGlyphs/CustomGlyphDefinitions.ts | 289 +++++++----------- demo/client.ts | 1 + 2 files changed, 109 insertions(+), 181 deletions(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 8be6eee8..f5f65972 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -3,10 +3,38 @@ * @license MIT */ -import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphPathDrawFunctionDefinition } from './Types'; +import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphDefinitionPart, type CustomGlyphPathDrawFunctionDefinition } from './Types'; /* eslint-disable max-len */ +/** + * Frozen {@link CustomGlyphDefinitionPart} objects for reuse across glyph definitions. + */ +namespace Parts { + // Lines + export const LINE_H: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }); + export const LINE_V: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }); + + // Fading lines + 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 }); + 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 }); + 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 }); + 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 }); + + // Curved corners + 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 }); + 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 }); + 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 }); + 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 }); + + // Node parts + 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' }); + 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 }); + export const NODE_LINE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }); + export const NODE_LINE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }); + export const NODE_LINE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }); + export const NODE_LINE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }); +} export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } = { // #region Box Drawing (2500-257F) @@ -307,211 +335,110 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi // TODO: These should be composed of common shapes instead of repeating the path data. // Line without branches - '\u{F5D0}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, // HORIZONTAL LINE (Same as 2500) - '\u{F5D1}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, // VERTICAL LINE (Same as 2502) - '\u{F5D2}': { 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 }, // HORIZONTAL LINE FADE TO RIGHT - '\u{F5D3}': { 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 }, // HORIZONTAL LINE FADE TO LEFT - '\u{F5D4}': { 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 }, // VERTICAL LINE FADE TO BOTTOM - '\u{F5D5}': { 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 }, // VERTICAL LINE FADE TO TOP - '\u{F5D6}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE BOTTOM TO RIGHT (Same as 256D) - '\u{F5D7}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE BOTTOM TO LEFT (Same as 256E) - '\u{F5D8}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO RIGHT (Same as 2570) - '\u{F5D9}': { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, // CURVED LINE TOP TO LEFT (Same as 256F) + '\u{F5D0}': Parts.LINE_H, // HORIZONTAL LINE (Same as 2500) + '\u{F5D1}': Parts.LINE_V, // VERTICAL LINE (Same as 2502) + '\u{F5D2}': Parts.FADE_RIGHT, // HORIZONTAL LINE FADE TO RIGHT + '\u{F5D3}': Parts.FADE_LEFT, // HORIZONTAL LINE FADE TO LEFT + '\u{F5D4}': Parts.FADE_DOWN, // VERTICAL LINE FADE TO BOTTOM + '\u{F5D5}': Parts.FADE_UP, // VERTICAL LINE FADE TO TOP + '\u{F5D6}': Parts.CURVE_DOWN_RIGHT, // CURVED LINE BOTTOM TO RIGHT (Same as 256D) + '\u{F5D7}': Parts.CURVE_DOWN_LEFT, // CURVED LINE BOTTOM TO LEFT (Same as 256E) + '\u{F5D8}': Parts.CURVE_UP_RIGHT, // CURVED LINE TOP TO RIGHT (Same as 2570) + '\u{F5D9}': Parts.CURVE_UP_LEFT, // CURVED LINE TOP TO LEFT (Same as 256F) // Vertical and branching to the right - '\u{F5DA}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5DB}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5DC}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], + '\u{F5DA}': [Parts.LINE_V, Parts.CURVE_UP_RIGHT], + '\u{F5DB}': [Parts.LINE_V, Parts.CURVE_DOWN_RIGHT], + '\u{F5DC}': [Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_RIGHT], // Vertical and branching to the left - '\u{F5DD}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5DE}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5DF}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], + '\u{F5DD}': [Parts.LINE_V, Parts.CURVE_UP_LEFT], + '\u{F5DE}': [Parts.LINE_V, Parts.CURVE_DOWN_LEFT], + '\u{F5DF}': [Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_LEFT], // Horizontal and branching down - '\u{F5E0}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5E1}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5E2}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], + '\u{F5E0}': [Parts.LINE_H, Parts.CURVE_DOWN_LEFT], + '\u{F5E1}': [Parts.LINE_H, Parts.CURVE_DOWN_RIGHT], + '\u{F5E2}': [Parts.CURVE_DOWN_LEFT, Parts.CURVE_DOWN_RIGHT], // Horizontal and branching up - '\u{F5E3}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5E4}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5E5}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], + '\u{F5E3}': [Parts.LINE_H, Parts.CURVE_UP_LEFT], + '\u{F5E4}': [Parts.LINE_H, Parts.CURVE_UP_RIGHT], + '\u{F5E5}': [Parts.CURVE_UP_LEFT, Parts.CURVE_UP_RIGHT], // Branching in all four directions - '\u{F5E6}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5E7}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5E8}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5E9}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5EA}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5EB}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], - '\u{F5EC}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - ], - '\u{F5ED}': [ - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5`, strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5`, strokeWidth: 1 }, - ], + '\u{F5E6}': [Parts.LINE_V, Parts.CURVE_UP_LEFT, Parts.CURVE_UP_RIGHT], + '\u{F5E7}': [Parts.LINE_V, Parts.CURVE_DOWN_LEFT, Parts.CURVE_DOWN_RIGHT], + '\u{F5E8}': [Parts.LINE_H, Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_LEFT], + '\u{F5E9}': [Parts.LINE_H, Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_RIGHT], + '\u{F5EA}': [Parts.LINE_V, Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_LEFT], + '\u{F5EB}': [Parts.LINE_V, Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_RIGHT], + '\u{F5EC}': [Parts.LINE_H, Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_LEFT], + '\u{F5ED}': [Parts.LINE_H, Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_RIGHT], // Node (circle filling ~70% of cell, assumes 2:1 height:width aspect ratio) - '\u{F5EE}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, // Stroke as well to ensure it's the same outline as empty circle - ], - '\u{F5EF}': { 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 }, + '\u{F5EE}': [Parts.NODE_FILL, Parts.NODE_STROKE], + '\u{F5EF}': Parts.NODE_STROKE, // Node branching to right - '\u{F5F0}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, - ], - '\u{F5F1}': [ - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, - ], + '\u{F5F0}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_RIGHT], + '\u{F5F1}': [Parts.NODE_STROKE, Parts.NODE_LINE_RIGHT], // Node branching to left - '\u{F5F2}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, - ], - '\u{F5F3}': [ - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, - ], + '\u{F5F2}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_LEFT], + '\u{F5F3}': [Parts.NODE_STROKE, Parts.NODE_LINE_LEFT], // Node branching horizontally - '\u{F5F4}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, - ], - '\u{F5F5}': [ - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }, - ], + '\u{F5F4}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], + '\u{F5F5}': [Parts.NODE_STROKE, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // Node branching down - '\u{F5F6}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, - ], - '\u{F5F7}': [ - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, - ], + '\u{F5F6}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN], + '\u{F5F7}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN], // Node branching up - '\u{F5F8}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, - ], - '\u{F5F9}': [ - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, - ], + '\u{F5F8}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP], + '\u{F5F9}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP], // Node branching vertically - '\u{F5FA}': [ - { type: CustomGlyphDefinitionType.PATH, data: 'M.85,.5 A.35,.175,0,1,1,.15,.5 A.35,.175,0,1,1,.85,.5' }, - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, - ], - '\u{F5FB}': [ - { 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 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }, - { type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }, - ], + '\u{F5FA}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_UP], + '\u{F5FB}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_UP], - // TODO: Implement rest - // NODE FILLED BRANCHING DOWN RIGHT - // NODE EMPTY BRANCHING DOWN RIGHT - // NODE FILLED BRANCHING DOWN LEFT - // NODE EMPTY BRANCHING DOWN LEFT - // NODE FILLED BRANCHING UP RIGHT - // NODE EMPTY BRANCHING UP RIGHT - // NODE FILLED BRANCHING UP LEFT - // NODE EMPTY BRANCHING UP LEFT - // NODE FILLED BRANCHING UP DOWN RIGHT - // NODE EMPTY BRANCHING UP DOWN RIGHT - // NODE FILLED BRANCHING UP DOWN LEFT - // NODE EMPTY BRANCHING UP DOWN LEFT - // NODE FILLED BRANCHING DOWN LEFT RIGHT - // NODE EMPTY BRANCHING DOWN LEFT RIGHT - // NODE FILLED BRANCHING UP LEFT RIGHT - // NODE EMPTY BRANCHING UP LEFT RIGHT - // NODE FILLED BRANCHING UP DOWN LEFT RIGHT - // NODE EMPTY BRANCHING UP DOWN LEFT RIGHT + // Node branching down right + '\u{F5FC}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING DOWN RIGHT + '\u{F5FD}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING DOWN RIGHT + + // Node branching down left + '\u{F5FE}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE FILLED BRANCHING DOWN LEFT + '\u{F5FF}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE EMPTY BRANCHING DOWN LEFT + + // Node branching up right + '\u{F600}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP RIGHT + '\u{F601}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP RIGHT + + // Node branching up left + '\u{F602}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT], // NODE FILLED BRANCHING UP LEFT + '\u{F603}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT], // NODE EMPTY BRANCHING UP LEFT + + // Node branching up down right + '\u{F604}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP DOWN RIGHT + '\u{F605}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP DOWN RIGHT + + // Node branching up down left + '\u{F606}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE FILLED BRANCHING UP DOWN LEFT + '\u{F607}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE EMPTY BRANCHING UP DOWN LEFT + + // Node branching down left right + '\u{F608}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING DOWN LEFT RIGHT + '\u{F609}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING DOWN LEFT RIGHT + + // Node branching up left right + '\u{F60A}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP LEFT RIGHT + '\u{F60B}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP LEFT RIGHT + + // Node branching up down left right + '\u{F60C}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP DOWN LEFT RIGHT + '\u{F60D}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP DOWN LEFT RIGHT // #endregion diff --git a/demo/client.ts b/demo/client.ts index 2da5f368..0abe340a 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -960,6 +960,7 @@ function customGlyphRangesHandler(): void { // https://github.com/xtermjs/xterm.js/issues/5477 writeUnicodeTable(term, 'Git Branch Symbols', 0xF5D0, 0xF5FB, [ ['Git Branch Symbols', 0xF5D0, 0xF5FB], + ['Extended Git Branch Symbols', 0xF5FC, 0xF60D], ]); // Symbols for Legacy Computing // Range: 1FB00–1FBFF From 2be529ce852a7f98b046f464c4a800d5b1876ae2 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:05:42 -0800 Subject: [PATCH 6/8] Polish definitions --- .../customGlyphs/CustomGlyphDefinitions.ts | 227 ++++++++---------- addons/addon-webgl/typings/addon-webgl.d.ts | 2 +- demo/client.ts | 13 +- 3 files changed, 103 insertions(+), 139 deletions(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index f5f65972..68e5f274 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -7,35 +7,6 @@ import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, /* eslint-disable max-len */ -/** - * Frozen {@link CustomGlyphDefinitionPart} objects for reuse across glyph definitions. - */ -namespace Parts { - // Lines - export const LINE_H: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }); - export const LINE_V: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }); - - // Fading lines - 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 }); - 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 }); - 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 }); - 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 }); - - // Curved corners - 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 }); - 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 }); - 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 }); - 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 }); - - // Node parts - 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' }); - 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 }); - export const NODE_LINE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }); - export const NODE_LINE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }); - export const NODE_LINE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }); - export const NODE_LINE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }); -} - export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } = { // #region Box Drawing (2500-257F) @@ -327,118 +298,82 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi // #endregion - // #region Git Branch Symbols (F5D0-F5FB) + // #region Git Branch Symbols (F5D0-F60D) // Initially added in https://github.com/kovidgoyal/kitty/pull/7681 then in // [Wezterm](https://github.com/wezterm/wezterm/issues/6328). - // TODO: These should be composed of common shapes instead of repeating the path data. + // Straight lines (F5D0-F5D9) + '\u{F5D0}': GitBranchSymbolsParts.LINE_H, // Same as 2500 + '\u{F5D1}': GitBranchSymbolsParts.LINE_V, // Same as 2502 + '\u{F5D2}': GitBranchSymbolsParts.FADE_RIGHT, + '\u{F5D3}': GitBranchSymbolsParts.FADE_LEFT, + '\u{F5D4}': GitBranchSymbolsParts.FADE_DOWN, + '\u{F5D5}': GitBranchSymbolsParts.FADE_UP, - // Line without branches - '\u{F5D0}': Parts.LINE_H, // HORIZONTAL LINE (Same as 2500) - '\u{F5D1}': Parts.LINE_V, // VERTICAL LINE (Same as 2502) - '\u{F5D2}': Parts.FADE_RIGHT, // HORIZONTAL LINE FADE TO RIGHT - '\u{F5D3}': Parts.FADE_LEFT, // HORIZONTAL LINE FADE TO LEFT - '\u{F5D4}': Parts.FADE_DOWN, // VERTICAL LINE FADE TO BOTTOM - '\u{F5D5}': Parts.FADE_UP, // VERTICAL LINE FADE TO TOP - '\u{F5D6}': Parts.CURVE_DOWN_RIGHT, // CURVED LINE BOTTOM TO RIGHT (Same as 256D) - '\u{F5D7}': Parts.CURVE_DOWN_LEFT, // CURVED LINE BOTTOM TO LEFT (Same as 256E) - '\u{F5D8}': Parts.CURVE_UP_RIGHT, // CURVED LINE TOP TO RIGHT (Same as 2570) - '\u{F5D9}': Parts.CURVE_UP_LEFT, // CURVED LINE TOP TO LEFT (Same as 256F) + // Curved lines (F5D6-F5D9) + '\u{F5D6}': GitBranchSymbolsParts.CURVE_DOWN_RIGHT, // Same as 256D) + '\u{F5D7}': GitBranchSymbolsParts.CURVE_DOWN_LEFT, // Same as 256E) + '\u{F5D8}': GitBranchSymbolsParts.CURVE_UP_RIGHT, // Same as 2570) + '\u{F5D9}': GitBranchSymbolsParts.CURVE_UP_LEFT, // Same as 256F) - // Vertical and branching to the right - '\u{F5DA}': [Parts.LINE_V, Parts.CURVE_UP_RIGHT], - '\u{F5DB}': [Parts.LINE_V, Parts.CURVE_DOWN_RIGHT], - '\u{F5DC}': [Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_RIGHT], + // Branching lines (F5DA-F5ED) + '\u{F5DA}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5DB}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_RIGHT], + '\u{F5DC}': [GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5DD}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_UP_LEFT], + '\u{F5DE}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_LEFT], + '\u{F5DF}': [GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_LEFT], + '\u{F5E0}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_LEFT], + '\u{F5E1}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_RIGHT], + '\u{F5E2}': [GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_DOWN_RIGHT], + '\u{F5E3}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_UP_LEFT], + '\u{F5E4}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5E5}': [GitBranchSymbolsParts.CURVE_UP_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5E6}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_UP_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5E7}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_DOWN_RIGHT], + '\u{F5E8}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_LEFT], + '\u{F5E9}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5EA}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_LEFT], + '\u{F5EB}': [GitBranchSymbolsParts.LINE_V, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT], + '\u{F5EC}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_RIGHT, GitBranchSymbolsParts.CURVE_UP_LEFT], + '\u{F5ED}': [GitBranchSymbolsParts.LINE_H, GitBranchSymbolsParts.CURVE_DOWN_LEFT, GitBranchSymbolsParts.CURVE_UP_RIGHT], - // Vertical and branching to the left - '\u{F5DD}': [Parts.LINE_V, Parts.CURVE_UP_LEFT], - '\u{F5DE}': [Parts.LINE_V, Parts.CURVE_DOWN_LEFT], - '\u{F5DF}': [Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_LEFT], + // Nodes (F5EE-F5FB) + '\u{F5EE}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE], + '\u{F5EF}': GitBranchSymbolsParts.NODE_STROKE, + '\u{F5F0}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F5F1}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F5F2}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F5F3}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F5F4}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F5F5}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F5F6}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN], + '\u{F5F7}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN], + '\u{F5F8}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP], + '\u{F5F9}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP], + '\u{F5FA}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_UP], + '\u{F5FB}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_UP], - // Horizontal and branching down - '\u{F5E0}': [Parts.LINE_H, Parts.CURVE_DOWN_LEFT], - '\u{F5E1}': [Parts.LINE_H, Parts.CURVE_DOWN_RIGHT], - '\u{F5E2}': [Parts.CURVE_DOWN_LEFT, Parts.CURVE_DOWN_RIGHT], - - // Horizontal and branching up - '\u{F5E3}': [Parts.LINE_H, Parts.CURVE_UP_LEFT], - '\u{F5E4}': [Parts.LINE_H, Parts.CURVE_UP_RIGHT], - '\u{F5E5}': [Parts.CURVE_UP_LEFT, Parts.CURVE_UP_RIGHT], - - // Branching in all four directions - '\u{F5E6}': [Parts.LINE_V, Parts.CURVE_UP_LEFT, Parts.CURVE_UP_RIGHT], - '\u{F5E7}': [Parts.LINE_V, Parts.CURVE_DOWN_LEFT, Parts.CURVE_DOWN_RIGHT], - '\u{F5E8}': [Parts.LINE_H, Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_LEFT], - '\u{F5E9}': [Parts.LINE_H, Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_RIGHT], - '\u{F5EA}': [Parts.LINE_V, Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_LEFT], - '\u{F5EB}': [Parts.LINE_V, Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_RIGHT], - '\u{F5EC}': [Parts.LINE_H, Parts.CURVE_DOWN_RIGHT, Parts.CURVE_UP_LEFT], - '\u{F5ED}': [Parts.LINE_H, Parts.CURVE_DOWN_LEFT, Parts.CURVE_UP_RIGHT], - - // Node (circle filling ~70% of cell, assumes 2:1 height:width aspect ratio) - '\u{F5EE}': [Parts.NODE_FILL, Parts.NODE_STROKE], - '\u{F5EF}': Parts.NODE_STROKE, - - // Node branching to right - '\u{F5F0}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_RIGHT], - '\u{F5F1}': [Parts.NODE_STROKE, Parts.NODE_LINE_RIGHT], - - // Node branching to left - '\u{F5F2}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_LEFT], - '\u{F5F3}': [Parts.NODE_STROKE, Parts.NODE_LINE_LEFT], - - // Node branching horizontally - '\u{F5F4}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], - '\u{F5F5}': [Parts.NODE_STROKE, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], - - // Node branching down - '\u{F5F6}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN], - '\u{F5F7}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN], - - // Node branching up - '\u{F5F8}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP], - '\u{F5F9}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP], - - // Node branching vertically - '\u{F5FA}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_UP], - '\u{F5FB}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_UP], - - // Node branching down right - '\u{F5FC}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING DOWN RIGHT - '\u{F5FD}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING DOWN RIGHT - - // Node branching down left - '\u{F5FE}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE FILLED BRANCHING DOWN LEFT - '\u{F5FF}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE EMPTY BRANCHING DOWN LEFT - - // Node branching up right - '\u{F600}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP RIGHT - '\u{F601}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP RIGHT - - // Node branching up left - '\u{F602}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT], // NODE FILLED BRANCHING UP LEFT - '\u{F603}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT], // NODE EMPTY BRANCHING UP LEFT - - // Node branching up down right - '\u{F604}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP DOWN RIGHT - '\u{F605}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP DOWN RIGHT - - // Node branching up down left - '\u{F606}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE FILLED BRANCHING UP DOWN LEFT - '\u{F607}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT], // NODE EMPTY BRANCHING UP DOWN LEFT - - // Node branching down left right - '\u{F608}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING DOWN LEFT RIGHT - '\u{F609}': [Parts.NODE_STROKE, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING DOWN LEFT RIGHT - - // Node branching up left right - '\u{F60A}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP LEFT RIGHT - '\u{F60B}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP LEFT RIGHT - - // Node branching up down left right - '\u{F60C}': [Parts.NODE_FILL, Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE FILLED BRANCHING UP DOWN LEFT RIGHT - '\u{F60D}': [Parts.NODE_STROKE, Parts.NODE_LINE_UP, Parts.NODE_LINE_DOWN, Parts.NODE_LINE_LEFT, Parts.NODE_LINE_RIGHT], // NODE EMPTY BRANCHING UP DOWN LEFT RIGHT + // Extended Git Branch Symbols (F5FC-F60D) + '\u{F5FC}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F5FD}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F5FE}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F5FF}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F600}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F601}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F602}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F603}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F604}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F605}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F606}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F607}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT], + '\u{F608}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F609}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F60A}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F60B}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F60C}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], + '\u{F60D}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_UP, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT, GitBranchSymbolsParts.NODE_LINE_RIGHT], // #endregion @@ -1010,3 +945,29 @@ const enum Shapes { /** ┆ */ THREE_DASHES_VERTICAL = 'M.5,.0667 L.5,.2667 M.5,.4 L.5,.6 M.5,.7333 L.5,.9333', /** ┊ */ FOUR_DASHES_VERTICAL = 'M.5,.05 L.5,.2 M.5,.3 L.5,.45 L.5,.55 M.5,.7 L.5,.95', } + +namespace GitBranchSymbolsParts { + // Lines + export const LINE_H: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }); + export const LINE_V: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }); + + // Fading lines + 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 }); + 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 }); + 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 }); + 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 }); + + // Curved corners + 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 }); + 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 }); + 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 }); + 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 }); + + // Node parts + 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' }); + 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 }); + export const NODE_LINE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }); + export const NODE_LINE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }); + export const NODE_LINE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }); + export const NODE_LINE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }); +} diff --git a/addons/addon-webgl/typings/addon-webgl.d.ts b/addons/addon-webgl/typings/addon-webgl.d.ts index eff6e424..5de7289c 100644 --- a/addons/addon-webgl/typings/addon-webgl.d.ts +++ b/addons/addon-webgl/typings/addon-webgl.d.ts @@ -61,7 +61,7 @@ declare module '@xterm/addon-webgl' { * - Braille Patterns (U+2800-U+28FF) * - Powerline Symbols (U+E0A0–U+E0D4, Private Use Area with widespread * adoption) - * - Git Branch Symbols (U+F5D0-U+F5FB, Private Use Area initially adopted + * - Git Branch Symbols (U+F5D0-U+F60D, Private Use Area initially adopted * in [Kitty in 2024](https://github.com/kovidgoyal/kitty/pull/7681) by * author of [vim-flog](https://github.com/rbong/vim-flog)) * - Symbols for Legacy Computing (U+1FB00–U+1FBFF) diff --git a/demo/client.ts b/demo/client.ts index 0abe340a..0f43231d 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -952,15 +952,18 @@ function customGlyphRangesHandler(): void { // Range: E0A0–E0D4 // https://github.com/ryanoasis/nerd-fonts writeUnicodeTable(term, 'Powerline Symbols', 0xE0A0, 0xE0D4, [ - ['Powerline Symbols', 0xE0A0, 0xE0B3, [0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF]], - ['Powerline Extra Symbols', 0xE0B4, 0xE0D4, [0xE0C9, 0xE0CB, 0xE0D3]], + ['Powerline symbols', 0xE0A0, 0xE0B3, [0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF]], + ['Powerline extra symbols', 0xE0B4, 0xE0D4, [0xE0C9, 0xE0CB, 0xE0D3]], ]); // Git Branch Symbols - // F5D0-F5FB + // F5D0-F60D // https://github.com/xtermjs/xterm.js/issues/5477 writeUnicodeTable(term, 'Git Branch Symbols', 0xF5D0, 0xF5FB, [ - ['Git Branch Symbols', 0xF5D0, 0xF5FB], - ['Extended Git Branch Symbols', 0xF5FC, 0xF60D], + ['Straight lines', 0xF5D0, 0xF5D5], + ['Curved lines', 0xF5D6, 0xF5D9], + ['Branching lines', 0xF5DA, 0xF5ED], + ['Nodes', 0xF5EE, 0xF5FB], + ['Extended nodes', 0xF5FC, 0xF60D], ]); // Symbols for Legacy Computing // Range: 1FB00–1FBFF From 6612153c44d5d9a96f7201e1a0a0ca9769ddb2c4 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:10:36 -0800 Subject: [PATCH 7/8] Add alignment tests --- .../customGlyphs/CustomGlyphDefinitions.ts | 52 +++++++++---------- demo/client.ts | 7 ++- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 68e5f274..7f8d3ddf 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -7,6 +7,32 @@ import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, /* eslint-disable max-len */ +namespace GitBranchSymbolsParts { + // Lines + export const LINE_H: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }); + export const LINE_V: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }); + + // Fading lines + 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 }); + 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 }); + 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 }); + 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 }); + + // Curved corners + 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 }); + 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 }); + 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 }); + 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 }); + + // Node parts + 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' }); + 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 }); + export const NODE_LINE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }); + export const NODE_LINE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }); + export const NODE_LINE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }); + export const NODE_LINE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }); +} + export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } = { // #region Box Drawing (2500-257F) @@ -945,29 +971,3 @@ const enum Shapes { /** ┆ */ THREE_DASHES_VERTICAL = 'M.5,.0667 L.5,.2667 M.5,.4 L.5,.6 M.5,.7333 L.5,.9333', /** ┊ */ FOUR_DASHES_VERTICAL = 'M.5,.05 L.5,.2 M.5,.3 L.5,.45 L.5,.55 M.5,.7 L.5,.95', } - -namespace GitBranchSymbolsParts { - // Lines - export const LINE_H: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.LEFT_TO_RIGHT, strokeWidth: 1 }); - export const LINE_V: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: Shapes.TOP_TO_BOTTOM, strokeWidth: 1 }); - - // Fading lines - 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 }); - 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 }); - 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 }); - 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 }); - - // Curved corners - 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 }); - 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 }); - 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 }); - 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 }); - - // Node parts - 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' }); - 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 }); - export const NODE_LINE_RIGHT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M1,.5 L.85,.5', strokeWidth: 1 }); - export const NODE_LINE_LEFT: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M0,.5 L.15,.5', strokeWidth: 1 }); - export const NODE_LINE_DOWN: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,1 L.5,.7', strokeWidth: 1 }); - export const NODE_LINE_UP: CustomGlyphDefinitionPart = Object.freeze({ type: CustomGlyphDefinitionType.PATH, data: 'M.5,0 L.5,.3', strokeWidth: 1 }); -} diff --git a/demo/client.ts b/demo/client.ts index 0f43231d..d211c885 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -904,14 +904,13 @@ function customGlyphAlignmentHandler(): void { term.write('\n\r'); term.write('\x1b[0mGit Branch Symbols alignment tests:\x1b[32m\n\r'); - term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7}\n\r'); - term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1}\n\r'); - term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D8}\u{F5D0}\u{F5D9}\n\r'); + term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7} \u{F5FC}\u{F5FC}\u{F5FE} \u{F5FD}\u{F609}\u{F5FF}\n\r'); + term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1} \u{F604}\u{F60C}\u{F606} \u{F605}\u{F60D}\u{F607}\n\r'); + term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D8}\u{F5D0}\u{F5D9} \u{F600}\u{F60A}\u{F602} \u{F601}\u{F60B}\u{F603}\n\r'); term.write(' \u{F5DC}\u{F5DF} \u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\n\r'); term.write('\u{F5F1}\u{F5E6}\u{F5E7}\u{F5F3} \u{F5D3}\u{F5D0}\u{F5E0}\u{F5E1}\u{F5E2}\u{F5E3}\u{F5E4}\u{F5E5}\u{F5E8}\u{F5E9}\u{F5EC}\u{F5ED}\u{F5D2}\n\r'); term.write('\u{F5F1}\u{F5EA}\u{F5EB}\u{F5F3} \u{F5F9}\u{F5F9}\u{F5F9} \u{F5F9}\u{F5F9}\u{F5F9}\u{F5F9}\n\r'); term.write(' \u{F5F9}\u{F5F9} \n\r'); - term.write('\x1b[0m'); term.write('\n\r'); window.scrollTo(0, 0); From 8b1306f46de13157739eeadd02e2821abda6287d Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:13:11 -0800 Subject: [PATCH 8/8] More polish --- .../addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts | 7 ++++--- addons/addon-webgl/typings/addon-webgl.d.ts | 6 ++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 7f8d3ddf..eb0db9e2 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -326,8 +326,8 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi // #region Git Branch Symbols (F5D0-F60D) - // Initially added in https://github.com/kovidgoyal/kitty/pull/7681 then in - // [Wezterm](https://github.com/wezterm/wezterm/issues/6328). + // Initially added in Kitty (https://github.com/kovidgoyal/kitty/pull/7681) + // then in Wezterm (https://github.com/wezterm/wezterm/issues/6328). // Straight lines (F5D0-F5D9) '\u{F5D0}': GitBranchSymbolsParts.LINE_H, // Same as 2500 @@ -381,7 +381,8 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi '\u{F5FA}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_UP], '\u{F5FB}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_UP], - // Extended Git Branch Symbols (F5FC-F60D) + // Extended Nodes (F5FC-F60D) + // These were added a little later https://github.com/kovidgoyal/kitty/pull/7805 '\u{F5FC}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT], '\u{F5FD}': [GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_RIGHT], '\u{F5FE}': [GitBranchSymbolsParts.NODE_FILL, GitBranchSymbolsParts.NODE_STROKE, GitBranchSymbolsParts.NODE_LINE_DOWN, GitBranchSymbolsParts.NODE_LINE_LEFT], diff --git a/addons/addon-webgl/typings/addon-webgl.d.ts b/addons/addon-webgl/typings/addon-webgl.d.ts index 5de7289c..5a4e9a77 100644 --- a/addons/addon-webgl/typings/addon-webgl.d.ts +++ b/addons/addon-webgl/typings/addon-webgl.d.ts @@ -67,15 +67,13 @@ declare module '@xterm/addon-webgl' { * - Symbols for Legacy Computing (U+1FB00–U+1FBFF) * * This will typically result in better rendering with continuous lines, - * even when line height and letter spacing is used. Note that this doesn't - * work with the DOM renderer which renders all characters using the font. - * The default is true. + * even when line height and letter spacing is used. The default is true. */ customGlyphs?: boolean; /** * Whether to enable the preserveDrawingBuffer flag when creating the WebGL - * context. This may be useful in tests. This defaults to false. + * context. This may be useful in tests. This default is false. */ preserveDrawingBuffer?: boolean }