[mort] Bring back mort generalizations
authorEbrahim Byagowi <ebrahim@gnu.org>
Tue, 30 Oct 2018 15:11:34 +0000 (18:41 +0330)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 31 Oct 2018 02:18:06 +0000 (19:18 -0700)
Started by reverting https://github.com/harfbuzz/harfbuzz/commit/1f1c85a5

Just a starting point, if we agree even mort can come back.

src/hb-aat-layout-common.hh
src/hb-aat-layout-kerx-table.hh
src/hb-aat-layout-morx-table.hh
src/hb-aat-layout.cc
src/hb-ot-face.hh

index ce40abd..7327cc5 100644 (file)
@@ -410,9 +410,13 @@ struct Entry<void>
   DEFINE_SIZE_STATIC (4);
 };
 
-template <typename Extra>
+template <typename Types, typename Extra>
 struct StateTable
 {
+  typedef typename Types::HBUINT HBUINT;
+  typedef typename Types::HBUSHORT HBUSHORT;
+  typedef typename Types::ClassType ClassType;
+
   enum State
   {
     STATE_START_OF_TEXT = 0,
@@ -504,23 +508,73 @@ struct StateTable
   }
 
   protected:
-  HBUINT32     nClasses;       /* Number of classes, which is the number of indices
+  HBUINT       nClasses;       /* Number of classes, which is the number of indices
                                 * in a single line in the state array. */
-  LOffsetTo<Lookup<HBUINT16>, false>
+  OffsetTo<ClassType, HBUINT, false>
                classTable;     /* Offset to the class table. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
+  OffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT, false>
                stateArrayTable;/* Offset to the state array. */
-  LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
+  OffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT, false>
                entryTable;     /* Offset to the entry array. */
 
   public:
   DEFINE_SIZE_STATIC (16);
 };
 
-template <typename EntryData>
+struct ClassTable
+{
+  inline unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? classArrayZ[glyph_id - firstGlyph] : 1;
+  }
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classArrayZ.sanitize (c, glyphCount));
+  }
+  protected:
+  GlyphID      firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16     glyphCount;     /* Total number of glyphs (equivalent to the last
+                                * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<HBUINT8>
+               classArrayZ;    /* The class codes (indexed by glyph index minus
+                                * firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (4, classArrayZ);
+};
+
+struct MortTypes
+{
+  static const bool extended = false;
+  typedef HBUINT16 HBUINT;
+  typedef HBUINT8 HBUSHORT;
+  struct ClassType : ClassTable
+  {
+    inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs HB_UNUSED) const
+    {
+      return ClassTable::get_class (glyph_id);
+    }
+  };
+};
+struct MorxTypes
+{
+  static const bool extended = true;
+  typedef HBUINT32 HBUINT;
+  typedef HBUINT16 HBUSHORT;
+  struct ClassType : Lookup<HBUINT16>
+  {
+    inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+    {
+      const HBUINT16 *v = get_value (glyph_id, num_glyphs);
+      return v ? *v : 1;
+    }
+  };
+};
+
+template <typename Types, typename EntryData>
 struct StateTableDriver
 {
-  inline StateTableDriver (const StateTable<EntryData> &machine_,
+  inline StateTableDriver (const StateTable<Types, EntryData> &machine_,
                           hb_buffer_t *buffer_,
                           hb_face_t *face_) :
              machine (machine_),
@@ -533,13 +587,13 @@ struct StateTableDriver
     if (!c->in_place)
       buffer->clear_output ();
 
-    unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
+    unsigned int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
     bool last_was_dont_advance = false;
     for (buffer->idx = 0; buffer->successful;)
     {
       unsigned int klass = buffer->idx < buffer->len ?
                           machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
-                          (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT;
+                          (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
       const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
       if (unlikely (!entry))
        break;
@@ -553,7 +607,7 @@ struct StateTableDriver
        /* If there's no action and we're just epsilon-transitioning to state 0,
         * safe to break. */
        if (c->is_actionable (this, entry) ||
-           !(entry->newState == StateTable<EntryData>::STATE_START_OF_TEXT &&
+           !(entry->newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
              entry->flags == context_t::DontAdvance))
          buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
       }
@@ -590,7 +644,7 @@ struct StateTableDriver
   }
 
   public:
-  const StateTable<EntryData> &machine;
+  const StateTable<Types, EntryData> &machine;
   hb_buffer_t *buffer;
   unsigned int num_glyphs;
 };
index a883125..94e0a9b 100644 (file)
@@ -163,12 +163,12 @@ struct KerxSubTableFormat1
        kernAction (&table->machine + table->kernAction),
        depth (0) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+    inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
                               const Entry<EntryData> *entry)
     {
       return entry->data.kernActionIndex != 0xFFFF;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
                            const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -239,7 +239,7 @@ struct KerxSubTableFormat1
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face);
+    StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->font->face);
     driver.drive (&dc);
 
     return_trace (true);
@@ -255,7 +255,7 @@ struct KerxSubTableFormat1
 
   protected:
   KerxSubTableHeader                           header;
-  StateTable<EntryData>                                machine;
+  StateTable<MorxTypes, EntryData>                             machine;
   LOffsetTo<UnsizedArrayOf<FWORD>, false>      kernAction;
   public:
   DEFINE_SIZE_STATIC (32);
@@ -365,12 +365,12 @@ struct KerxSubTableFormat4
        mark_set (false),
        mark (0) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+    inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
                               const Entry<EntryData> *entry)
     {
       return entry->data.ankrActionIndex != 0xFFFF;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
                            const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -473,7 +473,7 @@ struct KerxSubTableFormat4
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face);
+    StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->font->face);
     driver.drive (&dc);
 
     return_trace (true);
@@ -489,7 +489,8 @@ struct KerxSubTableFormat4
 
   protected:
   KerxSubTableHeader   header;
-  StateTable<EntryData>        machine;
+  StateTable<MorxTypes, EntryData>
+                       machine;
   HBUINT32             flags;
   public:
   DEFINE_SIZE_STATIC (32);
index a562091..336d0e3 100644 (file)
 /*
  * morx -- Extended Glyph Metamorphosis
  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
  */
 #define HB_AAT_TAG_morx HB_TAG('m','o','r','x')
+#define HB_AAT_TAG_mort HB_TAG('m','o','r','t')
 
 
 namespace AAT {
 
 using namespace OT;
 
-
+template <typename Types>
 struct RearrangementSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
   typedef void EntryData;
 
   struct driver_context_t
@@ -69,12 +73,12 @@ struct RearrangementSubtable
        ret (false),
        start (0), end (0) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+    inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
                               const Entry<EntryData> *entry)
     {
       return (entry->flags & Verb) && start < end;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
                            const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -165,7 +169,7 @@ struct RearrangementSubtable
 
     driver_context_t dc (this);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
@@ -178,13 +182,16 @@ struct RearrangementSubtable
   }
 
   protected:
-  StateTable<EntryData>        machine;
+  StateTable<Types, EntryData> machine;
   public:
   DEFINE_SIZE_STATIC (16);
 };
 
+template <typename Types>
 struct ContextualSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
   struct EntryData
   {
     HBUINT16   markIndex;      /* Index of the substitution table for the
@@ -212,7 +219,7 @@ struct ContextualSubtable
        mark (0),
        subs (table+table->substitutionTables) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver,
+    inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver,
                               const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -222,7 +229,7 @@ struct ContextualSubtable
 
       return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
                            const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -280,7 +287,7 @@ struct ContextualSubtable
 
     driver_context_t dc (this);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
@@ -310,16 +317,19 @@ struct ContextualSubtable
   }
 
   protected:
-  StateTable<EntryData>
+  StateTable<Types, EntryData>
                machine;
-  LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32, false>, false>
+  OffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT, false>
                substitutionTables;
   public:
   DEFINE_SIZE_STATIC (20);
 };
 
+template <typename Types>
 struct LigatureSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
   struct EntryData
   {
     HBUINT16   ligActionIndex; /* Index to the first ligActionTable entry
@@ -363,12 +373,12 @@ struct LigatureSubtable
        ligature (table+table->ligature),
        match_length (0) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+    inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
                               const Entry<EntryData> *entry)
     {
       return entry->flags & PerformAction;
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
                            const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -482,7 +492,7 @@ struct LigatureSubtable
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
@@ -497,18 +507,19 @@ struct LigatureSubtable
   }
 
   protected:
-  StateTable<EntryData>
+  StateTable<Types, EntryData>
                machine;
-  LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
+  OffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT, false>
                ligAction;      /* Offset to the ligature action table. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
+  OffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT, false>
                component;      /* Offset to the component table. */
-  LOffsetTo<UnsizedArrayOf<GlyphID>, false>
+  OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false>
                ligature;       /* Offset to the actual ligature lists. */
   public:
   DEFINE_SIZE_STATIC (28);
 };
 
+template <typename Types>
 struct NoncontextualSubtable
 {
   inline bool apply (hb_aat_apply_context_t *c) const
@@ -545,8 +556,11 @@ struct NoncontextualSubtable
   DEFINE_SIZE_MIN (2);
 };
 
+template <typename Types>
 struct InsertionSubtable
 {
+  typedef typename Types::HBUINT HBUINT;
+
   struct EntryData
   {
     HBUINT16   currentInsertIndex;     /* Zero-based index into the insertion glyph table.
@@ -622,13 +636,13 @@ struct InsertionSubtable
        mark (0),
        insertionAction (table+table->insertionAction) {}
 
-    inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+    inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
                               const Entry<EntryData> *entry)
     {
       return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
             (entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF);
     }
-    inline bool transition (StateTableDriver<EntryData> *driver,
+    inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
                            const Entry<EntryData> *entry)
     {
       hb_buffer_t *buffer = driver->buffer;
@@ -720,7 +734,7 @@ struct InsertionSubtable
 
     driver_context_t dc (this, c);
 
-    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);
@@ -735,9 +749,9 @@ struct InsertionSubtable
   }
 
   protected:
-  StateTable<EntryData>
+  StateTable<Types, EntryData>
                machine;
-  LOffsetTo<UnsizedArrayOf<GlyphID>, false>
+  OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false>
                insertionAction;        /* Byte offset from stateHeader to the start of
                                         * the insertion glyph table. */
   public:
@@ -765,9 +779,10 @@ struct Feature
   DEFINE_SIZE_STATIC (12);
 };
 
-
+template <typename Types>
 struct ChainSubtable
 {
+  template <typename T>
   friend struct Chain;
 
   inline unsigned int get_size (void) const { return length; }
@@ -830,18 +845,21 @@ struct ChainSubtable
   HBUINT32     coverage;       /* Coverage flags and subtable type. */
   HBUINT32     subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
   union {
-  RearrangementSubtable                rearrangement;
-  ContextualSubtable           contextual;
-  LigatureSubtable             ligature;
-  NoncontextualSubtable                noncontextual;
-  InsertionSubtable            insertion;
+  RearrangementSubtable<Types> rearrangement;
+  ContextualSubtable<Types>    contextual;
+  LigatureSubtable<Types>      ligature;
+  NoncontextualSubtable<Types> noncontextual;
+  InsertionSubtable<Types>     insertion;
   } u;
   public:
-  DEFINE_SIZE_MIN (12);
+  DEFINE_SIZE_MIN (2 * sizeof (HBUINT32) + 4);
 };
 
+template <typename Types>
 struct Chain
 {
+  typedef typename Types::HBUINT HBUINT;
+
   inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
   {
     hb_mask_t flags = defaultFlags;
@@ -868,7 +886,7 @@ struct Chain
   inline void apply (hb_aat_apply_context_t *c,
                     hb_mask_t flags) const
   {
-    const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
+    const ChainSubtable<Types> *subtable = &StructAtOffset<ChainSubtable<Types> > (&featureZ, featureZ[0].static_size * featureCount);
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
@@ -877,9 +895,9 @@ struct Chain
       if (!(subtable->subFeatureFlags & flags))
         goto skip;
 
-      if (!(subtable->coverage & ChainSubtable::AllDirections) &&
+      if (!(subtable->coverage & ChainSubtable<Types>::AllDirections) &&
          HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
-         bool (subtable->coverage & ChainSubtable::Vertical))
+         bool (subtable->coverage & ChainSubtable<Types>::Vertical))
         goto skip;
 
       /* Buffer contents is always in logical direction.  Determine if
@@ -909,9 +927,9 @@ struct Chain
                                (the order opposite that of the characters, which
                                may be right-to-left or left-to-right).
        */
-      reverse = subtable->coverage & ChainSubtable::Logical ?
-               bool (subtable->coverage & ChainSubtable::Backwards) :
-               bool (subtable->coverage & ChainSubtable::Backwards) !=
+      reverse = subtable->coverage & ChainSubtable<Types>::Logical ?
+               bool (subtable->coverage & ChainSubtable<Types>::Backwards) :
+               bool (subtable->coverage & ChainSubtable<Types>::Backwards) !=
                HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
 
       if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
@@ -932,7 +950,7 @@ struct Chain
       if (unlikely (!c->buffer->successful)) return;
 
     skip:
-      subtable = &StructAfter<ChainSubtable> (*subtable);
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
       c->set_lookup_index (c->lookup_index + 1);
     }
   }
@@ -950,38 +968,39 @@ struct Chain
     if (!c->check_array (featureZ.arrayZ, featureCount))
       return_trace (false);
 
-    const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount);
+    const ChainSubtable<Types> *subtable = &StructAtOffset<ChainSubtable<Types> > (&featureZ, featureZ[0].static_size * featureCount);
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
       if (!subtable->sanitize (c))
        return_trace (false);
-      subtable = &StructAfter<ChainSubtable> (*subtable);
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
     }
 
     return_trace (true);
   }
 
   protected:
-  HBUINT32     defaultFlags;   /* The default specification for subtables. */
-  HBUINT32     length;         /* Total byte count, including this header. */
-  HBUINT32     featureCount;   /* Number of feature subtable entries. */
-  HBUINT32     subtableCount;  /* The number of subtables in the chain. */
+  HBUINT       defaultFlags;   /* The default specification for subtables. */
+  HBUINT       length;         /* Total byte count, including this header. */
+  HBUINT       featureCount;   /* Number of feature subtable entries. */
+  HBUINT       subtableCount;  /* The number of subtables in the chain. */
 
   UnsizedArrayOf<Feature>      featureZ;       /* Features. */
 /*ChainSubtable        firstSubtable;*//* Subtables. */
 /*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
 
   public:
-  DEFINE_SIZE_MIN (16);
+  DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
 };
 
 
 /*
- * The 'morx' Table
+ * The 'mort'/'morx' Table
  */
 
-struct morx
+template <typename Types>
+struct mortmorx
 {
   static const hb_tag_t tableTag = HB_AAT_TAG_morx;
 
@@ -990,12 +1009,12 @@ struct morx
   inline void compile_flags (const hb_aat_map_builder_t *mapper,
                             hb_aat_map_t *map) const
   {
-    const Chain *chain = &firstChain;
+    const Chain<Types> *chain = &firstChain;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
       map->chain_flags.push (chain->compile_flags (mapper));
-      chain = &StructAfter<Chain> (*chain);
+      chain = &StructAfter<Chain<Types> > (*chain);
     }
   }
 
@@ -1019,13 +1038,13 @@ struct morx
   {
     if (unlikely (!c->buffer->successful)) return;
     c->set_lookup_index (0);
-    const Chain *chain = &firstChain;
+    const Chain<Types> *chain = &firstChain;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
       chain->apply (c, c->plan->aat_map.chain_flags[i]);
       if (unlikely (!c->buffer->successful)) return;
-      chain = &StructAfter<Chain> (*chain);
+      chain = &StructAfter<Chain<Types> > (*chain);
     }
     remove_deleted_glyphs (c->buffer);
   }
@@ -1037,13 +1056,13 @@ struct morx
        !chainCount.sanitize (c))
       return_trace (false);
 
-    const Chain *chain = &firstChain;
+    const Chain<Types> *chain = &firstChain;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
       if (!chain->sanitize (c, version))
        return_trace (false);
-      chain = &StructAfter<Chain> (*chain);
+      chain = &StructAfter<Chain<Types> > (*chain);
     }
 
     return_trace (true);
@@ -1055,12 +1074,22 @@ struct morx
   HBUINT16     unused;         /* Set to 0. */
   HBUINT32     chainCount;     /* Number of metamorphosis chains contained in this
                                 * table. */
-  Chain                firstChain;     /* Chains. */
+  Chain<Types> firstChain;     /* Chains. */
 
   public:
   DEFINE_SIZE_MIN (8);
 };
 
+struct morx : mortmorx<MorxTypes>
+{
+  static const hb_tag_t tableTag       = HB_AAT_TAG_morx;
+};
+struct mort : mortmorx<MortTypes>
+{
+  static const hb_tag_t tableTag       = HB_AAT_TAG_mort;
+};
+
+
 } /* namespace AAT */
 
 
index ec05393..59157c2 100644 (file)
@@ -130,9 +130,23 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
 
 
 /*
- * morx/kerx/trak
+ * mort/morx/kerx/trak
  */
 
+// static inline const AAT::mort&
+// _get_mort (hb_face_t *face, hb_blob_t **blob = nullptr)
+// {
+//   if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+//   {
+//     if (blob)
+//       *blob = hb_blob_get_empty ();
+//     return Null(AAT::mort);
+//   }
+//   const AAT::morx& mort = *(hb_ot_face_data (face)->mort.get ());
+//   if (blob)
+//     *blob = hb_ot_face_data (face)->mort.get_blob ();
+//   return mort;
+// }
 static inline const AAT::morx&
 _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
 {
index f3b7945..6e629eb 100644 (file)
@@ -52,6 +52,7 @@
     HB_OT_TABLE(OT, BASE) \
     /* AAT shaping. */ \
     HB_OT_TABLE(AAT, morx) \
+    HB_OT_TABLE(AAT, mort) \
     HB_OT_TABLE(AAT, kerx) \
     HB_OT_TABLE(AAT, ankr) \
     HB_OT_TABLE(AAT, trak) \