src/hb-ot-layout-gsub-table.hh | 7 +++++ src/hb-ot-layout-gsubgpos.hh | 11 +++++++-- src/hb-ot-layout.cc | 5 ++++ src/hb-ot-map.cc | 12 ++++++---- src/hb-ot-map.hh | 11 +++++++-- src/hb-ot-shape.cc | 7 +++++ test/shaping/data/in-house/Makefile.sources | 1 test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf |binary test/shaping/data/in-house/tests/rand.tests | 3 ++ 9 files changed, 48 insertions(+), 9 deletions(-)
New commits: commit 71c9f84e7c0afe41a8987b8a4ebc2b45a22fac56 Author: Behdad Esfahbod <beh...@behdad.org> Date: Mon Sep 10 22:37:19 2018 +0200 Make --features rand=1 available to the user Use rand=255 to mean "randomize". Part of https://github.com/harfbuzz/harfbuzz/pull/803 diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 255a2827..dfa50979 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -541,18 +541,15 @@ struct AlternateSet unsigned int shift = hb_ctz (lookup_mask); unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); - if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); - - /* This is ugly... If alt_index is 1, we take it as "on", and randomize - * feature if it is the rand feature. If it's > 1, it's a user-set value - * for sure, so respect it. So, user cannot set rand=1 and expect it to - * choose the first alternate... */ - if (alt_index == 1 && c->random) + /* If alt_index is MAX, randomize feature if it is the rand feature. */ + if (alt_index == HB_OT_MAP_MAX_VALUE && c->random) { c->random_state = (0x5DEECE66Dull * c->random_state + 11) & (((uint64_t) 1 << 48) - 1); alt_index = (c->random_state >> 32) % count + 1; } + if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); + c->replace_glyph (alternates[alt_index - 1]); return_trace (true); diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index df032264..be1b449c 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -33,6 +33,7 @@ #include "hb-buffer.hh" #include "hb-map.hh" #include "hb-set.hh" +#include "hb-ot-map.hh" #include "hb-ot-layout-common.hh" #include "hb-ot-layout-gdef-table.hh" diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 8617f054..cb70583f 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -210,8 +210,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, /* Uses the global bit */ bits_needed = 0; else - /* Limit to 8 bits per feature. */ - bits_needed = MIN(8u, hb_bit_storage (info->max_value)); + /* Limit bits per feature. */ + bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value)); if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t)) continue; /* Feature disabled, or not enough bits. */ diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index 091cb3b6..cc36fa27 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh @@ -32,6 +32,9 @@ #include "hb-buffer.hh" +#define HB_OT_MAP_MAX_BITS 8u +#define HB_OT_MAP_MAX_VALUE ((1u << HB_OT_MAP_MAX_BITS) - 1u) + struct hb_ot_shape_plan_t; static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS}; diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 00a8a647..437b0feb 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -96,7 +96,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE); /* Random! */ - map->add_feature (HB_TAG ('r','a','n','d'), 1, F_GLOBAL | F_RANDOM); + map->add_feature (HB_TAG ('r','a','n','d'), HB_OT_MAP_MAX_VALUE, F_GLOBAL | F_RANDOM); if (planner->shaper->collect_features) planner->shaper->collect_features (planner); commit cc1c4fdf88f6953dcd07fb42ee963404657cdef4 Author: Behdad Esfahbod <beh...@behdad.org> Date: Mon Sep 10 16:36:05 2018 +0200 Respect user's wish if they set rand feature manually Except if the set it to 1, which would mean "randomize"... Ugly. diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index ae679441..255a2827 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -534,25 +534,27 @@ struct AlternateSet if (unlikely (!count)) return_trace (false); - if (c->random) - { - c->random_state = (0x5DEECE66Dull * c->random_state + 11) & (((uint64_t) 1 << 48) - 1); - c->replace_glyph (alternates[(c->random_state >> 32) % count]); - } - else - { - hb_mask_t glyph_mask = c->buffer->cur().mask; - hb_mask_t lookup_mask = c->lookup_mask; + hb_mask_t glyph_mask = c->buffer->cur().mask; + hb_mask_t lookup_mask = c->lookup_mask; - /* Note: This breaks badly if two features enabled this lookup together. */ - unsigned int shift = hb_ctz (lookup_mask); - unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); + /* Note: This breaks badly if two features enabled this lookup together. */ + unsigned int shift = hb_ctz (lookup_mask); + unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); - if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); + if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); - c->replace_glyph (alternates[alt_index - 1]); + /* This is ugly... If alt_index is 1, we take it as "on", and randomize + * feature if it is the rand feature. If it's > 1, it's a user-set value + * for sure, so respect it. So, user cannot set rand=1 and expect it to + * choose the first alternate... */ + if (alt_index == 1 && c->random) + { + c->random_state = (0x5DEECE66Dull * c->random_state + 11) & (((uint64_t) 1 << 48) - 1); + alt_index = (c->random_state >> 32) % count + 1; } + c->replace_glyph (alternates[alt_index - 1]); + return_trace (true); } commit 80de4bcd2677bfb0907ea7059524f918b109ac37 Author: Behdad Esfahbod <beh...@behdad.org> Date: Mon Sep 10 16:24:52 2018 +0200 Minor clean up of 'rand' patchset diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index db24a284..ae679441 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -534,10 +534,13 @@ struct AlternateSet if (unlikely (!count)) return_trace (false); - if (c->random) { + if (c->random) + { c->random_state = (0x5DEECE66Dull * c->random_state + 11) & (((uint64_t) 1 << 48) - 1); c->replace_glyph (alternates[(c->random_state >> 32) % count]); - } else { + } + else + { hb_mask_t glyph_mask = c->buffer->cur().mask; hb_mask_t lookup_mask = c->lookup_mask; diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 3a028f34..df032264 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -478,11 +478,12 @@ struct hb_ot_apply_context_t : unsigned int nesting_level_left; unsigned int debug_depth; + bool has_glyph_classes; bool auto_zwnj; bool auto_zwj; bool random; + uint64_t random_state; - bool has_glyph_classes; hb_ot_apply_context_t (unsigned int table_index_, @@ -500,11 +501,11 @@ struct hb_ot_apply_context_t : lookup_props (0), nesting_level_left (HB_MAX_NESTING_LEVEL), debug_depth (0), + has_glyph_classes (gdef.has_glyph_classes ()), auto_zwnj (true), auto_zwj (true), random (false), - random_state (1), - has_glyph_classes (gdef.has_glyph_classes ()) {} + random_state (1) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 0007e0ab..00a8a647 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -70,7 +70,6 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, unsigned int num_user_features) { hb_ot_map_builder_t *map = &planner->map; - bool default_rand = true; map->add_global_bool_feature (HB_TAG('r','v','r','n')); map->add_gsub_pause (nullptr); @@ -91,10 +90,14 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, break; } + /* Automatic fractions. */ map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE); map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE); map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE); + /* Random! */ + map->add_feature (HB_TAG ('r','a','n','d'), 1, F_GLOBAL | F_RANDOM); + if (planner->shaper->collect_features) planner->shaper->collect_features (planner); @@ -118,17 +121,13 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, if (planner->shaper->override_features) planner->shaper->override_features (planner); - for (unsigned int i = 0; i < num_user_features; i++) { + for (unsigned int i = 0; i < num_user_features; i++) + { const hb_feature_t *feature = &user_features[i]; map->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1) ? F_GLOBAL : F_NONE); - if (feature->tag == HB_TAG ('r','a','n','d')) - default_rand = false; } - - if (default_rand) - map->add_feature (HB_TAG ('r','a','n','d'), 1, F_GLOBAL | F_RANDOM); } diff --git a/test/shaping/data/in-house/tests/rand.tests b/test/shaping/data/in-house/tests/rand.tests index 781abf42..5ea0fc04 100644 --- a/test/shaping/data/in-house/tests/rand.tests +++ b/test/shaping/data/in-house/tests/rand.tests @@ -1,3 +1,3 @@ ../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=-rand:U+0054,U+0055,U+0056:[1=0+560|2=1+602|3=2+602] -../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=rand=2:U+0054,U+0055,U+0056:[5=0+560|8=1+602|11=2+602] +#../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=rand=2:U+0054,U+0055,U+0056:[5=0+560|8=1+602|11=2+602] ../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names:U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056:[6=0+560|9=1+602|10=2+602|6=3+560|9=4+602|12=5+602|5=6+560|8=7+602|11=8+602|6=9+560|8=10+602|10=11+602] commit b545e27d8891f1e7f1fd034dd84abe44c839c380 Author: David Corbett <corbett....@husky.neu.edu> Date: Fri Feb 23 12:22:32 2018 -0500 Don't seed the RNG from the contents of the buffer diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 113433d9..3a028f34 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -503,16 +503,13 @@ struct hb_ot_apply_context_t : auto_zwnj (true), auto_zwj (true), random (false), - random_state (0), + random_state (1), has_glyph_classes (gdef.has_glyph_classes ()) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; } - inline void set_random_state (uint64_t random_state_) { - random = true; - random_state = random_state_; - } + inline void set_random (bool random_) { random = random_; } inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } inline void set_lookup_props (unsigned int lookup_props_) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index b31dbbca..51c11985 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1270,10 +1270,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); if (lookups[table_index][i].random) { - uint64_t random_state = 1; - for (unsigned int j = 0; j < buffer->len; j++) - random_state = 31 * random_state + buffer->info[j].codepoint; - c.set_random_state (random_state); + c.set_random (true); buffer->unsafe_to_break_all (); } apply_string<Proxy> (&c, diff --git a/test/shaping/data/in-house/tests/rand.tests b/test/shaping/data/in-house/tests/rand.tests index f1023e82..781abf42 100644 --- a/test/shaping/data/in-house/tests/rand.tests +++ b/test/shaping/data/in-house/tests/rand.tests @@ -1,3 +1,3 @@ ../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=-rand:U+0054,U+0055,U+0056:[1=0+560|2=1+602|3=2+602] ../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=rand=2:U+0054,U+0055,U+0056:[5=0+560|8=1+602|11=2+602] -../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names:U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056:[4=0+560|7=1+602|11=2+602|6=3+560|8=4+602|10=5+602|5=6+560|9=7+602|10=8+602|5=9+560|7=10+602|12=11+602] +../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names:U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056:[6=0+560|9=1+602|10=2+602|6=3+560|9=4+602|12=5+602|5=6+560|8=7+602|11=8+602|6=9+560|8=10+602|10=11+602] commit 2de96e846844d21888af6893378b21a33fc19232 Author: David Corbett <corbett....@husky.neu.edu> Date: Sat Jan 27 19:48:38 2018 -0500 Test 'rand' diff --git a/test/shaping/data/in-house/Makefile.sources b/test/shaping/data/in-house/Makefile.sources index ef16faed..1bb8604e 100644 --- a/test/shaping/data/in-house/Makefile.sources +++ b/test/shaping/data/in-house/Makefile.sources @@ -32,6 +32,7 @@ TESTS = \ tests/mongolian-variation-selector.tests \ tests/myanmar-syllable.tests \ tests/none-directional.tests \ + tests/rand.tests \ tests/spaces.tests \ tests/simple.tests \ tests/sinhala.tests \ diff --git a/test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf b/test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf new file mode 100644 index 00000000..588ce3b9 Binary files /dev/null and b/test/shaping/data/in-house/fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf differ diff --git a/test/shaping/data/in-house/tests/rand.tests b/test/shaping/data/in-house/tests/rand.tests new file mode 100644 index 00000000..f1023e82 --- /dev/null +++ b/test/shaping/data/in-house/tests/rand.tests @@ -0,0 +1,3 @@ +../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=-rand:U+0054,U+0055,U+0056:[1=0+560|2=1+602|3=2+602] +../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names --features=rand=2:U+0054,U+0055,U+0056:[5=0+560|8=1+602|11=2+602] +../fonts/5bb74492f5e0ffa1fbb72e4c881be035120b6513.ttf:--no-glyph-names:U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056,U+0054,U+0055,U+0056:[4=0+560|7=1+602|11=2+602|6=3+560|8=4+602|10=5+602|5=6+560|9=7+602|10=8+602|5=9+560|7=10+602|12=11+602] commit f05df643b44d9bbfd742e93f02c235fc821190d0 Author: David Corbett <corbett....@husky.neu.edu> Date: Fri Jan 26 21:36:15 2018 -0500 Allow requesting a specific glyph for 'rand' Randomization only happens by default. If the user specifies a value for 'rand', that value is respected. diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index fb320e29..8617f054 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -254,6 +254,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, map->stage[1] = info->stage[1]; map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ); map->auto_zwj = !(info->flags & F_MANUAL_ZWJ); + map->random = !!(info->flags & F_RANDOM); if ((info->flags & F_GLOBAL) && info->max_value == 1) { /* Uses the global bit */ map->shift = global_bit_shift; @@ -304,7 +305,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, m.features[i].mask, m.features[i].auto_zwnj, m.features[i].auto_zwj, - m.features[i].tag == HB_TAG ('r','a','n','d')); + m.features[i].random); /* Sort lookups and merge duplicates */ if (last_num_lookups < m.lookups[table_index].len) diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index 2518a492..091cb3b6 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh @@ -52,6 +52,7 @@ struct hb_ot_map_t unsigned int needs_fallback : 1; unsigned int auto_zwnj : 1; unsigned int auto_zwj : 1; + unsigned int random : 1; inline int cmp (const hb_tag_t *tag_) const { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; } @@ -168,7 +169,8 @@ enum hb_ot_map_feature_flags_t { F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */ F_MANUAL_ZWNJ = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */ F_MANUAL_ZWJ = 0x0008u, /* Don't skip over ZWJ when matching **input**. */ - F_GLOBAL_SEARCH = 0x0010u /* If feature not found in LangSys, look for it in global feature list and pick one. */ + F_GLOBAL_SEARCH = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */ + F_RANDOM = 0x0020u /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */ }; HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t); /* Macro version for where const is desired. */ diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index f5aeb0df..0007e0ab 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -49,7 +49,6 @@ static hb_tag_t common_features[] = { HB_TAG('m','a','r','k'), HB_TAG('m','k','m','k'), HB_TAG('r','l','i','g'), - HB_TAG('r','a','n','d'), }; @@ -71,6 +70,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, unsigned int num_user_features) { hb_ot_map_builder_t *map = &planner->map; + bool default_rand = true; map->add_global_bool_feature (HB_TAG('r','v','r','n')); map->add_gsub_pause (nullptr); @@ -123,7 +123,12 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, map->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1) ? F_GLOBAL : F_NONE); + if (feature->tag == HB_TAG ('r','a','n','d')) + default_rand = false; } + + if (default_rand) + map->add_feature (HB_TAG ('r','a','n','d'), 1, F_GLOBAL | F_RANDOM); } commit c2a75e07e54314f6c611dda0f050ed5f09909e43 Author: David Corbett <corbett....@husky.neu.edu> Date: Thu Jan 25 14:22:03 2018 -0500 Implement 'rand' diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 76a0ea6d..db24a284 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -534,16 +534,21 @@ struct AlternateSet if (unlikely (!count)) return_trace (false); - hb_mask_t glyph_mask = c->buffer->cur().mask; - hb_mask_t lookup_mask = c->lookup_mask; + if (c->random) { + c->random_state = (0x5DEECE66Dull * c->random_state + 11) & (((uint64_t) 1 << 48) - 1); + c->replace_glyph (alternates[(c->random_state >> 32) % count]); + } else { + hb_mask_t glyph_mask = c->buffer->cur().mask; + hb_mask_t lookup_mask = c->lookup_mask; - /* Note: This breaks badly if two features enabled this lookup together. */ - unsigned int shift = hb_ctz (lookup_mask); - unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); + /* Note: This breaks badly if two features enabled this lookup together. */ + unsigned int shift = hb_ctz (lookup_mask); + unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); - if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); + if (unlikely (alt_index > count || alt_index == 0)) return_trace (false); - c->replace_glyph (alternates[alt_index - 1]); + c->replace_glyph (alternates[alt_index - 1]); + } return_trace (true); } diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 719a5050..113433d9 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -480,6 +480,8 @@ struct hb_ot_apply_context_t : bool auto_zwnj; bool auto_zwj; + bool random; + uint64_t random_state; bool has_glyph_classes; @@ -500,11 +502,17 @@ struct hb_ot_apply_context_t : debug_depth (0), auto_zwnj (true), auto_zwj (true), + random (false), + random_state (0), has_glyph_classes (gdef.has_glyph_classes ()) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; } + inline void set_random_state (uint64_t random_state_) { + random = true; + random_state = random_state_; + } inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } inline void set_lookup_props (unsigned int lookup_props_) diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index a1220f4d..b31dbbca 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1268,6 +1268,14 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); + if (lookups[table_index][i].random) + { + uint64_t random_state = 1; + for (unsigned int j = 0; j < buffer->len; j++) + random_state = 31 * random_state + buffer->info[j].codepoint; + c.set_random_state (random_state); + buffer->unsafe_to_break_all (); + } apply_string<Proxy> (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 29f52dcc..fb320e29 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -95,7 +95,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, unsigned int variations_index, hb_mask_t mask, bool auto_zwnj, - bool auto_zwj) + bool auto_zwj, + bool random) { unsigned int lookup_indices[32]; unsigned int offset, len; @@ -122,6 +123,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, lookup->index = lookup_indices[i]; lookup->auto_zwnj = auto_zwnj; lookup->auto_zwj = auto_zwj; + lookup->random = random; } offset += len; @@ -301,7 +303,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, variations_index, m.features[i].mask, m.features[i].auto_zwnj, - m.features[i].auto_zwj); + m.features[i].auto_zwj, + m.features[i].tag == HB_TAG ('r','a','n','d')); /* Sort lookups and merge duplicates */ if (last_num_lookups < m.lookups[table_index].len) diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index 32a9e7e0..2518a492 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh @@ -61,6 +61,7 @@ struct hb_ot_map_t unsigned short index; unsigned short auto_zwnj : 1; unsigned short auto_zwj : 1; + unsigned short random : 1; hb_mask_t mask; static int cmp (const void *pa, const void *pb) @@ -206,7 +207,8 @@ struct hb_ot_map_builder_t unsigned int variations_index, hb_mask_t mask, bool auto_zwnj = true, - bool auto_zwj = true); + bool auto_zwj = true, + bool random = false); struct feature_info_t { hb_tag_t tag; diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 63102f6b..f5aeb0df 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -49,6 +49,7 @@ static hb_tag_t common_features[] = { HB_TAG('m','a','r','k'), HB_TAG('m','k','m','k'), HB_TAG('r','l','i','g'), + HB_TAG('r','a','n','d'), }; _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/harfbuzz