diff --git a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts index 48c7ee8d..122e2924 100644 --- a/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts +++ b/addons/addon-webgl/src/customGlyphs/CustomGlyphDefinitions.ts @@ -128,7 +128,7 @@ export const unifiedCharDefinitions: { [index: string]: CustomGlyphCharacterDefi '\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 + '\u{1FB3B}': sextant(0b111110), // BLOCK SEXTANT-23456 // 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 @@ -184,6 +184,53 @@ export const unifiedCharDefinitions: { [index: string]: CustomGlyphCharacterDefi '\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 + // TODO: Block elements, window title bar, block elements + + // Rectangular shade characters (1FB8C-1FB94) + '\u{1FB8C}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION, data: [[ // LEFT HALF MEDIUM SHADE + [1, 0], + [0, 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]] }, + // TODO: Make sure these are rendered correctly + '\u{1FB91}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { // UPPER HALF BLOCK AND LOWER HALF INVERSE MEDIUM SHADE + pattern: [[ + [1, 0], + [0, 1] + ], [0, 0, 1, 0.5]], + vectors: [{ x: 0, y: 4, 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: [[ + [1, 0], + [0, 1] + ], [0, 0.5, 1, 0.5]], + vectors: [{ x: 0, y: 0, w: 8, h: 4 }] + } }, + // 1FB93 is reserved + '\u{1FB94}': { type: CustomGlyphDefinitionType.BLOCK_PATTERN_WITH_REGION_AND_SOLID_OCTANT_BLOCK_VECTOR, data: { // LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK + pattern: [[ + [1, 0], + [0, 1] + ], [0.5, 0, 0.5, 1]], + vectors: [{ x: 0, y: 0, w: 4, h: 8 }] + } }, + // #endregion }; @@ -293,45 +340,6 @@ function sextant(pattern: number): { type: CustomGlyphDefinitionType.PATH_FUNCTI }; } -/** - * 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 -}; - 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 18044c47..79a97931 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, powerlineDefinitions, rectangularShadeDefinitions, unifiedCharDefinitions } from 'customGlyphs/CustomGlyphDefinitions'; -import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types'; +import { blockElementDefinitions, boxDrawingDefinitions, powerlineDefinitions, unifiedCharDefinitions } from 'customGlyphs/CustomGlyphDefinitions'; +import { CustomGlyphDefinitionType, CustomGlyphVectorType, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type CustomGlyphRegionDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from 'customGlyphs/Types'; /** * Try drawing a custom block element or box drawing character, returning whether it was @@ -30,6 +30,13 @@ export function tryDrawCustomGlyph( 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); @@ -43,18 +50,6 @@ export function tryDrawCustomGlyph( 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 boxDrawingDefinition = boxDrawingDefinitions[c]; if (boxDrawingDefinition) { drawBoxDrawingChar(ctx, boxDrawingDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio); @@ -190,9 +185,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, @@ -224,40 +219,40 @@ function drawRectangularShadeChar( * 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; +// 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 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); +// // 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); - } - } - } -} +// 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 diff --git a/addons/addon-webgl/src/customGlyphs/Types.ts b/addons/addon-webgl/src/customGlyphs/Types.ts index 40ccee01..b7841ab4 100644 --- a/addons/addon-webgl/src/customGlyphs/Types.ts +++ b/addons/addon-webgl/src/customGlyphs/Types.ts @@ -33,13 +33,21 @@ 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, } +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, data: string } );