src/hb-aat-layout-morx-table.hh |  257 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 230 insertions(+), 27 deletions(-)

New commits:
commit 9ff76c6025b55d184c96b193f23aa935ab32f1fc
Author: Behdad Esfahbod <[email protected]>
Date:   Sat Sep 15 18:31:14 2018 +0200

    [morx] Respect default feature settings
    
    Does NOT apply user-selected features.  But at least now enables
    correct subtables.

diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 52de7bcd..c544cb37 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -760,11 +760,6 @@ struct ChainSubtable
     Insertion          = 5
   };
 
-  inline void apply (hb_aat_apply_context_t *c) const
-  {
-    dispatch (c);
-  }
-
   template <typename context_t>
   inline typename context_t::return_t dispatch (context_t *c) const
   {
@@ -810,21 +805,38 @@ struct Chain
 {
   inline void apply (hb_aat_apply_context_t *c) const
   {
+    uint32_t flags = defaultFlags;
+    {
+      /* Compute applicable flags.  TODO Should move this to planning
+       * stage and take user-requested features into account. */
+      unsigned int count = featureCount;
+      for (unsigned i = 0; i < count; i++)
+      {
+        const Feature &feature = featureZ[i];
+       if (false) /* XXX Check if feature enabled... */
+       {
+         flags &= feature.disableFlags;
+         flags |= feature.enableFlags;
+       }
+      }
+    }
+
     const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, 
featureZ[0].static_size * featureCount);
     unsigned int count = subtableCount;
     for (unsigned int i = 0; i < count; i++)
     {
+      if (!(subtable->subFeatureFlags & flags))
+        goto skip;
+
       if (!c->buffer->message (c->font, "start chain subtable %d", 
c->lookup_index))
-      {
-       c->set_lookup_index (c->lookup_index + 1);
-       continue;
-      }
+        goto skip;
 
-      subtable->apply (c);
-      subtable = &StructAfter<ChainSubtable> (*subtable);
+      subtable->dispatch (c);
 
       (void) c->buffer->message (c->font, "end chain subtable %d", 
c->lookup_index);
 
+    skip:
+      subtable = &StructAfter<ChainSubtable> (*subtable);
       c->set_lookup_index (c->lookup_index + 1);
     }
   }
commit 2f97da6e2d6629e112789d399765d90f96952c0a
Author: Behdad Esfahbod <[email protected]>
Date:   Sat Sep 15 14:51:50 2018 +0200

    [aat] Change version field

diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 82e1d13f..52de7bcd 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -831,7 +831,7 @@ struct Chain
 
   inline unsigned int get_size (void) const { return length; }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int major) const
+  inline bool sanitize (hb_sanitize_context_t *c, unsigned int version) const
   {
     TRACE_SANITIZE (this);
     if (!length.sanitize (c) ||
@@ -862,7 +862,7 @@ struct Chain
 
   UnsizedArrayOf<Feature>      featureZ;       /* Features. */
 /*ChainSubtable        firstSubtable;*//* Subtables. */
-/*subtableGlyphCoverageArray*/ /* Only if major == 3. */
+/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
 
   public:
   DEFINE_SIZE_MIN (16);
@@ -892,8 +892,7 @@ struct morx
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!version.sanitize (c) ||
-       (version.major >> (sizeof (HBUINT32) == 4 ? 1 : 0)) != 1 ||
+    if (!version.sanitize (c) || version < 2 ||
        !chainCount.sanitize (c))
       return_trace (false);
 
@@ -901,7 +900,7 @@ struct morx
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
     {
-      if (!chain->sanitize (c, version.major))
+      if (!chain->sanitize (c, version))
        return_trace (false);
       chain = &StructAfter<Chain> (*chain);
     }
@@ -910,8 +909,9 @@ struct morx
   }
 
   protected:
-  FixedVersion<>version;       /* Version number of the glyph metamorphosis 
table.
-                                * 1 for mort, 2 or 3 for morx. */
+  HBUINT16     version;        /* Version number of the glyph metamorphosis 
table.
+                                * 2 or 3. */
+  HBUINT16     unused;         /* Set to 0. */
   HBUINT32     chainCount;     /* Number of metamorphosis chains contained in 
this
                                 * table. */
   Chain                firstChain;     /* Chains. */
commit 29c2bd1795b933a611512af50a14f25e25d43159
Author: Behdad Esfahbod <[email protected]>
Date:   Sat Sep 15 14:47:18 2018 +0200

    [morx] Add stub for InsertionChain

diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index e4774c4c..82e1d13f 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -50,7 +50,8 @@ struct RearrangementSubtable
   struct driver_context_t
   {
     static const bool in_place = true;
-    enum Flags {
+    enum Flags
+    {
       MarkFirst                = 0x8000,       /* If set, make the current 
glyph the first
                                         * glyph to be rearranged. */
       DontAdvance      = 0x4000,       /* If set, don't advance to the next 
glyph
@@ -196,7 +197,8 @@ struct ContextualSubtable
   struct driver_context_t
   {
     static const bool in_place = true;
-    enum Flags {
+    enum Flags
+    {
       SetMark          = 0x8000,       /* If set, make the current glyph the 
marked glyph. */
       DontAdvance      = 0x4000,       /* If set, don't advance to the next 
glyph before
                                         * going to the new state. */
@@ -329,7 +331,8 @@ struct LigatureSubtable
   struct driver_context_t
   {
     static const bool in_place = false;
-    enum Flags {
+    enum Flags
+    {
       SetComponent     = 0x8000,       /* Push this glyph onto the component 
stack for
                                         * eventual processing. */
       DontAdvance      = 0x4000,       /* Leave the glyph pointer at this 
glyph for the
@@ -338,7 +341,8 @@ struct LigatureSubtable
                                         * group. */
       Reserved         = 0x1FFF,       /* These bits are reserved and should 
be set to 0. */
     };
-    enum LigActionFlags {
+    enum LigActionFlags
+    {
       LigActionLast    = 0x80000000,   /* This is the last action in the list. 
This also
                                         * implies storage. */
       LigActionStore   = 0x40000000,   /* Store the ligature at the current 
cumulated index
@@ -517,19 +521,205 @@ struct NoncontextualSubtable
 
 struct InsertionSubtable
 {
+  struct EntryData
+  {
+    HBUINT16   currentInsertIndex;     /* Zero-based index into the insertion 
glyph table.
+                                        * The number of glyphs to be inserted 
is contained
+                                        * in the currentInsertCount field in 
the flags.
+                                        * A value of 0xFFFF indicates no 
insertion is to
+                                        * be done. */
+    HBUINT16   markedInsertIndex;      /* Zero-based index into the insertion 
glyph table.
+                                        * The number of glyphs to be inserted 
is contained
+                                        * in the markedInsertCount field in 
the flags.
+                                        * A value of 0xFFFF indicates no 
insertion is to
+                                        * be done. */
+    public:
+    DEFINE_SIZE_STATIC (4);
+  };
+
+  struct driver_context_t
+  {
+    static const bool in_place = false;
+    enum Flags
+    {
+      SetMark          = 0x8000,       /* If set, mark the current glyph. */
+      DontAdvance      = 0x4000,       /* If set, don't advance to the next 
glyph before
+                                        * going to the new state.  This does 
not mean
+                                        * that the glyph pointed to is the 
same one as
+                                        * before. If you've made insertions 
immediately
+                                        * downstream of the current glyph, the 
next glyph
+                                        * processed would in fact be the first 
one
+                                        * inserted. */
+      CurrentIsKashidaLike= 0x2000,    /* If set, and the currentInsertList is 
nonzero,
+                                        * then the specified glyph list will 
be inserted
+                                        * as a kashida-like insertion, either 
before or
+                                        * after the current glyph (depending 
on the state
+                                        * of the currentInsertBefore flag). If 
clear, and
+                                        * the currentInsertList is nonzero, 
then the
+                                        * specified glyph list will be 
inserted as a
+                                        * split-vowel-like insertion, either 
before or
+                                        * after the current glyph (depending 
on the state
+                                        * of the currentInsertBefore flag). */
+      MarkedIsKashidaLike= 0x1000,     /* If set, and the markedInsertList is 
nonzero,
+                                        * then the specified glyph list will 
be inserted
+                                        * as a kashida-like insertion, either 
before or
+                                        * after the marked glyph (depending on 
the state
+                                        * of the markedInsertBefore flag). If 
clear, and
+                                        * the markedInsertList is nonzero, 
then the
+                                        * specified glyph list will be 
inserted as a
+                                        * split-vowel-like insertion, either 
before or
+                                        * after the marked glyph (depending on 
the state
+                                        * of the markedInsertBefore flag). */
+      CurrentInsertBefore= 0x0800,     /* If set, specifies that insertions 
are to be made
+                                        * to the left of the current glyph. If 
clear,
+                                        * they're made to the right of the 
current glyph. */
+      MarkedInsertBefore= 0x0400,      /* If set, specifies that insertions 
are to be
+                                        * made to the left of the marked 
glyph. If clear,
+                                        * they're made to the right of the 
marked glyph. */
+      CurrentInsertCount= 0x3E0,       /* This 5-bit field is treated as a 
count of the
+                                        * number of glyphs to insert at the 
current
+                                        * position. Since zero means no 
insertions, the
+                                        * largest number of insertions at any 
given
+                                        * current location is 31 glyphs. */
+      MarkedInsertCount= 0x001F,       /* This 5-bit field is treated as a 
count of the
+                                        * number of glyphs to insert at the 
marked
+                                        * position. Since zero means no 
insertions, the
+                                        * largest number of insertions at any 
given
+                                        * marked location is 31 glyphs. */
+    };
+
+    inline driver_context_t (const InsertionSubtable *table,
+                            hb_aat_apply_context_t *c_) :
+       ret (false),
+       c (c_),
+       mark_set (false),
+       mark (0),
+       insertionAction (table+table->insertionAction) {}
+
+    inline bool is_actionable (StateTableDriver<EntryData> *driver,
+                              const Entry<EntryData> *entry)
+    {
+      return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
+            (entry->data.currentInsertIndex != 0xFFFF 
||entry->data.markedInsertIndex != 0xFFFF);
+    }
+    inline bool transition (StateTableDriver<EntryData> *driver,
+                           const Entry<EntryData> *entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry->flags;
+
+#if 0
+      if (flags & SetComponent)
+      {
+        if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
+         return false;
+
+       /* Never mark same index twice, in case DontAdvance was used... */
+       if (match_length && match_positions[match_length - 1] == 
buffer->out_len)
+         match_length--;
+
+       match_positions[match_length++] = buffer->out_len;
+      }
+
+      if (flags & PerformAction)
+      {
+       unsigned int end = buffer->out_len;
+       unsigned int action_idx = entry->data.ligActionIndex;
+       unsigned int action;
+       unsigned int ligature_idx = 0;
+        do
+       {
+         if (unlikely (!match_length))
+           return false;
+
+         buffer->move_to (match_positions[--match_length]);
+
+         const HBUINT32 &actionData = ligAction[action_idx];
+         if (unlikely (!actionData.sanitize (&c->sanitizer))) return false;
+         action = actionData;
+
+         uint32_t uoffset = action & LigActionOffset;
+         if (uoffset & 0x20000000)
+           uoffset += 0xC0000000;
+         int32_t offset = (int32_t) uoffset;
+         unsigned int component_idx = buffer->cur().codepoint + offset;
+
+         const HBUINT16 &componentData = component[component_idx];
+         if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
+         ligature_idx += componentData;
+
+         if (action & (LigActionStore | LigActionLast))
+         {
+           const GlyphID &ligatureData = ligature[ligature_idx];
+           if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
+           hb_codepoint_t lig = ligatureData;
+
+           match_positions[match_length++] = buffer->out_len;
+           buffer->replace_glyph (lig);
+
+           //ligature_idx = 0; // XXX Yes or no?
+         }
+         else
+         {
+           buffer->skip_glyph ();
+           end--;
+         }
+         /* TODO merge_clusters / unsafe_to_break */
+
+         action_idx++;
+       }
+       while (!(action & LigActionLast));
+       buffer->move_to (end);
+      }
+#endif
+
+      if (flags & SetMark)
+      {
+       mark_set = true;
+       mark = buffer->idx;
+      }
+
+
+      return true;
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    bool mark_set;
+    unsigned int mark;
+    const UnsizedArrayOf<GlyphID> &insertionAction;
+  };
+
   inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    /* TODO */
-    return_trace (false);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    /* TODO */
-    return_trace (true);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                 insertionAction);
   }
+
+  protected:
+  StateTable<EntryData>
+               machine;
+  LOffsetTo<UnsizedArrayOf<GlyphID> >
+               insertionAction;        /* Byte offset from stateHeader to the 
start of
+                                        * the insertion glyph table. */
+  public:
+  DEFINE_SIZE_STATIC (20);
 };
 
 
@@ -561,7 +751,8 @@ struct ChainSubtable
   inline unsigned int get_size (void) const { return length; }
   inline unsigned int get_type (void) const { return coverage & 0xFF; }
 
-  enum Type {
+  enum Type
+  {
     Rearrangement      = 0,
     Contextual         = 1,
     Ligature           = 2,
_______________________________________________
HarfBuzz mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/harfbuzz

Reply via email to