[HarfBuzz] harfbuzz: Branch 'master' - 6 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Oct 11 01:49:49 UTC 2018


 src/hb-aat-layout-kerx-table.hh |  128 +++++++++++++++++++++++++++++++++-------
 src/hb-aat-layout-morx-table.hh |    4 -
 src/hb-ot-shape.cc              |   50 ++++++++-------
 3 files changed, 136 insertions(+), 46 deletions(-)

New commits:
commit 9f450f07b0a1593962e3b45d00f2cf93916f3466
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 10 21:46:58 2018 -0400

    [kerx] Make Format1 work
    
    Tested using Kannada MN:
    
    $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0C95,0CCd,C95,CCD
    [kn_ka.virama=0+1299|kn_ka.vattu=0+115|_blank=0 at -115,0+385]
    
    $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0C95,0CCd,C95,CCD --features=-kern
    [kn_ka.virama=0+1799|kn_ka.vattu=0+230|_blank=0+0]
    
    I don't see the GPOS table in the font do the same.  ¯\_(ツ)_/¯

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 552bb065..cc99868d 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -123,7 +123,7 @@ struct KerxSubTableFormat1
     inline driver_context_t (const KerxSubTableFormat1 *table,
 			     hb_aat_apply_context_t *c_) :
 	c (c_),
-	kernAction (table+table->kernAction),
+	kernAction (&table->machine + table->kernAction),
 	depth (0) {}
 
     inline bool is_actionable (StateTableDriver<EntryData> *driver,
@@ -159,16 +159,21 @@ struct KerxSubTableFormat1
 	  return false;
 	}
 
-        for (; depth; depth--)
+        for (unsigned int i = 0; i < depth; i++)
 	{
-	  unsigned int idx = stack[depth - 1];
+	  /* Apparently, when spec says "Each pops one glyph from the kerning stack
+	   * and applies the kerning value to it.", it doesn't mean it in that order.
+	   * The deepest item in the stack corresponds to the first item in the action
+	   * list.  Discovered by testing. */
+	  unsigned int idx = stack[i];
 	  int v = *actions++;
 	  /* XXX Non-forward direction... */
 	  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-	    buffer->pos[idx].x_advance += v;
+	    buffer->pos[idx].x_advance += c->font->em_scale_x (v);
 	  else
-	    buffer->pos[idx].y_advance += v;
+	    buffer->pos[idx].y_advance += c->font->em_scale_y (v);
 	}
+	depth = 0;
       }
 
       return true;
commit 504cb68fc972c7f606bf9fc62015376382f78f45
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 10 21:29:46 2018 -0400

    Disable mark advance zeroing as well as mark fallback positioning if doing kerx

diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 3b1c93db..e2405237 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -114,7 +114,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
   }
 
   plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
-  if (!plan.apply_gpos)
+  if (!plan.apply_gpos && !plan.apply_kerx)
     plan.fallback_mark_positioning = true;
 }
 
@@ -820,34 +820,36 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c)
 
   hb_ot_layout_position_start (c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
-
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      break;
-  }
+  if (!c->plan->apply_kerx)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+	zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+	break;
+
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+	break;
+    }
 
   if (c->plan->apply_gpos)
-    c->plan->position (c->font, c->buffer);
+    ;//c->plan->position (c->font, c->buffer);
   else if (c->plan->apply_kerx)
     hb_aat_layout_position (c->plan, c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
-
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      break;
-  }
+  if (!c->plan->apply_kerx)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+	zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+	break;
+
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+	break;
+    }
 
   /* Finishing off GPOS has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
commit 84967537966a76297c89460d95e7336f1bfc332d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 10 21:18:37 2018 -0400

    [kerx] Implement Format1
    
    Untested.

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index edc17a39..552bb065 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -101,9 +101,9 @@ struct KerxSubTableFormat1
 {
   struct EntryData
   {
-    HBUINT16	ligActionIndex;	/* Index to the first ligActionTable entry
-				 * for processing this group, if indicated
-				 * by the flags. */
+    HBUINT16	kernActionIndex;/* Index into the kerning value array. If
+				 * this index is 0xFFFF, then no kerning
+				 * is to be performed. */
     public:
     DEFINE_SIZE_STATIC (2);
   };
@@ -120,25 +120,65 @@ struct KerxSubTableFormat1
       Reserved		= 0x1FFF,	/* Not used; set to 0. */
     };
 
-    inline driver_context_t (const KerxSubTableFormat1 *table)
-	{}
+    inline driver_context_t (const KerxSubTableFormat1 *table,
+			     hb_aat_apply_context_t *c_) :
+	c (c_),
+	kernAction (table+table->kernAction),
+	depth (0) {}
 
     inline bool is_actionable (StateTableDriver<EntryData> *driver,
 			       const Entry<EntryData> *entry)
     {
-      return false; // XXX return (entry->flags & Verb) && start < end;
+      return entry->data.kernActionIndex != 0xFFFF;
     }
     inline bool transition (StateTableDriver<EntryData> *driver,
 			    const Entry<EntryData> *entry)
     {
-      //hb_buffer_t *buffer = driver->buffer;
-      //unsigned int flags = entry->flags;
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry->flags;
+
+      if (flags & Reset)
+      {
+        depth = 0;
+      }
+
+      if (flags & Push)
+      {
+        if (likely (depth < ARRAY_LENGTH (stack)))
+	  stack[depth++] = buffer->idx;
+	else
+	  depth = 0; /* Probably not what CoreText does, but better? */
+      }
+
+      if (entry->data.kernActionIndex != 0xFFFF)
+      {
+	const FWORD *actions = &kernAction[entry->data.kernActionIndex];
+        if (!c->sanitizer.check_array (actions, depth))
+	{
+	  depth = 0;
+	  return false;
+	}
+
+        for (; depth; depth--)
+	{
+	  unsigned int idx = stack[depth - 1];
+	  int v = *actions++;
+	  /* XXX Non-forward direction... */
+	  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+	    buffer->pos[idx].x_advance += v;
+	  else
+	    buffer->pos[idx].y_advance += v;
+	}
+      }
 
       return true;
     }
 
-    public:
     private:
+    hb_aat_apply_context_t *c;
+    const UnsizedArrayOf<FWORD> &kernAction;
+    unsigned int stack[8];
+    unsigned int depth;
   };
 
   inline bool apply (hb_aat_apply_context_t *c) const
@@ -148,7 +188,7 @@ struct KerxSubTableFormat1
     if (!c->plan->requested_kerning)
       return false;
 
-    driver_context_t dc (this);
+    driver_context_t dc (this, c);
 
     StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face);
     driver.drive (&dc);
@@ -165,7 +205,7 @@ struct KerxSubTableFormat1
   protected:
   KerxSubTableHeader				header;
   StateTable<EntryData>				machine;
-  LOffsetTo<UnsizedArrayOf<FWORD>, false>	values;
+  LOffsetTo<UnsizedArrayOf<FWORD>, false>	kernAction;
   public:
   DEFINE_SIZE_STATIC (32);
 };
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 5de85126..b902fd79 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -365,7 +365,7 @@ struct LigatureSubtable
     inline bool is_actionable (StateTableDriver<EntryData> *driver,
 			       const Entry<EntryData> *entry)
     {
-      return !!(entry->flags & PerformAction);
+      return entry->flags & PerformAction;
     }
     inline bool transition (StateTableDriver<EntryData> *driver,
 			    const Entry<EntryData> *entry)
commit c9165f5450b99e6d93e2a168b198384a221eef58
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 10 20:43:21 2018 -0400

    [kerx] More UnsizedArrayOf<>

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 0d3b330a..edc17a39 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -205,8 +205,7 @@ struct KerxSubTableFormat2
     TRACE_SANITIZE (this);
     return_trace (likely (rowWidth.sanitize (c) &&
 			  leftClassTable.sanitize (c, this) &&
-			  rightClassTable.sanitize (c, this) &&
-			  array.sanitize (c, this)));
+			  rightClassTable.sanitize (c, this)));
   }
 
   struct accelerator_t
@@ -233,7 +232,8 @@ struct KerxSubTableFormat2
   LOffsetTo<Lookup<HBUINT16> >
 			rightClassTable;/* Offset from beginning of this subtable to
 					 * right-hand class table. */
-  LOffsetTo<FWORD>	array;		/* Offset from beginning of this subtable to
+  LOffsetTo<UnsizedArrayOf<FWORD>, false>
+			 array;		/* Offset from beginning of this subtable to
 					 * the start of the kerning array. */
   public:
   DEFINE_SIZE_STATIC (28);
@@ -324,12 +324,10 @@ struct KerxSubTableFormat6
 			  is_long () ?
 			  (
 			    u.l.rowIndexTable.sanitize (c, this) &&
-			    u.l.columnIndexTable.sanitize (c, this) &&
-			    u.l.array.sanitize (c, this)
+			    u.l.columnIndexTable.sanitize (c, this)
 			  ) : (
 			    u.s.rowIndexTable.sanitize (c, this) &&
-			    u.s.columnIndexTable.sanitize (c, this) &&
-			    u.s.array.sanitize (c, this)
+			    u.s.columnIndexTable.sanitize (c, this)
 			  )));
   }
 
@@ -359,13 +357,15 @@ struct KerxSubTableFormat6
     {
       LOffsetTo<Lookup<HBUINT32> >	rowIndexTable;
       LOffsetTo<Lookup<HBUINT32> >	columnIndexTable;
-      LOffsetTo<FWORD32>		array;
+      LOffsetTo<UnsizedArrayOf<FWORD32>, false>
+					array;
     } l;
     struct Short
     {
       LOffsetTo<Lookup<HBUINT16> >	rowIndexTable;
       LOffsetTo<Lookup<HBUINT16> >	columnIndexTable;
-      LOffsetTo<FWORD>			array;
+      LOffsetTo<UnsizedArrayOf<FWORD>, false>
+					array;
     } s;
   } u;
   public:
commit ca54eba4846d0afda4601929556617a7ebe51714
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 10 20:41:16 2018 -0400

    [kerx] Fix bound-checking error introduced a couple commits past

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 4118d8ee..0d3b330a 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -180,7 +180,7 @@ struct KerxSubTableFormat2
     unsigned int offset = l + r;
     const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset);
     if (unlikely ((const char *) v < (const char *) &array ||
-		  (const char *) v + v->static_size - (const char *) this <= header.length))
+		  (const char *) v + v->static_size - (const char *) this > header.length))
       return 0;
     return *v;
   }
@@ -284,7 +284,7 @@ struct KerxSubTableFormat6
       unsigned int offset = l + r;
       const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
       if (unlikely ((const char *) v < (const char *) &t.array ||
-		    (const char *) v + v->static_size - (const char *) this <= header.length))
+		    (const char *) v + v->static_size - (const char *) this > header.length))
 	return 0;
       return *v;
     }
@@ -296,7 +296,7 @@ struct KerxSubTableFormat6
       unsigned int offset = l + r;
       const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
       if (unlikely ((const char *) v < (const char *) &t.array ||
-		    (const char *) v + v->static_size - (const char *) this <= header.length))
+		    (const char *) v + v->static_size - (const char *) this > header.length))
 	return 0;
       return *v;
     }
commit 339036dd970625e03696b4533ced1e25fc4fd131
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Oct 10 20:37:22 2018 -0400

    [kerx] Start fleshing out Format1

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 3cff334a..4118d8ee 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -99,6 +99,48 @@ struct KerxSubTableFormat0
 
 struct KerxSubTableFormat1
 {
+  struct EntryData
+  {
+    HBUINT16	ligActionIndex;	/* Index to the first ligActionTable entry
+				 * for processing this group, if indicated
+				 * by the flags. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  struct driver_context_t
+  {
+    static const bool in_place = true;
+    enum Flags
+    {
+      Push		= 0x8000,	/* If set, push this glyph on the kerning stack. */
+      DontAdvance	= 0x4000,	/* If set, don't advance to the next glyph
+					 * before going to the new state. */
+      Reset		= 0x2000,	/* If set, reset the kerning data (clear the stack) */
+      Reserved		= 0x1FFF,	/* Not used; set to 0. */
+    };
+
+    inline driver_context_t (const KerxSubTableFormat1 *table)
+	{}
+
+    inline bool is_actionable (StateTableDriver<EntryData> *driver,
+			       const Entry<EntryData> *entry)
+    {
+      return false; // XXX return (entry->flags & Verb) && start < end;
+    }
+    inline bool transition (StateTableDriver<EntryData> *driver,
+			    const Entry<EntryData> *entry)
+    {
+      //hb_buffer_t *buffer = driver->buffer;
+      //unsigned int flags = entry->flags;
+
+      return true;
+    }
+
+    public:
+    private:
+  };
+
   inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
@@ -106,7 +148,10 @@ struct KerxSubTableFormat1
     if (!c->plan->requested_kerning)
       return false;
 
-    /* TODO */
+    driver_context_t dc (this);
+
+    StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
 
     return_trace (true);
   }
@@ -114,14 +159,13 @@ struct KerxSubTableFormat1
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  stateHeader.sanitize (c)));
+    return_trace (likely (machine.sanitize (c)));
   }
 
   protected:
-  KerxSubTableHeader		header;
-  StateTable<HBUINT16>		stateHeader;
-  LOffsetTo<ArrayOf<HBUINT16> >	valueTable;
+  KerxSubTableHeader				header;
+  StateTable<EntryData>				machine;
+  LOffsetTo<UnsizedArrayOf<FWORD>, false>	values;
   public:
   DEFINE_SIZE_STATIC (32);
 };
@@ -159,8 +203,7 @@ struct KerxSubTableFormat2
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-			  rowWidth.sanitize (c) &&
+    return_trace (likely (rowWidth.sanitize (c) &&
 			  leftClassTable.sanitize (c, this) &&
 			  rightClassTable.sanitize (c, this) &&
 			  array.sanitize (c, this)));
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index 0020750c..5de85126 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -164,7 +164,7 @@ struct RearrangementSubtable
 
     driver_context_t dc (this);
 
-    StateTableDriver<void> driver (machine, c->buffer, c->face);
+    StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
     driver.drive (&dc);
 
     return_trace (dc.ret);


More information about the HarfBuzz mailing list