[Indic] Lookup consonant position in the font
authorBehdad Esfahbod <behdad@behdad.org>
Thu, 19 Jul 2012 20:20:21 +0000 (16:20 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 19 Jul 2012 20:20:21 +0000 (16:20 -0400)
Fixes most failures of Oriya, and improves others a bit.

src/hb-ot-map-private.hh
src/hb-ot-shape-complex-indic-private.hh
src/hb-ot-shape-complex-indic.cc

index 3811206..d098c75 100644 (file)
@@ -50,17 +50,22 @@ struct hb_ot_map_t
 
   inline hb_mask_t get_global_mask (void) const { return global_mask; }
 
-  inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
-    const feature_map_t *map = features.bsearch (&tag);
+  inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = NULL) const {
+    const feature_map_t *map = features.bsearch (&feature_tag);
     if (shift) *shift = map ? map->shift : 0;
     return map ? map->mask : 0;
   }
 
-  inline hb_mask_t get_1_mask (hb_tag_t tag) const {
-    const feature_map_t *map = features.bsearch (&tag);
+  inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const {
+    const feature_map_t *map = features.bsearch (&feature_tag);
     return map ? map->_1_mask : 0;
   }
 
+  inline hb_mask_t get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
+    const feature_map_t *map = features.bsearch (&feature_tag);
+    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  }
+
   inline hb_tag_t get_chosen_script (unsigned int table_index) const
   { return chosen_script[table_index]; }
 
index e64213b..bbf5484 100644 (file)
@@ -164,111 +164,6 @@ enum indic_matra_category_t {
 
 #include "hb-ot-shape-complex-indic-table.hh"
 
-/* XXX
- * This is a hack for now.  We should:
- * 1. Move this data into the main Indic table,
- * and/or
- * 2. Probe font lookups to determine consonant positions.
- */
-static const struct consonant_position_t {
-  hb_codepoint_t u;
-  indic_position_t position;
-} consonant_positions[] = {
-  {0x0930, POS_BELOW_C},
-  {0x09AC, POS_BELOW_C},
-  {0x09AF, POS_POST_C},
-  {0x09B0, POS_BELOW_C},
-  {0x09F0, POS_BELOW_C},
-  {0x0A2F, POS_POST_C},
-  {0x0A30, POS_BELOW_C},
-  {0x0A35, POS_BELOW_C},
-  {0x0A39, POS_BELOW_C},
-  {0x0AB0, POS_BELOW_C},
-  {0x0B24, POS_BELOW_C},
-  {0x0B28, POS_BELOW_C},
-  {0x0B2C, POS_BELOW_C},
-  {0x0B2D, POS_BELOW_C},
-  {0x0B2E, POS_BELOW_C},
-  {0x0B2F, POS_POST_C},
-  {0x0B30, POS_BELOW_C},
-  {0x0B32, POS_BELOW_C},
-  {0x0B33, POS_BELOW_C},
-  {0x0B5F, POS_POST_C},
-  {0x0B71, POS_BELOW_C},
-  {0x0C15, POS_BELOW_C},
-  {0x0C16, POS_BELOW_C},
-  {0x0C17, POS_BELOW_C},
-  {0x0C18, POS_BELOW_C},
-  {0x0C19, POS_BELOW_C},
-  {0x0C1A, POS_BELOW_C},
-  {0x0C1B, POS_BELOW_C},
-  {0x0C1C, POS_BELOW_C},
-  {0x0C1D, POS_BELOW_C},
-  {0x0C1E, POS_BELOW_C},
-  {0x0C1F, POS_BELOW_C},
-  {0x0C20, POS_BELOW_C},
-  {0x0C21, POS_BELOW_C},
-  {0x0C22, POS_BELOW_C},
-  {0x0C23, POS_BELOW_C},
-  {0x0C24, POS_BELOW_C},
-  {0x0C25, POS_BELOW_C},
-  {0x0C26, POS_BELOW_C},
-  {0x0C27, POS_BELOW_C},
-  {0x0C28, POS_BELOW_C},
-  {0x0C2A, POS_BELOW_C},
-  {0x0C2B, POS_BELOW_C},
-  {0x0C2C, POS_BELOW_C},
-  {0x0C2D, POS_BELOW_C},
-  {0x0C2E, POS_BELOW_C},
-  {0x0C2F, POS_BELOW_C},
-  {0x0C30, POS_BELOW_C},
-  {0x0C32, POS_BELOW_C},
-  {0x0C33, POS_BELOW_C},
-  {0x0C35, POS_BELOW_C},
-  {0x0C36, POS_BELOW_C},
-  {0x0C37, POS_BELOW_C},
-  {0x0C38, POS_BELOW_C},
-  {0x0C39, POS_BELOW_C},
-  {0x0C95, POS_BELOW_C},
-  {0x0C96, POS_BELOW_C},
-  {0x0C97, POS_BELOW_C},
-  {0x0C98, POS_BELOW_C},
-  {0x0C99, POS_BELOW_C},
-  {0x0C9A, POS_BELOW_C},
-  {0x0C9B, POS_BELOW_C},
-  {0x0C9C, POS_BELOW_C},
-  {0x0C9D, POS_BELOW_C},
-  {0x0C9E, POS_BELOW_C},
-  {0x0C9F, POS_BELOW_C},
-  {0x0CA0, POS_BELOW_C},
-  {0x0CA1, POS_BELOW_C},
-  {0x0CA2, POS_BELOW_C},
-  {0x0CA3, POS_BELOW_C},
-  {0x0CA4, POS_BELOW_C},
-  {0x0CA5, POS_BELOW_C},
-  {0x0CA6, POS_BELOW_C},
-  {0x0CA7, POS_BELOW_C},
-  {0x0CA8, POS_BELOW_C},
-  {0x0CAA, POS_BELOW_C},
-  {0x0CAB, POS_BELOW_C},
-  {0x0CAC, POS_BELOW_C},
-  {0x0CAD, POS_BELOW_C},
-  {0x0CAE, POS_BELOW_C},
-  {0x0CAF, POS_BELOW_C},
-  {0x0CB0, POS_BELOW_C},
-  {0x0CB2, POS_BELOW_C},
-  {0x0CB3, POS_BELOW_C},
-  {0x0CB5, POS_BELOW_C},
-  {0x0CB6, POS_BELOW_C},
-  {0x0CB7, POS_BELOW_C},
-  {0x0CB8, POS_BELOW_C},
-  {0x0CB9, POS_BELOW_C},
-  {0x0CDE, POS_BELOW_C},
-  {0x0D2F, POS_POST_C},
-  {0x0D30, POS_POST_C},
-  {0x0D32, POS_BELOW_C},
-  {0x0D35, POS_POST_C},
-};
 
 /* XXX
  * This is a hack for now.  We should move this data into the main Indic table.
index 4254d73..ea40100 100644 (file)
@@ -87,21 +87,48 @@ compare_codepoint (const void *pa, const void *pb)
   return a < b ? -1 : a == b ? 0 : +1;
 }
 
-static indic_position_t
-consonant_position (hb_codepoint_t u)
+static bool
+would_substitute (hb_codepoint_t *glyphs, unsigned int glyphs_count,
+                 hb_tag_t feature_tag, hb_ot_map_t *map, hb_face_t *face)
 {
-  consonant_position_t *record;
-
-  /* Khmer does not have pre-base half forms. */
-  if (0x1780 <= u && u <= 0x17FF)
-    return POS_BELOW_C;
-
-  record = (consonant_position_t *) bsearch (&u, consonant_positions,
-                                            ARRAY_LENGTH (consonant_positions),
-                                            sizeof (consonant_positions[0]),
-                                            compare_codepoint);
+  unsigned int lookup_indices[32];
+  unsigned int offset, len;
+
+  offset = 0;
+  do {
+    len = ARRAY_LENGTH (lookup_indices);
+    hb_ot_layout_feature_get_lookup_indexes (face, HB_OT_TAG_GSUB,
+                                            map->get_feature_index (0/*GSUB*/, feature_tag),
+                                            offset,
+                                            &len,
+                                            lookup_indices);
+
+    for (unsigned int i = 0; i < len; i++)
+      if (hb_ot_layout_would_substitute_lookup (face, glyphs, glyphs_count, lookup_indices[i]))
+       return true;
+
+    offset += len;
+  } while (len == ARRAY_LENGTH (lookup_indices));
+
+  return false;
+}
 
