[pango/harfbuzz-ng: 3/17] [harfbuzz/GSUB] towards a partially working GSUB



commit 25f2af64013f6d88289d526315d2d0c91b77e3a1
Author: Behdad Esfahbod <behdad behdad org>
Date:   Thu Apr 16 04:45:30 2009 -0400

    [harfbuzz/GSUB] towards a partially working GSUB
---
 pango/opentype/harfbuzz-buffer.c           |    2 +-
 pango/opentype/harfbuzz-impl.h             |    2 +-
 pango/opentype/harfbuzz.c                  |    1 -
 pango/opentype/hb-ot-layout-gdef-private.h |    4 +-
 pango/opentype/hb-ot-layout-gsub-private.h |  383 ++++++++++++++++++++-------
 pango/opentype/hb-ot-layout-open-private.h |   31 ++-
 pango/opentype/hb-ot-layout-private.h      |    6 +-
 pango/opentype/hb-ot-layout.cc             |   94 +++++--
 pango/opentype/hb-ot-layout.h              |    2 -
 9 files changed, 381 insertions(+), 144 deletions(-)

diff --git a/pango/opentype/harfbuzz-buffer.c b/pango/opentype/harfbuzz-buffer.c
index 3008c93..1a39dc1 100644
--- a/pango/opentype/harfbuzz-buffer.c
+++ b/pango/opentype/harfbuzz-buffer.c
@@ -59,7 +59,7 @@
 
 /* Internal API */
 
-static HB_Error
+/*static XXX */ HB_Error
 hb_buffer_ensure( HB_Buffer buffer,
 		   HB_UInt   size )
 {
diff --git a/pango/opentype/harfbuzz-impl.h b/pango/opentype/harfbuzz-impl.h
index 29101f8..60508ed 100644
--- a/pango/opentype/harfbuzz-impl.h
+++ b/pango/opentype/harfbuzz-impl.h
@@ -78,7 +78,7 @@ HB_BEGIN_HEADER
 
 
 #define  ALLOC(_ptr,_size)   \
-           ( (_ptr) = _hb_alloc( _size, &error ), error != 0 )
+           ( *(void**)&(_ptr) = _hb_alloc( _size, &error ), error != 0 )
 
 #define  REALLOC(_ptr,_newsz)  \
            ( (_ptr) = _hb_realloc( (_ptr), (_newsz), &error ), error != 0 )
diff --git a/pango/opentype/harfbuzz.c b/pango/opentype/harfbuzz.c
index b7e64bc..a0415f5 100644
--- a/pango/opentype/harfbuzz.c
+++ b/pango/opentype/harfbuzz.c
@@ -24,7 +24,6 @@
 
 #define HB_INTERNAL static
 #include "harfbuzz-buffer.c"
-#include "harfbuzz-gdef.c"
 #include "harfbuzz-gsub.c"
 #include "harfbuzz-gpos.c"
 #include "harfbuzz-impl.c"
diff --git a/pango/opentype/hb-ot-layout-gdef-private.h b/pango/opentype/hb-ot-layout-gdef-private.h
index 5418d8b..7730ac0 100644
--- a/pango/opentype/hb-ot-layout-gdef-private.h
+++ b/pango/opentype/hb-ot-layout-gdef-private.h
@@ -35,7 +35,7 @@
 #define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \
   inline const Type& name (hb_codepoint_t glyph) { \
     const Coverage &c = get_coverage (); \
-    hb_ot_layout_coverage_t c_index = c.get_coverage (glyph); \
+    unsigned int c_index = c.get_coverage (glyph); \
     return (*this)[c_index]; \
   }
 
@@ -209,7 +209,7 @@ struct LigCaretList {
   DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph);
 
   private:
-  /* AttachPoint tables, in Coverage Index order */
+  /* LigGlyph tables, in Coverage Index order */
   DEFINE_OFFSET_ARRAY_TYPE (LigGlyph, ligGlyph, ligGlyphCount);
   DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
 
diff --git a/pango/opentype/hb-ot-layout-gsub-private.h b/pango/opentype/hb-ot-layout-gsub-private.h
index d8c1d8d..968dd4a 100644
--- a/pango/opentype/hb-ot-layout-gsub-private.h
+++ b/pango/opentype/hb-ot-layout-gsub-private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007,2008  Red Hat, Inc.
+ * Copyright (C) 2007,2008,2009  Red Hat, Inc.
  *
  *  This is part of HarfBuzz, an OpenType Layout engine library.
  *
@@ -35,7 +35,7 @@
 #include "harfbuzz-buffer-private.h" /* XXX */
 
 #define DEFINE_GET_GLYPH_COVERAGE(name) \
-  inline hb_ot_layout_coverage_t get_##name (hb_codepoint_t glyph) const { \
+  inline unsigned int get_##name (hb_codepoint_t glyph) const { \
     const Coverage &c = get_coverage (); \
     return c.get_coverage (glyph); \
   }
@@ -46,6 +46,12 @@
 			 unsigned int    context_length, \
 			 unsigned int    nesting_level_left, \
 			 unsigned int    lookup_flag) const
+#define SUBTABLE_SUBSTITUTE_CHAIN(obj) \
+	obj.substitute (layout, \
+			buffer, \
+			context_length, \
+			nesting_level_left, \
+			lookup_flag)
 
 struct SingleSubstFormat1 {
 
@@ -55,47 +61,21 @@ struct SingleSubstFormat1 {
   DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
   DEFINE_GET_GLYPH_COVERAGE (glyph_coverage);
 
-  inline SUBTABLE_SUBSTITUTE {
-    hb_codepoint_t glyph_id;
-    hb_ot_layout_coverage_t index;
-    unsigned int property;
-
-    HB_UNUSED (nesting_level_left);
-
-    if (HB_UNLIKELY (context_length < 1))
-      return false;
+  inline bool single_substitute (hb_codepoint_t &glyph_id) const {
 
-    if (!_hb_ot_layout_check_glyph_property (layout, IN_CURITEM (), lookup_flag, &property))
-      return false;
-
-    glyph_id = IN_CURGLYPH ();
+    unsigned int index;
 
     index = get_glyph_coverage (glyph_id);
-    if (-1 == index)
+    if (NOT_COVERED == index)
       return false;
 
     glyph_id += deltaGlyphID;
-    _hb_buffer_replace_output_glyph (buffer, glyph_id, context_length == NO_CONTEXT);
-
-    if ( _hb_ot_layout_has_new_glyph_classes (layout) )
-    {
-      /* we inherit the old glyph class to the substituted glyph */
-      _hb_ot_layout_set_glyph_property (layout, glyph_id, property);
-    }
 
     return true;
-}
+  }
 
 #if 0
 
-  switch ( ss->SubstFormat )
-  {
-  case 1:
-    value = (IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
-    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
-      return error;
-    break;
-
   case 2:
     if ( index >= ss->ssf.ssf2.GlyphCount )
       return ERR(HB_Err_Invalid_SubTable);
@@ -103,17 +83,6 @@ struct SingleSubstFormat1 {
     if ( REPLACE_Glyph( buffer, value, nesting_level ) )
       return error;
     break;
-
-  default:
-    return ERR(HB_Err_Invalid_SubTable);
-  }
-
-  if ( _hb_ot_layout_has_new_glyph_classes (layout) )
-  {
-    /* we inherit the old glyph class to the substituted glyph */
-
-    hb_ot_layout_set_glyph_class (layout, value, properties);
-  }
 #endif
 
   private:
@@ -126,7 +95,25 @@ struct SingleSubstFormat1 {
 ASSERT_SIZE (SingleSubstFormat1, 6);
 
 struct SingleSubstFormat2 {
-  /* TODO */
+
+  friend struct SingleSubst;
+
+  private:
+  DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
+  DEFINE_GET_GLYPH_COVERAGE (glyph_coverage);
+
+  inline bool single_substitute (hb_codepoint_t &glyph_id) const {
+
+    unsigned int index;
+
+    index = get_glyph_coverage (glyph_id);
+
+    if (index >= glyphCount)
+      return false;
+
+    glyph_id = substitute[index];
+    return true;
+  }
 
   private:
   USHORT	substFormat;		/* Format identifier--format = 2 */
@@ -139,24 +126,75 @@ struct SingleSubstFormat2 {
 };
 ASSERT_SIZE (SingleSubstFormat2, 6);
 
-struct MultipleSubstFormat1 {
-  /* TODO */
+struct SingleSubst {
+
+  friend struct SubstLookupSubTable;
+
+  unsigned int get_size (void) const {
+    switch (u.substFormat) {
+    case 1: return sizeof (u.format1);
+    case 2: return sizeof (u.format2);
+    default:return sizeof (u.substFormat);
+    }
+  }
 
   private:
-  USHORT	substFormat;		/* Format identifier--format = 1 */
-  Offset	coverage;		/* Offset to Coverage table--from
-					 * beginning of Substitution table */
-  USHORT	sequenceCount;		/* Number of Sequence table offsets in
-					 * the Sequence array */
-  Offset	sequence[];		/* Array of offsets to Sequence
-					 * tables--from beginning of
-					 * Substitution table--ordered by
-					 * Coverage Index */
+  inline SUBTABLE_SUBSTITUTE {
+
+    hb_codepoint_t glyph_id;
+    unsigned int property;
+
+    HB_UNUSED (nesting_level_left);
+
+    if (HB_UNLIKELY (context_length < 1))
+      return false;
+
+    if (!_hb_ot_layout_check_glyph_property (layout, IN_CURITEM (), lookup_flag, &property))
+      return false;
+
+    glyph_id = IN_CURGLYPH ();
+
+    switch (u.substFormat) {
+    case 1: if (!u.format1.single_substitute (glyph_id)) return false;
+    case 2: if (!u.format2.single_substitute (glyph_id)) return false;
+    default:return false;
+    }
+
+    _hb_buffer_replace_output_glyph (buffer, glyph_id, context_length == NO_CONTEXT);
+
+    if ( _hb_ot_layout_has_new_glyph_classes (layout) )
+    {
+      /* we inherit the old glyph class to the substituted glyph */
+      _hb_ot_layout_set_glyph_property (layout, glyph_id, property);
+    }
+
+    return true;
+  }
+
+  private:
+  union {
+  USHORT	substFormat;	/* Format identifier */
+  SingleSubstFormat1	format1;
+  SingleSubstFormat2	format2;
+  } u;
 };
-ASSERT_SIZE (MultipleSubstFormat1, 6);
+DEFINE_NULL (SingleSubst, 2);
+
 
 struct Sequence {
-  /* TODO */
+
+  friend struct MultipleSubstFormat1;
+
+  private:
+  /* GlyphID tables, in Coverage Index order */
+  DEFINE_OFFSET_ARRAY_TYPE (GlyphID, substitute, glyphCount);
+
+  inline void set_glyph_class (hb_ot_layout_t *layout, unsigned int property) const {
+    unsigned int n, count = glyphCount;
+
+    for (n = 0; n < count; n++)
+      _hb_ot_layout_set_glyph_property (layout, substitute[n], property);
+  }
 
   private:
   USHORT	glyphCount;		/* Number of GlyphIDs in the Substitute
@@ -166,20 +204,92 @@ struct Sequence {
 };
 DEFINE_NULL_ASSERT_SIZE (Sequence, 2);
 
-struct AlternateSubstFormat1 {
-  /* TODO */
+struct MultipleSubstFormat1 {
+
+  friend struct MultipleSubst;
+
+  private:
+  /* Sequence tables, in Coverage Index order */
+  DEFINE_OFFSET_ARRAY_TYPE (Sequence, sequence, sequenceCount);
+  DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
+  DEFINE_GET_GLYPH_COVERAGE (glyph_coverage);
+
+  inline SUBTABLE_SUBSTITUTE {
+
+    hb_codepoint_t glyph_id;
+    unsigned int index;
+    unsigned int property;
+
+    HB_UNUSED (nesting_level_left);
+
+    if (HB_UNLIKELY (context_length < 1))
+      return false;
+
+    if (!_hb_ot_layout_check_glyph_property (layout, IN_CURITEM (), lookup_flag, &property))
+      return false;
+
+    glyph_id = IN_CURGLYPH ();
+
+    index = get_glyph_coverage (glyph_id);
+    if (index >= sequenceCount)
+      return false;
+
+    const Sequence &seq = (*this)[index];
+    _hb_buffer_add_output_glyph_ids (buffer, 1,
+				     seq.glyphCount, seq.substitute,
+				     0xFFFF, 0xFFFF);
+
+    if ( _hb_ot_layout_has_new_glyph_classes (layout) )
+    {
+      /* this is a guess only ... */
+
+      if ( property == HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
+        property = HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
+
+      seq.set_glyph_class (layout, property);
+    }
+
+    return true;
+  }
 
   private:
   USHORT	substFormat;		/* Format identifier--format = 1 */
   Offset	coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  USHORT	alternateSetCount;	/* Number of AlternateSet tables */
-  Offset	alternateSet[];		/* Array of offsets to AlternateSet
+  USHORT	sequenceCount;		/* Number of Sequence table offsets in
+					 * the Sequence array */
+  Offset	sequence[];		/* Array of offsets to Sequence
 					 * tables--from beginning of
 					 * Substitution table--ordered by
 					 * Coverage Index */
 };
-ASSERT_SIZE (AlternateSubstFormat1, 6);
+ASSERT_SIZE (MultipleSubstFormat1, 6);
+
+struct MultipleSubst {
+
+  unsigned int get_size (void) const {
+    switch (u.substFormat) {
+    case 1: return sizeof (u.format1);
+    default:return sizeof (u.substFormat);
+    }
+  }
+
+  private:
+  inline SUBTABLE_SUBSTITUTE {
+    switch (u.substFormat) {
+    case 1: return SUBTABLE_SUBSTITUTE_CHAIN(u.format1);
+    default:return false;
+    }
+  }
+
+  private:
+  union {
+  USHORT	substFormat;	/* Format identifier */
+  MultipleSubstFormat1	format1;
+  } u;
+};
+DEFINE_NULL (MultipleSubst, 2);
+
 
 struct AlternateSet {
   /* TODO */
@@ -192,20 +302,33 @@ struct AlternateSet {
 };
 DEFINE_NULL_ASSERT_SIZE (AlternateSet, 2);
 
-struct LigatureSubstFormat1 {
+struct AlternateSubstFormat1 {
   /* TODO */
 
   private:
   USHORT	substFormat;		/* Format identifier--format = 1 */
   Offset	coverage;		/* Offset to Coverage table--from
 					 * beginning of Substitution table */
-  USHORT	ligSetCount;		/* Number of LigatureSet tables */
-  Offset	ligatureSet[];		/* Array of offsets to LigatureSet
+  USHORT	alternateSetCount;	/* Number of AlternateSet tables */
+  Offset	alternateSet[];		/* Array of offsets to AlternateSet
 					 * tables--from beginning of
 					 * Substitution table--ordered by
 					 * Coverage Index */
 };
-ASSERT_SIZE (LigatureSubstFormat1, 6);
+ASSERT_SIZE (AlternateSubstFormat1, 6);
+
+
+struct Ligature {
+  /* TODO */
+
+  private:
+  GlyphID	ligGlyph;		/* GlyphID of ligature to substitute */
+  USHORT	compCount;		/* Number of components in the ligature */
+  GlyphID	component[];		/* Array of component GlyphIDs--start
+					 * with the second  component--ordered
+					 * in writing direction */
+};
+DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
 
 struct LigatureSet {
   /* TODO */
@@ -219,17 +342,21 @@ struct LigatureSet {
 };
 DEFINE_NULL_ASSERT_SIZE (LigatureSet, 2);
 
-struct Ligature {
+struct LigatureSubstFormat1 {
   /* TODO */
 
   private:
-  GlyphID	ligGlyph;		/* GlyphID of ligature to substitute */
-  USHORT	compCount;		/* Number of components in the ligature */
-  GlyphID	component[];		/* Array of component GlyphIDs--start
-					 * with the second  component--ordered
-					 * in writing direction */
+  USHORT	substFormat;		/* Format identifier--format = 1 */
+  Offset	coverage;		/* Offset to Coverage table--from
+					 * beginning of Substitution table */
+  USHORT	ligSetCount;		/* Number of LigatureSet tables */
+  Offset	ligatureSet[];		/* Array of offsets to LigatureSet
+					 * tables--from beginning of
+					 * Substitution table--ordered by
+					 * Coverage Index */
 };
-DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
+ASSERT_SIZE (LigatureSubstFormat1, 6);
+
 
 struct SubstLookupRecord {
   /* TODO */
@@ -533,6 +660,17 @@ ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10);
  * SubstLookup
  */
 
+enum {
+  GSUB_Single				= 1,
+  GSUB_Multiple				= 2,
+  GSUB_Alternate				= 3,
+  GSUB_Ligature				= 4,
+  GSUB_Context				= 5,
+  GSUB_ChainingContext			= 6,
+  GSUB_Extension				= 7,
+  GSUB_ReverseChainingContextSingle		= 8,
+};
+
 struct SubstLookupSubTable {
   DEFINE_NON_INSTANTIABLE(SubstLookupSubTable);
 
@@ -543,14 +681,14 @@ struct SubstLookupSubTable {
 //    case 1: return u.format1.get_size ();
 //    case 2: return u.format2.get_size ();
     /*
-    case Single:
-    case Multiple:
-    case Alternate:
-    case Ligature:
-    case Context:
-    case ChainingContext:
-    case Extension:
-    case ReverseChainingContextSingle:
+    case GSUB_Single:
+    case GSUB_Multiple:
+    case GSUB_Alternate:
+    case GSUB_Ligature:
+    case GSUB_Context:
+    case GSUB_ChainingContext:
+    case GSUB_Extension:
+    case GSUB_ReverseChainingContextSingle:
     */
     default:return sizeof (LookupSubTable);
     }
@@ -562,13 +700,25 @@ struct SubstLookupSubTable {
 			  unsigned int    nesting_level_left,
 			  unsigned int    lookup_type,
 			  unsigned int    lookup_flag) const {
+    switch (lookup_type) {
+    case GSUB_Single:	return SUBTABLE_SUBSTITUTE_CHAIN (u.singleSubst);
+    /*
+    case GSUB_Multiple:
+    case GSUB_Alternate:
+    case GSUB_Ligature:
+    case GSUB_Context:
+    case GSUB_ChainingContext:
+    case GSUB_Extension:
+    case GSUB_ReverseChainingContextSingle:
+    */
+    default:return false;
+    }
   }
 
   private:
   union {
   USHORT		substFormat;
-  CoverageFormat1	format1;
-  CoverageFormat2	format2;
+  SingleSubst		singleSubst;
   } u;
 };
 
@@ -576,25 +726,16 @@ struct SubstLookup : Lookup {
 
   DEFINE_NON_INSTANTIABLE(SubstLookup);
 
-  static const unsigned int Single				= 1;
-  static const unsigned int Multiple				= 2;
-  static const unsigned int Alternate				= 3;
-  static const unsigned int Ligature				= 4;
-  static const unsigned int Context				= 5;
-  static const unsigned int ChainingContext			= 6;
-  static const unsigned int Extension				= 7;
-  static const unsigned int ReverseChainingContextSingle	= 8;
-
   inline const SubstLookupSubTable& get_subtable (unsigned int i) const {
     return *(SubstLookupSubTable*)&(((Lookup *)this)->get_subtable (i));
   }
 
   /* Like get_type(), but looks through extension lookups.
-   * Never returns SubstLookup::Extension */
+   * Never returns Extension */
   inline unsigned int get_effective_type (void) const {
     unsigned int type = get_type ();
 
-    if (HB_UNLIKELY (type == Extension)) {
+    if (HB_UNLIKELY (type == GSUB_Extension)) {
       /* Return lookup type of first extension subtable.
        * The spec says all of them should have the same type.
        * XXX check for that somehow */
@@ -606,15 +747,16 @@ struct SubstLookup : Lookup {
 
   inline bool is_reverse (void) const {
     switch (get_effective_type ()) {
-    case ReverseChainingContextSingle:	return true;
-    default:				return false;
+    case GSUB_ReverseChainingContextSingle:	return true;
+    default:					return false;
     }
   }
 
-  inline bool substitute (hb_ot_layout_t *layout,
-			  hb_buffer_t    *buffer,
-			  unsigned int    context_length,
-			  unsigned int    nesting_level_left) const {
+  inline bool substitute_once (hb_ot_layout_t *layout,
+			       hb_buffer_t    *buffer,
+			       unsigned int    context_length,
+			       unsigned int    nesting_level_left) const {
+
     unsigned int lookup_type = get_type ();
     unsigned int lookup_flag = get_flag ();
 
@@ -630,6 +772,47 @@ struct SubstLookup : Lookup {
 
     return false;
   }
+
+  inline bool substitute_string (hb_ot_layout_t *layout,
+				 hb_buffer_t    *buffer,
+				 hb_ot_layout_feature_mask_t mask) const {
+
+    bool ret = false;
+
+    if (!is_reverse ()) {
+
+	/* in/out forward substitution */
+	_hb_buffer_clear_output (buffer);
+	buffer->in_pos = 0;
+	while (buffer->in_pos < buffer->in_length) {
+
+	  if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
+	      substitute_once (layout, buffer, NO_CONTEXT, MAX_NESTING_LEVEL))
+	    ret = true;
+	  else
+	    _hb_buffer_copy_output_glyph (buffer);
+
+	}
+	if (ret)
+	  _hb_buffer_swap (buffer);
+
+    } else {
+
+	/* in-place backward substitution */
+	buffer->in_pos = buffer->in_length - 1;
+	do {
+
+	  if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
+	      substitute_once (layout, buffer, NO_CONTEXT, MAX_NESTING_LEVEL))
+	    ret = true;
+	  else
+	    buffer->in_pos--;
+
+	} while (buffer->in_pos);
+    }
+
+    return ret;
+  }
 };
 DEFINE_NULL_ALIAS (SubstLookup, Lookup);
 
diff --git a/pango/opentype/hb-ot-layout-open-private.h b/pango/opentype/hb-ot-layout-open-private.h
index 4123a43..ecd1c08 100644
--- a/pango/opentype/hb-ot-layout-open-private.h
+++ b/pango/opentype/hb-ot-layout-open-private.h
@@ -36,6 +36,9 @@
 
 #define NO_INDEX		((unsigned int) 0xFFFF)
 #define NO_CONTEXT		((unsigned int) -1)
+#define NOT_COVERED		((unsigned int) -1)
+#define MAX_NESTING_LEVEL	32
+
 
 /*
  * Int types
@@ -717,16 +720,16 @@ struct CoverageFormat1 {
   /* GlyphIDs, in sorted numerical order */
   DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);
 
-  inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
+  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
     GlyphID gid;
     if (HB_UNLIKELY (glyph_id > 65535))
-      return -1;
+      return NOT_COVERED;
     gid = glyph_id;
     // TODO: bsearch
     for (unsigned int i = 0; i < glyphCount; i++)
       if (gid == glyphArray[i])
         return i;
-    return -1;
+    return NOT_COVERED;
   }
 
   private:
@@ -741,10 +744,10 @@ struct CoverageRangeRecord {
   friend struct CoverageFormat2;
 
   private:
-  inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
+  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
     if (glyph_id >= start && glyph_id <= end)
       return startCoverageIndex + (glyph_id - start);
-    return -1;
+    return NOT_COVERED;
   }
 
   private:
@@ -763,14 +766,14 @@ struct CoverageFormat2 {
   /* CoverageRangeRecords, in sorted numerical start order */
   DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
 
-  inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
+  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
     // TODO: bsearch
     for (unsigned int i = 0; i < rangeCount; i++) {
       int coverage = rangeRecord[i].get_coverage (glyph_id);
       if (coverage >= 0)
         return coverage;
     }
-    return -1;
+    return NOT_COVERED;
   }
 
   private:
@@ -793,11 +796,11 @@ struct Coverage {
     }
   }
 
-  hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const {
     switch (u.coverageFormat) {
     case 1: return u.format1.get_coverage(glyph_id);
     case 2: return u.format2.get_coverage(glyph_id);
-    default:return -1;
+    default:return NOT_COVERED;
     }
   }
 
@@ -990,4 +993,14 @@ struct GSUBGPOS {
 };
 DEFINE_NULL_ASSERT_SIZE (GSUBGPOS, 10);
 
+/* XXX */
+#include "harfbuzz-impl.h"
+HB_INTERNAL HB_Error
+_hb_buffer_add_output_glyph_ids( HB_Buffer  buffer,
+			      HB_UShort  num_in,
+			      HB_UShort  num_out,
+			      const GlyphID *glyph_data,
+			      HB_UShort  component,
+			      HB_UShort  ligID );
+
 #endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */
diff --git a/pango/opentype/hb-ot-layout-private.h b/pango/opentype/hb-ot-layout-private.h
index ae728eb..c152edc 100644
--- a/pango/opentype/hb-ot-layout-private.h
+++ b/pango/opentype/hb-ot-layout-private.h
@@ -35,7 +35,6 @@
 
 
 typedef unsigned int hb_ot_layout_class_t;
-typedef int hb_ot_layout_coverage_t;	/* -1 is not covered, >= 0 otherwise */
 
 /* XXX #define HB_OT_LAYOUT_INTERNAL static */
 #define HB_OT_LAYOUT_INTERNAL
@@ -64,6 +63,11 @@ _hb_ot_layout_check_glyph_property (hb_ot_layout_t *layout,
 				    unsigned int    lookup_flags,
 				    unsigned int   *property);
 
+/* XXX */
+HB_Error
+hb_buffer_ensure( HB_Buffer buffer,
+		   HB_UInt   size );
+
 HB_END_DECLS();
 
 #endif /* HB_OT_LAYOUT_PRIVATE_H */
diff --git a/pango/opentype/hb-ot-layout.cc b/pango/opentype/hb-ot-layout.cc
index 5a5e176..6b7d47b 100644
--- a/pango/opentype/hb-ot-layout.cc
+++ b/pango/opentype/hb-ot-layout.cc
@@ -544,42 +544,82 @@ hb_ot_layout_substitute_lookup (hb_ot_layout_t              *layout,
 {
   const GSUB &gsub = *(layout->gsub);
   const SubstLookup &l = gsub.get_lookup (lookup_index);
-  unsigned int lookup_type = l.get_type ();
-  unsigned int nesting_level_left = HB_OT_LAYOUT_MAX_NESTING_LEVEL;
-  unsigned int context_length = NO_CONTEXT;
-  bool handled, ret = false;
 
-  if (!l.is_reverse ()) {
+  return l.substitute_string (layout, buffer, mask);
+}
+
+
+
+/* XXX dupped, until he old code can be removed */
 
-      /* in/out forward substitution */
-      _hb_buffer_clear_output (buffer);
-      buffer->in_pos = 0;
-      while (buffer->in_pos < buffer->in_length) {
+static HB_Error
+hb_buffer_duplicate_out_buffer( HB_Buffer buffer )
+{
+  if ( !buffer->alt_string )
+    {
+      HB_Error error;
+
+      if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )
+	return error;
+    }
 
-	if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
-	    l.substitute (layout, buffer, context_length, nesting_level_left))
-	  ret = true;
-	else
-	  _hb_buffer_copy_output_glyph (buffer);
+  buffer->out_string = buffer->alt_string;
+  memcpy( buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]) );
+  buffer->separate_out = TRUE;
 
-      }
-      _hb_buffer_swap (buffer);
+  return HB_Err_Ok;
+}
 
-  } else {
 
-      /* in-place backward substitution */
-      buffer->in_pos = buffer->in_length - 1;
-      do {
 
-	if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
-	    l.substitute (layout, buffer, context_length, nesting_level_left))
-	  ret = true;
-	else
-	  buffer->in_pos--;
+HB_INTERNAL HB_Error
+_hb_buffer_add_output_glyph_ids( HB_Buffer  buffer,
+			      HB_UShort  num_in,
+			      HB_UShort  num_out,
+			      const GlyphID *glyph_data,
+			      HB_UShort  component,
+			      HB_UShort  ligID )
+{
+  HB_Error  error;
+  HB_UShort i;
+  HB_UInt properties;
+  HB_UInt cluster;
+
+  error = hb_buffer_ensure( buffer, buffer->out_pos + num_out );
+  if ( error )
+    return error;
+
+  if ( !buffer->separate_out )
+    {
+      error = hb_buffer_duplicate_out_buffer( buffer );
+      if ( error )
+	return error;
+    }
 
-      } while (buffer->in_pos);
+  properties = buffer->in_string[buffer->in_pos].properties;
+  cluster = buffer->in_string[buffer->in_pos].cluster;
+  if ( component == 0xFFFF )
+    component = buffer->in_string[buffer->in_pos].component;
+  if ( ligID == 0xFFFF )
+    ligID = buffer->in_string[buffer->in_pos].ligID;
 
+  for ( i = 0; i < num_out; i++ )
+  {
+    HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
+
+    item->gindex = glyph_data[i];
+    item->properties = properties;
+    item->cluster = cluster;
+    item->component = component;
+    item->ligID = ligID;
+    item->gproperty = HB_GLYPH_PROPERTY_UNKNOWN;
   }
 
-  return ret;
+  buffer->in_pos  += num_in;
+  buffer->out_pos += num_out;
+
+  buffer->out_length = buffer->out_pos;
+
+  return HB_Err_Ok;
 }
+
diff --git a/pango/opentype/hb-ot-layout.h b/pango/opentype/hb-ot-layout.h
index a6b9d37..2fc9089 100644
--- a/pango/opentype/hb-ot-layout.h
+++ b/pango/opentype/hb-ot-layout.h
@@ -93,8 +93,6 @@ typedef enum {
 
 typedef uint32_t hb_ot_layout_feature_mask_t;
 
-#define HB_OT_LAYOUT_MAX_NESTING_LEVEL		100
-
 #define HB_OT_LAYOUT_NO_SCRIPT_INDEX		((unsigned int) 0xFFFF)
 #define HB_OT_LAYOUT_NO_FEATURE_INDEX		((unsigned int) 0xFFFF)
 #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX	((unsigned int) 0xFFFF)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]