Do Arabic fallback shaping
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 10 Apr 2012 20:44:38 +0000 (16:44 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 10 Apr 2012 20:44:38 +0000 (16:44 -0400)
src/hb-ot-shape-complex-arabic.cc

index 89d6b53..991f7cf 100644 (file)
@@ -58,8 +58,6 @@ enum {
 
 static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
 {
-  /* TODO Macroize the magic bit operations */
-
   if (likely (hb_in_range<hb_codepoint_t> (u, JOINING_TABLE_FIRST, JOINING_TABLE_LAST))) {
     unsigned int j_type = joining_table[u - JOINING_TABLE_FIRST];
     if (likely (j_type != JOINING_TYPE_X))
@@ -82,6 +80,12 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ
         JOINING_TYPE_T : JOINING_TYPE_U;
 }
 
+static hb_codepoint_t get_arabic_shape (hb_codepoint_t u, unsigned int shape)
+{
+  if (likely (hb_in_range<hb_codepoint_t> (u, SHAPING_TABLE_FIRST, SHAPING_TABLE_LAST)) && shape < 4)
+    return shaping_table[u - SHAPING_TABLE_FIRST][shape];
+  return u;
+}
 
 
 static const hb_tag_t arabic_syriac_features[] =
@@ -189,6 +193,15 @@ _hb_ot_shape_complex_normalization_preference_arabic (void)
   return HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
 }
 
+
+static void
+arabic_fallback_shape (hb_buffer_t *buffer)
+{
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    buffer->info[i].codepoint = get_arabic_shape (buffer->info[i].codepoint, buffer->info[i].arabic_shaping_action());
+}
+
 void
 _hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map, hb_buffer_t *buffer)
 {
@@ -218,12 +231,27 @@ _hb_ot_shape_complex_setup_masks_arabic (hb_ot_map_t *map, hb_buffer_t *buffer)
   }
 
   hb_mask_t mask_array[TOTAL_NUM_FEATURES + 1] = {0};
+  hb_mask_t total_masks = 0;
   unsigned int num_masks = buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
-  for (unsigned int i = 0; i < num_masks; i++)
+  for (unsigned int i = 0; i < num_masks; i++) {
     mask_array[i] = map->get_1_mask (arabic_syriac_features[i]);
+    total_masks |= mask_array[i];
+  }
 
-  for (unsigned int i = 0; i < count; i++)
-    buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()];
+  if (total_masks) {
+    /* Has OpenType tables */
+    for (unsigned int i = 0; i < count; i++)
+      buffer->info[i].mask |= mask_array[buffer->info[i].arabic_shaping_action()];
+  } else if (buffer->props.script == HB_SCRIPT_ARABIC) {
+    /* Fallback Arabic shaping to Presentation Forms */
+    /* Pitfalls:
+     * - This path fires if user force-set init/medi/fina/isol off,
+     * - If font does not declare script 'arab', well, what to do?
+     *   Most probably it's safe to assume that init/medi/fina/isol
+     *   still mean Arabic shaping, although they do not have to.
+     */
+    arabic_fallback_shape (buffer);
+  }
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }