Merge pull request #5472 from Tyriar/tyriar/5466_refactor__unified

Custom glyph: Unify rendering function and move all definitions into a single ordered object
This commit is contained in:
Daniel Imms
2025-12-22 13:31:36 -08:00
committed by GitHub
7 changed files with 551 additions and 579 deletions
-8
View File
@@ -159,14 +159,6 @@
"@typescript-eslint/prefer-namespace-keyword": "warn",
"@typescript-eslint/type-annotation-spacing": "warn",
"comma-dangle": [
"warn",
{
"objects": "never",
"arrays": "never",
"functions": "never"
}
],
"curly": [
"warn",
"multi-line"
@@ -3,158 +3,282 @@
* @license MIT
*/
import { CustomGlyphVectorType, type CustomGlyphDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types';
import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphPathDrawFunctionDefinition } from './Types';
/* eslint-disable @typescript-eslint/naming-convention */
export const unifiedCharDefinitions: { [index: string]: ICustomGlyphVectorShape[] | undefined } = {
};
export const customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } = {
// #region Box Drawing (2500-257F)
export const blockElementDefinitions: { [index: string]: ICustomGlyphSolidOctantBlockVector[] | undefined } = {
// Block elements (0x2580-0x2590)
'▀': [{ x: 0, y: 0, w: 8, h: 4 }], // UPPER HALF BLOCK
'▁': [{ x: 0, y: 7, w: 8, h: 1 }], // LOWER ONE EIGHTH BLOCK
'▂': [{ x: 0, y: 6, w: 8, h: 2 }], // LOWER ONE QUARTER BLOCK
'▃': [{ x: 0, y: 5, w: 8, h: 3 }], // LOWER THREE EIGHTHS BLOCK
'▄': [{ x: 0, y: 4, w: 8, h: 4 }], // LOWER HALF BLOCK
'▅': [{ x: 0, y: 3, w: 8, h: 5 }], // LOWER FIVE EIGHTHS BLOCK
'▆': [{ x: 0, y: 2, w: 8, h: 6 }], // LOWER THREE QUARTERS BLOCK
'▇': [{ x: 0, y: 1, w: 8, h: 7 }], // LOWER SEVEN EIGHTHS BLOCK
'█': [{ x: 0, y: 0, w: 8, h: 8 }], // FULL BLOCK
'▉': [{ x: 0, y: 0, w: 7, h: 8 }], // LEFT SEVEN EIGHTHS BLOCK
'▊': [{ x: 0, y: 0, w: 6, h: 8 }], // LEFT THREE QUARTERS BLOCK
'▋': [{ x: 0, y: 0, w: 5, h: 8 }], // LEFT FIVE EIGHTHS BLOCK
'▌': [{ x: 0, y: 0, w: 4, h: 8 }], // LEFT HALF BLOCK
'▍': [{ x: 0, y: 0, w: 3, h: 8 }], // LEFT THREE EIGHTHS BLOCK
'▎': [{ x: 0, y: 0, w: 2, h: 8 }], // LEFT ONE QUARTER BLOCK
'▏': [{ x: 0, y: 0, w: 1, h: 8 }], // LEFT ONE EIGHTH BLOCK
'▐': [{ x: 4, y: 0, w: 4, h: 8 }], // RIGHT HALF BLOCK
// https://www.unicode.org/charts/PDF/U2500.pdf
// Block elements (0x2594-0x2595)
'▔': [{ x: 0, y: 0, w: 8, h: 1 }], // UPPER ONE EIGHTH BLOCK
'▕': [{ x: 7, y: 0, w: 1, h: 8 }], // RIGHT ONE EIGHTH BLOCK
// Light and heavy solid lines (2500-2503)
'─': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT } },
'━': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT } },
'│': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM } },
'┃': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM } },
// Terminal graphic characters (0x2596-0x259F)
'▖': [{ x: 0, y: 4, w: 4, h: 4 }], // QUADRANT LOWER LEFT
'▗': [{ x: 4, y: 4, w: 4, h: 4 }], // QUADRANT LOWER RIGHT
'▘': [{ x: 0, y: 0, w: 4, h: 4 }], // QUADRANT UPPER LEFT
'▙': [{ x: 0, y: 0, w: 4, h: 8 }, { x: 0, y: 4, w: 8, h: 4 }], // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
'▚': [{ x: 0, y: 0, w: 4, h: 4 }, { x: 4, y: 4, w: 4, h: 4 }], // QUADRANT UPPER LEFT AND LOWER RIGHT
'▛': [{ x: 0, y: 0, w: 4, h: 8 }, { x: 4, y: 0, w: 4, h: 4 }], // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
'▜': [{ x: 0, y: 0, w: 8, h: 4 }, { x: 4, y: 0, w: 4, h: 8 }], // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
'▝': [{ x: 4, y: 0, w: 4, h: 4 }], // QUADRANT UPPER RIGHT
'▞': [{ x: 4, y: 0, w: 4, h: 4 }, { x: 0, y: 4, w: 4, h: 4 }], // QUADRANT UPPER RIGHT AND LOWER LEFT
'▟': [{ x: 4, y: 0, w: 4, h: 8 }, { x: 0, y: 4, w: 8, h: 4 }], // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
// Light and heavy dashed lines (2504-250B)
'┄': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.THREE_DASHES_HORIZONTAL } },
'┅': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.THREE_DASHES_HORIZONTAL } },
'┆': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.THREE_DASHES_VERTICAL } },
'┇': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.THREE_DASHES_VERTICAL } },
'┈': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.FOUR_DASHES_HORIZONTAL } },
'┉': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.FOUR_DASHES_HORIZONTAL } },
'┊': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.FOUR_DASHES_VERTICAL } },
'┋': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.FOUR_DASHES_VERTICAL } },
// VERTICAL ONE EIGHTH BLOCK-2 through VERTICAL ONE EIGHTH BLOCK-7
'\u{1FB70}': [{ x: 1, y: 0, w: 1, h: 8 }],
'\u{1FB71}': [{ x: 2, y: 0, w: 1, h: 8 }],
'\u{1FB72}': [{ x: 3, y: 0, w: 1, h: 8 }],
'\u{1FB73}': [{ x: 4, y: 0, w: 1, h: 8 }],
'\u{1FB74}': [{ x: 5, y: 0, w: 1, h: 8 }],
'\u{1FB75}': [{ x: 6, y: 0, w: 1, h: 8 }],
// Light and heavy line box components (250C-254B)
'┌': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM } },
'┍': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'┎': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'┏': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM } },
'┐': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM } },
'┑': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'┒': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'┓': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM } },
'└': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT } },
'┕': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'┖': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'┗': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT } },
'┘': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT } },
'┙': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'┚': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'┛': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.TOP_TO_LEFT } },
'├': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.T_RIGHT } },
'┝': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'┞': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'┟': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'┠': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM } },
'┡': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT } },
'┢': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM } },
'┣': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.T_RIGHT } },
'┤': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.T_LEFT } },
'┥': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'┦': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'┧': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'┨': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM } },
'┩': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_LEFT } },
'┪': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM } },
'┫': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.T_LEFT } },
'┬': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.T_BOTTOM } },
'┭': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'┮': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'┯': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT } },
'┰': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'┱': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM } },
'┲': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM } },
'┳': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.T_BOTTOM } },
'┴': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.T_TOP } },
'┵': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'┶': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'┷': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT } },
'┸': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'┹': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.TOP_TO_LEFT } },
'┺': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT } },
'┻': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.T_TOP } },
'┼': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.CROSS } },
'┽': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_RIGHT}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'┾': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_LEFT}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'┿': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM, [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT } },
'╀': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: `${Shapes.LEFT_TO_RIGHT} ${Shapes.MIDDLE_TO_BOTTOM}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'╁': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: `${Shapes.MIDDLE_TO_TOP} ${Shapes.LEFT_TO_RIGHT}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'╂': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT, [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM } },
'╃': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_LEFT } },
'╄': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT } },
'╅': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT, [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM } },
'╆': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT, [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM } },
'╇': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: `${Shapes.MIDDLE_TO_TOP} ${Shapes.LEFT_TO_RIGHT}` } },
'╈': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: `${Shapes.LEFT_TO_RIGHT} ${Shapes.MIDDLE_TO_BOTTOM}` } },
'╉': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_LEFT}` } },
'╊': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_RIGHT}` } },
'╋': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.CROSS } },
// HORIZONTAL ONE EIGHTH BLOCK-2 through HORIZONTAL ONE EIGHTH BLOCK-7
'\u{1FB76}': [{ x: 0, y: 1, w: 8, h: 1 }],
'\u{1FB77}': [{ x: 0, y: 2, w: 8, h: 1 }],
'\u{1FB78}': [{ x: 0, y: 3, w: 8, h: 1 }],
'\u{1FB79}': [{ x: 0, y: 4, w: 8, h: 1 }],
'\u{1FB7A}': [{ x: 0, y: 5, w: 8, h: 1 }],
'\u{1FB7B}': [{ x: 0, y: 6, w: 8, h: 1 }],
// Light and heavy dashed lines (254C-254F)
'╌': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TWO_DASHES_HORIZONTAL } },
'╍': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.TWO_DASHES_HORIZONTAL } },
'╎': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.TWO_DASHES_VERTICAL } },
'╏': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.TWO_DASHES_VERTICAL } },
// LEFT AND LOWER ONE EIGHTH BLOCK
'\u{1FB7C}': [{ x: 0, y: 0, w: 1, h: 8 }, { x: 0, y: 7, w: 8, h: 1 }],
// LEFT AND UPPER ONE EIGHTH BLOCK
'\u{1FB7D}': [{ x: 0, y: 0, w: 1, h: 8 }, { x: 0, y: 0, w: 8, h: 1 }],
// RIGHT AND UPPER ONE EIGHTH BLOCK
'\u{1FB7E}': [{ x: 7, y: 0, w: 1, h: 8 }, { x: 0, y: 0, w: 8, h: 1 }],
// RIGHT AND LOWER ONE EIGHTH BLOCK
'\u{1FB7F}': [{ x: 7, y: 0, w: 1, h: 8 }, { x: 0, y: 7, w: 8, h: 1 }],
// UPPER AND LOWER ONE EIGHTH BLOCK
'\u{1FB80}': [{ x: 0, y: 0, w: 8, h: 1 }, { x: 0, y: 7, w: 8, h: 1 }],
// HORIZONTAL ONE EIGHTH BLOCK-1358
'\u{1FB81}': [{ x: 0, y: 0, w: 8, h: 1 }, { x: 0, y: 2, w: 8, h: 1 }, { x: 0, y: 4, w: 8, h: 1 }, { x: 0, y: 7, w: 8, h: 1 }],
// Double lines (2550-2551)
'═': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` } },
'║': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` } },
// UPPER ONE QUARTER BLOCK
'\u{1FB82}': [{ x: 0, y: 0, w: 8, h: 2 }],
// UPPER THREE EIGHTHS BLOCK
'\u{1FB83}': [{ x: 0, y: 0, w: 8, h: 3 }],
// UPPER FIVE EIGHTHS BLOCK
'\u{1FB84}': [{ x: 0, y: 0, w: 8, h: 5 }],
// UPPER THREE QUARTERS BLOCK
'\u{1FB85}': [{ x: 0, y: 0, w: 8, h: 6 }],
// UPPER SEVEN EIGHTHS BLOCK
'\u{1FB86}': [{ x: 0, y: 0, w: 8, h: 7 }],
// Light and double line box components (2552-256C)
'╒': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 - yp} L1,${.5 - yp} M.5,${.5 + yp} L1,${.5 + yp}` } },
'╓': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},1 L${.5 - xp},.5 L1,.5 M${.5 + xp},.5 L${.5 + xp},1` } },
'╔': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M1,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1` } },
'╕': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L.5,${.5 - yp} L.5,1 M0,${.5 + yp} L.5,${.5 + yp}` } },
'╖': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M${.5 + xp},1 L${.5 + xp},.5 L0,.5 M${.5 - xp},.5 L${.5 - xp},1` } },
'╗': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M0,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},1` } },
'╘': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 + yp} L1,${.5 + yp} M.5,${.5 - yp} L1,${.5 - yp}` } },
'╙': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M1,.5 L${.5 - xp},.5 L${.5 - xp},0 M${.5 + xp},.5 L${.5 + xp},0` } },
'╚': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0 M1,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},0` } },
'╛': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L.5,${.5 + yp} L.5,0 M0,${.5 - yp} L.5,${.5 - yp}` } },
'╜': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,.5 L${.5 + xp},.5 L${.5 + xp},0 M${.5 - xp},.5 L${.5 - xp},0` } },
'╝': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0 M0,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},0` } },
'╞': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M.5,${.5 - yp} L1,${.5 - yp} M.5,${.5 + yp} L1,${.5 + yp}` } },
'╟': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1 M${.5 + xp},.5 L1,.5` } },
'╠': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1 M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0` } },
'╡': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M0,${.5 - yp} L.5,${.5 - yp} M0,${.5 + yp} L.5,${.5 + yp}` } },
'╢': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,.5 L${.5 - xp},.5 M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` } },
'╣': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M${.5 + xp},0 L${.5 + xp},1 M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0` } },
'╤': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp} M.5,${.5 + yp} L.5,1` } },
'╥': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},.5 L${.5 - xp},1 M${.5 + xp},.5 L${.5 + xp},1` } },
'╦': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1` } },
'╧': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - yp} M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` } },
'╨': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},.5 L${.5 - xp},0 M${.5 + xp},.5 L${.5 + xp},0` } },
'╩': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L1,${.5 + yp} M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0 M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0` } },
'╪': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` } },
'╫': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` } },
'╬': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1 M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0 M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0` } },
// RIGHT ONE QUARTER BLOCK
'\u{1FB87}': [{ x: 6, y: 0, w: 2, h: 8 }],
// RIGHT THREE EIGHTHS B0OCK
'\u{1FB88}': [{ x: 5, y: 0, w: 3, h: 8 }],
// RIGHT FIVE EIGHTHS BL0CK
'\u{1FB89}': [{ x: 3, y: 0, w: 5, h: 8 }],
// RIGHT THREE QUARTERS 0LOCK
'\u{1FB8A}': [{ x: 2, y: 0, w: 6, h: 8 }],
// RIGHT SEVEN EIGHTHS B0OCK
'\u{1FB8B}': [{ x: 1, y: 0, w: 7, h: 8 }],
// Character cell arcs (256D-2570)
'╭': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5` } },
'╮': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5` } },
'╯': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5` } },
'╰': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5` } },
// CHECKER BOARD FILL
'\u{1FB95}': [
{ x: 0, y: 0, w: 2, h: 2 }, { x: 4, y: 0, w: 2, h: 2 },
{ x: 2, y: 2, w: 2, h: 2 }, { x: 6, y: 2, w: 2, h: 2 },
{ x: 0, y: 4, w: 2, h: 2 }, { x: 4, y: 4, w: 2, h: 2 },
{ x: 2, y: 6, w: 2, h: 2 }, { x: 6, y: 6, w: 2, h: 2 }
],
// INVERSE CHECKER BOARD FILL
'\u{1FB96}': [
{ x: 2, y: 0, w: 2, h: 2 }, { x: 6, y: 0, w: 2, h: 2 },
{ x: 0, y: 2, w: 2, h: 2 }, { x: 4, y: 2, w: 2, h: 2 },
{ x: 2, y: 4, w: 2, h: 2 }, { x: 6, y: 4, w: 2, h: 2 },
{ x: 0, y: 6, w: 2, h: 2 }, { x: 4, y: 6, w: 2, h: 2 }
],
// HEAVY HORIZONTAL FILL (upper middle and lower one quarter block)
'\u{1FB97}': [{ x: 0, y: 2, w: 8, h: 2 }, { x: 0, y: 6, w: 8, h: 2 }]
};
// Character cell diagonals (2571-2573)
'╱': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: 'M1,0 L0,1' } },
'╲': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: 'M0,0 L1,1' } },
'╳': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: 'M1,0 L0,1 M0,0 L1,1' } },
/**
* Generates a drawing function for sextant characters. Sextants are a 2x3 grid where each cell
* can be on or off.
* @param pattern A 6-bit pattern where bit 0 = top-left, bit 1 = top-right, bit 2 = middle-left,
* bit 3 = middle-right, bit 4 = bottom-left, bit 5 = bottom-right
*/
function sextant(pattern: number): CustomGlyphDrawFunctionDefinition {
return () => {
// Sextant grid: 2 columns, 3 rows
// Row heights in 8ths: top=3, middle=2, bottom=3
// Column widths: left=4, right=4
const rects: string[] = [];
const colW = 0.5; // Each column is half width
const rowH = [3 / 8, 2 / 8, 3 / 8]; // Row heights as fractions
const rowY = [0, 3 / 8, 5 / 8]; // Row Y positions
// Light and heavy half lines (2574-257B)
'╴': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT } },
'╵': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP } },
'╶': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT } },
'╷': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM } },
'╸': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'╹': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
'╺': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'╻': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
for (let row = 0; row < 3; row++) {
const leftBit = (pattern >> (row * 2)) & 1;
const rightBit = (pattern >> (row * 2 + 1)) & 1;
// Mixed light and heavy lines (257C-257F)
'╼': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT } },
'╽': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM } },
'╾': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT } },
'╿': { type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP } },
if (leftBit && rightBit) {
// Full row
rects.push(`M0,${rowY[row]} L1,${rowY[row]} L1,${rowY[row] + rowH[row]} L0,${rowY[row] + rowH[row]} Z`);
} else if (leftBit) {
rects.push(`M0,${rowY[row]} L${colW},${rowY[row]} L${colW},${rowY[row] + rowH[row]} L0,${rowY[row] + rowH[row]} Z`);
} else if (rightBit) {
rects.push(`M${colW},${rowY[row]} L1,${rowY[row]} L1,${rowY[row] + rowH[row]} L${colW},${rowY[row] + rowH[row]} Z`);
}
}
return rects.join(' ');
};
}
// #endregion
export const symbolsForLegacyComputingDefinitions: { [index: string]: CustomGlyphDrawFunctionDefinition | undefined } = {
// Block sextants (0x1FB00-0x1FB3B)
// Each sextant is a 2x3 grid of cells in an 8x8 block
// Cell positions: bit 0=top-left, bit 1=top-right, bit 2=middle-left, bit 3=middle-right,
// bit 4=bottom-left, bit 5=bottom-right
// Patterns 0 (empty), 21 (left half), 42 (right half), 63 (full) are excluded as they exist
// elsewhere
// #region Block elements (2580-259F)
// https://www.unicode.org/charts/PDF/U2580.pdf
// Block elements (2580-2590)
'▀': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 4 }] }, // UPPER HALF BLOCK
'▁': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 7, w: 8, h: 1 }] }, // LOWER ONE EIGHTH BLOCK
'▂': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 6, w: 8, h: 2 }] }, // LOWER ONE QUARTER BLOCK
'▃': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 5, w: 8, h: 3 }] }, // LOWER THREE EIGHTHS BLOCK
'▄': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 4, w: 8, h: 4 }] }, // LOWER HALF BLOCK
'▅': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 3, w: 8, h: 5 }] }, // LOWER FIVE EIGHTHS BLOCK
'▆': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 2, w: 8, h: 6 }] }, // LOWER THREE QUARTERS BLOCK
'▇': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 1, w: 8, h: 7 }] }, // LOWER SEVEN EIGHTHS BLOCK
'█': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 8 }] }, // FULL BLOCK (=solid -> 25A0=black square)
'▉': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 7, h: 8 }] }, // LEFT SEVEN EIGHTHS BLOCK
'▊': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 6, h: 8 }] }, // LEFT THREE QUARTERS BLOCK
'▋': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 5, h: 8 }] }, // LEFT FIVE EIGHTHS BLOCK
'▌': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 4, h: 8 }] }, // LEFT HALF BLOCK
'▍': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 3, h: 8 }] }, // LEFT THREE EIGHTHS BLOCK
'▎': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 2, h: 8 }] }, // LEFT ONE QUARTER BLOCK
'▏': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 1, h: 8 }] }, // LEFT ONE EIGHTH BLOCK
'▐': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 4, y: 0, w: 4, h: 8 }] }, // RIGHT HALF BLOCK
// Shade characters (2591-2593)
'░': { type: CustomGlyphDefinitionType.BLOCK_PATTERN, data: [ // LIGHT SHADE (25%)
[1, 0],
[0, 0]
] },
'▒': { type: CustomGlyphDefinitionType.BLOCK_PATTERN, data: [ // MEDIUM SHADE (=speckles fill, dotted fill, 50%, used in mapping to cp949, -> 1FB90 inverse medium shade)
[1, 0],
[0, 1]
] },
'▓': { type: CustomGlyphDefinitionType.BLOCK_PATTERN, data: [ // DARK SHADE (75%)
[1, 1],
[1, 0]
] },
// Block elements (2594-2595)
'▔': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 1 }] }, // UPPER ONE EIGHTH BLOCK
'▕': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 7, y: 0, w: 1, h: 8 }] }, // RIGHT ONE EIGHTH BLOCK
// Terminal graphic characters (2596-259F)
'▖': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 4, w: 4, h: 4 }] }, // QUADRANT LOWER LEFT
'▗': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 4, y: 4, w: 4, h: 4 }] }, // QUADRANT LOWER RIGHT
'▘': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 4, h: 4 }] }, // QUADRANT UPPER LEFT
'▙': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 4, h: 8 }, { x: 0, y: 4, w: 8, h: 4 }] }, // QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT (-> 1F67F reverse checker board, -> 1FB95 checker board fill)
'▚': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 4, h: 4 }, { x: 4, y: 4, w: 4, h: 4 }] }, // QUADRANT UPPER LEFT AND LOWER RIGHT
'▛': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 4, h: 8 }, { x: 4, y: 0, w: 4, h: 4 }] }, // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
'▜': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 4 }, { x: 4, y: 0, w: 4, h: 8 }] }, // QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
'▝': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 4, y: 0, w: 4, h: 4 }] }, // QUADRANT UPPER RIGHT
'▞': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 4, y: 0, w: 4, h: 4 }, { x: 0, y: 4, w: 4, h: 4 }] }, // QUADRANT UPPER RIGHT AND LOWER LEFT (-> 1F67E checker board, 1FB96 inverse checker board fill)
'▟': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 4, y: 0, w: 4, h: 8 }, { x: 0, y: 4, w: 8, h: 4 }] }, // QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
// #endregion
// #region Powerline Symbols (E0A0-E0BF)
// This contains the definitions of the primarily used box drawing characters as vector shapes.
// The reason these characters are defined specially is to avoid common problems if a user's font
// has not been patched with powerline characters and also to get pixel perfect rendering as
// rendering issues can occur around AA/SPAA.
//
// The line variants draw beyond the cell and get clipped to ensure the end of the line is not
// visible.
//
// Original symbols defined in https://github.com/powerline/fontpatcher
// Git branch
'\u{E0A0}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M.3,1 L.03,1 L.03,.88 C.03,.82,.06,.78,.11,.73 C.15,.7,.2,.68,.28,.65 L.43,.6 C.49,.58,.53,.56,.56,.53 C.59,.5,.6,.47,.6,.43 L.6,.27 L.4,.27 L.69,.1 L.98,.27 L.78,.27 L.78,.46 C.78,.52,.76,.56,.72,.61 C.68,.66,.63,.67,.56,.7 L.48,.72 C.42,.74,.38,.76,.35,.78 C.32,.8,.31,.84,.31,.88 L.31,1 M.3,.5 L.03,.59 L.03,.09 L.3,.09 L.3,.655', type: CustomGlyphVectorType.FILL } },
// L N
'\u{E0A1}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M.7,.4 L.7,.47 L.2,.47 L.2,.03 L.355,.03 L.355,.4 L.705,.4 M.7,.5 L.86,.5 L.86,.95 L.69,.95 L.44,.66 L.46,.86 L.46,.95 L.3,.95 L.3,.49 L.46,.49 L.71,.78 L.69,.565 L.69,.5', type: CustomGlyphVectorType.FILL } },
// Lock
'\u{E0A2}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M.25,.94 C.16,.94,.11,.92,.11,.87 L.11,.53 C.11,.48,.15,.455,.23,.45 L.23,.3 C.23,.25,.26,.22,.31,.19 C.36,.16,.43,.15,.51,.15 C.59,.15,.66,.16,.71,.19 C.77,.22,.79,.26,.79,.3 L.79,.45 C.87,.45,.91,.48,.91,.53 L.91,.87 C.91,.92,.86,.94,.77,.94 L.24,.94 M.53,.2 C.49,.2,.45,.21,.42,.23 C.39,.25,.38,.27,.38,.3 L.38,.45 L.68,.45 L.68,.3 C.68,.27,.67,.25,.64,.23 C.61,.21,.58,.2,.53,.2 M.58,.82 L.58,.66 C.63,.65,.65,.63,.65,.6 C.65,.58,.64,.57,.61,.56 C.58,.55,.56,.54,.52,.54 C.48,.54,.46,.55,.43,.56 C.4,.57,.39,.59,.39,.6 C.39,.63,.41,.64,.46,.66 L.46,.82 L.57,.82', type: CustomGlyphVectorType.FILL } },
// Right triangle solid
'\u{E0B0}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0,0 L1,.5 L0,1', type: CustomGlyphVectorType.FILL, rightPadding: 2 } },
// Right triangle line
'\u{E0B1}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M-1,-.5 L1,.5 L-1,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 } },
// Left triangle solid
'\u{E0B2}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M1,0 L0,.5 L1,1', type: CustomGlyphVectorType.FILL, leftPadding: 2 } },
// Left triangle line
'\u{E0B3}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M2,-.5 L0,.5 L2,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 } },
// Powerline Extra Symbols
// Right semi-circle solid
'\u{E0B4}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M0,0 L0,1 C0.552,1,1,0.776,1,.5 C1,0.224,0.552,0,0,0', type: CustomGlyphVectorType.FILL, rightPadding: 1 } },
// Right semi-circle line
'\u{E0B5}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M.2,1 C.422,1,.8,.826,.78,.5 C.8,.174,0.422,0,.2,0', type: CustomGlyphVectorType.STROKE, rightPadding: 1 } },
// Left semi-circle solid
'\u{E0B6}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M1,0 L1,1 C0.448,1,0,0.776,0,.5 C0,0.224,0.448,0,1,0', type: CustomGlyphVectorType.FILL, leftPadding: 1 } },
// Left semi-circle line
'\u{E0B7}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M.8,1 C0.578,1,0.2,.826,.22,.5 C0.2,0.174,0.578,0,0.8,0', type: CustomGlyphVectorType.STROKE, leftPadding: 1 } },
// Lower left triangle
'\u{E0B8}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M-.5,-.5 L1.5,1.5 L-.5,1.5', type: CustomGlyphVectorType.FILL } },
// Backslash separator
'\u{E0B9}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M-.5,-.5 L1.5,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 } },
// Lower right triangle
'\u{E0BA}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M1.5,-.5 L-.5,1.5 L1.5,1.5', type: CustomGlyphVectorType.FILL } },
// Forward slash separator redundant (identical to E0BD)
'\u{E0BB}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M1.5,-.5 L-.5,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 } },
// Upper left triangle
'\u{E0BC}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M1.5,-.5 L-.5,1.5 L-.5,-.5', type: CustomGlyphVectorType.FILL } },
// Forward slash separator
'\u{E0BD}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M1.5,-.5 L-.5,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 } },
// Upper right triangle
'\u{E0BE}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M-.5,-.5 L1.5,1.5 L1.5,-.5', type: CustomGlyphVectorType.FILL } },
// Backslash separator redundant (identical to E0B9)
'\u{E0BF}': { type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: { d: 'M-.5,-.5 L1.5,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 } },
// #endregion
// #region Symbols for Legacy Computing (1FB00-1FB3B)
// https://www.unicode.org/charts/PDF/U1FB00.pdf
// Block mosaic terminal graphic characters (1FB00-1FB3B)
// The term "sextant" refers to block mosaics divided into six parts.
'\u{1FB00}': sextant(0b000001), // BLOCK SEXTANT-1
'\u{1FB01}': sextant(0b000010), // BLOCK SEXTANT-2
'\u{1FB02}': sextant(0b000011), // BLOCK SEXTANT-12 (upper one third block)
@@ -175,7 +299,6 @@ export const symbolsForLegacyComputingDefinitions: { [index: string]: CustomGlyp
'\u{1FB11}': sextant(0b010010), // BLOCK SEXTANT-25
'\u{1FB12}': sextant(0b010011), // BLOCK SEXTANT-125
'\u{1FB13}': sextant(0b010100), // BLOCK SEXTANT-35
// Pattern 21 (0x15 = 0b010101) = left half block, skipped (exists as U+258C)
'\u{1FB14}': sextant(0b010110), // BLOCK SEXTANT-235
'\u{1FB15}': sextant(0b010111), // BLOCK SEXTANT-1235
'\u{1FB16}': sextant(0b011000), // BLOCK SEXTANT-45
@@ -196,7 +319,6 @@ export const symbolsForLegacyComputingDefinitions: { [index: string]: CustomGlyp
'\u{1FB25}': sextant(0b100111), // BLOCK SEXTANT-1236
'\u{1FB26}': sextant(0b101000), // BLOCK SEXTANT-46
'\u{1FB27}': sextant(0b101001), // BLOCK SEXTANT-146
// Pattern 42 (0x2A = 0b101010) = right half block, skipped (exists as U+2590)
'\u{1FB28}': sextant(0b101011), // BLOCK SEXTANT-1246
'\u{1FB29}': sextant(0b101100), // BLOCK SEXTANT-346
'\u{1FB2A}': sextant(0b101101), // BLOCK SEXTANT-1346
@@ -216,142 +338,196 @@ export const symbolsForLegacyComputingDefinitions: { [index: string]: CustomGlyp
'\u{1FB38}': sextant(0b111011), // BLOCK SEXTANT-12456
'\u{1FB39}': sextant(0b111100), // BLOCK SEXTANT-3456 (lower two thirds block)
'\u{1FB3A}': sextant(0b111101), // BLOCK SEXTANT-13456
'\u{1FB3B}': sextant(0b111110), // BLOCK SEXTANT-23456
// Pattern 63 (0x3F = 0b111111) = full block, skipped (exists as U+2588)
'\u{1FB3B}': sextant(0b111110), // BLOCK SEXTANT-23456
// Smooth mosaic terminal graphic characters (0x1FB3C-0x1FB6F)
// These are triangular/diagonal shapes. "X BLOCK DIAGONAL A TO B" means the X region is filled,
// with a diagonal edge from point A to point B.
// Reference points: upper/lower = y (0/1), left/right = x (0/1), centre = x=0.5
// Vertical uses sextant grid: upper-middle = y=1/3, lower-middle = y=2/3
// Smooth mosaic terminal graphic characters (1FB3C-1FB6F)
'\u{1FB3C}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0,1 L0.5,1 Z' }, // LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB3D}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0,1 L1,1 Z' }, // LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB3E}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0,1 L0.5,1 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB3F}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0,1 L1,1 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB40}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L0,1 L0.5,1 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE
'\u{1FB41}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0.5,0 L1,0 L1,1 L0,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB42}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L1,0 L1,1 L0,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB43}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0.5,0 L1,0 L1,1 L0,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB44}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L1,0 L1,1 L0,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB45}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L0.5,0 L1,0 L1,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE
'\u{1FB46}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L1,0.3333 L1,1 L0,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT
'\u{1FB47}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,1 L1,0.6667 L1,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB48}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L1,0.6667 L1,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB49}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,1 L1,0.3333 L1,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB4A}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L1,0.3333 L1,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB4B}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,1 L1,0 L1,1 Z' }, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT
'\u{1FB4C}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,0 L0,0 L0,1 L1,1 L1,0.3333 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB4D}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L0,1 L1,1 L1,0.3333 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB4E}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,0 L0,0 L0,1 L1,1 L1,0.6667 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB4F}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L0,1 L1,1 L1,0.6667 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB50}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,0 L0,0 L0,1 L1,1 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT
'\u{1FB51}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0,1 L1,1 L1,0.6667 Z' }, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT
'\u{1FB52}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0.5,1 L1,1 L1,0 L0,0 Z' }, // UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB53}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L1,1 L1,0 L0,0 Z' }, // UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB54}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0.5,1 L1,1 L1,0 L0,0 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB55}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L1,1 L1,0 L0,0 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB56}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L0.5,1 L1,1 L1,0 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE
'\u{1FB57}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0,0 L0.5,0 Z' }, // UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB58}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L0,0 L1,0 Z' }, // UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB59}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0,0 L0.5,0 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB5A}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0,0 L1,0 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB5B}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L0,0 L0.5,0 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE
'\u{1FB5C}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.6667 L0,0 L1,0 L1,0.3333 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT
'\u{1FB5D}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,1 L0,1 L0,0 L1,0 L1,0.6667 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB5E}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L0,0 L1,0 L1,0.6667 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB5F}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,1 L0,1 L0,0 L1,0 L1,0.3333 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB60}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L0,0 L1,0 L1,0.3333 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB61}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,1 L0,1 L0,0 L1,0 Z' }, // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT
'\u{1FB62}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,0 L1,0 L1,0.3333 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB63}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,0.3333 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB64}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,0 L1,0 L1,0.6667 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB65}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,0.6667 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB66}': { type: CustomGlyphDefinitionType.PATH, data: 'M0.5,0 L1,0 L1,1 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT
'\u{1FB67}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0.3333 L1,0.6667 L1,0 L0,0 Z' }, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT
'\u{1FB68}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,1 L0,1 L0.5,0.5 Z' }, // UPPER AND RIGHT AND LOWER TRIANGULAR THREE QUARTERS BLOCK (missing left)
'\u{1FB69}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L0.5,0.5 L1,0 L1,1 L0,1 Z' }, // LEFT AND LOWER AND RIGHT TRIANGULAR THREE QUARTERS BLOCK (missing upper)
'\u{1FB6A}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L0.5,0.5 L1,1 L0,1 Z' }, // UPPER AND LEFT AND LOWER TRIANGULAR THREE QUARTERS BLOCK (missing right)
'\u{1FB6B}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L1,1 L0.5,0.5 L0,1 Z' }, // LEFT AND UPPER AND RIGHT TRIANGULAR THREE QUARTERS BLOCK (missing lower)
'\u{1FB6C}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L0.5,0.5 L0,1 Z' }, // LEFT TRIANGULAR ONE QUARTER BLOCK
'\u{1FB6D}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,0 L1,0 L0.5,0.5 Z' }, // UPPER TRIANGULAR ONE QUARTER BLOCK
'\u{1FB6E}': { type: CustomGlyphDefinitionType.PATH, data: 'M1,0 L1,1 L0.5,0.5 Z' }, // RIGHT TRIANGULAR ONE QUARTER BLOCK
'\u{1FB6F}': { type: CustomGlyphDefinitionType.PATH, data: 'M0,1 L1,1 L0.5,0.5 Z' }, // LOWER TRIANGULAR ONE QUARTER BLOCK
// LOWER LEFT BLOCK variants (1FB3C-1FB40) - filled region in lower-left
'\u{1FB3C}': () => `M0,${2/3} L0,1 L0.5,1 Z`, // LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB3D}': () => `M0,${2/3} L0,1 L1,1 Z`, // LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB3E}': () => `M0,${1/3} L0,1 L0.5,1 Z`, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB3F}': () => `M0,${1/3} L0,1 L1,1 Z`, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB40}': () => 'M0,0 L0,1 L0.5,1 Z', // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE
// Block elements (1FB70-1FB80)
'\u{1FB70}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 1, y: 0, w: 1, h: 8 }] }, // VERTICAL ONE EIGHTH BLOCK-2
'\u{1FB71}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 2, y: 0, w: 1, h: 8 }] }, // VERTICAL ONE EIGHTH BLOCK-3
'\u{1FB72}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 3, y: 0, w: 1, h: 8 }] }, // VERTICAL ONE EIGHTH BLOCK-4
'\u{1FB73}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 4, y: 0, w: 1, h: 8 }] }, // VERTICAL ONE EIGHTH BLOCK-5
'\u{1FB74}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 5, y: 0, w: 1, h: 8 }] }, // VERTICAL ONE EIGHTH BLOCK-6
'\u{1FB75}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 6, y: 0, w: 1, h: 8 }] }, // VERTICAL ONE EIGHTH BLOCK-7
'\u{1FB76}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 1, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-2
'\u{1FB77}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 2, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-3
'\u{1FB78}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 3, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-4
'\u{1FB79}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 4, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-5
'\u{1FB7A}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 5, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-6
'\u{1FB7B}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 6, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-7
'\u{1FB7C}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 1, h: 8 }, { x: 0, y: 7, w: 8, h: 1 }] }, // LEFT AND LOWER ONE EIGHTH BLOCK
'\u{1FB7D}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 1, h: 8 }, { x: 0, y: 0, w: 8, h: 1 }] }, // LEFT AND UPPER ONE EIGHTH BLOCK
'\u{1FB7E}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 7, y: 0, w: 1, h: 8 }, { x: 0, y: 0, w: 8, h: 1 }] }, // RIGHT AND UPPER ONE EIGHTH BLOCK
'\u{1FB7F}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 7, y: 0, w: 1, h: 8 }, { x: 0, y: 7, w: 8, h: 1 }] }, // RIGHT AND LOWER ONE EIGHTH BLOCK
'\u{1FB80}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 1 }, { x: 0, y: 7, w: 8, h: 1 }] }, // UPPER AND LOWER ONE EIGHTH BLOCK
// LOWER RIGHT BLOCK variants (1FB41-1FB4B) - filled region in lower-right
'\u{1FB41}': () => `M0,${1/3} L0.5,0 L1,0 L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB42}': () => `M0,${1/3} L1,0 L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB43}': () => `M0,${2/3} L0.5,0 L1,0 L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB44}': () => `M0,${2/3} L1,0 L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB45}': () => 'M0,1 L0.5,0 L1,0 L1,1 Z', // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE
'\u{1FB46}': () => `M0,${2/3} L1,${1/3} L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT
'\u{1FB47}': () => `M0.5,1 L1,${2/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB48}': () => `M0,1 L1,${2/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB49}': () => `M0.5,1 L1,${1/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB4A}': () => `M0,1 L1,${1/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB4B}': () => 'M0.5,1 L1,0 L1,1 Z', // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT
// Window title bar (1FB81-1FB81)
'\u{1FB81}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 1 }, { x: 0, y: 2, w: 8, h: 1 }, { x: 0, y: 4, w: 8, h: 1 }, { x: 0, y: 7, w: 8, h: 1 }] }, // HORIZONTAL ONE EIGHTH BLOCK-1358
// LOWER LEFT BLOCK variants continued (1FB4C-1FB51) - large fills with upper-right cut
'\u{1FB4C}': () => `M0.5,0 L0,0 L0,1 L1,1 L1,${1/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB4D}': () => `M0,0 L0,1 L1,1 L1,${1/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB4E}': () => `M0.5,0 L0,0 L0,1 L1,1 L1,${2/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB4F}': () => `M0,0 L0,1 L1,1 L1,${2/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB50}': () => 'M0.5,0 L0,0 L0,1 L1,1 Z', // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT
'\u{1FB51}': () => `M0,${1/3} L0,1 L1,1 L1,${2/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT
// Block elements (1FB82-1FB8B)
'\u{1FB82}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 2 }] }, // UPPER ONE QUARTER BLOCK
'\u{1FB83}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 3 }] }, // UPPER THREE EIGHTHS BLOCK
'\u{1FB84}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 5 }] }, // UPPER FIVE EIGHTHS BLOCK
'\u{1FB85}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 6 }] }, // UPPER THREE QUARTERS BLOCK
'\u{1FB86}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 0, y: 0, w: 8, h: 7 }] }, // UPPER SEVEN EIGHTHS BLOCK
'\u{1FB87}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 6, y: 0, w: 2, h: 8 }] }, // RIGHT ONE QUARTER BLOCK
'\u{1FB88}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 5, y: 0, w: 3, h: 8 }] }, // RIGHT THREE EIGHTHS B0OCK
'\u{1FB89}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 3, y: 0, w: 5, h: 8 }] }, // RIGHT FIVE EIGHTHS BL0CK
'\u{1FB8A}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 2, y: 0, w: 6, h: 8 }] }, // RIGHT THREE QUARTERS 0LOCK
'\u{1FB8B}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [{ x: 1, y: 0, w: 7, h: 8 }] }, // RIGHT SEVEN EIGHTHS B0OCK
// UPPER RIGHT BLOCK variants (1FB52-1FB56) - large fills with lower-left cut
'\u{1FB52}': () => `M0,${2/3} L0.5,1 L1,1 L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB53}': () => `M0,${2/3} L1,1 L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB54}': () => `M0,${1/3} L0.5,1 L1,1 L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE
'\u{1FB55}': () => `M0,${1/3} L1,1 L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT
'\u{1FB56}': () => 'M0,0 L0.5,1 L1,1 L1,0 Z', // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE
// UPPER LEFT BLOCK variants (1FB57-1FB61) - small to large fills in upper-left
'\u{1FB57}': () => `M0,${1/3} L0,0 L0.5,0 Z`, // UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB58}': () => `M0,${1/3} L0,0 L1,0 Z`, // UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB59}': () => `M0,${2/3} L0,0 L0.5,0 Z`, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE
'\u{1FB5A}': () => `M0,${2/3} L0,0 L1,0 Z`, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT
'\u{1FB5B}': () => 'M0,1 L0,0 L0.5,0 Z', // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE
'\u{1FB5C}': () => `M0,${2/3} L0,0 L1,0 L1,${1/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT
'\u{1FB5D}': () => `M0.5,1 L0,1 L0,0 L1,0 L1,${2/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB5E}': () => `M0,1 L0,0 L1,0 L1,${2/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB5F}': () => `M0.5,1 L0,1 L0,0 L1,0 L1,${1/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB60}': () => `M0,1 L0,0 L1,0 L1,${1/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB61}': () => 'M0.5,1 L0,1 L0,0 L1,0 Z', // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT
// UPPER RIGHT BLOCK variants continued (1FB62-1FB67) - small to medium fills in upper-right
'\u{1FB62}': () => `M0.5,0 L1,0 L1,${1/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT
'\u{1FB63}': () => `M0,0 L1,0 L1,${1/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT
'\u{1FB64}': () => `M0.5,0 L1,0 L1,${2/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT
'\u{1FB65}': () => `M0,0 L1,0 L1,${2/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT
'\u{1FB66}': () => 'M0.5,0 L1,0 L1,1 Z', // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT
'\u{1FB67}': () => `M0,${1/3} L1,${2/3} L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT
// Triangular blocks (1FB68-1FB6F)
// Three-quarter blocks: full block minus one triangular quarter pointing to center
'\u{1FB68}': () => 'M0,0 L1,0 L1,1 L0,1 L0.5,0.5 Z', // UPPER AND RIGHT AND LOWER TRIANGULAR THREE QUARTERS BLOCK (missing left)
'\u{1FB69}': () => 'M0,0 L0.5,0.5 L1,0 L1,1 L0,1 Z', // LEFT AND LOWER AND RIGHT TRIANGULAR THREE QUARTERS BLOCK (missing upper)
'\u{1FB6A}': () => 'M0,0 L1,0 L0.5,0.5 L1,1 L0,1 Z', // UPPER AND LEFT AND LOWER TRIANGULAR THREE QUARTERS BLOCK (missing right)
'\u{1FB6B}': () => 'M0,0 L1,0 L1,1 L0.5,0.5 L0,1 Z', // LEFT AND UPPER AND RIGHT TRIANGULAR THREE QUARTERS BLOCK (missing lower)
'\u{1FB6C}': () => 'M0,0 L0.5,0.5 L0,1 Z', // LEFT TRIANGULAR ONE QUARTER BLOCK
'\u{1FB6D}': () => 'M0,0 L1,0 L0.5,0.5 Z', // UPPER TRIANGULAR ONE QUARTER BLOCK
'\u{1FB6E}': () => 'M1,0 L1,1 L0.5,0.5 Z', // RIGHT TRIANGULAR ONE QUARTER BLOCK
'\u{1FB6F}': () => 'M0,1 L1,1 L0.5,0.5 Z' // LOWER TRIANGULAR ONE QUARTER BLOCK
};
/**
* Rectangular shade characters - these use medium shade pattern (50%) like 0x2592.
* Each entry is [pattern, region] where region is [x, y, width, height] in 0-1 normalized
* coordinates. Pattern is the medium shade checkerboard pattern.
*/
const mediumShadePattern: CustomGlyphPatternDefinition = [
[1, 0],
[0, 1]
];
const inverseMediumShadePattern: CustomGlyphPatternDefinition = [
[0, 1],
[1, 0]
];
export const rectangularShadeDefinitions: { [index: string]: [CustomGlyphPatternDefinition, [number, number, number, number]] | undefined } = {
'\u{1FB8C}': [mediumShadePattern, [0, 0, 0.5, 1]], // LEFT HALF MEDIUM SHADE
'\u{1FB8D}': [mediumShadePattern, [0.5, 0, 0.5, 1]], // RIGHT HALF MEDIUM SHADE
'\u{1FB8E}': [mediumShadePattern, [0, 0, 1, 0.5]], // UPPER HALF MEDIUM SHADE
'\u{1FB8F}': [mediumShadePattern, [0, 0.5, 1, 0.5]], // LOWER HALF MEDIUM SHADE
'\u{1FB90}': [inverseMediumShadePattern, [0, 0, 1, 1]] // INVERSE MEDIUM SHADE
};
/** Region defined as [x, y, width, height] in 0-1 normalized coordinates. */
type RegionDefinition = [number, number, number, number];
/** [solidRegion, shadeRegion] where shade region uses inverse medium shade pattern. */
type BlockShadeComboDefinition = [RegionDefinition, RegionDefinition];
/**
* Block + inverse shade combo characters.
*/
export const blockShadeComboDefinitions: { [index: string]: BlockShadeComboDefinition | undefined } = {
'\u{1FB91}': [[0, 0, 1, 0.5], [0, 0.5, 1, 0.5]], // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
'\u{1FB92}': [[0, 0.5, 1, 0.5], [0, 0, 1, 0.5]], // UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK
// 1FB93 is reserved
'\u{1FB94}': [[0.5, 0, 0.5, 1], [0, 0, 0.5, 1]] // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
};
/**
* Defines the repeating pattern used by special characters, the pattern is made up of a 2d array of
* pixel values to be filled (1) or not filled (0).
*/
export const patternCharacterDefinitions: { [key: string]: CustomGlyphPatternDefinition | undefined } = {
// Shade characters (0x2591-0x2593)
'░': [ // LIGHT SHADE (25%)
[1, 0],
[0, 0]
],
'▒': [ // MEDIUM SHADE (50%)
// Rectangular shade characters (1FB8C-1FB94)
'\u{1FB8C}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [[ // LEFT HALF MEDIUM SHADE
[1, 0],
[0, 1]
],
'▓': [ // DARK SHADE (75%)
[1, 1],
], [0, 0, 0.5, 1]] },
'\u{1FB8D}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [[ // RIGHT HALF MEDIUM SHADE
[1, 0],
[0, 1]
], [0.5, 0, 0.5, 1]] },
'\u{1FB8E}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [[ // UPPER HALF MEDIUM SHADE
[1, 0],
[0, 1]
], [0, 0, 1, 0.5]] },
'\u{1FB8F}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [[ // LOWER HALF MEDIUM SHADE
[1, 0],
[0, 1]
], [0, 0.5, 1, 0.5]] },
'\u{1FB90}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [[ // INVERSE MEDIUM SHADE
[0, 1],
[1, 0]
]
], [0, 0, 1, 1]] },
'\u{1FB91}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE
pattern: [[
[0, 1],
[1, 0]
], [0, 0.5, 1, 0.5]],
vectors: [{ x: 0, y: 0, w: 8, h: 4 }]
} },
'\u{1FB92}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { // UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK
pattern: [[
[0, 1],
[1, 0]
], [0, 0, 1, 0.5]],
vectors: [{ x: 0, y: 4, w: 8, h: 4 }]
} },
// 1FB93 is <reserved>
'\u{1FB94}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK
pattern: [[
[0, 1],
[1, 0]
], [0, 0, 0.5, 1]],
vectors: [{ x: 4, y: 0, w: 4, h: 8 }]
} },
// Fill characters (1FB95-1FB97)
'\u{1FB95}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [ // CHECKER BOARD FILL
{ x: 0, y: 0, w: 2, h: 2 }, { x: 4, y: 0, w: 2, h: 2 },
{ x: 2, y: 2, w: 2, h: 2 }, { x: 6, y: 2, w: 2, h: 2 },
{ x: 0, y: 4, w: 2, h: 2 }, { x: 4, y: 4, w: 2, h: 2 },
{ x: 2, y: 6, w: 2, h: 2 }, { x: 6, y: 6, w: 2, h: 2 }
] },
'\u{1FB96}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [ // INVERSE CHECKER BOARD FILL
{ x: 2, y: 0, w: 2, h: 2 }, { x: 6, y: 0, w: 2, h: 2 },
{ x: 0, y: 2, w: 2, h: 2 }, { x: 4, y: 2, w: 2, h: 2 },
{ x: 2, y: 4, w: 2, h: 2 }, { x: 6, y: 4, w: 2, h: 2 },
{ x: 0, y: 6, w: 2, h: 2 }, { x: 4, y: 6, w: 2, h: 2 }
] },
'\u{1FB97}': { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: [ // HEAVY HORIZONTAL FILL (upper middle and lower one quarter block)
{ x: 0, y: 2, w: 8, h: 2 }, { x: 0, y: 6, w: 8, h: 2 }
] },
// #endregion
};
/**
* Generates a drawing function for sextant characters. Sextants are a 2x3 grid where each cell
* can be on or off.
* @param pattern A 6-bit pattern where bit 0 = top-left, bit 1 = top-right, bit 2 = middle-left,
* bit 3 = middle-right, bit 4 = bottom-left, bit 5 = bottom-right
*/
function sextant(pattern: number): { type: CustomGlyphDefinitionType.PATH_FUNCTION, data: CustomGlyphPathDrawFunctionDefinition } {
return {
type: CustomGlyphDefinitionType.PATH_FUNCTION,
data: () => {
// Sextant grid: 2 columns, 3 rows
// Row heights in 8ths: top=3, middle=2, bottom=3
// Column widths: left=4, right=4
const rects: string[] = [];
const colW = 0.5; // Each column is half width
const rowH = [3 / 8, 2 / 8, 3 / 8]; // Row heights as fractions
const rowY = [0, 3 / 8, 5 / 8]; // Row Y positions
for (let row = 0; row < 3; row++) {
const leftBit = (pattern >> (row * 2)) & 1;
const rightBit = (pattern >> (row * 2 + 1)) & 1;
if (leftBit && rightBit) {
// Full row
rects.push(`M0,${rowY[row]} L1,${rowY[row]} L1,${rowY[row] + rowH[row]} L0,${rowY[row] + rowH[row]} Z`);
} else if (leftBit) {
rects.push(`M0,${rowY[row]} L${colW},${rowY[row]} L${colW},${rowY[row] + rowH[row]} L0,${rowY[row] + rowH[row]} Z`);
} else if (rightBit) {
rects.push(`M${colW},${rowY[row]} L1,${rowY[row]} L1,${rowY[row] + rowH[row]} L${colW},${rowY[row] + rowH[row]} Z`);
}
}
return rects.join(' ');
}
};
}
const enum Shapes {
/** │ */ TOP_TO_BOTTOM = 'M.5,0 L.5,1',
/** ─ */ LEFT_TO_RIGHT = 'M0,.5 L1,.5',
@@ -385,205 +561,3 @@ const enum FontWeight {
NORMAL = 1,
BOLD = 3
}
/**
* This contains the definitions of all box drawing characters in the format of SVG paths (ie. the
* svg d attribute).
*/
export const boxDrawingDefinitions: { [character: string]: { [fontWeight: number]: string | CustomGlyphDrawFunctionDefinition } | undefined } = {
// U+2500-U+257F
// https://www.unicode.org/charts/PDF/U2500.pdf
// Uniform normal and bold
'─': { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT },
'━': { [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT },
'│': { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM },
'┃': { [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM },
'┌': { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM },
'┏': { [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM },
'┐': { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM },
'┓': { [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM },
'└': { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT },
'┗': { [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT },
'┘': { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT },
'┛': { [FontWeight.BOLD]: Shapes.TOP_TO_LEFT },
'├': { [FontWeight.NORMAL]: Shapes.T_RIGHT },
'┣': { [FontWeight.BOLD]: Shapes.T_RIGHT },
'┤': { [FontWeight.NORMAL]: Shapes.T_LEFT },
'┫': { [FontWeight.BOLD]: Shapes.T_LEFT },
'┬': { [FontWeight.NORMAL]: Shapes.T_BOTTOM },
'┳': { [FontWeight.BOLD]: Shapes.T_BOTTOM },
'┴': { [FontWeight.NORMAL]: Shapes.T_TOP },
'┻': { [FontWeight.BOLD]: Shapes.T_TOP },
'┼': { [FontWeight.NORMAL]: Shapes.CROSS },
'╋': { [FontWeight.BOLD]: Shapes.CROSS },
'╴': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT },
'╸': { [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'╵': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP },
'╹': { [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'╶': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT },
'╺': { [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'╷': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM },
'╻': { [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
// Double border
'═': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` },
'║': { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` },
'╒': { [FontWeight.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 - yp} L1,${.5 - yp} M.5,${.5 + yp} L1,${.5 + yp}` },
'╓': { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},1 L${.5 - xp},.5 L1,.5 M${.5 + xp},.5 L${.5 + xp},1` },
'╔': { [FontWeight.NORMAL]: (xp, yp) => `M1,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1` },
'╕': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L.5,${.5 - yp} L.5,1 M0,${.5 + yp} L.5,${.5 + yp}` },
'╖': { [FontWeight.NORMAL]: (xp, yp) => `M${.5 + xp},1 L${.5 + xp},.5 L0,.5 M${.5 - xp},.5 L${.5 - xp},1` },
'╗': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M0,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},1` },
'╘': { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 + yp} L1,${.5 + yp} M.5,${.5 - yp} L1,${.5 - yp}` },
'╙': { [FontWeight.NORMAL]: (xp, yp) => `M1,.5 L${.5 - xp},.5 L${.5 - xp},0 M${.5 + xp},.5 L${.5 + xp},0` },
'╚': { [FontWeight.NORMAL]: (xp, yp) => `M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0 M1,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},0` },
'╛': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L.5,${.5 + yp} L.5,0 M0,${.5 - yp} L.5,${.5 - yp}` },
'╜': { [FontWeight.NORMAL]: (xp, yp) => `M0,.5 L${.5 + xp},.5 L${.5 + xp},0 M${.5 - xp},.5 L${.5 - xp},0` },
'╝': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0 M0,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},0` },
'╞': { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M.5,${.5 - yp} L1,${.5 - yp} M.5,${.5 + yp} L1,${.5 + yp}` },
'╟': { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1 M${.5 + xp},.5 L1,.5` },
'╠': { [FontWeight.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1 M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0` },
'╡': { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M0,${.5 - yp} L.5,${.5 - yp} M0,${.5 + yp} L.5,${.5 + yp}` },
'╢': { [FontWeight.NORMAL]: (xp, yp) => `M0,.5 L${.5 - xp},.5 M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` },
'╣': { [FontWeight.NORMAL]: (xp, yp) => `M${.5 + xp},0 L${.5 + xp},1 M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0` },
'╤': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp} M.5,${.5 + yp} L.5,1` },
'╥': { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},.5 L${.5 - xp},1 M${.5 + xp},.5 L${.5 + xp},1` },
'╦': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1` },
'╧': { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - yp} M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` },
'╨': { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},.5 L${.5 - xp},0 M${.5 + xp},.5 L${.5 + xp},0` },
'╩': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L1,${.5 + yp} M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0 M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0` },
'╪': { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` },
'╫': { [FontWeight.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` },
'╬': { [FontWeight.NORMAL]: (xp, yp) => `M0,${.5 + yp} L${.5 - xp},${.5 + yp} L${.5 - xp},1 M1,${.5 + yp} L${.5 + xp},${.5 + yp} L${.5 + xp},1 M0,${.5 - yp} L${.5 - xp},${.5 - yp} L${.5 - xp},0 M1,${.5 - yp} L${.5 + xp},${.5 - yp} L${.5 + xp},0` },
// Diagonal
'╱': { [FontWeight.NORMAL]: 'M1,0 L0,1' },
'╲': { [FontWeight.NORMAL]: 'M0,0 L1,1' },
'╳': { [FontWeight.NORMAL]: 'M1,0 L0,1 M0,0 L1,1' },
// Mixed weight
'╼': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'╽': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'╾': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'╿': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'┍': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'┎': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'┑': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'┒': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'┕': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'┖': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'┙': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'┚': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'┝': { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'┞': { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'┟': { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'┠': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM },
'┡': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT },
'┢': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM },
'┥': { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'┦': { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'┧': { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'┨': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM },
'┩': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_LEFT },
'┪': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM },
'┭': { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'┮': { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'┯': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT },
'┰': { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'┱': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM },
'┲': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM },
'┵': { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'┶': { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'┷': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT },
'┸': { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'┹': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: Shapes.TOP_TO_LEFT },
'┺': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT },
'┽': { [FontWeight.NORMAL]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_RIGHT}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_LEFT },
'┾': { [FontWeight.NORMAL]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_LEFT}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_RIGHT },
'┿': { [FontWeight.NORMAL]: Shapes.TOP_TO_BOTTOM, [FontWeight.BOLD]: Shapes.LEFT_TO_RIGHT },
'╀': { [FontWeight.NORMAL]: `${Shapes.LEFT_TO_RIGHT} ${Shapes.MIDDLE_TO_BOTTOM}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_TOP },
'╁': { [FontWeight.NORMAL]: `${Shapes.MIDDLE_TO_TOP} ${Shapes.LEFT_TO_RIGHT}`, [FontWeight.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
'╂': { [FontWeight.NORMAL]: Shapes.LEFT_TO_RIGHT, [FontWeight.BOLD]: Shapes.TOP_TO_BOTTOM },
'╃': { [FontWeight.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_LEFT },
'╄': { [FontWeight.NORMAL]: Shapes.LEFT_TO_BOTTOM, [FontWeight.BOLD]: Shapes.TOP_TO_RIGHT },
'╅': { [FontWeight.NORMAL]: Shapes.TOP_TO_RIGHT, [FontWeight.BOLD]: Shapes.LEFT_TO_BOTTOM },
'╆': { [FontWeight.NORMAL]: Shapes.TOP_TO_LEFT, [FontWeight.BOLD]: Shapes.RIGHT_TO_BOTTOM },
'╇': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [FontWeight.BOLD]: `${Shapes.MIDDLE_TO_TOP} ${Shapes.LEFT_TO_RIGHT}` },
'╈': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_TOP, [FontWeight.BOLD]: `${Shapes.LEFT_TO_RIGHT} ${Shapes.MIDDLE_TO_BOTTOM}` },
'╉': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [FontWeight.BOLD]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_LEFT}` },
'╊': { [FontWeight.NORMAL]: Shapes.MIDDLE_TO_LEFT, [FontWeight.BOLD]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_RIGHT}` },
// Dashed
'╌': { [FontWeight.NORMAL]: Shapes.TWO_DASHES_HORIZONTAL },
'╍': { [FontWeight.BOLD]: Shapes.TWO_DASHES_HORIZONTAL },
'┄': { [FontWeight.NORMAL]: Shapes.THREE_DASHES_HORIZONTAL },
'┅': { [FontWeight.BOLD]: Shapes.THREE_DASHES_HORIZONTAL },
'┈': { [FontWeight.NORMAL]: Shapes.FOUR_DASHES_HORIZONTAL },
'┉': { [FontWeight.BOLD]: Shapes.FOUR_DASHES_HORIZONTAL },
'╎': { [FontWeight.NORMAL]: Shapes.TWO_DASHES_VERTICAL },
'╏': { [FontWeight.BOLD]: Shapes.TWO_DASHES_VERTICAL },
'┆': { [FontWeight.NORMAL]: Shapes.THREE_DASHES_VERTICAL },
'┇': { [FontWeight.BOLD]: Shapes.THREE_DASHES_VERTICAL },
'┊': { [FontWeight.NORMAL]: Shapes.FOUR_DASHES_VERTICAL },
'┋': { [FontWeight.BOLD]: Shapes.FOUR_DASHES_VERTICAL },
// Curved
'╭': { [FontWeight.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5` },
'╮': { [FontWeight.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5` },
'╯': { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5` },
'╰': { [FontWeight.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5` }
};
/**
* This contains the definitions of the primarily used box drawing characters as vector shapes. The
* reason these characters are defined specially is to avoid common problems if a user's font has
* not been patched with powerline characters and also to get pixel perfect rendering as rendering
* issues can occur around AA/SPAA.
*
* The line variants draw beyond the cell and get clipped to ensure the end of the line is not
* visible.
*
* Original symbols defined in https://github.com/powerline/fontpatcher
*/
export const powerlineDefinitions: { [index: string]: ICustomGlyphVectorShape } = {
// Git branch
'\u{E0A0}': { d: 'M.3,1 L.03,1 L.03,.88 C.03,.82,.06,.78,.11,.73 C.15,.7,.2,.68,.28,.65 L.43,.6 C.49,.58,.53,.56,.56,.53 C.59,.5,.6,.47,.6,.43 L.6,.27 L.4,.27 L.69,.1 L.98,.27 L.78,.27 L.78,.46 C.78,.52,.76,.56,.72,.61 C.68,.66,.63,.67,.56,.7 L.48,.72 C.42,.74,.38,.76,.35,.78 C.32,.8,.31,.84,.31,.88 L.31,1 M.3,.5 L.03,.59 L.03,.09 L.3,.09 L.3,.655', type: CustomGlyphVectorType.FILL },
// L N
'\u{E0A1}': { d: 'M.7,.4 L.7,.47 L.2,.47 L.2,.03 L.355,.03 L.355,.4 L.705,.4 M.7,.5 L.86,.5 L.86,.95 L.69,.95 L.44,.66 L.46,.86 L.46,.95 L.3,.95 L.3,.49 L.46,.49 L.71,.78 L.69,.565 L.69,.5', type: CustomGlyphVectorType.FILL },
// Lock
'\u{E0A2}': { d: 'M.25,.94 C.16,.94,.11,.92,.11,.87 L.11,.53 C.11,.48,.15,.455,.23,.45 L.23,.3 C.23,.25,.26,.22,.31,.19 C.36,.16,.43,.15,.51,.15 C.59,.15,.66,.16,.71,.19 C.77,.22,.79,.26,.79,.3 L.79,.45 C.87,.45,.91,.48,.91,.53 L.91,.87 C.91,.92,.86,.94,.77,.94 L.24,.94 M.53,.2 C.49,.2,.45,.21,.42,.23 C.39,.25,.38,.27,.38,.3 L.38,.45 L.68,.45 L.68,.3 C.68,.27,.67,.25,.64,.23 C.61,.21,.58,.2,.53,.2 M.58,.82 L.58,.66 C.63,.65,.65,.63,.65,.6 C.65,.58,.64,.57,.61,.56 C.58,.55,.56,.54,.52,.54 C.48,.54,.46,.55,.43,.56 C.4,.57,.39,.59,.39,.6 C.39,.63,.41,.64,.46,.66 L.46,.82 L.57,.82', type: CustomGlyphVectorType.FILL },
// Right triangle solid
'\u{E0B0}': { d: 'M0,0 L1,.5 L0,1', type: CustomGlyphVectorType.FILL, rightPadding: 2 },
// Right triangle line
'\u{E0B1}': { d: 'M-1,-.5 L1,.5 L-1,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 },
// Left triangle solid
'\u{E0B2}': { d: 'M1,0 L0,.5 L1,1', type: CustomGlyphVectorType.FILL, leftPadding: 2 },
// Left triangle line
'\u{E0B3}': { d: 'M2,-.5 L0,.5 L2,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 },
// Right semi-circle solid
'\u{E0B4}': { d: 'M0,0 L0,1 C0.552,1,1,0.776,1,.5 C1,0.224,0.552,0,0,0', type: CustomGlyphVectorType.FILL, rightPadding: 1 },
// Right semi-circle line
'\u{E0B5}': { d: 'M.2,1 C.422,1,.8,.826,.78,.5 C.8,.174,0.422,0,.2,0', type: CustomGlyphVectorType.STROKE, rightPadding: 1 },
// Left semi-circle solid
'\u{E0B6}': { d: 'M1,0 L1,1 C0.448,1,0,0.776,0,.5 C0,0.224,0.448,0,1,0', type: CustomGlyphVectorType.FILL, leftPadding: 1 },
// Left semi-circle line
'\u{E0B7}': { d: 'M.8,1 C0.578,1,0.2,.826,.22,.5 C0.2,0.174,0.578,0,0.8,0', type: CustomGlyphVectorType.STROKE, leftPadding: 1 },
// Lower left triangle
'\u{E0B8}': { d: 'M-.5,-.5 L1.5,1.5 L-.5,1.5', type: CustomGlyphVectorType.FILL },
// Backslash separator
'\u{E0B9}': { d: 'M-.5,-.5 L1.5,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 },
// Lower right triangle
'\u{E0BA}': { d: 'M1.5,-.5 L-.5,1.5 L1.5,1.5', type: CustomGlyphVectorType.FILL },
// Upper left triangle
'\u{E0BC}': { d: 'M1.5,-.5 L-.5,1.5 L-.5,-.5', type: CustomGlyphVectorType.FILL },
// Forward slash separator
'\u{E0BD}': { d: 'M1.5,-.5 L-.5,1.5', type: CustomGlyphVectorType.STROKE, leftPadding: 1, rightPadding: 1 },
// Upper right triangle
'\u{E0BE}': { d: 'M-.5,-.5 L1.5,1.5 L1.5,-.5', type: CustomGlyphVectorType.FILL }
};
// Forward slash separator redundant
powerlineDefinitions['\u{E0BB}'] = powerlineDefinitions['\u{E0BD}'];
// Backslash separator redundant
powerlineDefinitions['\u{E0BF}'] = powerlineDefinitions['\u{E0B9}'];
@@ -4,8 +4,8 @@
*/
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
import { blockElementDefinitions, blockShadeComboDefinitions, boxDrawingDefinitions, patternCharacterDefinitions, powerlineDefinitions, rectangularShadeDefinitions, symbolsForLegacyComputingDefinitions } from 'customGlyphs/CustomGlyphDefinitions';
import { CustomGlyphVectorType, type CustomGlyphDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types';
import { customGlyphDefinitions } from './CustomGlyphDefinitions';
import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type CustomGlyphRegionDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from './Types';
/**
* Try drawing a custom block element or box drawing character, returning whether it was
@@ -21,46 +21,33 @@ export function tryDrawCustomGlyph(
fontSize: number,
devicePixelRatio: number
): boolean {
const blockElementDefinition = blockElementDefinitions[c];
if (blockElementDefinition) {
drawBlockVectorChar(ctx, blockElementDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const symbolsForLegacyComputingDefinition = symbolsForLegacyComputingDefinitions[c];
if (symbolsForLegacyComputingDefinition) {
drawPathDefinitionCharacter(ctx, symbolsForLegacyComputingDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const rectangularShadeDefinition = rectangularShadeDefinitions[c];
if (rectangularShadeDefinition) {
drawRectangularShadeChar(ctx, rectangularShadeDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const blockShadeComboDefinition = blockShadeComboDefinitions[c];
if (blockShadeComboDefinition) {
drawBlockShadeComboChar(ctx, blockShadeComboDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const patternDefinition = patternCharacterDefinitions[c];
if (patternDefinition) {
drawPatternChar(ctx, patternDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
}
const boxDrawingDefinition = boxDrawingDefinitions[c];
if (boxDrawingDefinition) {
drawBoxDrawingChar(ctx, boxDrawingDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio);
return true;
}
const powerlineDefinition = powerlineDefinitions[c];
if (powerlineDefinition) {
drawPowerlineChar(ctx, powerlineDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio);
return true;
const unifiedCharDefinition = customGlyphDefinitions[c];
if (unifiedCharDefinition) {
switch (unifiedCharDefinition.type) {
case CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR:
drawBlockVectorChar(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
case CustomGlyphDefinitionType.BLOCK_PATTERN:
drawPatternChar(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
case CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION:
drawBlockPatternWithRegion(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
case CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR:
drawBlockPatternWithRegion(ctx, unifiedCharDefinition.data.pattern, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
drawBlockVectorChar(ctx, unifiedCharDefinition.data.vectors, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
case CustomGlyphDefinitionType.PATH_FUNCTION:
case CustomGlyphDefinitionType.PATH:
drawPathDefinitionCharacter(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
return true;
case CustomGlyphDefinitionType.VECTOR_SHAPE:
drawVectorShape(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio);
return true;
case CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT:
drawPathDefinitionCharacterWithWeight(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio);
return true;
}
}
return false;
@@ -89,13 +76,13 @@ function drawBlockVectorChar(
function drawPathDefinitionCharacter(
ctx: CanvasRenderingContext2D,
charDefinition: CustomGlyphDrawFunctionDefinition,
charDefinition: CustomGlyphPathDrawFunctionDefinition | string,
xOffset: number,
yOffset: number,
deviceCellWidth: number,
deviceCellHeight: number
): void {
const instructions = charDefinition(0, 0);
const instructions = typeof charDefinition === 'string' ? charDefinition : charDefinition(0, 0);
ctx.beginPath();
for (const instruction of instructions.split(' ')) {
const type = instruction[0];
@@ -186,9 +173,9 @@ function drawPatternChar(
* Draws rectangular shade characters - medium shade pattern clipped to a region.
* Uses a checkerboard pattern that shifts 1px each row (same as medium shade U+2592).
*/
function drawRectangularShadeChar(
function drawBlockPatternWithRegion(
ctx: CanvasRenderingContext2D,
definition: [CustomGlyphPatternDefinition, [number, number, number, number]],
definition: [pattern: CustomGlyphPatternDefinition, region: CustomGlyphRegionDefinition],
xOffset: number,
yOffset: number,
deviceCellWidth: number,
@@ -216,45 +203,6 @@ function drawRectangularShadeChar(
ctx.restore();
}
/**
* Draws block + inverse shade combo characters.
* Fills the solid region completely, then draws inverse medium shade in the shade region.
*/
function drawBlockShadeComboChar(
ctx: CanvasRenderingContext2D,
regions: [[number, number, number, number], [number, number, number, number]],
xOffset: number,
yOffset: number,
deviceCellWidth: number,
deviceCellHeight: number
): void {
const [solidRegion, shadeRegion] = regions;
// Draw solid block region
const solidX = Math.round(xOffset + solidRegion[0] * deviceCellWidth);
const solidY = Math.round(yOffset + solidRegion[1] * deviceCellHeight);
const solidW = Math.round(solidRegion[2] * deviceCellWidth);
const solidH = Math.round(solidRegion[3] * deviceCellHeight);
ctx.fillRect(solidX, solidY, solidW, solidH);
// Draw inverse medium shade region
const shadeX = Math.round(xOffset + shadeRegion[0] * deviceCellWidth);
const shadeY = Math.round(yOffset + shadeRegion[1] * deviceCellHeight);
const shadeW = Math.round(shadeRegion[2] * deviceCellWidth);
const shadeH = Math.round(shadeRegion[3] * deviceCellHeight);
for (let py = 0; py < shadeH; py++) {
const absY = shadeY + py - yOffset;
for (let px = 0; px < shadeW; px++) {
const absX = shadeX + px - xOffset;
// Inverse checkerboard: fill at (x + y) % 2 === 1
if (((absX + absY) % 2) === 1) {
ctx.fillRect(shadeX + px, shadeY + py, 1, 1);
}
}
}
}
/**
* Draws the following box drawing characters by mapping a subset of SVG d attribute instructions to
* canvas draw calls.
@@ -295,7 +243,7 @@ function drawBlockShadeComboChar(
*
* Source: https://www.w3.org/2001/06/utf-8-test/UTF-8-demo.html
*/
function drawBoxDrawingChar(
function drawPathDefinitionCharacterWithWeight(
ctx: CanvasRenderingContext2D,
charDefinition: { [fontWeight: number]: string | ((xp: number, yp: number) => string) },
xOffset: number,
@@ -334,7 +282,7 @@ function drawBoxDrawingChar(
}
}
function drawPowerlineChar(
function drawVectorShape(
ctx: CanvasRenderingContext2D,
charDefinition: ICustomGlyphVectorShape,
xOffset: number,
+27 -1
View File
@@ -14,7 +14,7 @@ export interface ICustomGlyphSolidOctantBlockVector {
* @param xp The percentage of 15% of the x axis.
* @param yp The percentage of 15% of the x axis on the y axis.
*/
export type CustomGlyphDrawFunctionDefinition = (xp: number, yp: number) => string;
export type CustomGlyphPathDrawFunctionDefinition = (xp: number, yp: number) => string;
export interface ICustomGlyphVectorShape {
d: string;
@@ -29,3 +29,29 @@ export const enum CustomGlyphVectorType {
}
export type CustomGlyphPatternDefinition = number[][];
export const enum CustomGlyphDefinitionType {
SOLID_OCTANT_BLOCK_VECTOR,
BLOCK_PATTERN,
BLOCK_PATTERN_WITH_REGION,
BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR,
PATH_FUNCTION,
PATH_FUNCTION_WITH_WEIGHT,
PATH,
VECTOR_SHAPE,
}
export type CustomGlyphRegionDefinition = [x: number, y: number, w: number, h: number];
export type CustomGlyphCharacterDefinition = (
{ type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: ICustomGlyphSolidOctantBlockVector[] } |
{ type: CustomGlyphDefinitionType.BLOCK_PATTERN, data: CustomGlyphPatternDefinition } |
{ type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [pattern: CustomGlyphPatternDefinition, region: CustomGlyphRegionDefinition] } |
// TODO: Consolidate these, draws should be possible via regions/clipping instead of special
// casing
{ type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { pattern: [pattern: CustomGlyphPatternDefinition, region: CustomGlyphRegionDefinition], vectors: ICustomGlyphSolidOctantBlockVector[] } } |
{ type: CustomGlyphDefinitionType.PATH_FUNCTION, data: CustomGlyphPathDrawFunctionDefinition } |
{ type: CustomGlyphDefinitionType.PATH_FUNCTION_WITH_WEIGHT, data: { [fontWeight: number]: string | CustomGlyphPathDrawFunctionDefinition } } |
{ type: CustomGlyphDefinitionType.PATH, data: string } |
{ type: CustomGlyphDefinitionType.VECTOR_SHAPE, data: ICustomGlyphVectorShape }
);
+36 -5
View File
@@ -234,8 +234,8 @@ if (document.location.pathname === '/test') {
document.getElementById('create-new-window').addEventListener('click', createNewWindowButtonHandler);
document.getElementById('serialize').addEventListener('click', serializeButtonHandler);
document.getElementById('htmlserialize').addEventListener('click', htmlSerializeButtonHandler);
document.getElementById('custom-glyph').addEventListener('click', writeCustomGlyphHandler);
document.getElementById('symbols-for-legacy-computing').addEventListener('click', writeSymbolsForLegacyComputing);
document.getElementById('custom-glyph-alignment').addEventListener('click', customGlyphAlignmentHandler);
document.getElementById('custom-glyph-ranges').addEventListener('click', customGlyphRangesHandler);
document.getElementById('load-test').addEventListener('click', loadTest);
document.getElementById('load-test-long-lines').addEventListener('click', loadTestLongLines);
document.getElementById('print-cjk').addEventListener('click', addCjk);
@@ -786,7 +786,7 @@ function styleAtlasPage(e: HTMLCanvasElement): void {
e.style.height = `${e.height / window.devicePixelRatio}px`;
}
function writeCustomGlyphHandler(): void {
function customGlyphAlignmentHandler(): void {
term.write('\n\r');
term.write('\n\r');
term.write('Box styles: ┎┰┒┍┯┑╓╥╖╒╤╕ ┏┳┓┌┲┓┌┬┐┏┱┐\n\r');
@@ -839,10 +839,41 @@ function writeCustomGlyphHandler(): void {
window.scrollTo(0, 0);
}
function writeSymbolsForLegacyComputing(): void {
function customGlyphRangesHandler(): void {
// Box Drawing
// 2500-257F
// https://www.unicode.org/charts/PDF/U2500.pdf
writeUnicodeTable(term, 'Box Drawing', 0x2500, 0x257F, [
['Light and heavy solid lines', 0x2500, 0x2503],
['Light and heavy dashed lines', 0x2504, 0x250B],
['Light and heavy line box components', 0x250C, 0x254B],
['Light and heavy dashed lines', 0x254C, 0x254F],
['Double lines', 0x2550, 0x2551],
['Light and double line box components', 0x2552, 0x256C],
['Character cell arcs', 0x256D, 0x2570],
['Character cell diagonals', 0x2571, 0x2573],
['Light and heavy half lines', 0x2574, 0x257B],
['Mixed light and heavy lines', 0x257C, 0x257F],
]);
// Box Elements
// 2580-259F
// https://www.unicode.org/charts/PDF/U2580.pdf
writeUnicodeTable(term, 'Box Elements', 0x2580, 0x259F, [
['Block elements', 0x2580, 0x2590],
['Shade characters', 0x2591, 0x2593],
['Block elements', 0x2594, 0x2595],
['Terminal graphic characters', 0x2596, 0x259F],
]);
// Powerline Symbols
// Range: E0A0–E0BF
// https://github.com/ryanoasis/nerd-fonts
writeUnicodeTable(term, 'Powerline Symbols', 0xE0A0, 0xE0BF, [
['Powerline Symbols', 0xE0A0, 0xE0B3],
['Powerline Extra Symbols', 0xE0B4, 0xE0BF],
]);
// Symbols for Legacy Computing
// Range: 1FB00–1FBFF
// Source: The Unicode Standard, Version 17.0 https://www.unicode.org/charts/PDF/U1FB00.pdf
// https://www.unicode.org/charts/PDF/U1FB00.pdf
writeUnicodeTable(term, 'Symbols for Legacy Computing', 0x1FB00, 0x1FBFF, [
['Block mosaic terminal graphic characters (Sextants)', 0x1FB00, 0x1FB3B],
['Smooth mosaic terminal graphic characters', 0x1FB3C, 0x1FB6F],
+2 -2
View File
@@ -92,8 +92,8 @@
<dd><button id="print-cjk-sgr" title="Prints the 20977 characters from the CJK Unified Ideographs unicode block with randomized SGR attributes">CJK Unified Ideographs (random SGR)</button></dd>
<dt>Styles</dt>
<dd><button id="custom-glyph" title="Write custom box drawing and block element characters to the terminal">Test custom glyphs</button></dd>
<dd><button id="symbols-for-legacy-computing" title="Write this unicode range to the terminal">Print Symbols for Legacy Computing (Range: 1FB00–1FBFF)</button></dd>
<dd><button id="custom-glyph-alignment" title="Write custom glyph alignment tests to the terminal">Custom glyph alignment test</button></dd>
<dd><button id="custom-glyph-ranges" title="Write custom glyph unicode range to the terminal">Custom glyph ranges</button></dd>
<dd><button id="powerline-symbol-test" title="Write powerline symbol characters to the terminal (\ue0a0+)">Powerline symbol test</button></dd>
<dd><button id="underline-test" title="Write text with Kitty's extended underline sequences">Underline test</button></dd>
<dd><button id="sgr-test" title="Write text with SGR attribute">SGR test</button></dd>
+11 -10
View File
@@ -6,7 +6,7 @@ export type UnicodeRangeDefinition = [
label: string,
start: number,
end: number,
]
];
/**
* Write a unicode table to the terminal from start to end code points.
@@ -14,29 +14,29 @@ export type UnicodeRangeDefinition = [
* Beware: Vibe coding ahead
*/
export function writeUnicodeTable(term: Terminal, name: string, start: number, end: number, definitions?: UnicodeRangeDefinition[]): void {
function bold(text: string) {
function bold(text: string): string {
return '\x1b[1m' + text + '\x1b[22m';
}
function faint(text: string) {
function faint(text: string): string {
return '\x1b[2m' + text + '\x1b[22m';
}
// Rotating colors: Red, Green, Yellow, Blue, Magenta, Cyan
const colors = [31, 32, 33, 34, 35, 36];
function color(text: string, colorIndex: number) {
function color(text: string, colorIndex: number): string {
const c = colors[colorIndex % colors.length];
return '\x1b[' + c + 'm' + text + '\x1b[39m';
}
term.write('\n\r');
term.write('\n\r');
term.write(bold(name) + '\n\r');
term.write(`${bold(name)} (${start.toString(16).toUpperCase()}-${end.toString(16).toUpperCase()})\n\r`);
term.write('\n\r');
term.write(bold(' 0 1 2 3 4 5 6 7 8 9 A B C D E F') + '\n\r');
const startRow = Math.floor(start / 16);
// Build a map of codepoint -> label and colorIndex for start positions
const labelStartMap = new Map<number, { label: string; colorIndex: number }>();
const labelStartMap = new Map<number, { label: string, colorIndex: number }>();
// Build a map of codepoint -> colorIndex for all codepoints in each range
const codePointColorMap = new Map<number, number>();
let lastDefinitionEnd = start; // Track the last definition's end to stop printing there
@@ -59,7 +59,7 @@ export function writeUnicodeTable(term: Terminal, name: string, start: number, e
for (let row = startRow; row <= endRow; row++) {
// Collect labels for this row with their column positions and color
const rowLabels: { col: number; label: string; colorIndex: number }[] = [];
const rowLabels: { col: number, label: string, colorIndex: number }[] = [];
for (let col = 0; col < 16; col++) {
const codePoint = row * 16 + col;
const labelInfo = labelStartMap.get(codePoint);
@@ -71,7 +71,8 @@ export function writeUnicodeTable(term: Terminal, name: string, start: number, e
// If labels exist and don't start at column 0, first output chars before first label
if (rowLabels.length > 0 && rowLabels[0].col > 0) {
const rowHex = row.toString(16).toUpperCase();
term.write(bold('U+' + rowHex + 'x '));
const rowPrefix = `U+${rowHex}x`.padEnd(8, ' ');
term.write(bold(rowPrefix));
for (let col = 0; col < rowLabels[0].col; col++) {
const codePoint = row * 16 + col;
term.write(' ');
@@ -93,7 +94,7 @@ export function writeUnicodeTable(term: Terminal, name: string, start: number, e
if (rowLabels.length > 0) {
// Render label lines from top to bottom (first label on top, last label closest to row)
for (let i = 0; i < rowLabels.length; i++) {
const prefix = ' '; // Same width as "U+1FB0x "
const prefix = ' '.repeat(8); // Same width as "U+1FB0x "
let line = '';
let visualLen = 0; // Track visual length separately from string length (escape codes don't count)
for (let col = 0; col < 16; col++) {
@@ -117,7 +118,7 @@ export function writeUnicodeTable(term: Terminal, name: string, start: number, e
// Row prefix (e.g., "U+1FB0x ")
const rowHex = row.toString(16).toUpperCase();
const rowPrefix = 'U+' + rowHex + 'x ';
const rowPrefix = `U+${rowHex}x`.padEnd(8, ' ');
const isSecondPrint = rowLabels.length > 0 && rowLabels[0].col > 0;
term.write(isSecondPrint ? ' '.repeat(rowPrefix.length) : bold(rowPrefix));