Give it a start at GSUB
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 15 Apr 2009 23:50:16 +0000 (19:50 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 15 Apr 2009 23:50:16 +0000 (19:50 -0400)
src/hb-common.h
src/hb-ot-layout-gdef-private.h
src/hb-ot-layout-gsub-private.h
src/hb-ot-layout-open-private.h
src/hb-ot-layout-private.h
src/hb-ot-layout.cc
src/hb-ot-layout.h
src/main.cc

index c60ad84..d404353 100644 (file)
@@ -46,6 +46,9 @@ typedef uint32_t hb_tag_t;
                                ((const char *) s)[2], \
                                ((const char *) s)[3]))
 
-typedef uint16_t hb_glyph_t;
+typedef uint32_t hb_codepoint_t;
+
+/* XXX */
+typedef struct HB_BufferRec_ hb_buffer_t;
 
 #endif /* HB_COMMON_H */
index 447ee0e..5418d8b 100644 (file)
 
 
 #define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \
-  inline const Type& name (hb_glyph_t glyph_id) { \
+  inline const Type& name (hb_codepoint_t glyph) { \
     const Coverage &c = get_coverage (); \
-    hb_ot_layout_coverage_t c_index = c.get_coverage (glyph_id); \
+    hb_ot_layout_coverage_t c_index = c.get_coverage (glyph); \
     return (*this)[c_index]; \
   }
 
 
 struct GlyphClassDef : ClassDef {
-  static const uint16_t BaseGlyph              = 0x0001u;
-  static const uint16_t LigatureGlyph          = 0x0002u;
-  static const uint16_t MarkGlyph              = 0x0003u;
-  static const uint16_t ComponentGlyph         = 0x0004u;
+  static const unsigned int BaseGlyph          = 0x0001u;
+  static const unsigned int LigatureGlyph      = 0x0002u;
+  static const unsigned int MarkGlyph          = 0x0003u;
+  static const unsigned int ComponentGlyph     = 0x0004u;
 };
 
 /*
@@ -72,7 +72,7 @@ struct AttachList {
   friend struct GDEF;
 
   private:
-  /* const AttachPoint& get_attach_points (hb_glyph_t glyph_id); */
+  /* const AttachPoint& get_attach_points (hb_codepoint_t glyph); */
   DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (AttachPoint, get_attach_points);
 
   private:
@@ -205,7 +205,7 @@ struct LigCaretList {
   friend struct GDEF;
 
   private:
-  /* const LigGlyph& get_lig_glyph (hb_glyph_t glyph_id); */
+  /* const LigGlyph& get_lig_glyph (hb_codepoint_t glyph); */
   DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph);
 
   private:
@@ -245,12 +245,12 @@ struct GDEF {
   DEFINE_GET_HAS_ACCESSOR (LigCaretList, lig_caret_list, ligCaretList);
   DEFINE_GET_HAS_ACCESSOR (ClassDef, mark_attachment_types, markAttachClassDef);
 
-  inline hb_ot_layout_class_t get_glyph_class (hb_glyph_t glyph_id) const {
-    return get_glyph_classes ().get_class (glyph_id);
+  inline hb_ot_layout_class_t get_glyph_class (hb_codepoint_t glyph) const {
+    return get_glyph_classes ().get_class (glyph);
   }
 
-  inline hb_ot_layout_class_t get_mark_attachment_type (hb_glyph_t glyph_id) const {
-    return get_mark_attachment_types ().get_class (glyph_id);
+  inline hb_ot_layout_class_t get_mark_attachment_type (hb_codepoint_t glyph) const {
+    return get_mark_attachment_types ().get_class (glyph);
   }
 
   /* TODO get_attach and get_lig_caret */
index 8ce7705..ae41090 100644 (file)
 
 
 struct SingleSubstFormat1 {
-  /* TODO */
+
+  friend struct SingleSubst;
+
+  private:
+  inline bool substitute (hb_ot_layout_t *layout,
+                         hb_buffer_t    *buffer,
+                         unsigned int    context_length,
+                         unsigned int    nesting_level_left) const {
+//    if (get_coverage (IN_CURGLYPH()))
+//      return ;
+  }
 
   private:
   USHORT       substFormat;            /* Format identifier--format = 1 */
@@ -450,6 +460,108 @@ struct ReverseChainSingleSubstFormat1 {
 ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10);
 
 /*
+ * SubstLookup
+ */
+
+struct SubstLookupSubTable {
+  DEFINE_NON_INSTANTIABLE(SubstLookupSubTable);
+
+  friend struct SubstLookup;
+
+  unsigned int get_size (unsigned int lookup_type) const {
+    switch (lookup_type) {
+//    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:
+    */
+    default:return sizeof (LookupSubTable);
+    }
+  }
+
+  inline bool substitute (hb_ot_layout_t *layout,
+                         hb_buffer_t    *buffer,
+                         unsigned int    context_length,
+                         unsigned int    nesting_level_left,
+                         unsigned int    lookup_type) const {
+  }
+
+  private:
+  union {
+  USHORT               substFormat;
+  CoverageFormat1      format1;
+  CoverageFormat2      format2;
+  } u;
+};
+
+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 */
+  inline unsigned int get_effective_type (void) const {
+    unsigned int type = get_type ();
+
+    if (HB_UNLIKELY (type == Extension)) {
+      /* Return lookup type of first extension subtable.
+       * The spec says all of them should have the same type.
+       * XXX check for that somehow */
+//XXX      type = get_subtable(0).v.extension.get_type ();
+    }
+
+    return type;
+  }
+
+  inline bool is_reverse (void) const {
+    switch (get_effective_type ()) {
+    case 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 {
+    unsigned int lookup_type = get_type ();
+
+    if (HB_UNLIKELY (nesting_level_left == 0))
+      return false;
+    nesting_level_left--;
+  
+    for (unsigned int i = 0; i < get_subtable_count (); i++)
+      if (get_subtable (i).substitute (layout, buffer,
+                                      context_length, nesting_level_left,
+                                      lookup_type))
+       return true;
+  
+    return false;
+  }
+};
+DEFINE_NULL_ALIAS (SubstLookup, Lookup);
+
+/*
  * GSUB
  */
 
@@ -458,6 +570,12 @@ struct GSUB : GSUBGPOS {
 
   STATIC_DEFINE_GET_FOR_DATA (GSUB);
   /* XXX check version here? */
+
+  inline const SubstLookup& get_lookup (unsigned int i) const {
+    return *(SubstLookup*)&(((GSUBGPOS *)this)->get_lookup (i));
+  }
+
+
 };
 DEFINE_NULL_ALIAS (GSUB, GSUBGPOS);
 
index 9d45f7c..66fd55e 100644 (file)
@@ -35,6 +35,7 @@
 
 
 #define NO_INDEX               ((unsigned int) 0xFFFF)
+#define NO_CONTEXT             ((unsigned int) -1)
 
 /*
  * Int types
 /* makes class uninstantiable.  should be used for union classes that don't
  * contain any complete type */
 #define DEFINE_NON_INSTANTIABLE(Type) \
-  private: inline Type() {} /* cannot be instantiated */ \
+  protected: inline Type() {} /* cannot be instantiated */ \
   public:
 
 // TODO use a global nul-array for most Null's
 
 
 
+
 /*
  *
  * The OpenType Font File
@@ -642,12 +644,12 @@ struct FeatureList {
 DEFINE_NULL_ASSERT_SIZE (FeatureList, 2);
 
 struct LookupFlag : USHORT {
-  static const uint16_t RightToLeft            = 0x0001u;
-  static const uint16_t IgnoreBaseGlyphs       = 0x0002u;
-  static const uint16_t IgnoreLigatures                = 0x0004u;
-  static const uint16_t IgnoreMarks            = 0x0008u;
-  static const uint16_t Reserved               = 0x00F0u;
-  static const uint16_t MarkAttachmentType     = 0xFF00u;
+  static const unsigned int RightToLeft                = 0x0001u;
+  static const unsigned int IgnoreBaseGlyphs   = 0x0002u;
+  static const unsigned int IgnoreLigatures    = 0x0004u;
+  static const unsigned int IgnoreMarks                = 0x0008u;
+  static const unsigned int Reserved           = 0x00F0u;
+  static const unsigned int MarkAttachmentType = 0xFF00u;
 };
 DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2);
 
@@ -661,8 +663,9 @@ DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2);
 
 
 struct Lookup {
-  /* SubTables, in the desired order */
-  DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);
+  DEFINE_NON_INSTANTIABLE(Lookup);
+
+  DEFINE_ARRAY_INTERFACE (LookupSubTable, subtable);   /* get_subtable_count(), get_subtable(i) */
 
   inline bool is_right_to_left (void) const { return lookupFlag & LookupFlag::RightToLeft; }
   inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
@@ -670,10 +673,14 @@ struct Lookup {
   inline bool ignore_marks     (void) const { return lookupFlag & LookupFlag::IgnoreMarks; }
   inline bool get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; }
 
-  inline uint16_t get_type (void) const { return lookupType; }
-  inline uint16_t get_flag (void) const { return lookupFlag; }
+  inline unsigned int get_type (void) const { return lookupType; }
+  inline unsigned int get_flag (void) const { return lookupFlag; }
 
   private:
+  /* SubTables, in the desired order */
+  DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);
+
+  protected:
   USHORT       lookupType;     /* Different enumerations for GSUB and GPOS */
   USHORT       lookupFlag;     /* Lookup qualifiers */
   USHORT       subTableCount;  /* Number of SubTables for this lookup */
@@ -710,8 +717,10 @@ struct CoverageFormat1 {
   /* GlyphIDs, in sorted numerical order */
   DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);
 
-  inline hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const {
+  inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
     GlyphID gid;
+    if (HB_UNLIKELY (glyph_id > 65535))
+      return -1;
     gid = glyph_id;
     // TODO: bsearch
     for (unsigned int i = 0; i < glyphCount; i++)
@@ -732,7 +741,7 @@ struct CoverageRangeRecord {
   friend struct CoverageFormat2;
 
   private:
-  inline hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const {
+  inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
     if (glyph_id >= start && glyph_id <= end)
       return startCoverageIndex + (glyph_id - start);
     return -1;
@@ -754,7 +763,7 @@ struct CoverageFormat2 {
   /* CoverageRangeRecords, in sorted numerical start order */
   DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
 
-  inline hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const {
+  inline hb_ot_layout_coverage_t 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);
@@ -784,7 +793,7 @@ struct Coverage {
     }
   }
 
-  hb_ot_layout_coverage_t get_coverage (hb_glyph_t glyph_id) const {
+  hb_ot_layout_coverage_t 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);
@@ -813,7 +822,7 @@ struct ClassDefFormat1 {
   /* GlyphIDs, in sorted numerical order */
   DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount);
 
-  inline hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const {
+  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
     if (glyph_id >= startGlyph && glyph_id - startGlyph < glyphCount)
       return classValueArray[glyph_id - startGlyph];
     return 0;
@@ -832,7 +841,7 @@ struct ClassRangeRecord {
   friend struct ClassDefFormat2;
 
   private:
-  inline hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const {
+  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
     if (glyph_id >= start && glyph_id <= end)
       return classValue;
     return 0;
@@ -853,9 +862,9 @@ struct ClassDefFormat2 {
   /* ClassRangeRecords, in sorted numerical start order */
   DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount);
 
-  inline hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const {
+  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
     // TODO: bsearch
-    for (int i = 0; i < rangeCount; i++) {
+    for (unsigned int i = 0; i < rangeCount; i++) {
       int classValue = rangeRecord[i].get_class (glyph_id);
       if (classValue > 0)
         return classValue;
@@ -882,7 +891,7 @@ struct ClassDef {
     }
   }
 
-  hb_ot_layout_class_t get_class (hb_glyph_t glyph_id) const {
+  hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
     switch (u.classFormat) {
     case 1: return u.format1.get_class(glyph_id);
     case 2: return u.format2.get_class(glyph_id);
@@ -949,7 +958,7 @@ DEFINE_NULL_ASSERT_SIZE (Device, 6);
  * GSUB/GPOS Common
  */
 
-typedef struct GSUBGPOS {
+struct GSUBGPOS {
   static const hb_tag_t GSUBTag                = HB_TAG ('G','S','U','B');
   static const hb_tag_t GPOSTag                = HB_TAG ('G','P','O','S');
 
index 8060e4f..a1be8aa 100644 (file)
@@ -53,7 +53,7 @@ _hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout);
 
 HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t
 _hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout,
-                                   hb_glyph_t      glyph);
+                                   hb_codepoint_t  glyph);
 
 HB_OT_LAYOUT_INTERNAL hb_bool_t
 _hb_ot_layout_check_glyph_properties (hb_ot_layout_t                  *layout,
index 1172248..68fd3e5 100644 (file)
@@ -35,6 +35,8 @@
 #include "hb-ot-layout-gdef-private.h"
 #include "hb-ot-layout-gsub-private.h"
 
+/* XXX */
+#include "harfbuzz-buffer-private.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -50,6 +52,7 @@ struct _hb_ot_layout_t {
     unsigned int len;
   } new_gdef;
 
+  /* TODO add max-nesting-level here? */
 };
 
 hb_ot_layout_t *
@@ -109,7 +112,7 @@ _hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout)
 
 HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t
 _hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout,
-                                   hb_glyph_t      glyph)
+                                   hb_codepoint_t  glyph)
 {
   hb_ot_layout_class_t klass;
 
@@ -186,7 +189,7 @@ _hb_ot_layout_check_glyph_properties (hb_ot_layout_t                  *layout,
 
 hb_ot_layout_glyph_class_t
 hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout,
-                             hb_glyph_t      glyph)
+                             hb_codepoint_t  glyph)
 {
   hb_ot_layout_glyph_properties_t properties;
   hb_ot_layout_class_t klass;
@@ -201,7 +204,7 @@ hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout,
 
 void
 hb_ot_layout_set_glyph_class (hb_ot_layout_t             *layout,
-                             hb_glyph_t                  glyph,
+                             hb_codepoint_t              glyph,
                              hb_ot_layout_glyph_class_t  klass)
 {
   /* TODO optimize this, similar to old harfbuzz code for example */
@@ -243,7 +246,7 @@ hb_ot_layout_set_glyph_class (hb_ot_layout_t             *layout,
 void
 hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout,
                                  uint16_t        num_total_glyphs,
-                                 hb_glyph_t     *glyphs,
+                                 hb_codepoint_t *glyphs,
                                  unsigned char  *klasses,
                                  uint16_t        count)
 {
@@ -508,3 +511,55 @@ hb_ot_layout_feature_get_lookup_index (hb_ot_layout_t            *layout,
 
   return f.get_lookup_index (num_lookup);
 }
+
+/*
+ * GSUB
+ */
+
+hb_bool_t
+hb_ot_layout_substitute_lookup (hb_ot_layout_t              *layout,
+                               hb_buffer_t                 *buffer,
+                               unsigned int                 lookup_index,
+                               hb_ot_layout_feature_mask_t  mask)
+{
+  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 ()) {
+
+      /* 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) &&
+           l.substitute (layout, buffer, context_length, nesting_level_left))
+         ret = true;
+       else
+         _hb_buffer_copy_output_glyph (buffer);
+
+      }
+      _hb_buffer_swap (buffer);
+
+  } 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--;
+
+      } while (buffer->in_pos);
+
+  }
+
+  return ret;
+}
index 447dac2..c29485c 100644 (file)
@@ -67,17 +67,17 @@ hb_ot_layout_has_font_glyph_classes (hb_ot_layout_t *layout);
 
 hb_ot_layout_glyph_class_t
 hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout,
-                             hb_glyph_t      glyph);
+                             hb_codepoint_t  glyph);
 
 void
 hb_ot_layout_set_glyph_class (hb_ot_layout_t            *layout,
-                             hb_glyph_t                 glyph,
+                             hb_codepoint_t             glyph,
                              hb_ot_layout_glyph_class_t klass);
 
 void
 hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout,
                                  uint16_t        num_total_glyphs,
-                                 hb_glyph_t     *glyphs,
+                                 hb_codepoint_t *glyphs,
                                  unsigned char  *klasses,
                                  uint16_t        count);
 
@@ -91,6 +91,10 @@ typedef enum {
   HB_OT_LAYOUT_TABLE_TYPE_NONE
 } hb_ot_layout_table_type_t;
 
+typedef uint16_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)
@@ -195,6 +199,25 @@ hb_ot_layout_feature_get_lookup_index (hb_ot_layout_t            *layout,
                                       unsigned int               feature_index,
                                       unsigned int               num_lookup);
 
+/*
+ * GSUB
+ */
+
+hb_bool_t
+hb_ot_layout_substitute_lookup (hb_ot_layout_t              *layout,
+                               hb_buffer_t                 *buffer,
+                               unsigned int                 lookup_index,
+                               hb_ot_layout_feature_mask_t  mask);
+
+
+
+
+
+
+
+
+
+
 
 /*
 #define PANGO_OT_ALL_GLYPHS                    ((guint) 0xFFFF)
index b149e11..4c24ff4 100644 (file)
@@ -125,10 +125,10 @@ main (int argc, char **argv)
                  feature.get_lookup_count());
 
          int num_lookups = feature.get_lookup_count ();
-         printf ("        %d lookup(s) found in language system\n", num_lookups);
+         printf ("        %d lookup(s) found in feature\n", num_lookups);
          for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
            unsigned int lookup_index = feature.get_lookup_index (n_lookup);
-           printf ("        Feature index %2d of %2d: %d\n", n_lookup, num_lookups,
+           printf ("        Lookup index %2d of %2d: %d\n", n_lookup, num_lookups,
                    feature.get_lookup_index (n_lookup));
          }
        }