shellfie 2.0.18 → 2.0.20

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 (78) hide show
  1. package/README.md +63 -46
  2. package/dist/highlight/index.d.ts +41 -0
  3. package/dist/highlight/index.d.ts.map +1 -0
  4. package/dist/highlight/index.js +309 -0
  5. package/dist/highlight/index.js.map +1 -0
  6. package/dist/highlight/languages/bash.d.ts +3 -0
  7. package/dist/highlight/languages/bash.d.ts.map +1 -0
  8. package/dist/highlight/languages/bash.js +78 -0
  9. package/dist/highlight/languages/bash.js.map +1 -0
  10. package/dist/highlight/languages/c.d.ts +4 -0
  11. package/dist/highlight/languages/c.d.ts.map +1 -0
  12. package/dist/highlight/languages/c.js +101 -0
  13. package/dist/highlight/languages/c.js.map +1 -0
  14. package/dist/highlight/languages/csharp.d.ts +3 -0
  15. package/dist/highlight/languages/csharp.d.ts.map +1 -0
  16. package/dist/highlight/languages/csharp.js +78 -0
  17. package/dist/highlight/languages/csharp.js.map +1 -0
  18. package/dist/highlight/languages/go.d.ts +3 -0
  19. package/dist/highlight/languages/go.d.ts.map +1 -0
  20. package/dist/highlight/languages/go.js +47 -0
  21. package/dist/highlight/languages/go.js.map +1 -0
  22. package/dist/highlight/languages/html.d.ts +3 -0
  23. package/dist/highlight/languages/html.d.ts.map +1 -0
  24. package/dist/highlight/languages/html.js +44 -0
  25. package/dist/highlight/languages/html.js.map +1 -0
  26. package/dist/highlight/languages/index.d.ts +26 -0
  27. package/dist/highlight/languages/index.d.ts.map +1 -0
  28. package/dist/highlight/languages/index.js +65 -0
  29. package/dist/highlight/languages/index.js.map +1 -0
  30. package/dist/highlight/languages/java.d.ts +3 -0
  31. package/dist/highlight/languages/java.d.ts.map +1 -0
  32. package/dist/highlight/languages/java.js +57 -0
  33. package/dist/highlight/languages/java.js.map +1 -0
  34. package/dist/highlight/languages/javascript.d.ts +3 -0
  35. package/dist/highlight/languages/javascript.d.ts.map +1 -0
  36. package/dist/highlight/languages/javascript.js +53 -0
  37. package/dist/highlight/languages/javascript.js.map +1 -0
  38. package/dist/highlight/languages/json.d.ts +3 -0
  39. package/dist/highlight/languages/json.d.ts.map +1 -0
  40. package/dist/highlight/languages/json.js +25 -0
  41. package/dist/highlight/languages/json.js.map +1 -0
  42. package/dist/highlight/languages/python.d.ts +3 -0
  43. package/dist/highlight/languages/python.d.ts.map +1 -0
  44. package/dist/highlight/languages/python.js +80 -0
  45. package/dist/highlight/languages/python.js.map +1 -0
  46. package/dist/highlight/languages/rust.d.ts +3 -0
  47. package/dist/highlight/languages/rust.d.ts.map +1 -0
  48. package/dist/highlight/languages/rust.js +68 -0
  49. package/dist/highlight/languages/rust.js.map +1 -0
  50. package/dist/highlight/languages/typescript.d.ts +3 -0
  51. package/dist/highlight/languages/typescript.d.ts.map +1 -0
  52. package/dist/highlight/languages/typescript.js +77 -0
  53. package/dist/highlight/languages/typescript.js.map +1 -0
  54. package/dist/highlight/tokenizer.d.ts +41 -0
  55. package/dist/highlight/tokenizer.d.ts.map +1 -0
  56. package/dist/highlight/tokenizer.js +147 -0
  57. package/dist/highlight/tokenizer.js.map +1 -0
  58. package/dist/highlight/types.d.ts +47 -0
  59. package/dist/highlight/types.d.ts.map +1 -0
  60. package/dist/highlight/types.js +27 -0
  61. package/dist/highlight/types.js.map +1 -0
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +23 -3
  65. package/dist/index.js.map +1 -1
  66. package/dist/renderer/customGlyphs.d.ts +1 -0
  67. package/dist/renderer/customGlyphs.d.ts.map +1 -1
  68. package/dist/renderer/customGlyphs.js +179 -90
  69. package/dist/renderer/customGlyphs.js.map +1 -1
  70. package/dist/renderer/index.d.ts.map +1 -1
  71. package/dist/renderer/index.js +11 -4
  72. package/dist/renderer/index.js.map +1 -1
  73. package/dist/renderer/text.d.ts.map +1 -1
  74. package/dist/renderer/text.js +10 -3
  75. package/dist/renderer/text.js.map +1 -1
  76. package/dist/types.d.ts +9 -0
  77. package/dist/types.d.ts.map +1 -1
  78. package/package.json +1 -1
