[HarfBuzz] New release?

Jonathan Kew jfkthame at googlemail.com
Wed Jan 2 14:03:39 PST 2013


On 2/1/13 21:45, Behdad Esfahbod wrote:
> On 13-01-02 05:20 AM, Khaled Hosny wrote:
>> Hi Behdad,
>>
>> Any estimates for when next HarfBuzz will be released? (for integrating
>> new XeTeX into TeX Live).
>
> Just ask!  I'll roll one today.  I'll see if I can fix the issues Jonathan
> reported first.
>


FWIW, here's the patch I've been using for now to handle the problem of 
(incorrectly) using the global empty set as a "throwaway" destination 
for collecting glyph sets. This (in addition to the other fixes I've 
posted) has allowed me to experiment with the collect_glyphs feature, 
though it hasn't had a huge amount of testing yet so there may still be 
additional places where checks are needed.

JK

-------------- next part --------------
diff --git a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
--- a/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh
@@ -139,17 +139,17 @@ struct RangeRecord
   }
 
   inline bool intersects (const hb_set_t *glyphs) const {
     return glyphs->intersects (start, end);
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const {
-    glyphs->add_range (start, end);
+    if (glyphs) glyphs->add_range (start, end);
   }
 
   GlyphID	start;		/* First GlyphID in the range */
   GlyphID	end;		/* Last GlyphID in the range */
   USHORT	value;		/* Value */
   public:
   DEFINE_SIZE_STATIC (6);
 };
@@ -855,20 +855,22 @@ struct Coverage
     case 1: return u.format1.intersects_coverage (glyphs, index);
     case 2: return u.format2.intersects_coverage (glyphs, index);
     default:return false;
     }
   }
 
   template <typename set_t>
   inline void add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: u.format1.add_coverage (glyphs); break;
-    case 2: u.format2.add_coverage (glyphs); break;
-    default:                                 break;
+    if (glyphs) {
+      switch (u.format) {
+      case 1: u.format1.add_coverage (glyphs); break;
+      case 2: u.format2.add_coverage (glyphs); break;
+      default:                                 break;
+      }
     }
   }
 
   struct Iter {
     Iter (void) : format (0) {};
     inline void init (const Coverage &c_) {
       format = c_.u.format;
       switch (format) {
@@ -1031,20 +1033,22 @@ struct ClassDef
     switch (u.format) {
     case 1: return TRACE_RETURN (u.format1.sanitize (c));
     case 2: return TRACE_RETURN (u.format2.sanitize (c));
     default:return TRACE_RETURN (true);
     }
   }
 
   inline void add_class (hb_set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: u.format1.add_class (glyphs, klass); return;
-    case 2: u.format2.add_class (glyphs, klass); return;
-    default:return;
+    if (glyphs) {
+      switch (u.format) {
+      case 1: u.format1.add_class (glyphs, klass); return;
+      case 2: u.format2.add_class (glyphs, klass); return;
+      default:return;
+      }
     }
   }
 
   inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
     switch (u.format) {
     case 1: return u.format1.intersects_class (glyphs, klass);
     case 2: return u.format2.intersects_class (glyphs, klass);
     default:return false;
diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
--- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -559,26 +559,28 @@ struct PairValueRecord
 struct PairSet
 {
   friend struct PairPosFormat1;
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c,
 			      const ValueFormat *valueFormats) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    unsigned int len1 = valueFormats[0].get_len ();
-    unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
+    if (c->input) {
+      unsigned int len1 = valueFormats[0].get_len ();
+      unsigned int len2 = valueFormats[1].get_len ();
+      unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record = CastP<PairValueRecord> (array);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      c->input->add (record->secondGlyph);
-      record = &StructAtOffset<PairValueRecord> (record, record_size);
+      const PairValueRecord *record = CastP<PairValueRecord> (array);
+      unsigned int count = len;
+      for (unsigned int i = 0; i < count; i++)
+      {
+        c->input->add (record->secondGlyph);
+        record = &StructAtOffset<PairValueRecord> (record, record_size);
+      }
     }
   }
 
   inline bool apply (hb_apply_context_t *c,
 		     const ValueFormat *valueFormats,
 		     unsigned int pos) const
   {
     TRACE_APPLY (this);
@@ -700,25 +702,27 @@ struct PairPosFormat2
 {
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     /* (this+coverage).add_coverage (c->input); // Don't need this. */
 
     /* TODO only add values for pairs that have nonzero adjustments. */
 
-    unsigned int count1 = class1Count;
-    const ClassDef &klass1 = this+classDef1;
-    for (unsigned int i = 0; i < count1; i++)
-      klass1.add_class (c->input, i);
+    if (c->input) {
+      unsigned int count1 = class1Count;
+      const ClassDef &klass1 = this+classDef1;
+      for (unsigned int i = 0; i < count1; i++)
+        klass1.add_class (c->input, i);
 
-    unsigned int count2 = class2Count;
-    const ClassDef &klass2 = this+classDef2;
-    for (unsigned int i = 0; i < count2; i++)
-      klass2.add_class (c->input, i);
+      unsigned int count2 = class2Count;
+      const ClassDef &klass2 = this+classDef2;
+      for (unsigned int i = 0; i < count2; i++)
+        klass2.add_class (c->input, i);
+    }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool apply (hb_apply_context_t *c) const
diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
--- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -49,18 +49,18 @@ struct SingleSubstFormat1
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
       hb_codepoint_t glyph_id = iter.get_glyph ();
-      c->input->add (glyph_id);
-      c->output->add ((glyph_id + deltaGlyphID) & 0xFFFF);
+      if (c->input) c->input->add (glyph_id);
+      if (c->output) c->output->add ((glyph_id + deltaGlyphID) & 0xFFFF);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
@@ -125,18 +125,18 @@ struct SingleSubstFormat2
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
-      c->input->add (iter.get_glyph ());
-      c->output->add (substitute[iter.get_coverage ()]);
+      if (c->input) c->input->add (iter.get_glyph ());
+      if (c->output) c->output->add (substitute[iter.get_coverage ()]);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
@@ -257,19 +257,21 @@ struct Sequence
     unsigned int count = substitute.len;
     for (unsigned int i = 0; i < count; i++)
       c->glyphs->add (substitute[i]);
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    unsigned int count = substitute.len;
-    for (unsigned int i = 0; i < count; i++)
-      c->output->add (substitute[i]);
+    if (c->output) {
+      unsigned int count = substitute.len;
+      for (unsigned int i = 0; i < count; i++)
+        c->output->add (substitute[i]);
+    }
   }
 
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     if (unlikely (!substitute.len)) return TRACE_RETURN (false);
 
     unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
@@ -446,21 +448,22 @@ struct AlternateSubstFormat1
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
-      c->input->add (iter.get_glyph ());
+      if (c->input) c->input->add (iter.get_glyph ());
       const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
       unsigned int count = alt_set.len;
-      for (unsigned int i = 0; i < count; i++)
-	c->output->add (alt_set[i]);
+      if (c->output)
+        for (unsigned int i = 0; i < count; i++)
+	  c->output->add (alt_set[i]);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
@@ -589,19 +592,20 @@ struct Ligature
         return;
     c->glyphs->add (ligGlyph);
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     unsigned int count = component.len;
-    for (unsigned int i = 1; i < count; i++)
-      c->input->add (component[i]);
-    c->output->add (ligGlyph);
+    if (c->input)
+      for (unsigned int i = 1; i < count; i++)
+        c->input->add (component[i]);
+    if (c->output) c->output->add (ligGlyph);
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     if (c->len != component.len)
       return TRACE_RETURN (false);
 
@@ -762,17 +766,17 @@ struct LigatureSubstFormat1
     }
   }
 
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     Coverage::Iter iter;
     for (iter.init (this+coverage); iter.more (); iter.next ()) {
-      c->input->add (iter.get_glyph ());
+      if (c->input) c->input->add (iter.get_glyph ());
       (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
     }
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
@@ -940,18 +944,19 @@ struct ReverseChainSingleSubstFormat1
       (this+backtrack[i]).add_coverage (c->before);
 
     count = lookahead.len;
     for (unsigned int i = 0; i < count; i++)
       (this+lookahead[i]).add_coverage (c->after);
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
     count = substitute.len;
-    for (unsigned int i = 0; i < count; i++)
-      c->output->add (substitute[i]);
+    if (c->output)
+      for (unsigned int i = 0; i < count; i++)
+        c->output->add (substitute[i]);
   }
 
   inline const Coverage &get_coverage (void) const
   {
     return this+coverage;
   }
 
   inline bool would_apply (hb_would_apply_context_t *c) const
diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
--- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh
@@ -161,17 +161,17 @@ struct hb_collect_glyphs_context_t
      * glyphs in the recursion.  If output is not requested, we can go home now. */
 
     if (output == hb_set_get_empty ())
       return HB_VOID;
 
     hb_set_t *old_before = before;
     hb_set_t *old_input  = input;
     hb_set_t *old_after  = after;
-    before = input = after = hb_set_get_empty ();
+    before = input = after = NULL;
 
     nesting_level_left--;
     recurse_func (this, lookup_index);
     nesting_level_left++;
 
     before = old_before;
     input  = old_input;
     after  = old_after;
@@ -190,20 +190,20 @@ struct hb_collect_glyphs_context_t
 
   hb_collect_glyphs_context_t (hb_face_t *face_,
 			       hb_set_t  *glyphs_before, /* OUT. May be NULL */
 			       hb_set_t  *glyphs_input,  /* OUT. May be NULL */
 			       hb_set_t  *glyphs_after,  /* OUT. May be NULL */
 			       hb_set_t  *glyphs_output, /* OUT. May be NULL */
 			       unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
 			      face (face_),
-			      before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
-			      input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
-			      after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
-			      output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
+			      before (glyphs_before),
+			      input  (glyphs_input),
+			      after  (glyphs_after),
+			      output (glyphs_output),
 			      recurse_func (NULL),
 			      nesting_level_left (nesting_level_left_),
 			      debug_depth (0) {}
 
   void set_recurse_func (recurse_func_t func) { recurse_func = func; }
 };
 
 
@@ -551,18 +551,19 @@ static inline void collect_coverage (hb_
 }
 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
 				  hb_set_t *glyphs,
 				  unsigned int count,
 				  const USHORT values[],
 				  collect_glyphs_func_t collect_func,
 				  const void *collect_data)
 {
-  for (unsigned int i = 0; i < count; i++)
-    collect_func (glyphs, values[i], collect_data);
+  if (glyphs)
+    for (unsigned int i = 0; i < count; i++)
+      collect_func (glyphs, values[i], collect_data);
 }
 
 
 static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
 {
   return glyph_id == value;
 }
 static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)


More information about the HarfBuzz mailing list