Improve shaper selection
authorBehdad Esfahbod <behdad@behdad.org>
Thu, 15 Nov 2012 00:24:05 +0000 (16:24 -0800)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 15 Nov 2012 01:53:09 +0000 (17:53 -0800)
src/hb-ot-map-private.hh
src/hb-ot-map.cc
src/hb-ot-shape-complex-indic.cc
src/hb-ot-shape-complex-private.hh
src/hb-ot-shape-complex-thai.cc

index 11d97e1..c7dbea5 100644 (file)
@@ -115,9 +115,6 @@ struct hb_ot_map_t
     *lookup_count = end - start;
   }
 
-  inline hb_tag_t get_chosen_script (unsigned int table_index) const
-  { return chosen_script[table_index]; }
-
   HB_INTERNAL void substitute_closure (const struct hb_ot_shape_plan_t *plan, hb_face_t *face, hb_set_t *glyphs) const;
   HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
   HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
@@ -130,6 +127,9 @@ struct hb_ot_map_t
     pauses[1].finish ();
   }
 
+  public:
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
 
   private:
 
@@ -140,7 +140,6 @@ struct hb_ot_map_t
 
   hb_mask_t global_mask;
 
-  hb_tag_t chosen_script[2];
   hb_prealloced_array_t<feature_map_t, 8> features;
   hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
   hb_prealloced_array_t<pause_map_t, 1> pauses[2]; /* GSUB/GPOS */
@@ -200,6 +199,7 @@ struct hb_ot_map_builder_t
   hb_segment_properties_t props;
 
   hb_tag_t chosen_script[2];
+  bool found_script[2];
   unsigned int script_index[2], language_index[2];
 
   private:
index 046fa97..024b7df 100644 (file)
@@ -79,7 +79,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
     hb_tag_t table_tag = table_tags[table_index];
-    hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
+    found_script[table_index] = hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
     hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
   }
 }
@@ -161,8 +161,10 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m)
 {
   m.global_mask = 1;
 
-  for (unsigned int table_index = 0; table_index < 2; table_index++)
+  for (unsigned int table_index = 0; table_index < 2; table_index++) {
     m.chosen_script[table_index] = chosen_script[table_index];
+    m.found_script[table_index] = found_script[table_index];
+  }
 
   if (!feature_infos.len)
     return;
index a7f9b60..324a04b 100644 (file)
@@ -329,7 +329,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan)
       break;
     }
 
-  indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.get_chosen_script (0) & 0x000000FF) != '2');
+  indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2');
   indic_plan->virama_glyph = (hb_codepoint_t) -1;
 
   indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'));
index 043e8e3..9f8cecd 100644 (file)
@@ -278,15 +278,18 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
     case HB_SCRIPT_TAKRI:
 
       /* Only use Indic shaper if the font has Indic tables. */
-      if (planner->map.chosen_script[0] == HB_OT_TAG_DEFAULT_SCRIPT)
-       return &_hb_ot_complex_shaper_default;
-      else
+      if (planner->map.found_script[0])
        return &_hb_ot_complex_shaper_indic;
+      else
+       return &_hb_ot_complex_shaper_default;
 
     case HB_SCRIPT_KHMER:
       /* If the font has 'liga', let the generic shaper do it. */
-      if (planner->map.chosen_script[0] == HB_OT_TAG_DEFAULT_SCRIPT ||
-         hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB, planner->map.script_index[0], planner->map.language_index[0], HB_TAG ('l','i','g','a'), NULL))
+      if (!planner->map.found_script[0] ||
+         hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
+                                             planner->map.script_index[0],
+                                             planner->map.language_index[0],
+                                             HB_TAG ('l','i','g','a'), NULL))
        return &_hb_ot_complex_shaper_default;
       else
        return &_hb_ot_complex_shaper_indic;
index d6f4669..0736eca 100644 (file)
 /* Thai / Lao shaper */
 
 static void
-preprocess_text_thai (const hb_ot_shape_plan_t *plan HB_UNUSED,
+do_thai_pua_shaping (const hb_ot_shape_plan_t *plan,
+                    hb_buffer_t              *buffer,
+                    hb_font_t                *font)
+{
+}
+
+static void
+preprocess_text_thai (const hb_ot_shape_plan_t *plan,
                      hb_buffer_t              *buffer,
-                     hb_font_t                *font HB_UNUSED)
+                     hb_font_t                *font)
 {
+  /* This function implements the shaping logic documented here:
+   *
+   *   http://linux.thai.net/~thep/th-otf/shaping.html
+   *
+   * The first shaping rule listed there is needed even if the font has Thai
+   * OpenType tables.  The rest do fallback positioning based on PUA codepoints.
+   * We implement that only if there exist no Thai GSUB in the font.
+   */
+
   /* The following is NOT specified in the MS OT Thai spec, however, it seems
    * to be what Uniscribe and other engines implement.  According to Eric Muller:
    *
@@ -122,6 +138,10 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan HB_UNUSED,
     }
   }
   buffer->swap_buffers ();
+
+  /* If font has Thai GSUB, we are done. */
+  if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0])
+    do_thai_pua_shaping (plan, buffer, font);
 }
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =