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..aa67528f 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -3,49 +3,67 @@ * @license MIT */ -import { CustomGlyphVectorType, type CustomGlyphDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types'; +import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types'; /* eslint-disable @typescript-eslint/naming-convention */ -export const unifiedCharDefinitions: { [index: string]: ICustomGlyphVectorShape[] | undefined } = { +export const unifiedCharDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } = { + // #region Block elements (2580-259F) + + // Block elements (2580-2590) + // https://www.unicode.org/charts/PDF/U2580.pdf + '▀': { 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_DEFINITION, data: [ // LIGHT SHADE (25%) + [1, 0], + [0, 0] + ] }, + '▒': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_DEFINITION, 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_DEFINITION, 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 }; 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 - - // 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 - - // 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 - // 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 }], @@ -332,26 +350,6 @@ export const blockShadeComboDefinitions: { [index: string]: BlockShadeComboDefin '\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%) - [1, 0], - [0, 1] - ], - '▓': [ // DARK SHADE (75%) - [1, 1], - [1, 0] - ] -}; - const enum Shapes { /** │ */ TOP_TO_BOTTOM = 'M.5,0 L.5,1', /** ─ */ LEFT_TO_RIGHT = 'M0,.5 L1,.5', diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphRasterizer.ts index e84883dd..64fc5bd2 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 { blockElementDefinitions, blockShadeComboDefinitions, boxDrawingDefinitions, powerlineDefinitions, rectangularShadeDefinitions, symbolsForLegacyComputingDefinitions, unifiedCharDefinitions } from 'customGlyphs/CustomGlyphDefinitions'; +import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types'; /** * Try drawing a custom block element or box drawing character, returning whether it was @@ -21,6 +21,18 @@ export function tryDrawCustomGlyph( fontSize: number, devicePixelRatio: number ): boolean { + const unifiedCharDefinition = unifiedCharDefinitions[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_DEFINITION: + drawPatternChar(ctx, unifiedCharDefinition.data, xOffset, yOffset, deviceCellWidth, deviceCellHeight); + return true; + } + } + const blockElementDefinition = blockElementDefinitions[c]; if (blockElementDefinition) { drawBlockVectorChar(ctx, blockElementDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight); @@ -45,12 +57,6 @@ export function tryDrawCustomGlyph( 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); diff --git a/addons/addon-webgl/src/customGlyphs/Types.ts b/addons/addon-webgl/src/customGlyphs/Types.ts index d4aebc73..2be68b41 100644 --- a/addons/addon-webgl/src/customGlyphs/Types.ts +++ b/addons/addon-webgl/src/customGlyphs/Types.ts @@ -29,3 +29,13 @@ export const enum CustomGlyphVectorType { } export type CustomGlyphPatternDefinition = number[][]; + +export const enum CustomGlyphDefinitionType { + SOLID_OCTANT_BLOCK_VECTOR, + BLOCK_PATTERN_DEFINITION, +} + +export type CustomGlyphCharacterDefinition = ( + { type: CustomGlyphDefinitionType.SOLID_OCTANT_BLOCK_VECTOR, data: ICustomGlyphSolidOctantBlockVector[] } | + { type: CustomGlyphDefinitionType.BLOCK_PATTERN_DEFINITION, data: CustomGlyphPatternDefinition } +); diff --git a/demo/client.ts b/demo/client.ts index 994b9eda..4bb27fed 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,19 @@ function writeCustomGlyphHandler(): void { window.scrollTo(0, 0); } -function writeSymbolsForLegacyComputing(): void { +function customGlyphRangesHandler(): void { + // 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], + ]); // 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..50840d83 100644 --- a/demo/index.html +++ b/demo/index.html @@ -92,8 +92,8 @@