Fix applying default-value for features
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 13 Oct 2010 19:34:50 +0000 (15:34 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 13 Oct 2010 19:34:50 +0000 (15:34 -0400)
Previously if a default global feature was overrided by a non-global
user feature, we were not setting any default mask for the feature,
essentially disabling the feature by default.  Fix that.

TODO
src/hb-ot-map-private.hh
src/hb-ot-map.cc

diff --git a/TODO b/TODO
index efd0a31..0345d4c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,6 @@
 General fixes:
 =============
 
-- Fix feature mask bugs
-
 - Fix tt kern on/off
 
 - Remove hb_internal_glyph_info_t, etc
index 8e65f49..65f57ea 100644 (file)
@@ -47,9 +47,10 @@ struct hb_ot_map_t {
 
   struct feature_info_t {
     hb_tag_t tag;
-    unsigned int value;
-    unsigned int seq;
-    bool global;
+    unsigned int seq; /* sequence#, used for stable sorting only */
+    unsigned int max_value;
+    bool global; /* whether the feature applies value to every glyph in the buffer */
+    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
 
     static int cmp (const feature_info_t *a, const feature_info_t *b)
     { return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
@@ -87,9 +88,10 @@ struct hb_ot_map_t {
   {
     feature_info_t *info = &feature_infos[feature_count++];
     info->tag = tag;
-    info->value = value;
     info->seq = feature_count;
+    info->max_value = value;
     info->global = global;
+    info->default_value = global ? value : 0;
   }
 
   inline void add_bool_feature (hb_tag_t tag, bool global = true)
index 94be14f..8c696f8 100644 (file)
@@ -98,7 +98,8 @@ hb_ot_map_t::compile (hb_face_t *face,
        feature_infos[j] = feature_infos[i];
       else {
        feature_infos[j].global = false;
-       feature_infos[j].value = MAX (feature_infos[j].value, feature_infos[i].value);
+       feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value);
+       /* Inherit default_value from j */
       }
     }
   feature_count = j + 1;
@@ -112,13 +113,13 @@ hb_ot_map_t::compile (hb_face_t *face,
 
     unsigned int bits_needed;
 
-    if (info->global && info->value == 1)
+    if (info->global && info->max_value == 1)
       /* Uses the global bit */
       bits_needed = 0;
     else
-      bits_needed = _hb_bit_storage (info->value);
+      bits_needed = _hb_bit_storage (info->max_value);
 
-    if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
+    if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
       continue; /* Feature disabled, or not enough bits. */
 
 
@@ -140,7 +141,7 @@ hb_ot_map_t::compile (hb_face_t *face,
     map->tag = info->tag;
     map->index[0] = feature_index[0];
     map->index[1] = feature_index[1];
-    if (info->global && info->value == 1) {
+    if (info->global && info->max_value == 1) {
       /* Uses the global bit */
       map->shift = 0;
       map->mask = 1;
@@ -149,7 +150,7 @@ hb_ot_map_t::compile (hb_face_t *face,
       map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
       next_bit += bits_needed;
       if (info->global)
-       global_mask |= map->mask;
+       global_mask |= ((info->default_value << map->shift) & map->mask);
     }
 
   }