diff --git a/.eslintrc.json b/.eslintrc.json index acd85af6..70d89032 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -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" diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index aa3ef321..ccfe43bb 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -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 + '\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}']; diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts index e84883dd..3d59f710 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts @@ -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, diff --git a/addons/addon-webgl/src/customGlyphs/Types.ts b/addons/addon-webgl/src/customGlyphs/Types.ts index d4aebc73..bfe5155a 100644 --- a/addons/addon-webgl/src/customGlyphs/Types.ts +++ b/addons/addon-webgl/src/customGlyphs/Types.ts @@ -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 } +); diff --git a/demo/client.ts b/demo/client.ts index 994b9eda..6643f6be 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -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], diff --git a/demo/index.html b/demo/index.html index 4f0a6d0c..99ed7e9f 100644 --- a/demo/index.html +++ b/demo/index.html @@ -92,8 +92,8 @@
Styles
-
-
+
+
diff --git a/demo/unicodeTable.ts b/demo/unicodeTable.ts index 2e254ab6..23b2a9fa 100644 --- a/demo/unicodeTable.ts +++ b/demo/unicodeTable.ts @@ -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(); + const labelStartMap = new Map(); // Build a map of codepoint -> colorIndex for all codepoints in each range const codePointColorMap = new Map(); 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));