From d9ece9a30a4309b1319c0f7737b1ebea78abcd27 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Mon, 14 Sep 2026 09:49:04 -0400 Subject: [PATCH] bdf-glyph: hand-drawn 6x10 supplement for IPA + combining marks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit laer-klokken chat posted ɨ ɑČŧ Ľīĸę îɱ öĸąý ɓʊţ and ♫⃠; the X11 6x10 fallback face has no IPA letters (ɑ ɓ ɨ ɱ ʊ) or U+20E0, so font_1 drew nothing. The endpoint now consults system/backend/bdf-supplement.mjs on every miss (batch, single-char, and BDF-fetch failure). Native: widen the unifont subset to include IPA Extensions and Combining Diacritical Marks for Symbols; regenerate font-unicode.h (1754 → 1898 glyphs, baseline verified byte-identical first). Co-Authored-By: Claude Fable 5.1 --- fedac/native/scripts/bdf-unicode-to-c.py | 2 + fedac/native/src/font-unicode.h | 146 ++++++++++++++++++++++- system/backend/bdf-supplement.mjs | 124 +++++++++++++++++++ system/netlify/functions/bdf-glyph.js | 22 +++- 4 files changed, 290 insertions(+), 4 deletions(-) create mode 100644 system/backend/bdf-supplement.mjs diff --git a/fedac/native/scripts/bdf-unicode-to-c.py b/fedac/native/scripts/bdf-unicode-to-c.py index 9bb7d79978..c4168b06bf 100755 --- a/fedac/native/scripts/bdf-unicode-to-c.py +++ b/fedac/native/scripts/bdf-unicode-to-c.py @@ -19,10 +19,12 @@ def ranges(): (0x0020, 0x007E), # ASCII (full unifont parity for FONT_UNIFONT — nom word cells) (0x00A0, 0x00FF), # Latin-1 Supplement (accented chars, typographic) (0x0100, 0x017F), # Latin Extended-A + (0x0250, 0x02AF), # IPA Extensions (laer-klokken chat: ɑ ɓ ɨ ɱ ʊ …) (0x0391, 0x03CE), # Greek (alpha..omega) (0x0400, 0x04FF), # Cyrillic (rusnom boards + labels) (0x2010, 0x2027), # General Punctuation (em-dash, ellipsis, quotes) (0x2030, 0x2044), # Per mille, primes, fractions + (0x20D0, 0x20FF), # Combining Diacritical Marks for Symbols (♫⃠) (0x2190, 0x21FF), # Arrows (0x2200, 0x22FF), # Math operators (0x2500, 0x257F), # Box Drawing diff --git a/fedac/native/src/font-unicode.h b/fedac/native/src/font-unicode.h index d895860fc1..9941b189aa 100644 --- a/fedac/native/src/font-unicode.h +++ b/fedac/native/src/font-unicode.h @@ -17,7 +17,7 @@ typedef struct { } UnicodeGlyph; static const int unicode_ascent = 14; -static const int unicode_glyph_count = 1754; +static const int unicode_glyph_count = 1898; static const UnicodeGlyph unicode_glyphs[] = { {0x0020, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, @@ -339,6 +339,102 @@ static const UnicodeGlyph unicode_glyphs[] = { {0x017D, 8, 16, 0, -2, 8, {0x2400, 0x1800, 0x0000, 0x0000, 0x7E00, 0x0200, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x4000, 0x7E00, 0x0000, 0x0000}}, {0x017E, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x2400, 0x1800, 0x0000, 0x0000, 0x7E00, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x7E00, 0x0000, 0x0000}}, {0x017F, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0C00, 0x1000, 0x1000, 0x1000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000}}, + {0x0250, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5C00, 0x6200, 0x4200, 0x4200, 0x7C00, 0x4000, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x0251, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3A00, 0x4600, 0x4200, 0x4200, 0x4200, 0x4600, 0x4A00, 0x3200, 0x0000, 0x0000}}, + {0x0252, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4C00, 0x5200, 0x6200, 0x4200, 0x4200, 0x4200, 0x6200, 0x5C00, 0x0000, 0x0000}}, + {0x0253, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x3800, 0x4000, 0x4000, 0x5C00, 0x6200, 0x4200, 0x4200, 0x4200, 0x4200, 0x6200, 0x5C00, 0x0000, 0x0000}}, + {0x0254, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x0200, 0x0200, 0x0200, 0x0200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x0255, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4000, 0x4000, 0x4000, 0x4C00, 0x5200, 0x3C00, 0x4000, 0x0000}}, + {0x0256, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0400, 0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0300, 0x0000}}, + {0x0257, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0300, 0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000}}, + {0x0258, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x7E00, 0x0200, 0x0200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x0259, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x0200, 0x0200, 0x7E00, 0x4200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x025A, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3400, 0x4D00, 0x1A00, 0x2800, 0x4800, 0x4800, 0x4800, 0x3000, 0x0000, 0x0000}}, + {0x025B, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4000, 0x3C00, 0x4000, 0x4000, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x025C, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x0200, 0x3C00, 0x0200, 0x0200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x025D, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3400, 0x4D00, 0x0A00, 0x3000, 0x0800, 0x0800, 0x4800, 0x3000, 0x0000, 0x0000}}, + {0x025E, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x5C00, 0x4200, 0x4200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x025F, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0400, 0x0400, 0x0400, 0x1F00, 0x0400, 0x0400, 0x0400, 0x4800, 0x3000}}, + {0x0260, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0300, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x4400, 0x3800}}, + {0x0261, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3A00, 0x4600, 0x4200, 0x4200, 0x4200, 0x4600, 0x3A00, 0x0200, 0x4200, 0x3C00}}, + {0x0262, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4000, 0x4000, 0x4E00, 0x4200, 0x4200, 0x3E00, 0x0000, 0x0000}}, + {0x0263, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x4200, 0x4200, 0x2400, 0x2400, 0x1800, 0x1800, 0x2400, 0x2400, 0x1800}}, + {0x0264, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4400, 0xAA00, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000}}, + {0x0265, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x4600, 0x3A00, 0x0200, 0x0200, 0x0200}}, + {0x0266, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x3800, 0x4000, 0x4000, 0x5C00, 0x6200, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x0000, 0x0000}}, + {0x0267, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x3800, 0x4000, 0x4000, 0x5C00, 0x6200, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x0200, 0x0C00}}, + {0x0268, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0800, 0x0800, 0x0000, 0x1800, 0x0800, 0x0800, 0x3E00, 0x0800, 0x0800, 0x0800, 0x3E00, 0x0000, 0x0000}}, + {0x0269, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0C00, 0x0000, 0x0000}}, + {0x026A, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3E00, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x3E00, 0x0000, 0x0000}}, + {0x026B, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x1800, 0x0800, 0x0800, 0x0800, 0x3A00, 0x4C00, 0x0800, 0x0800, 0x0800, 0x0800, 0x3E00, 0x0000, 0x0000}}, + {0x026C, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x1800, 0x0800, 0x0800, 0x3800, 0x4800, 0x3E00, 0x0800, 0x0800, 0x0800, 0x0800, 0x3E00, 0x0000, 0x0000}}, + {0x026D, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x1800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0600, 0x0000}}, + {0x026E, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x3000, 0x1000, 0x1000, 0x1F00, 0x1100, 0x1200, 0x1400, 0x1600, 0x1100, 0x1100, 0x7D00, 0x0900, 0x0600}}, + {0x026F, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x3700, 0x0000, 0x0000}}, + {0x0270, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x3700, 0x0100, 0x0100}}, + {0x0271, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7600, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4100, 0x0600, 0x0000}}, + {0x0272, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1600, 0x1900, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x1100, 0x6000, 0x0000}}, + {0x0273, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0300, 0x0000}}, + {0x0274, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x4200, 0x6200, 0x5200, 0x4A00, 0x4600, 0x4200, 0x4200, 0x0000, 0x0000}}, + {0x0275, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x7E00, 0x4200, 0x4200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x0276, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3700, 0x4800, 0x4800, 0x4E00, 0x4800, 0x4800, 0x4800, 0x3700, 0x0000, 0x0000}}, + {0x0277, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3E00, 0x4100, 0x4100, 0x4900, 0x4900, 0x4900, 0x4900, 0x3600, 0x0000, 0x0000}}, + {0x0278, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0800, 0x0800, 0x0800, 0x3E00, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x3E00, 0x0800, 0x0800}}, + {0x0279, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x4200, 0x4600, 0x3A00, 0x0000, 0x0000}}, + {0x027A, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x4200, 0x4600, 0x3A00, 0x0000, 0x0000}}, + {0x027B, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x4C00, 0x3400, 0x0300, 0x0000}}, + {0x027C, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5C00, 0x6200, 0x4200, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000}}, + {0x027D, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5C00, 0x6200, 0x4200, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x3000, 0x0000}}, + {0x027E, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000}}, + {0x027F, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200}}, + {0x0280, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7C00, 0x4200, 0x4200, 0x7C00, 0x4800, 0x4400, 0x4200, 0x4200, 0x0000, 0x0000}}, + {0x0281, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x4200, 0x4400, 0x4800, 0x7C00, 0x4200, 0x4200, 0x7C00, 0x0000, 0x0000}}, + {0x0282, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4000, 0x3000, 0x0C00, 0x0200, 0x4200, 0x7C00, 0x4000, 0x3000}}, + {0x0283, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x6000, 0x0000}}, + {0x0284, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x6000, 0x0000}}, + {0x0285, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0C00, 0x0000}}, + {0x0286, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0600, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x3800, 0x4E00, 0x3000, 0x0000}}, + {0x0287, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x6000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000}}, + {0x0288, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0E00, 0x0000}}, + {0x0289, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2200, 0x2200, 0x2200, 0x7F00, 0x2200, 0x2200, 0x2600, 0x1A00, 0x0000, 0x0000}}, + {0x028A, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x2400, 0x4200, 0x4200, 0x4200, 0x4200, 0x2400, 0x1800, 0x0000, 0x0000}}, + {0x028B, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xCC00, 0x4200, 0x4200, 0x4200, 0x4200, 0x4400, 0x4800, 0x3000, 0x0000, 0x0000}}, + {0x028C, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1800, 0x1800, 0x2400, 0x2400, 0x2400, 0x4200, 0x4200, 0x4200, 0x0000, 0x0000}}, + {0x028D, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3600, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4900, 0x4100, 0x0000, 0x0000}}, + {0x028E, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4000, 0x4000, 0x5800, 0x6400, 0x4200, 0x4200, 0x4200, 0x4200, 0x4200, 0x0000, 0x0000}}, + {0x028F, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4100, 0x4100, 0x2200, 0x1400, 0x0800, 0x0800, 0x0800, 0x0800, 0x0000, 0x0000}}, + {0x0290, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7C00, 0x0800, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x7C00, 0x0400, 0x0300}}, + {0x0291, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7E00, 0x0200, 0x0400, 0x0800, 0x1000, 0x2600, 0x4900, 0x7E00, 0x1000, 0x0000}}, + {0x0292, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3E00, 0x0400, 0x0800, 0x1000, 0x1C00, 0x0200, 0x0200, 0x0200, 0x4200, 0x3C00}}, + {0x0293, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3E00, 0x0400, 0x0800, 0x1000, 0x1C00, 0x0200, 0x0200, 0x3200, 0x4A00, 0x3C00}}, + {0x0294, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x0200, 0x0400, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0000, 0x0000}}, + {0x0295, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x4000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000}}, + {0x0296, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0400, 0x0200, 0x4200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x0297, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4200, 0x3C00}}, + {0x0298, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x4200, 0x5A00, 0x5A00, 0x4200, 0x4200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x0299, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7C00, 0x4200, 0x4200, 0x7C00, 0x4200, 0x4200, 0x4200, 0x7C00, 0x0000, 0x0000}}, + {0x029A, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x3A00, 0x4200, 0x4200, 0x4200, 0x3C00, 0x0000, 0x0000}}, + {0x029B, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3B00, 0x4400, 0x4000, 0x4000, 0x4C00, 0x4400, 0x4400, 0x3C00, 0x0000, 0x0000}}, + {0x029C, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2200, 0x2200, 0x2200, 0x3E00, 0x2200, 0x2200, 0x2200, 0x2200, 0x0000, 0x0000}}, + {0x029D, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0400, 0x0400, 0x0000, 0x0C00, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x3E00, 0x4800, 0x3000}}, + {0x029E, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4200, 0x2200, 0x1200, 0x0A00, 0x0600, 0x0A00, 0x1200, 0x2200, 0x0200, 0x0200, 0x0200}}, + {0x029F, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7E00, 0x0000, 0x0000}}, + {0x02A0, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0300, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400}}, + {0x02A1, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x0200, 0x0400, 0x0800, 0x0800, 0x3E00, 0x0800, 0x0800, 0x0000, 0x0000}}, + {0x02A2, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x4200, 0x4200, 0x4000, 0x2000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000}}, + {0x02A3, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, 0x3F00, 0x5100, 0x5200, 0x5200, 0x5400, 0x5400, 0x5800, 0x3F00, 0x0000, 0x0000}}, + {0x02A4, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, 0x3F00, 0x5100, 0x5200, 0x5400, 0x5600, 0x5100, 0x5100, 0x3100, 0x0900, 0x0600}}, + {0x02A5, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, 0x3F00, 0x5100, 0x5200, 0x5400, 0x5800, 0x5200, 0x5500, 0x3E00, 0x0400, 0x0000}}, + {0x02A6, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x4000, 0x4600, 0xF900, 0x4800, 0x4400, 0x4200, 0x4100, 0x4100, 0x3E00, 0x0000, 0x0000}}, + {0x02A7, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0300, 0x2400, 0x2400, 0x2400, 0x7C00, 0x2400, 0x2400, 0x2400, 0x2400, 0x2400, 0x1C00, 0x0400, 0x1800}}, + {0x02A8, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x4000, 0x4600, 0xF900, 0x4800, 0x4800, 0x4800, 0x4A00, 0x4D00, 0x3E00, 0x0400, 0x0000}}, + {0x02A9, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x4800, 0x4000, 0x6E00, 0x5100, 0x5100, 0x5100, 0x5100, 0x5100, 0x5100, 0x0200, 0x0C00}}, + {0x02AA, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x6000, 0x2000, 0x2000, 0x2600, 0x2900, 0x2800, 0x2400, 0x2200, 0x2100, 0x2100, 0x7E00, 0x0000, 0x0000}}, + {0x02AB, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x6000, 0x2000, 0x2000, 0x3E00, 0x2200, 0x2400, 0x2400, 0x2800, 0x2800, 0x3000, 0x7E00, 0x0000, 0x0000}}, + {0x02AC, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x4900, 0x4900, 0x5500, 0x3600, 0x2200, 0x0000, 0x4900, 0x4900, 0x5500, 0x3600, 0x2200, 0x0000, 0x0000}}, + {0x02AD, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x7E00, 0x4200, 0x4200, 0x4200, 0x0000, 0x0000, 0x7E00, 0x4200, 0x4200, 0x4200, 0x0000, 0x0000}}, + {0x02AE, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6400, 0x2400, 0x2400, 0x2400, 0x2400, 0x2400, 0x2C00, 0x1400, 0x0400, 0x0400}}, + {0x02AF, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6400, 0x2400, 0x2400, 0x2400, 0x2400, 0x2400, 0x2C00, 0x1400, 0x0400, 0x0300}}, {0x0391, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x1800, 0x2400, 0x2400, 0x4200, 0x4200, 0x7E00, 0x4200, 0x4200, 0x4200, 0x4200, 0x0000, 0x0000}}, {0x0392, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x7C00, 0x4200, 0x4200, 0x4200, 0x7C00, 0x4200, 0x4200, 0x4200, 0x4200, 0x7C00, 0x0000, 0x0000}}, {0x0393, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x7E00, 0x4200, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000}}, @@ -702,6 +798,54 @@ static const UnicodeGlyph unicode_glyphs[] = { {0x2042, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0800, 0x1C00, 0x0800, 0x0000, 0x2200, 0x7700, 0x2200, 0x0000, 0x0000, 0x0000}}, {0x2043, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C00, 0x3C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, {0x2044, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0200, 0x0400, 0x0800, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x4000, 0x0000, 0x0000}}, + {0x20D0, 8, 16, 0, -2, 8, {0x0000, 0x1000, 0x2000, 0x7E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D1, 8, 16, 0, -2, 8, {0x0000, 0x0800, 0x0400, 0x7E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D2, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000}}, + {0x20D3, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D4, 8, 16, 0, -2, 8, {0x0000, 0x4C00, 0x5200, 0x6000, 0x7800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D5, 8, 16, 0, -2, 8, {0x0000, 0x3200, 0x4A00, 0x0600, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D6, 8, 16, 0, -2, 8, {0x1000, 0x2000, 0x7E00, 0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D7, 8, 16, 0, -2, 8, {0x0800, 0x0400, 0x7E00, 0x0400, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D8, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1800, 0x2400, 0x2400, 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20D9, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x3400, 0x2400, 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20DA, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C00, 0x2C00, 0x2400, 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20DB, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x2A00, 0x2A00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20DC, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x5500, 0x5500, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20DD, 16, 16, 0, -2, 16, {0x0000, 0x0380, 0x0C60, 0x3018, 0x2008, 0x4004, 0x4004, 0x8002, 0x8002, 0x8002, 0x4004, 0x4004, 0x2008, 0x3018, 0x0C60, 0x0380}}, + {0x20DE, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x7FFE, 0x0000}}, + {0x20DF, 16, 16, 0, -2, 16, {0x0000, 0x0100, 0x0280, 0x0440, 0x0820, 0x1010, 0x2008, 0x4004, 0x8002, 0x4004, 0x2008, 0x1010, 0x0820, 0x0440, 0x0280, 0x0100}}, + {0x20E0, 16, 16, 0, -2, 16, {0x0000, 0x0380, 0x0C60, 0x3018, 0x3008, 0x5804, 0x4C04, 0x8602, 0x8302, 0x8182, 0x40C4, 0x4064, 0x2038, 0x3018, 0x0C60, 0x0380}}, + {0x20E1, 8, 16, 0, -2, 8, {0x2400, 0x4200, 0xFF00, 0x4200, 0x2400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20E2, 16, 16, 0, -2, 16, {0x0000, 0x0000, 0x0000, 0x3FFC, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x4002, 0x3FFC, 0x7FFE, 0x0000}}, + {0x20E3, 16, 16, 0, -2, 16, {0x0000, 0x3FFC, 0x6006, 0x5FFA, 0x500A, 0x500A, 0x500A, 0x500A, 0x500A, 0x500A, 0x500A, 0x500A, 0x5FFA, 0x6006, 0x3FFC, 0x0000}}, + {0x20E4, 16, 16, 0, -2, 16, {0x0080, 0x01C0, 0x0140, 0x0360, 0x0220, 0x0410, 0x0410, 0x0808, 0x0808, 0x180C, 0x1004, 0x1004, 0x2002, 0x2002, 0x3FFE, 0x0000}}, + {0x20E5, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x2000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0000, 0x0000}}, + {0x20E6, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x2800, 0x0000, 0x0000}}, + {0x20E7, 16, 16, 0, -2, 16, {0x0000, 0x1FFF, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000}}, + {0x20E8, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x5400}}, + {0x20E9, 8, 16, 0, -2, 8, {0x0000, 0xFF00, 0x8100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20EA, 16, 16, 0, -2, 16, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0x0800, 0x1FFC, 0x0800, 0x0400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20EB, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0A00, 0x0A00, 0x0A00, 0x1400, 0x1400, 0x1400, 0x1400, 0x1400, 0x2800, 0x2800, 0x2800, 0x2800, 0x0000, 0x0000}}, + {0x20EC, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7E00, 0x0400, 0x0800}}, + {0x20ED, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7E00, 0x2000, 0x1000}}, + {0x20EE, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x2000, 0x7E00, 0x2000, 0x1000}}, + {0x20EF, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0800, 0x0400, 0x7E00, 0x0400, 0x0800}}, + {0x20F0, 8, 16, 0, -2, 8, {0x2400, 0x1800, 0x7E00, 0x1800, 0x2400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, + {0x20F1, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x61EE, 0x6FCE, 0x63EE, 0x6FEE, 0x6FC6, 0x7FFE, 0x0000}}, + {0x20F2, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x6186, 0x6FF6, 0x6386, 0x6FBE, 0x6F86, 0x7FFE, 0x0000}}, + {0x20F3, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x618E, 0x6FF6, 0x63C6, 0x6FF6, 0x6F8E, 0x7FFE, 0x0000}}, + {0x20F4, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x61B6, 0x6FB6, 0x6386, 0x6FF6, 0x6FF6, 0x7FFE, 0x0000}}, + {0x20F5, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x6186, 0x6FBE, 0x6386, 0x6FF6, 0x6F86, 0x7FFE, 0x0000}}, + {0x20F6, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x61CE, 0x6FBE, 0x638E, 0x6FB6, 0x6FCE, 0x7FFE, 0x0000}}, + {0x20F7, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x6186, 0x6FF6, 0x63EE, 0x6FDE, 0x6FDE, 0x7FFE, 0x0000}}, + {0x20F8, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x61CE, 0x6FB6, 0x63CE, 0x6FB6, 0x6FCE, 0x7FFE, 0x0000}}, + {0x20F9, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x61CE, 0x6FB6, 0x63C6, 0x6FF6, 0x6FCE, 0x7FFE, 0x0000}}, + {0x20FA, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x6186, 0x6FB6, 0x6386, 0x6FB6, 0x6FB6, 0x7FFE, 0x0000}}, + {0x20FB, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x618E, 0x6FB6, 0x638E, 0x6FB6, 0x6F8E, 0x7FFE, 0x0000}}, + {0x20FC, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x61C6, 0x6FBE, 0x63BE, 0x6FBE, 0x6FC6, 0x7FFE, 0x0000}}, + {0x20FD, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x618E, 0x6FB6, 0x63B6, 0x6FB6, 0x6F8E, 0x7FFE, 0x0000}}, + {0x20FE, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x6186, 0x6FBE, 0x638E, 0x6FBE, 0x6F86, 0x7FFE, 0x0000}}, + {0x20FF, 16, 16, 0, -2, 16, {0x0000, 0x7FFE, 0x61CE, 0x7DB6, 0x61B6, 0x6FB6, 0x61CE, 0x7FFE, 0x7FFE, 0x6186, 0x6FBE, 0x638E, 0x6FBE, 0x6FBE, 0x7FFE, 0x0000}}, {0x2190, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x2000, 0x7F00, 0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000}}, {0x2191, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0800, 0x1C00, 0x2A00, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800}}, {0x2192, 8, 16, 0, -2, 8, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0800, 0x0400, 0xFE00, 0x0400, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000}}, diff --git a/system/backend/bdf-supplement.mjs b/system/backend/bdf-supplement.mjs new file mode 100644 index 0000000000..ed722904e1 --- /dev/null +++ b/system/backend/bdf-supplement.mjs @@ -0,0 +1,124 @@ +// bdf-supplement, 26.09.14 +// Hand-drawn glyphs for characters a BDF font lacks. The `bdf-glyph` +// endpoint consults this after a miss, so chat can show letters the X11 +// 6x10 face never shipped (IPA, combining marks) without a second font. +// +// Rows are top-to-bottom, `#` = lit pixel. Every 6x10 glyph is drawn on the +// same 6x10 cell the BDF uses: baseline at row 7, rows 8–9 for descenders. + +const SIX_BY_TEN = { + // ɑ latin small letter alpha — single-storey a + 0x0251: [ + "......", + "......", + "......", + ".####.", + "#...#.", + "#...#.", + "#...#.", + ".####.", + "......", + "......", + ], + // ɓ latin small letter b with hook + 0x0253: [ + "......", + ".##...", + "#.....", + "#.##..", + "##..#.", + "#...#.", + "##..#.", + "#.##..", + "......", + "......", + ], + // ɨ latin small letter i with stroke + 0x0268: [ + "......", + "..#...", + "......", + ".##...", + "..#...", + "#####.", + "..#...", + ".###..", + "......", + "......", + ], + // ɱ latin small letter m with hook + 0x0271: [ + "......", + "......", + "......", + "##.#..", + "#.#.#.", + "#.#.#.", + "#.#.#.", + "#...#.", + "....#.", + "...#..", + ], + // ʊ latin small letter upsilon + 0x028a: [ + "......", + "......", + "......", + "##.##.", + "#...#.", + "#...#.", + "#...#.", + ".###..", + "......", + "......", + ], + // ⃠ combining enclosing circle backslash — drawn as its own cell + 0x20e0: [ + "......", + ".###..", + "#...#.", + "##..#.", + "#.#.#.", + "#..##.", + "#...#.", + ".###..", + "......", + "......", + ], +}; + +const FONTS = { + "6x10": { glyphs: SIX_BY_TEN, ascent: 8, descent: 2, yOffset: -2 }, +}; + +// Return glyph JSON in the exact shape `bdf-glyph` emits, or null. +export function supplementGlyph(fontName, charCode) { + const font = FONTS[fontName]; + const rows = font?.glyphs[charCode]; + if (!rows) return null; + + const height = rows.length; + const width = rows[0].length; + const commands = []; + rows.forEach((row, y) => { + for (let x = 0; x < row.length; x++) { + if (row[x] === "#") commands.push({ name: "point", args: [x, y] }); + } + }); + + return { + resolution: [width, height], + offset: [0, font.yOffset], + baselineOffset: [0, font.ascent - height - font.yOffset], + advance: width, + bbx: { width, height, xOffset: 0, yOffset: font.yOffset }, + dwidth: { x: width, y: 0 }, + fontMetrics: { ascent: font.ascent, descent: font.descent }, + commands, + supplement: true, + }; +} + +export function hasSupplement(fontName, charCode) { + return Boolean(FONTS[fontName]?.glyphs[charCode]); +} diff --git a/system/netlify/functions/bdf-glyph.js b/system/netlify/functions/bdf-glyph.js index a3d7a95550..ae41471899 100644 --- a/system/netlify/functions/bdf-glyph.js +++ b/system/netlify/functions/bdf-glyph.js @@ -13,6 +13,7 @@ import { PutObjectCommand, } from "@aws-sdk/client-s3"; import { shell } from "../../backend/shell.mjs"; +import { supplementGlyph } from "../../backend/bdf-supplement.mjs"; const gunzip = promisify(zlib.gunzip); @@ -431,6 +432,12 @@ async function parseGlyphFromBDF(charCodeToFind, charToFind, bdfText, fontParam) } } + // Not in the BDF — fall back to a hand-drawn supplement, if one exists. + const supplement = supplementGlyph(fontParam, charCodeToFind); + if (supplement) { + await cacheGlyph(charCodeToFind, supplement, fontParam); + return supplement; + } return null; // Glyph not found } @@ -541,10 +548,10 @@ export const handler = async (event) => { } } catch (error) { shell.error("Error in batch bdf-glyph:", error); - // Mark unfetched as null - for (const { codePointStr } of needsFetch) { + // BDF unreachable — supplements still work, everything else is null + for (const { codePointStr, charCode } of needsFetch) { if (!(codePointStr in results)) { - results[codePointStr] = null; + results[codePointStr] = supplementGlyph(fontParam, charCode); } } } @@ -859,6 +866,15 @@ export const handler = async (event) => { } if (!glyphFound) { + const supplement = supplementGlyph(fontParam, charCodeToFind); + if (supplement) { + if (!nocache) await cacheGlyph(charCodeToFind, supplement, fontParam); + return { + statusCode: 200, + body: JSON.stringify(supplement), + headers: { ...corsHeaders, "Content-Type": "application/json" }, + }; + } shell.log( `Glyph for character '${charToFind}' (code ${charCodeToFind}) was not found after parsing the entire file.`, ); -- 2.54.0