@@ -9,6 +9,62 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.isCustomGlyph = isCustomGlyph;
10
10
  exports.containsCustomGlyphs = containsCustomGlyphs;
11
11
  exports.renderCustomGlyph = renderCustomGlyph;
12
+ /**
13
+ * Round a coordinate value to 2 decimal places to eliminate floating-point precision artifacts
14
+ * (e.g., 19.599999999999998 → 19.6) while preserving enough precision to avoid gaps between blocks.
15
+ */
16
+ function r(value) {
17
+ return Math.round(value * 100) / 100;
18
+ }
19
+ /**
20
+ * Parse a color string (hex, rgb, rgba) and return [r, g, b] components (0-255).
21
+ */
22
+ function parseColor(color) {
23
+ // Handle hex colors
24
+ if (color.startsWith('#')) {
25
+ const hex = color.slice(1);
26
+ if (hex.length === 3) {
27
+ return [
28
+ parseInt(hex[0] + hex[0], 16),
29
+ parseInt(hex[1] + hex[1], 16),
30
+ parseInt(hex[2] + hex[2], 16),
31
+ ];
32
+ }
33
+ if (hex.length >= 6) {
34
+ return [
35
+ parseInt(hex.slice(0, 2), 16),
36
+ parseInt(hex.slice(2, 4), 16),
37
+ parseInt(hex.slice(4, 6), 16),
38
+ ];
39
+ }
40
+ }
41
+ // Handle rgb/rgba colors
42
+ const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
43
+ if (rgbMatch) {
44
+ return [
45
+ parseInt(rgbMatch[1], 10),
46
+ parseInt(rgbMatch[2], 10),
47
+ parseInt(rgbMatch[3], 10),
48
+ ];
49
+ }
50
+ // Fallback to black
51
+ return [0, 0, 0];
52
+ }
53
+ /**
54
+ * Blend foreground color with background color at given opacity.
55
+ * Returns a solid hex color that looks like the foreground at the given opacity over the background.
56
+ */
57
+ function blendColors(fg, bg, opacity) {
58
+ const [fgR, fgG, fgB] = parseColor(fg);
59
+ const [bgR, bgG, bgB] = parseColor(bg);
60
+ // Blend: result = fg * opacity + bg * (1 - opacity)
61
+ const r = Math.round(fgR * opacity + bgR * (1 - opacity));
62
+ const g = Math.round(fgG * opacity + bgG * (1 - opacity));
63
+ const b = Math.round(fgB * opacity + bgB * (1 - opacity));
64
+ // Return as hex
65
+ const toHex = (n) => n.toString(16).padStart(2, '0');
66
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
67
+ }
12
68
  function isCustomGlyph(codePoint) {
13
69
  return ((codePoint >= 0x2500 && codePoint <= 0x257f) ||
14
70
  (codePoint >= 0x2580 && codePoint <= 0x259f) ||
@@ -39,10 +95,10 @@ function renderCustomGlyph(char, ctx) {
39
95
  // Black Square (U+25A0) - render as cell-width square, vertically centered
40
96
  if (codePoint === 0x25a0) {
41
97
  const { cellWidth, cellHeight, x, y, color } = ctx;
42
- const size = cellWidth;
43
- const squareY = y + (cellHeight - size) / 2;
98
+ const size = r(cellWidth);
99
+ const squareY = r(y + (cellHeight - cellWidth) / 2);
44
100
  return {
45
- svg: `<rect x="${x}" y="${squareY}" width="${size}" height="${size}" fill="${color}" shape-rendering="crispEdges"/>`,
101
+ svg: `<rect x="${r(x)}" y="${squareY}" width="${size}" height="${size}" fill="${color}" shape-rendering="crispEdges"/>`,
46
102
  handled: true,
47
103
  };
48
104
  }
@@ -202,8 +258,13 @@ function renderBoxDrawing(codePoint, ctx) {
202
258
  return { svg: '', handled: false };
203
259
  }
204
260
  const { cellWidth, cellHeight, x, y, color, lineWidth, heavyLineWidth } = ctx;
205
- const centerX = x + cellWidth / 2;
206
- const centerY = y + cellHeight / 2;
261
+ // Pre-compute rounded values
262
+ const rx = r(x);
263
+ const ry = r(y);
264
+ const rBottom = r(y + cellHeight);
265
+ const rRight = r(x + cellWidth);
266
+ const centerX = r(x + cellWidth / 2);
267
+ const centerY = r(y + cellHeight / 2);
207
268
  const getWidth = (type) => {
208
269
  if (type === 0)
209
270
  return 0;
@@ -213,7 +274,7 @@ function renderBoxDrawing(codePoint, ctx) {
213
274
  return heavyLineWidth;
214
275
  return lineWidth;
215
276
  };
216
- const doubleOffset = lineWidth * 1.5;
277
+ const doubleOffset = r(lineWidth * 1.5);
217
278
  const hasDoubleUp = segments.up === 3;
218
279
  const hasDoubleDown = segments.down === 3;
219
280
  const hasDoubleLeft = segments.left === 3;
@@ -224,240 +285,268 @@ function renderBoxDrawing(codePoint, ctx) {
224
285
  const paths = [];
225
286
  if (segments.up > 0) {
226
287
  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}"/>`);
288
+ paths.push(`<line x1="${r(centerX - doubleOffset)}" y1="${ry}" x2="${r(centerX - doubleOffset)}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${r(centerX + doubleOffset)}" y1="${ry}" x2="${r(centerX + doubleOffset)}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
228
289
  }
229
290
  else {
230
291
  const w = getWidth(segments.up);
231
- paths.push(`<line x1="${centerX}" y1="${y}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
292
+ paths.push(`<line x1="${centerX}" y1="${ry}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
232
293
  }
233
294
  }
234
295
  if (segments.down > 0) {
235
296
  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}"/>`);
297
+ paths.push(`<line x1="${r(centerX - doubleOffset)}" y1="${centerY}" x2="${r(centerX - doubleOffset)}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${r(centerX + doubleOffset)}" y1="${centerY}" x2="${r(centerX + doubleOffset)}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
237
298
  }
238
299
  else {
239
300
  const w = getWidth(segments.down);
240
- paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${centerX}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${w}"/>`);
301
+ paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${centerX}" y2="${rBottom}" stroke="${color}" stroke-width="${w}"/>`);
241
302
  }
242
303
  }
243
304
  if (segments.left > 0) {
244
305
  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}"/>`);
306
+ paths.push(`<line x1="${rx}" y1="${r(centerY - doubleOffset)}" x2="${centerX}" y2="${r(centerY - doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${r(centerY + doubleOffset)}" x2="${centerX}" y2="${r(centerY + doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`);
246
307
  }
247
308
  else {
248
309
  const w = getWidth(segments.left);
249
- paths.push(`<line x1="${x}" y1="${centerY}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
310
+ paths.push(`<line x1="${rx}" y1="${centerY}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
250
311
  }
251
312
  }
252
313
  if (segments.right > 0) {
253
314
  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}"/>`);
315
+ paths.push(`<line x1="${centerX}" y1="${r(centerY - doubleOffset)}" x2="${rRight}" y2="${r(centerY - doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX}" y1="${r(centerY + doubleOffset)}" x2="${rRight}" y2="${r(centerY + doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`);
255
316
  }
256
317
  else {
257
318
  const w = getWidth(segments.right);
258
- paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${x + cellWidth}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
319
+ paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${rRight}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
259
320
  }
260
321
  }
261
322
  return { svg: paths.join(''), handled: true };
262
323
  }
