diff options
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: |
