[HarfBuzz] harfbuzz: Branch 'master' - 7 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Tue Sep 11 08:48:09 UTC 2018
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 <behdad at 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 <behdad at 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 <behdad at 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.dav at 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.dav at 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.dav at 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.dav at 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'),
};
More information about the HarfBuzz
mailing list