diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 0bea7f3d..052f8c38 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -637,6 +637,20 @@ export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefi '\u{1FBFA}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M.5,.175 C.2,.175,.15,.305,.15,.435 L.05,.63 L.35,.63 C.35,.682,.42,.76,.5,.76 C.58,.76,.65,.682,.65,.63 L.95,.63 L.85,.435 C.85,.305,.8,.175,.5,.175 Z', type: CustomGlyphVectorType.FILL } }, // ALARM BELL SYMBOL // #endregion + + // #region Braille Patterns (2800-28FF) + + // https://www.unicode.org/charts/PDF/U2800.pdf + + // Braille patterns (2800-28FF) + ...Object.fromEntries( + Array.from({ length: 256 }, (_, i) => [ + String.fromCodePoint(0x2800 + i), + { type: CustomGlyphDefinitionType.BRAILLE, data: i } + ]) + ), + + // #endregion }; /** diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts index 3e0bfcae..6fedf067 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts @@ -71,6 +71,9 @@ function drawDefinitionPart( case CustomGlyphDefinitionType.VECTOR_SHAPE: drawVectorShape(ctx, part.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio); break; + case CustomGlyphDefinitionType.BRAILLE: + drawBrailleCharacter(ctx, part.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight); + break; } if (part.clipPath) { @@ -99,6 +102,52 @@ function drawBlockVectorChar( } } +/** + * Braille dot positions in octant coordinates (x, y for center of each dot area) + * Columns: left=1-2, right=5-6 (leaving 0 and 7 as margins, 3-4 as gap) + * Rows: 0-1, 2-3, 4-5, 6-7 for the 4 rows + */ +const brailleDotPositions = new Uint8Array([ + 1, 0, // dot 1 - bit 0 + 1, 2, // dot 2 - bit 1 + 1, 4, // dot 3 - bit 2 + 5, 0, // dot 4 - bit 3 + 5, 2, // dot 5 - bit 4 + 5, 4, // dot 6 - bit 5 + 1, 6, // dot 7 - bit 6 + 5, 6, // dot 8 - bit 7 +]); + +/** + * Draws a braille pattern + */ +function drawBrailleCharacter( + ctx: CanvasRenderingContext2D, + pattern: number, + xOffset: number, + yOffset: number, + deviceCellWidth: number, + deviceCellHeight: number +): void { + const xEighth = deviceCellWidth / 8; + const paddingY = deviceCellHeight * 0.1; + const usableHeight = deviceCellHeight * 0.8; + const yEighth = usableHeight / 8; + const radius = Math.min(xEighth, yEighth); + + for (let bit = 0; bit < 8; bit++) { + if (pattern & (1 << bit)) { + const x = brailleDotPositions[bit * 2]; + const y = brailleDotPositions[bit * 2 + 1]; + const cx = xOffset + (x + 1) * xEighth; + const cy = yOffset + paddingY + (y + 1) * yEighth; + ctx.beginPath(); + ctx.arc(cx, cy, radius, 0, Math.PI * 2); + ctx.fill(); + } + } +} + function drawPathDefinitionCharacter( ctx: CanvasRenderingContext2D, charDefinition: CustomGlyphPathDrawFunctionDefinition | string, diff --git a/addons/addon-webgl/src/customGlyphs/Types.ts b/addons/addon-webgl/src/customGlyphs/Types.ts index 0e4a2fa6..30820321 100644 --- a/addons/addon-webgl/src/customGlyphs/Types.ts +++ b/addons/addon-webgl/src/customGlyphs/Types.ts @@ -37,6 +37,7 @@ export const enum CustomGlyphDefinitionType { PATH, PATH_NEGATIVE, VECTOR_SHAPE, + BRAILLE, } export type CustomGlyphDefinitionPartRaw = ( @@ -45,7 +46,8 @@ export type CustomGlyphDefinitionPartRaw = ( { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: CustomGlyphPathDrawFunctionDefinition | string } | { type: CustomGlyphDefinitionType.PATH, data: string } | { type: CustomGlyphDefinitionType.PATH_NEGATIVE, data: ICustomGlyphVectorShape } | - { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: ICustomGlyphVectorShape} + { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: ICustomGlyphVectorShape} | + { type: CustomGlyphDefinitionType.BRAILLE, data: number } ); export interface ICustomGlyphDefinitionCommon { diff --git a/demo/client.ts b/demo/client.ts index 0cfc6981..e0bb2b85 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -894,6 +894,12 @@ function customGlyphRangesHandler(): void { ['Block elements', 0x2594, 0x2595], ['Terminal graphic characters', 0x2596, 0x259F], ]); + // Braille Patterns + // 2800-28FF + // https://www.unicode.org/charts/PDF/U2800.pdf + writeUnicodeTable(term, 'Braille patterns', 0x2800, 0x28FF, [ + ['Braille patterns', 0x2800, 0x28FF], + ]); // Powerline Symbols // Range: E0A0–E0BF // https://github.com/ryanoasis/nerd-fonts diff --git a/typings/xterm-headless.d.ts b/typings/xterm-headless.d.ts index 369de459..1a74471e 100644 --- a/typings/xterm-headless.d.ts +++ b/typings/xterm-headless.d.ts @@ -69,6 +69,7 @@ declare module '@xterm/headless' { * * - Box Drawing (U+2500-U+257F) * - Box Elements (U+2580-U+259F) + * - Braille Patterns (U+2800-U+28FF) * - Powerline Symbols (U+E0A0–U+E0BF) * - Symbols for Legacy Computing (U+1FB00–U+1FBFF) * diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 18709d71..b4cf3628 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -83,6 +83,7 @@ declare module '@xterm/xterm' { * * - Box Drawing (U+2500-U+257F) * - Box Elements (U+2580-U+259F) + * - Braille Patterns (U+2800-U+28FF) * - Powerline Symbols (U+E0A0–U+E0BF) * - Symbols for Legacy Computing (U+1FB00–U+1FBFF) *