From 8f4b0d4c3f686458f22ffbddc42534bcc425b820 Mon Sep 17 00:00:00 2001 From: Bryson Meiling Date: Fri, 16 Oct 2026 14:50:09 -0600 Subject: [PATCH] text: test the whole Adobe Symbol encoding table The symbol_unicode table has 130 entries; only U+F0DE was covered by a test. Add symbol_unicode_table_covers_the_adobe_encoding, which asserts every code->real-Unicode mapping directly against the authoritative unicode.org/MAPPINGS/VENDORS/ADOBE/symbol.txt table, plus that ASCII pass-through and CUS fragment codes return None. It is pure and platform-independent (no fonts involved), so it runs on every machine and catches any typo in the table. --- crates/text/src/tests.rs | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/crates/text/src/tests.rs b/crates/text/src/tests.rs index 1c4df854..f51fd0c9 100644 --- a/crates/text/src/tests.rs +++ b/crates/text/src/tests.rs @@ -969,6 +969,56 @@ fn symbol_font_remaps_private_use_to_real_unicode() { } } +/// Every entry of the Adobe Symbol encoding table, in full. Pure and platform-independent: the +/// table maps a Symbol code to its real Unicode character regardless of any installed font, so this +/// runs on every machine. Guarded against typos in `symbol_unicode` (e.g. 0x40 must be U+2245, the +/// congruent sign, not U+22C5 dot operator). +#[test] +fn symbol_unicode_table_covers_the_adobe_encoding() { + // (code, real Unicode) from unicode.org/Public/MAPPINGS/VENDORS/ADOBE/symbol.txt. + // Only the non-ASCII, non-CUS entries; ASCII codes pass through as themselves and CUS fragment + // glyphs have no standard Unicode point, so `symbol_unicode` returns None for them. + let table: &[(u32, u32)] = &[ + // 0x20–0x7E: the few mathematical ones among the ASCII-range characters. + (0x22, 0x2200), (0x24, 0x2203), (0x27, 0x220B), (0x2A, 0x2217), (0x2D, 0x2212), (0x3C, 0x2264), (0x3D, 0x2265), (0x3E, 0x221E), (0x3F, 0x2234), (0x40, 0x2245), + (0x5C, 0x2234), (0x5E, 0x22A5), (0x7E, 0x223C), + // 0x41–0x5A: Greek uppercase. + (0x41, 0x0391), (0x42, 0x0392), (0x43, 0x03A7), (0x44, 0x0394), (0x45, 0x0395), (0x46, 0x03A6), (0x47, 0x0393), (0x48, 0x0397), (0x49, 0x0399), (0x4A, 0x03D1), + (0x4B, 0x039A), (0x4C, 0x039B), (0x4D, 0x039C), (0x4E, 0x039D), (0x4F, 0x039F), (0x50, 0x03A0), (0x51, 0x0398), (0x52, 0x03A1), (0x53, 0x03A3), (0x54, 0x03A4), + (0x55, 0x03A5), (0x56, 0x03C2), (0x57, 0x03A9), (0x58, 0x039E), (0x59, 0x03A8), (0x5A, 0x0396), + // 0x61–0x7A: Greek lowercase. + (0x61, 0x03B1), (0x62, 0x03B2), (0x63, 0x03C7), (0x64, 0x03B4), (0x65, 0x03B5), (0x66, 0x03C6), (0x67, 0x03B3), (0x68, 0x03B7), (0x69, 0x03B9), (0x6A, 0x03D5), + (0x6B, 0x03BA), (0x6C, 0x03BB), (0x6D, 0x03BC), (0x6E, 0x03BD), (0x6F, 0x03BF), (0x70, 0x03C0), (0x71, 0x03B8), (0x72, 0x03C1), (0x73, 0x03C3), (0x74, 0x03C4), + (0x75, 0x03C5), (0x76, 0x03D6), (0x77, 0x03C9), (0x78, 0x03BE), (0x79, 0x03C8), (0x7A, 0x03B6), + // 0xA1–0xAF: Greek upsilon with hook, primes, math, suits and arrows. + (0xA1, 0x03D2), (0xA2, 0x2032), (0xA3, 0x2264), (0xA4, 0x2215), (0xA5, 0x221E), (0xA6, 0x0192), (0xA7, 0x2663), (0xA8, 0x2666), (0xA9, 0x2665), (0xAA, 0x2660), + (0xAB, 0x2194), (0xAC, 0x2190), (0xAD, 0x2191), (0xAE, 0x2192), (0xAF, 0x2193), + // 0xB0–0xBC: degree, plus-minus, double prime, math and ellipsis. + (0xB0, 0x00B0), (0xB1, 0x00B1), (0xB2, 0x2033), (0xB3, 0x2265), (0xB4, 0x00D7), (0xB5, 0x221D), (0xB6, 0x2202), (0xB7, 0x2022), (0xB8, 0x00F7), (0xB9, 0x2260), + (0xBA, 0x2261), (0xBB, 0x2248), (0xBC, 0x2026), (0xBF, 0x21B5), + // 0xC0–0xCF: letterlike symbols, set relations. + (0xC0, 0x2135), (0xC1, 0x2111), (0xC2, 0x211C), (0xC3, 0x2118), (0xC4, 0x2297), (0xC5, 0x2295), (0xC6, 0x2205), (0xC7, 0x2229), (0xC8, 0x222A), (0xC9, 0x2283), + (0xCA, 0x2287), (0xCB, 0x2284), (0xCC, 0x2282), (0xCD, 0x2286), (0xCE, 0x2208), (0xCF, 0x2209), + // 0xD0–0xDF: angle, nabla, product, radical, not, ands, ors, double arrows. + (0xD0, 0x2220), (0xD1, 0x2207), (0xD5, 0x220F), (0xD6, 0x221A), (0xD7, 0x22C5), (0xD8, 0x00AC), (0xD9, 0x2227), (0xDA, 0x2228), (0xDB, 0x21D4), (0xDC, 0x21D0), + (0xDD, 0x21D1), (0xDE, 0x21D2), (0xDF, 0x21D3), + // 0xE0–0xF5: lozenge, angle brackets, summation, integral. + (0xE0, 0x25CA), (0xE1, 0x2329), (0xE5, 0x2211), (0xF1, 0x232A), (0xF2, 0x222B), (0xF3, 0x2320), (0xF5, 0x2321), + ]; + for &(code, uni) in table { + assert_eq!(symbol_unicode(code), Some(uni), "Symbol code 0x{code:02X} must map to U+{uni:04X}"); + } + // ASCII codes pass through as themselves (symbol_unicode has no entry), and the CUS fragment + // codes return None: 0x60 radical extender, 0xBD/0xBE arrow extenders, 0xD2–0xD4 serif marks, + // 0xE2–0xE4 sans-serif marks and the paren/bracket extender run 0xE6–0xFF. + for code in [0x20, 0x21, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2B, 0x2C, 0x2E, 0x2F, 0x30, 0x31, 0x39, 0x3A, 0x3B, 0x5B, 0x5D, 0x5F, 0x7B, 0x7C, 0x7D] { + assert_eq!(symbol_unicode(code), None, "ASCII code 0x{code:02X} has no Symbol remap"); + } + for code in [0x60, 0xBD, 0xBE, 0xD2, 0xD3, 0xD4, 0xE2, 0xE3, 0xE4, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF4, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF] { + assert_eq!(symbol_unicode(code), None, "CUS code 0x{code:02X} has no standard Unicode remap"); + } +} + #[test] fn symbol_font_characters_draw_in_the_sym_font() { // PowerPoint stores a Symbol-font character as U+F0xx with ``: