[HarfBuzz] harfbuzz: Branch 'master' - 11 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu May 23 12:55:30 PDT 2013


 src/hb-icu-le.cc                           |    2 
 src/hb-icu-le/PortableFontInstance.cpp     |   23 +-
 src/hb-icu-le/PortableFontInstance.h       |    9 +
 src/hb-ot-layout-gpos-table.hh             |   40 +----
 src/hb-ot-layout-gsub-table.hh             |  108 +++++++------
 src/hb-ot-layout-gsubgpos-private.hh       |  176 ++++++++++++++++++++++
 src/hb-ot-layout-private.hh                |   47 ++++--
 src/hb-ot-layout.cc                        |  224 ++++++++++++++++++++++-------
 src/hb-ot-map-private.hh                   |    7 
 src/hb-ot-map.cc                           |   43 -----
 src/hb-ot-shape-complex-arabic-fallback.hh |   15 +
 src/hb-ot-shape-fallback.cc                |    3 
 12 files changed, 487 insertions(+), 210 deletions(-)

New commits:
commit fb502a22787f4110472771ef771619342e64577a
Merge: b9408d2 9d9e72e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 23 15:54:52 2013 -0400

    Merge commit '9d9e72e94e7914f82ce62a304e7242f79c13edaf'

commit b9408d24f3029f5287b17779235b1c750ff5158a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 23 15:43:02 2013 -0400

    [icu_le] Fix scaling
    
    Seems to work...

diff --git a/src/hb-icu-le.cc b/src/hb-icu-le.cc
index c05d330..350f5c6 100644
--- a/src/hb-icu-le.cc
+++ b/src/hb-icu-le.cc
@@ -63,6 +63,8 @@ _hb_icu_le_shaper_font_data_create (hb_font_t *font)
 {
   LEErrorCode status = LE_NO_ERROR;
   hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face,
+								 1,
+								 1,
 								 font->x_scale,
 								 font->y_scale,
 								 status);
diff --git a/src/hb-icu-le/PortableFontInstance.cpp b/src/hb-icu-le/PortableFontInstance.cpp
index c38e2b1..9d423c4 100644
--- a/src/hb-icu-le/PortableFontInstance.cpp
+++ b/src/hb-icu-le/PortableFontInstance.cpp
@@ -25,8 +25,16 @@
 #include <string.h>
 
 
-PortableFontInstance::PortableFontInstance(hb_face_t *face, float xScale, float yScale, LEErrorCode &status)
-    : fFace(face), fXScale(xScale), fYScale(yScale), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0),
+PortableFontInstance::PortableFontInstance(hb_face_t *face,
+					   float xScale,
+					   float yScale,
+					   unsigned int xPixelsPerEM,
+					   unsigned int yPixelsPerEM,
+					   LEErrorCode &status)
+    : fFace(face),
+      fXScale(xScale), fYScale(yScale),
+      fXPixelsPerEM(xPixelsPerEM), fYPixelsPerEM(yPixelsPerEM),
+      fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0),
       fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
 {
     if (LE_FAILURE(status)) {
@@ -194,8 +202,7 @@ void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) co
         index = fNumLongHorMetrics - 1;
     }
 
-    advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
-    advance.fY = 0;
+    transformFunits (SWAPW(fHMTXTable->hMetrics[index].advanceWidth), 0, advance);
 }
 
 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const
@@ -249,20 +256,20 @@ LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const
 
 float PortableFontInstance::getXPixelsPerEm() const
 {
-    return fXScale;
+    return fXPixelsPerEM;
 }
 
 float PortableFontInstance::getYPixelsPerEm() const
 {
-    return fYScale;
+    return fYPixelsPerEM;
 }
 
 float PortableFontInstance::getScaleFactorX() const
 {
-    return 1.0;
+    return fXScale;
 }
 
 float PortableFontInstance::getScaleFactorY() const
 {
-    return 1.0;
+    return fYScale;
 }
diff --git a/src/hb-icu-le/PortableFontInstance.h b/src/hb-icu-le/PortableFontInstance.h
index 0794560..5b92d83 100644
--- a/src/hb-icu-le/PortableFontInstance.h
+++ b/src/hb-icu-le/PortableFontInstance.h
@@ -36,6 +36,8 @@ private:
 
     float     fXScale;
     float     fYScale;
+    unsigned int fXPixelsPerEM;
+    unsigned int fYPixelsPerEM;
     le_int32  fUnitsPerEM;
     le_int32  fAscent;
     le_int32  fDescent;
@@ -59,7 +61,12 @@ protected:
     hb_blob_t *readFontTable(LETag tableTag) const;
 
 public:
-    PortableFontInstance(hb_face_t *face, float xScale, float yScale, LEErrorCode &status);
+    PortableFontInstance(hb_face_t *face,
+			 float xScale,
+			 float yScale,
+			 unsigned int xPixelsPerEM,
+			 unsigned int yPixelsPerEM,
+			 LEErrorCode &status);
 
     virtual ~PortableFontInstance();
 
commit 9d9e72e94e7914f82ce62a304e7242f79c13edaf
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 3 18:10:10 2013 -0400

    [OTLayout] Use is_inplace() when flipping buffers

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 145cf8f..355f51c 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -804,6 +804,8 @@ apply_string (OT::hb_apply_context_t *c,
 	      const hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
+  OT::hb_is_inplace_context_t inplace_c (c->face);
+  bool inplace = lookup.is_inplace (&inplace_c);
 
   if (unlikely (!c->buffer->len || !c->lookup_mask))
     return false;
@@ -826,8 +828,13 @@ apply_string (OT::hb_apply_context_t *c,
       else
 	c->buffer->next_glyph ();
     }
-    if (ret && Proxy::table_index == 0)
+    if (ret)
+    {
+      if (!inplace)
 	c->buffer->swap_buffers ();
+      else
+        assert (!c->buffer->has_separate_output ());
+    }
   }
   else
   {
commit 45f3d980c9503bd94e64f6e3f67f97688347d00c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 3 17:49:44 2013 -0400

    [OTLayout] Merge / templateize apply_string()

diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index e47af07..2cf90b7 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1472,31 +1472,6 @@ struct PosLookup : Lookup
 
   static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
 
-  inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const
-  {
-    bool ret = false;
-
-    if (unlikely (!c->buffer->len || !c->lookup_mask))
-      return false;
-
-    c->set_recurse_func (apply_recurse_func);
-    c->set_lookup (*this);
-
-    c->buffer->idx = 0;
-
-    while (c->buffer->idx < c->buffer->len)
-    {
-      if (digest->may_have (c->buffer->cur().codepoint) &&
-	  (c->buffer->cur().mask & c->lookup_mask) &&
-	  apply_once (c))
-	ret = true;
-      else
-	c->buffer->idx++;
-    }
-
-    return ret;
-  }
-
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 123b17c..6ab1a2b 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1247,54 +1247,6 @@ struct SubstLookup : Lookup
   }
 
   static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
-  inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const
-  {
-    bool ret = false;
-
-    if (unlikely (!c->buffer->len || !c->lookup_mask))
-      return false;
-
-    c->set_recurse_func (apply_recurse_func);
-    c->set_lookup (*this);
-
-    if (likely (!is_reverse ()))
-    {
-      /* in/out forward substitution */
-      c->buffer->clear_output ();
-      c->buffer->idx = 0;
-
-      while (c->buffer->idx < c->buffer->len)
-      {
-	if (digest->may_have (c->buffer->cur().codepoint) &&
-	    (c->buffer->cur().mask & c->lookup_mask) &&
-	    apply_once (c))
-	  ret = true;
-	else
-	  c->buffer->next_glyph ();
-      }
-      if (ret)
-	c->buffer->swap_buffers ();
-    }
-    else
-    {
-      /* in-place backward substitution */
-      c->buffer->remove_output ();
-      c->buffer->idx = c->buffer->len - 1;
-      do
-      {
-	if (digest->may_have (c->buffer->cur().codepoint) &&
-	    (c->buffer->cur().mask & c->lookup_mask) &&
-	    apply_once (c))
-	  ret = true;
-	else
-	  c->buffer->idx--;
-
-      }
-      while ((int) c->buffer->idx >= 0);
-    }
-
-    return ret;
-  }
 
   inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
 						  unsigned int i)
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index a70f84c..145cf8f 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -2,7 +2,7 @@
  * Copyright © 1998-2004  David Turner and Werner Lemberg
  * Copyright © 2006  Behdad Esfahbod
  * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
+ * Copyright © 2012,2013  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -788,6 +788,69 @@ struct GPOSProxy
 };
 
 
+template <typename Lookup>
+static inline bool apply_once (OT::hb_apply_context_t *c,
+			       const Lookup &lookup)
+{
+  if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
+    return false;
+  return lookup.dispatch (c);
+}
+
+template <typename Proxy>
+static inline bool
+apply_string (OT::hb_apply_context_t *c,
+	      const typename Proxy::Lookup &lookup,
+	      const hb_ot_layout_lookup_accelerator_t &accel)
+{
+  bool ret = false;
+
+  if (unlikely (!c->buffer->len || !c->lookup_mask))
+    return false;
+
+  c->set_lookup (lookup);
+
+  if (likely (!lookup.is_reverse ()))
+  {
+    /* in/out forward substitution/positioning */
+    if (Proxy::table_index == 0)
+      c->buffer->clear_output ();
+    c->buffer->idx = 0;
+
+    while (c->buffer->idx < c->buffer->len)
+    {
+      if (accel.digest.may_have (c->buffer->cur().codepoint) &&
+	  (c->buffer->cur().mask & c->lookup_mask) &&
+	  apply_once (c, lookup))
+	ret = true;
+      else
+	c->buffer->next_glyph ();
+    }
+    if (ret && Proxy::table_index == 0)
+	c->buffer->swap_buffers ();
+  }
+  else
+  {
+    /* in-place backward substitution/positioning */
+    if (Proxy::table_index == 0)
+      c->buffer->remove_output ();
+    c->buffer->idx = c->buffer->len - 1;
+    do
+    {
+      if (accel.digest.may_have (c->buffer->cur().codepoint) &&
+	  (c->buffer->cur().mask & c->lookup_mask) &&
+	  apply_once (c, lookup))
+	ret = true;
+      else
+	c->buffer->idx--;
+
+    }
+    while ((int) c->buffer->idx >= 0);
+  }
+
+  return ret;
+}
+
 template <typename Proxy>
 inline void hb_ot_map_t::apply (const Proxy &proxy,
 				const hb_ot_shape_plan_t *plan,
@@ -797,6 +860,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
   const unsigned int table_index = proxy.table_index;
   unsigned int i = 0;
   OT::hb_apply_context_t c (table_index, font, buffer);
+  c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
 
   for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
     const stage_map_t *stage = &stages[table_index][stage_index];
@@ -805,7 +869,9 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
       unsigned int lookup_index = lookups[table_index][i].index;
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
-      proxy.table.get_lookup (lookup_index).apply_string (&c, &proxy.accels[lookup_index].digest);
+      apply_string<Proxy> (&c,
+			   proxy.table.get_lookup (lookup_index),
+			   proxy.accels[lookup_index]);
     }
 
     if (stage->pause_func)
@@ -833,5 +899,5 @@ hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
 				const OT::SubstLookup &lookup,
 				const hb_ot_layout_lookup_accelerator_t &accel)
 {
-  lookup.apply_string (c, &accel.digest);
+  apply_string<GSUBProxy> (c, lookup, accel);
 }
commit e015b8f2187d1102b9c34d1a63504e7b05ee20ee
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 3 17:34:29 2013 -0400

    [OTLayout] Minor

diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 7e5efa2..e47af07 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1429,6 +1429,11 @@ struct PosLookup : Lookup
   inline const PosLookupSubTable& get_subtable (unsigned int i) const
   { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
 
+  inline bool is_reverse (void) const
+  {
+    return false;
+  }
+
   inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const
   {
     TRACE_IS_INPLACE (this);
commit 780cd930a974165d76dbf7a87701d11b7f15db06
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 3 17:33:16 2013 -0400

    [OTLayout] Minor

diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index a9933d1..7e5efa2 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1435,7 +1435,7 @@ struct PosLookup : Lookup
     return TRACE_RETURN (true);
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const
+  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (NULL);
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index fc37cd9..123b17c 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1208,7 +1208,7 @@ struct SubstLookup : Lookup
     return TRACE_RETURN (dispatch (c));
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const
+  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index d1d63e3..a70f84c 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -614,13 +614,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
     case HB_OT_TAG_GSUB:
     {
       const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
-      l.collect_glyphs_lookup (&c);
+      l.collect_glyphs (&c);
       return;
     }
     case HB_OT_TAG_GPOS:
     {
       const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
-      l.collect_glyphs_lookup (&c);
+      l.collect_glyphs (&c);
       return;
     }
   }
commit 2e0c44f4bedd3e24c731c0e9e23358e9a4891a35
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 24 16:42:05 2013 -0400

    [OTLayout] Add is_inplace() method to GSUB

diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 56b3a4f..a9933d1 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,2012  Google, Inc.
+ * Copyright © 2010,2012,2013  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -1429,6 +1429,12 @@ struct PosLookup : Lookup
   inline const PosLookupSubTable& get_subtable (unsigned int i) const
   { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
 
+  inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    return TRACE_RETURN (true);
+  }
+
   inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 3b6635b..fc37cd9 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,2012  Google, Inc.
+ * Copyright © 2010,2012,2013  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -37,6 +37,12 @@ namespace OT {
 
 struct SingleSubstFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -115,6 +121,12 @@ struct SingleSubstFormat1
 
 struct SingleSubstFormat2
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -251,6 +263,13 @@ struct SingleSubst
 
 struct Sequence
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    /* For len==0 we don't do anything, so it's harmless. */
+    return TRACE_RETURN (substitute.len <= 1);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -315,6 +334,18 @@ struct Sequence
 
 struct MultipleSubstFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    /* Some tools generate MultipleSubst with each substitute having length 1!
+     * So, check them. */
+    unsigned int count = sequence.len;
+    for (unsigned int i = 0; i < count; i++)
+	if (!(this+sequence[i]).is_inplace (c))
+	  return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -440,6 +471,12 @@ typedef ArrayOf<GlyphID> AlternateSet;	/* Array of alternate GlyphIDs--in
 
 struct AlternateSubstFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -760,6 +797,12 @@ struct LigatureSet
 
 struct LigatureSubstFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    return TRACE_RETURN (false);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -908,6 +951,12 @@ struct ExtensionSubst : Extension<ExtensionSubst>
 
 struct ReverseChainSingleSubstFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -1145,6 +1194,13 @@ struct SubstLookup : Lookup
     return lookup_type_is_reverse (type);
   }
 
+  inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    c->set_recurse_func (dispatch_recurse_func<hb_is_inplace_context_t>);
+    return TRACE_RETURN (dispatch (c));
+  }
+
   inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 5169e78..9fc638b 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -44,6 +44,55 @@ namespace OT {
 	 "");
 
 
+
+#ifndef HB_DEBUG_IS_INPLACE
+#define HB_DEBUG_IS_INPLACE (HB_DEBUG+0)
+#endif
+
+#define TRACE_IS_INPLACE(this) \
+	hb_auto_trace_t<HB_DEBUG_IS_INPLACE, bool> trace \
+	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
+	 "");
+
+struct hb_is_inplace_context_t
+{
+  inline const char *get_name (void) { return "IS_INPLACE"; }
+  static const unsigned int max_debug_depth = HB_DEBUG_IS_INPLACE;
+  typedef bool return_t;
+  typedef return_t (*recurse_func_t) (hb_is_inplace_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  inline return_t dispatch (const T &obj) { return obj.is_inplace (this); }
+  static return_t default_return_value (void) { return true; }
+  bool stop_sublookup_iteration (return_t r) const { return !r; }
+
+  return_t recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return default_return_value ();
+
+    nesting_level_left--;
+    bool ret = recurse_func (this, lookup_index);
+    nesting_level_left++;
+    return ret;
+  }
+
+  hb_face_t *face;
+  recurse_func_t recurse_func;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_is_inplace_context_t (hb_face_t *face_,
+			   unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
+			   face (face_),
+			   recurse_func (NULL),
+			   nesting_level_left (nesting_level_left_),
+			   debug_depth (0) {}
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+};
+
+
+
 #ifndef HB_DEBUG_CLOSURE
 #define HB_DEBUG_CLOSURE (HB_DEBUG+0)
 #endif
@@ -1102,6 +1151,17 @@ static inline bool context_apply_lookup (hb_apply_context_t *c,
 
 struct Rule
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
+    unsigned int count = lookupCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (!c->recurse (lookupRecord[i].lookupListIndex))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE (this);
@@ -1161,6 +1221,16 @@ struct Rule
 
 struct RuleSet
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if (!(this+rule[i]).is_inplace (c))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE (this);
@@ -1217,6 +1287,16 @@ struct RuleSet
 
 struct ContextFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+ruleSet[i]).is_inplace (c))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -1303,6 +1383,16 @@ struct ContextFormat1
 
 struct ContextFormat2
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+ruleSet[i]).is_inplace (c))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -1398,6 +1488,17 @@ struct ContextFormat2
 
 struct ContextFormat3
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
+    unsigned int count = lookupCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (!c->recurse (lookupRecord[i].lookupListIndex))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -1639,6 +1740,19 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
 
 struct ChainRule
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
+    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    unsigned int count = lookup.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!c->recurse (lookup.array[i].lookupListIndex))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE (this);
@@ -1724,6 +1838,16 @@ struct ChainRule
 
 struct ChainRuleSet
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if (!(this+rule[i]).is_inplace (c))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   {
     TRACE_CLOSURE (this);
@@ -1777,6 +1901,16 @@ struct ChainRuleSet
 
 struct ChainContextFormat1
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+ruleSet[i]).is_inplace (c))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -1860,6 +1994,16 @@ struct ChainContextFormat1
 
 struct ChainContextFormat2
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+ruleSet[i]).is_inplace (c))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
@@ -1984,6 +2128,20 @@ struct ChainContextFormat2
 
 struct ChainContextFormat3
 {
+  inline bool is_inplace (hb_is_inplace_context_t *c) const
+  {
+    TRACE_IS_INPLACE (this);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+
+    unsigned int count = lookup.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!c->recurse (lookup.array[i].lookupListIndex))
+        return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   inline void closure (hb_closure_context_t *c) const
   {
     TRACE_CLOSURE (this);
commit bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 2 18:52:24 2013 -0400

    [OTLayout] Refactor a bit more

diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 5a5bce3..5169e78 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -278,14 +278,12 @@ struct hb_apply_context_t
 
   hb_apply_context_t (unsigned int table_index_,
 		      hb_font_t *font_,
-		      hb_buffer_t *buffer_,
-		      hb_mask_t lookup_mask_,
-		      bool auto_zwj_) :
+		      hb_buffer_t *buffer_) :
 			table_index (table_index_),
 			font (font_), face (font->face), buffer (buffer_),
 			direction (buffer_->props.direction),
-			lookup_mask (lookup_mask_),
-			auto_zwj (auto_zwj_),
+			lookup_mask (1),
+			auto_zwj (true),
 			recurse_func (NULL),
 			nesting_level_left (MAX_NESTING_LEVEL),
 			lookup_props (0),
@@ -293,6 +291,8 @@ struct hb_apply_context_t
 			has_glyph_classes (gdef.has_glyph_classes ()),
 			debug_depth (0) {}
 
+  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
+  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
   inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
   inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
   inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index bd01078..a9de356 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -202,12 +202,19 @@ HB_INTERNAL void
 hb_ot_layout_substitute_start (hb_font_t    *font,
 			       hb_buffer_t  *buffer);
 
-HB_INTERNAL hb_bool_t
-hb_ot_layout_substitute_lookup (hb_font_t    *font,
-				hb_buffer_t  *buffer,
-				unsigned int  lookup_index,
-				hb_mask_t     mask,
-				hb_bool_t     auto_zwj);
+
+struct hb_ot_layout_lookup_accelerator_t;
+
+namespace OT {
+  struct hb_apply_context_t;
+  struct SubstLookup;
+}
+
+HB_INTERNAL void
+hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
+				const OT::SubstLookup &lookup,
+				const hb_ot_layout_lookup_accelerator_t &accel);
+
 
 /* Should be called after all the substitute_lookup's are done */
 HB_INTERNAL void
@@ -220,13 +227,6 @@ HB_INTERNAL void
 hb_ot_layout_position_start (hb_font_t    *font,
 			     hb_buffer_t  *buffer);
 
-HB_INTERNAL hb_bool_t
-hb_ot_layout_position_lookup (hb_font_t    *font,
-			      hb_buffer_t  *buffer,
-			      unsigned int  lookup_index,
-			      hb_mask_t     mask,
-			      hb_bool_t     auto_zwj);
-
 /* Should be called after all the position_lookup's are done */
 HB_INTERNAL void
 hb_ot_layout_position_finish (hb_font_t    *font,
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index a944a95..d1d63e3 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -669,22 +669,6 @@ hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
   OT::GSUB::substitute_start (font, buffer);
 }
 
-hb_bool_t
-hb_ot_layout_substitute_lookup (hb_font_t    *font,
-				hb_buffer_t  *buffer,
-				unsigned int  lookup_index,
-				hb_mask_t     mask,
-				hb_bool_t     auto_zwj)
-{
-  if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false;
-
-  OT::hb_apply_context_t c (0, font, buffer, mask, auto_zwj);
-
-  const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index);
-
-  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_accels[lookup_index].digest);
-}
-
 void
 hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
 {
@@ -719,22 +703,6 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
   OT::GPOS::position_start (font, buffer);
 }
 
-hb_bool_t
-hb_ot_layout_position_lookup (hb_font_t    *font,
-			      hb_buffer_t  *buffer,
-			      unsigned int  lookup_index,
-			      hb_mask_t     mask,
-			      hb_bool_t     auto_zwj)
-{
-  if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false;
-
-  OT::hb_apply_context_t c (1, font, buffer, mask, auto_zwj);
-
-  const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index);
-
-  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_accels[lookup_index].digest);
-}
-
 void
 hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
 {
@@ -788,35 +756,57 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 
 
 /*
- * Parts of hb-ot-map are implemented here such that they have direct
+ * Parts of different types are implemented here such that they have direct
  * access to GSUB/GPOS lookups.
  */
 
 
-inline void hb_ot_map_t::apply (unsigned int table_index,
+struct GSUBProxy
+{
+  static const unsigned int table_index = 0;
+  typedef OT::SubstLookup Lookup;
+
+  GSUBProxy (hb_face_t *face) :
+    table (*hb_ot_layout_from_face (face)->gsub),
+    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
+
+  const OT::GSUB &table;
+  const hb_ot_layout_lookup_accelerator_t *accels;
+};
+
+struct GPOSProxy
+{
+  static const unsigned int table_index = 1;
+  typedef OT::PosLookup Lookup;
+
+  GPOSProxy (hb_face_t *face) :
+    table (*hb_ot_layout_from_face (face)->gpos),
+    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
+
+  const OT::GPOS &table;
+  const hb_ot_layout_lookup_accelerator_t *accels;
+};
+
+
+template <typename Proxy>
+inline void hb_ot_map_t::apply (const Proxy &proxy,
 				const hb_ot_shape_plan_t *plan,
 				hb_font_t *font,
 				hb_buffer_t *buffer) const
 {
+  const unsigned int table_index = proxy.table_index;
   unsigned int i = 0;
+  OT::hb_apply_context_t c (table_index, font, buffer);
 
   for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
-      switch (table_index)
-      {
-        case 0:
-	  hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index,
-					  lookups[table_index][i].mask,
-					  lookups[table_index][i].auto_zwj);
-	  break;
-
-	case 1:
-	  hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index,
-					lookups[table_index][i].mask,
-					lookups[table_index][i].auto_zwj);
-	  break;
-      }
+    {
+      unsigned int lookup_index = lookups[table_index][i].index;
+      c.set_lookup_mask (lookups[table_index][i].mask);
+      c.set_auto_zwj (lookups[table_index][i].auto_zwj);
+      proxy.table.get_lookup (lookup_index).apply_string (&c, &proxy.accels[lookup_index].digest);
+    }
 
     if (stage->pause_func)
     {
@@ -828,10 +818,20 @@ inline void hb_ot_map_t::apply (unsigned int table_index,
 
 void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
 {
-  apply (0, plan, font, buffer);
+  GSUBProxy proxy (font->face);
+  apply (proxy, plan, font, buffer);
 }
 
 void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
 {
-  apply (1, plan, font, buffer);
+  GPOSProxy proxy (font->face);
+  apply (proxy, plan, font, buffer);
+}
+
+HB_INTERNAL void
+hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
+				const OT::SubstLookup &lookup,
+				const hb_ot_layout_lookup_accelerator_t &accel)
+{
+  lookup.apply_string (c, &accel.digest);
 }
diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh
index 5ed54a6..0e718a6 100644
--- a/src/hb-ot-map-private.hh
+++ b/src/hb-ot-map-private.hh
@@ -118,10 +118,9 @@ struct hb_ot_map_t
   }
 
   HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
-  HB_INTERNAL inline void apply (unsigned int table_index,
-				 const struct hb_ot_shape_plan_t *plan,
-				 hb_font_t *font,
-				 hb_buffer_t *buffer) const;
+  template <typename Proxy>
+  HB_INTERNAL inline void apply (const Proxy &proxy,
+				 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) 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;
 
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index 91d6e44..6b2b87e 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -246,10 +246,13 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
 			    hb_font_t *font,
 			    hb_buffer_t *buffer)
 {
+  OT::hb_apply_context_t c (0, font, buffer);
   for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
     if (fallback_plan->lookup_array[i]) {
-      OT::hb_apply_context_t c (0, font, buffer, fallback_plan->mask_array[i], true/*auto_zwj*/);
-      fallback_plan->lookup_array[i]->apply_string (&c, &fallback_plan->accel_array[i].digest);
+      c.set_lookup_mask (fallback_plan->mask_array[i]);
+      hb_ot_layout_substitute_lookup (&c,
+				      *fallback_plan->lookup_array[i],
+				      fallback_plan->accel_array[i]);
     }
 }
 
diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc
index 3341825..284d030 100644
--- a/src/hb-ot-shape-fallback.cc
+++ b/src/hb-ot-shape-fallback.cc
@@ -420,7 +420,8 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
   hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
 					      HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
 
-  OT::hb_apply_context_t c (1, font, buffer, kern_mask, true/*auto_zwj*/);
+  OT::hb_apply_context_t c (1, font, buffer);
+  c.set_lookup_mask (kern_mask);
   c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
 
   for (buffer->idx = 0; buffer->idx < count;)
commit d2c96819de9a7428b65ef0adf794416224221f36
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 2 18:18:24 2013 -0400

    Move code around

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 76a6256..a944a95 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -34,6 +34,8 @@
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
 
+#include "hb-ot-map-private.hh"
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -783,3 +785,53 @@ hb_ot_layout_get_size_params (hb_face_t    *face,
 
   return false;
 }
+
+
+/*
+ * Parts of hb-ot-map are implemented here such that they have direct
+ * access to GSUB/GPOS lookups.
+ */
+
+
+inline void hb_ot_map_t::apply (unsigned int table_index,
+				const hb_ot_shape_plan_t *plan,
+				hb_font_t *font,
+				hb_buffer_t *buffer) const
+{
+  unsigned int i = 0;
+
+  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
+    const stage_map_t *stage = &stages[table_index][stage_index];
+    for (; i < stage->last_lookup; i++)
+      switch (table_index)
+      {
+        case 0:
+	  hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index,
+					  lookups[table_index][i].mask,
+					  lookups[table_index][i].auto_zwj);
+	  break;
+
+	case 1:
+	  hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index,
+					lookups[table_index][i].mask,
+					lookups[table_index][i].auto_zwj);
+	  break;
+      }
+
+    if (stage->pause_func)
+    {
+      buffer->clear_output ();
+      stage->pause_func (plan, font, buffer);
+    }
+  }
+}
+
+void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
+{
+  apply (0, plan, font, buffer);
+}
+
+void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
+{
+  apply (1, plan, font, buffer);
+}
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index dd26afc..43856fa 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -102,49 +102,6 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
   info->stage[1] = current_stage[1];
 }
 
-inline void hb_ot_map_t::apply (unsigned int table_index,
-				const hb_ot_shape_plan_t *plan,
-				hb_font_t *font,
-				hb_buffer_t *buffer) const
-{
-  unsigned int i = 0;
-
-  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
-    const stage_map_t *stage = &stages[table_index][stage_index];
-    for (; i < stage->last_lookup; i++)
-      switch (table_index)
-      {
-        case 0:
-	  hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index,
-					  lookups[table_index][i].mask,
-					  lookups[table_index][i].auto_zwj);
-	  break;
-
-	case 1:
-	  hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index,
-					lookups[table_index][i].mask,
-					lookups[table_index][i].auto_zwj);
-	  break;
-      }
-
-    if (stage->pause_func)
-    {
-      buffer->clear_output ();
-      stage->pause_func (plan, font, buffer);
-    }
-  }
-}
-
-void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
-{
-  apply (0, plan, font, buffer);
-}
-
-void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
-{
-  apply (1, plan, font, buffer);
-}
-
 
 void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
 {
commit 45fd9424c723f115ca98995b8f8a25185a6fc71d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu May 2 18:06:51 2013 -0400

    [OTLayout] Add hb_ot_layout_lookup_accelerator_t

diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 4866c41..bd01078 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -244,6 +244,23 @@ namespace OT {
   struct GPOS;
 }
 
+struct hb_ot_layout_lookup_accelerator_t
+{
+  template <typename TLookup>
+  inline void init (const TLookup &lookup)
+  {
+    digest.init ();
+    lookup.add_coverage (&digest);
+  }
+
+  template <typename TLookup>
+  inline void fini (const TLookup &lookup)
+  {
+  }
+
+  hb_set_digest_t digest;
+};
+
 struct hb_ot_layout_t
 {
   hb_blob_t *gdef_blob;
@@ -257,8 +274,8 @@ struct hb_ot_layout_t
   unsigned int gsub_lookup_count;
   unsigned int gpos_lookup_count;
 
-  hb_set_digest_t *gsub_digests;
-  hb_set_digest_t *gpos_digests;
+  hb_ot_layout_lookup_accelerator_t *gsub_accels;
+  hb_ot_layout_lookup_accelerator_t *gpos_accels;
 };
 
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index c80ca7d..76a6256 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -59,26 +59,20 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
   layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
 
-  layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_set_digest_t));
-  layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_set_digest_t));
+  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
+  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
 
-  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) ||
-		(layout->gpos_lookup_count && !layout->gpos_digests)))
+  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
+		(layout->gpos_lookup_count && !layout->gpos_accels)))
   {
     _hb_ot_layout_destroy (layout);
     return NULL;
   }
 
   for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-  {
-    layout->gsub_digests[i].init ();
-    layout->gsub->get_lookup (i).add_coverage (&layout->gsub_digests[i]);
-  }
+    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
   for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-  {
-    layout->gpos_digests[i].init ();
-    layout->gpos->get_lookup (i).add_coverage (&layout->gpos_digests[i]);
-  }
+    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
 
   return layout;
 }
@@ -90,8 +84,13 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   hb_blob_destroy (layout->gsub_blob);
   hb_blob_destroy (layout->gpos_blob);
 
-  free (layout->gsub_digests);
-  free (layout->gpos_digests);
+  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
+    layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
+  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
+    layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
+
+  free (layout->gsub_accels);
+  free (layout->gpos_accels);
 
   free (layout);
 }
@@ -659,7 +658,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
 
   const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
 
-  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
+  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest);
 }
 
 void
@@ -681,7 +680,7 @@ hb_ot_layout_substitute_lookup (hb_font_t    *font,
 
   const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index);
 
-  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]);
+  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_accels[lookup_index].digest);
 }
 
 void
@@ -731,7 +730,7 @@ hb_ot_layout_position_lookup (hb_font_t    *font,
 
   const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index);
 
-  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]);
+  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_accels[lookup_index].digest);
 }
 
 void
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index 996e40e..91d6e44 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -199,7 +199,7 @@ struct arabic_fallback_plan_t
 
   hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES];
   OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES];
-  hb_set_digest_t digest_array[ARABIC_NUM_FALLBACK_FEATURES];
+  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES];
 };
 
 static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
@@ -214,12 +214,11 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 
   for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
   {
-    fallback_plan->digest_array[i].init ();
     fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]);
     if (fallback_plan->mask_array[i]) {
       fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i);
       if (fallback_plan->lookup_array[i])
-	fallback_plan->lookup_array[i]->add_coverage (&fallback_plan->digest_array[i]);
+	fallback_plan->accel_array[i].init (*fallback_plan->lookup_array[i]);
     }
   }
 
@@ -234,7 +233,10 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 
   for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
     if (fallback_plan->lookup_array[i])
+    {
+      fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]);
       free (fallback_plan->lookup_array[i]);
+    }
 
   free (fallback_plan);
 }
@@ -247,7 +249,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
   for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
     if (fallback_plan->lookup_array[i]) {
       OT::hb_apply_context_t c (0, font, buffer, fallback_plan->mask_array[i], true/*auto_zwj*/);
-      fallback_plan->lookup_array[i]->apply_string (&c, &fallback_plan->digest_array[i]);
+      fallback_plan->lookup_array[i]->apply_string (&c, &fallback_plan->accel_array[i].digest);
     }
 }
 
commit 76ea563673d24ae1673a5aa3a21da6014479d433
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat May 4 16:01:20 2013 -0400

    [OTLayout] Add note about collect_glyphs() and recursive lookups

diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index f46b378..5a5bce3 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -158,7 +158,13 @@ struct hb_collect_glyphs_context_t
 
     /* Note that GPOS sets recurse_func to NULL already, so it doesn't get
      * past the previous check.  For GSUB, we only want to collect the output
-     * glyphs in the recursion.  If output is not requested, we can go home now. */
+     * glyphs in the recursion.  If output is not requested, we can go home now.
+     *
+     * Note further, that the above is not exactly correct.  A recursed lookup
+     * is allowed to match input that is not matched in the context, but that's
+     * not how most fonts are built.  It's possible to relax that and recurse
+     * with all sets here if it proves to be an issue.
+     */
 
     if (output == hb_set_get_empty ())
       return HB_VOID;



More information about the HarfBuzz mailing list