@xterm/addon-webgl 0.20.0-beta.3 → 0.20.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,914 +0,0 @@
1
- /**
2
- * Copyright (c) 2021 The xterm.js authors. All rights reserved.
3
- * @license MIT
4
- */
5
-
6
- /* eslint-disable @typescript-eslint/naming-convention */
7
-
8
- import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
9
-
10
- interface IBlockVector {
11
- x: number;
12
- y: number;
13
- w: number;
14
- h: number;
15
- }
16
-
17
- export const blockElementDefinitions: { [index: string]: IBlockVector[] | undefined } = {
18
- // Block elements (0x2580-0x2590)
19
- '▀': [{ x: 0, y: 0, w: 8, h: 4 }], // UPPER HALF BLOCK
20
- '▁': [{ x: 0, y: 7, w: 8, h: 1 }], // LOWER ONE EIGHTH BLOCK
21
- '▂': [{ x: 0, y: 6, w: 8, h: 2 }], // LOWER ONE QUARTER BLOCK
22
- '▃': [{ x: 0, y: 5, w: 8, h: 3 }], // LOWER THREE EIGHTHS BLOCK
23
- '▄': [{ x: 0, y: 4, w: 8, h: 4 }], // LOWER HALF BLOCK
24
- '▅': [{ x: 0, y: 3, w: 8, h: 5 }], // LOWER FIVE EIGHTHS BLOCK
25
- '▆': [{ x: 0, y: 2, w: 8, h: 6 }], // LOWER THREE QUARTERS BLOCK
26
- '▇': [{ x: 0, y: 1, w: 8, h: 7 }], // LOWER SEVEN EIGHTHS BLOCK
27
- '█': [{ x: 0, y: 0, w: 8, h: 8 }], // FULL BLOCK
28
- '▉': [{ x: 0, y: 0, w: 7, h: 8 }], // LEFT SEVEN EIGHTHS BLOCK
29
- '▊': [{ x: 0, y: 0, w: 6, h: 8 }], // LEFT THREE QUARTERS BLOCK
30
- '▋': [{ x: 0, y: 0, w: 5, h: 8 }], // LEFT FIVE EIGHTHS BLOCK
31
- '▌': [{ x: 0, y: 0, w: 4, h: 8 }], // LEFT HALF BLOCK
32
- '▍': [{ x: 0, y: 0, w: 3, h: 8 }], // LEFT THREE EIGHTHS BLOCK
33
- '▎': [{ x: 0, y: 0, w: 2, h: 8 }], // LEFT ONE QUARTER BLOCK
34
- '▏': [{ x: 0, y: 0, w: 1, h: 8 }], // LEFT ONE EIGHTH BLOCK
35
- '▐': [{ x: 4, y: 0, w: 4, h: 8 }], // RIGHT HALF BLOCK
36
-
37
- // Block elements (0x2594-0x2595)
38
- '▔': [{ x: 0, y: 0, w: 8, h: 1 }], // UPPER ONE EIGHTH BLOCK
39
- '▕': [{ x: 7, y: 0, w: 1, h: 8 }], // RIGHT ONE EIGHTH BLOCK
40
-
41
- // Terminal graphic characters (0x2596-0x259F)
42
- '▖': [{ x: 0, y: 4, w: 4, h: 4 }], // QUADRANT LOWER LEFT
43
- '▗': [{ x: 4, y: 4, w: 4, h: 4 }], // QUADRANT LOWER RIGHT
44
- '▘': [{ x: 0, y: 0, w: 4, h: 4 }], // QUADRANT UPPER LEFT
45
- '▙': [{ 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
46
- '▚': [{ x: 0, y: 0, w: 4, h: 4 }, { x: 4, y: 4, w: 4, h: 4 }], // QUADRANT UPPER LEFT AND LOWER RIGHT
47
- '▛': [{ 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
48
- '▜': [{ 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
49
- '▝': [{ x: 4, y: 0, w: 4, h: 4 }], // QUADRANT UPPER RIGHT
50
- '▞': [{ x: 4, y: 0, w: 4, h: 4 }, { x: 0, y: 4, w: 4, h: 4 }], // QUADRANT UPPER RIGHT AND LOWER LEFT
51
- '▟': [{ 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
52
-
53
- // VERTICAL ONE EIGHTH BLOCK-2 through VERTICAL ONE EIGHTH BLOCK-7
54
- '\u{1FB70}': [{ x: 1, y: 0, w: 1, h: 8 }],
55
- '\u{1FB71}': [{ x: 2, y: 0, w: 1, h: 8 }],
56
- '\u{1FB72}': [{ x: 3, y: 0, w: 1, h: 8 }],
57
- '\u{1FB73}': [{ x: 4, y: 0, w: 1, h: 8 }],
58
- '\u{1FB74}': [{ x: 5, y: 0, w: 1, h: 8 }],
59
- '\u{1FB75}': [{ x: 6, y: 0, w: 1, h: 8 }],
60
-
61
- // HORIZONTAL ONE EIGHTH BLOCK-2 through HORIZONTAL ONE EIGHTH BLOCK-7
62
- '\u{1FB76}': [{ x: 0, y: 1, w: 8, h: 1 }],
63
- '\u{1FB77}': [{ x: 0, y: 2, w: 8, h: 1 }],
64
- '\u{1FB78}': [{ x: 0, y: 3, w: 8, h: 1 }],
65
- '\u{1FB79}': [{ x: 0, y: 4, w: 8, h: 1 }],
66
- '\u{1FB7A}': [{ x: 0, y: 5, w: 8, h: 1 }],
67
- '\u{1FB7B}': [{ x: 0, y: 6, w: 8, h: 1 }],
68
-
69
- // LEFT AND LOWER ONE EIGHTH BLOCK
70
- '\u{1FB7C}': [{ x: 0, y: 0, w: 1, h: 8 }, { x: 0, y: 7, w: 8, h: 1 }],
71
- // LEFT AND UPPER ONE EIGHTH BLOCK
72
- '\u{1FB7D}': [{ x: 0, y: 0, w: 1, h: 8 }, { x: 0, y: 0, w: 8, h: 1 }],
73
- // RIGHT AND UPPER ONE EIGHTH BLOCK
74
- '\u{1FB7E}': [{ x: 7, y: 0, w: 1, h: 8 }, { x: 0, y: 0, w: 8, h: 1 }],
75
- // RIGHT AND LOWER ONE EIGHTH BLOCK
76
- '\u{1FB7F}': [{ x: 7, y: 0, w: 1, h: 8 }, { x: 0, y: 7, w: 8, h: 1 }],
77
- // UPPER AND LOWER ONE EIGHTH BLOCK
78
- '\u{1FB80}': [{ x: 0, y: 0, w: 8, h: 1 }, { x: 0, y: 7, w: 8, h: 1 }],
79
- // HORIZONTAL ONE EIGHTH BLOCK-1358
80
- '\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 }],
81
-
82
- // UPPER ONE QUARTER BLOCK
83
- '\u{1FB82}': [{ x: 0, y: 0, w: 8, h: 2 }],
84
- // UPPER THREE EIGHTHS BLOCK
85
- '\u{1FB83}': [{ x: 0, y: 0, w: 8, h: 3 }],
86
- // UPPER FIVE EIGHTHS BLOCK
87
- '\u{1FB84}': [{ x: 0, y: 0, w: 8, h: 5 }],
88
- // UPPER THREE QUARTERS BLOCK
89
- '\u{1FB85}': [{ x: 0, y: 0, w: 8, h: 6 }],
90
- // UPPER SEVEN EIGHTHS BLOCK
91
- '\u{1FB86}': [{ x: 0, y: 0, w: 8, h: 7 }],
92
-
93
- // RIGHT ONE QUARTER BLOCK
94
- '\u{1FB87}': [{ x: 6, y: 0, w: 2, h: 8 }],
95
- // RIGHT THREE EIGHTHS B0OCK
96
- '\u{1FB88}': [{ x: 5, y: 0, w: 3, h: 8 }],
97
- // RIGHT FIVE EIGHTHS BL0CK
98
- '\u{1FB89}': [{ x: 3, y: 0, w: 5, h: 8 }],
99
- // RIGHT THREE QUARTERS 0LOCK
100
- '\u{1FB8A}': [{ x: 2, y: 0, w: 6, h: 8 }],
101
- // RIGHT SEVEN EIGHTHS B0OCK
102
- '\u{1FB8B}': [{ x: 1, y: 0, w: 7, h: 8 }],
103
-
104
- // CHECKER BOARD FILL
105
- '\u{1FB95}': [
106
- { x: 0, y: 0, w: 2, h: 2 }, { x: 4, y: 0, w: 2, h: 2 },
107
- { x: 2, y: 2, w: 2, h: 2 }, { x: 6, y: 2, w: 2, h: 2 },
108
- { x: 0, y: 4, w: 2, h: 2 }, { x: 4, y: 4, w: 2, h: 2 },
109
- { x: 2, y: 6, w: 2, h: 2 }, { x: 6, y: 6, w: 2, h: 2 }
110
- ],
111
- // INVERSE CHECKER BOARD FILL
112
- '\u{1FB96}': [
113
- { x: 2, y: 0, w: 2, h: 2 }, { x: 6, y: 0, w: 2, h: 2 },
114
- { x: 0, y: 2, w: 2, h: 2 }, { x: 4, y: 2, w: 2, h: 2 },
115
- { x: 2, y: 4, w: 2, h: 2 }, { x: 6, y: 4, w: 2, h: 2 },
116
- { x: 0, y: 6, w: 2, h: 2 }, { x: 4, y: 6, w: 2, h: 2 }
117
- ],
118
- // HEAVY HORIZONTAL FILL (upper middle and lower one quarter block)
119
- '\u{1FB97}': [{ x: 0, y: 2, w: 8, h: 2 }, { x: 0, y: 6, w: 8, h: 2 }]
120
- };
121
-
122
- /**
123
- * Generates a drawing function for sextant characters. Sextants are a 2x3 grid where each cell
124
- * can be on or off.
125
- * @param pattern A 6-bit pattern where bit 0 = top-left, bit 1 = top-right, bit 2 = middle-left,
126
- * bit 3 = middle-right, bit 4 = bottom-left, bit 5 = bottom-right
127
- */
128
- function sextant(pattern: number): DrawFunctionDefinition {
129
- return () => {
130
- // Sextant grid: 2 columns, 3 rows
131
- // Row heights in 8ths: top=3, middle=2, bottom=3
132
- // Column widths: left=4, right=4
133
- const rects: string[] = [];
134
- const colW = 0.5; // Each column is half width
135
- const rowH = [3 / 8, 2 / 8, 3 / 8]; // Row heights as fractions
136
- const rowY = [0, 3 / 8, 5 / 8]; // Row Y positions
137
-
138
- for (let row = 0; row < 3; row++) {
139
- const leftBit = (pattern >> (row * 2)) & 1;
140
- const rightBit = (pattern >> (row * 2 + 1)) & 1;
141
-
142
- if (leftBit && rightBit) {
143
- // Full row
144
- rects.push(`M0,${rowY[row]} L1,${rowY[row]} L1,${rowY[row] + rowH[row]} L0,${rowY[row] + rowH[row]} Z`);
145
- } else if (leftBit) {
146
- rects.push(`M0,${rowY[row]} L${colW},${rowY[row]} L${colW},${rowY[row] + rowH[row]} L0,${rowY[row] + rowH[row]} Z`);
147
- } else if (rightBit) {
148
- rects.push(`M${colW},${rowY[row]} L1,${rowY[row]} L1,${rowY[row] + rowH[row]} L${colW},${rowY[row] + rowH[row]} Z`);
149
- }
150
- }
151
- return rects.join(' ');
152
- };
153
- }
154
-
155
- export const symbolsForLegacyComputingDefinitions: { [index: string]: DrawFunctionDefinition | undefined } = {
156
- // Block sextants (0x1FB00-0x1FB3B)
157
- // Each sextant is a 2x3 grid of cells in an 8x8 block
158
- // Cell positions: bit 0=top-left, bit 1=top-right, bit 2=middle-left, bit 3=middle-right,
159
- // bit 4=bottom-left, bit 5=bottom-right
160
- // Patterns 0 (empty), 21 (left half), 42 (right half), 63 (full) are excluded as they exist
161
- // elsewhere
162
- '\u{1FB00}': sextant(0b000001), // BLOCK SEXTANT-1
163
- '\u{1FB01}': sextant(0b000010), // BLOCK SEXTANT-2
164
- '\u{1FB02}': sextant(0b000011), // BLOCK SEXTANT-12 (upper one third block)
165
- '\u{1FB03}': sextant(0b000100), // BLOCK SEXTANT-3
166
- '\u{1FB04}': sextant(0b000101), // BLOCK SEXTANT-13
167
- '\u{1FB05}': sextant(0b000110), // BLOCK SEXTANT-23
168
- '\u{1FB06}': sextant(0b000111), // BLOCK SEXTANT-123
169
- '\u{1FB07}': sextant(0b001000), // BLOCK SEXTANT-4
170
- '\u{1FB08}': sextant(0b001001), // BLOCK SEXTANT-14
171
- '\u{1FB09}': sextant(0b001010), // BLOCK SEXTANT-24
172
- '\u{1FB0A}': sextant(0b001011), // BLOCK SEXTANT-124
173
- '\u{1FB0B}': sextant(0b001100), // BLOCK SEXTANT-34 (middle one third block)
174
- '\u{1FB0C}': sextant(0b001101), // BLOCK SEXTANT-134
175
- '\u{1FB0D}': sextant(0b001110), // BLOCK SEXTANT-234
176
- '\u{1FB0E}': sextant(0b001111), // BLOCK SEXTANT-1234 (upper two thirds block)
177
- '\u{1FB0F}': sextant(0b010000), // BLOCK SEXTANT-5
178
- '\u{1FB10}': sextant(0b010001), // BLOCK SEXTANT-15
179
- '\u{1FB11}': sextant(0b010010), // BLOCK SEXTANT-25
180
- '\u{1FB12}': sextant(0b010011), // BLOCK SEXTANT-125
181
- '\u{1FB13}': sextant(0b010100), // BLOCK SEXTANT-35
182
- // Pattern 21 (0x15 = 0b010101) = left half block, skipped (exists as U+258C)
183
- '\u{1FB14}': sextant(0b010110), // BLOCK SEXTANT-235
184
- '\u{1FB15}': sextant(0b010111), // BLOCK SEXTANT-1235
185
- '\u{1FB16}': sextant(0b011000), // BLOCK SEXTANT-45
186
- '\u{1FB17}': sextant(0b011001), // BLOCK SEXTANT-145
187
- '\u{1FB18}': sextant(0b011010), // BLOCK SEXTANT-245
188
- '\u{1FB19}': sextant(0b011011), // BLOCK SEXTANT-1245
189
- '\u{1FB1A}': sextant(0b011100), // BLOCK SEXTANT-345
190
- '\u{1FB1B}': sextant(0b011101), // BLOCK SEXTANT-1345
191
- '\u{1FB1C}': sextant(0b011110), // BLOCK SEXTANT-2345
192
- '\u{1FB1D}': sextant(0b011111), // BLOCK SEXTANT-12345
193
- '\u{1FB1E}': sextant(0b100000), // BLOCK SEXTANT-6
194
- '\u{1FB1F}': sextant(0b100001), // BLOCK SEXTANT-16
195
- '\u{1FB20}': sextant(0b100010), // BLOCK SEXTANT-26
196
- '\u{1FB21}': sextant(0b100011), // BLOCK SEXTANT-126
197
- '\u{1FB22}': sextant(0b100100), // BLOCK SEXTANT-36
198
- '\u{1FB23}': sextant(0b100101), // BLOCK SEXTANT-136
199
- '\u{1FB24}': sextant(0b100110), // BLOCK SEXTANT-236
200
- '\u{1FB25}': sextant(0b100111), // BLOCK SEXTANT-1236
201
- '\u{1FB26}': sextant(0b101000), // BLOCK SEXTANT-46
202
- '\u{1FB27}': sextant(0b101001), // BLOCK SEXTANT-146
203
- // Pattern 42 (0x2A = 0b101010) = right half block, skipped (exists as U+2590)
204
- '\u{1FB28}': sextant(0b101011), // BLOCK SEXTANT-1246
205
- '\u{1FB29}': sextant(0b101100), // BLOCK SEXTANT-346
206
- '\u{1FB2A}': sextant(0b101101), // BLOCK SEXTANT-1346
207
- '\u{1FB2B}': sextant(0b101110), // BLOCK SEXTANT-2346
208
- '\u{1FB2C}': sextant(0b101111), // BLOCK SEXTANT-12346
209
- '\u{1FB2D}': sextant(0b110000), // BLOCK SEXTANT-56 (lower one third block)
210
- '\u{1FB2E}': sextant(0b110001), // BLOCK SEXTANT-156
211
- '\u{1FB2F}': sextant(0b110010), // BLOCK SEXTANT-256
212
- '\u{1FB30}': sextant(0b110011), // BLOCK SEXTANT-1256 (upper and lower one
213
- // third block)
214
- '\u{1FB31}': sextant(0b110100), // BLOCK SEXTANT-356
215
- '\u{1FB32}': sextant(0b110101), // BLOCK SEXTANT-1356
216
- '\u{1FB33}': sextant(0b110110), // BLOCK SEXTANT-2356
217
- '\u{1FB34}': sextant(0b110111), // BLOCK SEXTANT-12356
218
- '\u{1FB35}': sextant(0b111000), // BLOCK SEXTANT-456
219
- '\u{1FB36}': sextant(0b111001), // BLOCK SEXTANT-1456
220
- '\u{1FB37}': sextant(0b111010), // BLOCK SEXTANT-2456
221
- '\u{1FB38}': sextant(0b111011), // BLOCK SEXTANT-12456
222
- '\u{1FB39}': sextant(0b111100), // BLOCK SEXTANT-3456 (lower two thirds block)
223
- '\u{1FB3A}': sextant(0b111101), // BLOCK SEXTANT-13456
224
- '\u{1FB3B}': sextant(0b111110), // BLOCK SEXTANT-23456
225
- // Pattern 63 (0x3F = 0b111111) = full block, skipped (exists as U+2588)
226
-
227
- // Smooth mosaic terminal graphic characters (0x1FB3C-0x1FB6F)
228
- // These are triangular/diagonal shapes. "X BLOCK DIAGONAL A TO B" means the X region is filled,
229
- // with a diagonal edge from point A to point B.
230
- // Reference points: upper/lower = y (0/1), left/right = x (0/1), centre = x=0.5
231
- // Vertical uses sextant grid: upper-middle = y=1/3, lower-middle = y=2/3
232
-
233
- // LOWER LEFT BLOCK variants (1FB3C-1FB40) - filled region in lower-left
234
- '\u{1FB3C}': () => `M0,${2/3} L0,1 L0.5,1 Z`, // LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER CENTRE
235
- '\u{1FB3D}': () => `M0,${2/3} L0,1 L1,1 Z`, // LOWER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT
236
- '\u{1FB3E}': () => `M0,${1/3} L0,1 L0.5,1 Z`, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER CENTRE
237
- '\u{1FB3F}': () => `M0,${1/3} L0,1 L1,1 Z`, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT
238
- '\u{1FB40}': () => 'M0,0 L0,1 L0.5,1 Z', // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE
239
-
240
- // LOWER RIGHT BLOCK variants (1FB41-1FB4B) - filled region in lower-right
241
- '\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
242
- '\u{1FB42}': () => `M0,${1/3} L1,0 L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT
243
- '\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
244
- '\u{1FB44}': () => `M0,${2/3} L1,0 L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT
245
- '\u{1FB45}': () => 'M0,1 L0.5,0 L1,0 L1,1 Z', // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE
246
- '\u{1FB46}': () => `M0,${2/3} L1,${1/3} L1,1 L0,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT
247
- '\u{1FB47}': () => `M0.5,1 L1,${2/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO LOWER MIDDLE RIGHT
248
- '\u{1FB48}': () => `M0,1 L1,${2/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT
249
- '\u{1FB49}': () => `M0.5,1 L1,${1/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER MIDDLE RIGHT
250
- '\u{1FB4A}': () => `M0,1 L1,${1/3} L1,1 Z`, // LOWER RIGHT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT
251
- '\u{1FB4B}': () => 'M0.5,1 L1,0 L1,1 Z', // LOWER RIGHT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT
252
-
253
- // LOWER LEFT BLOCK variants continued (1FB4C-1FB51) - large fills with upper-right cut
254
- '\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
255
- '\u{1FB4D}': () => `M0,0 L0,1 L1,1 L1,${1/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT
256
- '\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
257
- '\u{1FB4F}': () => `M0,0 L0,1 L1,1 L1,${2/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT
258
- '\u{1FB50}': () => 'M0.5,0 L0,0 L0,1 L1,1 Z', // LOWER LEFT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT
259
- '\u{1FB51}': () => `M0,${1/3} L0,1 L1,1 L1,${2/3} Z`, // LOWER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT
260
-
261
- // UPPER RIGHT BLOCK variants (1FB52-1FB56) - large fills with lower-left cut
262
- '\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
263
- '\u{1FB53}': () => `M0,${2/3} L1,1 L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL LOWER MIDDLE LEFT TO LOWER RIGHT
264
- '\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
265
- '\u{1FB55}': () => `M0,${1/3} L1,1 L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER RIGHT
266
- '\u{1FB56}': () => 'M0,0 L0.5,1 L1,1 L1,0 Z', // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER CENTRE
267
-
268
- // UPPER LEFT BLOCK variants (1FB57-1FB61) - small to large fills in upper-left
269
- '\u{1FB57}': () => `M0,${1/3} L0,0 L0.5,0 Z`, // UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER CENTRE
270
- '\u{1FB58}': () => `M0,${1/3} L0,0 L1,0 Z`, // UPPER LEFT BLOCK DIAGONAL UPPER MIDDLE LEFT TO UPPER RIGHT
271
- '\u{1FB59}': () => `M0,${2/3} L0,0 L0.5,0 Z`, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER CENTRE
272
- '\u{1FB5A}': () => `M0,${2/3} L0,0 L1,0 Z`, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER RIGHT
273
- '\u{1FB5B}': () => 'M0,1 L0,0 L0.5,0 Z', // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER CENTRE
274
- '\u{1FB5C}': () => `M0,${2/3} L0,0 L1,0 L1,${1/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER MIDDLE LEFT TO UPPER MIDDLE RIGHT
275
- '\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
276
- '\u{1FB5E}': () => `M0,1 L0,0 L1,0 L1,${2/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO LOWER MIDDLE RIGHT
277
- '\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
278
- '\u{1FB60}': () => `M0,1 L0,0 L1,0 L1,${1/3} Z`, // UPPER LEFT BLOCK DIAGONAL LOWER LEFT TO UPPER MIDDLE RIGHT
279
- '\u{1FB61}': () => 'M0.5,1 L0,1 L0,0 L1,0 Z', // UPPER LEFT BLOCK DIAGONAL LOWER CENTRE TO UPPER RIGHT
280
-
281
- // UPPER RIGHT BLOCK variants continued (1FB62-1FB67) - small to medium fills in upper-right
282
- '\u{1FB62}': () => `M0.5,0 L1,0 L1,${1/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO UPPER MIDDLE RIGHT
283
- '\u{1FB63}': () => `M0,0 L1,0 L1,${1/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO UPPER MIDDLE RIGHT
284
- '\u{1FB64}': () => `M0.5,0 L1,0 L1,${2/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER MIDDLE RIGHT
285
- '\u{1FB65}': () => `M0,0 L1,0 L1,${2/3} Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER LEFT TO LOWER MIDDLE RIGHT
286
- '\u{1FB66}': () => 'M0.5,0 L1,0 L1,1 Z', // UPPER RIGHT BLOCK DIAGONAL UPPER CENTRE TO LOWER RIGHT
287
- '\u{1FB67}': () => `M0,${1/3} L1,${2/3} L1,0 L0,0 Z`, // UPPER RIGHT BLOCK DIAGONAL UPPER MIDDLE LEFT TO LOWER MIDDLE RIGHT
288
-
289
- // Triangular blocks (1FB68-1FB6F)
290
- // Three-quarter blocks: full block minus one triangular quarter pointing to center
291
- '\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)
292
- '\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)
293
- '\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)
294
- '\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)
295
- '\u{1FB6C}': () => 'M0,0 L0.5,0.5 L0,1 Z', // LEFT TRIANGULAR ONE QUARTER BLOCK
296
- '\u{1FB6D}': () => 'M0,0 L1,0 L0.5,0.5 Z', // UPPER TRIANGULAR ONE QUARTER BLOCK
297
- '\u{1FB6E}': () => 'M1,0 L1,1 L0.5,0.5 Z', // RIGHT TRIANGULAR ONE QUARTER BLOCK
298
- '\u{1FB6F}': () => 'M0,1 L1,1 L0.5,0.5 Z' // LOWER TRIANGULAR ONE QUARTER BLOCK
299
- };
300
-
301
- type PatternDefinition = number[][];
302
-
303
- /**
304
- * Defines the repeating pattern used by special characters, the pattern is made up of a 2d array of
305
- * pixel values to be filled (1) or not filled (0).
306
- */
307
- const patternCharacterDefinitions: { [key: string]: PatternDefinition | undefined } = {
308
- // Shade characters (0x2591-0x2593)
309
- '░': [ // LIGHT SHADE (25%)
310
- [1, 0, 0, 0],
311
- [0, 0, 0, 0],
312
- [0, 0, 1, 0],
313
- [0, 0, 0, 0]
314
- ],
315
- '▒': [ // MEDIUM SHADE (50%)
316
- [1, 0],
317
- [0, 0],
318
- [0, 1],
319
- [0, 0]
320
- ],
321
- '▓': [ // DARK SHADE (75%)
322
- [0, 1],
323
- [1, 1],
324
- [1, 0],
325
- [1, 1]
326
- ]
327
- };
328
-
329
- const enum Shapes {
330
- /** │ */ TOP_TO_BOTTOM = 'M.5,0 L.5,1',
331
- /** ─ */ LEFT_TO_RIGHT = 'M0,.5 L1,.5',
332
-
333
- /** └ */ TOP_TO_RIGHT = 'M.5,0 L.5,.5 L1,.5',
334
- /** ┘ */ TOP_TO_LEFT = 'M.5,0 L.5,.5 L0,.5',
335
- /** ┐ */ LEFT_TO_BOTTOM = 'M0,.5 L.5,.5 L.5,1',
336
- /** ┌ */ RIGHT_TO_BOTTOM = 'M0.5,1 L.5,.5 L1,.5',
337
-
338
- /** ╵ */ MIDDLE_TO_TOP = 'M.5,.5 L.5,0',
339
- /** ╴ */ MIDDLE_TO_LEFT = 'M.5,.5 L0,.5',
340
- /** ╶ */ MIDDLE_TO_RIGHT = 'M.5,.5 L1,.5',
341
- /** ╷ */ MIDDLE_TO_BOTTOM = 'M.5,.5 L.5,1',
342
-
343
- /** ┴ */ T_TOP = 'M0,.5 L1,.5 M.5,.5 L.5,0',
344
- /** ┤ */ T_LEFT = 'M.5,0 L.5,1 M.5,.5 L0,.5',
345
- /** ├ */ T_RIGHT = 'M.5,0 L.5,1 M.5,.5 L1,.5',
346
- /** ┬ */ T_BOTTOM = 'M0,.5 L1,.5 M.5,.5 L.5,1',
347
-
348
- /** ┼ */ CROSS = 'M0,.5 L1,.5 M.5,0 L.5,1',
349
-
350
- /** ╌ */ TWO_DASHES_HORIZONTAL = 'M.1,.5 L.4,.5 M.6,.5 L.9,.5', // .2 empty, .3 filled
351
- /** ┄ */ THREE_DASHES_HORIZONTAL = 'M.0667,.5 L.2667,.5 M.4,.5 L.6,.5 M.7333,.5 L.9333,.5', // .1333 empty, .2 filled
352
- /** ┉ */ FOUR_DASHES_HORIZONTAL = 'M.05,.5 L.2,.5 M.3,.5 L.45,.5 M.55,.5 L.7,.5 M.8,.5 L.95,.5', // .1 empty, .15 filled
353
- /** ╎ */ TWO_DASHES_VERTICAL = 'M.5,.1 L.5,.4 M.5,.6 L.5,.9',
354
- /** ┆ */ THREE_DASHES_VERTICAL = 'M.5,.0667 L.5,.2667 M.5,.4 L.5,.6 M.5,.7333 L.5,.9333',
355
- /** ┊ */ FOUR_DASHES_VERTICAL = 'M.5,.05 L.5,.2 M.5,.3 L.5,.45 L.5,.55 M.5,.7 L.5,.95',
356
- }
357
-
358
- const enum Style {
359
- NORMAL = 1,
360
- BOLD = 3
361
- }
362
-
363
- /**
364
- * @param xp The percentage of 15% of the x axis.
365
- * @param yp The percentage of 15% of the x axis on the y axis.
366
- */
367
- type DrawFunctionDefinition = (xp: number, yp: number) => string;
368
-
369
- /**
370
- * This contains the definitions of all box drawing characters in the format of SVG paths (ie. the
371
- * svg d attribute).
372
- */
373
- export const boxDrawingDefinitions: { [character: string]: { [fontWeight: number]: string | DrawFunctionDefinition } | undefined } = {
374
- // Uniform normal and bold
375
- '─': { [Style.NORMAL]: Shapes.LEFT_TO_RIGHT },
376
- '━': { [Style.BOLD]: Shapes.LEFT_TO_RIGHT },
377
- '│': { [Style.NORMAL]: Shapes.TOP_TO_BOTTOM },
378
- '┃': { [Style.BOLD]: Shapes.TOP_TO_BOTTOM },
379
- '┌': { [Style.NORMAL]: Shapes.RIGHT_TO_BOTTOM },
380
- '┏': { [Style.BOLD]: Shapes.RIGHT_TO_BOTTOM },
381
- '┐': { [Style.NORMAL]: Shapes.LEFT_TO_BOTTOM },
382
- '┓': { [Style.BOLD]: Shapes.LEFT_TO_BOTTOM },
383
- '└': { [Style.NORMAL]: Shapes.TOP_TO_RIGHT },
384
- '┗': { [Style.BOLD]: Shapes.TOP_TO_RIGHT },
385
- '┘': { [Style.NORMAL]: Shapes.TOP_TO_LEFT },
386
- '┛': { [Style.BOLD]: Shapes.TOP_TO_LEFT },
387
- '├': { [Style.NORMAL]: Shapes.T_RIGHT },
388
- '┣': { [Style.BOLD]: Shapes.T_RIGHT },
389
- '┤': { [Style.NORMAL]: Shapes.T_LEFT },
390
- '┫': { [Style.BOLD]: Shapes.T_LEFT },
391
- '┬': { [Style.NORMAL]: Shapes.T_BOTTOM },
392
- '┳': { [Style.BOLD]: Shapes.T_BOTTOM },
393
- '┴': { [Style.NORMAL]: Shapes.T_TOP },
394
- '┻': { [Style.BOLD]: Shapes.T_TOP },
395
- '┼': { [Style.NORMAL]: Shapes.CROSS },
396
- '╋': { [Style.BOLD]: Shapes.CROSS },
397
- '╴': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT },
398
- '╸': { [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
399
- '╵': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP },
400
- '╹': { [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
401
- '╶': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT },
402
- '╺': { [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
403
- '╷': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM },
404
- '╻': { [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
405
-
406
- // Double border
407
- '═': { [Style.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` },
408
- '║': { [Style.NORMAL]: (xp, yp) => `M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` },
409
- '╒': { [Style.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 - yp} L1,${.5 - yp} M.5,${.5 + yp} L1,${.5 + yp}` },
410
- '╓': { [Style.NORMAL]: (xp, yp) => `M${.5 - xp},1 L${.5 - xp},.5 L1,.5 M${.5 + xp},.5 L${.5 + xp},1` },
411
- '╔': { [Style.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` },
412
- '╕': { [Style.NORMAL]: (xp, yp) => `M0,${.5 - yp} L.5,${.5 - yp} L.5,1 M0,${.5 + yp} L.5,${.5 + yp}` },
413
- '╖': { [Style.NORMAL]: (xp, yp) => `M${.5 + xp},1 L${.5 + xp},.5 L0,.5 M${.5 - xp},.5 L${.5 - xp},1` },
414
- '╗': { [Style.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` },
415
- '╘': { [Style.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 + yp} L1,${.5 + yp} M.5,${.5 - yp} L1,${.5 - yp}` },
416
- '╙': { [Style.NORMAL]: (xp, yp) => `M1,.5 L${.5 - xp},.5 L${.5 - xp},0 M${.5 + xp},.5 L${.5 + xp},0` },
417
- '╚': { [Style.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` },
418
- '╛': { [Style.NORMAL]: (xp, yp) => `M0,${.5 + yp} L.5,${.5 + yp} L.5,0 M0,${.5 - yp} L.5,${.5 - yp}` },
419
- '╜': { [Style.NORMAL]: (xp, yp) => `M0,.5 L${.5 + xp},.5 L${.5 + xp},0 M${.5 - xp},.5 L${.5 - xp},0` },
420
- '╝': { [Style.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` },
421
- '╞': { [Style.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M.5,${.5 - yp} L1,${.5 - yp} M.5,${.5 + yp} L1,${.5 + yp}` },
422
- '╟': { [Style.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` },
423
- '╠': { [Style.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` },
424
- '╡': { [Style.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M0,${.5 - yp} L.5,${.5 - yp} M0,${.5 + yp} L.5,${.5 + yp}` },
425
- '╢': { [Style.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` },
426
- '╣': { [Style.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` },
427
- '╤': { [Style.NORMAL]: (xp, yp) => `M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp} M.5,${.5 + yp} L.5,1` },
428
- '╥': { [Style.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},.5 L${.5 - xp},1 M${.5 + xp},.5 L${.5 + xp},1` },
429
- '╦': { [Style.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` },
430
- '╧': { [Style.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - yp} M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` },
431
- '╨': { [Style.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},.5 L${.5 - xp},0 M${.5 + xp},.5 L${.5 + xp},0` },
432
- '╩': { [Style.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` },
433
- '╪': { [Style.NORMAL]: (xp, yp) => `${Shapes.TOP_TO_BOTTOM} M0,${.5 - yp} L1,${.5 - yp} M0,${.5 + yp} L1,${.5 + yp}` },
434
- '╫': { [Style.NORMAL]: (xp, yp) => `${Shapes.LEFT_TO_RIGHT} M${.5 - xp},0 L${.5 - xp},1 M${.5 + xp},0 L${.5 + xp},1` },
435
- '╬': { [Style.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` },
436
-
437
- // Diagonal
438
- '╱': { [Style.NORMAL]: 'M1,0 L0,1' },
439
- '╲': { [Style.NORMAL]: 'M0,0 L1,1' },
440
- '╳': { [Style.NORMAL]: 'M1,0 L0,1 M0,0 L1,1' },
441
-
442
- // Mixed weight
443
- '╼': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
444
- '╽': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
445
- '╾': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
446
- '╿': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
447
- '┍': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
448
- '┎': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
449
- '┑': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
450
- '┒': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
451
- '┕': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
452
- '┖': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
453
- '┙': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
454
- '┚': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
455
- '┝': { [Style.NORMAL]: Shapes.TOP_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
456
- '┞': { [Style.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
457
- '┟': { [Style.NORMAL]: Shapes.TOP_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
458
- '┠': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: Shapes.TOP_TO_BOTTOM },
459
- '┡': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: Shapes.TOP_TO_RIGHT },
460
- '┢': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: Shapes.RIGHT_TO_BOTTOM },
461
- '┥': { [Style.NORMAL]: Shapes.TOP_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
462
- '┦': { [Style.NORMAL]: Shapes.LEFT_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
463
- '┧': { [Style.NORMAL]: Shapes.TOP_TO_LEFT, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
464
- '┨': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: Shapes.TOP_TO_BOTTOM },
465
- '┩': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: Shapes.TOP_TO_LEFT },
466
- '┪': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: Shapes.LEFT_TO_BOTTOM },
467
- '┭': { [Style.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
468
- '┮': { [Style.NORMAL]: Shapes.LEFT_TO_BOTTOM, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
469
- '┯': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: Shapes.LEFT_TO_RIGHT },
470
- '┰': { [Style.NORMAL]: Shapes.LEFT_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
471
- '┱': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: Shapes.LEFT_TO_BOTTOM },
472
- '┲': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: Shapes.RIGHT_TO_BOTTOM },
473
- '┵': { [Style.NORMAL]: Shapes.TOP_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
474
- '┶': { [Style.NORMAL]: Shapes.TOP_TO_LEFT, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
475
- '┷': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: Shapes.LEFT_TO_RIGHT },
476
- '┸': { [Style.NORMAL]: Shapes.LEFT_TO_RIGHT, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
477
- '┹': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: Shapes.TOP_TO_LEFT },
478
- '┺': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: Shapes.TOP_TO_RIGHT },
479
- '┽': { [Style.NORMAL]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_RIGHT}`, [Style.BOLD]: Shapes.MIDDLE_TO_LEFT },
480
- '┾': { [Style.NORMAL]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_LEFT}`, [Style.BOLD]: Shapes.MIDDLE_TO_RIGHT },
481
- '┿': { [Style.NORMAL]: Shapes.TOP_TO_BOTTOM, [Style.BOLD]: Shapes.LEFT_TO_RIGHT },
482
- '╀': { [Style.NORMAL]: `${Shapes.LEFT_TO_RIGHT} ${Shapes.MIDDLE_TO_BOTTOM}`, [Style.BOLD]: Shapes.MIDDLE_TO_TOP },
483
- '╁': { [Style.NORMAL]: `${Shapes.MIDDLE_TO_TOP} ${Shapes.LEFT_TO_RIGHT}`, [Style.BOLD]: Shapes.MIDDLE_TO_BOTTOM },
484
- '╂': { [Style.NORMAL]: Shapes.LEFT_TO_RIGHT, [Style.BOLD]: Shapes.TOP_TO_BOTTOM },
485
- '╃': { [Style.NORMAL]: Shapes.RIGHT_TO_BOTTOM, [Style.BOLD]: Shapes.TOP_TO_LEFT },
486
- '╄': { [Style.NORMAL]: Shapes.LEFT_TO_BOTTOM, [Style.BOLD]: Shapes.TOP_TO_RIGHT },
487
- '╅': { [Style.NORMAL]: Shapes.TOP_TO_RIGHT, [Style.BOLD]: Shapes.LEFT_TO_BOTTOM },
488
- '╆': { [Style.NORMAL]: Shapes.TOP_TO_LEFT, [Style.BOLD]: Shapes.RIGHT_TO_BOTTOM },
489
- '╇': { [Style.NORMAL]: Shapes.MIDDLE_TO_BOTTOM, [Style.BOLD]: `${Shapes.MIDDLE_TO_TOP} ${Shapes.LEFT_TO_RIGHT}` },
490
- '╈': { [Style.NORMAL]: Shapes.MIDDLE_TO_TOP, [Style.BOLD]: `${Shapes.LEFT_TO_RIGHT} ${Shapes.MIDDLE_TO_BOTTOM}` },
491
- '╉': { [Style.NORMAL]: Shapes.MIDDLE_TO_RIGHT, [Style.BOLD]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_LEFT}` },
492
- '╊': { [Style.NORMAL]: Shapes.MIDDLE_TO_LEFT, [Style.BOLD]: `${Shapes.TOP_TO_BOTTOM} ${Shapes.MIDDLE_TO_RIGHT}` },
493
-
494
- // Dashed
495
- '╌': { [Style.NORMAL]: Shapes.TWO_DASHES_HORIZONTAL },
496
- '╍': { [Style.BOLD]: Shapes.TWO_DASHES_HORIZONTAL },
497
- '┄': { [Style.NORMAL]: Shapes.THREE_DASHES_HORIZONTAL },
498
- '┅': { [Style.BOLD]: Shapes.THREE_DASHES_HORIZONTAL },
499
- '┈': { [Style.NORMAL]: Shapes.FOUR_DASHES_HORIZONTAL },
500
- '┉': { [Style.BOLD]: Shapes.FOUR_DASHES_HORIZONTAL },
501
- '╎': { [Style.NORMAL]: Shapes.TWO_DASHES_VERTICAL },
502
- '╏': { [Style.BOLD]: Shapes.TWO_DASHES_VERTICAL },
503
- '┆': { [Style.NORMAL]: Shapes.THREE_DASHES_VERTICAL },
504
- '┇': { [Style.BOLD]: Shapes.THREE_DASHES_VERTICAL },
505
- '┊': { [Style.NORMAL]: Shapes.FOUR_DASHES_VERTICAL },
506
- '┋': { [Style.BOLD]: Shapes.FOUR_DASHES_VERTICAL },
507
-
508
- // Curved
509
- '╭': { [Style.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,1,.5` },
510
- '╮': { [Style.NORMAL]: (xp, yp) => `M.5,1 L.5,${.5 + (yp / .15 * .5)} C.5,${.5 + (yp / .15 * .5)},.5,.5,0,.5` },
511
- '╯': { [Style.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,0,.5` },
512
- '╰': { [Style.NORMAL]: (xp, yp) => `M.5,0 L.5,${.5 - (yp / .15 * .5)} C.5,${.5 - (yp / .15 * .5)},.5,.5,1,.5` }
513
- };
514
-
515
- interface IVectorShape {
516
- d: string;
517
- type: VectorType;
518
- leftPadding?: number;
519
- rightPadding?: number;
520
- }
521
-
522
- const enum VectorType {
523
- FILL,
524
- STROKE
525
- }
526
-
527
- /**
528
- * This contains the definitions of the primarily used box drawing characters as vector shapes. The
529
- * reason these characters are defined specially is to avoid common problems if a user's font has
530
- * not been patched with powerline characters and also to get pixel perfect rendering as rendering
531
- * issues can occur around AA/SPAA.
532
- *
533
- * The line variants draw beyond the cell and get clipped to ensure the end of the line is not
534
- * visible.
535
- *
536
- * Original symbols defined in https://github.com/powerline/fontpatcher
537
- */
538
- export const powerlineDefinitions: { [index: string]: IVectorShape } = {
539
- // Git branch
540
- '\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: VectorType.FILL },
541
- // L N
542
- '\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: VectorType.FILL },
543
- // Lock
544
- '\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: VectorType.FILL },
545
- // Right triangle solid
546
- '\u{E0B0}': { d: 'M0,0 L1,.5 L0,1', type: VectorType.FILL, rightPadding: 2 },
547
- // Right triangle line
548
- '\u{E0B1}': { d: 'M-1,-.5 L1,.5 L-1,1.5', type: VectorType.STROKE, leftPadding: 1, rightPadding: 1 },
549
- // Left triangle solid
550
- '\u{E0B2}': { d: 'M1,0 L0,.5 L1,1', type: VectorType.FILL, leftPadding: 2 },
551
- // Left triangle line
552
- '\u{E0B3}': { d: 'M2,-.5 L0,.5 L2,1.5', type: VectorType.STROKE, leftPadding: 1, rightPadding: 1 },
553
- // Right semi-circle solid
554
- '\u{E0B4}': { d: 'M0,0 L0,1 C0.552,1,1,0.776,1,.5 C1,0.224,0.552,0,0,0', type: VectorType.FILL, rightPadding: 1 },
555
- // Right semi-circle line
556
- '\u{E0B5}': { d: 'M.2,1 C.422,1,.8,.826,.78,.5 C.8,.174,0.422,0,.2,0', type: VectorType.STROKE, rightPadding: 1 },
557
- // Left semi-circle solid
558
- '\u{E0B6}': { d: 'M1,0 L1,1 C0.448,1,0,0.776,0,.5 C0,0.224,0.448,0,1,0', type: VectorType.FILL, leftPadding: 1 },
559
- // Left semi-circle line
560
- '\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: VectorType.STROKE, leftPadding: 1 },
561
- // Lower left triangle
562
- '\u{E0B8}': { d: 'M-.5,-.5 L1.5,1.5 L-.5,1.5', type: VectorType.FILL },
563
- // Backslash separator
564
- '\u{E0B9}': { d: 'M-.5,-.5 L1.5,1.5', type: VectorType.STROKE, leftPadding: 1, rightPadding: 1 },
565
- // Lower right triangle
566
- '\u{E0BA}': { d: 'M1.5,-.5 L-.5,1.5 L1.5,1.5', type: VectorType.FILL },
567
- // Upper left triangle
568
- '\u{E0BC}': { d: 'M1.5,-.5 L-.5,1.5 L-.5,-.5', type: VectorType.FILL },
569
- // Forward slash separator
570
- '\u{E0BD}': { d: 'M1.5,-.5 L-.5,1.5', type: VectorType.STROKE, leftPadding: 1, rightPadding: 1 },
571
- // Upper right triangle
572
- '\u{E0BE}': { d: 'M-.5,-.5 L1.5,1.5 L1.5,-.5', type: VectorType.FILL }
573
- };
574
- // Forward slash separator redundant
575
- powerlineDefinitions['\u{E0BB}'] = powerlineDefinitions['\u{E0BD}'];
576
- // Backslash separator redundant
577
- powerlineDefinitions['\u{E0BF}'] = powerlineDefinitions['\u{E0B9}'];
578
-
579
- /**
580
- * Try drawing a custom block element or box drawing character, returning whether it was
581
- * successfully drawn.
582
- */
583
- export function tryDrawCustomChar(
584
- ctx: CanvasRenderingContext2D,
585
- c: string,
586
- xOffset: number,
587
- yOffset: number,
588
- deviceCellWidth: number,
589
- deviceCellHeight: number,
590
- fontSize: number,
591
- devicePixelRatio: number
592
- ): boolean {
593
- const blockElementDefinition = blockElementDefinitions[c];
594
- if (blockElementDefinition) {
595
- drawBlockVectorChar(ctx, blockElementDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
596
- return true;
597
- }
598
-
599
- const symbolsForLegacyComputingDefinition = symbolsForLegacyComputingDefinitions[c];
600
- if (symbolsForLegacyComputingDefinition) {
601
- drawPathDefinitionCharacter(ctx, symbolsForLegacyComputingDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
602
- return true;
603
- }
604
-
605
- const patternDefinition = patternCharacterDefinitions[c];
606
- if (patternDefinition) {
607
- drawPatternChar(ctx, patternDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight);
608
- return true;
609
- }
610
-
611
- const boxDrawingDefinition = boxDrawingDefinitions[c];
612
- if (boxDrawingDefinition) {
613
- drawBoxDrawingChar(ctx, boxDrawingDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, devicePixelRatio);
614
- return true;
615
- }
616
-
617
- const powerlineDefinition = powerlineDefinitions[c];
618
- if (powerlineDefinition) {
619
- drawPowerlineChar(ctx, powerlineDefinition, xOffset, yOffset, deviceCellWidth, deviceCellHeight, fontSize, devicePixelRatio);
620
- return true;
621
- }
622
-
623
- return false;
624
- }
625
-
626
- function drawBlockVectorChar(
627
- ctx: CanvasRenderingContext2D,
628
- charDefinition: IBlockVector[],
629
- xOffset: number,
630
- yOffset: number,
631
- deviceCellWidth: number,
632
- deviceCellHeight: number
633
- ): void {
634
- for (let i = 0; i < charDefinition.length; i++) {
635
- const box = charDefinition[i];
636
- const xEighth = deviceCellWidth / 8;
637
- const yEighth = deviceCellHeight / 8;
638
- ctx.fillRect(
639
- xOffset + box.x * xEighth,
640
- yOffset + box.y * yEighth,
641
- box.w * xEighth,
642
- box.h * yEighth
643
- );
644
- }
645
- }
646
-
647
- function drawPathDefinitionCharacter(
648
- ctx: CanvasRenderingContext2D,
649
- charDefinition: DrawFunctionDefinition,
650
- xOffset: number,
651
- yOffset: number,
652
- deviceCellWidth: number,
653
- deviceCellHeight: number
654
- ): void {
655
- const instructions = charDefinition(0, 0);
656
- ctx.beginPath();
657
- for (const instruction of instructions.split(' ')) {
658
- const type = instruction[0];
659
- const args: string[] = instruction.substring(1).split(',');
660
- if (!args[0] || !args[1]) {
661
- if (type === 'Z') {
662
- ctx.closePath();
663
- }
664
- continue;
665
- }
666
- const translatedArgs = args.map((e, i) => {
667
- const val = parseFloat(e);
668
- return i % 2 === 0
669
- ? xOffset + val * deviceCellWidth
670
- : yOffset + val * deviceCellHeight;
671
- });
672
- if (type === 'M') {
673
- ctx.moveTo(translatedArgs[0], translatedArgs[1]);
674
- } else if (type === 'L') {
675
- ctx.lineTo(translatedArgs[0], translatedArgs[1]);
676
- }
677
- }
678
- ctx.fill();
679
- }
680
-
681
- const cachedPatterns: Map<PatternDefinition, Map</* fillStyle */string, CanvasPattern>> = new Map();
682
-
683
- function drawPatternChar(
684
- ctx: CanvasRenderingContext2D,
685
- charDefinition: number[][],
686
- xOffset: number,
687
- yOffset: number,
688
- deviceCellWidth: number,
689
- deviceCellHeight: number
690
- ): void {
691
- let patternSet = cachedPatterns.get(charDefinition);
692
- if (!patternSet) {
693
- patternSet = new Map();
694
- cachedPatterns.set(charDefinition, patternSet);
695
- }
696
- const fillStyle = ctx.fillStyle;
697
- if (typeof fillStyle !== 'string') {
698
- throw new Error(`Unexpected fillStyle type "${fillStyle}"`);
699
- }
700
- let pattern = patternSet.get(fillStyle);
701
- if (!pattern) {
702
- const width = charDefinition[0].length;
703
- const height = charDefinition.length;
704
- const tmpCanvas = ctx.canvas.ownerDocument.createElement('canvas');
705
- tmpCanvas.width = width;
706
- tmpCanvas.height = height;
707
- const tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d'));
708
- const imageData = new ImageData(width, height);
709
-
710
- // Extract rgba from fillStyle
711
- let r: number;
712
- let g: number;
713
- let b: number;
714
- let a: number;
715
- if (fillStyle.startsWith('#')) {
716
- r = parseInt(fillStyle.slice(1, 3), 16);
717
- g = parseInt(fillStyle.slice(3, 5), 16);
718
- b = parseInt(fillStyle.slice(5, 7), 16);
719
- a = fillStyle.length > 7 && parseInt(fillStyle.slice(7, 9), 16) || 1;
720
- } else if (fillStyle.startsWith('rgba')) {
721
- ([r, g, b, a] = fillStyle.substring(5, fillStyle.length - 1).split(',').map(e => parseFloat(e)));
722
- } else {
723
- throw new Error(`Unexpected fillStyle color format "${fillStyle}" when drawing pattern glyph`);
724
- }
725
-
726
- for (let y = 0; y < height; y++) {
727
- for (let x = 0; x < width; x++) {
728
- imageData.data[(y * width + x) * 4 ] = r;
729
- imageData.data[(y * width + x) * 4 + 1] = g;
730
- imageData.data[(y * width + x) * 4 + 2] = b;
731
- imageData.data[(y * width + x) * 4 + 3] = charDefinition[y][x] * (a * 255);
732
- }
733
- }
734
- tmpCtx.putImageData(imageData, 0, 0);
735
- pattern = throwIfFalsy(ctx.createPattern(tmpCanvas, null));
736
- patternSet.set(fillStyle, pattern);
737
- }
738
- ctx.fillStyle = pattern;
739
- ctx.fillRect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
740
- }
741
-
742
- /**
743
- * Draws the following box drawing characters by mapping a subset of SVG d attribute instructions to
744
- * canvas draw calls.
745
- *
746
- * Box styles: ┎┰┒┍┯┑╓╥╖╒╤╕ ┏┳┓┌┲┓┌┬┐┏┱┐
747
- * ┌─┬─┐ ┏━┳━┓ ╔═╦═╗ ┠╂┨┝┿┥╟╫╢╞╪╡ ┡╇┩├╊┫┢╈┪┣╉┤
748
- * │ │ │ ┃ ┃ ┃ ║ ║ ║ ┖┸┚┕┷┙╙╨╜╘╧╛ └┴┘└┺┛┗┻┛┗┹┘
749
- * ├─┼─┤ ┣━╋━┫ ╠═╬═╣ ┏┱┐┌┲┓┌┬┐┌┬┐ ┏┳┓┌┮┓┌┬┐┏┭┐
750
- * │ │ │ ┃ ┃ ┃ ║ ║ ║ ┡╃┤├╄┩├╆┪┢╅┤ ┞╀┦├┾┫┟╁┧┣┽┤
751
- * └─┴─┘ ┗━┻━┛ ╚═╩═╝ └┴┘└┴┘└┺┛┗┹┘ └┴┘└┶┛┗┻┛┗┵┘
752
- *
753
- * Other:
754
- * ╭─╮ ╲ ╱ ╷╻╎╏┆┇┊┋ ╺╾╴ ╌╌╌ ┄┄┄ ┈┈┈
755
- * │ │ ╳ ╽╿╎╏┆┇┊┋ ╶╼╸ ╍╍╍ ┅┅┅ ┉┉┉
756
- * ╰─╯ ╱ ╲ ╹╵╎╏┆┇┊┋
757
- *
758
- * All box drawing characters:
759
- * ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏
760
- * ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟
761
- * ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯
762
- * ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿
763
- * ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏
764
- * ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟
765
- * ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯
766
- * ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
767
- *
768
- * ---
769
- *
770
- * Box drawing alignment tests: █
771
- * ▉
772
- * ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
773
- * ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
774
- * ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
775
- * ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
776
- * ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
777
- * ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
778
- * ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
779
- *
780
- * Source: https://www.w3.org/2001/06/utf-8-test/UTF-8-demo.html
781
- */
782
- function drawBoxDrawingChar(
783
- ctx: CanvasRenderingContext2D,
784
- charDefinition: { [fontWeight: number]: string | ((xp: number, yp: number) => string) },
785
- xOffset: number,
786
- yOffset: number,
787
- deviceCellWidth: number,
788
- deviceCellHeight: number,
789
- devicePixelRatio: number
790
- ): void {
791
- ctx.strokeStyle = ctx.fillStyle;
792
- for (const [fontWeight, instructions] of Object.entries(charDefinition)) {
793
- ctx.beginPath();
794
- ctx.lineWidth = devicePixelRatio * Number.parseInt(fontWeight);
795
- let actualInstructions: string;
796
- if (typeof instructions === 'function') {
797
- const xp = .15;
798
- const yp = .15 / deviceCellHeight * deviceCellWidth;
799
- actualInstructions = instructions(xp, yp);
800
- } else {
801
- actualInstructions = instructions;
802
- }
803
- for (const instruction of actualInstructions.split(' ')) {
804
- const type = instruction[0];
805
- const f = svgToCanvasInstructionMap[type];
806
- if (!f) {
807
- console.error(`Could not find drawing instructions for "${type}"`);
808
- continue;
809
- }
810
- const args: string[] = instruction.substring(1).split(',');
811
- if (!args[0] || !args[1]) {
812
- continue;
813
- }
814
- f(ctx, translateArgs(args, deviceCellWidth, deviceCellHeight, xOffset, yOffset, true, devicePixelRatio));
815
- }
816
- ctx.stroke();
817
- ctx.closePath();
818
- }
819
- }
820
-
821
- function drawPowerlineChar(
822
- ctx: CanvasRenderingContext2D,
823
- charDefinition: IVectorShape,
824
- xOffset: number,
825
- yOffset: number,
826
- deviceCellWidth: number,
827
- deviceCellHeight: number,
828
- fontSize: number,
829
- devicePixelRatio: number
830
- ): void {
831
- // Clip the cell to make sure drawing doesn't occur beyond bounds
832
- const clipRegion = new Path2D();
833
- clipRegion.rect(xOffset, yOffset, deviceCellWidth, deviceCellHeight);
834
- ctx.clip(clipRegion);
835
-
836
- ctx.beginPath();
837
- // Scale the stroke with DPR and font size
838
- const cssLineWidth = fontSize / 12;
839
- ctx.lineWidth = devicePixelRatio * cssLineWidth;
840
- for (const instruction of charDefinition.d.split(' ')) {
841
- const type = instruction[0];
842
- const f = svgToCanvasInstructionMap[type];
843
- if (!f) {
844
- console.error(`Could not find drawing instructions for "${type}"`);
845
- continue;
846
- }
847
- const args: string[] = instruction.substring(1).split(',');
848
- if (!args[0] || !args[1]) {
849
- continue;
850
- }
851
- f(ctx, translateArgs(
852
- args,
853
- deviceCellWidth,
854
- deviceCellHeight,
855
- xOffset,
856
- yOffset,
857
- false,
858
- devicePixelRatio,
859
- (charDefinition.leftPadding ?? 0) * (cssLineWidth / 2),
860
- (charDefinition.rightPadding ?? 0) * (cssLineWidth / 2)
861
- ));
862
- }
863
- if (charDefinition.type === VectorType.STROKE) {
864
- ctx.strokeStyle = ctx.fillStyle;
865
- ctx.stroke();
866
- } else {
867
- ctx.fill();
868
- }
869
- ctx.closePath();
870
- }
871
-
872
- function clamp(value: number, max: number, min: number = 0): number {
873
- return Math.max(Math.min(value, max), min);
874
- }
875
-
876
- const svgToCanvasInstructionMap: { [index: string]: any } = {
877
- 'C': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.bezierCurveTo(args[0], args[1], args[2], args[3], args[4], args[5]),
878
- 'L': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.lineTo(args[0], args[1]),
879
- 'M': (ctx: CanvasRenderingContext2D, args: number[]) => ctx.moveTo(args[0], args[1])
880
- };
881
-
882
- function translateArgs(args: string[], cellWidth: number, cellHeight: number, xOffset: number, yOffset: number, doClamp: boolean, devicePixelRatio: number, leftPadding: number = 0, rightPadding: number = 0): number[] {
883
- const result = args.map(e => parseFloat(e) || parseInt(e));
884
-
885
- if (result.length < 2) {
886
- throw new Error('Too few arguments for instruction');
887
- }
888
-
889
- for (let x = 0; x < result.length; x += 2) {
890
- // Translate from 0-1 to 0-cellWidth
891
- result[x] *= cellWidth - (leftPadding * devicePixelRatio) - (rightPadding * devicePixelRatio);
892
- // Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
893
- // line at 100% devicePixelRatio
894
- if (doClamp && result[x] !== 0) {
895
- result[x] = clamp(Math.round(result[x] + 0.5) - 0.5, cellWidth, 0);
896
- }
897
- // Apply the cell's offset (ie. x*cellWidth)
898
- result[x] += xOffset + (leftPadding * devicePixelRatio);
899
- }
900
-
901
- for (let y = 1; y < result.length; y += 2) {
902
- // Translate from 0-1 to 0-cellHeight
903
- result[y] *= cellHeight;
904
- // Ensure coordinate doesn't escape cell bounds and round to the nearest 0.5 to ensure a crisp
905
- // line at 100% devicePixelRatio
906
- if (doClamp && result[y] !== 0) {
907
- result[y] = clamp(Math.round(result[y] + 0.5) - 0.5, cellHeight, 0);
908
- }
909
- // Apply the cell's offset (ie. x*cellHeight)
910
- result[y] += yOffset;
911
- }
912
-
913
- return result;
914
- }