[HarfBuzz] harfbuzz: Branch 'master' - 7 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Oct 2 16:46:36 UTC 2018


 src/Makefile.sources                                                                        |    1 
 src/dump-khmer-data.cc                                                                      |    8 -
 src/gen-use-table.py                                                                        |   30 ++--
 src/hb-ot-shape-complex-indic-machine.hh                                                    |   62 ++++----
 src/hb-ot-shape-complex-indic-machine.rl                                                    |   18 +-
 src/hb-ot-shape-complex-khmer-machine.hh                                                    |   22 +--
 src/hb-ot-shape-complex-khmer-machine.rl                                                    |    8 -
 src/hb-ot-shape-complex-khmer.hh                                                            |    1 
 src/hb-ot-shape-complex-myanmar-machine.hh                                                  |   22 +--
 src/hb-ot-shape-complex-myanmar-machine.rl                                                  |    8 -
 src/hb-ot-shape-complex-tibetan.cc                                                          |   63 ---------
 src/hb-ot-shape-complex-use-machine.hh                                                      |   56 +++-----
 src/hb-ot-shape-complex-use-machine.rl                                                      |   29 +---
 src/hb-ot-shape-complex-use-table.cc                                                        |   70 ++++++----
 src/hb-ot-shape-complex.hh                                                                  |    9 -
 test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-leters.txt            |    3 
 test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt |   33 ++++
 test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt     |   17 ++
 test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letter.txt          |    8 +
 test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt         |    9 +
 test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt           |    3 
 test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt       |    5 
 test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt               |    3 
 test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt             |    5 
 24 files changed, 259 insertions(+), 234 deletions(-)

New commits:
commit fef7af1e22efb399517137b35d0ba9f307411ca3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 18:46:13 2018 +0200

    [tibetan] Remove unused Tibetan shaper

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 46af3ae5..69ab155a 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -137,7 +137,6 @@ HB_OT_sources = \
 	hb-ot-shape-complex-myanmar.hh \
 	hb-ot-shape-complex-myanmar.cc \
 	hb-ot-shape-complex-thai.cc \
-	hb-ot-shape-complex-tibetan.cc \
 	hb-ot-shape-complex-use.cc \
 	hb-ot-shape-complex-use.hh \
 	hb-ot-shape-complex-use-table.cc \
diff --git a/src/hb-ot-shape-complex-tibetan.cc b/src/hb-ot-shape-complex-tibetan.cc
deleted file mode 100644
index 5d6dfeae..00000000
--- a/src/hb-ot-shape-complex-tibetan.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex.hh"
-
-
-static const hb_tag_t tibetan_features[] =
-{
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-  HB_TAG_NONE
-};
-
-static void
-collect_features_tibetan (hb_ot_shape_planner_t *plan)
-{
-  for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++)
-    plan->map.enable_feature (*script_features);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
-{
-  collect_features_tibetan,
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  HB_TAG_NONE, /* gpos_tag */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
diff --git a/src/hb-ot-shape-complex.hh b/src/hb-ot-shape-complex.hh
index ce0191e8..36b5b22e 100644
--- a/src/hb-ot-shape-complex.hh
+++ b/src/hb-ot-shape-complex.hh
@@ -59,7 +59,6 @@ enum hb_ot_shape_zero_width_marks_type_t {
   HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
   HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
   HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
   HB_COMPLEX_SHAPER_IMPLEMENT (use) \
   /* ^--- Add new shapers here */
 
commit 32a438166fbccac6e0d9a615a492fc8cabfd21ab
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 18:43:29 2018 +0200

    [tibetan] Route Tibetan through USE
    
    Fixes https://github.com/harfbuzz/harfbuzz/pull/933
    https://github.com/harfbuzz/harfbuzz/issues/1012
    
    Tibetan failures go from 0 to 2:
    
    TIBETAN: 208467 out of 208469 tests passed. 2 failed (0.000959375%)

diff --git a/src/gen-use-table.py b/src/gen-use-table.py
index 9c7e6f48..2afbc760 100755
--- a/src/gen-use-table.py
+++ b/src/gen-use-table.py
@@ -8,7 +8,7 @@ if len (sys.argv) != 5:
 	print ("usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt", file=sys.stderr)
 	sys.exit (1)
 
-BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"]
+BLACKLISTED_BLOCKS = ["Thai", "Lao"]
 
 files = [io.open (x, encoding='utf-8') for x in sys.argv[1:]]
 
@@ -307,11 +307,28 @@ def map_to_use(data):
 
 		# Resolve Indic_Syllabic_Category
 
-		# TODO: These don't have UISC assigned in Unicode 8.0, but
-		# have UIPC
+		# TODO: These don't have UISC assigned in Unicode 8.0, but have UIPC
 		if U == 0x17DD: UISC = Vowel_Dependent
 		if 0x1CE2 <= U <= 0x1CE8: UISC = Cantillation_Mark
 
+		# Tibetan:
+		# TODO: These don't have UISC assigned in Unicode 11.0, but have UIPC
+		if 0x0F18 <= U <= 0x0F19 or 0x0F3E <= U <= 0x0F3F: UISC = Vowel_Dependent
+		if 0x0F86 <= U <= 0x0F87: UISC = Tone_Mark
+		# Overrides to allow NFC order matching syllable
+		# https://github.com/harfbuzz/harfbuzz/issues/1012
+		if UBlock == 'Tibetan' and is_VOWEL (U, UISC, UGC):
+			if UIPC == Top:
+				UIPC = Bottom
+
+		# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
+		# also  https://github.com/harfbuzz/harfbuzz/issues/1012
+		if UBlock == 'Chakma' and is_VOWEL (U, UISC, UGC):
+			if UIPC == Top:
+				UIPC = Bottom
+			elif UIPC == Bottom:
+				UIPC = Top
+
 		# TODO: https://github.com/harfbuzz/harfbuzz/pull/627
 		if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
 
@@ -359,13 +376,6 @@ def map_to_use(data):
 		# https://github.com/roozbehp/unicode-data/issues/8
 		if U == 0x0A51: UIPC = Bottom
 
-		# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
-		if UBlock == 'Chakma' and is_VOWEL (U, UISC, UGC):
-			if UIPC == Top:
-				UIPC = Bottom
-			elif UIPC == Bottom:
-				UIPC = Top
-
 		assert (UIPC in [Not_Applicable, Visual_Order_Left] or
 			USE in use_positions), "%s %s %s %s %s" % (hex(U), UIPC, USE, UISC, UGC)
 
diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc
index d4237b0a..e9d969fb 100644
--- a/src/hb-ot-shape-complex-use-table.cc
+++ b/src/hb-ot-shape-complex-use-table.cc
@@ -194,7 +194,24 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 0DE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
 
-#define use_offset_0x1000u 1360
+#define use_offset_0x0f18u 1360
+
+
+  /* Tibetan */
+                                                                      VBlw,  VBlw,     O,     O,     O,     O,     O,     O,
+  /* 0F20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F30 */     B,     B,     B,     B,     O,    FM,     O,    FM,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
+  /* 0F40 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
+  /* 0F70 */     O,  VBlw,  VBlw,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw, VMAbv, VMPst,
+  /* 0F80 */  VBlw,  VAbv, VMAbv, VMAbv,  VBlw,   IND, VMAbv, VMAbv,     B,     B,     B,     B,     B,   SUB,   SUB,   SUB,
+  /* 0F90 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
+  /* 0FC0 */     O,     O,     O,     O,     O,     O,    FM,     O,
+
+#define use_offset_0x1000u 1536
 
 
   /* Myanmar */
@@ -210,7 +227,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1080 */     B,     B,  MBlw,  VPst,  VPre,  VAbv,  VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw,     B, VMPst,
   /* 1090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,  VPst,  VAbv,     O,     O,
 
-#define use_offset_0x1700u 1520
+#define use_offset_0x1700u 1696
 
 
   /* Tagalog */
@@ -243,7 +260,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,  VAbv,     O,     O,
   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1900u 1760
+#define use_offset_0x1900u 1936
 
 
   /* Limbu */
@@ -287,7 +304,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1b00u 2176
+#define use_offset_0x1b00u 2352
 
 
   /* Balinese */
@@ -323,7 +340,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
 
-#define use_offset_0x1cd0u 2512
+#define use_offset_0x1cd0u 2688
 
 
   /* Vedic Extensions */
@@ -332,20 +349,20 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
   /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,    CS,    CS, VMPst, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1df8u 2560
+#define use_offset_0x1df8u 2736
 
 
   /* Combining Diacritical Marks Supplement */
                                                                          O,     O,     O,    FM,     O,     O,     O,     O,
 
-#define use_offset_0x2008u 2568
+#define use_offset_0x2008u 2744
 
 
   /* General Punctuation */
                                                                          O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
   /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
 
-#define use_offset_0x2060u 2584
+#define use_offset_0x2060u 2760
 
   /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -354,20 +371,20 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
 
-#define use_offset_0x20f0u 2624
+#define use_offset_0x20f0u 2800
 
 
   /* Combining Diacritical Marks for Symbols */
 
   /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x25c8u 2632
+#define use_offset_0x25c8u 2808
 
 
   /* Geometric Shapes */
                                                                          O,     O,     O,     O,    GB,     O,     O,     O,
 
-#define use_offset_0xa800u 2640
+#define use_offset_0xa800u 2816
 
 
   /* Syloti Nagri */
@@ -454,7 +471,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
   /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
 
-#define use_offset_0xabc0u 3400
+#define use_offset_0xabc0u 3576
 
 
   /* Meetei Mayek */
@@ -464,14 +481,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
   /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0xfe00u 3464
+#define use_offset_0xfe00u 3640
 
 
   /* Variation Selectors */
 
   /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
 
-#define use_offset_0x10a00u 3480
+#define use_offset_0x10a00u 3656
 
 
   /* Kharoshthi */
@@ -482,7 +499,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 10A30 */     B,     B,     B,     B,     B,     B,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11000u 3560
+#define use_offset_0x11000u 3736
 
 
   /* Brahmi */
@@ -503,7 +520,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 110A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11100u 3752
+#define use_offset_0x11100u 3928
 
 
   /* Chakma */
@@ -511,7 +528,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11100 */ VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VBlw,  VAbv,  VAbv,
-  /* 11130 */  VBlw,  VAbv,  VAbv,     H, CMAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11130 */  VBlw,  VAbv,  VAbv,     H, CMBlw,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11140 */     O,     O,     O,     O,     B,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Mahajani */
@@ -541,7 +558,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
   /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
 
-#define use_offset_0x11280u 4072
+#define use_offset_0x11280u 4248
 
 
   /* Multani */
@@ -569,7 +586,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
-#define use_offset_0x11400u 4320
+#define use_offset_0x11400u 4496
 
 
   /* Newa */
@@ -592,7 +609,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 114C0 */ VMAbv, VMPst,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11580u 4544
+#define use_offset_0x11580u 4720
 
 
   /* Siddham */
@@ -635,7 +652,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
 
-#define use_offset_0x11800u 4992
+#define use_offset_0x11800u 5168
 
 
   /* Dogra */
@@ -645,7 +662,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11820 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,
   /* 11830 */  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11a00u 5056
+#define use_offset_0x11a00u 5232
 
 
   /* Zanabazar Square */
@@ -664,7 +681,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
   /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     B,     O,     O,
 
-#define use_offset_0x11c00u 5216
+#define use_offset_0x11c00u 5392
 
 
   /* Bhaiksuki */
@@ -685,7 +702,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-#define use_offset_0x11d00u 5400
+#define use_offset_0x11d00u 5576
 
 
   /* Masaram Gondi */
@@ -705,7 +722,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11D90 */  VAbv,  VAbv,     O,  VPst,  VPst, VMAbv, VMPst,     H,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11ee0u 5576
+#define use_offset_0x11ee0u 5752
 
 
   /* Makasar */
@@ -713,7 +730,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = {
   /* 11EE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11EF0 */     B,     B,    GB,  VAbv,  VBlw,  VPre,  VPst,     O,
 
-}; /* Table items: 5600; occupancy: 73% */
+}; /* Table items: 5776; occupancy: 74% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_category (hb_codepoint_t u)
@@ -725,6 +742,7 @@ hb_use_get_category (hb_codepoint_t u)
       if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x0F18u, 0x0FC7u)) return use_table[u - 0x0F18u + use_offset_0x0f18u];
       break;
 
     case 0x1u:
diff --git a/src/hb-ot-shape-complex.hh b/src/hb-ot-shape-complex.hh
index c18f1b96..ce0191e8 100644
--- a/src/hb-ot-shape-complex.hh
+++ b/src/hb-ot-shape-complex.hh
@@ -232,12 +232,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
       return &_hb_ot_complex_shaper_hangul;
 
 
-    /* Unicode-2.0 additions */
-    case HB_SCRIPT_TIBETAN:
-
-      return &_hb_ot_complex_shaper_tibetan;
-
-
     /* Unicode-1.1 additions */
     case HB_SCRIPT_HEBREW:
 
@@ -289,7 +283,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
 
 
     /* Unicode-2.0 additions */
-    //case HB_SCRIPT_TIBETAN:
+    case HB_SCRIPT_TIBETAN:
 
     /* Unicode-3.0 additions */
     //case HB_SCRIPT_MONGOLIAN:
commit 77792187be1405599e6aecfc3ed1fc771d505ddb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 18:20:16 2018 +0200

    [khmer] Remove unused khmer_position()

diff --git a/src/dump-khmer-data.cc b/src/dump-khmer-data.cc
index 12871fa8..1e79a976 100644
--- a/src/dump-khmer-data.cc
+++ b/src/dump-khmer-data.cc
@@ -34,10 +34,8 @@ main (void)
     hb_glyph_info_t info;
     info.codepoint = u;
     set_khmer_properties (info);
-    if (info.khmer_category() != INDIC_SYLLABIC_CATEGORY_OTHER ||
-	info.khmer_position() != INDIC_MATRA_CATEGORY_NOT_APPLICABLE)
-      printf("U+%04X	%u	%u\n", u,
-	     info.khmer_category(),
-	     info.khmer_position());
+    if (info.khmer_category() != INDIC_SYLLABIC_CATEGORY_OTHER)
+      printf("U+%04X	%u\n", u,
+	     info.khmer_category());
   }
 }
diff --git a/src/hb-ot-shape-complex-khmer.hh b/src/hb-ot-shape-complex-khmer.hh
index 4ee0b838..62229458 100644
--- a/src/hb-ot-shape-complex-khmer.hh
+++ b/src/hb-ot-shape-complex-khmer.hh
@@ -34,7 +34,6 @@
 
 /* buffer var allocations */
 #define khmer_category() indic_category() /* khmer_category_t */
-#define khmer_position() indic_position() /* indic_position_t */
 
 
 /* Note: This enum is duplicated in the -machine.rl source file.
commit 5101abd42f4027edf182eddfa58c629b11c2a7f6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 17:49:06 2018 +0200

    [indic/use] Factor common expressions in ragel machine
    
    No machine change.

diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh
index 85db4df5..e2ecfb89 100644
--- a/src/hb-ot-shape-complex-indic-machine.hh
+++ b/src/hb-ot-shape-complex-indic-machine.hh
@@ -911,7 +911,7 @@ static const int indic_syllable_machine_en_main = 138;
 
 
 
-#line 90 "hb-ot-shape-complex-indic-machine.rl"
+#line 92 "hb-ot-shape-complex-indic-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -938,7 +938,7 @@ find_syllables (hb_buffer_t *buffer)
 	act = 0;
 	}
 
-#line 110 "hb-ot-shape-complex-indic-machine.rl"
+#line 112 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
@@ -983,71 +983,71 @@ _eof_trans:
 	{te = p+1;}
 	break;
 	case 14:
-#line 81 "hb-ot-shape-complex-indic-machine.rl"
+#line 83 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (consonant_syllable); }}
 	break;
 	case 16:
-#line 82 "hb-ot-shape-complex-indic-machine.rl"
+#line 84 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (vowel_syllable); }}
 	break;
 	case 21:
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
+#line 85 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (standalone_cluster); }}
 	break;
 	case 24:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
+#line 86 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (symbol_cluster); }}
 	break;
 	case 18:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
+#line 87 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 11:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p+1;{ found_syllable (non_indic_cluster); }}
 	break;
 	case 13:
-#line 81 "hb-ot-shape-complex-indic-machine.rl"
+#line 83 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (consonant_syllable); }}
 	break;
 	case 15:
-#line 82 "hb-ot-shape-complex-indic-machine.rl"
+#line 84 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (vowel_syllable); }}
 	break;
 	case 20:
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
+#line 85 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (standalone_cluster); }}
 	break;
 	case 23:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
+#line 86 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (symbol_cluster); }}
 	break;
 	case 17:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
+#line 87 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 19:
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{te = p;p--;{ found_syllable (non_indic_cluster); }}
 	break;
 	case 1:
-#line 81 "hb-ot-shape-complex-indic-machine.rl"
+#line 83 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
 	break;
 	case 3:
-#line 82 "hb-ot-shape-complex-indic-machine.rl"
+#line 84 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (vowel_syllable); }}
 	break;
 	case 7:
-#line 83 "hb-ot-shape-complex-indic-machine.rl"
+#line 85 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (standalone_cluster); }}
 	break;
 	case 8:
-#line 84 "hb-ot-shape-complex-indic-machine.rl"
+#line 86 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (symbol_cluster); }}
 	break;
 	case 4:
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
+#line 87 "hb-ot-shape-complex-indic-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
 	case 5:
@@ -1068,19 +1068,19 @@ _eof_trans:
 	case 22:
 #line 1 "NONE"
 	{te = p+1;}
-#line 81 "hb-ot-shape-complex-indic-machine.rl"
+#line 83 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 1;}
 	break;
 	case 6:
 #line 1 "NONE"
 	{te = p+1;}
-#line 85 "hb-ot-shape-complex-indic-machine.rl"
+#line 87 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 5;}
 	break;
 	case 12:
 #line 1 "NONE"
 	{te = p+1;}
-#line 86 "hb-ot-shape-complex-indic-machine.rl"
+#line 88 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 6;}
 	break;
 #line 1087 "hb-ot-shape-complex-indic-machine.hh"
@@ -1108,7 +1108,7 @@ _again:
 
 	}
 
-#line 118 "hb-ot-shape-complex-indic-machine.rl"
+#line 120 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index 455938e9..c5d945d4 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -69,12 +69,14 @@ halant_group = (z?.H.(ZWJ.N?)?);
 final_halant_group = halant_group | H.ZWNJ;
 halant_or_matra_group = (final_halant_group | matra_group{0,4});
 
+complex_syllable_tail = (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
 
-consonant_syllable =	(Repha|CS)? cn (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
-vowel_syllable =	reph? V.n? (ZWJ | (halant_group.cn){0,4} halant_or_matra_group syllable_tail);
-standalone_cluster =	((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
+
+consonant_syllable =	(Repha|CS)? cn complex_syllable_tail;
+vowel_syllable =	reph? V.n? (ZWJ | complex_syllable_tail);
+standalone_cluster =	((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? complex_syllable_tail;
 symbol_cluster = 	symbol syllable_tail;
-broken_cluster =	reph? n? (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
+broken_cluster =	reph? n? complex_syllable_tail;
 other =			any;
 
 main := |*
diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh
index ba6c9bf1..e7caca5a 100644
--- a/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/hb-ot-shape-complex-use-machine.hh
@@ -315,7 +315,7 @@ static const int use_syllable_machine_en_main = 4;
 
 
 
-#line 141 "hb-ot-shape-complex-use-machine.rl"
+#line 140 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
@@ -342,7 +342,7 @@ find_syllables (hb_buffer_t *buffer)
 	act = 0;
 	}
 
-#line 161 "hb-ot-shape-complex-use-machine.rl"
+#line 160 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
@@ -387,59 +387,59 @@ _eof_trans:
 	{te = p+1;}
 	break;
 	case 12:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 129 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (independent_cluster); }}
 	break;
 	case 14:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 131 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (standard_cluster); }}
 	break;
 	case 9:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (broken_cluster); }}
 	break;
 	case 8:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
 	{te = p+1;{ found_syllable (non_cluster); }}
 	break;
 	case 11:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 129 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (independent_cluster); }}
 	break;
 	case 15:
-#line 131 "hb-ot-shape-complex-use-machine.rl"
+#line 130 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
 	break;
 	case 13:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 131 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (standard_cluster); }}
 	break;
 	case 17:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
 	break;
 	case 16:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 133 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (numeral_cluster); }}
 	break;
 	case 20:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (symbol_cluster); }}
 	break;
 	case 18:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (broken_cluster); }}
 	break;
 	case 19:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
 	{te = p;p--;{ found_syllable (non_cluster); }}
 	break;
 	case 1:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 131 "hb-ot-shape-complex-use-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (standard_cluster); }}
 	break;
 	case 4:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
 	break;
 	case 2:
@@ -457,13 +457,13 @@ _eof_trans:
 	case 3:
 #line 1 "NONE"
 	{te = p+1;}
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
 	{act = 7;}
 	break;
 	case 10:
 #line 1 "NONE"
 	{te = p+1;}
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
 	{act = 8;}
 	break;
 #line 470 "hb-ot-shape-complex-use-machine.hh"
@@ -491,7 +491,7 @@ _again:
 
 	}
 
-#line 169 "hb-ot-shape-complex-use-machine.rl"
+#line 168 "hb-ot-shape-complex-use-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index 0c9ab078..ddbeef6c 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -97,6 +97,14 @@ dependent_vowels = VPre* VAbv* VBlw* VPst*;
 vowel_modifiers = VMPre* VMAbv* VMBlw* VMPst*;
 final_consonants = FAbv* FBlw* FPst* FM?;
 
+complex_syllable_tail =
+	consonant_modifiers
+	medial_consonants
+	dependent_vowels
+	vowel_modifiers
+	final_consonants
+;
+
 virama_terminated_cluster =
 	(R|CS)? (B | GB) VS?
 	consonant_modifiers
@@ -104,19 +112,11 @@ virama_terminated_cluster =
 ;
 standard_cluster =
 	(R|CS)? (B | GB) VS?
-	consonant_modifiers
-	medial_consonants
-	dependent_vowels
-	vowel_modifiers
-	final_consonants
+	complex_syllable_tail
 ;
 broken_cluster =
 	R?
-	consonant_modifiers
-	medial_consonants
-	dependent_vowels
-	vowel_modifiers
-	final_consonants
+	complex_syllable_tail
 ;
 
 number_joiner_terminated_cluster = N VS? (HN N VS?)* HN;
commit 6f457f8370de5d96452ee3a2d1b0a97b025ef1d1
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 17:46:27 2018 +0200

    [indic] Minor flip grammar around
    
    No behavior change.

diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index bf5c1c8d..455938e9 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -70,7 +70,7 @@ final_halant_group = halant_group | H.ZWNJ;
 halant_or_matra_group = (final_halant_group | matra_group{0,4});
 
 
-consonant_syllable =	(Repha|CS)? (cn.halant_group){0,4} cn halant_or_matra_group syllable_tail;
+consonant_syllable =	(Repha|CS)? cn (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
 vowel_syllable =	reph? V.n? (ZWJ | (halant_group.cn){0,4} halant_or_matra_group syllable_tail);
 standalone_cluster =	((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? (halant_group.cn){0,4} halant_or_matra_group syllable_tail;
 symbol_cluster = 	symbol syllable_tail;
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index df50a3e3..0c9ab078 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -110,7 +110,6 @@ standard_cluster =
 	vowel_modifiers
 	final_consonants
 ;
-
 broken_cluster =
 	R?
 	consonant_modifiers
commit d992982d23ef0c39ea42595ed0e8a4752977d1a5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 17:16:01 2018 +0200

    [indic] Add some confusable sequences from Unicode Standard

diff --git a/test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-leters.txt b/test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-leters.txt
new file mode 100644
index 00000000..f09dbc8f
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-bengali/bengali-vowel-leters.txt
@@ -0,0 +1,3 @@
+আ অা
+ৠ ঋৃ
+ৡ ঌৢ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt
new file mode 100644
index 00000000..42654365
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-atomic-consonants.txt
@@ -0,0 +1,33 @@
+ख ख्ा ख्‍ा
+ग ग्ा ग्‍ा
+घ घ्ा घ्‍ा
+च च्ा च्‍ा
+ज ज्ा ज्‍ा
+झ झ्ा झ्‍ा
+ञ ञ्ा ञ्‍ा
+ण ण्ा ण्‍ा
+त त्ा त्‍ा
+थ थ्ा थ्‍ा
+ध ध्ा ध्‍ा
+न न्ा न्‍ा
+ऩ ऩ्ा ऩ्‍ा ऩ्ा ऩ्‍ा
+प प्ा प्‍ा
+ब ब्ा ब्‍ा
+भ भ्ा भ्‍ा
+म म्ा म्‍ा
+य य्ा य्‍ा
+ल ल्ा ल्‍ा
+व व्ा व्‍ा
+श श्ा श्‍ा
+ष ष्ा ष्‍ा
+स स्ा स्‍ा
+ख़ ख़्ा ख़्‍ा ख़्ा ख़्‍ा
+ग़ ग़्ा ग़्‍ा ग़्ा ग़्‍ा
+ज़ ज़्ा ज़्‍ा ज़्ा ज़्‍ा
+य़ य़्ा य़्‍ा य़्ा य़्‍ा
+ॹ ॹ्ा ॹ्‍ा
+ॺ ॺ्ा ॺ्‍ा
+ज़ ॻ्ा ॻ्‍ा
+ॼ ॼ्ा ॼ्‍ा
+ॾ ॾ्ा ॾ्‍ा
+ॿ ॿ्ा ॿ्‍ा
diff --git a/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt
new file mode 100644
index 00000000..5a41252f
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-devanagari/devanagari-vowel-letters.txt
@@ -0,0 +1,17 @@
+ऄ अॆ
+आ अा
+ई र्इ
+ऊ उु
+ऍ एॅ
+ऎ एॆ
+ऐ एे
+ऑ अॉ आॅ
+ऒ अॊ आॆ
+ओ अो आे
+औ अौ आै
+ॲ अॅ
+ॳ अऺ
+ॴ अऻ आऺ
+ॵ अॏ
+ॶ अॖ
+ॷ अॗ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letter.txt b/test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letter.txt
new file mode 100644
index 00000000..add4332b
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-gujarati/gujarati-vowel-letter.txt
@@ -0,0 +1,8 @@
+આ અા
+ઍ અૅ
+એ અે
+ઐ અૈ
+ઑ અૉ
+ઓ અો અાૅ
+ઔ અૌ અાૈ
+ૉ ૅા
diff --git a/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt
new file mode 100644
index 00000000..b2adaabd
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-gurmukhi/gurmukhi-vowel-letters.txt
@@ -0,0 +1,9 @@
+ਆ ਅਾ
+ਇ ੲਿ
+ਈ ੲੀ
+ਉ ੳੁ
+ਊ ੳੂ
+ਏ ੲੇ
+ਐ ਅੈ
+ਓ ੳੋ
+ਔ ਅੌ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt
new file mode 100644
index 00000000..cc05db93
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-kannada/kannada-vowel-letters.txt
@@ -0,0 +1,3 @@
+ಊ ಉಾ
+ಔ ಒೌ
+ೠ ಋಾ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt
new file mode 100644
index 00000000..061c642f
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-malayalam/malayalam-vowel-letters.txt
@@ -0,0 +1,5 @@
+ഈ ഇൗ
+ഊ ഉൗ
+ഐ എെ
+ഓ ഒാ
+ഔ ഒൗ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt
new file mode 100644
index 00000000..e8d24cb5
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-oriya/oriya-vowel-letters.txt
@@ -0,0 +1,3 @@
+ଆ ଅା
+ଐ ଏୗ
+ଔ ଓୗ
diff --git a/test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt b/test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt
new file mode 100644
index 00000000..c3cfc84c
--- /dev/null
+++ b/test/shaping/texts/in-house/shaper-indic/script-telugu/telugu-vowel-letters.txt
@@ -0,0 +1,5 @@
+ఓ ఒౕ
+ఔ ఒౌ
+ీ ిౕ
+ే ెౕ
+ో ొౕ
commit 40d5d19d5b875eef526a2a66892c3f638f633fa3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Oct 2 17:04:05 2018 +0200

    [ragel] Use ts/te (token-start / token-end) instead of manual tracking

diff --git a/src/hb-ot-shape-complex-indic-machine.hh b/src/hb-ot-shape-complex-indic-machine.hh
index 6a19bfb3..85db4df5 100644
--- a/src/hb-ot-shape-complex-indic-machine.hh
+++ b/src/hb-ot-shape-complex-indic-machine.hh
@@ -916,10 +916,9 @@ static const int indic_syllable_machine_en_main = 138;
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -927,11 +926,11 @@ static const int indic_syllable_machine_en_main = 138;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 935 "hb-ot-shape-complex-indic-machine.hh"
+#line 934 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	cs = indic_syllable_machine_start;
 	ts = 0;
@@ -939,16 +938,15 @@ find_syllables (hb_buffer_t *buffer)
 	act = 0;
 	}
 
-#line 111 "hb-ot-shape-complex-indic-machine.rl"
+#line 110 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 952 "hb-ot-shape-complex-indic-machine.hh"
+#line 950 "hb-ot-shape-complex-indic-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -962,7 +960,7 @@ _resume:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 966 "hb-ot-shape-complex-indic-machine.hh"
+#line 964 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1085,7 +1083,7 @@ _eof_trans:
 #line 86 "hb-ot-shape-complex-indic-machine.rl"
 	{act = 6;}
 	break;
-#line 1089 "hb-ot-shape-complex-indic-machine.hh"
+#line 1087 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 _again:
@@ -1094,7 +1092,7 @@ _again:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 1098 "hb-ot-shape-complex-indic-machine.hh"
+#line 1096 "hb-ot-shape-complex-indic-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -1110,7 +1108,7 @@ _again:
 
 	}
 
-#line 120 "hb-ot-shape-complex-indic-machine.rl"
+#line 118 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-indic-machine.rl b/src/hb-ot-shape-complex-indic-machine.rl
index 5c5fece3..bf5c1c8d 100644
--- a/src/hb-ot-shape-complex-indic-machine.rl
+++ b/src/hb-ot-shape-complex-indic-machine.rl
@@ -91,10 +91,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -102,7 +101,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -113,7 +112,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-khmer-machine.hh b/src/hb-ot-shape-complex-khmer-machine.hh
index d013456b..2bc8ca65 100644
--- a/src/hb-ot-shape-complex-khmer-machine.hh
+++ b/src/hb-ot-shape-complex-khmer-machine.hh
@@ -232,10 +232,9 @@ static const int khmer_syllable_machine_en_main = 22;
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -243,11 +242,11 @@ static const int khmer_syllable_machine_en_main = 22;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 251 "hb-ot-shape-complex-khmer-machine.hh"
+#line 250 "hb-ot-shape-complex-khmer-machine.hh"
 	{
 	cs = khmer_syllable_machine_start;
 	ts = 0;
@@ -255,16 +254,15 @@ find_syllables (hb_buffer_t *buffer)
 	act = 0;
 	}
 
-#line 101 "hb-ot-shape-complex-khmer-machine.rl"
+#line 100 "hb-ot-shape-complex-khmer-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 268 "hb-ot-shape-complex-khmer-machine.hh"
+#line 266 "hb-ot-shape-complex-khmer-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -278,7 +276,7 @@ _resume:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 282 "hb-ot-shape-complex-khmer-machine.hh"
+#line 280 "hb-ot-shape-complex-khmer-machine.hh"
 	}
 
 	_keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -348,7 +346,7 @@ _eof_trans:
 #line 76 "hb-ot-shape-complex-khmer-machine.rl"
 	{act = 3;}
 	break;
-#line 352 "hb-ot-shape-complex-khmer-machine.hh"
+#line 350 "hb-ot-shape-complex-khmer-machine.hh"
 	}
 
 _again:
@@ -357,7 +355,7 @@ _again:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 361 "hb-ot-shape-complex-khmer-machine.hh"
+#line 359 "hb-ot-shape-complex-khmer-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -373,7 +371,7 @@ _again:
 
 	}
 
-#line 110 "hb-ot-shape-complex-khmer-machine.rl"
+#line 108 "hb-ot-shape-complex-khmer-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-khmer-machine.rl b/src/hb-ot-shape-complex-khmer-machine.rl
index eb9f6988..4c596ab6 100644
--- a/src/hb-ot-shape-complex-khmer-machine.rl
+++ b/src/hb-ot-shape-complex-khmer-machine.rl
@@ -81,10 +81,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -92,7 +91,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -103,7 +102,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-myanmar-machine.hh b/src/hb-ot-shape-complex-myanmar-machine.hh
index 7fa23517..0c19e4f6 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.hh
+++ b/src/hb-ot-shape-complex-myanmar-machine.hh
@@ -283,10 +283,9 @@ static const int myanmar_syllable_machine_en_main = 0;
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -294,11 +293,11 @@ static const int myanmar_syllable_machine_en_main = 0;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 302 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 301 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	cs = myanmar_syllable_machine_start;
 	ts = 0;
@@ -306,16 +305,15 @@ find_syllables (hb_buffer_t *buffer)
 	act = 0;
 	}
 
-#line 115 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 319 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 317 "hb-ot-shape-complex-myanmar-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -329,7 +327,7 @@ _resume:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 333 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 331 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -379,7 +377,7 @@ _eof_trans:
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
 	break;
-#line 383 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 381 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 _again:
@@ -388,7 +386,7 @@ _again:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 392 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 390 "hb-ot-shape-complex-myanmar-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -404,7 +402,7 @@ _again:
 
 	}
 
-#line 124 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-myanmar-machine.rl b/src/hb-ot-shape-complex-myanmar-machine.rl
index 62f51d1e..7845a86d 100644
--- a/src/hb-ot-shape-complex-myanmar-machine.rl
+++ b/src/hb-ot-shape-complex-myanmar-machine.rl
@@ -95,10 +95,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -106,7 +105,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -117,7 +116,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;
diff --git a/src/hb-ot-shape-complex-use-machine.hh b/src/hb-ot-shape-complex-use-machine.hh
index 77ca3aeb..ba6c9bf1 100644
--- a/src/hb-ot-shape-complex-use-machine.hh
+++ b/src/hb-ot-shape-complex-use-machine.hh
@@ -320,10 +320,9 @@ static const int use_syllable_machine_en_main = 4;
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -331,11 +330,11 @@ static const int use_syllable_machine_en_main = 4;
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   
-#line 339 "hb-ot-shape-complex-use-machine.hh"
+#line 338 "hb-ot-shape-complex-use-machine.hh"
 	{
 	cs = use_syllable_machine_start;
 	ts = 0;
@@ -343,16 +342,15 @@ find_syllables (hb_buffer_t *buffer)
 	act = 0;
 	}
 
-#line 162 "hb-ot-shape-complex-use-machine.rl"
+#line 161 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   
-#line 356 "hb-ot-shape-complex-use-machine.hh"
+#line 354 "hb-ot-shape-complex-use-machine.hh"
 	{
 	int _slen;
 	int _trans;
@@ -366,7 +364,7 @@ _resume:
 #line 1 "NONE"
 	{ts = p;}
 	break;
-#line 370 "hb-ot-shape-complex-use-machine.hh"
+#line 368 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -468,7 +466,7 @@ _eof_trans:
 #line 137 "hb-ot-shape-complex-use-machine.rl"
 	{act = 8;}
 	break;
-#line 472 "hb-ot-shape-complex-use-machine.hh"
+#line 470 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 _again:
@@ -477,7 +475,7 @@ _again:
 #line 1 "NONE"
 	{ts = 0;}
 	break;
-#line 481 "hb-ot-shape-complex-use-machine.hh"
+#line 479 "hb-ot-shape-complex-use-machine.hh"
 	}
 
 	if ( ++p != pe )
@@ -493,7 +491,7 @@ _again:
 
 	}
 
-#line 171 "hb-ot-shape-complex-use-machine.rl"
+#line 169 "hb-ot-shape-complex-use-machine.rl"
 
 }
 
diff --git a/src/hb-ot-shape-complex-use-machine.rl b/src/hb-ot-shape-complex-use-machine.rl
index a233b120..df50a3e3 100644
--- a/src/hb-ot-shape-complex-use-machine.rl
+++ b/src/hb-ot-shape-complex-use-machine.rl
@@ -142,10 +142,9 @@ main := |*
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -153,7 +152,7 @@ main := |*
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
   %%{
@@ -164,7 +163,6 @@ find_syllables (hb_buffer_t *buffer)
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
   %%{
     write exec;


More information about the HarfBuzz mailing list