263
324
  function renderDoubleLineCorner(segments, ctx, doubleOffset) {
264
325
  const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
265
- const centerX = x + cellWidth / 2;
266
- const centerY = y + cellHeight / 2;
326
+ // Pre-compute rounded values
327
+ const rx = r(x);
328
+ const ry = r(y);
329
+ const rBottom = r(y + cellHeight);
330
+ const rRight = r(x + cellWidth);
331
+ const centerX = r(x + cellWidth / 2);
332
+ const centerY = r(y + cellHeight / 2);
267
333
  const paths = [];
268
334
  const hasUp = segments.up === 3;
269
335
  const hasDown = segments.down === 3;
270
336
  const hasLeft = segments.left === 3;
271
337
  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;
338
+ const outerLeft = r(centerX - doubleOffset);
339
+ const outerRight = r(centerX + doubleOffset);
340
+ const outerTop = r(centerY - doubleOffset);
341
+ const outerBottom = r(centerY + doubleOffset);
276
342
  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}"/>`);
343
+ paths.push(`<path d="M ${outerLeft} ${ry} L ${outerLeft} ${outerBottom} L ${rRight} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
344
+ paths.push(`<path d="M ${outerRight} ${ry} L ${outerRight} ${outerTop} L ${rRight} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
279
345
  }
