shellfie 1.3.6 → 2.0.0

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.
Files changed (117) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +223 -160
  3. package/dist/fonts/index.d.ts +21 -0
  4. package/dist/fonts/index.d.ts.map +1 -0
  5. package/dist/fonts/index.js +92 -0
  6. package/dist/fonts/index.js.map +1 -0
  7. package/dist/index.d.ts +14 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +124 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/parser/index.d.ts +6 -0
  12. package/dist/parser/index.d.ts.map +1 -0
  13. package/dist/parser/index.js +189 -0
  14. package/dist/parser/index.js.map +1 -0
  15. package/dist/parser/types.d.ts +17 -0
  16. package/dist/parser/types.d.ts.map +1 -0
  17. package/dist/parser/types.js +3 -0
  18. package/dist/parser/types.js.map +1 -0
  19. package/dist/renderer/colors.d.ts +9 -0
  20. package/dist/renderer/colors.d.ts.map +1 -0
  21. package/dist/renderer/colors.js +100 -0
  22. package/dist/renderer/colors.js.map +1 -0
  23. package/dist/renderer/customGlyphs.d.ts +17 -0
  24. package/dist/renderer/customGlyphs.d.ts.map +1 -0
  25. package/dist/renderer/customGlyphs.js +730 -0
  26. package/dist/renderer/customGlyphs.js.map +1 -0
  27. package/dist/renderer/index.d.ts +10 -0
  28. package/dist/renderer/index.d.ts.map +1 -0
  29. package/dist/renderer/index.js +231 -0
  30. package/dist/renderer/index.js.map +1 -0
  31. package/dist/renderer/text.d.ts +13 -0
  32. package/dist/renderer/text.d.ts.map +1 -0
  33. package/dist/renderer/text.js +128 -0
  34. package/dist/renderer/text.js.map +1 -0
  35. package/dist/templates/base.d.ts +5 -0
  36. package/dist/templates/base.d.ts.map +1 -0
  37. package/dist/templates/base.js +37 -0
  38. package/dist/templates/base.js.map +1 -0
  39. package/dist/templates/index.d.ts +13 -0
  40. package/dist/templates/index.d.ts.map +1 -0
  41. package/dist/templates/index.js +34 -0
  42. package/dist/templates/index.js.map +1 -0
  43. package/dist/templates/macos.d.ts +12 -0
  44. package/dist/templates/macos.d.ts.map +1 -0
  45. package/dist/templates/macos.js +34 -0
  46. package/dist/templates/macos.js.map +1 -0
  47. package/dist/templates/minimal.d.ts +13 -0
  48. package/dist/templates/minimal.d.ts.map +1 -0
  49. package/dist/templates/minimal.js +27 -0
  50. package/dist/templates/minimal.js.map +1 -0
  51. package/dist/templates/windows.d.ts +12 -0
  52. package/dist/templates/windows.d.ts.map +1 -0
  53. package/dist/templates/windows.js +34 -0
  54. package/dist/templates/windows.js.map +1 -0
  55. package/dist/themes/catppuccin-mocha.d.ts +3 -0
  56. package/dist/themes/catppuccin-mocha.d.ts.map +1 -0
  57. package/dist/themes/catppuccin-mocha.js +27 -0
  58. package/dist/themes/catppuccin-mocha.js.map +1 -0
  59. package/dist/themes/dracula.d.ts +3 -0
  60. package/dist/themes/dracula.d.ts.map +1 -0
  61. package/dist/themes/dracula.js +27 -0
  62. package/dist/themes/dracula.js.map +1 -0
  63. package/dist/themes/github-dark.d.ts +3 -0
  64. package/dist/themes/github-dark.d.ts.map +1 -0
  65. package/dist/themes/github-dark.js +27 -0
  66. package/dist/themes/github-dark.js.map +1 -0
  67. package/dist/themes/github-light.d.ts +3 -0
  68. package/dist/themes/github-light.d.ts.map +1 -0
  69. package/dist/themes/github-light.js +27 -0
  70. package/dist/themes/github-light.js.map +1 -0
  71. package/dist/themes/gruvbox-dark.d.ts +3 -0
  72. package/dist/themes/gruvbox-dark.d.ts.map +1 -0
  73. package/dist/themes/gruvbox-dark.js +27 -0
  74. package/dist/themes/gruvbox-dark.js.map +1 -0
  75. package/dist/themes/gruvbox-light.d.ts +3 -0
  76. package/dist/themes/gruvbox-light.d.ts.map +1 -0
  77. package/dist/themes/gruvbox-light.js +27 -0
  78. package/dist/themes/gruvbox-light.js.map +1 -0
  79. package/dist/themes/index.d.ts +27 -0
  80. package/dist/themes/index.d.ts.map +1 -0
  81. package/dist/themes/index.js +54 -0
  82. package/dist/themes/index.js.map +1 -0
  83. package/dist/themes/monokai.d.ts +3 -0
  84. package/dist/themes/monokai.d.ts.map +1 -0
  85. package/dist/themes/monokai.js +27 -0
  86. package/dist/themes/monokai.js.map +1 -0
  87. package/dist/themes/nord.d.ts +3 -0
  88. package/dist/themes/nord.d.ts.map +1 -0
  89. package/dist/themes/nord.js +27 -0
  90. package/dist/themes/nord.js.map +1 -0
  91. package/dist/themes/one-dark.d.ts +3 -0
  92. package/dist/themes/one-dark.d.ts.map +1 -0
  93. package/dist/themes/one-dark.js +27 -0
  94. package/dist/themes/one-dark.js.map +1 -0
  95. package/dist/themes/solarized-dark.d.ts +3 -0
  96. package/dist/themes/solarized-dark.d.ts.map +1 -0
  97. package/dist/themes/solarized-dark.js +27 -0
  98. package/dist/themes/solarized-dark.js.map +1 -0
  99. package/dist/themes/solarized-light.d.ts +3 -0
  100. package/dist/themes/solarized-light.d.ts.map +1 -0
  101. package/dist/themes/solarized-light.js +27 -0
  102. package/dist/themes/solarized-light.js.map +1 -0
  103. package/dist/themes/tokyo-night.d.ts +3 -0
  104. package/dist/themes/tokyo-night.d.ts.map +1 -0
  105. package/dist/themes/tokyo-night.js +27 -0
  106. package/dist/themes/tokyo-night.js.map +1 -0
  107. package/dist/types.d.ts +151 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +3 -0
  110. package/dist/types.js.map +1 -0
  111. package/package.json +32 -21
  112. package/shellfie.d.ts +0 -29
  113. package/shellfie.js +0 -115
  114. package/template/template.css +0 -58
  115. package/template/template.html +0 -21
  116. package/utils/config.js +0 -41
  117. package/utils/styles.js +0 -32
