Imported Upstream version 1.7.6
[platform/upstream/harfbuzz.git] / src / hb-ot-layout-gpos-table.hh
index 952fd60..46ffcc6 100644 (file)
@@ -51,11 +51,11 @@ enum attach_type_t {
 
 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
 
-typedef USHORT Value;
+typedef HBUINT16 Value;
 
 typedef Value ValueRecord[VAR];
 
-struct ValueFormat : USHORT
+struct ValueFormat : HBUINT16
 {
   enum Flags {
     xPlacement = 0x0001u,      /* Includes horizontal adjustment for placement */
@@ -74,14 +74,14 @@ struct ValueFormat : USHORT
 
 /* All fields are options.  Only those available advance the value pointer. */
 #if 0
-  SHORT                xPlacement;             /* Horizontal adjustment for
+  HBINT16              xPlacement;             /* Horizontal adjustment for
                                         * placement--in design units */
-  SHORT                yPlacement;             /* Vertical adjustment for
+  HBINT16              yPlacement;             /* Vertical adjustment for
                                         * placement--in design units */
-  SHORT                xAdvance;               /* Horizontal adjustment for
+  HBINT16              xAdvance;               /* Horizontal adjustment for
                                         * advance--in design units (only used
                                         * for horizontal writing) */
-  SHORT                yAdvance;               /* Vertical adjustment for advance--in
+  HBINT16              yAdvance;               /* Vertical adjustment for advance--in
                                         * design units (only used for vertical
                                         * writing) */
   Offset       xPlaDevice;             /* Offset to Device table for
@@ -99,11 +99,11 @@ struct ValueFormat : USHORT
 #endif
 
   inline unsigned int get_len (void) const
-  { return _hb_popcount32 ((unsigned int) *this); }
+  { return _hb_popcount ((unsigned int) *this); }
   inline unsigned int get_size (void) const
   { return get_len () * Value::static_size; }
 
-  void apply_value (hb_apply_context_t   *c,
+  void apply_value (hb_ot_apply_context_t   *c,
                    const void           *base,
                    const Value          *values,
                    hb_glyph_position_t  &glyph_pos) const
@@ -178,8 +178,8 @@ struct ValueFormat : USHORT
   static inline const OffsetTo<Device>& get_device (const Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
 
-  static inline const SHORT& get_short (const Value* value)
-  { return *CastP<SHORT> (value); }
+  static inline const HBINT16& get_short (const Value* value)
+  { return *CastP<HBINT16> (value); }
 
   public:
 
@@ -232,12 +232,12 @@ struct ValueFormat : USHORT
 
 struct AnchorFormat1
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                         hb_position_t *x, hb_position_t *y) const
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                         float *x, float *y) const
   {
     hb_font_t *font = c->font;
-    *x = font->em_scale_x (xCoordinate);
-    *y = font->em_scale_y (yCoordinate);
+    *x = font->em_fscale_x (xCoordinate);
+    *y = font->em_fscale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -247,17 +247,17 @@ struct AnchorFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
-  SHORT                xCoordinate;            /* Horizontal value--in design units */
-  SHORT                yCoordinate;            /* Vertical value--in design units */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
+  FWORD                xCoordinate;            /* Horizontal value--in design units */
+  FWORD                yCoordinate;            /* Vertical value--in design units */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct AnchorFormat2
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
-                         hb_position_t *x, hb_position_t *y) const
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                         float *x, float *y) const
   {
     hb_font_t *font = c->font;
     unsigned int x_ppem = font->x_ppem;
@@ -267,8 +267,8 @@ struct AnchorFormat2
 
     ret = (x_ppem || y_ppem) &&
           font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
-    *x = ret && x_ppem ? cx : font->em_scale_x (xCoordinate);
-    *y = ret && y_ppem ? cy : font->em_scale_y (yCoordinate);
+    *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
+    *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -278,22 +278,22 @@ struct AnchorFormat2
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 2 */
-  SHORT                xCoordinate;            /* Horizontal value--in design units */
-  SHORT                yCoordinate;            /* Vertical value--in design units */
-  USHORT       anchorPoint;            /* Index to glyph contour point */
+  HBUINT16     format;                 /* Format identifier--format = 2 */
+  FWORD                xCoordinate;            /* Horizontal value--in design units */
+  FWORD                yCoordinate;            /* Vertical value--in design units */
+  HBUINT16     anchorPoint;            /* Index to glyph contour point */
   public:
   DEFINE_SIZE_STATIC (8);
 };
 
 struct AnchorFormat3
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                         hb_position_t *x, hb_position_t *y) const
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                         float *x, float *y) const
   {
     hb_font_t *font = c->font;
-    *x = font->em_scale_x (xCoordinate);
-    *y = font->em_scale_y (yCoordinate);
+    *x = font->em_fscale_x (xCoordinate);
+    *y = font->em_fscale_y (yCoordinate);
 
     if (font->x_ppem || font->num_coords)
       *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
@@ -308,9 +308,9 @@ struct AnchorFormat3
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 3 */
-  SHORT                xCoordinate;            /* Horizontal value--in design units */
-  SHORT                yCoordinate;            /* Vertical value--in design units */
+  HBUINT16     format;                 /* Format identifier--format = 3 */
+  FWORD                xCoordinate;            /* Horizontal value--in design units */
+  FWORD                yCoordinate;            /* Vertical value--in design units */
   OffsetTo<Device>
                xDeviceTable;           /* Offset to Device table for X
                                         * coordinate-- from beginning of
@@ -325,15 +325,15 @@ struct AnchorFormat3
 
 struct Anchor
 {
-  inline void get_anchor (hb_apply_context_t *c, hb_codepoint_t glyph_id,
-                         hb_position_t *x, hb_position_t *y) const
+  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                         float *x, float *y) const
   {
     *x = *y = 0;
     switch (u.format) {
     case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
     case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
     case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
-    default:                                            return;
+    default:                                         return;
     }
   }
 
@@ -351,7 +351,7 @@ struct Anchor
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   AnchorFormat1                format1;
   AnchorFormat2                format2;
   AnchorFormat3                format3;
@@ -382,7 +382,7 @@ struct AnchorMatrix
     return_trace (true);
   }
 
-  USHORT       rows;                   /* Number of rows */
+  HBUINT16     rows;                   /* Number of rows */
   protected:
   OffsetTo<Anchor>
                matrixZ[VAR];           /* Matrix of offsets to Anchor tables--
@@ -403,7 +403,7 @@ struct MarkRecord
   }
 
   protected:
-  USHORT       klass;                  /* Class defined for this mark */
+  HBUINT16     klass;                  /* Class defined for this mark */
   OffsetTo<Anchor>
                markAnchor;             /* Offset to Anchor table--from
                                         * beginning of MarkArray table */
@@ -413,7 +413,7 @@ struct MarkRecord
 
 struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */
 {
-  inline bool apply (hb_apply_context_t *c,
+  inline bool apply (hb_ot_apply_context_t *c,
                     unsigned int mark_index, unsigned int glyph_index,
                     const AnchorMatrix &anchors, unsigned int class_count,
                     unsigned int glyph_pos) const
@@ -430,14 +430,15 @@ struct MarkArray : ArrayOf<MarkRecord>    /* Array of MarkRecords--in Coverage orde
      * return false such that the subsequent subtables have a chance at it. */
     if (unlikely (!found)) return_trace (false);
 
-    hb_position_t mark_x, mark_y, base_x, base_y;
+    float mark_x, mark_y, base_x, base_y;
 
+    buffer->unsafe_to_break (glyph_pos, buffer->idx);
     mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
     glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 
     hb_glyph_position_t &o = buffer->cur_pos();
-    o.x_offset = base_x - mark_x;
-    o.y_offset = base_y - mark_y;
+    o.x_offset = round (base_x - mark_x);
+    o.y_offset = round (base_y - mark_y);
     o.attach_type() = ATTACH_TYPE_MARK;
     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
@@ -461,7 +462,7 @@ struct SinglePosFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
+    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -469,7 +470,7 @@ struct SinglePosFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -491,7 +492,7 @@ struct SinglePosFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
   OffsetTo<Coverage>
                coverage;               /* Offset to Coverage table--from
                                         * beginning of subtable */
@@ -509,7 +510,7 @@ struct SinglePosFormat2
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
+    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -517,7 +518,7 @@ struct SinglePosFormat2
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -543,13 +544,13 @@ struct SinglePosFormat2
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 2 */
+  HBUINT16     format;                 /* Format identifier--format = 2 */
   OffsetTo<Coverage>
                coverage;               /* Offset to Coverage table--from
                                         * beginning of subtable */
   ValueFormat  valueFormat;            /* Defines the types of data in the
                                         * ValueRecord */
-  USHORT       valueCount;             /* Number of ValueRecords */
+  HBUINT16     valueCount;             /* Number of ValueRecords */
   ValueRecord  values;                 /* Array of ValueRecords--positioning
                                         * values applied to glyphs */
   public:
@@ -572,7 +573,7 @@ struct SinglePos
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   SinglePosFormat1     format1;
   SinglePosFormat2     format2;
   } u;
@@ -603,18 +604,13 @@ struct PairSet
     TRACE_COLLECT_GLYPHS (this);
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
+    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      c->input->add (record->secondGlyph);
-      record = &StructAtOffset<PairValueRecord> (record, record_size);
-    }
+    c->input->add_array (&record->secondGlyph, len, record_size);
   }
 
-  inline bool apply (hb_apply_context_t *c,
+  inline bool apply (hb_ot_apply_context_t *c,
                     const ValueFormat *valueFormats,
                     unsigned int pos) const
   {
@@ -622,7 +618,7 @@ struct PairSet
     hb_buffer_t *buffer = c->buffer;
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
-    unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
+    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
     const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
@@ -643,6 +639,7 @@ struct PairSet
         min = mid + 1;
       else
       {
+        buffer->unsafe_to_break (buffer->idx, pos + 1);
        valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
        valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
        if (len2)
@@ -666,7 +663,7 @@ struct PairSet
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return_trace (false);
+       && c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false);
 
     unsigned int count = len;
     const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
@@ -675,8 +672,8 @@ struct PairSet
   }
 
   protected:
-  USHORT       len;                    /* Number of PairValueRecords */
-  USHORT       arrayZ[VAR];            /* Array of PairValueRecords--ordered
+  HBUINT16     len;                    /* Number of PairValueRecords */
+  HBUINT16     arrayZ[VAR];            /* Array of PairValueRecords--ordered
                                         * by GlyphID of the second glyph */
   public:
   DEFINE_SIZE_ARRAY (2, arrayZ);
@@ -687,7 +684,7 @@ struct PairPosFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
+    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = pairSet.len;
     for (unsigned int i = 0; i < count; i++)
       (this+pairSet[i]).collect_glyphs (c, valueFormat);
@@ -698,14 +695,14 @@ struct PairPosFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
@@ -731,7 +728,7 @@ struct PairPosFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
   OffsetTo<Coverage>
                coverage;               /* Offset to Coverage table--from
                                         * beginning of subtable */
@@ -753,17 +750,8 @@ struct PairPosFormat2
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    unsigned int count1 = class1Count;
-    const ClassDef &klass1 = this+classDef1;
-    for (unsigned int i = 0; i < count1; i++)
-      klass1.add_class (c->input, i);
-
-    unsigned int count2 = class2Count;
-    const ClassDef &klass2 = this+classDef2;
-    for (unsigned int i = 0; i < count2; i++)
-      klass2.add_class (c->input, i);
+    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
+    if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -771,14 +759,14 @@ struct PairPosFormat2
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
@@ -790,6 +778,7 @@ struct PairPosFormat2
     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
+    buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
     valueFormat1.apply_value (c, this, v, buffer->cur_pos());
     valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
@@ -820,7 +809,7 @@ struct PairPosFormat2
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 2 */
+  HBUINT16     format;                 /* Format identifier--format = 2 */
   OffsetTo<Coverage>
                coverage;               /* Offset to Coverage table--from
                                         * beginning of subtable */
@@ -838,9 +827,9 @@ struct PairPosFormat2
                classDef2;              /* Offset to ClassDef table--from
                                         * beginning of PairPos subtable--for
                                         * the second glyph of the pair */
-  USHORT       class1Count;            /* Number of classes in ClassDef1
+  HBUINT16     class1Count;            /* Number of classes in ClassDef1
                                         * table--includes Class0 */
-  USHORT       class2Count;            /* Number of classes in ClassDef2
+  HBUINT16     class2Count;            /* Number of classes in ClassDef2
                                         * table--includes Class0 */
   ValueRecord  values;                 /* Matrix of value pairs:
                                         * class1-major, class2-minor,
@@ -865,7 +854,7 @@ struct PairPos
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   PairPosFormat1       format1;
   PairPosFormat2       format2;
   } u;
@@ -903,7 +892,7 @@ struct CursivePosFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
+    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -911,7 +900,7 @@ struct CursivePosFormat1
     return this+coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -919,7 +908,7 @@ struct CursivePosFormat1
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
     if (!this_record.exitAnchor) return_trace (false);
 
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     if (!skippy_iter.next ()) return_trace (false);
 
@@ -929,7 +918,8 @@ struct CursivePosFormat1
     unsigned int i = buffer->idx;
     unsigned int j = skippy_iter.idx;
 
-    hb_position_t entry_x, entry_y, exit_x, exit_y;
+    buffer->unsafe_to_break (i, j);
+    float entry_x, entry_y, exit_x, exit_y;
     (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
     (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
 
@@ -939,32 +929,32 @@ struct CursivePosFormat1
     /* Main-direction adjustment */
     switch (c->direction) {
       case HB_DIRECTION_LTR:
-       pos[i].x_advance  =  exit_x + pos[i].x_offset;
+       pos[i].x_advance  = round (exit_x) + pos[i].x_offset;
 
-       d = entry_x + pos[j].x_offset;
+       d = round (entry_x) + pos[j].x_offset;
        pos[j].x_advance -= d;
        pos[j].x_offset  -= d;
        break;
       case HB_DIRECTION_RTL:
-       d = exit_x + pos[i].x_offset;
+       d = round (exit_x) + pos[i].x_offset;
        pos[i].x_advance -= d;
        pos[i].x_offset  -= d;
 
-       pos[j].x_advance  =  entry_x + pos[j].x_offset;
+       pos[j].x_advance  = round (entry_x) + pos[j].x_offset;
        break;
       case HB_DIRECTION_TTB:
-       pos[i].y_advance  =  exit_y + pos[i].y_offset;
+       pos[i].y_advance  = round (exit_y) + pos[i].y_offset;
 
-       d = entry_y + pos[j].y_offset;
+       d = round (entry_y) + pos[j].y_offset;
        pos[j].y_advance -= d;
        pos[j].y_offset  -= d;
        break;
       case HB_DIRECTION_BTT:
-       d = exit_y + pos[i].y_offset;
+       d = round (exit_y) + pos[i].y_offset;
        pos[i].y_advance -= d;
        pos[i].y_offset  -= d;
 
-       pos[j].y_advance  =  entry_y;
+       pos[j].y_advance  = round (entry_y);
        break;
       case HB_DIRECTION_INVALID:
       default:
@@ -1018,7 +1008,7 @@ struct CursivePosFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
   OffsetTo<Coverage>
                coverage;               /* Offset to Coverage table--from
                                         * beginning of subtable */
@@ -1044,7 +1034,7 @@ struct CursivePos
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   CursivePosFormat1    format1;
   } u;
 };
