Imported Upstream version 2.6.7
[platform/upstream/harfbuzz.git] / src / hb-ot-layout-gpos-table.hh
1 /*
2  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
3  * Copyright © 2010,2012,2013  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28
29 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
30 #define HB_OT_LAYOUT_GPOS_TABLE_HH
31
32 #include "hb-ot-layout-gsubgpos.hh"
33
34
35 namespace OT {
36
37 struct MarkArray;
38 static void Markclass_closure_and_remap_indexes (const Coverage  &mark_coverage,
39                                                  const MarkArray &mark_array,
40                                                  const hb_set_t  &glyphset,
41                                                  hb_map_t*        klass_mapping /* INOUT */);
42
43 /* buffer **position** var allocations */
44 #define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
45 #define attach_type() var.u8[2] /* attachment type */
46 /* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
47
48 enum attach_type_t {
49   ATTACH_TYPE_NONE      = 0X00,
50
51   /* Each attachment should be either a mark or a cursive; can't be both. */
52   ATTACH_TYPE_MARK      = 0X01,
53   ATTACH_TYPE_CURSIVE   = 0X02,
54 };
55
56
57 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
58
59 typedef HBUINT16 Value;
60
61 typedef UnsizedArrayOf<Value> ValueRecord;
62
63 struct ValueFormat : HBUINT16
64 {
65   enum Flags {
66     xPlacement  = 0x0001u,      /* Includes horizontal adjustment for placement */
67     yPlacement  = 0x0002u,      /* Includes vertical adjustment for placement */
68     xAdvance    = 0x0004u,      /* Includes horizontal adjustment for advance */
69     yAdvance    = 0x0008u,      /* Includes vertical adjustment for advance */
70     xPlaDevice  = 0x0010u,      /* Includes horizontal Device table for placement */
71     yPlaDevice  = 0x0020u,      /* Includes vertical Device table for placement */
72     xAdvDevice  = 0x0040u,      /* Includes horizontal Device table for advance */
73     yAdvDevice  = 0x0080u,      /* Includes vertical Device table for advance */
74     ignored     = 0x0F00u,      /* Was used in TrueType Open for MM fonts */
75     reserved    = 0xF000u,      /* For future use */
76
77     devices     = 0x00F0u       /* Mask for having any Device table */
78   };
79
80 /* All fields are options.  Only those available advance the value pointer. */
81 #if 0
82   HBINT16               xPlacement;             /* Horizontal adjustment for
83                                          * placement--in design units */
84   HBINT16               yPlacement;             /* Vertical adjustment for
85                                          * placement--in design units */
86   HBINT16               xAdvance;               /* Horizontal adjustment for
87                                          * advance--in design units (only used
88                                          * for horizontal writing) */
89   HBINT16               yAdvance;               /* Vertical adjustment for advance--in
90                                          * design units (only used for vertical
91                                          * writing) */
92   OffsetTo<Device>      xPlaDevice;     /* Offset to Device table for
93                                          * horizontal placement--measured from
94                                          * beginning of PosTable (may be NULL) */
95   OffsetTo<Device>      yPlaDevice;     /* Offset to Device table for vertical
96                                          * placement--measured from beginning
97                                          * of PosTable (may be NULL) */
98   OffsetTo<Device>      xAdvDevice;     /* Offset to Device table for
99                                          * horizontal advance--measured from
100                                          * beginning of PosTable (may be NULL) */
101   OffsetTo<Device>      yAdvDevice;     /* Offset to Device table for vertical
102                                          * advance--measured from beginning of
103                                          * PosTable (may be NULL) */
104 #endif
105
106   unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
107   unsigned int get_size () const { return get_len () * Value::static_size; }
108
109   bool apply_value (hb_ot_apply_context_t *c,
110                     const void            *base,
111                     const Value           *values,
112                     hb_glyph_position_t   &glyph_pos) const
113   {
114     bool ret = false;
115     unsigned int format = *this;
116     if (!format) return ret;
117
118     hb_font_t *font = c->font;
119     bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
120
121     if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++, &ret));
122     if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++, &ret));
123     if (format & xAdvance) {
124       if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
125       values++;
126     }
127     /* y_advance values grow downward but font-space grows upward, hence negation */
128     if (format & yAdvance) {
129       if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
130       values++;
131     }
132
133     if (!has_device ()) return ret;
134
135     bool use_x_device = font->x_ppem || font->num_coords;
136     bool use_y_device = font->y_ppem || font->num_coords;
137
138     if (!use_x_device && !use_y_device) return ret;
139
140     const VariationStore &store = c->var_store;
141
142     /* pixel -> fractional pixel */
143     if (format & xPlaDevice) {
144       if (use_x_device) glyph_pos.x_offset  += (base + get_device (values, &ret)).get_x_delta (font, store);
145       values++;
146     }
147     if (format & yPlaDevice) {
148       if (use_y_device) glyph_pos.y_offset  += (base + get_device (values, &ret)).get_y_delta (font, store);
149       values++;
150     }
151     if (format & xAdvDevice) {
152       if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
153       values++;
154     }
155     if (format & yAdvDevice) {
156       /* y_advance values grow downward but font-space grows upward, hence negation */
157       if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
158       values++;
159     }
160     return ret;
161   }
162
163   void serialize_copy (hb_serialize_context_t *c, const void *base,
164                        const Value *values, const hb_map_t *layout_variation_idx_map) const
165   {
166     unsigned int format = *this;
167     if (!format) return;
168
169     if (format & xPlacement) c->copy (*values++);
170     if (format & yPlacement) c->copy (*values++);
171     if (format & xAdvance)   c->copy (*values++);
172     if (format & yAdvance)   c->copy (*values++);
173
174     if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
175     if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
176     if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
177     if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
178   }
179
180   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
181                                   const void *base,
182                                   const hb_array_t<const Value>& values) const
183   {
184     unsigned format = *this;
185     unsigned i = 0;
186     if (format & xPlacement) i++;
187     if (format & yPlacement) i++;
188     if (format & xAdvance) i++;
189     if (format & yAdvance) i++;
190     if (format & xPlaDevice)
191     {
192       (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
193       i++;
194     }
195
196     if (format & ValueFormat::yPlaDevice)
197     {
198       (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
199       i++;
200     }
201
202     if (format & ValueFormat::xAdvDevice)
203     {
204
205       (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
206       i++;
207     }
208
209     if (format & ValueFormat::yAdvDevice)
210     {
211
212       (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
213       i++;
214     }
215   }
216
217   private:
218   bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
219   {
220     unsigned int format = *this;
221
222     if (format & xPlacement) values++;
223     if (format & yPlacement) values++;
224     if (format & xAdvance)   values++;
225     if (format & yAdvance)   values++;
226
227     if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
228     if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
229     if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
230     if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
231
232     return true;
233   }
234
235   static inline OffsetTo<Device>& get_device (Value* value)
236   {
237     return *static_cast<OffsetTo<Device> *> (value);
238   }
239   static inline const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
240   {
241     if (worked) *worked |= bool (*value);
242     return *static_cast<const OffsetTo<Device> *> (value);
243   }
244
245   bool copy_device (hb_serialize_context_t *c, const void *base,
246                     const Value *src_value, const hb_map_t *layout_variation_idx_map) const
247   {
248     Value       *dst_value = c->copy (*src_value);
249
250     if (!dst_value) return false;
251     if (*dst_value == 0) return true;
252
253     *dst_value = 0;
254     c->push ();
255     if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
256     {
257       c->add_link (*dst_value, c->pop_pack ());
258       return true;
259     }
260     else
261     {
262       c->pop_discard ();
263       return false;
264     }
265   }
266
267   static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
268   {
269     if (worked) *worked |= bool (*value);
270     return *reinterpret_cast<const HBINT16 *> (value);
271   }
272
273   public:
274
275   bool has_device () const
276   {
277     unsigned int format = *this;
278     return (format & devices) != 0;
279   }
280
281   bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
282   {
283     TRACE_SANITIZE (this);
284     return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
285   }
286
287   bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
288   {
289     TRACE_SANITIZE (this);
290     unsigned int len = get_len ();
291
292     if (!c->check_range (values, count, get_size ())) return_trace (false);
293
294     if (!has_device ()) return_trace (true);
295
296     for (unsigned int i = 0; i < count; i++) {
297       if (!sanitize_value_devices (c, base, values))
298         return_trace (false);
299       values += len;
300     }
301
302     return_trace (true);
303   }
304
305   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
306   bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
307   {
308     TRACE_SANITIZE (this);
309
310     if (!has_device ()) return_trace (true);
311
312     for (unsigned int i = 0; i < count; i++) {
313       if (!sanitize_value_devices (c, base, values))
314         return_trace (false);
315       values += stride;
316     }
317
318     return_trace (true);
319   }
320 };
321
322 template<typename Iterator>
323 static void SinglePos_serialize (hb_serialize_context_t *c,
324                                  const void *src,
325                                  Iterator it,
326                                  ValueFormat valFormat,
327                                  const hb_map_t *layout_variation_idx_map);
328
329
330 struct AnchorFormat1
331 {
332   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
333                    float *x, float *y) const
334   {
335     hb_font_t *font = c->font;
336     *x = font->em_fscale_x (xCoordinate);
337     *y = font->em_fscale_y (yCoordinate);
338   }
339
340   bool sanitize (hb_sanitize_context_t *c) const
341   {
342     TRACE_SANITIZE (this);
343     return_trace (c->check_struct (this));
344   }
345
346   AnchorFormat1* copy (hb_serialize_context_t *c) const
347   {
348     TRACE_SERIALIZE (this);
349     return_trace (c->embed<AnchorFormat1> (this));
350   }
351
352   protected:
353   HBUINT16      format;                 /* Format identifier--format = 1 */
354   FWORD         xCoordinate;            /* Horizontal value--in design units */
355   FWORD         yCoordinate;            /* Vertical value--in design units */
356   public:
357   DEFINE_SIZE_STATIC (6);
358 };
359
360 struct AnchorFormat2
361 {
362   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
363                    float *x, float *y) const
364   {
365     hb_font_t *font = c->font;
366
367 #ifdef HB_NO_HINTING
368     *x = font->em_fscale_x (xCoordinate);
369     *y = font->em_fscale_y (yCoordinate);
370     return;
371 #endif
372
373     unsigned int x_ppem = font->x_ppem;
374     unsigned int y_ppem = font->y_ppem;
375     hb_position_t cx = 0, cy = 0;
376     bool ret;
377
378     ret = (x_ppem || y_ppem) &&
379           font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
380     *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
381     *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
382   }
383
384   bool sanitize (hb_sanitize_context_t *c) const
385   {
386     TRACE_SANITIZE (this);
387     return_trace (c->check_struct (this));
388   }
389
390   AnchorFormat2* copy (hb_serialize_context_t *c) const
391   {
392     TRACE_SERIALIZE (this);
393     return_trace (c->embed<AnchorFormat2> (this));
394   }
395
396   protected:
397   HBUINT16      format;                 /* Format identifier--format = 2 */
398   FWORD         xCoordinate;            /* Horizontal value--in design units */
399   FWORD         yCoordinate;            /* Vertical value--in design units */
400   HBUINT16      anchorPoint;            /* Index to glyph contour point */
401   public:
402   DEFINE_SIZE_STATIC (8);
403 };
404
405 struct AnchorFormat3
406 {
407   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
408                    float *x, float *y) const
409   {
410     hb_font_t *font = c->font;
411     *x = font->em_fscale_x (xCoordinate);
412     *y = font->em_fscale_y (yCoordinate);
413
414     if (font->x_ppem || font->num_coords)
415       *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
416     if (font->y_ppem || font->num_coords)
417       *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
418   }
419
420   bool sanitize (hb_sanitize_context_t *c) const
421   {
422     TRACE_SANITIZE (this);
423     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
424   }
425
426   AnchorFormat3* copy (hb_serialize_context_t *c,
427                        const hb_map_t *layout_variation_idx_map) const
428   {
429     TRACE_SERIALIZE (this);
430     if (!layout_variation_idx_map) return_trace (nullptr);
431
432     auto *out = c->embed<AnchorFormat3> (this);
433     if (unlikely (!out)) return_trace (nullptr);
434
435     out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
436     out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
437     return_trace (out);
438   }
439
440   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
441   {
442     (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
443     (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
444   }
445
446   protected:
447   HBUINT16      format;                 /* Format identifier--format = 3 */
448   FWORD         xCoordinate;            /* Horizontal value--in design units */
449   FWORD         yCoordinate;            /* Vertical value--in design units */
450   OffsetTo<Device>
451                 xDeviceTable;           /* Offset to Device table for X
452                                          * coordinate-- from beginning of
453                                          * Anchor table (may be NULL) */
454   OffsetTo<Device>
455                 yDeviceTable;           /* Offset to Device table for Y
456                                          * coordinate-- from beginning of
457                                          * Anchor table (may be NULL) */
458   public:
459   DEFINE_SIZE_STATIC (10);
460 };
461
462 struct Anchor
463 {
464   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
465                    float *x, float *y) const
466   {
467     *x = *y = 0;
468     switch (u.format) {
469     case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
470     case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
471     case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
472     default:                                          return;
473     }
474   }
475
476   bool sanitize (hb_sanitize_context_t *c) const
477   {
478     TRACE_SANITIZE (this);
479     if (!u.format.sanitize (c)) return_trace (false);
480     switch (u.format) {
481     case 1: return_trace (u.format1.sanitize (c));
482     case 2: return_trace (u.format2.sanitize (c));
483     case 3: return_trace (u.format3.sanitize (c));
484     default:return_trace (true);
485     }
486   }
487
488   Anchor* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
489   {
490     TRACE_SERIALIZE (this);
491     switch (u.format) {
492     case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c)));
493     case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c)));
494     case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c, layout_variation_idx_map)));
495     default:return_trace (nullptr);
496     }
497   }
498
499   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
500   {
501     switch (u.format) {
502     case 1: case 2:
503       return;
504     case 3:
505       u.format3.collect_variation_indices (c);
506       return;
507     default: return;
508     }
509   }
510
511   protected:
512   union {
513   HBUINT16              format;         /* Format identifier */
514   AnchorFormat1         format1;
515   AnchorFormat2         format2;
516   AnchorFormat3         format3;
517   } u;
518   public:
519   DEFINE_SIZE_UNION (2, format);
520 };
521
522
523 struct AnchorMatrix
524 {
525   const Anchor& get_anchor (unsigned int row, unsigned int col,
526                             unsigned int cols, bool *found) const
527   {
528     *found = false;
529     if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
530     *found = !matrixZ[row * cols + col].is_null ();
531     return this+matrixZ[row * cols + col];
532   }
533
534   template <typename Iterator,
535             hb_requires (hb_is_iterator (Iterator))>
536   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
537                                   Iterator index_iter) const
538   {
539     for (unsigned i : index_iter)
540       (this+matrixZ[i]).collect_variation_indices (c);
541   }
542
543   template <typename Iterator,
544             hb_requires (hb_is_iterator (Iterator))>
545   bool serialize (hb_serialize_context_t *c,
546                   unsigned                num_rows,
547                   AnchorMatrix const     *offset_matrix,
548                   const hb_map_t         *layout_variation_idx_map,
549                   Iterator                index_iter)
550   {
551     TRACE_SERIALIZE (this);
552     if (!index_iter.len ()) return_trace (false);
553     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
554
555     this->rows = num_rows;
556     for (const unsigned i : index_iter)
557     {
558       auto *offset = c->embed (offset_matrix->matrixZ[i]);
559       if (!offset) return_trace (false);
560       offset->serialize_copy (c, offset_matrix->matrixZ[i],
561                               offset_matrix, c->to_bias (this),
562                               hb_serialize_context_t::Head,
563                               layout_variation_idx_map);
564     }
565
566     return_trace (true);
567   }
568
569   bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
570   {
571     TRACE_SANITIZE (this);
572     if (!c->check_struct (this)) return_trace (false);
573     if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
574     unsigned int count = rows * cols;
575     if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
576     for (unsigned int i = 0; i < count; i++)
577       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
578     return_trace (true);
579   }
580
581   HBUINT16      rows;                   /* Number of rows */
582   UnsizedArrayOf<OffsetTo<Anchor>>
583                 matrixZ;                /* Matrix of offsets to Anchor tables--
584                                          * from beginning of AnchorMatrix table */
585   public:
586   DEFINE_SIZE_ARRAY (2, matrixZ);
587 };
588
589
590 struct MarkRecord
591 {
592   friend struct MarkArray;
593
594   unsigned get_class () const { return (unsigned) klass; }
595   bool sanitize (hb_sanitize_context_t *c, const void *base) const
596   {
597     TRACE_SANITIZE (this);
598     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
599   }
600
601   MarkRecord *copy (hb_serialize_context_t *c,
602                     const void             *src_base,
603                     unsigned                dst_bias,
604                     const hb_map_t         *klass_mapping,
605                     const hb_map_t         *layout_variation_idx_map) const
606   {
607     TRACE_SERIALIZE (this);
608     auto *out = c->embed (this);
609     if (unlikely (!out)) return_trace (nullptr);
610
611     out->klass = klass_mapping->get (klass);
612     out->markAnchor.serialize_copy (c, markAnchor, src_base, dst_bias, hb_serialize_context_t::Head, layout_variation_idx_map);
613     return_trace (out);
614   }
615
616   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
617                                   const void *src_base) const
618   {
619     (src_base+markAnchor).collect_variation_indices (c);
620   }
621
622   protected:
623   HBUINT16      klass;                  /* Class defined for this mark */
624   OffsetTo<Anchor>
625                 markAnchor;             /* Offset to Anchor table--from
626                                          * beginning of MarkArray table */
627   public:
628   DEFINE_SIZE_STATIC (4);
629 };
630
631 struct MarkArray : ArrayOf<MarkRecord>  /* Array of MarkRecords--in Coverage order */
632 {
633   bool apply (hb_ot_apply_context_t *c,
634               unsigned int mark_index, unsigned int glyph_index,
635               const AnchorMatrix &anchors, unsigned int class_count,
636               unsigned int glyph_pos) const
637   {
638     TRACE_APPLY (this);
639     hb_buffer_t *buffer = c->buffer;
640     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
641     unsigned int mark_class = record.klass;
642
643     const Anchor& mark_anchor = this + record.markAnchor;
644     bool found;
645     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
646     /* If this subtable doesn't have an anchor for this base and this class,
647      * return false such that the subsequent subtables have a chance at it. */
648     if (unlikely (!found)) return_trace (false);
649
650     float mark_x, mark_y, base_x, base_y;
651
652     buffer->unsafe_to_break (glyph_pos, buffer->idx);
653     mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
654     glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
655
656     hb_glyph_position_t &o = buffer->cur_pos();
657     o.x_offset = roundf (base_x - mark_x);
658     o.y_offset = roundf (base_y - mark_y);
659     o.attach_type() = ATTACH_TYPE_MARK;
660     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
661     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
662
663     buffer->idx++;
664     return_trace (true);
665   }
666
667   template<typename Iterator,
668            hb_requires (hb_is_source_of (Iterator, MarkRecord))>
669   bool serialize (hb_serialize_context_t *c,
670                   const hb_map_t         *klass_mapping,
671                   const hb_map_t         *layout_variation_idx_map,
672                   const void             *base,
673                   Iterator                it)
674   {
675     TRACE_SERIALIZE (this);
676     if (unlikely (!c->extend_min (*this))) return_trace (false);
677     if (unlikely (!c->check_assign (len, it.len ()))) return_trace (false);
678     c->copy_all (it, base, c->to_bias (this), klass_mapping, layout_variation_idx_map);
679     return_trace (true);
680   }
681
682   bool sanitize (hb_sanitize_context_t *c) const
683   {
684     TRACE_SANITIZE (this);
685     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
686   }
687 };
688
689
690 /* Lookups */
691
692 struct SinglePosFormat1
693 {
694   bool intersects (const hb_set_t *glyphs) const
695   { return (this+coverage).intersects (glyphs); }
696
697   void closure_lookups (hb_closure_lookups_context_t *c) const {}
698   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
699   {
700     if (!valueFormat.has_device ()) return;
701     
702     auto it =
703     + hb_iter (this+coverage)
704     | hb_filter (c->glyph_set)
705     ;
706
707     if (!it) return;
708     valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
709   }
710
711   void collect_glyphs (hb_collect_glyphs_context_t *c) const
712   { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
713
714   const Coverage &get_coverage () const { return this+coverage; }
715
716   bool apply (hb_ot_apply_context_t *c) const
717   {
718     TRACE_APPLY (this);
719     hb_buffer_t *buffer = c->buffer;
720     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
721     if (likely (index == NOT_COVERED)) return_trace (false);
722
723     valueFormat.apply_value (c, this, values, buffer->cur_pos());
724
725     buffer->idx++;
726     return_trace (true);
727   }
728
729   template<typename Iterator,
730            hb_requires (hb_is_iterator (Iterator))>
731   void serialize (hb_serialize_context_t *c,
732                   const void *src,
733                   Iterator it,
734                   ValueFormat valFormat,
735                   const hb_map_t *layout_variation_idx_map)
736   {
737     auto out = c->extend_min (*this);
738     if (unlikely (!out)) return;
739     if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
740
741     + it
742     | hb_map (hb_second)
743     | hb_apply ([&] (hb_array_t<const Value> _)
744                 { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); })
745     ;
746
747     auto glyphs =
748     + it
749     | hb_map_retains_sorting (hb_first)
750     ;
751
752     coverage.serialize (c, this).serialize (c, glyphs);
753   }
754
755   bool subset (hb_subset_context_t *c) const
756   {
757     TRACE_SUBSET (this);
758     const hb_set_t &glyphset = *c->plan->glyphset ();
759     const hb_map_t &glyph_map = *c->plan->glyph_map;
760
761     auto it =
762     + hb_iter (this+coverage)
763     | hb_filter (glyphset)
764     | hb_map_retains_sorting (glyph_map)
765     | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
766     ;
767
768     bool ret = bool (it);
769     SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map);
770     return_trace (ret);
771   }
772
773   bool sanitize (hb_sanitize_context_t *c) const
774   {
775     TRACE_SANITIZE (this);
776     return_trace (c->check_struct (this) &&
777                   coverage.sanitize (c, this) &&
778                   valueFormat.sanitize_value (c, this, values));
779   }
780
781   protected:
782   HBUINT16      format;                 /* Format identifier--format = 1 */
783   OffsetTo<Coverage>
784                 coverage;               /* Offset to Coverage table--from
785                                          * beginning of subtable */
786   ValueFormat   valueFormat;            /* Defines the types of data in the
787                                          * ValueRecord */
788   ValueRecord   values;                 /* Defines positioning
789                                          * value(s)--applied to all glyphs in
790                                          * the Coverage table */
791   public:
792   DEFINE_SIZE_ARRAY (6, values);
793 };
794
795 struct SinglePosFormat2
796 {
797   bool intersects (const hb_set_t *glyphs) const
798   { return (this+coverage).intersects (glyphs); }
799
800   void closure_lookups (hb_closure_lookups_context_t *c) const {}
801   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
802   {
803     if (!valueFormat.has_device ()) return;
804      
805     auto it =
806     + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
807     | hb_filter (c->glyph_set, hb_first)
808     ;
809
810     if (!it) return;
811
812     unsigned sub_length = valueFormat.get_len ();
813     const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
814
815     for (unsigned i : + it
816                       | hb_map (hb_second))
817       valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
818
819   }
820
821   void collect_glyphs (hb_collect_glyphs_context_t *c) const
822   { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
823
824   const Coverage &get_coverage () const { return this+coverage; }
825
826   bool apply (hb_ot_apply_context_t *c) const
827   {
828     TRACE_APPLY (this);
829     hb_buffer_t *buffer = c->buffer;
830     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
831     if (likely (index == NOT_COVERED)) return_trace (false);
832
833     if (likely (index >= valueCount)) return_trace (false);
834
835     valueFormat.apply_value (c, this,
836                              &values[index * valueFormat.get_len ()],
837                              buffer->cur_pos());
838
839     buffer->idx++;
840     return_trace (true);
841   }
842
843   template<typename Iterator,
844            hb_requires (hb_is_iterator (Iterator))>
845   void serialize (hb_serialize_context_t *c,
846                   const void *src,
847                   Iterator it,
848                   ValueFormat valFormat,
849                   const hb_map_t *layout_variation_idx_map)
850   {
851     auto out = c->extend_min (*this);
852     if (unlikely (!out)) return;
853     if (unlikely (!c->check_assign (valueFormat, valFormat))) return;
854     if (unlikely (!c->check_assign (valueCount, it.len ()))) return;
855
856     + it
857     | hb_map (hb_second)
858     | hb_apply ([&] (hb_array_t<const Value> _)
859                 { valFormat.serialize_copy (c, src, &_, layout_variation_idx_map); })
860     ;
861
862     auto glyphs =
863     + it
864     | hb_map_retains_sorting (hb_first)
865     ;
866
867     coverage.serialize (c, this).serialize (c, glyphs);
868   }
869
870   bool subset (hb_subset_context_t *c) const
871   {
872     TRACE_SUBSET (this);
873     const hb_set_t &glyphset = *c->plan->glyphset ();
874     const hb_map_t &glyph_map = *c->plan->glyph_map;
875
876     unsigned sub_length = valueFormat.get_len ();
877     auto values_array = values.as_array (valueCount * sub_length);
878
879     auto it =
880     + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
881     | hb_filter (glyphset, hb_first)
882     | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
883                               {
884                                 return hb_pair (glyph_map[_.first],
885                                                 values_array.sub_array (_.second * sub_length,
886                                                                         sub_length));
887                               })
888     ;
889
890     bool ret = bool (it);
891     SinglePos_serialize (c->serializer, this, it, valueFormat, c->plan->layout_variation_idx_map);
892     return_trace (ret);
893   }
894
895   bool sanitize (hb_sanitize_context_t *c) const
896   {
897     TRACE_SANITIZE (this);
898     return_trace (c->check_struct (this) &&
899                   coverage.sanitize (c, this) &&
900                   valueFormat.sanitize_values (c, this, values, valueCount));
901   }
902
903   protected:
904   HBUINT16      format;                 /* Format identifier--format = 2 */
905   OffsetTo<Coverage>
906                 coverage;               /* Offset to Coverage table--from
907                                          * beginning of subtable */
908   ValueFormat   valueFormat;            /* Defines the types of data in the
909                                          * ValueRecord */
910   HBUINT16      valueCount;             /* Number of ValueRecords */
911   ValueRecord   values;                 /* Array of ValueRecords--positioning
912                                          * values applied to glyphs */
913   public:
914   DEFINE_SIZE_ARRAY (8, values);
915 };
916
917 struct SinglePos
918 {
919   template<typename Iterator,
920            hb_requires (hb_is_iterator (Iterator))>
921   unsigned get_format (Iterator glyph_val_iter_pairs)
922   {
923     hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
924
925     for (const auto iter : glyph_val_iter_pairs)
926       for (const auto _ : hb_zip (iter.second, first_val_iter))
927         if (_.first != _.second)
928           return 2;
929
930     return 1;
931   }
932
933
934   template<typename Iterator,
935            hb_requires (hb_is_iterator (Iterator))>
936   void serialize (hb_serialize_context_t *c,
937                   const void *src,
938                   Iterator glyph_val_iter_pairs,
939                   ValueFormat valFormat,
940                   const hb_map_t *layout_variation_idx_map)
941   {
942     if (unlikely (!c->extend_min (u.format))) return;
943     unsigned format = 2;
944
945     if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs);
946
947     u.format = format;
948     switch (u.format) {
949     case 1: u.format1.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map);
950             return;
951     case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, valFormat, layout_variation_idx_map);
952             return;
953     default:return;
954     }
955   }
956
957   template <typename context_t, typename ...Ts>
958   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
959   {
960     TRACE_DISPATCH (this, u.format);
961     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
962     switch (u.format) {
963     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
964     case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
965     default:return_trace (c->default_return_value ());
966     }
967   }
968
969   protected:
970   union {
971   HBUINT16              format;         /* Format identifier */
972   SinglePosFormat1      format1;
973   SinglePosFormat2      format2;
974   } u;
975 };
976
977 template<typename Iterator>
978 static void
979 SinglePos_serialize (hb_serialize_context_t *c,
980                      const void *src,
981                      Iterator it,
982                      ValueFormat valFormat,
983                      const hb_map_t *layout_variation_idx_map)
984 { c->start_embed<SinglePos> ()->serialize (c, src, it, valFormat, layout_variation_idx_map); }
985
986
987 struct PairValueRecord
988 {
989   friend struct PairSet;
990
991   int cmp (hb_codepoint_t k) const
992   { return secondGlyph.cmp (k); }
993
994   struct serialize_closure_t
995   {
996     const void          *base;
997     const ValueFormat   *valueFormats;
998     unsigned            len1; /* valueFormats[0].get_len() */
999     const hb_map_t      *glyph_map;
1000     const hb_map_t      *layout_variation_idx_map;
1001   };
1002
1003   bool serialize (hb_serialize_context_t *c,
1004                   serialize_closure_t *closure) const
1005   {
1006     TRACE_SERIALIZE (this);
1007     auto *out = c->start_embed (*this);
1008     if (unlikely (!c->extend_min (out))) return_trace (false);
1009
1010     out->secondGlyph = (*closure->glyph_map)[secondGlyph];
1011
1012     closure->valueFormats[0].serialize_copy (c, closure->base, &values[0], closure->layout_variation_idx_map);
1013     closure->valueFormats[1].serialize_copy (c, closure->base, &values[closure->len1], closure->layout_variation_idx_map);
1014
1015     return_trace (true);
1016   }
1017
1018   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
1019                                   const ValueFormat *valueFormats,
1020                                   const void *base) const
1021   {
1022     unsigned record1_len = valueFormats[0].get_len ();
1023     unsigned record2_len = valueFormats[1].get_len ();
1024     const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
1025
1026     if (valueFormats[0].has_device ())
1027       valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
1028
1029     if (valueFormats[1].has_device ())
1030       valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
1031   }
1032
1033   protected:
1034   HBGlyphID     secondGlyph;            /* GlyphID of second glyph in the
1035                                          * pair--first glyph is listed in the
1036                                          * Coverage table */
1037   ValueRecord   values;                 /* Positioning data for the first glyph
1038                                          * followed by for second glyph */
1039   public:
1040   DEFINE_SIZE_ARRAY (2, values);
1041 };
1042
1043 struct PairSet
1044 {
1045   friend struct PairPosFormat1;
1046
1047   bool intersects (const hb_set_t *glyphs,
1048                    const ValueFormat *valueFormats) const
1049   {
1050     unsigned int len1 = valueFormats[0].get_len ();
1051     unsigned int len2 = valueFormats[1].get_len ();
1052     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
1053
1054     const PairValueRecord *record = &firstPairValueRecord;
1055     unsigned int count = len;
1056     for (unsigned int i = 0; i < count; i++)
1057     {
1058       if (glyphs->has (record->secondGlyph))
1059         return true;
1060       record = &StructAtOffset<const PairValueRecord> (record, record_size);
1061     }
1062     return false;
1063   }
1064
1065   void collect_glyphs (hb_collect_glyphs_context_t *c,
1066                               const ValueFormat *valueFormats) const
1067   {
1068     unsigned int len1 = valueFormats[0].get_len ();
1069     unsigned int len2 = valueFormats[1].get_len ();
1070     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
1071
1072     const PairValueRecord *record = &firstPairValueRecord;
1073     c->input->add_array (&record->secondGlyph, len, record_size);
1074   }
1075
1076   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
1077                                   const ValueFormat *valueFormats) const
1078   {
1079     unsigned len1 = valueFormats[0].get_len ();
1080     unsigned len2 = valueFormats[1].get_len ();
1081     unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
1082
1083     const PairValueRecord *record = &firstPairValueRecord;
1084     unsigned count = len;
1085     for (unsigned i = 0; i < count; i++)
1086     {
1087       if (c->glyph_set->has (record->secondGlyph))
1088       { record->collect_variation_indices (c, valueFormats, this); }
1089
1090       record = &StructAtOffset<const PairValueRecord> (record, record_size);
1091     }
1092   }
1093
1094   bool apply (hb_ot_apply_context_t *c,
1095               const ValueFormat *valueFormats,
1096               unsigned int pos) const
1097   {
1098     TRACE_APPLY (this);
1099     hb_buffer_t *buffer = c->buffer;
1100     unsigned int len1 = valueFormats[0].get_len ();
1101     unsigned int len2 = valueFormats[1].get_len ();
1102     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
1103
1104     const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
1105                                                 &firstPairValueRecord,
1106                                                 len,
1107                                                 record_size);
1108     if (record)
1109     {
1110       /* Note the intentional use of "|" instead of short-circuit "||". */
1111       if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
1112           valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
1113         buffer->unsafe_to_break (buffer->idx, pos + 1);
1114       if (len2)
1115         pos++;
1116       buffer->idx = pos;
1117       return_trace (true);
1118     }
1119     return_trace (false);
1120   }
1121
1122   bool subset (hb_subset_context_t *c,
1123                const ValueFormat valueFormats[2]) const
1124   {
1125     TRACE_SUBSET (this);
1126     auto snap = c->serializer->snapshot ();
1127
1128     auto *out = c->serializer->start_embed (*this);
1129     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1130     out->len = 0;
1131
1132     const hb_set_t &glyphset = *c->plan->glyphset ();
1133     const hb_map_t &glyph_map = *c->plan->glyph_map;
1134
1135     unsigned len1 = valueFormats[0].get_len ();
1136     unsigned len2 = valueFormats[1].get_len ();
1137     unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
1138
1139     PairValueRecord::serialize_closure_t closure =
1140     {
1141       this,
1142       valueFormats,
1143       len1,
1144       &glyph_map,
1145       c->plan->layout_variation_idx_map
1146     };
1147
1148     const PairValueRecord *record = &firstPairValueRecord;
1149     unsigned count = len, num = 0;
1150     for (unsigned i = 0; i < count; i++)
1151     {
1152       if (glyphset.has (record->secondGlyph)
1153          && record->serialize (c->serializer, &closure)) num++;
1154       record = &StructAtOffset<const PairValueRecord> (record, record_size);
1155     }
1156
1157     out->len = num;
1158     if (!num) c->serializer->revert (snap);
1159     return_trace (num);
1160   }
1161
1162   struct sanitize_closure_t
1163   {
1164     const ValueFormat *valueFormats;
1165     unsigned int len1; /* valueFormats[0].get_len() */
1166     unsigned int stride; /* 1 + len1 + len2 */
1167   };
1168
1169   bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
1170   {
1171     TRACE_SANITIZE (this);
1172     if (!(c->check_struct (this)
1173        && c->check_range (&firstPairValueRecord,
1174                           len,
1175                           HBUINT16::static_size,
1176                           closure->stride))) return_trace (false);
1177
1178     unsigned int count = len;
1179     const PairValueRecord *record = &firstPairValueRecord;
1180     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
1181                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
1182   }
1183
1184   protected:
1185   HBUINT16              len;    /* Number of PairValueRecords */
1186   PairValueRecord       firstPairValueRecord;
1187                                 /* Array of PairValueRecords--ordered
1188                                  * by GlyphID of the second glyph */
1189   public:
1190   DEFINE_SIZE_MIN (2);
1191 };
1192
1193 struct PairPosFormat1
1194 {
1195   bool intersects (const hb_set_t *glyphs) const
1196   {
1197     return
1198     + hb_zip (this+coverage, pairSet)
1199     | hb_filter (*glyphs, hb_first)
1200     | hb_map (hb_second)
1201     | hb_map ([glyphs, this] (const OffsetTo<PairSet> &_)
1202               { return (this+_).intersects (glyphs, valueFormat); })
1203     | hb_any
1204     ;
1205   }
1206
1207   void closure_lookups (hb_closure_lookups_context_t *c) const {}
1208   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
1209   {
1210     if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
1211
1212     auto it =
1213     + hb_zip (this+coverage, pairSet)
1214     | hb_filter (c->glyph_set, hb_first)
1215     | hb_map (hb_second)
1216     ;
1217
1218     if (!it) return;
1219     + it
1220     | hb_map (hb_add (this))
1221     | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
1222     ;
1223   }
1224
1225   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1226   {
1227     if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
1228     unsigned int count = pairSet.len;
1229     for (unsigned int i = 0; i < count; i++)
1230       (this+pairSet[i]).collect_glyphs (c, valueFormat);
1231   }
1232
1233   const Coverage &get_coverage () const { return this+coverage; }
1234
1235   bool apply (hb_ot_apply_context_t *c) const
1236   {
1237     TRACE_APPLY (this);
1238     hb_buffer_t *buffer = c->buffer;
1239     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
1240     if (likely (index == NOT_COVERED)) return_trace (false);
1241
1242     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1243     skippy_iter.reset (buffer->idx, 1);
1244     if (!skippy_iter.next ()) return_trace (false);
1245
1246     return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
1247   }
1248
1249   bool subset (hb_subset_context_t *c) const
1250   {
1251     TRACE_SUBSET (this);
1252
1253     const hb_set_t &glyphset = *c->plan->glyphset ();
1254     const hb_map_t &glyph_map = *c->plan->glyph_map;
1255
1256     auto *out = c->serializer->start_embed (*this);
1257     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1258     out->format = format;
1259     out->valueFormat[0] = valueFormat[0];
1260     out->valueFormat[1] = valueFormat[1];
1261
1262     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
1263
1264     + hb_zip (this+coverage, pairSet)
1265     | hb_filter (glyphset, hb_first)
1266     | hb_filter ([this, c, out] (const OffsetTo<PairSet>& _)
1267                  {
1268                    auto *o = out->pairSet.serialize_append (c->serializer);
1269                    if (unlikely (!o)) return false;
1270                    auto snap = c->serializer->snapshot ();
1271                    bool ret = o->serialize_subset (c, _, this, valueFormat);
1272                    if (!ret)
1273                    {
1274                      out->pairSet.pop ();
1275                      c->serializer->revert (snap);
1276                    }
1277                    return ret;
1278                  },
1279                  hb_second)
1280     | hb_map (hb_first)
1281     | hb_map (glyph_map)
1282     | hb_sink (new_coverage)
1283     ;
1284
1285     out->coverage.serialize (c->serializer, out)
1286                  .serialize (c->serializer, new_coverage.iter ());
1287
1288     return_trace (bool (new_coverage));
1289   }
1290
1291   bool sanitize (hb_sanitize_context_t *c) const
1292   {
1293     TRACE_SANITIZE (this);
1294
1295     if (!c->check_struct (this)) return_trace (false);
1296
1297     unsigned int len1 = valueFormat[0].get_len ();
1298     unsigned int len2 = valueFormat[1].get_len ();
1299     PairSet::sanitize_closure_t closure =
1300     {
1301       valueFormat,
1302       len1,
1303       1 + len1 + len2
1304     };
1305
1306     return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
1307   }
1308
1309   protected:
1310   HBUINT16      format;                 /* Format identifier--format = 1 */
1311   OffsetTo<Coverage>
1312                 coverage;               /* Offset to Coverage table--from
1313                                          * beginning of subtable */
1314   ValueFormat   valueFormat[2];         /* [0] Defines the types of data in
1315                                          * ValueRecord1--for the first glyph
1316                                          * in the pair--may be zero (0) */
1317                                         /* [1] Defines the types of data in
1318                                          * ValueRecord2--for the second glyph
1319                                          * in the pair--may be zero (0) */
1320   OffsetArrayOf<PairSet>
1321                 pairSet;                /* Array of PairSet tables
1322                                          * ordered by Coverage Index */
1323   public:
1324   DEFINE_SIZE_ARRAY (10, pairSet);
1325 };
1326
1327 struct PairPosFormat2
1328 {
1329   bool intersects (const hb_set_t *glyphs) const
1330   {
1331     return (this+coverage).intersects (glyphs) &&
1332            (this+classDef2).intersects (glyphs);
1333   }
1334
1335   void closure_lookups (hb_closure_lookups_context_t *c) const {}
1336   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
1337   {
1338     if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
1339
1340     hb_set_t class1_set, class2_set;
1341     for (const unsigned cp : c->glyph_set->iter ())
1342     {
1343       unsigned klass1 = (this+classDef1).get (cp);
1344       unsigned klass2 = (this+classDef2).get (cp);
1345       class1_set.add (klass1);
1346       class2_set.add (klass2);
1347     }
1348
1349     if (class1_set.is_empty () || class2_set.is_empty ()) return;
1350     
1351     unsigned len1 = valueFormat1.get_len ();
1352     unsigned len2 = valueFormat2.get_len ();
1353     const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
1354     for (const unsigned class1_idx : class1_set.iter ())
1355     {
1356       for (const unsigned class2_idx : class2_set.iter ())
1357       {
1358         unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
1359         if (valueFormat1.has_device ())
1360           valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
1361         
1362         if (valueFormat2.has_device ())
1363           valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
1364       }
1365     }
1366   }
1367
1368   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1369   {
1370     if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
1371     if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
1372   }
1373
1374   const Coverage &get_coverage () const { return this+coverage; }
1375
1376   bool apply (hb_ot_apply_context_t *c) const
1377   {
1378     TRACE_APPLY (this);
1379     hb_buffer_t *buffer = c->buffer;
1380     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
1381     if (likely (index == NOT_COVERED)) return_trace (false);
1382
1383     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1384     skippy_iter.reset (buffer->idx, 1);
1385     if (!skippy_iter.next ()) return_trace (false);
1386
1387     unsigned int len1 = valueFormat1.get_len ();
1388     unsigned int len2 = valueFormat2.get_len ();
1389     unsigned int record_len = len1 + len2;
1390
1391     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
1392     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
1393     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
1394
1395     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
1396     /* Note the intentional use of "|" instead of short-circuit "||". */
1397     if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
1398         valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
1399       buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
1400
1401     buffer->idx = skippy_iter.idx;
1402     if (len2)
1403       buffer->idx++;
1404
1405     return_trace (true);
1406   }
1407
1408   bool subset (hb_subset_context_t *c) const
1409   {
1410     TRACE_SUBSET (this);
1411     auto *out = c->serializer->start_embed (*this);
1412     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1413     out->format = format;
1414     out->valueFormat1 = valueFormat1;
1415     out->valueFormat2 = valueFormat2;
1416
1417     hb_map_t klass1_map;
1418     out->classDef1.serialize_subset (c, classDef1, this, &klass1_map);
1419     out->class1Count = klass1_map.get_population ();
1420
1421     hb_map_t klass2_map;
1422     out->classDef2.serialize_subset (c, classDef2, this, &klass2_map);
1423     out->class2Count = klass2_map.get_population ();
1424
1425     unsigned len1 = valueFormat1.get_len ();
1426     unsigned len2 = valueFormat2.get_len ();
1427
1428     + hb_range ((unsigned) class1Count)
1429     | hb_filter (klass1_map)
1430     | hb_apply ([&] (const unsigned class1_idx)
1431                 {
1432                   + hb_range ((unsigned) class2Count)
1433                   | hb_filter (klass2_map)
1434                   | hb_apply ([&] (const unsigned class2_idx)
1435                               {
1436                                 unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
1437                                 valueFormat1.serialize_copy (c->serializer, this, &values[idx], c->plan->layout_variation_idx_map);
1438                                 valueFormat2.serialize_copy (c->serializer, this, &values[idx + len1], c->plan->layout_variation_idx_map);
1439                               })
1440                   ;
1441                 })
1442     ;
1443
1444     const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
1445     const hb_map_t &glyph_map = *c->plan->glyph_map;
1446
1447     auto it =
1448     + hb_iter (this+coverage)
1449     | hb_filter (glyphset)
1450     | hb_map_retains_sorting (glyph_map)
1451     ;
1452
1453     out->coverage.serialize (c->serializer, out).serialize (c->serializer, it);
1454     return_trace (out->class1Count && out->class2Count && bool (it));
1455   }
1456
1457   bool sanitize (hb_sanitize_context_t *c) const
1458   {
1459     TRACE_SANITIZE (this);
1460     if (!(c->check_struct (this)
1461        && coverage.sanitize (c, this)
1462        && classDef1.sanitize (c, this)
1463        && classDef2.sanitize (c, this))) return_trace (false);
1464
1465     unsigned int len1 = valueFormat1.get_len ();
1466     unsigned int len2 = valueFormat2.get_len ();
1467     unsigned int stride = len1 + len2;
1468     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
1469     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
1470     return_trace (c->check_range ((const void *) values,
1471                                   count,
1472                                   record_size) &&
1473                   valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
1474                   valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
1475   }
1476
1477   protected:
1478   HBUINT16      format;                 /* Format identifier--format = 2 */
1479   OffsetTo<Coverage>
1480                 coverage;               /* Offset to Coverage table--from
1481                                          * beginning of subtable */
1482   ValueFormat   valueFormat1;           /* ValueRecord definition--for the
1483                                          * first glyph of the pair--may be zero
1484                                          * (0) */
1485   ValueFormat   valueFormat2;           /* ValueRecord definition--for the
1486                                          * second glyph of the pair--may be
1487                                          * zero (0) */
1488   OffsetTo<ClassDef>
1489                 classDef1;              /* Offset to ClassDef table--from
1490                                          * beginning of PairPos subtable--for
1491                                          * the first glyph of the pair */
1492   OffsetTo<ClassDef>
1493                 classDef2;              /* Offset to ClassDef table--from
1494                                          * beginning of PairPos subtable--for
1495                                          * the second glyph of the pair */
1496   HBUINT16      class1Count;            /* Number of classes in ClassDef1
1497                                          * table--includes Class0 */
1498   HBUINT16      class2Count;            /* Number of classes in ClassDef2
1499                                          * table--includes Class0 */
1500   ValueRecord   values;                 /* Matrix of value pairs:
1501                                          * class1-major, class2-minor,
1502                                          * Each entry has value1 and value2 */
1503   public:
1504   DEFINE_SIZE_ARRAY (16, values);
1505 };
1506
1507 struct PairPos
1508 {
1509   template <typename context_t, typename ...Ts>
1510   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
1511   {
1512     TRACE_DISPATCH (this, u.format);
1513     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1514     switch (u.format) {
1515     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
1516     case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
1517     default:return_trace (c->default_return_value ());
1518     }
1519   }
1520
1521   protected:
1522   union {
1523   HBUINT16              format;         /* Format identifier */
1524   PairPosFormat1        format1;
1525   PairPosFormat2        format2;
1526   } u;
1527 };
1528
1529
1530 struct EntryExitRecord
1531 {
1532   friend struct CursivePosFormat1;
1533
1534   bool sanitize (hb_sanitize_context_t *c, const void *base) const
1535   {
1536     TRACE_SANITIZE (this);
1537     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
1538   }
1539
1540   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
1541                                   const void *src_base) const
1542   {
1543     (src_base+entryAnchor).collect_variation_indices (c);
1544     (src_base+exitAnchor).collect_variation_indices (c);
1545   }
1546
1547   EntryExitRecord* copy (hb_serialize_context_t *c,
1548                          const void *src_base,
1549                          const void *dst_base,
1550                          const hb_map_t *layout_variation_idx_map) const
1551   {
1552     TRACE_SERIALIZE (this);
1553     auto *out = c->embed (this);
1554     if (unlikely (!out)) return_trace (nullptr);
1555
1556     out->entryAnchor.serialize_copy (c, entryAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map);
1557     out->exitAnchor.serialize_copy (c, exitAnchor, src_base, c->to_bias (dst_base), hb_serialize_context_t::Head, layout_variation_idx_map);
1558     return_trace (out);
1559   }
1560
1561   protected:
1562   OffsetTo<Anchor>
1563                 entryAnchor;            /* Offset to EntryAnchor table--from
1564                                          * beginning of CursivePos
1565                                          * subtable--may be NULL */
1566   OffsetTo<Anchor>
1567                 exitAnchor;             /* Offset to ExitAnchor table--from
1568                                          * beginning of CursivePos
1569                                          * subtable--may be NULL */
1570   public:
1571   DEFINE_SIZE_STATIC (4);
1572 };
1573
1574 static void
1575 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
1576
1577 struct CursivePosFormat1
1578 {
1579   bool intersects (const hb_set_t *glyphs) const
1580   { return (this+coverage).intersects (glyphs); }
1581
1582   void closure_lookups (hb_closure_lookups_context_t *c) const {}
1583
1584   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
1585   {
1586     + hb_zip (this+coverage, entryExitRecord)
1587     | hb_filter (c->glyph_set, hb_first)
1588     | hb_map (hb_second)
1589     | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
1590     ;
1591   }
1592
1593   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1594   { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
1595
1596   const Coverage &get_coverage () const { return this+coverage; }
1597
1598   bool apply (hb_ot_apply_context_t *c) const
1599   {
1600     TRACE_APPLY (this);
1601     hb_buffer_t *buffer = c->buffer;
1602
1603     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
1604     if (!this_record.entryAnchor) return_trace (false);
1605
1606     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1607     skippy_iter.reset (buffer->idx, 1);
1608     if (!skippy_iter.prev ()) return_trace (false);
1609
1610     const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
1611     if (!prev_record.exitAnchor) return_trace (false);
1612
1613     unsigned int i = skippy_iter.idx;
1614     unsigned int j = buffer->idx;
1615
1616     buffer->unsafe_to_break (i, j);
1617     float entry_x, entry_y, exit_x, exit_y;
1618     (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
1619     (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
1620
1621     hb_glyph_position_t *pos = buffer->pos;
1622
1623     hb_position_t d;
1624     /* Main-direction adjustment */
1625     switch (c->direction) {
1626       case HB_DIRECTION_LTR:
1627         pos[i].x_advance  = roundf (exit_x) + pos[i].x_offset;
1628
1629         d = roundf (entry_x) + pos[j].x_offset;
1630         pos[j].x_advance -= d;
1631         pos[j].x_offset  -= d;
1632         break;
1633       case HB_DIRECTION_RTL:
1634         d = roundf (exit_x) + pos[i].x_offset;
1635         pos[i].x_advance -= d;
1636         pos[i].x_offset  -= d;
1637
1638         pos[j].x_advance  = roundf (entry_x) + pos[j].x_offset;
1639         break;
1640       case HB_DIRECTION_TTB:
1641         pos[i].y_advance  = roundf (exit_y) + pos[i].y_offset;
1642
1643         d = roundf (entry_y) + pos[j].y_offset;
1644         pos[j].y_advance -= d;
1645         pos[j].y_offset  -= d;
1646         break;
1647       case HB_DIRECTION_BTT:
1648         d = roundf (exit_y) + pos[i].y_offset;
1649         pos[i].y_advance -= d;
1650         pos[i].y_offset  -= d;
1651
1652         pos[j].y_advance  = roundf (entry_y);
1653         break;
1654       case HB_DIRECTION_INVALID:
1655       default:
1656         break;
1657     }
1658
1659     /* Cross-direction adjustment */
1660
1661     /* We attach child to parent (think graph theory and rooted trees whereas
1662      * the root stays on baseline and each node aligns itself against its
1663      * parent.
1664      *
1665      * Optimize things for the case of RightToLeft, as that's most common in
1666      * Arabic. */
1667     unsigned int child  = i;
1668     unsigned int parent = j;
1669     hb_position_t x_offset = entry_x - exit_x;
1670     hb_position_t y_offset = entry_y - exit_y;
1671     if  (!(c->lookup_props & LookupFlag::RightToLeft))
1672     {
1673       unsigned int k = child;
1674       child = parent;
1675       parent = k;
1676       x_offset = -x_offset;
1677       y_offset = -y_offset;
1678     }
1679
1680     /* If child was already connected to someone else, walk through its old
1681      * chain and reverse the link direction, such that the whole tree of its
1682      * previous connection now attaches to new parent.  Watch out for case
1683      * where new parent is on the path from old chain...
1684      */
1685     reverse_cursive_minor_offset (pos, child, c->direction, parent);
1686
1687     pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
1688     pos[child].attach_chain() = (int) parent - (int) child;
1689     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
1690     if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
1691       pos[child].y_offset = y_offset;
1692     else
1693       pos[child].x_offset = x_offset;
1694
1695     buffer->idx++;
1696     return_trace (true);
1697   }
1698
1699   template <typename Iterator,
1700             hb_requires (hb_is_iterator (Iterator))>
1701   void serialize (hb_serialize_context_t *c,
1702                   Iterator it,
1703                   const void *src_base,
1704                   const hb_map_t *layout_variation_idx_map)
1705   {
1706     if (unlikely (!c->extend_min ((*this)))) return;
1707     this->format = 1;
1708     this->entryExitRecord.len = it.len ();
1709
1710     for (const EntryExitRecord& entry_record : + it
1711                                                | hb_map (hb_second))
1712       c->copy (entry_record, src_base, this, layout_variation_idx_map);
1713
1714     auto glyphs =
1715     + it
1716     | hb_map_retains_sorting (hb_first)
1717     ;
1718
1719     coverage.serialize (c, this).serialize (c, glyphs);
1720   }
1721
1722   bool subset (hb_subset_context_t *c) const
1723   {
1724     TRACE_SUBSET (this);
1725     const hb_set_t &glyphset = *c->plan->glyphset ();
1726     const hb_map_t &glyph_map = *c->plan->glyph_map;
1727
1728     auto *out = c->serializer->start_embed (*this);
1729     if (unlikely (!out)) return_trace (false);
1730
1731     auto it =
1732     + hb_zip (this+coverage, entryExitRecord)
1733     | hb_filter (glyphset, hb_first)
1734     | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
1735                               { return hb_pair (glyph_map[p.first], p.second);})
1736     ;
1737
1738     bool ret = bool (it);
1739     out->serialize (c->serializer, it, this, c->plan->layout_variation_idx_map);
1740     return_trace (ret);
1741   }
1742
1743   bool sanitize (hb_sanitize_context_t *c) const
1744   {
1745     TRACE_SANITIZE (this);
1746     return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
1747   }
1748
1749   protected:
1750   HBUINT16      format;                 /* Format identifier--format = 1 */
1751   OffsetTo<Coverage>
1752                 coverage;               /* Offset to Coverage table--from
1753                                          * beginning of subtable */
1754   ArrayOf<EntryExitRecord>
1755                 entryExitRecord;        /* Array of EntryExit records--in
1756                                          * Coverage Index order */
1757   public:
1758   DEFINE_SIZE_ARRAY (6, entryExitRecord);
1759 };
1760
1761 struct CursivePos
1762 {
1763   template <typename context_t, typename ...Ts>
1764   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
1765   {
1766     TRACE_DISPATCH (this, u.format);
1767     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1768     switch (u.format) {
1769     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
1770     default:return_trace (c->default_return_value ());
1771     }
1772   }
1773
1774   protected:
1775   union {
1776   HBUINT16              format;         /* Format identifier */
1777   CursivePosFormat1     format1;
1778   } u;
1779 };
1780
1781
1782 typedef AnchorMatrix BaseArray;         /* base-major--
1783                                          * in order of BaseCoverage Index--,
1784                                          * mark-minor--
1785                                          * ordered by class--zero-based. */
1786
1787 static void Markclass_closure_and_remap_indexes (const Coverage  &mark_coverage,
1788                                                  const MarkArray &mark_array,
1789                                                  const hb_set_t  &glyphset,
1790                                                  hb_map_t*        klass_mapping /* INOUT */)
1791 {
1792   hb_set_t orig_classes;
1793
1794   + hb_zip (mark_coverage, mark_array)
1795   | hb_filter (glyphset, hb_first)
1796   | hb_map (hb_second)
1797   | hb_map (&MarkRecord::get_class)
1798   | hb_sink (orig_classes)
1799   ;
1800
1801   unsigned idx = 0;
1802   for (auto klass : orig_classes.iter ())
1803   {
1804     if (klass_mapping->has (klass)) continue;
1805     klass_mapping->set (klass, idx);
1806     idx++;
1807   }
1808 }
1809
1810 struct MarkBasePosFormat1
1811 {
1812   bool intersects (const hb_set_t *glyphs) const
1813   { return (this+markCoverage).intersects (glyphs) &&
1814            (this+baseCoverage).intersects (glyphs); }
1815
1816   void closure_lookups (hb_closure_lookups_context_t *c) const {}
1817
1818   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
1819   {
1820     + hb_zip (this+markCoverage, this+markArray)
1821     | hb_filter (c->glyph_set, hb_first)
1822     | hb_map (hb_second)
1823     | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
1824     ;
1825
1826     hb_map_t klass_mapping;
1827     Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
1828
1829     unsigned basecount = (this+baseArray).rows;
1830     auto base_iter =
1831     + hb_zip (this+baseCoverage, hb_range (basecount))
1832     | hb_filter (c->glyph_set, hb_first)
1833     | hb_map (hb_second)
1834     ;
1835
1836     hb_sorted_vector_t<unsigned> base_indexes;
1837     for (const unsigned row : base_iter)
1838     {
1839       + hb_range ((unsigned) classCount)
1840       | hb_filter (klass_mapping)
1841       | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
1842       | hb_sink (base_indexes)
1843       ;
1844     }
1845     (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
1846   }
1847
1848   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1849   {
1850     if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
1851     if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
1852   }
1853
1854   const Coverage &get_coverage () const { return this+markCoverage; }
1855
1856   bool apply (hb_ot_apply_context_t *c) const
1857   {
1858     TRACE_APPLY (this);
1859     hb_buffer_t *buffer = c->buffer;
1860     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
1861     if (likely (mark_index == NOT_COVERED)) return_trace (false);
1862
1863     /* Now we search backwards for a non-mark glyph */
1864     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1865     skippy_iter.reset (buffer->idx, 1);
1866     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
1867     do {
1868       if (!skippy_iter.prev ()) return_trace (false);
1869       /* We only want to attach to the first of a MultipleSubst sequence.
1870        * https://github.com/harfbuzz/harfbuzz/issues/740
1871        * Reject others...
1872        * ...but stop if we find a mark in the MultipleSubst sequence:
1873        * https://github.com/harfbuzz/harfbuzz/issues/1020 */
1874       if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
1875           0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
1876           (skippy_iter.idx == 0 ||
1877            _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
1878            _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
1879            _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
1880            _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
1881            _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
1882            ))
1883         break;
1884       skippy_iter.reject ();
1885     } while (true);
1886
1887     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
1888     //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
1889
1890     unsigned int base_index = (this+baseCoverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint);
1891     if (base_index == NOT_COVERED) return_trace (false);
1892
1893     return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
1894   }
1895
1896   bool subset (hb_subset_context_t *c) const
1897   {
1898     TRACE_SUBSET (this);
1899     const hb_set_t &glyphset = *c->plan->glyphset ();
1900     const hb_map_t &glyph_map = *c->plan->glyph_map;
1901
1902     auto *out = c->serializer->start_embed (*this);
1903     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1904     out->format = format;
1905
1906     hb_map_t klass_mapping;
1907     Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
1908
1909     if (!klass_mapping.get_population ()) return_trace (false);
1910     out->classCount = klass_mapping.get_population ();
1911
1912     auto mark_iter =
1913     + hb_zip (this+markCoverage, this+markArray)
1914     | hb_filter (glyphset, hb_first)
1915     ;
1916
1917     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
1918     + mark_iter
1919     | hb_map (hb_first)
1920     | hb_map (glyph_map)
1921     | hb_sink (new_coverage)
1922     ;
1923
1924     if (!out->markCoverage.serialize (c->serializer, out)
1925                           .serialize (c->serializer, new_coverage.iter ()))
1926       return_trace (false);
1927
1928     out->markArray.serialize (c->serializer, out)
1929                   .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+markArray), + mark_iter
1930                                                                                                                    | hb_map (hb_second));
1931
1932     unsigned basecount = (this+baseArray).rows;
1933     auto base_iter =
1934     + hb_zip (this+baseCoverage, hb_range (basecount))
1935     | hb_filter (glyphset, hb_first)
1936     ;
1937
1938     new_coverage.reset ();
1939     + base_iter
1940     | hb_map (hb_first)
1941     | hb_map (glyph_map)
1942     | hb_sink (new_coverage)
1943     ;
1944
1945     if (!out->baseCoverage.serialize (c->serializer, out)
1946                           .serialize (c->serializer, new_coverage.iter ()))
1947       return_trace (false);
1948
1949     hb_sorted_vector_t<unsigned> base_indexes;
1950     for (const unsigned row : + base_iter
1951                               | hb_map (hb_second))
1952     {
1953       + hb_range ((unsigned) classCount)
1954       | hb_filter (klass_mapping)
1955       | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
1956       | hb_sink (base_indexes)
1957       ;
1958     }
1959     out->baseArray.serialize (c->serializer, out)
1960                   .serialize (c->serializer, base_iter.len (), &(this+baseArray), c->plan->layout_variation_idx_map, base_indexes.iter ());
1961
1962     return_trace (true);
1963   }
1964
1965   bool sanitize (hb_sanitize_context_t *c) const
1966   {
1967     TRACE_SANITIZE (this);
1968     return_trace (c->check_struct (this) &&
1969                   markCoverage.sanitize (c, this) &&
1970                   baseCoverage.sanitize (c, this) &&
1971                   markArray.sanitize (c, this) &&
1972                   baseArray.sanitize (c, this, (unsigned int) classCount));
1973   }
1974
1975   protected:
1976   HBUINT16      format;                 /* Format identifier--format = 1 */
1977   OffsetTo<Coverage>
1978                 markCoverage;           /* Offset to MarkCoverage table--from
1979                                          * beginning of MarkBasePos subtable */
1980   OffsetTo<Coverage>
1981                 baseCoverage;           /* Offset to BaseCoverage table--from
1982                                          * beginning of MarkBasePos subtable */
1983   HBUINT16      classCount;             /* Number of classes defined for marks */
1984   OffsetTo<MarkArray>
1985                 markArray;              /* Offset to MarkArray table--from
1986                                          * beginning of MarkBasePos subtable */
1987   OffsetTo<BaseArray>
1988                 baseArray;              /* Offset to BaseArray table--from
1989                                          * beginning of MarkBasePos subtable */
1990   public:
1991   DEFINE_SIZE_STATIC (12);
1992 };
1993
1994 struct MarkBasePos
1995 {
1996   template <typename context_t, typename ...Ts>
1997   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
1998   {
1999     TRACE_DISPATCH (this, u.format);
2000     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
2001     switch (u.format) {
2002     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
2003     default:return_trace (c->default_return_value ());
2004     }
2005   }
2006
2007   protected:
2008   union {
2009   HBUINT16              format;         /* Format identifier */
2010   MarkBasePosFormat1    format1;
2011   } u;
2012 };
2013
2014
2015 typedef AnchorMatrix LigatureAttach;    /* component-major--
2016                                          * in order of writing direction--,
2017                                          * mark-minor--
2018                                          * ordered by class--zero-based. */
2019
2020 typedef OffsetListOf<LigatureAttach> LigatureArray;
2021                                         /* Array of LigatureAttach
2022                                          * tables ordered by
2023                                          * LigatureCoverage Index */
2024
2025 struct MarkLigPosFormat1
2026 {
2027   bool intersects (const hb_set_t *glyphs) const
2028   { return (this+markCoverage).intersects (glyphs) &&
2029            (this+ligatureCoverage).intersects (glyphs); }
2030
2031   void closure_lookups (hb_closure_lookups_context_t *c) const {}
2032
2033   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
2034   {
2035     + hb_zip (this+markCoverage, this+markArray)
2036     | hb_filter (c->glyph_set, hb_first)
2037     | hb_map (hb_second)
2038     | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
2039     ;
2040
2041     hb_map_t klass_mapping;
2042     Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
2043
2044     unsigned ligcount = (this+ligatureArray).len;
2045     auto lig_iter =
2046     + hb_zip (this+ligatureCoverage, hb_range (ligcount))
2047     | hb_filter (c->glyph_set, hb_first)
2048     | hb_map (hb_second)
2049     ;
2050
2051     const LigatureArray& lig_array = this+ligatureArray;
2052     for (const unsigned i : lig_iter)
2053     {
2054       hb_sorted_vector_t<unsigned> lig_indexes;
2055       unsigned row_count = lig_array[i].rows;
2056       for (unsigned row : + hb_range (row_count))
2057       {
2058         + hb_range ((unsigned) classCount)
2059         | hb_filter (klass_mapping)
2060         | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
2061         | hb_sink (lig_indexes)
2062         ;
2063       }
2064
2065       lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
2066     }
2067   }
2068
2069   void collect_glyphs (hb_collect_glyphs_context_t *c) const
2070   {
2071     if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
2072     if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
2073   }
2074
2075   const Coverage &get_coverage () const { return this+markCoverage; }
2076
2077   bool apply (hb_ot_apply_context_t *c) const
2078   {
2079     TRACE_APPLY (this);
2080     hb_buffer_t *buffer = c->buffer;
2081     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
2082     if (likely (mark_index == NOT_COVERED)) return_trace (false);
2083
2084     /* Now we search backwards for a non-mark glyph */
2085     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
2086     skippy_iter.reset (buffer->idx, 1);
2087     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
2088     if (!skippy_iter.prev ()) return_trace (false);
2089
2090     /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
2091     //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
2092
2093     unsigned int j = skippy_iter.idx;
2094     unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[j].codepoint);
2095     if (lig_index == NOT_COVERED) return_trace (false);
2096
2097     const LigatureArray& lig_array = this+ligatureArray;
2098     const LigatureAttach& lig_attach = lig_array[lig_index];
2099
2100     /* Find component to attach to */
2101     unsigned int comp_count = lig_attach.rows;
2102     if (unlikely (!comp_count)) return_trace (false);
2103
2104     /* We must now check whether the ligature ID of the current mark glyph
2105      * is identical to the ligature ID of the found ligature.  If yes, we
2106      * can directly use the component index.  If not, we attach the mark
2107      * glyph to the last component of the ligature. */
2108     unsigned int comp_index;
2109     unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
2110     unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
2111     unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
2112     if (lig_id && lig_id == mark_id && mark_comp > 0)
2113       comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
2114     else
2115       comp_index = comp_count - 1;
2116
2117     return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
2118   }
2119
2120   bool subset (hb_subset_context_t *c) const
2121   {
2122     TRACE_SUBSET (this);
2123     // TODO(subset)
2124     return_trace (false);
2125   }
2126
2127   bool sanitize (hb_sanitize_context_t *c) const
2128   {
2129     TRACE_SANITIZE (this);
2130     return_trace (c->check_struct (this) &&
2131                   markCoverage.sanitize (c, this) &&
2132                   ligatureCoverage.sanitize (c, this) &&
2133                   markArray.sanitize (c, this) &&
2134                   ligatureArray.sanitize (c, this, (unsigned int) classCount));
2135   }
2136
2137   protected:
2138   HBUINT16      format;                 /* Format identifier--format = 1 */
2139   OffsetTo<Coverage>
2140                 markCoverage;           /* Offset to Mark Coverage table--from
2141                                          * beginning of MarkLigPos subtable */
2142   OffsetTo<Coverage>
2143                 ligatureCoverage;       /* Offset to Ligature Coverage
2144                                          * table--from beginning of MarkLigPos
2145                                          * subtable */
2146   HBUINT16      classCount;             /* Number of defined mark classes */
2147   OffsetTo<MarkArray>
2148                 markArray;              /* Offset to MarkArray table--from
2149                                          * beginning of MarkLigPos subtable */
2150   OffsetTo<LigatureArray>
2151                 ligatureArray;          /* Offset to LigatureArray table--from
2152                                          * beginning of MarkLigPos subtable */
2153   public:
2154   DEFINE_SIZE_STATIC (12);
2155 };
2156
2157 struct MarkLigPos
2158 {
2159   template <typename context_t, typename ...Ts>
2160   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
2161   {
2162     TRACE_DISPATCH (this, u.format);
2163     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
2164     switch (u.format) {
2165     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
2166     default:return_trace (c->default_return_value ());
2167     }
2168   }
2169
2170   protected:
2171   union {
2172   HBUINT16              format;         /* Format identifier */
2173   MarkLigPosFormat1     format1;
2174   } u;
2175 };
2176
2177
2178 typedef AnchorMatrix Mark2Array;        /* mark2-major--
2179                                          * in order of Mark2Coverage Index--,
2180                                          * mark1-minor--
2181                                          * ordered by class--zero-based. */
2182
2183 struct MarkMarkPosFormat1
2184 {
2185   bool intersects (const hb_set_t *glyphs) const
2186   { return (this+mark1Coverage).intersects (glyphs) &&
2187            (this+mark2Coverage).intersects (glyphs); }
2188
2189   void closure_lookups (hb_closure_lookups_context_t *c) const {}
2190
2191   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
2192   {
2193     + hb_zip (this+mark1Coverage, this+mark1Array)
2194     | hb_filter (c->glyph_set, hb_first)
2195     | hb_map (hb_second)
2196     | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
2197     ;
2198
2199     hb_map_t klass_mapping;
2200     Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
2201
2202     unsigned mark2_count = (this+mark2Array).rows;
2203     auto mark2_iter =
2204     + hb_zip (this+mark2Coverage, hb_range (mark2_count))
2205     | hb_filter (c->glyph_set, hb_first)
2206     | hb_map (hb_second)
2207     ;
2208
2209     hb_sorted_vector_t<unsigned> mark2_indexes;
2210     for (const unsigned row : mark2_iter)
2211     {
2212       + hb_range ((unsigned) classCount)
2213       | hb_filter (klass_mapping)
2214       | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
2215       | hb_sink (mark2_indexes)
2216       ;
2217     }
2218     (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
2219   }
2220
2221   void collect_glyphs (hb_collect_glyphs_context_t *c) const
2222   {
2223     if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
2224     if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
2225   }
2226
2227   const Coverage &get_coverage () const { return this+mark1Coverage; }
2228
2229   bool apply (hb_ot_apply_context_t *c) const
2230   {
2231     TRACE_APPLY (this);
2232     hb_buffer_t *buffer = c->buffer;
2233     unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
2234     if (likely (mark1_index == NOT_COVERED)) return_trace (false);
2235
2236     /* now we search backwards for a suitable mark glyph until a non-mark glyph */
2237     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
2238     skippy_iter.reset (buffer->idx, 1);
2239     skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
2240     if (!skippy_iter.prev ()) return_trace (false);
2241
2242     if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); }
2243
2244     unsigned int j = skippy_iter.idx;
2245
2246     unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
2247     unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
2248     unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
2249     unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
2250
2251     if (likely (id1 == id2)) {
2252       if (id1 == 0) /* Marks belonging to the same base. */
2253         goto good;
2254       else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
2255         goto good;
2256     } else {
2257       /* If ligature ids don't match, it may be the case that one of the marks
2258        * itself is a ligature.  In which case match. */
2259       if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
2260         goto good;
2261     }
2262
2263     /* Didn't match. */
2264     return_trace (false);
2265
2266     good:
2267     unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
2268     if (mark2_index == NOT_COVERED) return_trace (false);
2269
2270     return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
2271   }
2272
2273   bool subset (hb_subset_context_t *c) const
2274   {
2275     TRACE_SUBSET (this);
2276     const hb_set_t &glyphset = *c->plan->glyphset ();
2277     const hb_map_t &glyph_map = *c->plan->glyph_map;
2278
2279     auto *out = c->serializer->start_embed (*this);
2280     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
2281     out->format = format;
2282
2283     hb_map_t klass_mapping;
2284     Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
2285
2286     if (!klass_mapping.get_population ()) return_trace (false);
2287     out->classCount = klass_mapping.get_population ();
2288
2289     auto mark1_iter =
2290     + hb_zip (this+mark1Coverage, this+mark1Array)
2291     | hb_filter (glyphset, hb_first)
2292     ;
2293
2294     hb_sorted_vector_t<hb_codepoint_t> new_coverage;
2295     + mark1_iter
2296     | hb_map (hb_first)
2297     | hb_map (glyph_map)
2298     | hb_sink (new_coverage)
2299     ;
2300
2301     if (!out->mark1Coverage.serialize (c->serializer, out)
2302                            .serialize (c->serializer, new_coverage.iter ()))
2303       return_trace (false);
2304
2305     out->mark1Array.serialize (c->serializer, out)
2306                    .serialize (c->serializer, &klass_mapping, c->plan->layout_variation_idx_map, &(this+mark1Array), + mark1_iter
2307                                                                                                                      | hb_map (hb_second));
2308     
2309     unsigned mark2count = (this+mark2Array).rows;
2310     auto mark2_iter =
2311     + hb_zip (this+mark2Coverage, hb_range (mark2count))
2312     | hb_filter (glyphset, hb_first)
2313     ;
2314
2315     new_coverage.reset ();
2316     + mark2_iter
2317     | hb_map (hb_first)
2318     | hb_map (glyph_map)
2319     | hb_sink (new_coverage)
2320     ;
2321
2322     if (!out->mark2Coverage.serialize (c->serializer, out)
2323                            .serialize (c->serializer, new_coverage.iter ()))
2324       return_trace (false);
2325
2326     hb_sorted_vector_t<unsigned> mark2_indexes;
2327     for (const unsigned row : + mark2_iter
2328                               | hb_map (hb_second))
2329     {
2330       + hb_range ((unsigned) classCount)
2331       | hb_filter (klass_mapping)
2332       | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
2333       | hb_sink (mark2_indexes)
2334       ;
2335     }
2336     out->mark2Array.serialize (c->serializer, out)
2337                    .serialize (c->serializer, mark2_iter.len (), &(this+mark2Array), c->plan->layout_variation_idx_map, mark2_indexes.iter ());
2338
2339     return_trace (true);
2340   }
2341
2342   bool sanitize (hb_sanitize_context_t *c) const
2343   {
2344     TRACE_SANITIZE (this);
2345     return_trace (c->check_struct (this) &&
2346                   mark1Coverage.sanitize (c, this) &&
2347                   mark2Coverage.sanitize (c, this) &&
2348                   mark1Array.sanitize (c, this) &&
2349                   mark2Array.sanitize (c, this, (unsigned int) classCount));
2350   }
2351
2352   protected:
2353   HBUINT16      format;                 /* Format identifier--format = 1 */
2354   OffsetTo<Coverage>
2355                 mark1Coverage;          /* Offset to Combining Mark1 Coverage
2356                                          * table--from beginning of MarkMarkPos
2357                                          * subtable */
2358   OffsetTo<Coverage>
2359                 mark2Coverage;          /* Offset to Combining Mark2 Coverage
2360                                          * table--from beginning of MarkMarkPos
2361                                          * subtable */
2362   HBUINT16      classCount;             /* Number of defined mark classes */
2363   OffsetTo<MarkArray>
2364                 mark1Array;             /* Offset to Mark1Array table--from
2365                                          * beginning of MarkMarkPos subtable */
2366   OffsetTo<Mark2Array>
2367                 mark2Array;             /* Offset to Mark2Array table--from
2368                                          * beginning of MarkMarkPos subtable */
2369   public:
2370   DEFINE_SIZE_STATIC (12);
2371 };
2372
2373 struct MarkMarkPos
2374 {
2375   template <typename context_t, typename ...Ts>
2376   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
2377   {
2378     TRACE_DISPATCH (this, u.format);
2379     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
2380     switch (u.format) {
2381     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
2382     default:return_trace (c->default_return_value ());
2383     }
2384   }
2385
2386   protected:
2387   union {
2388   HBUINT16              format;         /* Format identifier */
2389   MarkMarkPosFormat1    format1;
2390   } u;
2391 };
2392
2393
2394 struct ContextPos : Context {};
2395
2396 struct ChainContextPos : ChainContext {};
2397
2398 struct ExtensionPos : Extension<ExtensionPos>
2399 {
2400   typedef struct PosLookupSubTable SubTable;
2401 };
2402
2403
2404
2405 /*
2406  * PosLookup
2407  */
2408
2409
2410 struct PosLookupSubTable
2411 {
2412   friend struct Lookup;
2413   friend struct PosLookup;
2414
2415   enum Type {
2416     Single              = 1,
2417     Pair                = 2,
2418     Cursive             = 3,
2419     MarkBase            = 4,
2420     MarkLig             = 5,
2421     MarkMark            = 6,
2422     Context             = 7,
2423     ChainContext        = 8,
2424     Extension           = 9
2425   };
2426
2427   template <typename context_t, typename ...Ts>
2428   typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
2429   {
2430     TRACE_DISPATCH (this, lookup_type);
2431     switch (lookup_type) {
2432     case Single:                return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
2433     case Pair:                  return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...));
2434     case Cursive:               return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...));
2435     case MarkBase:              return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...));
2436     case MarkLig:               return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...));
2437     case MarkMark:              return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...));
2438     case Context:               return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
2439     case ChainContext:          return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
2440     case Extension:             return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
2441     default:                    return_trace (c->default_return_value ());
2442     }
2443   }
2444
2445   bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
2446   {
2447     hb_intersects_context_t c (glyphs);
2448     return dispatch (&c, lookup_type);
2449   }
2450
2451   protected:
2452   union {
2453   SinglePos             single;
2454   PairPos               pair;
2455   CursivePos            cursive;
2456   MarkBasePos           markBase;
2457   MarkLigPos            markLig;
2458   MarkMarkPos           markMark;
2459   ContextPos            context;
2460   ChainContextPos       chainContext;
2461   ExtensionPos          extension;
2462   } u;
2463   public:
2464   DEFINE_SIZE_MIN (0);
2465 };
2466
2467
2468 struct PosLookup : Lookup
2469 {
2470   typedef struct PosLookupSubTable SubTable;
2471
2472   const SubTable& get_subtable (unsigned int i) const
2473   { return Lookup::get_subtable<SubTable> (i); }
2474
2475   bool is_reverse () const
2476   {
2477     return false;
2478   }
2479
2480   bool apply (hb_ot_apply_context_t *c) const
2481   {
2482     TRACE_APPLY (this);
2483     return_trace (dispatch (c));
2484   }
2485
2486   bool intersects (const hb_set_t *glyphs) const
2487   {
2488     hb_intersects_context_t c (glyphs);
2489     return dispatch (&c);
2490   }
2491
2492   hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
2493   { return dispatch (c); }
2494
2495   hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
2496   {
2497     if (c->is_lookup_visited (this_index))
2498       return hb_closure_lookups_context_t::default_return_value ();
2499
2500     c->set_lookup_visited (this_index);
2501     if (!intersects (c->glyphs))
2502     {
2503       c->set_lookup_inactive (this_index);
2504       return hb_closure_lookups_context_t::default_return_value ();
2505     }
2506     c->set_recurse_func (dispatch_closure_lookups_recurse_func);
2507
2508     hb_closure_lookups_context_t::return_t ret = dispatch (c);
2509     return ret;
2510   }
2511
2512   template <typename set_t>
2513   void collect_coverage (set_t *glyphs) const
2514   {
2515     hb_collect_coverage_context_t<set_t> c (glyphs);
2516     dispatch (&c);
2517   }
2518
2519   static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
2520
2521   template <typename context_t>
2522   static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
2523
2524   HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index);
2525
2526   template <typename context_t, typename ...Ts>
2527   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
2528   { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
2529
2530   bool subset (hb_subset_context_t *c) const
2531   { return Lookup::subset<SubTable> (c); }
2532
2533   bool sanitize (hb_sanitize_context_t *c) const
2534   { return Lookup::sanitize<SubTable> (c); }
2535 };
2536
2537 /*
2538  * GPOS -- Glyph Positioning
2539  * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
2540  */
2541
2542 struct GPOS : GSUBGPOS
2543 {
2544   static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
2545
2546   const PosLookup& get_lookup (unsigned int i) const
2547   { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
2548
2549   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
2550   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
2551   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
2552
2553   bool subset (hb_subset_context_t *c) const
2554   {
2555     hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_features);
2556     return GSUBGPOS::subset<PosLookup> (&l);
2557   }
2558
2559   bool sanitize (hb_sanitize_context_t *c) const
2560   { return GSUBGPOS::sanitize<PosLookup> (c); }
2561
2562   HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
2563                                    hb_face_t *face) const;
2564
2565   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
2566   {
2567     for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
2568     {
2569       if (!c->gpos_lookups->has (i)) continue;
2570       const PosLookup &l = get_lookup (i);
2571       l.dispatch (c);
2572     }
2573   }
2574
2575   typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
2576 };
2577
2578
2579 static void
2580 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
2581 {
2582   int chain = pos[i].attach_chain(), type = pos[i].attach_type();
2583   if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
2584     return;
2585
2586   pos[i].attach_chain() = 0;
2587
2588   unsigned int j = (int) i + chain;
2589
2590   /* Stop if we see new parent in the chain. */
2591   if (j == new_parent)
2592     return;
2593
2594   reverse_cursive_minor_offset (pos, j, direction, new_parent);
2595
2596   if (HB_DIRECTION_IS_HORIZONTAL (direction))
2597     pos[j].y_offset = -pos[i].y_offset;
2598   else
2599     pos[j].x_offset = -pos[i].x_offset;
2600
2601   pos[j].attach_chain() = -chain;
2602   pos[j].attach_type() = type;
2603 }
2604 static void
2605 propagate_attachment_offsets (hb_glyph_position_t *pos,
2606                               unsigned int len,
2607                               unsigned int i,
2608                               hb_direction_t direction)
2609 {
2610   /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
2611    * offset of glyph they are attached to. */
2612   int chain = pos[i].attach_chain(), type = pos[i].attach_type();
2613   if (likely (!chain))
2614     return;
2615
2616   pos[i].attach_chain() = 0;
2617
2618   unsigned int j = (int) i + chain;
2619
2620   if (unlikely (j >= len))
2621     return;
2622
2623   propagate_attachment_offsets (pos, len, j, direction);
2624
2625   assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
2626
2627   if (type & ATTACH_TYPE_CURSIVE)
2628   {
2629     if (HB_DIRECTION_IS_HORIZONTAL (direction))
2630       pos[i].y_offset += pos[j].y_offset;
2631     else
2632       pos[i].x_offset += pos[j].x_offset;
2633   }
2634   else /*if (type & ATTACH_TYPE_MARK)*/
2635   {
2636     pos[i].x_offset += pos[j].x_offset;
2637     pos[i].y_offset += pos[j].y_offset;
2638
2639     assert (j < i);
2640     if (HB_DIRECTION_IS_FORWARD (direction))
2641       for (unsigned int k = j; k < i; k++) {
2642         pos[i].x_offset -= pos[k].x_advance;
2643         pos[i].y_offset -= pos[k].y_advance;
2644       }
2645     else
2646       for (unsigned int k = j + 1; k < i + 1; k++) {
2647         pos[i].x_offset += pos[k].x_advance;
2648         pos[i].y_offset += pos[k].y_advance;
2649       }
2650   }
2651 }
2652
2653 void
2654 GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
2655 {
2656   unsigned int count = buffer->len;
2657   for (unsigned int i = 0; i < count; i++)
2658     buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
2659 }
2660
2661 void
2662 GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
2663 {
2664   //_hb_buffer_assert_gsubgpos_vars (buffer);
2665 }
2666
2667 void
2668 GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
2669 {
2670   _hb_buffer_assert_gsubgpos_vars (buffer);
2671
2672   unsigned int len;
2673   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
2674   hb_direction_t direction = buffer->props.direction;
2675
2676   /* Handle attachments */
2677   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
2678     for (unsigned int i = 0; i < len; i++)
2679       propagate_attachment_offsets (pos, len, i, direction);
2680 }
2681
2682
2683 struct GPOS_accelerator_t : GPOS::accelerator_t {};
2684
2685
2686 /* Out-of-class implementation for methods recursing */
2687
2688 #ifndef HB_NO_OT_LAYOUT
2689 template <typename context_t>
2690 /*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
2691 {
2692   const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
2693   return l.dispatch (c);
2694 }
2695
2696 /*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
2697 {
2698   const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index);
2699   return l.closure_lookups (c, this_index);
2700 }
2701
2702 /*static*/ bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
2703 {
2704   const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
2705   unsigned int saved_lookup_props = c->lookup_props;
2706   unsigned int saved_lookup_index = c->lookup_index;
2707   c->set_lookup_index (lookup_index);
2708   c->set_lookup_props (l.get_props ());
2709   bool ret = l.dispatch (c);
2710   c->set_lookup_index (saved_lookup_index);
2711   c->set_lookup_props (saved_lookup_props);
2712   return ret;
2713 }
2714 #endif
2715
2716
2717 } /* namespace OT */
2718
2719
2720 #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */