Implement 'rand'
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 76a0ea6..db24a28 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -534,16 +534,21 @@
 
     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 bd4611d..3e961c1 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -480,6 +480,8 @@
 
   bool auto_zwnj;
   bool auto_zwj;
+  bool random;
+  uint64_t random_state;
   bool has_glyph_classes;
 
 
@@ -500,11 +502,17 @@
 			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 a1220f4..b31dbbc 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -1268,6 +1268,14 @@
       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 29f52dc..fb320e2 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -95,7 +95,8 @@
 				  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 @@
       lookup->index = lookup_indices[i];
       lookup->auto_zwnj = auto_zwnj;
       lookup->auto_zwj = auto_zwj;
+      lookup->random = random;
     }
 
     offset += len;
@@ -301,7 +303,8 @@
 		       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 32a9e7e..2518a49 100644
--- a/src/hb-ot-map.hh
+++ b/src/hb-ot-map.hh
@@ -61,6 +61,7 @@
     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 @@
 				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 63102f6..f5aeb0d 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -49,6 +49,7 @@
   HB_TAG('m','a','r','k'),
   HB_TAG('m','k','m','k'),
   HB_TAG('r','l','i','g'),
+  HB_TAG('r','a','n','d'),
 };