diff options
| author | eunhhu <[email protected]> | 2026-09-28 15:03:30 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-28 15:03:30 +0100 |
| commit | 5788d7e5bd6a26421346d69ae517502527940a0b (patch) | |
| tree | ee540bf287a41bef4b052f43b4fe9c9c48099776 /text | |
| parent | b5659615bd770fd641f389e5fde8ae97be505fca (diff) | |
| download | vega-5788d7e5bd6a26421346d69ae517502527940a0b.tar.gz vega-5788d7e5bd6a26421346d69ae517502527940a0b.zip | |
Shape the Universal Shaping Engine's scripts as HarfBuzz does
The USE shaper, from HarfBuzz 10.2's source, for Sinhala, Tibetan,
Javanese, Balinese, Mongolian and the rest of its eighty-odd scripts
(and Indic fonts with the new dev3-style tags). The syllable machine
reads past CGJs and ZWNJs that marks follow; rphf goes on each
syllable's first glyphs and records the repha it made, pref records its
pre-base glyph, with substitution marks cleared between; a repha moves
before the first post-base glyph and pre-base vowels move back. Scripts
that join like Arabic take Arabic's forms (Mongolian's free variation
selectors their base's), the others join syllable to syllable. Marks
lose their advances before GPOS.
text/syllabic.py carries HarfBuzz's compressed USE table over as it is,
compiles the USE grammar with the others (100,000 random runs against
Ragel's machine: no syllable differs), and checks at compile time that
the categories syllabic.h names are the machines' own.
Noto Sans Sinhala, Javanese, Balinese, Mongolian, Noto Serif Tibetan,
FreeSerif's Sinhala and Unifont's five shape as HarfBuzz does at 5,000
runs a plan; all installed fonts (1,748 plans) and 21 Noto fonts too.
Diffstat (limited to 'text')
| -rw-r--r-- | text/shape-build.c | 55 | ||||
| -rw-r--r-- | text/shape.c | 214 | ||||
| -rw-r--r-- | text/shape.h | 10 | ||||
| -rw-r--r-- | text/syllabic-data.c | 501 | ||||
| -rw-r--r-- | text/syllabic.h | 16 | ||||
| -rw-r--r-- | text/syllabic.py | 40 |
6 files changed, 815 insertions, 21 deletions
diff --git a/text/shape-build.c b/text/shape-build.c index 166ad22..a3b924e 100644 --- a/text/shape-build.c +++ b/text/shape-build.c @@ -334,8 +334,9 @@ static int categorize(uint32_t script, hb_tag_t gsub_script) { if (script == TAG("Khmr")) return VEGA_SHAPER_KHMER; if (script == TAG("Syrc") || script == TAG("Thai") || script == TAG("Laoo") || script == TAG("Qaag")) return -1; if (listed(indic_scripts, sizeof(indic_scripts) / sizeof(*indic_scripts), script)) - return dflt ? VEGA_SHAPER_DEFAULT : (gsub_script & 0xFF) == '3' ? -1 : VEGA_SHAPER_INDIC; - if (listed(use_scripts, sizeof(use_scripts) / sizeof(*use_scripts), script)) return dflt ? VEGA_SHAPER_DEFAULT : -1; + return dflt ? VEGA_SHAPER_DEFAULT : (gsub_script & 0xFF) == '3' ? VEGA_SHAPER_USE : VEGA_SHAPER_INDIC; + if (listed(use_scripts, sizeof(use_scripts) / sizeof(*use_scripts), script)) + return dflt ? VEGA_SHAPER_DEFAULT : VEGA_SHAPER_USE; if (script == TAG("Mymr")) return dflt || gsub_script == TAG("mymr") ? VEGA_SHAPER_DEFAULT : VEGA_SHAPER_MYANMAR; return VEGA_SHAPER_DEFAULT; } @@ -545,6 +546,32 @@ static bool plan_for(hb_face_t *face, uint32_t script_tag, int direction, Plan * add_gsub_pause(m, VEGA_PAUSE_CLEAR_SYLLABLES); for (int i = 0; i < 4; ++i) enable_feature(m, TAG(myanmar_other[i]), F_MANUAL_ZWJ, 1); } + /* hb-ot-shaper-use.cc: syllables; the default glyph pre-processing; + * rphf and pref, each recording what it substituted; the basic + * features; the reordering; the topographical forms; the rest. */ + static const char *const use_basic[] = {"rkrf", "abvf", "blwf", "half", "pstf", "vatu", "cjct"}; + static const char *const use_topographical[] = {"isol", "init", "medi", "fina"}; + static const char *const use_other[] = {"abvs", "blws", "haln", "pres", "psts"}; + if (shaper == VEGA_SHAPER_USE) { + m->is_simple = false; + add_gsub_pause(m, VEGA_PAUSE_SYLLABLES); + enable_feature(m, TAG("locl"), F_PER_SYLLABLE, 1); + enable_feature(m, TAG("ccmp"), F_PER_SYLLABLE, 1); + enable_feature(m, TAG("nukt"), F_PER_SYLLABLE, 1); + enable_feature(m, TAG("akhn"), F_MANUAL_ZWJ | F_PER_SYLLABLE, 1); + add_gsub_pause(m, VEGA_PAUSE_CLEAR_SUBSTITUTED); + add_feature(m, TAG("rphf"), F_MANUAL_ZWJ | F_PER_SYLLABLE, 1); + add_gsub_pause(m, VEGA_PAUSE_RECORD_RPHF); + add_gsub_pause(m, VEGA_PAUSE_CLEAR_SUBSTITUTED); + enable_feature(m, TAG("pref"), F_MANUAL_ZWJ | F_PER_SYLLABLE, 1); + add_gsub_pause(m, VEGA_PAUSE_RECORD_PREF); + for (int i = 0; i < 7; ++i) enable_feature(m, TAG(use_basic[i]), F_MANUAL_ZWJ | F_PER_SYLLABLE, 1); + add_gsub_pause(m, VEGA_PAUSE_INITIAL_REORDERING); + add_gsub_pause(m, VEGA_PAUSE_CLEAR_SYLLABLES); + for (int i = 0; i < 4; ++i) add_feature(m, TAG(use_topographical[i]), F_NONE, 1); + add_gsub_pause(m, 0); + for (int i = 0; i < 5; ++i) enable_feature(m, TAG(use_other[i]), F_MANUAL_ZWJ, 1); + } if (shaper == VEGA_SHAPER_HANGUL) { m->is_simple = false; add_feature(m, TAG("ljmo"), F_NONE, 1); @@ -583,7 +610,7 @@ static bool plan_for(hb_face_t *face, uint32_t script_tag, int direction, Plan * /* Hangul's, Indic's and Khmer's shapers zero no marks (Myanmar's does, * before GPOS); none of these places marks without GPOS. */ bool zeroes = shaper != VEGA_SHAPER_HANGUL && shaper != VEGA_SHAPER_INDIC && shaper != VEGA_SHAPER_KHMER; - bool script_marks = zeroes && shaper != VEGA_SHAPER_MYANMAR; + bool script_marks = zeroes && shaper != VEGA_SHAPER_MYANMAR && shaper != VEGA_SHAPER_USE; bool adjust = !apply_gpos && (!apply_kern || !kern_table.cross), fallback_marks = adjust && script_marks; if (shaper == VEGA_SHAPER_ARABIC) { if (one_mask(m, "stch")) FAIL("%s: the font stretches (stch)", name); @@ -610,8 +637,9 @@ static bool plan_for(hb_face_t *face, uint32_t script_tag, int direction, Plan * plan->masks[VEGA_MASK_FRAC] = frac; plan->masks[VEGA_MASK_NUMR] = numr; plan->masks[VEGA_MASK_DNOM] = dnom; - if (shaper == VEGA_SHAPER_ARABIC) + if (shaper == VEGA_SHAPER_ARABIC || shaper == VEGA_SHAPER_USE) for (int i = 0; i < 7; ++i) plan->masks[VEGA_MASK_ISOL + i] = one_mask(m, arabic_features[i]); + if (shaper == VEGA_SHAPER_USE) plan->masks[VEGA_MASK_USE_RPHF] = one_mask(m, "rphf"); if (shaper == VEGA_SHAPER_HANGUL) { plan->masks[VEGA_MASK_LJMO] = one_mask(m, "ljmo"); plan->masks[VEGA_MASK_VJMO] = one_mask(m, "vjmo"); @@ -975,8 +1003,9 @@ void vega_shaping_check(hb_font_t *font, const VegaShaping *s, uint32_t script, * punctuation), and those whose glyphs some substitution starts from. */ Pool letters = {0}, marks = {0}, others = {0}, hot = {0}, jamo_pools[3] = {{0}}, indic[INDIC_POOLS] = {{0}}; bool hangul = script == HB_TAG('H', 'a', 'n', 'g'); + bool use = listed(use_scripts, sizeof(use_scripts) / sizeof(*use_scripts), script); bool syllabic = listed(indic_scripts, sizeof(indic_scripts) / sizeof(*indic_scripts), script) || - script == HB_TAG('K', 'h', 'm', 'r') || script == HB_TAG('M', 'y', 'm', 'r'); + script == HB_TAG('K', 'h', 'm', 'r') || script == HB_TAG('M', 'y', 'm', 'r') || use; hb_set_t *inputs = hb_set_create(); uint32_t common = HB_TAG('Z', 'y', 'y', 'y'), inherited = HB_TAG('Z', 'i', 'n', 'h'); for (unsigned t = 0; t < s->lookup_count[0]; ++t) @@ -990,7 +1019,21 @@ void vega_shaping_check(hb_font_t *font, const VegaShaping *s, uint32_t script, if (hangul && ((code >= 0x1100 && code <= 0x115F) || (code >= 0xA960 && code <= 0xA97C))) pool_add(&jamo_pools[0], code); if (hangul && ((code >= 0x1160 && code <= 0x11A7) || (code >= 0xD7B0 && code <= 0xD7C6))) pool_add(&jamo_pools[1], code); if (hangul && ((code >= 0x11A8 && code <= 0x11FF) || (code >= 0xD7CB && code <= 0xD7FB))) pool_add(&jamo_pools[2], code); - if (syllabic && (of == script || of == inherited)) { + if (use && (of == script || of == inherited)) { + int pool = -1; + switch (vega_use_category(code)) { + case VEGA_USE_B: case VEGA_USE_GB: case VEGA_USE_CS: pool = INDIC_CONSONANTS; break; + case VEGA_USE_R: pool = INDIC_RA; break; + case VEGA_USE_H: case VEGA_USE_IS: case VEGA_USE_HVM: case VEGA_USE_SK: pool = INDIC_HALANTS; break; + case VEGA_USE_SUB: case VEGA_USE_CMABV: case VEGA_USE_CMBLW: case VEGA_USE_MABV: case VEGA_USE_MBLW: + case VEGA_USE_MPST: case VEGA_USE_MPRE: pool = INDIC_NUKTAS; break; + case VEGA_USE_VABV: case VEGA_USE_VBLW: case VEGA_USE_VPST: case VEGA_USE_VPRE: pool = INDIC_MATRAS; break; + case VEGA_USE_VMABV: case VEGA_USE_VMBLW: case VEGA_USE_VMPST: case VEGA_USE_VMPRE: case VEGA_USE_SMABV: + case VEGA_USE_SMBLW: case VEGA_USE_FABV: case VEGA_USE_FBLW: case VEGA_USE_FPST: case VEGA_USE_FMABV: + case VEGA_USE_FMBLW: case VEGA_USE_FMPST: pool = INDIC_MODIFIERS; break; + } + if (pool >= 0) pool_add(&indic[pool], code); + } else if (syllabic && (of == script || of == inherited)) { int pool = -1; switch (vega_indic_categories(code) & 0xFF) { case VEGA_OT_C: case VEGA_OT_CS: pool = INDIC_CONSONANTS; break; diff --git a/text/shape.c b/text/shape.c index 4dd92da..76d5409 100644 --- a/text/shape.c +++ b/text/shape.c @@ -227,7 +227,7 @@ bool vega_shaping_open(VegaShaping *s, const unsigned char *bytes, size_t size, for (uint32_t i = 0; i < s->plan_count; ++i) { const unsigned char *p = s->plans + (size_t)i * VEGA_PLAN_BYTES; uint32_t ranges[2][2] = {{le32(p + 80), le32(p + 84)}, {le32(p + 88), le32(p + 92)}}; - if ((p[4] != VEGA_SHAPE_LTR && p[4] != VEGA_SHAPE_RTL) || p[5] > VEGA_SHAPE_RTL || p[6] > VEGA_SHAPER_MYANMAR) + if ((p[4] != VEGA_SHAPE_LTR && p[4] != VEGA_SHAPE_RTL) || p[5] > VEGA_SHAPE_RTL || p[6] > VEGA_SHAPER_USE) REFUSE("plan %u", i); if ((p[7] & VEGA_PLAN_FALLBACK_MARKS) && !s->extents) REFUSE("plan %u: marks placed without extents", i); for (int table = 0; table < 2; ++table) { @@ -236,7 +236,7 @@ bool vega_shaping_open(VegaShaping *s, const unsigned char *bytes, size_t size, for (uint32_t k = 0; k < ranges[table][1]; ++k) { const unsigned char *step = s->steps + (size_t)(ranges[table][0] + k) * VEGA_STEP_BYTES; bool pause = le16(step) == VEGA_STEP_PAUSE; - if (pause ? table || !step[2] || step[2] > VEGA_PAUSE_CLEAR_SYLLABLES : le16(step) >= s->lookup_count[table]) + if (pause ? table || !step[2] || step[2] > VEGA_PAUSE_RECORD_PREF : le16(step) >= s->lookup_count[table]) REFUSE("plan %u: a lookup the font lacks", i); } } @@ -315,6 +315,7 @@ typedef struct { struct VegaShaper { Info *info, *out; Position *pos; + uint32_t *kept; /* the glyphs a syllable machine reads (USE's) */ size_t len, out_len, idx, allocated, max_len; bool have_output, successful; int direction; @@ -334,6 +335,7 @@ void vega_shaper_free(VegaShaper *b) { free(b->info); free(b->out); free(b->pos); + free(b->kept); free(b->glyphs); free(b); } @@ -352,11 +354,13 @@ static bool ensure(VegaShaper *b, size_t size) { Info *out = info ? realloc(b->out, n * sizeof(*out)) : NULL; if (out) b->out = out; Position *pos = out ? realloc(b->pos, n * sizeof(*pos)) : NULL; - if (!pos) { + if (pos) b->pos = pos; + uint32_t *kept = pos ? realloc(b->kept, n * sizeof(*kept)) : NULL; + if (!kept) { b->successful = false; return false; } - b->pos = pos; + b->kept = kept; b->allocated = n; return true; } @@ -823,7 +827,7 @@ static bool compose(const Normalizer *c, uint32_t a, uint32_t b, uint32_t *ab) { switch (c->plan->shaper) { case VEGA_SHAPER_HEBREW: return compose_hebrew(c, a, b, ab); case VEGA_SHAPER_INDIC: return compose_indic(a, b, ab); - case VEGA_SHAPER_KHMER: return !is_mark_category(vega_category(a)) && compose_unicode(a, b, ab); + case VEGA_SHAPER_KHMER: case VEGA_SHAPER_USE: return !is_mark_category(vega_category(a)) && compose_unicode(a, b, ab); default: return compose_unicode(a, b, ab); } } @@ -1035,7 +1039,7 @@ static void normalize(const VegaShaping *s, const Plan *plan, VegaShaper *b) { * Indic's decomposes what decomposes even when the font has it whole. */ const bool none = plan->shaper == VEGA_SHAPER_HANGUL; const bool syllabic = plan->shaper == VEGA_SHAPER_INDIC || plan->shaper == VEGA_SHAPER_KHMER || - plan->shaper == VEGA_SHAPER_MYANMAR; + plan->shaper == VEGA_SHAPER_MYANMAR || plan->shaper == VEGA_SHAPER_USE; const bool always_short_circuit = none, might_short_circuit = none || !syllabic; bool all_simple = true; clear_output(b); @@ -1169,6 +1173,10 @@ static void setup_masks_arabic(VegaShaper *b, const Plan *plan) { prev = i; state = entry[2]; } + if (plan->script == TAG4('M', 'o', 'n', 'g')) + for (size_t i = 1; i < b->len; ++i) + if ((b->info[i].codepoint >= 0x180B && b->info[i].codepoint <= 0x180D) || b->info[i].codepoint == 0x180F) + b->info[i].action = b->info[i - 1].action; for (size_t i = 0; i < b->len; ++i) if (b->info[i].action < NONE) b->info[i].mask |= plan->masks[VEGA_MASK_ISOL + b->info[i].action]; } @@ -3325,6 +3333,183 @@ static bool myanmar_reorder(const VegaShaping *s, VegaShaper *b) { return changed; } +/* ---- The Universal Shaping Engine (hb-ot-shaper-use.cc): syllables by + * USE categories; rphf and pref, each recording what it made (a repha, a + * pre-base glyph); then a repha moved before the first post-base glyph and + * pre-base glyphs moved to the start (or past a halant). Scripts that join + * like Arabic take Arabic's forms; others join syllable to syllable. */ + +enum { USE_VIRAMA_TERMINATED, USE_SAKOT_TERMINATED, USE_STANDARD, USE_NUMBER_JOINER_TERMINATED, USE_NUMERAL, + USE_SYMBOL, USE_HIEROGLYPH, USE_BROKEN, USE_NON_CLUSTER }; + +/* The scripts with Arabic's joining data (hb-ot-shaper-arabic-joining-list.hh). */ +static bool arabic_joining_script(uint32_t script) { + switch (script) { + case TAG4('A', 'd', 'l', 'm'): case TAG4('A', 'r', 'a', 'b'): case TAG4('C', 'h', 'r', 's'): + case TAG4('R', 'o', 'h', 'g'): case TAG4('M', 'a', 'n', 'd'): case TAG4('M', 'a', 'n', 'i'): + case TAG4('M', 'o', 'n', 'g'): case TAG4('N', 'k', 'o', 'o'): case TAG4('O', 'u', 'g', 'r'): + case TAG4('P', 'h', 'a', 'g'): case TAG4('P', 'h', 'l', 'p'): case TAG4('S', 'o', 'g', 'd'): + case TAG4('S', 'y', 'r', 'c'): + return true; + default: + return false; + } +} + +static void setup_masks_use(VegaShaper *b, const Plan *plan) { + if (arabic_joining_script(plan->script)) setup_masks_arabic(b, plan); + for (size_t i = 0; i < b->len; ++i) b->info[i].category = vega_use_category(b->info[i].codepoint); +} + +/* The machine reads the glyphs but CGJs, and a ZWNJ only when no mark + * follows it (past CGJs); a syllable holds what it skipped after it. */ +static void find_syllables_use(VegaShaper *b) { + size_t n = 0; + for (size_t i = 0; i < b->len; ++i) { + if (b->info[i].category == VEGA_USE_CGJ) continue; + if (b->info[i].category == VEGA_USE_ZWNJ) { + size_t k = i + 1; + while (k < b->len && b->info[k].category == VEGA_USE_CGJ) k++; + if (k < b->len && is_unicode_mark(&b->info[k])) continue; + } + b->kept[n++] = (uint32_t)i; + } + const VegaMachine *m = &vega_use_machine; + unsigned serial = 1; + for (size_t p = 0; p < n;) { + unsigned state = 0, type = 0; + size_t end = p + 1; + for (size_t q = p; q < n; ++q) { + unsigned category = b->info[b->kept[q]].category; + size_t cell = (size_t)state * m->classes + m->class_of[category < 63 ? category : 63]; + state = m->width == 1 ? ((const uint8_t *)m->next)[cell] : ((const uint16_t *)m->next)[cell]; + if (state >= m->states) break; + if (m->accept[state]) type = m->accept[state], end = q + 1; + } + if (type == m->broken) b->scratch |= HAS_BROKEN_SYLLABLE; + size_t first = b->kept[p], last = end < n ? b->kept[end] : b->len; + for (size_t i = first; i < last; ++i) b->info[i].syllable = (uint8_t)(serial << 4 | (type ? type - 1 : 0)); + if (++serial == 16) serial = 1; + p = end; + } +} + +static void use_setup_syllables(const Plan *plan, VegaShaper *b) { + find_syllables_use(b); + Info *info = b->info; + /* rphf on what may be a repha: an encoded one, or the first three */ + uint32_t rphf = plan->masks[VEGA_MASK_USE_RPHF]; + if (rphf) + for (size_t start = 0, end; start < b->len; start = end) { + end = next_syllable(b, start); + size_t limit = info[start].category == VEGA_USE_R ? 1 : end - start < 3 ? end - start : 3; + for (size_t i = start; i < start + limit; ++i) info[i].mask |= rphf; + } + /* Joining forms, syllable to syllable, where Arabic's did not come. */ + if (arabic_joining_script(plan->script)) return; + enum { FORM_ISOL, FORM_INIT, FORM_MEDI, FORM_FINA, FORM_NONE }; + uint32_t masks[4] = {plan->masks[VEGA_MASK_ISOL], plan->masks[VEGA_MASK_INIT], plan->masks[VEGA_MASK_MEDI], + plan->masks[VEGA_MASK_FINA]}, + all = 0; + for (int i = 0; i < 4; ++i) { + if (masks[i] == plan->global_mask) masks[i] = 0; + all |= masks[i]; + } + if (!all) return; + uint32_t other = ~all; + size_t last_start = 0; + int last_form = FORM_NONE; + for (size_t start = 0, end; start < b->len; start = end) { + end = next_syllable(b, start); + unsigned type = info[start].syllable & 0x0F; + if (type == USE_HIEROGLYPH || type == USE_NON_CLUSTER) + last_form = FORM_NONE; + else { + bool join = last_form == FORM_FINA || last_form == FORM_ISOL; + if (join) { + last_form = last_form == FORM_FINA ? FORM_MEDI : FORM_INIT; + for (size_t i = last_start; i < start; ++i) info[i].mask = (info[i].mask & other) | masks[last_form]; + } + last_form = join ? FORM_FINA : FORM_ISOL; + for (size_t i = start; i < end; ++i) info[i].mask = (info[i].mask & other) | masks[last_form]; + } + last_start = start; + } +} + +/* A repha rphf made (the first substituted glyph under its mask) is a + * repha; a glyph pref made is a pre-base vowel. */ +static void use_record(const Plan *plan, VegaShaper *b, unsigned pause) { + uint32_t rphf = plan->masks[VEGA_MASK_USE_RPHF]; + if (pause == VEGA_PAUSE_RECORD_RPHF && !rphf) return; + for (size_t start = 0, end; start < b->len; start = end) { + end = next_syllable(b, start); + for (size_t i = start; i < end && (pause != VEGA_PAUSE_RECORD_RPHF || (b->info[i].mask & rphf)); ++i) + if (b->info[i].gprops & SUBSTITUTED) { + b->info[i].category = pause == VEGA_PAUSE_RECORD_RPHF ? VEGA_USE_R : VEGA_USE_VPRE; + break; + } + } +} + +static bool is_halant_use(const Info *i) { + return (i->category == VEGA_USE_H || i->category == VEGA_USE_HVM || i->category == VEGA_USE_IS) && + !(i->gprops & LIGATED); +} + +#define FLAG64_UNSAFE(x) ((x) < 64 ? (uint64_t)1 << (x) : 0) +#define USE_POST_BASE \ + (FLAG64_UNSAFE(VEGA_USE_FABV) | FLAG64_UNSAFE(VEGA_USE_FBLW) | FLAG64_UNSAFE(VEGA_USE_FPST) | \ + FLAG64_UNSAFE(VEGA_USE_FMABV) | FLAG64_UNSAFE(VEGA_USE_FMBLW) | FLAG64_UNSAFE(VEGA_USE_FMPST) | \ + FLAG64_UNSAFE(VEGA_USE_MABV) | FLAG64_UNSAFE(VEGA_USE_MBLW) | FLAG64_UNSAFE(VEGA_USE_MPST) | \ + FLAG64_UNSAFE(VEGA_USE_MPRE) | FLAG64_UNSAFE(VEGA_USE_VABV) | FLAG64_UNSAFE(VEGA_USE_VBLW) | \ + FLAG64_UNSAFE(VEGA_USE_VPST) | FLAG64_UNSAFE(VEGA_USE_VPRE) | FLAG64_UNSAFE(VEGA_USE_VMABV) | \ + FLAG64_UNSAFE(VEGA_USE_VMBLW) | FLAG64_UNSAFE(VEGA_USE_VMPST) | FLAG64_UNSAFE(VEGA_USE_VMPRE)) + +static void use_reorder_syllable(VegaShaper *b, size_t start, size_t end) { + unsigned type = b->info[start].syllable & 0x0F; + if (!(FLAG_UNSAFE(type) & (FLAG(USE_VIRAMA_TERMINATED) | FLAG(USE_SAKOT_TERMINATED) | FLAG(USE_STANDARD) | + FLAG(USE_SYMBOL) | FLAG(USE_BROKEN)))) + return; + Info *info = b->info; + /* A repha forward, before the first post-base glyph (or to the end). */ + if (info[start].category == VEGA_USE_R && end - start > 1) + for (size_t i = start + 1; i < end; ++i) { + bool post_base = (FLAG64_UNSAFE(info[i].category) & USE_POST_BASE) || is_halant_use(&info[i]); + if (post_base || i == end - 1) { + if (post_base) i--; + merge_clusters(b, start, i + 1); + Info t = info[start]; + memmove(&info[start], &info[start + 1], (i - start) * sizeof(Info)); + info[i] = t; + break; + } + } + /* Pre-base vowels back, to the start or past the last halant (only a + * multiple substitution's first component). */ + size_t j = start; + for (size_t i = start; i < end; ++i) { + uint32_t flag = FLAG_UNSAFE(info[i].category); + if (is_halant_use(&info[i])) + j = i + 1; + else if ((flag & (FLAG(VEGA_USE_VPRE) | FLAG(VEGA_USE_VMPRE))) && !lig_comp(&info[i]) && j < i) { + merge_clusters(b, j, i + 1); + Info t = info[i]; + memmove(&info[j + 1], &info[j], (i - j) * sizeof(Info)); + info[j] = t; + } + } +} + +static bool use_reorder(const VegaShaping *s, VegaShaper *b) { + bool changed = insert_dotted_circles(s, b, USE_BROKEN, VEGA_USE_B, VEGA_USE_R, -1); + for (size_t start = 0, end; start < b->len; start = end) { + end = next_syllable(b, start); + use_reorder_syllable(b, start, end); + } + return changed; +} + /* The shaper's part of the work at a pause in GSUB; whether it changed the * buffer. */ static bool shaper_pause(const VegaShaping *s, const Plan *plan, VegaShaper *b, unsigned pause) { @@ -3344,6 +3529,16 @@ static bool shaper_pause(const VegaShaping *s, const Plan *plan, VegaShaper *b, case VEGA_SHAPER_MYANMAR: if (pause == VEGA_PAUSE_SYLLABLES) find_syllables(b, &vega_myanmar_machine); return pause == VEGA_PAUSE_INITIAL_REORDERING && myanmar_reorder(s, b); + case VEGA_SHAPER_USE: + switch (pause) { + case VEGA_PAUSE_SYLLABLES: use_setup_syllables(plan, b); return false; + case VEGA_PAUSE_CLEAR_SUBSTITUTED: + for (size_t i = 0; i < b->len; ++i) b->info[i].gprops &= (uint16_t)~SUBSTITUTED; + return false; + case VEGA_PAUSE_RECORD_RPHF: case VEGA_PAUSE_RECORD_PREF: use_record(plan, b, pause); return false; + case VEGA_PAUSE_INITIAL_REORDERING: return use_reorder(s, b); + default: return false; + } default: return false; } } @@ -3423,8 +3618,8 @@ static void position(const VegaShaping *s, const Plan *plan, VegaShaper *b) { for (size_t i = 0; i < b->len; ++i) b->pos[i].x_advance = advance_of(s, b->info[i].codepoint); if (b->scratch & HAS_SPACE_FALLBACK) fallback_spaces(s, b); bool adjust = (plan->flags & VEGA_PLAN_ADJUST_ZEROING) && b->direction == VEGA_SHAPE_LTR; - /* Marks' advances go by GDEF: before GPOS (Myanmar's shaper) or after. */ - bool early = plan->shaper == VEGA_SHAPER_MYANMAR; + /* Marks' advances go by GDEF: before GPOS (Myanmar's shaper and USE) or after. */ + bool early = plan->shaper == VEGA_SHAPER_MYANMAR || plan->shaper == VEGA_SHAPER_USE; if ((plan->flags & VEGA_PLAN_ZERO_MARKS) && early) zero_mark_widths(b, adjust); if (plan->flags & VEGA_PLAN_GPOS) apply_table(s, plan, b, 1); if (plan->flags & VEGA_PLAN_KERN) kern_table(s, b, plan); @@ -3460,7 +3655,7 @@ long vega_shape(VegaShaper *b, const VegaShaping *s, const uint32_t *codes, size form_clusters(b); ensure_native_direction(b, &plan); if (plan.shaper == VEGA_SHAPER_HANGUL) preprocess_hangul(s, b); - if (plan.shaper == VEGA_SHAPER_INDIC) preprocess_vowel_constraints(&plan, b); + if (plan.shaper == VEGA_SHAPER_INDIC || plan.shaper == VEGA_SHAPER_USE) preprocess_vowel_constraints(&plan, b); /* Mirror what the font mirrors; mark the rest for rtlm. */ if (direction == VEGA_SHAPE_RTL) @@ -3474,6 +3669,7 @@ long vega_shape(VegaShaper *b, const VegaShaping *s, const uint32_t *codes, size if (plan.shaper == VEGA_SHAPER_ARABIC) setup_masks_arabic(b, &plan); if (plan.shaper == VEGA_SHAPER_INDIC) setup_masks_indic(b); if (plan.shaper == VEGA_SHAPER_KHMER || plan.shaper == VEGA_SHAPER_MYANMAR) setup_masks_category(b); + if (plan.shaper == VEGA_SHAPER_USE) setup_masks_use(b, &plan); if (plan.shaper == VEGA_SHAPER_HANGUL) for (size_t i = 0; i < b->len; ++i) if (b->info[i].action >= LJMO && b->info[i].action <= TJMO) diff --git a/text/shape.h b/text/shape.h index 7f02729..bd38d96 100644 --- a/text/shape.h +++ b/text/shape.h @@ -6,8 +6,8 @@ /* Shaping (docs/design/004-text.md): a run of characters (one script, one * direction) to glyphs and their positions, as HarfBuzz 10 shapes it with - * its default, Arabic, Hebrew, Hangul, Indic, Khmer and Myanmar shapers, - * glyph for glyph and unit for unit. + * its default, Arabic, Hebrew, Hangul, Indic, Khmer, Myanmar and Universal + * (USE) shapers, glyph for glyph and unit for unit. * * What a font's shaping needs travels in a symbol file (its shaping * section), written by the build tool: @@ -48,7 +48,7 @@ enum { VEGA_SHAPING_HEADER = 80, VEGA_PLAN_BYTES = 144, VEGA_STEP_BYTES = 8, VEG VEGA_PLAN_STAGES = 5 }; enum { VEGA_SHAPE_LTR = 1, VEGA_SHAPE_RTL = 2 }; enum { VEGA_SHAPER_DEFAULT, VEGA_SHAPER_ARABIC, VEGA_SHAPER_HEBREW, VEGA_SHAPER_HANGUL, VEGA_SHAPER_INDIC, - VEGA_SHAPER_KHMER, VEGA_SHAPER_MYANMAR }; + VEGA_SHAPER_KHMER, VEGA_SHAPER_MYANMAR, VEGA_SHAPER_USE }; /* Plan flags: GPOS runs; mark advances are zeroed after it (by GDEF); glyph * classes come from Unicode (the font has none); the font positions marks * (a 'mark' feature); automatic fractions; the kern table kerns; marks are @@ -66,6 +66,7 @@ enum { VEGA_MASK_RPHF = VEGA_MASK_SHAPER, VEGA_MASK_PREF, VEGA_MASK_BLWF, VEGA_M VEGA_MASK_PSTF, VEGA_MASK_INDIC_INIT }; /* Indic */ enum { VEGA_MASK_KHMER_PREF = VEGA_MASK_SHAPER, VEGA_MASK_KHMER_BLWF, VEGA_MASK_KHMER_ABVF, VEGA_MASK_KHMER_PSTF, VEGA_MASK_KHMER_CFAR }; /* Khmer */ +enum { VEGA_MASK_USE_RPHF = VEGA_MASK_INIT + 1 }; /* USE: that, and Arabic's for its joining forms */ /* The stages a plan names: Indic's, whose features decide a consonant's * position by whether they would substitute it. */ enum { VEGA_STAGE_RPHF, VEGA_STAGE_PREF, VEGA_STAGE_BLWF, VEGA_STAGE_PSTF, VEGA_STAGE_VATU }; @@ -75,7 +76,8 @@ enum { VEGA_INDIC_OLD_SPEC = 1 }; /* Step flags; pauses, which the shaper tells apart. */ enum { VEGA_STEP_AUTO_ZWNJ = 1, VEGA_STEP_AUTO_ZWJ = 2, VEGA_STEP_RANDOM = 4, VEGA_STEP_PER_SYLLABLE = 8 }; enum { VEGA_STEP_PAUSE = 0xFFFF }; -enum { VEGA_PAUSE_SYLLABLES = 1, VEGA_PAUSE_INITIAL_REORDERING, VEGA_PAUSE_FINAL_REORDERING, VEGA_PAUSE_CLEAR_SYLLABLES }; +enum { VEGA_PAUSE_SYLLABLES = 1, VEGA_PAUSE_INITIAL_REORDERING, VEGA_PAUSE_FINAL_REORDERING, VEGA_PAUSE_CLEAR_SYLLABLES, + VEGA_PAUSE_CLEAR_SUBSTITUTED, VEGA_PAUSE_RECORD_RPHF, VEGA_PAUSE_RECORD_PREF }; typedef struct { const unsigned char *p; uint32_t size; } VegaTable; /* Which glyphs may be in a set, as three 64-bit patterns of glyph bits diff --git a/text/syllabic-data.c b/text/syllabic-data.c index 3b3e6ff..cfff1b5 100644 --- a/text/syllabic-data.c +++ b/text/syllabic-data.c @@ -179,6 +179,383 @@ uint16_t vega_indic_categories(uint32_t u) { return 0x0E00; } +/* Each character's USE category (hb-ot-shaper-use-table.hh, Unicode 16): HarfBuzz's arrays and + * lookup. */ +static const uint8_t use_u8[3345] = { + 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 57, 58, 59, 195, 211, 62, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 15, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2, + 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17, + 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2, + 2, 34, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 2, 2, 2, + 37, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 38, 2, 39, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 40, 41, 42, 43, 44, 45, 2, 46, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 48, 2, + 49, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 51, 2, 2, 2, + 2, 2, 2, 2, 2, 52, 53, 2, 54, 2, 2, 55, 56, 2, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 2, 70, 71, 72, 73, + 2, 74, 2, 75, 76, 77, 78, 2, 2, 79, 80, 81, 82, 2, 83, 84, + 2, 85, 85, 85, 85, 85, 85, 85, 85, 86, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 87, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 88, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 89, 90, 2, 2, 2, 91, 2, 2, 2, 92, + 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 94, 94, 94, 95, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 97, 2, 2, 2, 2, 2, + 2, 2, 2, 98, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 99, 2, 2, 100, 2, 2, 2, 101, 2, 102, 2, 2, 2, + 2, 2, 2, 103, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 104, 104, 105, 106, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, + 0, 5, 0, 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 11, + 11, 11, 11, 0, 0, 0, 9, 12, 0, 2, 2, 2, 2, 13, 14, 0, + 0, 11, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 16, 17, + 18, 19, 20, 21, 22, 16, 23, 24, 25, 12, 26, 27, 20, 2, 2, 2, + 2, 2, 20, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, + 2, 28, 29, 30, 2, 2, 2, 9, 30, 9, 30, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 9, 0, 2, 2, 0, 17, + 18, 19, 20, 31, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 2, + 30, 2, 0, 0, 0, 0, 0, 9, 36, 12, 15, 30, 2, 2, 9, 0, + 30, 9, 2, 30, 9, 2, 0, 37, 18, 19, 31, 0, 27, 38, 27, 39, + 0, 40, 0, 0, 0, 30, 2, 9, 9, 0, 0, 0, 2, 2, 2, 2, + 2, 41, 42, 43, 0, 0, 0, 0, 0, 12, 15, 30, 2, 2, 2, 2, + 30, 2, 30, 2, 2, 2, 2, 2, 2, 9, 2, 30, 2, 2, 0, 17, + 18, 19, 20, 21, 27, 22, 35, 24, 0, 0, 0, 0, 0, 30, 41, 41, + 44, 12, 29, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 0, 17, + 45, 0, 0, 27, 22, 0, 0, 2, 30, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 46, 30, 2, 2, 9, 0, 2, 9, 2, 2, 0, 30, 9, 9, + 2, 0, 30, 9, 0, 2, 9, 0, 2, 2, 2, 2, 2, 2, 0, 0, + 23, 16, 47, 0, 48, 33, 48, 34, 0, 0, 0, 0, 35, 0, 0, 0, + 0, 15, 29, 49, 2, 2, 2, 9, 2, 9, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 0, 17, 22, 16, 23, 47, 22, 38, 22, 39, + 0, 0, 0, 27, 31, 2, 9, 0, 0, 10, 29, 30, 2, 2, 2, 9, + 2, 2, 2, 30, 2, 2, 0, 17, 45, 0, 0, 35, 47, 0, 0, 0, + 9, 50, 51, 0, 0, 0, 0, 0, 0, 11, 29, 2, 2, 2, 2, 9, + 2, 2, 2, 2, 2, 2, 52, 53, 23, 19, 20, 31, 48, 33, 48, 34, + 54, 0, 0, 0, 35, 0, 0, 0, 30, 12, 29, 30, 2, 2, 2, 2, + 2, 2, 2, 2, 9, 0, 2, 2, 2, 2, 30, 2, 2, 2, 2, 30, + 0, 2, 2, 2, 9, 0, 55, 0, 35, 23, 22, 31, 31, 18, 48, 48, + 25, 0, 23, 0, 0, 0, 0, 0, 0, 2, 0, 2, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 2, 56, 56, 57, 0, 0, + 18, 2, 2, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, + 0, 58, 21, 59, 22, 22, 20, 20, 46, 21, 11, 31, 11, 2, 2, 60, + 61, 61, 61, 61, 61, 62, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 63, 0, 0, 0, 0, 64, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 65, 45, 59, 66, 22, 22, 67, 68, 69, 70, + 71, 2, 2, 2, 2, 2, 1, 0, 5, 2, 2, 2, 23, 20, 2, 2, + 72, 71, 73, 74, 65, 73, 29, 29, 2, 52, 22, 53, 2, 2, 2, 2, + 2, 2, 75, 76, 77, 29, 29, 78, 79, 2, 2, 2, 2, 2, 29, 45, + 0, 2, 59, 80, 0, 0, 0, 0, 30, 2, 59, 47, 0, 0, 0, 0, + 0, 2, 59, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 9, + 2, 9, 59, 0, 0, 0, 0, 0, 0, 2, 2, 81, 45, 22, 59, 20, + 48, 48, 48, 48, 15, 82, 83, 84, 85, 86, 87, 0, 0, 0, 0, 88, + 0, 9, 0, 0, 30, 0, 89, 81, 90, 2, 2, 2, 2, 9, 0, 0, + 0, 42, 42, 91, 92, 2, 2, 2, 2, 2, 2, 2, 2, 13, 9, 0, + 0, 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 9, 22, 80, 45, 22, 94, 61, 0, 0, 95, 96, 95, 95, 97, 98, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 9, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 29, 0, 0, + 0, 2, 2, 2, 2, 2, 9, 0, 0, 2, 2, 2, 52, 99, 45, 0, + 0, 2, 2, 100, 101, 102, 103, 61, 63, 104, 16, 45, 22, 59, 21, 80, + 48, 48, 76, 11, 11, 11, 105, 46, 40, 11, 106, 74, 2, 2, 2, 2, + 2, 2, 2, 107, 22, 20, 20, 22, 48, 48, 22, 108, 2, 2, 2, 9, + 0, 0, 0, 0, 0, 0, 109, 110, 110, 110, 110, 0, 0, 0, 0, 0, + 0, 106, 74, 2, 2, 2, 2, 2, 2, 60, 61, 59, 25, 22, 111, 61, + 2, 2, 2, 2, 107, 22, 23, 45, 45, 102, 112, 0, 0, 0, 0, 0, + 0, 2, 2, 61, 18, 48, 23, 113, 102, 102, 102, 114, 115, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 0, 30, 2, 11, 46, 116, 116, 116, 11, 116, + 116, 15, 116, 116, 116, 26, 0, 40, 0, 0, 0, 117, 51, 11, 5, 0, + 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 6, 119, + 120, 42, 42, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 120, + 121, 120, 120, 120, 120, 120, 120, 120, 120, 0, 0, 122, 0, 0, 0, 0, + 0, 0, 7, 122, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 123, 123, 0, 0, + 0, 2, 2, 2, 2, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, + 124, 0, 123, 123, 0, 0, 0, 0, 0, 2, 53, 2, 108, 2, 10, 2, + 2, 2, 65, 19, 16, 0, 0, 31, 0, 2, 2, 0, 0, 0, 0, 0, + 0, 29, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 23, 23, 23, 23, + 23, 23, 23, 126, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 2, 0, 0, 0, 0, 0, 52, 2, 2, 2, 22, 22, 127, 116, + 0, 2, 2, 2, 128, 20, 59, 20, 113, 102, 129, 0, 0, 0, 0, 0, + 0, 11, 130, 2, 2, 2, 2, 2, 2, 2, 131, 23, 22, 20, 48, 132, + 133, 134, 0, 0, 0, 0, 0, 0, 0, 2, 2, 52, 30, 2, 2, 2, + 2, 2, 2, 2, 2, 10, 22, 59, 99, 76, 135, 136, 137, 0, 0, 0, + 0, 2, 138, 2, 2, 2, 2, 139, 0, 30, 2, 42, 5, 0, 79, 15, + 2, 53, 22, 140, 52, 53, 2, 2, 105, 10, 9, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 141, 21, 25, 0, 0, 142, 143, 0, 0, 0, + 0, 2, 65, 45, 23, 80, 47, 144, 0, 81, 81, 81, 81, 81, 81, 81, + 81, 0, 0, 0, 0, 0, 0, 0, 6, 120, 120, 120, 120, 121, 0, 0, + 0, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 30, 2, 2, 2, + 2, 2, 30, 2, 2, 2, 30, 9, 0, 128, 20, 27, 31, 0, 0, 145, + 146, 2, 2, 30, 2, 30, 2, 2, 2, 2, 2, 2, 0, 14, 37, 0, + 147, 2, 2, 13, 37, 0, 30, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 2, 2, 9, 2, 2, 11, 41, 0, 0, 0, + 0, 2, 2, 2, 0, 27, 22, 22, 30, 2, 2, 2, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 27, 38, 0, 2, 2, 2, 116, 116, 116, 116, + 116, 148, 2, 9, 0, 0, 0, 0, 0, 2, 14, 14, 0, 0, 0, 0, + 0, 9, 2, 2, 9, 2, 2, 2, 2, 30, 2, 9, 0, 30, 2, 0, + 0, 149, 150, 151, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 20, + 20, 20, 22, 22, 134, 0, 0, 0, 0, 0, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 2, 2, 2, 2, 2, 53, 52, 53, 0, 0, 0, 0, + 153, 11, 74, 2, 2, 2, 2, 2, 2, 18, 19, 21, 16, 24, 37, 0, + 0, 0, 31, 0, 0, 0, 0, 0, 0, 11, 49, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 128, 20, 22, 154, 22, 21, 155, 156, 2, 2, 2, 2, + 2, 0, 0, 65, 157, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 0, + 0, 2, 65, 25, 20, 20, 20, 22, 22, 108, 158, 0, 0, 56, 159, 31, + 160, 30, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, + 19, 22, 22, 161, 44, 0, 0, 0, 49, 128, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 9, 9, 2, 2, 30, 2, 2, 2, 2, 2, 2, 2, + 30, 2, 2, 2, 2, 2, 2, 2, 10, 18, 19, 21, 22, 162, 31, 0, + 0, 11, 11, 30, 2, 2, 2, 9, 30, 9, 2, 30, 2, 2, 58, 17, + 23, 16, 23, 47, 32, 33, 32, 34, 0, 0, 0, 0, 35, 0, 0, 0, + 2, 2, 23, 0, 11, 11, 11, 46, 0, 11, 11, 46, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 30, 0, 9, 2, 2, 2, 30, 45, 59, 20, + 20, 31, 33, 32, 32, 25, 163, 29, 164, 165, 37, 0, 0, 0, 0, 0, + 0, 12, 26, 0, 0, 0, 0, 0, 0, 2, 2, 65, 25, 20, 20, 20, + 22, 23, 126, 15, 17, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, + 166, 167, 0, 0, 0, 0, 0, 0, 0, 18, 19, 20, 20, 66, 99, 25, + 160, 11, 168, 9, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, + 65, 25, 20, 20, 0, 48, 48, 11, 169, 37, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 20, 0, 23, 19, 20, 20, 21, 16, 82, + 169, 38, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 10, 170, + 25, 20, 22, 22, 168, 9, 0, 0, 0, 2, 2, 2, 2, 2, 9, 43, + 136, 23, 22, 20, 76, 21, 22, 0, 0, 2, 2, 2, 9, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 18, 19, 20, 21, 22, 105, 169, 37, 0, + 0, 2, 2, 2, 9, 30, 0, 2, 2, 2, 2, 30, 9, 2, 2, 2, + 2, 23, 23, 18, 32, 33, 12, 171, 165, 172, 173, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 0, 2, 2, 2, 65, 25, 20, 20, 0, 22, 23, + 29, 108, 0, 33, 0, 0, 0, 0, 0, 52, 20, 22, 22, 22, 140, 2, + 2, 2, 174, 175, 11, 15, 176, 61, 177, 0, 0, 1, 147, 0, 0, 0, + 0, 52, 20, 22, 16, 19, 20, 2, 2, 2, 2, 158, 158, 158, 178, 178, + 178, 178, 178, 178, 15, 179, 0, 30, 0, 22, 20, 20, 31, 22, 22, 11, + 169, 0, 61, 61, 61, 61, 61, 61, 61, 66, 21, 82, 46, 0, 0, 0, + 0, 2, 2, 2, 9, 2, 30, 2, 2, 52, 22, 22, 31, 0, 38, 22, + 27, 11, 159, 180, 181, 0, 0, 0, 0, 2, 2, 2, 30, 9, 2, 2, + 2, 2, 2, 2, 2, 2, 23, 23, 47, 22, 35, 82, 68, 0, 0, 0, + 0, 2, 182, 66, 47, 0, 0, 0, 0, 11, 183, 2, 2, 2, 2, 2, + 2, 2, 2, 23, 22, 20, 31, 0, 48, 16, 143, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 156, 0, 0, 184, 184, 184, 184, 184, 184, 184, + 184, 185, 185, 185, 186, 187, 185, 184, 184, 188, 184, 184, 189, 190, 190, 190, + 190, 190, 190, 190, 0, 0, 0, 0, 0, 184, 184, 184, 184, 184, 191, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 192, 193, + 194, 11, 11, 11, 46, 0, 0, 0, 0, 29, 74, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 65, 47, 0, 2, 2, 2, 2, 2, 9, 0, + 58, 195, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 0, 0, 0, 40, 116, 26, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 30, 2, 2, 2, 2, 2, 0, 58, 37, 0, 6, 120, 120, 120, 121, 0, + 0, 11, 11, 11, 49, 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 46, 2, 2, 2, 2, 2, 2, 11, + 11, 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, + 20, 2, 2, 44, 44, 44, 92, 0, 0, 0, 0, 0, 5, 1, 1, 0, + 51, 0, 52, 5, 0, 0, 16, 47, 47, 0, 6, 1, 0, 1, 37, 37, + 37, 0, 37, 1, 32, 32, 32, 37, 39, 33, 35, 32, 1, 35, 22, 35, + 34, 34, 34, 34, 33, 33, 33, 35, 35, 35, 12, 22, 35, 38, 0, 0, + 33, 5, 37, 39, 39, 0, 1, 34, 0, 0, 22, 22, 0, 22, 12, 0, + 35, 45, 0, 32, 0, 33, 0, 33, 12, 0, 38, 37, 31, 5, 5, 0, + 28, 31, 31, 35, 33, 37, 0, 35, 0, 22, 22, 37, 1, 0, 43, 43, + 39, 1, 33, 33, 1, 18, 0, 53, 0, 0, 46, 0, 31, 0, 32, 33, + 34, 1, 11, 11, 11, 0, 11, 11, 0, 46, 0, 1, 35, 34, 22, 37, + 38, 39, 44, 33, 29, 30, 28, 28, 1, 28, 28, 35, 39, 39, 1, 28, + 35, 22, 33, 33, 39, 39, 38, 1, 39, 34, 35, 6, 6, 35, 37, 37, + 45, 24, 31, 45, 37, 45, 33, 44, 45, 1, 45, 1, 6, 16, 6, 5, + 31, 31, 1, 5, 1, 33, 11, 26, 26, 38, 26, 26, 25, 37, 46, 33, + 22, 1, 30, 28, 11, 24, 24, 27, 11, 48, 35, 33, 37, 37, 24, 31, + 35, 12, 1, 0, 41, 41, 41, 35, 44, 56, 56, 34, 24, 23, 23, 45, + 32, 38, 38, 37, 43, 0, 45, 14, 6, 16, 16, 16, 0, 47, 0, 51, + 52, 0, 12, 29, 35, 12, 37, 33, 38, 1, 34, 26, 35, 24, 39, 1, + 31, 33, 28, 29, 28, 12, 0, 34, 29, 30, 27, 28, 0, 1, 24, 24, + 26, 34, 1, 1, 22, 0, 39, 44, 0, 39, 34, 35, 38, 38, 37, 0, + 44, 38, 1, 39, 37, 39, 43, 43, 1, 4, 4, 0, 13, 22, 34, 33, + 44, 31, 0, 35, 1, 18, 18, 32, 33, 22, 37, 37, 12, 33, 32, 39, + 0, 37, 32, 44, 18, 45, 1, 43, 43, 12, 32, 39, 12, 39, 33, 37, + 35, 29, 18, 29, 32, 1, 46, 34, 37, 43, 11, 11, 5, 25, 25, 31, + 44, 34, 44, 18, 28, 5, 33, 18, 39, 49, 49, 50, 50, 50, 51, 52, + 50, 55, 49, 49, 54, 54, 54, 49, 0, 30, 30, 29, 37, 28, 34, 0, + 34, +}; +static const uint16_t use_u16[856] = { + 0, 0, 1, 2, 0, 3, 0, 3, 0, 0, 4, 5, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 12, + 0, 0, 0, 0, 10, 13, 0, 0, 14, 10, 10, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 18, 26, 27, 21, 22, 28, 29, 30, 31, 32, + 33, 34, 22, 35, 36, 0, 18, 37, 38, 21, 22, 39, 24, 40, 18, 41, + 42, 43, 44, 45, 46, 47, 31, 0, 48, 49, 22, 50, 51, 52, 18, 0, + 53, 49, 22, 54, 51, 55, 18, 56, 57, 49, 10, 58, 59, 60, 18, 0, + 61, 62, 10, 63, 64, 65, 31, 66, 67, 68, 10, 69, 70, 10, 71, 72, + 73, 74, 75, 76, 77, 0, 0, 0, 10, 10, 78, 79, 80, 81, 82, 83, + 84, 85, 0, 0, 0, 0, 0, 0, 10, 86, 10, 87, 10, 88, 89, 90, + 10, 10, 10, 91, 92, 93, 2, 0, 94, 0, 10, 10, 10, 10, 10, 95, + 96, 10, 97, 0, 0, 0, 0, 0, 98, 99, 100, 101, 31, 10, 102, 103, + 10, 10, 104, 10, 105, 106, 0, 0, 10, 107, 10, 10, 10, 108, 109, 110, + 2, 2, 0, 0, 0, 0, 0, 0, 111, 10, 10, 112, 113, 2, 114, 115, + 116, 10, 117, 10, 10, 10, 118, 119, 10, 10, 120, 121, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 126, + 127, 128, 129, 0, 0, 0, 130, 131, 132, 0, 0, 0, 0, 0, 0, 133, + 0, 0, 0, 0, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, + 0, 0, 0, 10, 10, 10, 136, 137, 0, 0, 138, 0, 0, 0, 0, 0, + 139, 10, 140, 0, 10, 10, 10, 141, 142, 10, 10, 143, 144, 2, 145, 146, + 10, 10, 147, 10, 148, 149, 0, 0, 150, 10, 10, 151, 152, 2, 153, 99, + 10, 10, 154, 155, 156, 2, 10, 157, 10, 10, 10, 158, 159, 0, 160, 161, + 0, 0, 0, 0, 10, 10, 162, 2, 163, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 0, 165, + 0, 0, 0, 0, 0, 0, 0, 166, 166, 167, 34, 168, 0, 0, 0, 0, + 169, 170, 10, 171, 95, 0, 0, 0, 0, 0, 0, 0, 70, 10, 172, 0, + 10, 173, 174, 0, 0, 0, 0, 0, 10, 10, 175, 2, 9, 10, 176, 10, + 177, 0, 0, 0, 0, 0, 0, 0, 10, 10, 178, 173, 0, 0, 0, 0, + 0, 0, 0, 10, 179, 180, 0, 10, 181, 0, 0, 182, 183, 0, 0, 0, + 184, 10, 10, 185, 186, 187, 188, 189, 190, 10, 10, 191, 192, 0, 0, 0, + 193, 10, 194, 195, 196, 10, 10, 197, 190, 10, 10, 198, 199, 106, 200, 103, + 10, 34, 201, 202, 203, 0, 0, 0, 204, 205, 95, 10, 10, 206, 207, 2, + 208, 21, 22, 209, 210, 211, 212, 213, 214, 10, 10, 215, 216, 217, 218, 0, + 10, 10, 10, 219, 220, 221, 222, 0, 200, 10, 10, 223, 224, 2, 0, 0, + 10, 10, 225, 226, 227, 228, 0, 0, 10, 10, 10, 229, 230, 2, 0, 0, + 10, 10, 231, 232, 2, 10, 141, 0, 10, 233, 234, 104, 235, 0, 0, 0, + 10, 10, 236, 237, 0, 0, 0, 0, 238, 239, 10, 240, 241, 2, 0, 0, + 0, 0, 242, 10, 10, 243, 244, 0, 245, 10, 10, 246, 247, 248, 10, 10, + 249, 250, 0, 0, 0, 0, 0, 0, 22, 10, 225, 251, 8, 10, 71, 19, + 10, 252, 74, 253, 0, 0, 0, 0, 254, 10, 10, 255, 256, 2, 257, 10, + 258, 259, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 260, + 261, 49, 10, 262, 263, 264, 0, 0, 265, 265, 265, 265, 265, 265, 265, 265, + 265, 265, 265, 266, 267, 268, 265, 265, 265, 265, 265, 265, 265, 265, 265, 269, + 10, 270, 271, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 10, 10, 10, 272, 0, 0, 0, 0, 0, 0, 0, 0, 273, 10, 274, 2, + 10, 10, 10, 10, 275, 276, 277, 277, 278, 279, 0, 0, 0, 0, 280, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 177, 0, 281, + 10, 10, 10, 10, 10, 10, 106, 71, 95, 282, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 283, 10, 10, 71, 284, 285, 0, 0, 0, + 0, 10, 286, 0, 10, 10, 287, 2, 0, 0, 0, 0, 0, 10, 288, 2, + 0, 0, 0, 0, 0, 10, 289, 106, 10, 10, 10, 10, 290, 2, 0, 0, + 130, 130, 130, 130, 130, 130, 130, 130, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 130, +}; +static unsigned use_b4(const uint8_t *a, unsigned i) { return (a[i >> 1] >> ((i & 1u) << 2)) & 15u; } +uint8_t vega_use_category(uint32_t u) { return (uint8_t)(u<921600u?use_u8[2953+(((use_u8[625+(((use_u16[((use_u8[113+(((use_b4(use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:0); } + +/* The categories syllabic.h names are the machines' own. */ +_Static_assert(VEGA_OT_A == 9, "indic A"); +_Static_assert(VEGA_OT_C == 1, "indic C"); +_Static_assert(VEGA_OT_CM == 16, "indic CM"); +_Static_assert(VEGA_OT_CS == 18, "indic CS"); +_Static_assert(VEGA_OT_DOTTEDCIRCLE == 11, "indic DOTTEDCIRCLE"); +_Static_assert(VEGA_OT_H == 4, "indic H"); +_Static_assert(VEGA_OT_M == 7, "indic M"); +_Static_assert(VEGA_OT_MPST == 13, "indic MPst"); +_Static_assert(VEGA_OT_N == 3, "indic N"); +_Static_assert(VEGA_OT_PLACEHOLDER == 10, "indic PLACEHOLDER"); +_Static_assert(VEGA_OT_RS == 12, "indic RS"); +_Static_assert(VEGA_OT_RA == 15, "indic Ra"); +_Static_assert(VEGA_OT_REPHA == 14, "indic Repha"); +_Static_assert(VEGA_OT_SM == 8, "indic SM"); +_Static_assert(VEGA_OT_SMPST == 57, "indic SMPst"); +_Static_assert(VEGA_OT_SYMBOL == 17, "indic Symbol"); +_Static_assert(VEGA_OT_V == 2, "indic V"); +_Static_assert(VEGA_OT_VD == 9, "indic VD"); +_Static_assert(VEGA_OT_X == 0, "indic X"); +_Static_assert(VEGA_OT_ZWJ == 6, "indic ZWJ"); +_Static_assert(VEGA_OT_ZWNJ == 5, "indic ZWNJ"); +_Static_assert(VEGA_OT_C == 1, "khmer C"); +_Static_assert(VEGA_OT_DOTTEDCIRCLE == 11, "khmer DOTTEDCIRCLE"); +_Static_assert(VEGA_OT_H == 4, "khmer H"); +_Static_assert(VEGA_OT_PLACEHOLDER == 10, "khmer PLACEHOLDER"); +_Static_assert(VEGA_OT_RA == 15, "khmer Ra"); +_Static_assert(VEGA_OT_ROBATIC == 25, "khmer Robatic"); +_Static_assert(VEGA_OT_V == 2, "khmer V"); +_Static_assert(VEGA_OT_VABV == 20, "khmer VAbv"); +_Static_assert(VEGA_OT_VBLW == 21, "khmer VBlw"); +_Static_assert(VEGA_OT_VPRE == 22, "khmer VPre"); +_Static_assert(VEGA_OT_VPST == 23, "khmer VPst"); +_Static_assert(VEGA_OT_XGROUP == 26, "khmer Xgroup"); +_Static_assert(VEGA_OT_YGROUP == 27, "khmer Ygroup"); +_Static_assert(VEGA_OT_ZWJ == 6, "khmer ZWJ"); +_Static_assert(VEGA_OT_ZWNJ == 5, "khmer ZWNJ"); +_Static_assert(VEGA_OT_A == 9, "myanmar A"); +_Static_assert(VEGA_OT_AS == 32, "myanmar As"); +_Static_assert(VEGA_OT_C == 1, "myanmar C"); +_Static_assert(VEGA_OT_CS == 18, "myanmar CS"); +_Static_assert(VEGA_OT_DOTTEDCIRCLE == 11, "myanmar DOTTEDCIRCLE"); +_Static_assert(VEGA_OT_H == 4, "myanmar H"); +_Static_assert(VEGA_OT_MH == 35, "myanmar MH"); +_Static_assert(VEGA_OT_ML == 41, "myanmar ML"); +_Static_assert(VEGA_OT_MR == 36, "myanmar MR"); +_Static_assert(VEGA_OT_MW == 37, "myanmar MW"); +_Static_assert(VEGA_OT_MY == 38, "myanmar MY"); +_Static_assert(VEGA_OT_PT == 39, "myanmar PT"); +_Static_assert(VEGA_OT_RA == 15, "myanmar Ra"); +_Static_assert(VEGA_OT_SM == 8, "myanmar SM"); +_Static_assert(VEGA_OT_SMPST == 57, "myanmar SMPst"); +_Static_assert(VEGA_OT_VABV == 20, "myanmar VAbv"); +_Static_assert(VEGA_OT_VBLW == 21, "myanmar VBlw"); +_Static_assert(VEGA_OT_VPRE == 22, "myanmar VPre"); +_Static_assert(VEGA_OT_VPST == 23, "myanmar VPst"); +_Static_assert(VEGA_OT_VS == 40, "myanmar VS"); +_Static_assert(VEGA_OT_ZWJ == 6, "myanmar ZWJ"); +_Static_assert(VEGA_OT_ZWNJ == 5, "myanmar ZWNJ"); +_Static_assert(VEGA_USE_B == 1, "use B"); +_Static_assert(VEGA_USE_CGJ == 6, "use CGJ"); +_Static_assert(VEGA_USE_CMABV == 31, "use CMAbv"); +_Static_assert(VEGA_USE_CMBLW == 32, "use CMBlw"); +_Static_assert(VEGA_USE_CS == 43, "use CS"); +_Static_assert(VEGA_USE_FABV == 24, "use FAbv"); +_Static_assert(VEGA_USE_FBLW == 25, "use FBlw"); +_Static_assert(VEGA_USE_FMABV == 45, "use FMAbv"); +_Static_assert(VEGA_USE_FMBLW == 46, "use FMBlw"); +_Static_assert(VEGA_USE_FMPST == 47, "use FMPst"); +_Static_assert(VEGA_USE_FPST == 26, "use FPst"); +_Static_assert(VEGA_USE_G == 49, "use G"); +_Static_assert(VEGA_USE_GB == 5, "use GB"); +_Static_assert(VEGA_USE_H == 12, "use H"); +_Static_assert(VEGA_USE_HM == 54, "use HM"); +_Static_assert(VEGA_USE_HN == 13, "use HN"); +_Static_assert(VEGA_USE_HR == 55, "use HR"); +_Static_assert(VEGA_USE_HVM == 53, "use HVM"); +_Static_assert(VEGA_USE_IS == 44, "use IS"); +_Static_assert(VEGA_USE_J == 50, "use J"); +_Static_assert(VEGA_USE_MABV == 27, "use MAbv"); +_Static_assert(VEGA_USE_MBLW == 28, "use MBlw"); +_Static_assert(VEGA_USE_MPRE == 30, "use MPre"); +_Static_assert(VEGA_USE_MPST == 29, "use MPst"); +_Static_assert(VEGA_USE_N == 4, "use N"); +_Static_assert(VEGA_USE_O == 0, "use O"); +_Static_assert(VEGA_USE_R == 18, "use R"); +_Static_assert(VEGA_USE_RK == 56, "use RK"); +_Static_assert(VEGA_USE_SB == 51, "use SB"); +_Static_assert(VEGA_USE_SE == 52, "use SE"); +_Static_assert(VEGA_USE_SMABV == 41, "use SMAbv"); +_Static_assert(VEGA_USE_SMBLW == 42, "use SMBlw"); +_Static_assert(VEGA_USE_SUB == 11, "use SUB"); +_Static_assert(VEGA_USE_SK == 48, "use Sk"); +_Static_assert(VEGA_USE_VABV == 33, "use VAbv"); +_Static_assert(VEGA_USE_VBLW == 34, "use VBlw"); +_Static_assert(VEGA_USE_VMABV == 37, "use VMAbv"); +_Static_assert(VEGA_USE_VMBLW == 38, "use VMBlw"); +_Static_assert(VEGA_USE_VMPRE == 23, "use VMPre"); +_Static_assert(VEGA_USE_VMPST == 39, "use VMPst"); +_Static_assert(VEGA_USE_VPRE == 22, "use VPre"); +_Static_assert(VEGA_USE_VPST == 35, "use VPst"); +_Static_assert(VEGA_USE_WJ == 16, "use WJ"); +_Static_assert(VEGA_USE_ZWNJ == 14, "use ZWNJ"); + /* The syllable machines: a DFA over classes of symbol; a state's accept is * the syllable type it ends, plus one. */ /* indic (hb-ot-shaper-indic-machine.rl): 137 states, 20 classes of symbol; types indic_consonant_syllable, indic_vowel_syllable, indic_standalone_cluster, indic_symbol_cluster, indic_broken_cluster, indic_non_indic_cluster. */ @@ -461,3 +838,127 @@ static const uint8_t myanmar_accept[57] = { }; const VegaMachine vega_myanmar_machine = {myanmar_class, 23, 57, myanmar_next[0], sizeof(myanmar_next[0][0]), myanmar_accept, 2}; +/* use (hb-ot-shaper-use-machine.rl): 109 states, 43 classes of symbol; types use_virama_terminated_cluster, use_sakot_terminated_cluster, use_standard_cluster, use_number_joiner_terminated_cluster, use_numeral_cluster, use_symbol_cluster, use_hieroglyph_cluster, use_broken_cluster, use_non_cluster. */ +static const uint8_t use_class[64] = { + 0, 1, 2, 2, 3, 4, 2, 2, 2, 2, 2, 5, 6, 7, 8, 2, 2, 2, 9, 2, 2, 2, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 2, 24, 25, 26, 2, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 2, 2, 2, 2, 2, 2, 2, +}; +static const uint8_t use_next[109][43] = { + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 6, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 30, 34, 3, 35, 3, 36, 3, 3, 37}, + {109, 109, 109, 109, 109, 38, 39, 109, 40, 109, 41, 42, 43, 44, 45, 46, 47, 48, 49, 38, 50, 51, 52, 53, 54, 55, 56, 57, 58, 109, 59, 60, 61, 62, 59, 109, 109, 109, 109, 63, 109, 109, 62}, + {109, 109, 109, 109, 109, 2, 64, 109, 65, 109, 66, 67, 68, 69, 70, 71, 72, 73, 74, 2, 75, 76, 77, 78, 79, 80, 81, 109, 109, 109, 82, 83, 84, 85, 86, 109, 109, 109, 109, 87, 109, 109, 88}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 89, 90, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 2, 64, 109, 65, 109, 66, 67, 68, 69, 70, 71, 72, 73, 74, 2, 75, 76, 77, 78, 79, 80, 81, 57, 58, 109, 82, 83, 84, 85, 86, 109, 109, 109, 109, 87, 109, 109, 88}, + {109, 109, 109, 109, 109, 6, 7, 109, 9, 109, 11, 12, 13, 14, 15, 16, 17, 18, 19, 6, 20, 21, 22, 23, 24, 25, 26, 109, 109, 109, 30, 31, 32, 37, 30, 109, 109, 109, 109, 36, 109, 109, 37}, + {109, 6, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 92, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 2, 109, 109, 2, 6, 7, 8, 9, 109, 11, 12, 13, 14, 15, 16, 17, 18, 19, 6, 20, 21, 22, 23, 24, 25, 26, 27, 28, 109, 30, 31, 32, 37, 30, 109, 109, 109, 109, 36, 109, 109, 37}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 11, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 21, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 31, 32, 37, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 31, 32, 37, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 31, 32, 37, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 93, 109, 9, 109, 11, 12, 13, 14, 15, 109, 17, 18, 109, 109, 109, 21, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 93, 109, 9, 109, 11, 12, 13, 14, 15, 109, 109, 18, 109, 109, 109, 21, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 93, 109, 9, 109, 11, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 21, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 93, 109, 9, 109, 11, 12, 13, 14, 15, 16, 17, 18, 109, 109, 109, 21, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 6, 7, 109, 9, 109, 11, 12, 13, 14, 15, 16, 17, 18, 19, 109, 20, 21, 22, 23, 24, 25, 26, 109, 109, 109, 30, 31, 32, 37, 30, 109, 109, 109, 109, 36, 109, 109, 37}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 21, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 22, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 23, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 27, 28, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 28, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 2, 109, 109, 2, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 6, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 31, 32, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 32, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 94, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 95, 109, 96, 109, 96, 97, 109}, + {109, 109, 109, 109, 109, 38, 39, 109, 40, 109, 41, 42, 43, 44, 45, 46, 47, 48, 49, 38, 50, 51, 52, 53, 54, 55, 56, 57, 58, 109, 59, 60, 61, 62, 59, 34, 109, 98, 109, 63, 109, 109, 62}, + {109, 6, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 38, 39, 109, 40, 109, 41, 42, 43, 44, 45, 46, 47, 48, 49, 38, 50, 51, 52, 53, 54, 55, 56, 109, 109, 109, 59, 60, 61, 62, 59, 109, 109, 109, 109, 63, 109, 109, 62}, + {109, 38, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 41, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 51, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 60, 61, 62, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 60, 61, 62, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 60, 61, 62, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 100, 109, 40, 109, 41, 42, 43, 44, 45, 109, 47, 48, 109, 109, 109, 51, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 100, 109, 40, 109, 41, 42, 43, 44, 45, 109, 109, 48, 109, 109, 109, 51, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 100, 109, 40, 109, 41, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 51, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 100, 109, 40, 109, 41, 42, 43, 44, 45, 46, 47, 48, 109, 109, 109, 51, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 38, 39, 109, 40, 109, 41, 42, 43, 44, 45, 46, 47, 48, 49, 109, 50, 51, 52, 53, 54, 55, 56, 109, 109, 109, 59, 60, 61, 62, 59, 109, 109, 109, 109, 63, 109, 109, 62}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 51, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 52, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 53, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 57, 58, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 58, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 38, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 60, 61, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 61, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 38, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 2, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 66, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 76, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 83, 84, 85, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 109, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 83, 84, 85, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 109, 109, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 83, 84, 85, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 102, 109, 65, 109, 66, 67, 68, 69, 70, 109, 72, 73, 109, 109, 109, 76, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 102, 109, 65, 109, 66, 67, 68, 69, 70, 109, 109, 73, 109, 109, 109, 76, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 102, 109, 65, 109, 66, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 76, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 102, 109, 65, 109, 66, 67, 68, 69, 70, 71, 72, 73, 109, 109, 109, 76, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 2, 64, 109, 65, 109, 66, 67, 68, 69, 70, 71, 72, 73, 74, 109, 75, 76, 77, 78, 79, 80, 81, 109, 109, 109, 82, 83, 84, 85, 86, 109, 109, 109, 109, 87, 109, 109, 88}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 76, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 77, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 78, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 2, 109, 109, 109, 109, 109, 109, 103, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 83, 84, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 84, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 2, 109, 109, 109, 109, 109, 109, 104, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 2, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 103, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 4, 109, 109, 109, 109, 105, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 106, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 8, 9, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 12, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 24, 25, 26, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 12, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 94, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 34, 95, 95, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 94, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 95, 109, 96, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 94, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 95, 109, 96, 109, 96, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 34, 109, 98, 109, 109, 109, 109, 109}, + {109, 107, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 42, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 54, 55, 56, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 42, 109, 109, 109}, + {109, 108, 109, 109, 109, 109, 109, 109, 104, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 67, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 79, 80, 81, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 67, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 9, 109, 109, 109, 13, 14, 15, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 31, 32, 37, 91, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 40, 109, 109, 109, 43, 44, 45, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 60, 61, 62, 99, 109, 109, 109, 109, 109, 109, 109, 109}, + {109, 109, 109, 109, 109, 109, 109, 109, 65, 109, 109, 109, 68, 69, 70, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 83, 84, 85, 101, 109, 109, 109, 109, 109, 109, 109, 109}, +}; +static const uint8_t use_accept[109] = { + 8, 6, 3, 9, 5, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, + 8, 9, 7, 6, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 2, 3, 1, 4, 5, 8, 8, 8, 7, 7, + 7, 7, 0, 6, 6, 2, 3, 1, 2, 4, 8, 6, 3, +}; +const VegaMachine vega_use_machine = {use_class, 43, 109, use_next[0], sizeof(use_next[0][0]), use_accept, 8}; + diff --git a/text/syllabic.h b/text/syllabic.h index 8ab8699..d03116b 100644 --- a/text/syllabic.h +++ b/text/syllabic.h @@ -24,6 +24,20 @@ enum { /* A character's category | position << 8 (hb_indic_get_categories). */ uint16_t vega_indic_categories(uint32_t u); +/* The Universal Shaping Engine's categories (hb-ot-shaper-use-machine.rl). */ +enum { + VEGA_USE_O = 0, VEGA_USE_B = 1, VEGA_USE_N = 4, VEGA_USE_GB = 5, VEGA_USE_CGJ = 6, VEGA_USE_SUB = 11, + VEGA_USE_H = 12, VEGA_USE_HN = 13, VEGA_USE_ZWNJ = 14, VEGA_USE_WJ = 16, VEGA_USE_R = 18, VEGA_USE_VPRE = 22, + VEGA_USE_VMPRE = 23, VEGA_USE_FABV = 24, VEGA_USE_FBLW = 25, VEGA_USE_FPST = 26, VEGA_USE_MABV = 27, + VEGA_USE_MBLW = 28, VEGA_USE_MPST = 29, VEGA_USE_MPRE = 30, VEGA_USE_CMABV = 31, VEGA_USE_CMBLW = 32, + VEGA_USE_VABV = 33, VEGA_USE_VBLW = 34, VEGA_USE_VPST = 35, VEGA_USE_VMABV = 37, VEGA_USE_VMBLW = 38, + VEGA_USE_VMPST = 39, VEGA_USE_SMABV = 41, VEGA_USE_SMBLW = 42, VEGA_USE_CS = 43, VEGA_USE_IS = 44, + VEGA_USE_FMABV = 45, VEGA_USE_FMBLW = 46, VEGA_USE_FMPST = 47, VEGA_USE_SK = 48, VEGA_USE_G = 49, VEGA_USE_J = 50, + VEGA_USE_SB = 51, VEGA_USE_SE = 52, VEGA_USE_HVM = 53, VEGA_USE_HM = 54, VEGA_USE_HR = 55, VEGA_USE_RK = 56 +}; +/* A character's USE category (hb_use_get_category). */ +uint8_t vega_use_category(uint32_t u); + /* A syllable machine: a DFA over classes of symbols (categories, those * past 63 taken as 63). From each position the longest run it accepts is * a syllable, ties to the pattern its grammar lists first (Ragel's @@ -36,5 +50,5 @@ typedef struct { const uint8_t *accept; /* [states]: the syllable type a state ends, plus one; 0 for none */ unsigned broken; /* the broken cluster's type, plus one */ } VegaMachine; -extern const VegaMachine vega_indic_machine, vega_khmer_machine, vega_myanmar_machine; +extern const VegaMachine vega_indic_machine, vega_khmer_machine, vega_myanmar_machine, vega_use_machine; #endif diff --git a/text/syllabic.py b/text/syllabic.py index 6eb7c93..4a79869 100644 --- a/text/syllabic.py +++ b/text/syllabic.py @@ -12,6 +12,10 @@ HARFBUZZ_SRC is HarfBuzz 10.2.0's src/ directory; what is read from it: read cell for cell (Unicode here is 15.1: the table is taken as HarfBuzz has it). Khmer and Myanmar read the same table. +- Each character's category for the Universal Shaping Engine: hb-ot- + shaper-use-table.hh, whose arrays and lookup (gen-use-table.py's) are + carried over as they are, the categories named in them resolved. + - The syllable machines: hb-ot-shaper-*-machine.rl, the Ragel grammars. This compiles each to a DFA with Ragel's scanner semantics (the longest match from each position, ties to the pattern listed first), its symbols @@ -27,7 +31,7 @@ import sys from pathlib import Path HB = Path(sys.argv[1] if len(sys.argv) > 1 else '.') -MACHINES = ['indic', 'khmer', 'myanmar'] +MACHINES = ['indic', 'khmer', 'myanmar', 'use'] ALPHABET = 64 # categories past 63 are folded into 63, which only `any` takes @@ -277,6 +281,22 @@ def runs_of(cells): return runs +def use_table(grammar): + """HarfBuzz's USE lookup: its arrays (categories resolved to numbers) + and its expression, as C.""" + text = (HB / 'hb-ot-shaper-use-table.hh').read_text() + part = text[text.index('#ifndef HB_OPTIMIZE_SIZE'):text.index('#else')] + arrays = [] + for kind, name, n, body in re.findall(r'static const (uint8_t|uint16_t)\s+(hb_use_\w+)\[(\d+)\] =\s*\{(.*?)\};', + part, re.S): + values = [int(t) if t.isdigit() else grammar.symbols[t] for t in re.findall(r'[A-Za-z_]\w*|\d+', body)] + assert len(values) == int(n), name + arrays.append((kind, name.replace('hb_use_', 'use_'), values)) + expression = re.search(r'return (u<.*?);\n', part).group(1).replace('hb_use_', 'use_') + assert expression.endswith(':O') + return arrays, expression[:-1] + str(grammar.symbols['O']) + + # ---- Checking against Ragel's machines (hb-ot-shaper-*-machine.hh) def ragel(name): @@ -445,6 +465,24 @@ def main(): out.append(f' return 0x{default[0] | default[1] << 8:04X};') out.append('}') out.append('') + arrays, expression = use_table(grammars['use']) + out.append('/* Each character\'s USE category (hb-ot-shaper-use-table.hh, Unicode 16): HarfBuzz\'s arrays and') + out.append(' * lookup. */') + for kind, name, values in arrays: + out.append(f'static const {kind} {name}[{len(values)}] = {{') + for k in range(0, len(values), 16): + out.append(' ' + ', '.join(str(v) for v in values[k:k + 16]) + ',') + out.append('};') + out.append('static unsigned use_b4(const uint8_t *a, unsigned i) { return (a[i >> 1] >> ((i & 1u) << 2)) & 15u; }') + out.append(f'uint8_t vega_use_category(uint32_t u) {{ return (uint8_t)({expression}); }}') + out.append('') + out.append('/* The categories syllabic.h names are the machines\' own. */') + for name, prefix in (('indic', 'VEGA_OT_'), ('khmer', 'VEGA_OT_'), ('myanmar', 'VEGA_OT_'), ('use', 'VEGA_USE_')): + for symbol, value in sorted(grammars[name].symbols.items()): + if name == 'myanmar' and symbol in ('IV', 'DB', 'GB'): + continue # Myanmar's names for V, N and PLACEHOLDER + out.append(f'_Static_assert({prefix}{symbol.upper()} == {value}, "{name} {symbol}");') + out.append('') out.append('/* The syllable machines: a DFA over classes of symbol; a state\'s accept is') out.append(' * the syllable type it ends, plus one. */') for name in MACHINES: |