@@ -0,0 +1,730 @@
1
+ "use strict";
2
+ // Custom Glyph Rendering for Box Drawing and Block Element Characters
3
+ // Supported Unicode ranges:
4
+ // - Box Drawing (U+2500-U+257F)
5
+ // - Block Elements (U+2580-U+259F)
6
+ // - Braille Patterns (U+2800-U+28FF)
7
+ // - Symbols for Legacy Computing (U+1FB00-U+1FBFF)
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.isCustomGlyph = isCustomGlyph;
10
+ exports.containsCustomGlyphs = containsCustomGlyphs;
11
+ exports.renderCustomGlyph = renderCustomGlyph;
12
+ function isCustomGlyph(codePoint) {
13
+ return ((codePoint >= 0x2500 && codePoint <= 0x257f) ||
14
+ (codePoint >= 0x2580 && codePoint <= 0x259f) ||
15
+ codePoint === 0x25a0 ||
16
+ (codePoint >= 0x2800 && codePoint <= 0x28ff) ||
17
+ (codePoint >= 0x1fb00 && codePoint <= 0x1fbff));
18
+ }
19
+ function containsCustomGlyphs(text) {
20
+ for (const char of text) {
21
+ const codePoint = char.codePointAt(0);
22
+ if (codePoint !== undefined && isCustomGlyph(codePoint)) {
23
+ return true;
24
+ }
25
+ }
26
+ return false;
27
+ }
28
+ function renderCustomGlyph(char, ctx) {
29
+ const codePoint = char.codePointAt(0);
30
+ if (codePoint === undefined) {
31
+ return { svg: '', handled: false };
32
+ }
33
+ if (codePoint >= 0x2500 && codePoint <= 0x257f) {
34
+ return renderBoxDrawing(codePoint, ctx);
35
+ }
36
+ if (codePoint >= 0x2580 && codePoint <= 0x259f) {
37
+ return renderBlockElement(codePoint, ctx);
38
+ }
39
+ // Black Square (U+25A0) - render as cell-width square, vertically centered
40
+ if (codePoint === 0x25a0) {
41
+ const { cellWidth, cellHeight, x, y, color } = ctx;
42
+ const size = cellWidth;
43
+ const squareY = y + (cellHeight - size) / 2;
44
+ return {
45
+ svg: `<rect x="${x}" y="${squareY}" width="${size}" height="${size}" fill="${color}" shape-rendering="crispEdges"/>`,
46
+ handled: true,
47
+ };
48
+ }
49
+ if (codePoint >= 0x2800 && codePoint <= 0x28ff) {
50
+ return renderBraille(codePoint, ctx);
51
+ }
52
+ if (codePoint >= 0x1fb00 && codePoint <= 0x1fbff) {
53
+ return renderLegacyComputing(codePoint, ctx);
54
+ }
55
+ return { svg: '', handled: false };
56
+ }
57
+ // Segment values: 0=none, 1=light, 2=heavy, 3=double
58
+ function getBoxSegments(codePoint) {
59
+ const boxMap = {
60
+ 0x2500: [0, 0, 1, 1], // ─
61
+ 0x2501: [0, 0, 2, 2], // ━
62
+ 0x2502: [1, 1, 0, 0], // │
63
+ 0x2503: [2, 2, 0, 0], // ┃
64
+ 0x2504: [0, 0, 1, 1], // ┄
65
+ 0x2505: [0, 0, 2, 2], // ┅
66
+ 0x2506: [1, 1, 0, 0], // ┆
67
+ 0x2507: [2, 2, 0, 0], // ┇
68
+ 0x2508: [0, 0, 1, 1], // ┈
69
+ 0x2509: [0, 0, 2, 2], // ┉
70
+ 0x250a: [1, 1, 0, 0], // ┊
71
+ 0x250b: [2, 2, 0, 0], // ┋
72
+ 0x250c: [0, 1, 0, 1], // ┌
73
+ 0x250d: [0, 1, 0, 2], // ┍
74
+ 0x250e: [0, 2, 0, 1], // ┎
75
+ 0x250f: [0, 2, 0, 2], // ┏
76
+ 0x2510: [0, 1, 1, 0], // ┐
77
+ 0x2511: [0, 1, 2, 0], // ┑
78
+ 0x2512: [0, 2, 1, 0], // ┒
79
+ 0x2513: [0, 2, 2, 0], // ┓
80
+ 0x2514: [1, 0, 0, 1], // └
81
+ 0x2515: [1, 0, 0, 2], // ┕
82
+ 0x2516: [2, 0, 0, 1], // ┖
83
+ 0x2517: [2, 0, 0, 2], // ┗
84
+ 0x2518: [1, 0, 1, 0], // ┘
85
+ 0x2519: [1, 0, 2, 0], // ┙
86
+ 0x251a: [2, 0, 1, 0], // ┚
87
+ 0x251b: [2, 0, 2, 0], // ┛
88
+ 0x251c: [1, 1, 0, 1], // ├
89
+ 0x251d: [1, 1, 0, 2], // ┝
90
+ 0x251e: [2, 1, 0, 1], // ┞
91
+ 0x251f: [1, 2, 0, 1], // ┟
92
+ 0x2520: [2, 2, 0, 1], // ┠
93
+ 0x2521: [2, 1, 0, 2], // ┡
94
+ 0x2522: [1, 2, 0, 2], // ┢
95
+ 0x2523: [2, 2, 0, 2], // ┣
96
+ 0x2524: [1, 1, 1, 0], // ┤
97
+ 0x2525: [1, 1, 2, 0], // ┥
98
+ 0x2526: [2, 1, 1, 0], // ┦
99
+ 0x2527: [1, 2, 1, 0], // ┧
100
+ 0x2528: [2, 2, 1, 0], // ┨
101
+ 0x2529: [2, 1, 2, 0], // ┩
102
+ 0x252a: [1, 2, 2, 0], // ┪
103
+ 0x252b: [2, 2, 2, 0], // ┫
104
+ 0x252c: [0, 1, 1, 1], // ┬
105
+ 0x252d: [0, 1, 2, 1], // ┭
106
+ 0x252e: [0, 1, 1, 2], // ┮
107
+ 0x252f: [0, 1, 2, 2], // ┯
108
+ 0x2530: [0, 2, 1, 1], // ┰
109
+ 0x2531: [0, 2, 2, 1], // ┱
110
+ 0x2532: [0, 2, 1, 2], // ┲
111
+ 0x2533: [0, 2, 2, 2], // ┳
112
+ 0x2534: [1, 0, 1, 1], // ┴
113
+ 0x2535: [1, 0, 2, 1], // ┵
114
+ 0x2536: [1, 0, 1, 2], // ┶
115
+ 0x2537: [1, 0, 2, 2], // ┷
116
+ 0x2538: [2, 0, 1, 1], // ┸
117
+ 0x2539: [2, 0, 2, 1], // ┹
118
+ 0x253a: [2, 0, 1, 2], // ┺
119
+ 0x253b: [2, 0, 2, 2], // ┻
120
+ 0x253c: [1, 1, 1, 1], // ┼
121
+ 0x253d: [1, 1, 2, 1], // ┽
122
+ 0x253e: [1, 1, 1, 2], // ┾
123
+ 0x253f: [1, 1, 2, 2], // ┿
124
+ 0x2540: [2, 1, 1, 1], // ╀
125
+ 0x2541: [1, 2, 1, 1], // ╁
126
+ 0x2542: [2, 2, 1, 1], // ╂
127
+ 0x2543: [2, 1, 2, 1], // ╃
128
+ 0x2544: [2, 1, 1, 2], // ╄
129
+ 0x2545: [1, 2, 2, 1], // ╅
130
+ 0x2546: [1, 2, 1, 2], // ╆
131
+ 0x2547: [2, 1, 2, 2], // ╇
132
+ 0x2548: [1, 2, 2, 2], // ╈
133
+ 0x2549: [2, 2, 2, 1], // ╉
134
+ 0x254a: [2, 2, 1, 2], // ╊
135
+ 0x254b: [2, 2, 2, 2], // ╋
136
+ 0x254c: [0, 0, 1, 1], // ╌
137
+ 0x254d: [0, 0, 2, 2], // ╍
138
+ 0x254e: [1, 1, 0, 0], // ╎
139
+ 0x254f: [2, 2, 0, 0], // ╏
140
+ 0x2550: [0, 0, 3, 3], // ═
141
+ 0x2551: [3, 3, 0, 0], // ║
142
+ 0x2552: [0, 1, 0, 3], // ╒
143
+ 0x2553: [0, 3, 0, 1], // ╓
144
+ 0x2554: [0, 3, 0, 3], // ╔
145
+ 0x2555: [0, 1, 3, 0], // ╕
146
+ 0x2556: [0, 3, 1, 0], // ╖
147
+ 0x2557: [0, 3, 3, 0], // ╗
148
+ 0x2558: [1, 0, 0, 3], // ╘
149
+ 0x2559: [3, 0, 0, 1], // ╙
150
+ 0x255a: [3, 0, 0, 3], // ╚
151
+ 0x255b: [1, 0, 3, 0], // ╛
152
+ 0x255c: [3, 0, 1, 0], // ╜
153
+ 0x255d: [3, 0, 3, 0], // ╝
154
+ 0x255e: [1, 1, 0, 3], // ╞
155
+ 0x255f: [3, 3, 0, 1], // ╟
156
+ 0x2560: [3, 3, 0, 3], // ╠
157
+ 0x2561: [1, 1, 3, 0], // ╡
158
+ 0x2562: [3, 3, 1, 0], // ╢
159
+ 0x2563: [3, 3, 3, 0], // ╣
160
+ 0x2564: [0, 1, 3, 3], // ╤
161
+ 0x2565: [0, 3, 1, 1], // ╥
162
+ 0x2566: [0, 3, 3, 3], // ╦
163
+ 0x2567: [1, 0, 3, 3], // ╧
164
+ 0x2568: [3, 0, 1, 1], // ╨
165
+ 0x2569: [3, 0, 3, 3], // ╩
166
+ 0x256a: [1, 1, 3, 3], // ╪
167
+ 0x256b: [3, 3, 1, 1], // ╫
168
+ 0x256c: [3, 3, 3, 3], // ╬
169
+ 0x256d: [0, 1, 0, 1], // ╭
170
+ 0x256e: [0, 1, 1, 0], // ╮
171
+ 0x256f: [1, 0, 1, 0], // ╯
172
+ 0x2570: [1, 0, 0, 1], // ╰
173
+ 0x2574: [0, 0, 1, 0], // ╴
174
+ 0x2575: [1, 0, 0, 0], // ╵
175
+ 0x2576: [0, 0, 0, 1], // ╶
176
+ 0x2577: [0, 1, 0, 0], // ╷
177
+ 0x2578: [0, 0, 2, 0], // ╸
178
+ 0x2579: [2, 0, 0, 0], // ╹
179
+ 0x257a: [0, 0, 0, 2], // ╺
180
+ 0x257b: [0, 2, 0, 0], // ╻
181
+ 0x257c: [0, 0, 1, 2], // ╼
182
+ 0x257d: [1, 2, 0, 0], // ╽
183
+ 0x257e: [0, 0, 2, 1], // ╾
184
+ 0x257f: [2, 1, 0, 0], // ╿
185
+ };
186
+ const segments = boxMap[codePoint];
187
+ if (!segments)
188
+ return null;
189
+ return {
190
+ up: segments[0],
191
+ down: segments[1],
192
+ left: segments[2],
193
+ right: segments[3],
194
+ };
195
+ }
196
+ function renderBoxDrawing(codePoint, ctx) {
197
+ if (codePoint >= 0x2571 && codePoint <= 0x2573) {
198
+ return renderDiagonalLine(codePoint, ctx);
199
+ }
200
+ const segments = getBoxSegments(codePoint);
201
+ if (!segments) {
202
+ return { svg: '', handled: false };
203
+ }
204
+ const { cellWidth, cellHeight, x, y, color, lineWidth, heavyLineWidth } = ctx;
205
+ const centerX = x + cellWidth / 2;
206
+ const centerY = y + cellHeight / 2;
207
+ const getWidth = (type) => {
208
+ if (type === 0)
209
+ return 0;
210
+ if (type === 1)
211
+ return lineWidth;
212
+ if (type === 2)
213
+ return heavyLineWidth;
214
+ return lineWidth;
215
+ };
216
+ const doubleOffset = lineWidth * 1.5;
217
+ const hasDoubleUp = segments.up === 3;
218
+ const hasDoubleDown = segments.down === 3;
219
+ const hasDoubleLeft = segments.left === 3;
220
+ const hasDoubleRight = segments.right === 3;
221
+ if ((hasDoubleUp || hasDoubleDown) && (hasDoubleLeft || hasDoubleRight)) {
222
+ return renderDoubleLineCorner(segments, ctx, doubleOffset);
223
+ }
224
+ const paths = [];
225
+ if (segments.up > 0) {
226
+ if (segments.up === 3) {
227
+ paths.push(`<line x1="${centerX - doubleOffset}" y1="${y}" x2="${centerX - doubleOffset}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX + doubleOffset}" y1="${y}" x2="${centerX + doubleOffset}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
228
+ }
229
+ else {
230
+ const w = getWidth(segments.up);
231
+ paths.push(`<line x1="${centerX}" y1="${y}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
232
+ }
233
+ }
234
+ if (segments.down > 0) {
235
+ if (segments.down === 3) {
236
+ paths.push(`<line x1="${centerX - doubleOffset}" y1="${centerY}" x2="${centerX - doubleOffset}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX + doubleOffset}" y1="${centerY}" x2="${centerX + doubleOffset}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
237
+ }
238
+ else {
239
+ const w = getWidth(segments.down);
240
+ paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${centerX}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${w}"/>`);
241
+ }
242
+ }
243
+ if (segments.left > 0) {
244
+ if (segments.left === 3) {
245
+ paths.push(`<line x1="${x}" y1="${centerY - doubleOffset}" x2="${centerX}" y2="${centerY - doubleOffset}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${x}" y1="${centerY + doubleOffset}" x2="${centerX}" y2="${centerY + doubleOffset}" stroke="${color}" stroke-width="${lineWidth}"/>`);
246
+ }
247
+ else {
248
+ const w = getWidth(segments.left);
249
+ paths.push(`<line x1="${x}" y1="${centerY}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
250
+ }
251
+ }
252
+ if (segments.right > 0) {
253
+ if (segments.right === 3) {
254
+ paths.push(`<line x1="${centerX}" y1="${centerY - doubleOffset}" x2="${x + cellWidth}" y2="${centerY - doubleOffset}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX}" y1="${centerY + doubleOffset}" x2="${x + cellWidth}" y2="${centerY + doubleOffset}" stroke="${color}" stroke-width="${lineWidth}"/>`);
255
+ }
256
+ else {
257
+ const w = getWidth(segments.right);
258
+ paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${x + cellWidth}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
259
+ }
260
+ }
261
+ return { svg: paths.join(''), handled: true };
262
+ }
263
+ function renderDoubleLineCorner(segments, ctx, doubleOffset) {
264
+ const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
265
+ const centerX = x + cellWidth / 2;
266
+ const centerY = y + cellHeight / 2;
267
+ const paths = [];
268
+ const hasUp = segments.up === 3;
269
+ const hasDown = segments.down === 3;
270
+ const hasLeft = segments.left === 3;
271
+ const hasRight = segments.right === 3;
272
+ const outerLeft = centerX - doubleOffset;
273
+ const outerRight = centerX + doubleOffset;
274
+ const outerTop = centerY - doubleOffset;
275
+ const outerBottom = centerY + doubleOffset;
276
+ if (hasUp && hasRight && !hasDown && !hasLeft) {
277
+ paths.push(`<path d="M ${outerLeft} ${y} L ${outerLeft} ${outerBottom} L ${x + cellWidth} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
278
+ paths.push(`<path d="M ${outerRight} ${y} L ${outerRight} ${outerTop} L ${x + cellWidth} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
279
+ }
280
+ else if (hasDown && hasRight && !hasUp && !hasLeft) {
281
+ paths.push(`<path d="M ${outerLeft} ${y + cellHeight} L ${outerLeft} ${outerTop} L ${x + cellWidth} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
282
+ paths.push(`<path d="M ${outerRight} ${y + cellHeight} L ${outerRight} ${outerBottom} L ${x + cellWidth} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
283
+ }
284
+ else if (hasDown && hasLeft && !hasUp && !hasRight) {
285
+ paths.push(`<path d="M ${outerRight} ${y + cellHeight} L ${outerRight} ${outerTop} L ${x} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
286
+ paths.push(`<path d="M ${outerLeft} ${y + cellHeight} L ${outerLeft} ${outerBottom} L ${x} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
287
+ }
288
+ else if (hasUp && hasLeft && !hasDown && !hasRight) {
289
+ paths.push(`<path d="M ${outerRight} ${y} L ${outerRight} ${outerBottom} L ${x} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
290
+ paths.push(`<path d="M ${outerLeft} ${y} L ${outerLeft} ${outerTop} L ${x} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
291
+ }
292
+ else if (hasUp && hasDown && hasRight && !hasLeft) {
293
+ paths.push(`<line x1="${outerLeft}" y1="${y}" x2="${outerLeft}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
294
+ paths.push(`<line x1="${outerRight}" y1="${y}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
295
+ paths.push(`<line x1="${outerRight}" y1="${outerTop}" x2="${x + cellWidth}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${x + cellWidth}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
296
+ }
297
+ else if (hasUp && hasDown && hasLeft && !hasRight) {
298
+ paths.push(`<line x1="${outerRight}" y1="${y}" x2="${outerRight}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
299
+ paths.push(`<line x1="${outerLeft}" y1="${y}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
300
+ paths.push(`<line x1="${x}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${x}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
301
+ }
302
+ else if (hasDown && hasLeft && hasRight && !hasUp) {
303
+ paths.push(`<line x1="${x}" y1="${outerTop}" x2="${x + cellWidth}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
304
+ paths.push(`<line x1="${x}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${x + cellWidth}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
305
+ paths.push(`<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
306
+ }
307
+ else if (hasUp && hasLeft && hasRight && !hasDown) {
308
+ paths.push(`<line x1="${x}" y1="${outerBottom}" x2="${x + cellWidth}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
309
+ paths.push(`<line x1="${x}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerTop}" x2="${x + cellWidth}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
310
+ paths.push(`<line x1="${outerLeft}" y1="${y}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${y}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
311
+ }
312
+ else if (hasUp && hasDown && hasLeft && hasRight) {
313
+ paths.push(`<line x1="${outerLeft}" y1="${y}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${y}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
314
+ paths.push(`<line x1="${x}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerTop}" x2="${x + cellWidth}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${x}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${x + cellWidth}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
315
+ }
316
+ else {
317
+ if (hasUp) {
318
+ paths.push(`<line x1="${outerLeft}" y1="${y}" x2="${outerLeft}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${y}" x2="${outerRight}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
319
+ }
320
+ if (hasDown) {
321
+ paths.push(`<line x1="${outerLeft}" y1="${centerY}" x2="${outerLeft}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${centerY}" x2="${outerRight}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
322
+ }
323
+ if (hasLeft) {
324
+ paths.push(`<line x1="${x}" y1="${outerTop}" x2="${centerX}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${x}" y1="${outerBottom}" x2="${centerX}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
325
+ }
326
+ if (hasRight) {
327
+ paths.push(`<line x1="${centerX}" y1="${outerTop}" x2="${x + cellWidth}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX}" y1="${outerBottom}" x2="${x + cellWidth}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
328
+ }
329
+ }
330
+ return { svg: paths.join(''), handled: true };
331
+ }
332
+ function renderDiagonalLine(codePoint, ctx) {
333
+ const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
334
+ const paths = [];
335
+ if (codePoint === 0x2571 || codePoint === 0x2573) {
336
+ paths.push(`<line x1="${x}" y1="${y + cellHeight}" x2="${x + cellWidth}" y2="${y}" stroke="${color}" stroke-width="${lineWidth}"/>`);
337
+ }
338
+ if (codePoint === 0x2572 || codePoint === 0x2573) {
339
+ paths.push(`<line x1="${x}" y1="${y}" x2="${x + cellWidth}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
340
+ }
341
+ return { svg: paths.join(''), handled: true };
342
+ }
343
+ // Block Elements (U+2580-U+259F)
344
+ function renderBlockElement(codePoint, ctx) {
345
+ const { cellWidth, cellHeight, x, y, color } = ctx;
346
+ const crisp = ' shape-rendering="crispEdges"';
347
+ let svg = '';
348
+ switch (codePoint) {
349
+ case 0x2580: // Upper half block
350
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
351
+ break;
352
+ case 0x2581: // Lower 1/8
353
+ svg = `<rect x="${x}" y="${y + cellHeight * 7 / 8}" width="${cellWidth}" height="${cellHeight / 8}" fill="${color}"${crisp}/>`;
354
+ break;
355
+ case 0x2582: // Lower 1/4
356
+ svg = `<rect x="${x}" y="${y + cellHeight * 3 / 4}" width="${cellWidth}" height="${cellHeight / 4}" fill="${color}"${crisp}/>`;
357
+ break;
358
+ case 0x2583: // Lower 3/8
359
+ svg = `<rect x="${x}" y="${y + cellHeight * 5 / 8}" width="${cellWidth}" height="${cellHeight * 3 / 8}" fill="${color}"${crisp}/>`;
360
+ break;
361
+ case 0x2584: // Lower half
362
+ svg = `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
363
+ break;
364
+ case 0x2585: // Lower 5/8
365
+ svg = `<rect x="${x}" y="${y + cellHeight * 3 / 8}" width="${cellWidth}" height="${cellHeight * 5 / 8}" fill="${color}"${crisp}/>`;
366
+ break;
367
+ case 0x2586: // Lower 3/4
368
+ svg = `<rect x="${x}" y="${y + cellHeight / 4}" width="${cellWidth}" height="${cellHeight * 3 / 4}" fill="${color}"${crisp}/>`;
369
+ break;
370
+ case 0x2587: // Lower 7/8
371
+ svg = `<rect x="${x}" y="${y + cellHeight / 8}" width="${cellWidth}" height="${cellHeight * 7 / 8}" fill="${color}"${crisp}/>`;
372
+ break;
373
+ case 0x2588: // Full block
374
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}"${crisp}/>`;
375
+ break;
376
+ case 0x2589: // Left 7/8
377
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth * 7 / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
378
+ break;
379
+ case 0x258a: // Left 3/4
380
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth * 3 / 4}" height="${cellHeight}" fill="${color}"${crisp}/>`;
381
+ break;
382
+ case 0x258b: // Left 5/8
383
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth * 5 / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
384
+ break;
385
+ case 0x258c: // Left half
386
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight}" fill="${color}"${crisp}/>`;
387
+ break;
388
+ case 0x258d: // Left 3/8
389
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth * 3 / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
390
+ break;
391
+ case 0x258e: // Left 1/4
392
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth / 4}" height="${cellHeight}" fill="${color}"${crisp}/>`;
393
+ break;
394
+ case 0x258f: // Left 1/8
395
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
396
+ break;
397
+ case 0x2590: // Right half block
398
+ svg = `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight}" fill="${color}"${crisp}/>`;
399
+ break;
400
+ case 0x2591: // Light shade (25%)
401
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="0.25"${crisp}/>`;
402
+ break;
403
+ case 0x2592: // Medium shade (50%)
404
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="0.5"${crisp}/>`;
405
+ break;
406
+ case 0x2593: // Dark shade (75%)
407
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="0.75"${crisp}/>`;
408
+ break;
409
+ case 0x2594: // Upper 1/8 block
410
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 8}" fill="${color}"${crisp}/>`;
411
+ break;
412
+ case 0x2595: // Right 1/8 block
413
+ svg = `<rect x="${x + cellWidth * 7 / 8}" y="${y}" width="${cellWidth / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
414
+ break;
415
+ case 0x2596: // Lower left
416
+ svg = `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
417
+ break;
418
+ case 0x2597: // Lower right
419
+ svg = `<rect x="${x + cellWidth / 2}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
420
+ break;
421
+ case 0x2598: // Upper left
422
+ svg = `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
423
+ break;
424
+ case 0x2599: // Upper left, lower left, lower right
425
+ svg = [
426
+ `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
427
+ `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
428
+ ].join('');
429
+ break;
430
+ case 0x259a: // Upper left, lower right
431
+ svg = [
432
+ `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
433
+ `<rect x="${x + cellWidth / 2}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
434
+ ].join('');
435
+ break;
436
+ case 0x259b: // Upper left, upper right, lower left
437
+ svg = [
438
+ `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
439
+ `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
440
+ ].join('');
441
+ break;
442
+ case 0x259c: // Upper left, upper right, lower right
443
+ svg = [
444
+ `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
445
+ `<rect x="${x + cellWidth / 2}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
446
+ ].join('');
447
+ break;
448
+ case 0x259d: // Upper right
449
+ svg = `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
450
+ break;
451
+ case 0x259e: // Upper right, lower left
452
+ svg = [
453
+ `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
454
+ `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
455
+ ].join('');
456
+ break;
457
+ case 0x259f: // Upper right, lower left, lower right
458
+ svg = [
459
+ `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
460
+ `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`,
461
+ ].join('');
462
+ break;
463
+ default:
464
+ return { svg: '', handled: false };
465
+ }
466
+ return { svg, handled: true };
467
+ }
468
+ // Braille Patterns (U+2800-U+28FF)
469
+ // 8-dot pattern in 2x4 grid: bits encode which dots are filled
470
+ function renderBraille(codePoint, ctx) {
471
+ const { cellWidth, cellHeight, x, y, color } = ctx;
472
+ const pattern = codePoint - 0x2800;
473
+ const dotRadius = Math.min(cellWidth, cellHeight) * 0.1;
474
+ const leftX = x + cellWidth * 0.3;
475
+ const rightX = x + cellWidth * 0.7;
476
+ const rows = [
477
+ y + cellHeight * 0.15,
478
+ y + cellHeight * 0.35,
479
+ y + cellHeight * 0.55,
480
+ y + cellHeight * 0.85,
481
+ ];
482
+ const dots = [];
483
+ const dotPositions = [
484
+ [leftX, rows[0]],
485
+ [leftX, rows[1]],
486
+ [leftX, rows[2]],
487
+ [rightX, rows[0]],
488
+ [rightX, rows[1]],
489
+ [rightX, rows[2]],
490
+ [leftX, rows[3]],
491
+ [rightX, rows[3]],
492
+ ];
493
+ for (let i = 0; i < 8; i++) {
494
+ if (pattern & (1 << i)) {
495
+ const [dx, dy] = dotPositions[i];
496
+ dots.push(`<circle cx="${dx}" cy="${dy}" r="${dotRadius}" fill="${color}"/>`);
497
+ }
498
+ }
499
+ return { svg: dots.join(''), handled: true };
500
+ }
501
+ // Symbols for Legacy Computing (U+1FB00-U+1FBFF)
502
+ function renderLegacyComputing(codePoint, ctx) {
503
+ if (codePoint >= 0x1fb00 && codePoint <= 0x1fb3b) {
504
+ return renderSextant(codePoint, ctx);
505
+ }
506
+ if (codePoint >= 0x1fb3c && codePoint <= 0x1fb6f) {
507
+ return renderSmoothMosaic(codePoint, ctx);
508
+ }
509
+ if (codePoint >= 0x1fb70 && codePoint <= 0x1fb8b) {
510
+ return renderLegacyBlockElement(codePoint, ctx);
511
+ }
512
+ if (codePoint >= 0x1fb8c && codePoint <= 0x1fb94) {
513
+ return renderLegacyShade(codePoint, ctx);
514
+ }
515
+ if (codePoint >= 0x1fb95 && codePoint <= 0x1fb99) {
516
+ return renderFillPattern(codePoint, ctx);
517
+ }
518
+ if (codePoint >= 0x1fb9a && codePoint <= 0x1fb9f) {
519
+ return renderTriangularShade(codePoint, ctx);
520
+ }
521
+ if (codePoint >= 0x1fba0 && codePoint <= 0x1fbaf) {
522
+ return renderCellDiagonal(codePoint, ctx);
523
+ }
524
+ return { svg: '', handled: false };
525
+ }
526
+ // Sextant characters (2x3 grid)
527
+ function renderSextant(codePoint, ctx) {
528
+ const { cellWidth, cellHeight, x, y, color } = ctx;
529
+ const sw = cellWidth / 2;
530
+ const sh = cellHeight / 3;
531
+ const offset = codePoint - 0x1fb00;
532
+ const sextantPatterns = {};
533
+ let patternIndex = 0;
534
+ for (let bits = 1; bits < 64; bits++) {
535
+ if (bits === 63)
536
+ continue;
537
+ sextantPatterns[patternIndex] = [];
538
+ if (bits & 1)
539
+ sextantPatterns[patternIndex].push(0);
540
+ if (bits & 2)
541
+ sextantPatterns[patternIndex].push(1);
542
+ if (bits & 4)
543
+ sextantPatterns[patternIndex].push(2);
544
+ if (bits & 8)
545
+ sextantPatterns[patternIndex].push(3);
546
+ if (bits & 16)
547
+ sextantPatterns[patternIndex].push(4);
548
+ if (bits & 32)
549
+ sextantPatterns[patternIndex].push(5);
550
+ patternIndex++;
551
+ }
552
+ const filled = sextantPatterns[offset] || [];
553
+ const rects = [];
554
+ const positions = [
555
+ [0, 0], [1, 0],
556
+ [0, 1], [1, 1],
557
+ [0, 2], [1, 2],
558
+ ];
559
+ for (const idx of filled) {
560
+ const [col, row] = positions[idx];
561
+ rects.push(`<rect x="${x + col * sw}" y="${y + row * sh}" width="${sw}" height="${sh}" fill="${color}"/>`);
562
+ }
563
+ return { svg: rects.join(''), handled: true };
564
+ }
565
+ function renderSmoothMosaic(codePoint, ctx) {
566
+ const { cellWidth, cellHeight, x, y, color } = ctx;
567
+ if (codePoint === 0x1fb3c) {
568
+ return {
569
+ svg: `<polygon points="${x},${y} ${x + cellWidth},${y} ${x},${y + cellHeight}" fill="${color}"/>`,
570
+ handled: true,
571
+ };
572
+ }
573
+ if (codePoint === 0x1fb3d) {
574
+ return {
575
+ svg: `<polygon points="${x},${y} ${x + cellWidth},${y} ${x + cellWidth},${y + cellHeight}" fill="${color}"/>`,
576
+ handled: true,
577
+ };
578
+ }
579
+ if (codePoint === 0x1fb3e) {
580
+ return {
581
+ svg: `<polygon points="${x},${y} ${x},${y + cellHeight} ${x + cellWidth},${y + cellHeight}" fill="${color}"/>`,
582
+ handled: true,
583
+ };
584
+ }
585
+ if (codePoint === 0x1fb3f) {
586
+ return {
587
+ svg: `<polygon points="${x + cellWidth},${y} ${x},${y + cellHeight} ${x + cellWidth},${y + cellHeight}" fill="${color}"/>`,
588
+ handled: true,
589
+ };
590
+ }
591
+ return {
592
+ svg: `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="0.5"/>`,
593
+ handled: true,
594
+ };
595
+ }
596
+ function renderLegacyBlockElement(codePoint, ctx) {
597
+ const { cellWidth, cellHeight, x, y, color } = ctx;
598
+ const offset = codePoint - 0x1fb70;
599
+ if (offset >= 0 && offset <= 5) {
600
+ const startY = y + (offset + 1) * (cellHeight / 8);
601
+ return {
602
+ svg: `<rect x="${x}" y="${startY}" width="${cellWidth}" height="${cellHeight / 8}" fill="${color}"/>`,
603
+ handled: true,
604
+ };
605
+ }
606
+ if (offset >= 6 && offset <= 11) {
607
+ const pos = offset - 6;
608
+ const startX = x + (pos + 1) * (cellWidth / 8);
609
+ return {
610
+ svg: `<rect x="${startX}" y="${y}" width="${cellWidth / 8}" height="${cellHeight}" fill="${color}"/>`,
611
+ handled: true,
612
+ };
613
+ }
614
+ return {
615
+ svg: `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="0.5"/>`,
616
+ handled: true,
617
+ };
618
+ }
619
+ function renderLegacyShade(codePoint, ctx) {
620
+ const { cellWidth, cellHeight, x, y, color } = ctx;
621
+ const offset = codePoint - 0x1fb8c;
622
+ const shadeOpacity = 0.5;
623
+ switch (offset) {
624
+ case 0:
625
+ return {
626
+ svg: `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
627
+ handled: true,
628
+ };
629
+ case 1:
630
+ return {
631
+ svg: `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
632
+ handled: true,
633
+ };
634
+ case 2:
635
+ return {
636
+ svg: `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
637
+ handled: true,
638
+ };
639
+ case 3:
640
+ return {
641
+ svg: `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
642
+ handled: true,
643
+ };
644
+ default:
645
+ return {
646
+ svg: `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
647
+ handled: true,
648
+ };
649
+ }
650
+ }
651
+ function renderFillPattern(codePoint, ctx) {
652
+ const { cellWidth, cellHeight, x, y, color } = ctx;
653
+ if (codePoint === 0x1fb95 || codePoint === 0x1fb96) {
654
+ const isInverse = codePoint === 0x1fb96;
655
+ const size = Math.min(cellWidth, cellHeight) / 4;
656
+ const rects = [];
657
+ for (let row = 0; row < 4; row++) {
658
+ for (let col = 0; col < 4; col++) {
659
+ const fill = ((row + col) % 2 === 0) !== isInverse;
660
+ if (fill) {
661
+ rects.push(`<rect x="${x + col * size}" y="${y + row * size}" width="${size}" height="${size}" fill="${color}"/>`);
662
+ }
663
+ }
664
+ }
665
+ return { svg: rects.join(''), handled: true };
666
+ }
667
+ return {
668
+ svg: `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}" fill-opacity="0.5"/>`,
669
+ handled: true,
670
+ };
671
+ }
672
+ function renderTriangularShade(codePoint, ctx) {
673
+ const { cellWidth, cellHeight, x, y, color } = ctx;
674
+ const shadeOpacity = 0.5;
675
+ switch (codePoint) {
676
+ case 0x1fb9a:
677
+ return {
678
+ svg: `<polygon points="${x},${y} ${x + cellWidth},${y} ${x},${y + cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
679
+ handled: true,
680
+ };
681
+ case 0x1fb9b:
682
+ return {
683
+ svg: `<polygon points="${x},${y} ${x + cellWidth},${y} ${x + cellWidth},${y + cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
684
+ handled: true,
685
+ };
686
+ case 0x1fb9c:
687
+ return {
688
+ svg: `<polygon points="${x + cellWidth},${y} ${x},${y + cellHeight} ${x + cellWidth},${y + cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
689
+ handled: true,
690
+ };
691
+ case 0x1fb9d:
692
+ return {
693
+ svg: `<polygon points="${x},${y} ${x},${y + cellHeight} ${x + cellWidth},${y + cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
694
+ handled: true,
695
+ };
696
+ default:
697
+ return {
698
+ svg: `<polygon points="${x},${y} ${x + cellWidth},${y} ${x + cellWidth / 2},${y + cellHeight}" fill="${color}" fill-opacity="${shadeOpacity}"/>`,
699
+ handled: true,
700
+ };
701
+ }
702
+ }
703
+ function renderCellDiagonal(codePoint, ctx) {
704
+ const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
705
+ const paths = [];
706
+ const offset = codePoint - 0x1fba0;
707
+ if (offset === 0 || offset === 2 || offset === 4 || offset === 6 ||
708
+ offset === 8 || offset === 10 || offset === 12 || offset === 14) {
709
+ paths.push(`<line x1="${x + cellWidth}" y1="${y}" x2="${x}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
710
+ }
711
+ if (offset === 1 || offset === 2 || offset === 5 || offset === 6 ||
712
+ offset === 9 || offset === 10 || offset === 13 || offset === 14) {
713
+ paths.push(`<line x1="${x}" y1="${y}" x2="${x + cellWidth}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
714
+ }
715
+ if (offset >= 4 && offset <= 7) {
716
+ const midX = x + cellWidth / 2;
717
+ const midY = y + cellHeight / 2;
718
+ if (offset === 4 || offset === 6) {
719
+ paths.push(`<line x1="${midX}" y1="${y}" x2="${x}" y2="${midY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
720
+ }
721
+ if (offset === 5 || offset === 6) {
722
+ paths.push(`<line x1="${x}" y1="${midY}" x2="${midX}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
723
+ }
724
+ }
725
+ if (paths.length === 0) {
726
+ paths.push(`<line x1="${x}" y1="${y}" x2="${x + cellWidth}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${x + cellWidth}" y1="${y}" x2="${x}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
727
+ }
728
+ return { svg: paths.join(''), handled: true };
729
+ }
730
+ //# sourceMappingURL=customGlyphs.js.map