@@ -1060,8 +1050,8 @@ struct MarkBasePosFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+markCoverage).add_coverage (c->input);
-    (this+baseCoverage).add_coverage (c->input);
+    if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
+    if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -1069,7 +1059,7 @@ struct MarkBasePosFormat1
     return this+markCoverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1077,13 +1067,23 @@ struct MarkBasePosFormat1
     if (likely (mark_index == NOT_COVERED)) return_trace (false);
 
     /* Now we search backwards for a non-mark glyph */
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     do {
       if (!skippy_iter.prev ()) return_trace (false);
-      /* We only want to attach to the first of a MultipleSubst sequence.  Reject others. */
-      if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break;
+      /* We only want to attach to the first of a MultipleSubst sequence.
+       * https://github.com/harfbuzz/harfbuzz/issues/740
+       * Reject others. */
+      if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
+         0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
+         (skippy_iter.idx == 0 ||
+          _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
+          _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
+          _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
+          _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
+          ))
+       break;
       skippy_iter.reject ();
     } while (1);
 
@@ -1107,14 +1107,14 @@ struct MarkBasePosFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
   OffsetTo<Coverage>
                markCoverage;           /* Offset to MarkCoverage table--from
                                         * beginning of MarkBasePos subtable */
   OffsetTo<Coverage>
                baseCoverage;           /* Offset to BaseCoverage table--from
                                         * beginning of MarkBasePos subtable */
