[HarfBuzz] harfbuzz-ng: Branch 'master' - 6 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Oct 13 12:55:19 PDT 2010


 TODO                              |    4 ++--
 src/hb-buffer.cc                  |    4 ++++
 src/hb-ot-map-private.hh          |   20 ++++++++++++++------
 src/hb-ot-map.cc                  |   14 ++++++++------
 src/hb-ot-shape-complex-arabic.cc |    2 +-
 src/hb-ot-shape.cc                |    6 +++---
 6 files changed, 32 insertions(+), 18 deletions(-)

New commits:
commit 39dede9ffffe732f78cbd092ccb3b48d77ddd66d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 13 15:54:06 2010 -0400

    Make sure boolean features always use value=1
    
    Previously boolean features turned on the entire feature mask.  This is
    wrong if feature is Alternate and user has provided values bigger than one.
    Though, I don't think other engines support such corner cases.

diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 65f57ea..0a1d9f6 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -61,6 +61,7 @@ struct hb_ot_map_t {
     unsigned int index[2]; /* GSUB, GPOS */
     unsigned int shift;
     hb_mask_t mask;
+    hb_mask_t _1_mask; /* mask for value=1, for quick access */
 
     static int cmp (const feature_map_t *a, const feature_map_t *b)
     { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; }
@@ -100,14 +101,19 @@ struct hb_ot_map_t {
   HB_INTERNAL void compile (hb_face_t *face,
 			    const hb_segment_properties_t *props);
 
-  hb_mask_t get_global_mask (void) const { return global_mask; }
+  inline hb_mask_t get_global_mask (void) const { return global_mask; }
 
-  hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
+  inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const {
     const feature_map_t *map = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
     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 = (const feature_map_t *) bsearch (&tag, feature_maps, feature_count, sizeof (feature_maps[0]), (hb_compare_func_t) feature_map_t::cmp);
+    return map ? map->_1_mask : 0;
+  }
+
   inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const {
     for (unsigned int i = 0; i < lookup_count[0]; i++)
       hb_ot_layout_substitute_lookup (face, buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 8c696f8..ca96ba9 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -150,8 +150,9 @@ 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 |= ((info->default_value << map->shift) & map->mask);
+	global_mask |= (info->default_value << map->shift) & map->mask;
     }
+    map->_1_mask = (1 << map->shift) & map->mask;
 
   }
   feature_count = j;
diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc
index 74d7125..4055e36 100644
--- a/src/hb-ot-shape-complex-arabic.cc
+++ b/src/hb-ot-shape-complex-arabic.cc
@@ -706,7 +706,7 @@ _hb_ot_shape_complex_setup_masks_arabic	(hb_ot_shape_context_t *c)
   hb_mask_t mask_array[TOTAL_NUM_FEATURES + 1] = {0};
   unsigned int num_masks = c->buffer->props.script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
   for (unsigned int i = 0; i < num_masks; i++)
-    mask_array[i] = c->plan->map.get_mask (arabic_syriac_features[i]);
+    mask_array[i] = c->plan->map.get_1_mask (arabic_syriac_features[i]);
 
   for (unsigned int i = 0; i < count; i++)
     c->buffer->info[i].mask |= mask_array[c->buffer->info[i].gproperty];
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 16bec61..ee5f796 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -174,7 +174,7 @@ hb_mirror_chars (hb_ot_shape_context_t *c)
   if (HB_DIRECTION_IS_FORWARD (c->buffer->props.direction))
     return;
 
-  hb_mask_t rtlm_mask = c->plan->map.get_mask (HB_TAG ('r','t','l','m'));
+  hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m'));
 
   unsigned int count = c->buffer->len;
   for (unsigned int i = 0; i < count; i++) {
commit 3506b2e78db27e7835bd2c09c053a9807c9cac40
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 13 15:38:52 2010 -0400

    Return early if mask is 0

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index d6e38e9..36a5e13 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -478,6 +478,9 @@ _hb_buffer_add_masks (hb_buffer_t *buffer,
   hb_mask_t not_mask = ~mask;
   value &= mask;
 
+  if (!mask)
+    return;
+
   if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
     unsigned int count = buffer->len;
     for (unsigned int i = 0; i < count; i++)
commit 5c1c8c9c50ddbe66ea595afb245a208b7775b27c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 13 15:36:38 2010 -0400

    Make sure feature values don't leak out of their mask

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 800a34d..d6e38e9 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -476,6 +476,7 @@ _hb_buffer_add_masks (hb_buffer_t *buffer,
 		      unsigned int cluster_end)
 {
   hb_mask_t not_mask = ~mask;
+  value &= mask;
 
   if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
     unsigned int count = buffer->len;
commit 852912fc2db06b6183a2dc87c45ec1b563063572
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 13 15:34:50 2010 -0400

    Fix applying default-value for features
    
    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.

diff --git a/TODO b/TODO
index efd0a31..0345d4c 100644
--- 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
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 8e65f49..65f57ea 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -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)
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 94be14f..8c696f8 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -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);
     }
 
   }
commit 2989be4919242670c94825bded96db20a7b2035b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 13 15:18:29 2010 -0400

    Set user masks after complex masks

diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 0ce3896..16bec61 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -86,6 +86,8 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
   hb_mask_t global_mask = c->plan->map.get_global_mask ();
   c->buffer->reset_masks (global_mask);
 
+  hb_ot_shape_complex_setup_masks (c);
+
   for (unsigned int i = 0; i < c->num_user_features; i++)
   {
     const hb_feature_t *feature = &c->user_features[i];
@@ -95,8 +97,6 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
       c->buffer->add_masks (feature->value << shift, mask, feature->start, feature->end);
     }
   }
-
-  hb_ot_shape_complex_setup_masks (c);
 }
 
 
commit a7820b7b15a809b4a1a4077147ceed7bea528483
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 13 14:20:48 2010 -0400

    Add TODO item

diff --git a/TODO b/TODO
index ffa83c8..efd0a31 100644
--- a/TODO
+++ b/TODO
@@ -9,6 +9,8 @@ General fixes:
 
 - Remove synthesized GDEF
 
+- Remove fixed-size feature/lookup arrays in hb-ot-map
+
 - Use size_t in sanitize
 
 



More information about the HarfBuzz mailing list