280
346
  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}"/>`);
347
+ paths.push(`<path d="M ${outerLeft} ${rBottom} L ${outerLeft} ${outerTop} L ${rRight} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
348
+ paths.push(`<path d="M ${outerRight} ${rBottom} L ${outerRight} ${outerBottom} L ${rRight} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
283
349
  }
284
350
  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}"/>`);
351
+ paths.push(`<path d="M ${outerRight} ${rBottom} L ${outerRight} ${outerTop} L ${rx} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
352
+ paths.push(`<path d="M ${outerLeft} ${rBottom} L ${outerLeft} ${outerBottom} L ${rx} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
287
353
  }
288
354
  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}"/>`);
355
+ paths.push(`<path d="M ${outerRight} ${ry} L ${outerRight} ${outerBottom} L ${rx} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
356
+ paths.push(`<path d="M ${outerLeft} ${ry} L ${outerLeft} ${outerTop} L ${rx} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
291
357
  }
292
358
  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}"/>`);
359
+ paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
360
+ paths.push(`<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
361
+ paths.push(`<line x1="${outerRight}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
296
362
  }
297
363
  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}"/>`);
364
+ paths.push(`<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
365
+ paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
366
+ paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
301
367
  }
302
368
  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}"/>`);
369
+ paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
370
+ paths.push(`<line x1="${rx}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
371
+ paths.push(`<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
306
372
  }
307
373
  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}"/>`);
374
+ paths.push(`<line x1="${rx}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
375
+ paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
376
+ paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
311
377
  }
312
378
  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}"/>`);
379
+ paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
380
+ paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
315
381
  }
316
382
  else {
317
383
  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}"/>`);
384
+ paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
319
385
  }
320
386
  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}"/>`);
387
+ paths.push(`<line x1="${outerLeft}" y1="${centerY}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${centerY}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
322
388
  }
323
389
  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}"/>`);
390
+ paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${centerX}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${outerBottom}" x2="${centerX}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
325
391
  }