-  USHORT       classCount;             /* Number of classes defined for marks */
+  HBUINT16     classCount;             /* Number of classes defined for marks */
   OffsetTo<MarkArray>
                markArray;              /* Offset to MarkArray table--from
                                         * beginning of MarkBasePos subtable */
@@ -1140,7 +1140,7 @@ struct MarkBasePos
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   MarkBasePosFormat1   format1;
   } u;
 };
@@ -1161,8 +1161,8 @@ struct MarkLigPosFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+markCoverage).add_coverage (c->input);
-    (this+ligatureCoverage).add_coverage (c->input);
+    if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
+    if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -1170,7 +1170,7 @@ struct MarkLigPosFormat1
     return this+markCoverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1178,7 +1178,7 @@ struct MarkLigPosFormat1
     if (likely (mark_index == NOT_COVERED)) return_trace (false);
 
     /* Now we search backwards for a non-mark glyph */
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
     if (!skippy_iter.prev ()) return_trace (false);
@@ -1224,7 +1224,7 @@ struct MarkLigPosFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
   OffsetTo<Coverage>
                markCoverage;           /* Offset to Mark Coverage table--from
                                         * beginning of MarkLigPos subtable */
@@ -1232,7 +1232,7 @@ struct MarkLigPosFormat1
                ligatureCoverage;       /* Offset to Ligature Coverage
                                         * table--from beginning of MarkLigPos
                                         * subtable */
-  USHORT       classCount;             /* Number of defined mark classes */
+  HBUINT16     classCount;             /* Number of defined mark classes */
   OffsetTo<MarkArray>
                markArray;              /* Offset to MarkArray table--from
                                         * beginning of MarkLigPos subtable */
@@ -1258,7 +1258,7 @@ struct MarkLigPos
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   MarkLigPosFormat1    format1;
   } u;
 };
@@ -1274,8 +1274,8 @@ struct MarkMarkPosFormat1
   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
     TRACE_COLLECT_GLYPHS (this);
-    (this+mark1Coverage).add_coverage (c->input);
-    (this+mark2Coverage).add_coverage (c->input);
+    if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
+    if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
   }
 
   inline const Coverage &get_coverage (void) const
@@ -1283,7 +1283,7 @@ struct MarkMarkPosFormat1
     return this+mark1Coverage;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1291,7 +1291,7 @@ struct MarkMarkPosFormat1
     if (likely (mark1_index == NOT_COVERED)) return_trace (false);
 
     /* now we search backwards for a suitable mark glyph until a non-mark glyph */
-    hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+    hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
     skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
     if (!skippy_iter.prev ()) return_trace (false);
@@ -1338,7 +1338,7 @@ struct MarkMarkPosFormat1
   }
 
   protected:
-  USHORT       format;                 /* Format identifier--format = 1 */
+  HBUINT16     format;                 /* Format identifier--format = 1 */
   OffsetTo<Coverage>
                mark1Coverage;          /* Offset to Combining Mark1 Coverage
                                         * table--from beginning of MarkMarkPos
@@ -1347,7 +1347,7 @@ struct MarkMarkPosFormat1
                mark2Coverage;          /* Offset to Combining Mark2 Coverage
                                         * table--from beginning of MarkMarkPos
                                         * subtable */
-  USHORT       classCount;             /* Number of defined mark classes */
+  HBUINT16     classCount;             /* Number of defined mark classes */
   OffsetTo<MarkArray>
                mark1Array;             /* Offset to Mark1Array table--from
                                         * beginning of MarkMarkPos subtable */
@@ -1373,7 +1373,7 @@ struct MarkMarkPos
 
   protected:
   union {
-  USHORT               format;         /* Format identifier */
+  HBUINT16             format;         /* Format identifier */
   MarkMarkPosFormat1   format1;
   } u;
 };
@@ -1432,7 +1432,7 @@ struct PosLookupSubTable
 
   protected:
   union {
-  USHORT               sub_format;
+  HBUINT16             sub_format;
   SinglePos            single;
   PairPos              pair;
   CursivePos           cursive;
@@ -1458,7 +1458,7 @@ struct PosLookup : Lookup
     return false;
   }
 
-  inline bool apply (hb_apply_context_t *c) const
+  inline bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
@@ -1477,7 +1477,7 @@ struct PosLookup : Lookup
     dispatch (&c);
   }
 
-  static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
+  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
   static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
@@ -1629,7 +1629,7 @@ template <typename context_t>
   return l.dispatch (c);
 }
 
-/*static*/ inline bool PosLookup::apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index)
+/*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
   const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
   const PosLookup &l = gpos.get_lookup (lookup_index);