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);
}
bool auto_zwnj;
bool auto_zwj;
+ bool random;
+ uint64_t random_state;
bool has_glyph_classes;
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_)
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]);
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;
lookup->index = lookup_indices[i];
lookup->auto_zwnj = auto_zwnj;
lookup->auto_zwj = auto_zwj;
+ lookup->random = random;
}
offset += len;
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)
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)
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;
HB_TAG('m','a','r','k'),
HB_TAG('m','k','m','k'),
HB_TAG('r','l','i','g'),
+ HB_TAG('r','a','n','d'),
};