-  return record ? record->position : POS_BASE_C;
+static indic_position_t
+consonant_position (hb_codepoint_t u, hb_ot_map_t *map, hb_font_t *font)
+{
+  hb_codepoint_t virama = (u & ~0x007F) | 0x004D;
+  if ((u & ~0x007F) == 0x0D80) virama = 0x0DCA; /* Sinahla */
+  if ((u & ~0x007F) == 0x1780) virama = 0x17D2; /* Khmer */
+  hb_codepoint_t glyphs[2];
+
+  hb_font_get_glyph (font, virama, 0, &glyphs[0]);
+  hb_font_get_glyph (font, u,      0, &glyphs[1]);
+
+  hb_face_t *face = hb_font_get_face (font);
+  if (would_substitute (glyphs, ARRAY_LENGTH (glyphs), HB_TAG('p','r','e','f'), map, face)) return POS_BELOW_C;
+  if (would_substitute (glyphs, ARRAY_LENGTH (glyphs), HB_TAG('b','l','w','f'), map, face)) return POS_BELOW_C;
+  if (would_substitute (glyphs, ARRAY_LENGTH (glyphs), HB_TAG('p','s','t','f'), map, face)) return POS_POST_C;
+  return POS_BASE_C;
 }
 
 #define MATRA_POS_LEFT(u)      POS_PRE_M
@@ -193,7 +220,7 @@ is_halant_or_coeng (const hb_glyph_info_t &info)
 }
 
 static inline void
-set_indic_properties (hb_glyph_info_t &info)
+set_indic_properties (hb_glyph_info_t &info, hb_ot_map_t *map, hb_font_t *font)
 {
   hb_codepoint_t u = info.codepoint;
   unsigned int type = get_indic_categories (u);
@@ -247,7 +274,7 @@ set_indic_properties (hb_glyph_info_t &info)
 
   if ((FLAG (cat) & CONSONANT_FLAGS))
   {
-    pos = consonant_position (u);
+    pos = consonant_position (u, map, font);
     if (is_ra (u))
       cat = OT_Ra;
   }
@@ -380,9 +407,9 @@ _hb_ot_shape_complex_normalization_preference_indic (void)
 
 
 void
-_hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map HB_UNUSED,
+_hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map,
                                        hb_buffer_t *buffer,
-                                       hb_font_t *font HB_UNUSED)
+                                       hb_font_t *font)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, indic_category);
   HB_BUFFER_ALLOCATE_VAR (buffer, indic_position);
@@ -392,7 +419,7 @@ _hb_ot_shape_complex_setup_masks_indic (hb_ot_map_t *map HB_UNUSED,
 
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
-    set_indic_properties (buffer->info[i]);
+    set_indic_properties (buffer->info[i], map, font);
 }
 
 static int