Minor refactoring
diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh
index cc36fa2..c4e7837 100644
--- a/src/hb-ot-map.hh
+++ b/src/hb-ot-map.hh
@@ -166,7 +166,8 @@
   hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
 };
 
-enum hb_ot_map_feature_flags_t {
+enum hb_ot_map_feature_flags_t
+{
   F_NONE		= 0x0000u,
   F_GLOBAL		= 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
   F_HAS_FALLBACK	= 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
@@ -179,6 +180,12 @@
 /* Macro version for where const is desired. */
 #define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
 
+struct hb_ot_map_feature_t
+{
+  hb_tag_t tag;
+  hb_ot_map_feature_flags_t flags;
+};
+
 
 struct hb_ot_map_builder_t
 {
@@ -192,9 +199,15 @@
   HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value,
 				hb_ot_map_feature_flags_t flags);
 
+  inline void add_feature (const hb_ot_map_feature_t &feat)
+  { add_feature (feat.tag, 1, feat.flags); }
+
   inline void add_global_bool_feature (hb_tag_t tag)
   { add_feature (tag, 1, F_GLOBAL); }
 
+  inline void disable_feature (hb_tag_t tag)
+  { add_feature (tag, 0, F_GLOBAL); }
+
   inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
   { add_pause (0, pause_func); }
   inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
diff --git a/src/hb-ot-shape-complex-hangul.cc b/src/hb-ot-shape-complex-hangul.cc
index ea73111..3d8199b 100644
--- a/src/hb-ot-shape-complex-hangul.cc
+++ b/src/hb-ot-shape-complex-hangul.cc
@@ -65,7 +65,7 @@
   /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
    * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
    * in calt, which is not desirable. */
-  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('c','a','l','t'));
 }
 
 struct hangul_shape_plan_t
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc
index c1aa1d0..b541402 100644
--- a/src/hb-ot-shape-complex-indic.cc
+++ b/src/hb-ot-shape-complex-indic.cc
@@ -95,42 +95,36 @@
  * Indic shaper.
  */
 
-struct feature_list_t
-{
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 indic_features[] =
 {
   /*
    * Basic features.
    * These features are applied in order, one at a time, after initial_reordering.
    */
-  {HB_TAG('n','u','k','t'), F_GLOBAL},
-  {HB_TAG('a','k','h','n'), F_GLOBAL},
-  {HB_TAG('r','p','h','f'), F_NONE},
-  {HB_TAG('r','k','r','f'), F_GLOBAL},
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('h','a','l','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('v','a','t','u'), F_GLOBAL},
-  {HB_TAG('c','j','c','t'), F_GLOBAL},
+  {HB_TAG('n','u','k','t'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('a','k','h','n'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('r','p','h','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('r','k','r','f'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('p','r','e','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('b','l','w','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('a','b','v','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('h','a','l','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('p','s','t','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('v','a','t','u'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('c','j','c','t'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
   /*
    * Other features.
    * These features are applied all at once, after final_reordering.
    * Default Bengali font in Windows for example has intermixed
    * lookups for init,pres,abvs,blws features.
    */
-  {HB_TAG('i','n','i','t'), F_NONE},
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  {HB_TAG('h','a','l','n'), F_GLOBAL},
+  {HB_TAG('i','n','i','t'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('p','r','e','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('a','b','v','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('b','l','w','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('p','s','t','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('h','a','l','n'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
   /*
    * Positioning features.
    * We don't care about the types.
@@ -169,7 +163,6 @@
 
   INDIC_NUM_FEATURES,
   INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
-  INDIC_SUBST_FEATURES = _DIST /* Don't forget to update this! */
 };
 
 static void
@@ -207,17 +200,14 @@
   map->add_gsub_pause (initial_reordering);
 
   for (; i < INDIC_BASIC_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
+    map->add_feature (indic_features[i]);
     map->add_gsub_pause (nullptr);
   }
 
   map->add_gsub_pause (final_reordering);
 
-  for (; i < INDIC_SUBST_FEATURES; i++)
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-
   for (; i < INDIC_NUM_FEATURES; i++)
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags);
+    map->add_feature (indic_features[i]);
 
   map->add_global_bool_feature (HB_TAG('c','a','l','t'));
   map->add_global_bool_feature (HB_TAG('c','l','i','g'));
@@ -228,7 +218,7 @@
 static void
 override_features_indic (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc
index 7a88aaa..9987841 100644
--- a/src/hb-ot-shape-complex-khmer.cc
+++ b/src/hb-ot-shape-complex-khmer.cc
@@ -32,32 +32,26 @@
  * Khmer shaper.
  */
 
-struct feature_list_t
-{
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 khmer_features[] =
 {
   /*
    * Basic features.
    * These features are applied in order, one at a time, after reordering.
    */
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('c','f','a','r'), F_NONE},
+  {HB_TAG('p','r','e','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('b','l','w','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('a','b','v','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('p','s','t','f'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('c','f','a','r'), F_NONE   | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
   /*
    * Other features.
    * These features are applied all at once.
    */
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
+  {HB_TAG('p','r','e','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('a','b','v','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('b','l','w','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
+  {HB_TAG('p','s','t','s'), F_GLOBAL | F_MANUAL_ZWJ | F_MANUAL_ZWNJ},
   /*
    * Positioning features.
    * We don't care about the types.
@@ -88,7 +82,6 @@
 
   KHMER_NUM_FEATURES,
   KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */
-  KHMER_SUBST_FEATURES = _DIST, /* Don't forget to update this! */
 };
 
 static void
@@ -128,15 +121,12 @@
 
   unsigned int i = 0;
   for (; i < KHMER_BASIC_FEATURES; i++)
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
+    map->add_feature (khmer_features[i]);
 
   map->add_gsub_pause (clear_syllables);
 
-  for (; i < KHMER_SUBST_FEATURES; i++)
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-
   for (; i < KHMER_NUM_FEATURES; i++)
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags);
+    map->add_feature (khmer_features[i]);
 
   map->add_global_bool_feature (HB_TAG('c','a','l','t'));
   map->add_global_bool_feature (HB_TAG('c','l','i','g'));
@@ -149,10 +139,10 @@
   /* Uniscribe does not apply 'kern' in Khmer. */
   if (hb_options ().uniscribe_bug_compatible)
   {
-    plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL);
+    plan->map.disable_feature (HB_TAG('k','e','r','n'));
   }
 
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc
index 8069e3d..215e705 100644
--- a/src/hb-ot-shape-complex-myanmar.cc
+++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -122,7 +122,7 @@
 static void
 override_features_myanmar (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }