@@ -117,6 +117,112 @@ export const blockElementDefinitions: { [index: string]: IBlockVector[] | undefi
117117 '\u{1FB97}' : [ { x : 0 , y : 2 , w : 8 , h : 2 } , { x : 0 , y : 6 , w : 8 , h : 2 } ]
118118} ;
119119
120+ /**
121+ * Generates a drawing function for sextant characters. Sextants are a 2x3 grid where each cell
122+ * can be on or off.
123+ * @param pattern A 6-bit pattern where bit 0 = top-left, bit 1 = top-right, bit 2 = middle-left,
124+ * bit 3 = middle-right, bit 4 = bottom-left, bit 5 = bottom-right
125+ */
126+ function sextant ( pattern : number ) : DrawFunctionDefinition {
127+ return ( ) => {
128+ // Sextant grid: 2 columns, 3 rows
129+ // Row heights in 8ths: top=3, middle=2, bottom=3
130+ // Column widths: left=4, right=4
131+ const rects : string [ ] = [ ] ;
132+ const colW = 0.5 ; // Each column is half width
133+ const rowH = [ 3 / 8 , 2 / 8 , 3 / 8 ] ; // Row heights as fractions
134+ const rowY = [ 0 , 3 / 8 , 5 / 8 ] ; // Row Y positions
135+
136+ for ( let row = 0 ; row < 3 ; row ++ ) {
137+ const leftBit = ( pattern >> ( row * 2 ) ) & 1 ;
138+ const rightBit = ( pattern >> ( row * 2 + 1 ) ) & 1 ;
139+
140+ if ( leftBit && rightBit ) {
141+ // Full row
142+ rects . push ( `M0,${ rowY [ row ] } L1,${ rowY [ row ] } L1,${ rowY [ row ] + rowH [ row ] } L0,${ rowY [ row ] + rowH [ row ] } Z` ) ;
143+ } else if ( leftBit ) {
144+ rects . push ( `M0,${ rowY [ row ] } L${ colW } ,${ rowY [ row ] } L${ colW } ,${ rowY [ row ] + rowH [ row ] } L0,${ rowY [ row ] + rowH [ row ] } Z` ) ;
145+ } else if ( rightBit ) {
146+ rects . push ( `M${ colW } ,${ rowY [ row ] } L1,${ rowY [ row ] } L1,${ rowY [ row ] + rowH [ row ] } L${ colW } ,${ rowY [ row ] + rowH [ row ] } Z` ) ;
147+ }
148+ }
149+ return rects . join ( ' ' ) ;
150+ } ;
151+ }
152+
153+ export const symbolsForLegacyComputingDefinitions : { [ index : string ] : DrawFunctionDefinition | undefined } = {
154+ // Block sextants (0x1FB00-0x1FB3B)
155+ // Each sextant is a 2x3 grid of cells in an 8x8 block
156+ // Cell positions: bit 0=top-left, bit 1=top-right, bit 2=middle-left, bit 3=middle-right,
157+ // bit 4=bottom-left, bit 5=bottom-right
158+ // Patterns 0 (empty), 21 (left half), 42 (right half), 63 (full) are excluded as they exist
159+ // elsewhere
160+ '\u{1FB00}' : sextant ( 0b000001 ) , // BLOCK SEXTANT-1
161+ '\u{1FB01}' : sextant ( 0b000010 ) , // BLOCK SEXTANT-2
162+ '\u{1FB02}' : sextant ( 0b000011 ) , // BLOCK SEXTANT-12 (upper one third block)
163+ '\u{1FB03}' : sextant ( 0b000100 ) , // BLOCK SEXTANT-3
164+ '\u{1FB04}' : sextant ( 0b000101 ) , // BLOCK SEXTANT-13
165+ '\u{1FB05}' : sextant ( 0b000110 ) , // BLOCK SEXTANT-23
166+ '\u{1FB06}' : sextant ( 0b000111 ) , // BLOCK SEXTANT-123
167+ '\u{1FB07}' : sextant ( 0b001000 ) , // BLOCK SEXTANT-4
168+ '\u{1FB08}' : sextant ( 0b001001 ) , // BLOCK SEXTANT-14
169+ '\u{1FB09}' : sextant ( 0b001010 ) , // BLOCK SEXTANT-24
170+ '\u{1FB0A}' : sextant ( 0b001011 ) , // BLOCK SEXTANT-124
171+ '\u{1FB0B}' : sextant ( 0b001100 ) , // BLOCK SEXTANT-34 (middle one third block)
172+ '\u{1FB0C}' : sextant ( 0b001101 ) , // BLOCK SEXTANT-134
173+ '\u{1FB0D}' : sextant ( 0b001110 ) , // BLOCK SEXTANT-234
174+ '\u{1FB0E}' : sextant ( 0b001111 ) , // BLOCK SEXTANT-1234 (upper two thirds block)
175+ '\u{1FB0F}' : sextant ( 0b010000 ) , // BLOCK SEXTANT-5
176+ '\u{1FB10}' : sextant ( 0b010001 ) , // BLOCK SEXTANT-15
177+ '\u{1FB11}' : sextant ( 0b010010 ) , // BLOCK SEXTANT-25
178+ '\u{1FB12}' : sextant ( 0b010011 ) , // BLOCK SEXTANT-125
179+ '\u{1FB13}' : sextant ( 0b010100 ) , // BLOCK SEXTANT-35
180+ // Pattern 21 (0x15 = 0b010101) = left half block, skipped (exists as U+258C)
181+ '\u{1FB14}' : sextant ( 0b010110 ) , // BLOCK SEXTANT-235
182+ '\u{1FB15}' : sextant ( 0b010111 ) , // BLOCK SEXTANT-1235
183+ '\u{1FB16}' : sextant ( 0b011000 ) , // BLOCK SEXTANT-45
184+ '\u{1FB17}' : sextant ( 0b011001 ) , // BLOCK SEXTANT-145
185+ '\u{1FB18}' : sextant ( 0b011010 ) , // BLOCK SEXTANT-245
186+ '\u{1FB19}' : sextant ( 0b011011 ) , // BLOCK SEXTANT-1245
187+ '\u{1FB1A}' : sextant ( 0b011100 ) , // BLOCK SEXTANT-345
188+ '\u{1FB1B}' : sextant ( 0b011101 ) , // BLOCK SEXTANT-1345
189+ '\u{1FB1C}' : sextant ( 0b011110 ) , // BLOCK SEXTANT-2345
190+ '\u{1FB1D}' : sextant ( 0b011111 ) , // BLOCK SEXTANT-12345
191+ '\u{1FB1E}' : sextant ( 0b100000 ) , // BLOCK SEXTANT-6
192+ '\u{1FB1F}' : sextant ( 0b100001 ) , // BLOCK SEXTANT-16
193+ '\u{1FB20}' : sextant ( 0b100010 ) , // BLOCK SEXTANT-26
194+ '\u{1FB21}' : sextant ( 0b100011 ) , // BLOCK SEXTANT-126
195+ '\u{1FB22}' : sextant ( 0b100100 ) , // BLOCK SEXTANT-36
196+ '\u{1FB23}' : sextant ( 0b100101 ) , // BLOCK SEXTANT-136
197+ '\u{1FB24}' : sextant ( 0b100110 ) , // BLOCK SEXTANT-236
198+ '\u{1FB25}' : sextant ( 0b100111 ) , // BLOCK SEXTANT-1236
199+ '\u{1FB26}' : sextant ( 0b101000 ) , // BLOCK SEXTANT-46
200+ '\u{1FB27}' : sextant ( 0b101001 ) , // BLOCK SEXTANT-146
201+ // Pattern 42 (0x2A = 0b101010) = right half block, skipped (exists as U+2590)
202+ '\u{1FB28}' : sextant ( 0b101011 ) , // BLOCK SEXTANT-1246
203+ '\u{1FB29}' : sextant ( 0b101100 ) , // BLOCK SEXTANT-346
204+ '\u{1FB2A}' : sextant ( 0b101101 ) , // BLOCK SEXTANT-1346
205+ '\u{1FB2B}' : sextant ( 0b101110 ) , // BLOCK SEXTANT-2346
206+ '\u{1FB2C}' : sextant ( 0b101111 ) , // BLOCK SEXTANT-12346
207+ '\u{1FB2D}' : sextant ( 0b110000 ) , // BLOCK SEXTANT-56 (lower one third block)
208+ '\u{1FB2E}' : sextant ( 0b110001 ) , // BLOCK SEXTANT-156
209+ '\u{1FB2F}' : sextant ( 0b110010 ) , // BLOCK SEXTANT-256
210+ '\u{1FB30}' : sextant ( 0b110011 ) , // BLOCK SEXTANT-1256 (upper and lower one
211+ // third block)
212+ '\u{1FB31}' : sextant ( 0b110100 ) , // BLOCK SEXTANT-356
213+ '\u{1FB32}' : sextant ( 0b110101 ) , // BLOCK SEXTANT-1356
214+ '\u{1FB33}' : sextant ( 0b110110 ) , // BLOCK SEXTANT-2356
215+ '\u{1FB34}' : sextant ( 0b110111 ) , // BLOCK SEXTANT-12356
216+ '\u{1FB35}' : sextant ( 0b111000 ) , // BLOCK SEXTANT-456
217+ '\u{1FB36}' : sextant ( 0b111001 ) , // BLOCK SEXTANT-1456
218+ '\u{1FB37}' : sextant ( 0b111010 ) , // BLOCK SEXTANT-2456
219+ '\u{1FB38}' : sextant ( 0b111011 ) , // BLOCK SEXTANT-12456
220+ '\u{1FB39}' : sextant ( 0b111100 ) , // BLOCK SEXTANT-3456 (lower two thirds block)
221+ '\u{1FB3A}' : sextant ( 0b111101 ) , // BLOCK SEXTANT-13456
222+ '\u{1FB3B}' : sextant ( 0b111110 ) // BLOCK SEXTANT-23456
223+ // Pattern 63 (0x3F = 0b111111) = full block, skipped (exists as U+2588)
224+ } ;
225+
120226type PatternDefinition = number [ ] [ ] ;
121227
122228/**
@@ -411,7 +517,13 @@ export function tryDrawCustomChar(
411517) : boolean {
412518 const blockElementDefinition = blockElementDefinitions [ c ] ;
413519 if ( blockElementDefinition ) {
414- drawBlockElementChar ( ctx , blockElementDefinition , xOffset , yOffset , deviceCellWidth , deviceCellHeight ) ;
520+ drawBlockVectorChar ( ctx , blockElementDefinition , xOffset , yOffset , deviceCellWidth , deviceCellHeight ) ;
521+ return true ;
522+ }
523+
524+ const symbolsForLegacyComputingDefinition = symbolsForLegacyComputingDefinitions [ c ] ;
525+ if ( symbolsForLegacyComputingDefinition ) {
526+ drawSextantChar ( ctx , symbolsForLegacyComputingDefinition , xOffset , yOffset , deviceCellWidth , deviceCellHeight ) ;
415527 return true ;
416528 }
417529
@@ -436,7 +548,7 @@ export function tryDrawCustomChar(
436548 return false ;
437549}
438550
439- function drawBlockElementChar (
551+ function drawBlockVectorChar (
440552 ctx : CanvasRenderingContext2D ,
441553 charDefinition : IBlockVector [ ] ,
442554 xOffset : number ,
@@ -457,6 +569,40 @@ function drawBlockElementChar(
457569 }
458570}
459571
572+ function drawSextantChar (
573+ ctx : CanvasRenderingContext2D ,
574+ charDefinition : DrawFunctionDefinition ,
575+ xOffset : number ,
576+ yOffset : number ,
577+ deviceCellWidth : number ,
578+ deviceCellHeight : number
579+ ) : void {
580+ const instructions = charDefinition ( 0 , 0 ) ;
581+ ctx . beginPath ( ) ;
582+ for ( const instruction of instructions . split ( ' ' ) ) {
583+ const type = instruction [ 0 ] ;
584+ const args : string [ ] = instruction . substring ( 1 ) . split ( ',' ) ;
585+ if ( ! args [ 0 ] || ! args [ 1 ] ) {
586+ if ( type === 'Z' ) {
587+ ctx . closePath ( ) ;
588+ }
589+ continue ;
590+ }
591+ const translatedArgs = args . map ( ( e , i ) => {
592+ const val = parseFloat ( e ) ;
593+ return i % 2 === 0
594+ ? xOffset + val * deviceCellWidth
595+ : yOffset + val * deviceCellHeight ;
596+ } ) ;
597+ if ( type === 'M' ) {
598+ ctx . moveTo ( translatedArgs [ 0 ] , translatedArgs [ 1 ] ) ;
599+ } else if ( type === 'L' ) {
600+ ctx . lineTo ( translatedArgs [ 0 ] , translatedArgs [ 1 ] ) ;
601+ }
602+ }
603+ ctx . fill ( ) ;
604+ }
605+
460606const cachedPatterns : Map < PatternDefinition , Map < /* fillStyle */ string , CanvasPattern > > = new Map ( ) ;
461607
462608function drawPatternChar (
0 commit comments