[OT] More serialize. Implements all basic GSUB subtables
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 4 Sep 2012 22:17:57 +0000 (18:17 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Tue, 4 Sep 2012 23:16:09 +0000 (19:16 -0400)
src/hb-open-type-private.hh
src/hb-ot-layout-common-private.hh
src/hb-ot-layout-gsub-table.hh

index 384cdb7..152105b 100644 (file)
@@ -428,6 +428,40 @@ struct hb_serialize_context_t
   bool ran_out_of_room;
 };
 
+template <typename Type>
+struct Supplier
+{
+  /* For automatic wrapping of bare arrays */
+  inline Supplier (const Type *array)
+  {
+    head = array;
+    len = (unsigned int) -1;
+  }
+
+  inline Supplier (const Type *array, unsigned int len_)
+  {
+    head = array;
+    len = len_;
+  }
+  inline const Type operator [] (unsigned int i) const
+  {
+    if (unlikely (i >= len)) return Type ();
+    return head[i];
+  }
+
+  inline void advance (unsigned int count) {
+    if (unlikely (count > len))
+      count = len;
+    len -= count;
+    head += count;
+  }
+
+  private:
+  unsigned int len;
+  const Type *head;
+};
+
+
 
 
 /*
@@ -687,7 +721,7 @@ struct GenericArrayOf
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const Type *items,
+                        Supplier<Type> &items,
                         unsigned int items_len)
   {
     TRACE_SERIALIZE ();
@@ -697,6 +731,7 @@ struct GenericArrayOf
     unsigned int count = items_len;
     for (unsigned int i = 0; i < count; i++)
       array[i].set (items[i]);
+    items.advance (items_len);
     return TRACE_RETURN (true);
   }
 
@@ -803,6 +838,22 @@ struct HeadlessArrayOf
   inline unsigned int get_size (void) const
   { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
 
+  inline bool serialize (hb_serialize_context_t *c,
+                        Supplier<Type> &items,
+                        unsigned int items_len)
+  {
+    TRACE_SERIALIZE ();
+    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    len.set (items_len); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return TRACE_RETURN (false);
+    if (unlikely (!items_len)) return TRACE_RETURN (true);
+    unsigned int count = items_len;
+    for (unsigned int i = 1; i < count; i++)
+      array[i-1].set (items[i]);
+    items.advance (items_len - 1);
+    return TRACE_RETURN (true);
+  }
+
   inline bool sanitize_shallow (hb_sanitize_context_t *c) {
     return c->check_struct (this)
        && c->check_array (this, Type::static_size, len);
index 6c5e423..a0b8b52 100644 (file)
@@ -356,7 +356,7 @@ struct CoverageFormat1
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
+                        Supplier<GlyphID> &glyphs,
                         unsigned int num_glyphs)
   {
     TRACE_SERIALIZE ();
@@ -365,6 +365,7 @@ struct CoverageFormat1
     if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
     for (unsigned int i = 0; i < num_glyphs; i++)
       glyphArray[i].set (glyphs[i]);
+    glyphs.advance (num_glyphs);
     return TRACE_RETURN (true);
   }
 
@@ -420,7 +421,7 @@ struct CoverageFormat2
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
+                        Supplier<GlyphID> &glyphs,
                         unsigned int num_glyphs)
   {
     TRACE_SERIALIZE ();
@@ -446,6 +447,7 @@ struct CoverageFormat2
       } else {
         rangeRecord[range].end = glyphs[i];
       }
+    glyphs.advance (num_glyphs);
     return TRACE_RETURN (true);
   }
 
@@ -526,7 +528,7 @@ struct Coverage
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
+                        Supplier<GlyphID> &glyphs,
                         unsigned int num_glyphs)
   {
     TRACE_SERIALIZE ();
index 2ab54e4..c4245ce 100644 (file)
@@ -73,7 +73,7 @@ struct SingleSubstFormat1
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
+                        Supplier<GlyphID> &glyphs,
                         unsigned int num_glyphs,
                         int delta)
   {
@@ -137,8 +137,8 @@ struct SingleSubstFormat2
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
-                        const USHORT *substitutes,
+                        Supplier<GlyphID> &glyphs,
+                        Supplier<GlyphID> &substitutes,
                         unsigned int num_glyphs)
   {
     TRACE_SERIALIZE ();
@@ -201,8 +201,8 @@ struct SingleSubst
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
-                        const USHORT *substitutes,
+                        Supplier<GlyphID> &glyphs,
+                        Supplier<GlyphID> &substitutes,
                         unsigned int num_glyphs)
   {
     TRACE_SERIALIZE ();
@@ -277,7 +277,7 @@ struct Sequence
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
+                        Supplier<GlyphID> &glyphs,
                         unsigned int num_glyphs)
   {
     TRACE_SERIALIZE ();
@@ -331,19 +331,20 @@ struct MultipleSubstFormat1
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
-                        unsigned int *substitute_len_list,
+                        Supplier<GlyphID> &glyphs,
+                        Supplier<unsigned int> &substitute_len_list,
                         unsigned int num_glyphs,
-                        const USHORT *substitute_glyphs_list)
+                        Supplier<GlyphID> &substitute_glyphs_list)
   {
     TRACE_SERIALIZE ();
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (false);
-    for (unsigned int i = 0; i < num_glyphs; i++) {
-      if (unlikely (!sequence[i].serialize (c, this).serialize (c, substitute_glyphs_list, substitute_len_list[i]))) return TRACE_RETURN (false);
-      substitute_glyphs_list += substitute_len_list[i];
-    }
+    for (unsigned int i = 0; i < num_glyphs; i++)
+      if (unlikely (!sequence[i].serialize (c, this).serialize (c,
+                                                               substitute_glyphs_list,
+                                                               substitute_len_list[i]))) return TRACE_RETURN (false);
+    substitute_len_list.advance (num_glyphs);
     return TRACE_RETURN (true);
   }
 
@@ -397,10 +398,10 @@ struct MultipleSubst
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
-                        unsigned int *substitute_len_list,
+                        Supplier<GlyphID> &glyphs,
+                        Supplier<unsigned int> &substitute_len_list,
                         unsigned int num_glyphs,
-                        const USHORT *substitute_glyphs_list)
+                        Supplier<GlyphID> &substitute_glyphs_list)
   {
     TRACE_SERIALIZE ();
     if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
@@ -486,19 +487,20 @@ struct AlternateSubstFormat1
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
-                        unsigned int *alternate_len_list,
+                        Supplier<GlyphID> &glyphs,
+                        Supplier<unsigned int> &alternate_len_list,
                         unsigned int num_glyphs,
-                        const USHORT *alternate_glyphs_list)
+                        Supplier<GlyphID> &alternate_glyphs_list)
   {
     TRACE_SERIALIZE ();
     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return TRACE_RETURN (false);
     if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false);
-    for (unsigned int i = 0; i < num_glyphs; i++) {
-      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c, alternate_glyphs_list, alternate_len_list[i]))) return TRACE_RETURN (false);
-      alternate_glyphs_list += alternate_len_list[i];
-    }
+    for (unsigned int i = 0; i < num_glyphs; i++)
+      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
+                                                                   alternate_glyphs_list,
+                                                                   alternate_len_list[i]))) return TRACE_RETURN (false);
+    alternate_len_list.advance (num_glyphs);
     return TRACE_RETURN (true);
   }
 
@@ -552,10 +554,10 @@ struct AlternateSubst
   }
 
   inline bool serialize (hb_serialize_context_t *c,
-                        const USHORT *glyphs,
-                        unsigned int *alternate_len_list,
+                        Supplier<GlyphID> &glyphs,
+                        Supplier<unsigned int> &alternate_len_list,
                         unsigned int num_glyphs,
-                        const USHORT *alternate_glyphs_list)
+                        Supplier<GlyphID> &alternate_glyphs_list)
   {
     TRACE_SERIALIZE ();
     if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
@@ -646,6 +648,18 @@ struct Ligature
     return TRACE_RETURN (true);
   }
 
+  inline bool serialize (hb_serialize_context_t *c,
+                        GlyphID ligature,
+                        Supplier<GlyphID> &components, /* Starting from second */
+                        unsigned int num_components /* Including first component */)
+  {
+    TRACE_SERIALIZE ();
+    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    ligGlyph.set (ligature);
+    if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false);
+    return TRACE_RETURN (true);
+  }
+
   public:
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE ();
@@ -701,6 +715,24 @@ struct LigatureSet
     return TRACE_RETURN (false);
   }
 
+  inline bool serialize (hb_serialize_context_t *c,
+                        Supplier<GlyphID> &ligatures,
+                        Supplier<unsigned int> &component_count_list,
+                        unsigned int num_ligatures,
+                        Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  {
+    TRACE_SERIALIZE ();
+    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN (false);
+    for (unsigned int i = 0; i < num_ligatures; i++)
+      if (unlikely (!ligature[i].serialize (c, this).serialize (c,
+                                                               ligatures[i],
+                                                               component_list,
+                                                               component_count_list[i]))) return TRACE_RETURN (false);
+    component_count_list.advance (num_ligatures);
+    return TRACE_RETURN (true);
+  }
+
   public:
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE ();
@@ -753,6 +785,28 @@ struct LigatureSubstFormat1
     return TRACE_RETURN (lig_set.apply (c));
   }
 
+  inline bool serialize (hb_serialize_context_t *c,
+                        Supplier<GlyphID> &first_glyphs,
+                        Supplier<unsigned int> &ligature_per_first_glyph_count_list,
+                        unsigned int num_first_glyphs,
+                        Supplier<GlyphID> &ligatures_list,
+                        Supplier<unsigned int> &component_count_list,
+                        Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  {
+    TRACE_SERIALIZE ();
+    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return TRACE_RETURN (false);
+    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RETURN (false);
+    for (unsigned int i = 0; i < num_first_glyphs; i++)
+      if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
+                                                                  ligatures_list,
+                                                                  component_count_list,
+                                                                  ligature_per_first_glyph_count_list[i],
+                                                                  component_list))) return TRACE_RETURN (false);
+    ligature_per_first_glyph_count_list.advance (num_first_glyphs);
+    return TRACE_RETURN (true);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE ();
     return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
@@ -810,6 +864,25 @@ struct LigatureSubst
     }
   }
 
+  inline bool serialize (hb_serialize_context_t *c,
+                        Supplier<GlyphID> &first_glyphs,
+                        Supplier<unsigned int> &ligature_per_first_glyph_count_list,
+                        unsigned int num_first_glyphs,
+                        Supplier<GlyphID> &ligatures_list,
+                        Supplier<unsigned int> &component_count_list,
+                        Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  {
+    TRACE_SERIALIZE ();
+    if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
+    unsigned int format = 1;
+    u.format.set (format);
+    switch (u.format) {
+    case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs,
+                                                     ligatures_list, component_count_list, component_list));
+    default:return TRACE_RETURN (false);
+    }
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE ();
     if (!u.format.sanitize (c)) return TRACE_RETURN (false);