326
392
  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}"/>`);
393
+ paths.push(`<line x1="${centerX}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
328
394
  }
329
395
  }
330
396
  return { svg: paths.join(''), handled: true };
331
397
  }
332
398
  function renderDiagonalLine(codePoint, ctx) {
333
399
  const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
400
+ const rx = r(x);
401
+ const ry = r(y);
402
+ const rBottom = r(y + cellHeight);
403
+ const rRight = r(x + cellWidth);
334
404
  const paths = [];
335
405
  if (codePoint === 0x2571 || codePoint === 0x2573) {
336
- paths.push(`<line x1="${x}" y1="${y + cellHeight}" x2="${x + cellWidth}" y2="${y}" stroke="${color}" stroke-width="${lineWidth}"/>`);
406
+ paths.push(`<line x1="${rx}" y1="${rBottom}" x2="${rRight}" y2="${ry}" stroke="${color}" stroke-width="${lineWidth}"/>`);
337
407
  }
338
408
  if (codePoint === 0x2572 || codePoint === 0x2573) {
339
- paths.push(`<line x1="${x}" y1="${y}" x2="${x + cellWidth}" y2="${y + cellHeight}" stroke="${color}" stroke-width="${lineWidth}"/>`);
409
+ paths.push(`<line x1="${rx}" y1="${ry}" x2="${rRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
340
410
  }
341
411
  return { svg: paths.join(''), handled: true };
342
412
  }
343
413
  // Block Elements (U+2580-U+259F)
