diff --git a/src/Makefile.am b/src/Makefile.am
index 4908876bb..a542ee7c5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -50,8 +50,9 @@ HBSOURCES += \
 	hb-ot-map.cc \
 	hb-ot-map-private.hh \
 	hb-ot-shape.cc \
+	hb-ot-shape-complex-arabic.cc \
+	hb-ot-shape-complex-private.hh \
 	hb-ot-shape-private.hh \
-	hb-ot-shape-arabic.cc \
 	hb-ot-tag.c \
 	$(NULL)
 HBHEADERS += \
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 0c05742c0..8e65f49ea 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -96,7 +96,7 @@ struct hb_ot_map_t {
   { add_feature (tag, 1, global); }
 
   HB_INTERNAL void compile (hb_face_t *face,
-			    hb_segment_properties_t *props);
+			    const hb_segment_properties_t *props);
 
   hb_mask_t get_global_mask (void) const { return global_mask; }
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 22056242f..ea11faf39 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -61,7 +61,7 @@ hb_ot_map_t::add_lookups (hb_face_t    *face,
 
 void
 hb_ot_map_t::compile (hb_face_t *face,
-		      hb_segment_properties_t *props)
+		      const hb_segment_properties_t *props)
 {
  global_mask = 0;
  lookup_count[0] = lookup_count[1] = 0;
diff --git a/src/hb-ot-shape-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
similarity index 98%
rename from src/hb-ot-shape-arabic.cc
rename to src/hb-ot-shape-complex-arabic.cc
index fb5182be1..5e6ce053e 100644
--- a/src/hb-ot-shape-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -669,6 +669,15 @@ static const struct arabic_state_table_entry {
 };
 
 
+
+void
+_hb_ot_shape_complex_collect_features_arabic	(hb_ot_shape_plan_t *plan, const hb_segment_properties_t  *props)
+{
+  unsigned int num_features = props->script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
+  for (unsigned int i = 0; i < num_features; i++)
+    plan->map.add_bool_feature (arabic_syriac_features[i], false);
+}
+
 void
 _hb_ot_analyze_complex_arabic (hb_ot_shape_context_t *c)
 {
diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh
new file mode 100644
index 000000000..1c605bbcc
--- /dev/null
+++ b/src/hb-ot-shape-complex-private.hh
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010  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
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
+#define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
+
+#include "hb-private.h"
+
+#include "hb-ot-map-private.hh"
+
+HB_BEGIN_DECLS
+
+
+enum hb_ot_complex_shaper_t {
+  hb_ot_complex_shaper_none,
+  hb_ot_complex_shaper_arabic
+};
+
+
+struct hb_ot_shape_plan_t
+{
+  hb_ot_map_t map;
+  hb_ot_complex_shaper_t shaper;
+};
+
+
+static inline hb_ot_complex_shaper_t
+hb_ot_shape_complex_categorize (const hb_segment_properties_t *props)
+{
+  switch ((int) props->script) {
+    case HB_SCRIPT_ARABIC:
+    case HB_SCRIPT_NKO:
+    case HB_SCRIPT_SYRIAC:
+      return hb_ot_complex_shaper_arabic;
+
+    default:
+      return hb_ot_complex_shaper_none;
+  }
+}
+
+
+
+/*
+ * collect_features()
+ *
+ * Called during planning.  Shapers should call plan->map.add_feature().
+ */
+
+HB_INTERNAL void _hb_ot_shape_complex_collect_features_arabic	(hb_ot_shape_plan_t *plan, const hb_segment_properties_t  *props);
+
+static inline void
+hb_ot_shape_complex_collect_features (hb_ot_shape_plan_t *plan,
+				      const hb_segment_properties_t  *props)
+{
+  switch (plan->shaper) {
+    case hb_ot_complex_shaper_arabic:	_hb_ot_shape_complex_collect_features_arabic (plan, props);	return;
+    case hb_ot_complex_shaper_none:	default:							return;
+  }
+}
+
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh
index de1cb3b45..aea52af73 100644
--- a/src/hb-ot-shape-private.hh
+++ b/src/hb-ot-shape-private.hh
@@ -31,21 +31,11 @@
 
 #include "hb-ot-shape.h"
 
+#include "hb-ot-shape-complex-private.hh"
 #include "hb-ot-map-private.hh"
 
 HB_BEGIN_DECLS
 
-enum hb_ot_complex_shaper_t {
-  hb_ot_complex_shaper_none,
-  hb_ot_complex_shaper_arabic
-};
-
-struct hb_ot_shape_plan_t
-{
-  hb_ot_map_t map;
-  hb_ot_complex_shaper_t shaper;
-};
-
 struct hb_ot_shape_context_t
 {
   /* Input to hb_ot_shape() */
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 061c203d2..b6acb2218 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -48,7 +48,7 @@ hb_tag_t default_features[] = {
 
 static void
 hb_ot_shape_collect_features (hb_ot_shape_plan_t       *plan,
-			      hb_segment_properties_t  *props,
+			      const hb_segment_properties_t  *props,
 			      const hb_feature_t       *user_features,
 			      unsigned int              num_user_features)
 {
@@ -70,7 +70,7 @@ hb_ot_shape_collect_features (hb_ot_shape_plan_t       *plan,
   for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
     plan->map.add_bool_feature (default_features[i]);
 
-  /* complex */
+  hb_ot_shape_complex_collect_features (plan, props);
 
   for (unsigned int i = 0; i < num_user_features; i++) {
     const hb_feature_t *feature = &user_features[i];
@@ -321,10 +321,12 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c)
 void
 hb_ot_shape_plan_internal (hb_ot_shape_plan_t       *plan,
 			   hb_face_t                *face,
-			   hb_segment_properties_t  *props,
+			   const hb_segment_properties_t  *props,
 			   const hb_feature_t       *user_features,
 			   unsigned int              num_user_features)
 {
+  plan->shaper = hb_ot_shape_complex_categorize (props);
+
   hb_ot_shape_collect_features (plan, props, user_features, num_user_features);
 
   plan->map.compile (face, props);