344
414
  function renderBlockElement(codePoint, ctx) {
345
- const { cellWidth, cellHeight, x, y, color } = ctx;
415
+ const { cellWidth, cellHeight, x, y, color, backgroundColor } = ctx;
346
416
  const crisp = ' shape-rendering="crispEdges"';
417
+ // Pre-compute rounded values for common fractions
418
+ const w = r(cellWidth);
419
+ const h = r(cellHeight);
420
+ const w2 = r(cellWidth / 2);
421
+ const w4 = r(cellWidth / 4);
422
+ const w8 = r(cellWidth / 8);
423
+ const w38 = r(cellWidth * 3 / 8);
424
+ const w58 = r(cellWidth * 5 / 8);
425
+ const w34 = r(cellWidth * 3 / 4);
426
+ const w78 = r(cellWidth * 7 / 8);
427
+ const h2 = r(cellHeight / 2);
428
+ const h4 = r(cellHeight / 4);
429
+ const h8 = r(cellHeight / 8);
430
+ const h38 = r(cellHeight * 3 / 8);
431
+ const h58 = r(cellHeight * 5 / 8);
432
+ const h34 = r(cellHeight * 3 / 4);
433
+ const h78 = r(cellHeight * 7 / 8);
434
+ const rx = r(x);
435
+ const ry = r(y);
347
436
  let svg = '';
348
437
  switch (codePoint) {
349
438
  case 0x2580: // Upper half block
350
- svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
439
+ svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`;
351
440
  break;
352
441
  case 0x2581: // Lower 1/8
353
- svg = `<rect x="${x}" y="${y + cellHeight * 7 / 8}" width="${cellWidth}" height="${cellHeight / 8}" fill="${color}"${crisp}/>`;
442
+ svg = `<rect x="${rx}" y="${r(y + h78)}" width="${w}" height="${h8}" fill="${color}"${crisp}/>`;
354
443
  break;
355
444
  case 0x2582: // Lower 1/4
356
- svg = `<rect x="${x}" y="${y + cellHeight * 3 / 4}" width="${cellWidth}" height="${cellHeight / 4}" fill="${color}"${crisp}/>`;
445
+ svg = `<rect x="${rx}" y="${r(y + h34)}" width="${w}" height="${h4}" fill="${color}"${crisp}/>`;
357
446
  break;
358
447
  case 0x2583: // Lower 3/8
359
- svg = `<rect x="${x}" y="${y + cellHeight * 5 / 8}" width="${cellWidth}" height="${cellHeight * 3 / 8}" fill="${color}"${crisp}/>`;
448
+ svg = `<rect x="${rx}" y="${r(y + h58)}" width="${w}" height="${h38}" fill="${color}"${crisp}/>`;
360
449
  break;
361
450
  case 0x2584: // Lower half
362
- svg = `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
451
+ svg = `<rect x="${rx}" y="${r(y + h2)}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`;
363
452
  break;
364
453
  case 0x2585: // Lower 5/8
365
- svg = `<rect x="${x}" y="${y + cellHeight * 3 / 8}" width="${cellWidth}" height="${cellHeight * 5 / 8}" fill="${color}"${crisp}/>`;
454
+ svg = `<rect x="${rx}" y="${r(y + h38)}" width="${w}" height="${h58}" fill="${color}"${crisp}/>`;
366
455
  break;
367
456
  case 0x2586: // Lower 3/4
368
- svg = `<rect x="${x}" y="${y + cellHeight / 4}" width="${cellWidth}" height="${cellHeight * 3 / 4}" fill="${color}"${crisp}/>`;
457
+ svg = `<rect x="${rx}" y="${r(y + h4)}" width="${w}" height="${h34}" fill="${color}"${crisp}/>`;
369
458
  break;
370
459
  case 0x2587: // Lower 7/8
371
- svg = `<rect x="${x}" y="${y + cellHeight / 8}" width="${cellWidth}" height="${cellHeight * 7 / 8}" fill="${color}"${crisp}/>`;
460
+ svg = `<rect x="${rx}" y="${r(y + h8)}" width="${w}" height="${h78}" fill="${color}"${crisp}/>`;
372
461
  break;
373
462
  case 0x2588: // Full block
374
- svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight}" fill="${color}"${crisp}/>`;
463
+ svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${color}"${crisp}/>`;
375
464
  break;
376
465
  case 0x2589: // Left 7/8
377
- svg = `<rect x="${x}" y="${y}" width="${cellWidth * 7 / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
466
+ svg = `<rect x="${rx}" y="${ry}" width="${w78}" height="${h}" fill="${color}"${crisp}/>`;
378
467
  break;
379
468
  case 0x258a: // Left 3/4
380
- svg = `<rect x="${x}" y="${y}" width="${cellWidth * 3 / 4}" height="${cellHeight}" fill="${color}"${crisp}/>`;
469
+ svg = `<rect x="${rx}" y="${ry}" width="${w34}" height="${h}" fill="${color}"${crisp}/>`;
381
470
  break;
382
471
  case 0x258b: // Left 5/8
383
- svg = `<rect x="${x}" y="${y}" width="${cellWidth * 5 / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
472
+ svg = `<rect x="${rx}" y="${ry}" width="${w58}" height="${h}" fill="${color}"${crisp}/>`;
384
473
  break;
385
474
  case 0x258c: // Left half
386
- svg = `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight}" fill="${color}"${crisp}/>`;
475
+ svg = `<rect x="${rx}" y="${ry}" width="${w2}" height="${h}" fill="${color}"${crisp}/>`;
387
476
  break;
388
477
  case 0x258d: // Left 3/8
389
- svg = `<rect x="${x}" y="${y}" width="${cellWidth * 3 / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
478
+ svg = `<rect x="${rx}" y="${ry}" width="${w38}" height="${h}" fill="${color}"${crisp}/>`;
390
479
  break;
391
480
  case 0x258e: // Left 1/4
392
- svg = `<rect x="${x}" y="${y}" width="${cellWidth / 4}" height="${cellHeight}" fill="${color}"${crisp}/>`;
481
+ svg = `<rect x="${rx}" y="${ry}" width="${w4}" height="${h}" fill="${color}"${crisp}/>`;
393
482
  break;
394
483
  case 0x258f: // Left 1/8
395
- svg = `<rect x="${x}" y="${y}" width="${cellWidth / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
484
+ svg = `<rect x="${rx}" y="${ry}" width="${w8}" height="${h}" fill="${color}"${crisp}/>`;
396
485
  break;
397
486
  case 0x2590: // Right half block
398
- svg = `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight}" fill="${color}"${crisp}/>`;
487
+ svg = `<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h}" fill="${color}"${crisp}/>`;
399
488
  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}/>`;
489
+ case 0x2591: // Light shade (25%) - pre-blend to avoid subpixel seams on high-DPI
490
+ svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${blendColors(color, backgroundColor, 0.25)}"${crisp}/>`;
402
491
  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}/>`;
492
+ case 0x2592: // Medium shade (50%) - pre-blend to avoid subpixel seams on high-DPI
493
+ svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${blendColors(color, backgroundColor, 0.5)}"${crisp}/>`;
405
494
  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}/>`;
495
+ case 0x2593: // Dark shade (75%) - pre-blend to avoid subpixel seams on high-DPI
496
+ svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${blendColors(color, backgroundColor, 0.75)}"${crisp}/>`;
408
497
  break;
409
498
  case 0x2594: // Upper 1/8 block
410
- svg = `<rect x="${x}" y="${y}" width="${cellWidth}" height="${cellHeight / 8}" fill="${color}"${crisp}/>`;
499
+ svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h8}" fill="${color}"${crisp}/>`;
411
500
  break;
412
501
  case 0x2595: // Right 1/8 block
413
- svg = `<rect x="${x + cellWidth * 7 / 8}" y="${y}" width="${cellWidth / 8}" height="${cellHeight}" fill="${color}"${crisp}/>`;
502
+ svg = `<rect x="${r(x + w78)}" y="${ry}" width="${w8}" height="${h}" fill="${color}"${crisp}/>`;
414
503
  break;
415
504
  case 0x2596: // Lower left
416
- svg = `<rect x="${x}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
505
+ svg = `<rect x="${rx}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
417
506
  break;
418
507
  case 0x2597: // Lower right
419
- svg = `<rect x="${x + cellWidth / 2}" y="${y + cellHeight / 2}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
508
+ svg = `<rect x="${r(x + w2)}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
420
509
  break;
421
510
  case 0x2598: // Upper left
422
- svg = `<rect x="${x}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
511
+ svg = `<rect x="${rx}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
423
512
  break;
424
513
  case 0x2599: // Upper left, lower left, lower right
425
514
  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}/>`,
515
+ `<rect x="${rx}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
516
+ `<rect x="${rx}" y="${r(y + h2)}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
428
517
  ].join('');
429
518
  break;
430
519
  case 0x259a: // Upper left, lower right
431
520
  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}/>`,
521
+ `<rect x="${rx}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
522
+ `<rect x="${r(x + w2)}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
434
523
  ].join('');
435
524
  break;
436
525
  case 0x259b: // Upper left, upper right, lower left
437
526
  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}/>`,
527
+ `<rect x="${rx}" y="${ry}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
528
+ `<rect x="${rx}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
440
529
  ].join('');
441
530
  break;
442
531
  case 0x259c: // Upper left, upper right, lower right
443
532
  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}/>`,
533
+ `<rect x="${rx}" y="${ry}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
534
+ `<rect x="${r(x + w2)}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
446
535
  ].join('');
447
536
  break;
448
537
  case 0x259d: // Upper right
449
- svg = `<rect x="${x + cellWidth / 2}" y="${y}" width="${cellWidth / 2}" height="${cellHeight / 2}" fill="${color}"${crisp}/>`;
538
+ svg = `<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
450
539
  break;
451
540
  case 0x259e: // Upper right, lower left
452
541
  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}/>`,
542
+ `<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
543
+ `<rect x="${rx}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
455
544
  ].join('');
456
545
  break;
457
546
  case 0x259f: // Upper right, lower left, lower right
458
547
  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}/>`,
548
+ `<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
549
+ `<rect x="${rx}" y="${r(y + h2)}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
461
550
  ].join('');
462
551
  break;
463
552
  default: