Imported Upstream version 2.3.1
[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
38 /* buffer **position** var allocations */
39 #define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
40 #define attach_type() var.u8[2] /* attachment type */
41 /* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
42
43 enum attach_type_t {
44   ATTACH_TYPE_NONE      = 0X00,
45
46   /* Each attachment should be either a mark or a cursive; can't be both. */
47   ATTACH_TYPE_MARK      = 0X01,
48   ATTACH_TYPE_CURSIVE   = 0X02,
49 };
50
51
52 /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
53
54 typedef HBUINT16 Value;
55
56 typedef UnsizedArrayOf<Value> ValueRecord;
57
58 struct ValueFormat : HBUINT16
59 {
60   enum Flags {
61     xPlacement  = 0x0001u,      /* Includes horizontal adjustment for placement */
62     yPlacement  = 0x0002u,      /* Includes vertical adjustment for placement */
63     xAdvance    = 0x0004u,      /* Includes horizontal adjustment for advance */
64     yAdvance    = 0x0008u,      /* Includes vertical adjustment for advance */
65     xPlaDevice  = 0x0010u,      /* Includes horizontal Device table for placement */
66     yPlaDevice  = 0x0020u,      /* Includes vertical Device table for placement */
67     xAdvDevice  = 0x0040u,      /* Includes horizontal Device table for advance */
68     yAdvDevice  = 0x0080u,      /* Includes vertical Device table for advance */
69     ignored     = 0x0F00u,      /* Was used in TrueType Open for MM fonts */
70     reserved    = 0xF000u,      /* For future use */
71
72     devices     = 0x00F0u       /* Mask for having any Device table */
73   };
74
75 /* All fields are options.  Only those available advance the value pointer. */
76 #if 0
77   HBINT16               xPlacement;             /* Horizontal adjustment for
78                                          * placement--in design units */
79   HBINT16               yPlacement;             /* Vertical adjustment for
80                                          * placement--in design units */
81   HBINT16               xAdvance;               /* Horizontal adjustment for
82                                          * advance--in design units (only used
83                                          * for horizontal writing) */
84   HBINT16               yAdvance;               /* Vertical adjustment for advance--in
85                                          * design units (only used for vertical
86                                          * writing) */
87   OffsetTo<Device>      xPlaDevice;     /* Offset to Device table for
88                                          * horizontal placement--measured from
89                                          * beginning of PosTable (may be NULL) */
90   OffsetTo<Device>      yPlaDevice;     /* Offset to Device table for vertical
91                                          * placement--measured from beginning
92                                          * of PosTable (may be NULL) */
93   OffsetTo<Device>      xAdvDevice;     /* Offset to Device table for
94                                          * horizontal advance--measured from
95                                          * beginning of PosTable (may be NULL) */
96   OffsetTo<Device>      yAdvDevice;     /* Offset to Device table for vertical
97                                          * advance--measured from beginning of
98                                          * PosTable (may be NULL) */
99 #endif
100
101   unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
102   unsigned int get_size () const { return get_len () * Value::static_size; }
103
104   bool apply_value (hb_ot_apply_context_t   *c,
105                     const void           *base,
106                     const Value          *values,
107                     hb_glyph_position_t  &glyph_pos) const
108   {
109     bool ret = false;
110     unsigned int format = *this;
111     if (!format) return ret;
112
113     hb_font_t *font = c->font;
114     bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
115
116     if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++, &ret));
117     if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++, &ret));
118     if (format & xAdvance) {
119       if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
120       values++;
121     }
122     /* y_advance values grow downward but font-space grows upward, hence negation */
123     if (format & yAdvance) {
124       if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
125       values++;
126     }
127
128     if (!has_device ()) return ret;
129
130     bool use_x_device = font->x_ppem || font->num_coords;
131     bool use_y_device = font->y_ppem || font->num_coords;
132
133     if (!use_x_device && !use_y_device) return ret;
134
135     const VariationStore &store = c->var_store;
136
137     /* pixel -> fractional pixel */
138     if (format & xPlaDevice) {
139       if (use_x_device) glyph_pos.x_offset  += (base + get_device (values, &ret)).get_x_delta (font, store);
140       values++;
141     }
142     if (format & yPlaDevice) {
143       if (use_y_device) glyph_pos.y_offset  += (base + get_device (values, &ret)).get_y_delta (font, store);
144       values++;
145     }
146     if (format & xAdvDevice) {
147       if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
148       values++;
149     }
150     if (format & yAdvDevice) {
151       /* y_advance values grow downward but font-space grows upward, hence negation */
152       if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
153       values++;
154     }
155     return ret;
156   }
157
158   private:
159   bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
160   {
161     unsigned int format = *this;
162
163     if (format & xPlacement) values++;
164     if (format & yPlacement) values++;
165     if (format & xAdvance)   values++;
166     if (format & yAdvance)   values++;
167
168     if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
169     if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
170     if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
171     if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
172
173     return true;
174   }
175
176   static OffsetTo<Device>& get_device (Value* value)
177   { return *CastP<OffsetTo<Device> > (value); }
178   static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
179   {
180     if (worked) *worked |= bool (*value);
181     return *CastP<OffsetTo<Device> > (value);
182   }
183
184   static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
185   {
186     if (worked) *worked |= bool (*value);
187     return *CastP<HBINT16> (value);
188   }
189
190   public:
191
192   bool has_device () const
193   {
194     unsigned int format = *this;
195     return (format & devices) != 0;
196   }
197
198   bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
199   {
200     TRACE_SANITIZE (this);
201     return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
202   }
203
204   bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
205   {
206     TRACE_SANITIZE (this);
207     unsigned int len = get_len ();
208
209     if (!c->check_range (values, count, get_size ())) return_trace (false);
210
211     if (!has_device ()) return_trace (true);
212
213     for (unsigned int i = 0; i < count; i++) {
214       if (!sanitize_value_devices (c, base, values))
215         return_trace (false);
216       values += len;
217     }
218
219     return_trace (true);
220   }
221
222   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
223   bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
224   {
225     TRACE_SANITIZE (this);
226
227     if (!has_device ()) return_trace (true);
228
229     for (unsigned int i = 0; i < count; i++) {
230       if (!sanitize_value_devices (c, base, values))
231         return_trace (false);
232       values += stride;
233     }
234
235     return_trace (true);
236   }
237 };
238
239
240 struct AnchorFormat1
241 {
242   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
243                    float *x, float *y) const
244   {
245     hb_font_t *font = c->font;
246     *x = font->em_fscale_x (xCoordinate);
247     *y = font->em_fscale_y (yCoordinate);
248   }
249
250   bool sanitize (hb_sanitize_context_t *c) const
251   {
252     TRACE_SANITIZE (this);
253     return_trace (c->check_struct (this));
254   }
255
256   protected:
257   HBUINT16      format;                 /* Format identifier--format = 1 */
258   FWORD         xCoordinate;            /* Horizontal value--in design units */
259   FWORD         yCoordinate;            /* Vertical value--in design units */
260   public:
261   DEFINE_SIZE_STATIC (6);
262 };
263
264 struct AnchorFormat2
265 {
266   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
267                    float *x, float *y) const
268   {
269     hb_font_t *font = c->font;
270     unsigned int x_ppem = font->x_ppem;
271     unsigned int y_ppem = font->y_ppem;
272     hb_position_t cx = 0, cy = 0;
273     bool ret;
274
275     ret = (x_ppem || y_ppem) &&
276           font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
277     *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
278     *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
279   }
280
281   bool sanitize (hb_sanitize_context_t *c) const
282   {
283     TRACE_SANITIZE (this);
284     return_trace (c->check_struct (this));
285   }
286
287   protected:
288   HBUINT16      format;                 /* Format identifier--format = 2 */
289   FWORD         xCoordinate;            /* Horizontal value--in design units */
290   FWORD         yCoordinate;            /* Vertical value--in design units */
291   HBUINT16      anchorPoint;            /* Index to glyph contour point */
292   public:
293   DEFINE_SIZE_STATIC (8);
294 };
295
296 struct AnchorFormat3
297 {
298   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
299                    float *x, float *y) const
300   {
301     hb_font_t *font = c->font;
302     *x = font->em_fscale_x (xCoordinate);
303     *y = font->em_fscale_y (yCoordinate);
304
305     if (font->x_ppem || font->num_coords)
306       *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
307     if (font->y_ppem || font->num_coords)
308       *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
309   }
310
311   bool sanitize (hb_sanitize_context_t *c) const
312   {
313     TRACE_SANITIZE (this);
314     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
315   }
316
317   protected:
318   HBUINT16      format;                 /* Format identifier--format = 3 */
319   FWORD         xCoordinate;            /* Horizontal value--in design units */
320   FWORD         yCoordinate;            /* Vertical value--in design units */
321   OffsetTo<Device>
322                 xDeviceTable;           /* Offset to Device table for X
323                                          * coordinate-- from beginning of
324                                          * Anchor table (may be NULL) */
325   OffsetTo<Device>
326                 yDeviceTable;           /* Offset to Device table for Y
327                                          * coordinate-- from beginning of
328                                          * Anchor table (may be NULL) */
329   public:
330   DEFINE_SIZE_STATIC (10);
331 };
332
333 struct Anchor
334 {
335   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
336                    float *x, float *y) const
337   {
338     *x = *y = 0;
339     switch (u.format) {
340     case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
341     case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
342     case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
343     default:                                          return;
344     }
345   }
346
347   bool sanitize (hb_sanitize_context_t *c) const
348   {
349     TRACE_SANITIZE (this);
350     if (!u.format.sanitize (c)) return_trace (false);
351     switch (u.format) {
352     case 1: return_trace (u.format1.sanitize (c));
353     case 2: return_trace (u.format2.sanitize (c));
354     case 3: return_trace (u.format3.sanitize (c));
355     default:return_trace (true);
356     }
357   }
358
359   protected:
360   union {
361   HBUINT16              format;         /* Format identifier */
362   AnchorFormat1         format1;
363   AnchorFormat2         format2;
364   AnchorFormat3         format3;
365   } u;
366   public:
367   DEFINE_SIZE_UNION (2, format);
368 };
369
370
371 struct AnchorMatrix
372 {
373   const Anchor& get_anchor (unsigned int row, unsigned int col,
374                             unsigned int cols, bool *found) const
375   {
376     *found = false;
377     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
378     *found = !matrixZ[row * cols + col].is_null ();
379     return this+matrixZ[row * cols + col];
380   }
381
382   bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
383   {
384     TRACE_SANITIZE (this);
385     if (!c->check_struct (this)) return_trace (false);
386     if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
387     unsigned int count = rows * cols;
388     if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
389     for (unsigned int i = 0; i < count; i++)
390       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
391     return_trace (true);
392   }
393
394   HBUINT16      rows;                   /* Number of rows */
395   protected:
396   UnsizedArrayOf<OffsetTo<Anchor> >
397                 matrixZ;                /* Matrix of offsets to Anchor tables--
398                                          * from beginning of AnchorMatrix table */
399   public:
400   DEFINE_SIZE_ARRAY (2, matrixZ);
401 };
402
403
404 struct MarkRecord
405 {
406   friend struct MarkArray;
407
408   bool sanitize (hb_sanitize_context_t *c, const void *base) const
409   {
410     TRACE_SANITIZE (this);
411     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
412   }
413
414   protected:
415   HBUINT16      klass;                  /* Class defined for this mark */
416   OffsetTo<Anchor>
417                 markAnchor;             /* Offset to Anchor table--from
418                                          * beginning of MarkArray table */
419   public:
420   DEFINE_SIZE_STATIC (4);
421 };
422
423 struct MarkArray : ArrayOf<MarkRecord>  /* Array of MarkRecords--in Coverage order */
424 {
425   bool apply (hb_ot_apply_context_t *c,
426               unsigned int mark_index, unsigned int glyph_index,
427               const AnchorMatrix &anchors, unsigned int class_count,
428               unsigned int glyph_pos) const
429   {
430     TRACE_APPLY (this);
431     hb_buffer_t *buffer = c->buffer;
432     const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
433     unsigned int mark_class = record.klass;
434
435     const Anchor& mark_anchor = this + record.markAnchor;
436     bool found;
437     const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
438     /* If this subtable doesn't have an anchor for this base and this class,
439      * return false such that the subsequent subtables have a chance at it. */
440     if (unlikely (!found)) return_trace (false);
441
442     float mark_x, mark_y, base_x, base_y;
443
444     buffer->unsafe_to_break (glyph_pos, buffer->idx);
445     mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
446     glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
447
448     hb_glyph_position_t &o = buffer->cur_pos();
449     o.x_offset = round (base_x - mark_x);
450     o.y_offset = round (base_y - mark_y);
451     o.attach_type() = ATTACH_TYPE_MARK;
452     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
453     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
454
455     buffer->idx++;
456     return_trace (true);
457   }
458
459   bool sanitize (hb_sanitize_context_t *c) const
460   {
461     TRACE_SANITIZE (this);
462     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
463   }
464 };
465
466
467 /* Lookups */
468
469 struct SinglePosFormat1
470 {
471   bool intersects (const hb_set_t *glyphs) const
472   { return (this+coverage).intersects (glyphs); }
473
474   void collect_glyphs (hb_collect_glyphs_context_t *c) const
475   { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
476
477   const Coverage &get_coverage () const { return this+coverage; }
478
479   bool apply (hb_ot_apply_context_t *c) const
480   {
481     TRACE_APPLY (this);
482     hb_buffer_t *buffer = c->buffer;
483     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
484     if (likely (index == NOT_COVERED)) return_trace (false);
485
486     valueFormat.apply_value (c, this, values, buffer->cur_pos());
487
488     buffer->idx++;
489     return_trace (true);
490   }
491
492   bool subset (hb_subset_context_t *c) const
493   {
494     TRACE_SUBSET (this);
495     // TODO(subset)
496     return_trace (false);
497   }
498
499   bool sanitize (hb_sanitize_context_t *c) const
500   {
501     TRACE_SANITIZE (this);
502     return_trace (c->check_struct (this) &&
503                   coverage.sanitize (c, this) &&
504                   valueFormat.sanitize_value (c, this, values));
505   }
506
507   protected:
508   HBUINT16      format;                 /* Format identifier--format = 1 */
509   OffsetTo<Coverage>
510                 coverage;               /* Offset to Coverage table--from
511                                          * beginning of subtable */
512   ValueFormat   valueFormat;            /* Defines the types of data in the
513                                          * ValueRecord */
514   ValueRecord   values;                 /* Defines positioning
515                                          * value(s)--applied to all glyphs in
516                                          * the Coverage table */
517   public:
518   DEFINE_SIZE_ARRAY (6, values);
519 };
520
521 struct SinglePosFormat2
522 {
523   bool intersects (const hb_set_t *glyphs) const
524   { return (this+coverage).intersects (glyphs); }
525
526   void collect_glyphs (hb_collect_glyphs_context_t *c) const
527   { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
528
529   const Coverage &get_coverage () const { return this+coverage; }
530
531   bool apply (hb_ot_apply_context_t *c) const
532   {
533     TRACE_APPLY (this);
534     hb_buffer_t *buffer = c->buffer;
535     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
536     if (likely (index == NOT_COVERED)) return_trace (false);
537
538     if (likely (index >= valueCount)) return_trace (false);
539
540     valueFormat.apply_value (c, this,
541                              &values[index * valueFormat.get_len ()],
542                              buffer->cur_pos());
543
544     buffer->idx++;
545     return_trace (true);
546   }
547
548   bool subset (hb_subset_context_t *c) const
549   {
550     TRACE_SUBSET (this);
551     // TODO(subset)
552     return_trace (false);
553   }
554
555   bool sanitize (hb_sanitize_context_t *c) const
556   {
557     TRACE_SANITIZE (this);
558     return_trace (c->check_struct (this) &&
559                   coverage.sanitize (c, this) &&
560                   valueFormat.sanitize_values (c, this, values, valueCount));
561   }
562
563   protected:
564   HBUINT16      format;                 /* Format identifier--format = 2 */
565   OffsetTo<Coverage>
566                 coverage;               /* Offset to Coverage table--from
567                                          * beginning of subtable */
568   ValueFormat   valueFormat;            /* Defines the types of data in the
569                                          * ValueRecord */
570   HBUINT16      valueCount;             /* Number of ValueRecords */
571   ValueRecord   values;                 /* Array of ValueRecords--positioning
572                                          * values applied to glyphs */
573   public:
574   DEFINE_SIZE_ARRAY (8, values);
575 };
576
577 struct SinglePos
578 {
579   template <typename context_t>
580   typename context_t::return_t dispatch (context_t *c) const
581   {
582     TRACE_DISPATCH (this, u.format);
583     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
584     switch (u.format) {
585     case 1: return_trace (c->dispatch (u.format1));
586     case 2: return_trace (c->dispatch (u.format2));
587     default:return_trace (c->default_return_value ());
588     }
589   }
590
591   protected:
592   union {
593   HBUINT16              format;         /* Format identifier */
594   SinglePosFormat1      format1;
595   SinglePosFormat2      format2;
596   } u;
597 };
598
599
600 struct PairValueRecord
601 {
602   friend struct PairSet;
603
604   protected:
605   GlyphID       secondGlyph;            /* GlyphID of second glyph in the
606                                          * pair--first glyph is listed in the
607                                          * Coverage table */
608   ValueRecord   values;                 /* Positioning data for the first glyph
609                                          * followed by for second glyph */
610   public:
611   DEFINE_SIZE_ARRAY (2, values);
612 };
613
614 struct PairSet
615 {
616   friend struct PairPosFormat1;
617
618   bool intersects (const hb_set_t *glyphs,
619                           const ValueFormat *valueFormats) const
620   {
621     unsigned int len1 = valueFormats[0].get_len ();
622     unsigned int len2 = valueFormats[1].get_len ();
623     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
624
625     const PairValueRecord *record = &firstPairValueRecord;
626     unsigned int count = len;
627     for (unsigned int i = 0; i < count; i++)
628     {
629       if (glyphs->has (record->secondGlyph))
630         return true;
631       record = &StructAtOffset<const PairValueRecord> (record, record_size);
632     }
633     return false;
634   }
635
636   void collect_glyphs (hb_collect_glyphs_context_t *c,
637                               const ValueFormat *valueFormats) const
638   {
639     unsigned int len1 = valueFormats[0].get_len ();
640     unsigned int len2 = valueFormats[1].get_len ();
641     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
642
643     const PairValueRecord *record = &firstPairValueRecord;
644     c->input->add_array (&record->secondGlyph, len, record_size);
645   }
646
647   bool apply (hb_ot_apply_context_t *c,
648                      const ValueFormat *valueFormats,
649                      unsigned int pos) const
650   {
651     TRACE_APPLY (this);
652     hb_buffer_t *buffer = c->buffer;
653     unsigned int len1 = valueFormats[0].get_len ();
654     unsigned int len2 = valueFormats[1].get_len ();
655     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
656
657     unsigned int count = len;
658
659     /* Hand-coded bsearch. */
660     if (unlikely (!count))
661       return_trace (false);
662     hb_codepoint_t x = buffer->info[pos].codepoint;
663     int min = 0, max = (int) count - 1;
664     while (min <= max)
665     {
666       int mid = ((unsigned int) min + (unsigned int) max) / 2;
667       const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
668       hb_codepoint_t mid_x = record->secondGlyph;
669       if (x < mid_x)
670         max = mid - 1;
671       else if (x > mid_x)
672         min = mid + 1;
673       else
674       {
675         /* Note the intentional use of "|" instead of short-circuit "||". */
676         if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
677             valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
678           buffer->unsafe_to_break (buffer->idx, pos + 1);
679         if (len2)
680           pos++;
681         buffer->idx = pos;
682         return_trace (true);
683       }
684     }
685
686     return_trace (false);
687   }
688
689   struct sanitize_closure_t
690   {
691     const void *base;
692     const ValueFormat *valueFormats;
693     unsigned int len1; /* valueFormats[0].get_len() */
694     unsigned int stride; /* 1 + len1 + len2 */
695   };
696
697   bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
698   {
699     TRACE_SANITIZE (this);
700     if (!(c->check_struct (this)
701        && c->check_range (&firstPairValueRecord,
702                           len,
703                           HBUINT16::static_size,
704                           closure->stride))) return_trace (false);
705
706     unsigned int count = len;
707     const PairValueRecord *record = &firstPairValueRecord;
708     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
709                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
710   }
711
712   protected:
713   HBUINT16              len;    /* Number of PairValueRecords */
714   PairValueRecord       firstPairValueRecord;
715                                 /* Array of PairValueRecords--ordered
716                                  * by GlyphID of the second glyph */
717   public:
718   DEFINE_SIZE_MIN (2);
719 };
720
721 struct PairPosFormat1
722 {
723   bool intersects (const hb_set_t *glyphs) const
724   {
725     unsigned int count = pairSet.len;
726     for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
727     {
728       if (unlikely (iter.get_coverage () >= count))
729         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
730       if (glyphs->has (iter.get_glyph ()) &&
731           (this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat))
732         return true;
733     }
734     return false;
735   }
736
737   void collect_glyphs (hb_collect_glyphs_context_t *c) const
738   {
739     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
740     unsigned int count = pairSet.len;
741     for (unsigned int i = 0; i < count; i++)
742       (this+pairSet[i]).collect_glyphs (c, valueFormat);
743   }
744
745   const Coverage &get_coverage () const { return this+coverage; }
746
747   bool apply (hb_ot_apply_context_t *c) const
748   {
749     TRACE_APPLY (this);
750     hb_buffer_t *buffer = c->buffer;
751     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
752     if (likely (index == NOT_COVERED)) return_trace (false);
753
754     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
755     skippy_iter.reset (buffer->idx, 1);
756     if (!skippy_iter.next ()) return_trace (false);
757
758     return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
759   }
760
761   bool subset (hb_subset_context_t *c) const
762   {
763     TRACE_SUBSET (this);
764     // TODO(subset)
765     return_trace (false);
766   }
767
768   bool sanitize (hb_sanitize_context_t *c) const
769   {
770     TRACE_SANITIZE (this);
771
772     if (!c->check_struct (this)) return_trace (false);
773
774     unsigned int len1 = valueFormat[0].get_len ();
775     unsigned int len2 = valueFormat[1].get_len ();
776     PairSet::sanitize_closure_t closure =
777     {
778       this,
779       valueFormat,
780       len1,
781       1 + len1 + len2
782     };
783
784     return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
785   }
786
787   protected:
788   HBUINT16      format;                 /* Format identifier--format = 1 */
789   OffsetTo<Coverage>
790                 coverage;               /* Offset to Coverage table--from
791                                          * beginning of subtable */
792   ValueFormat   valueFormat[2];         /* [0] Defines the types of data in
793                                          * ValueRecord1--for the first glyph
794                                          * in the pair--may be zero (0) */
795                                         /* [1] Defines the types of data in
796                                          * ValueRecord2--for the second glyph
797                                          * in the pair--may be zero (0) */
798   OffsetArrayOf<PairSet>
799                 pairSet;                /* Array of PairSet tables
800                                          * ordered by Coverage Index */
801   public:
802   DEFINE_SIZE_ARRAY (10, pairSet);
803 };
804
805 struct PairPosFormat2
806 {
807   bool intersects (const hb_set_t *glyphs) const
808   {
809     return (this+coverage).intersects (glyphs) &&
810            (this+classDef2).intersects (glyphs);
811   }
812
813   void collect_glyphs (hb_collect_glyphs_context_t *c) const
814   {
815     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
816     if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
817   }
818
819   const Coverage &get_coverage () const { return this+coverage; }
820
821   bool apply (hb_ot_apply_context_t *c) const
822   {
823     TRACE_APPLY (this);
824     hb_buffer_t *buffer = c->buffer;
825     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
826     if (likely (index == NOT_COVERED)) return_trace (false);
827
828     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
829     skippy_iter.reset (buffer->idx, 1);
830     if (!skippy_iter.next ()) return_trace (false);
831
832     unsigned int len1 = valueFormat1.get_len ();
833     unsigned int len2 = valueFormat2.get_len ();
834     unsigned int record_len = len1 + len2;
835
836     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
837     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
838     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
839
840     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
841     /* Note the intentional use of "|" instead of short-circuit "||". */
842     if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
843         valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
844       buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
845
846     buffer->idx = skippy_iter.idx;
847     if (len2)
848       buffer->idx++;
849
850     return_trace (true);
851   }
852
853   bool subset (hb_subset_context_t *c) const
854   {
855     TRACE_SUBSET (this);
856     // TODO(subset)
857     return_trace (false);
858   }
859
860   bool sanitize (hb_sanitize_context_t *c) const
861   {
862     TRACE_SANITIZE (this);
863     if (!(c->check_struct (this)
864        && coverage.sanitize (c, this)
865        && classDef1.sanitize (c, this)
866        && classDef2.sanitize (c, this))) return_trace (false);
867
868     unsigned int len1 = valueFormat1.get_len ();
869     unsigned int len2 = valueFormat2.get_len ();
870     unsigned int stride = len1 + len2;
871     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
872     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
873     return_trace (c->check_range ((const void *) values,
874                                   count,
875                                   record_size) &&
876                   valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
877                   valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
878   }
879
880   protected:
881   HBUINT16      format;                 /* Format identifier--format = 2 */
882   OffsetTo<Coverage>
883                 coverage;               /* Offset to Coverage table--from
884                                          * beginning of subtable */
885   ValueFormat   valueFormat1;           /* ValueRecord definition--for the
886                                          * first glyph of the pair--may be zero
887                                          * (0) */
888   ValueFormat   valueFormat2;           /* ValueRecord definition--for the
889                                          * second glyph of the pair--may be
890                                          * zero (0) */
891   OffsetTo<ClassDef>
892                 classDef1;              /* Offset to ClassDef table--from
893                                          * beginning of PairPos subtable--for
894                                          * the first glyph of the pair */
895   OffsetTo<ClassDef>
896                 classDef2;              /* Offset to ClassDef table--from
897                                          * beginning of PairPos subtable--for
898                                          * the second glyph of the pair */
899   HBUINT16      class1Count;            /* Number of classes in ClassDef1
900                                          * table--includes Class0 */
901   HBUINT16      class2Count;            /* Number of classes in ClassDef2
902                                          * table--includes Class0 */
903   ValueRecord   values;                 /* Matrix of value pairs:
904                                          * class1-major, class2-minor,
905                                          * Each entry has value1 and value2 */
906   public:
907   DEFINE_SIZE_ARRAY (16, values);
908 };
909
910 struct PairPos
911 {
912   template <typename context_t>
913   typename context_t::return_t dispatch (context_t *c) const
914   {
915     TRACE_DISPATCH (this, u.format);
916     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
917     switch (u.format) {
918     case 1: return_trace (c->dispatch (u.format1));
919     case 2: return_trace (c->dispatch (u.format2));
920     default:return_trace (c->default_return_value ());
921     }
922   }
923
924   protected:
925   union {
926   HBUINT16              format;         /* Format identifier */
927   PairPosFormat1        format1;
928   PairPosFormat2        format2;
929   } u;
930 };
931
932
933 struct EntryExitRecord
934 {
935   friend struct CursivePosFormat1;
936
937   bool sanitize (hb_sanitize_context_t *c, const void *base) const
938   {
939     TRACE_SANITIZE (this);
940     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
941   }
942
943   protected:
944   OffsetTo<Anchor>
945                 entryAnchor;            /* Offset to EntryAnchor table--from
946                                          * beginning of CursivePos
947                                          * subtable--may be NULL */
948   OffsetTo<Anchor>
949                 exitAnchor;             /* Offset to ExitAnchor table--from
950                                          * beginning of CursivePos
951                                          * subtable--may be NULL */
952   public:
953   DEFINE_SIZE_STATIC (4);
954 };
955
956 static void
957 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
958
959 struct CursivePosFormat1
960 {
961   bool intersects (const hb_set_t *glyphs) const
962   { return (this+coverage).intersects (glyphs); }
963
964   void collect_glyphs (hb_collect_glyphs_context_t *c) const
965   { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
966
967   const Coverage &get_coverage () const { return this+coverage; }
968
969   bool apply (hb_ot_apply_context_t *c) const
970   {
971     TRACE_APPLY (this);
972     hb_buffer_t *buffer = c->buffer;
973
974     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
975     if (!this_record.entryAnchor) return_trace (false);
976
977     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
978     skippy_iter.reset (buffer->idx, 1);
979     if (!skippy_iter.prev ()) return_trace (false);
980
981     const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
982     if (!prev_record.exitAnchor) return_trace (false);
983
984     unsigned int i = skippy_iter.idx;
985     unsigned int j = buffer->idx;
986
987     buffer->unsafe_to_break (i, j);
988     float entry_x, entry_y, exit_x, exit_y;
989     (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
990     (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
991
992     hb_glyph_position_t *pos = buffer->pos;
993
994     hb_position_t d;
995     /* Main-direction adjustment */
996     switch (c->direction) {
997       case HB_DIRECTION_LTR:
998         pos[i].x_advance  = round (exit_x) + pos[i].x_offset;
999
1000         d = round (entry_x) + pos[j].x_offset;
1001         pos[j].x_advance -= d;
1002         pos[j].x_offset  -= d;
1003         break;
1004       case HB_DIRECTION_RTL:
1005         d = round (exit_x) + pos[i].x_offset;
1006         pos[i].x_advance -= d;
1007         pos[i].x_offset  -= d;
1008
1009         pos[j].x_advance  = round (entry_x) + pos[j].x_offset;
1010         break;
1011       case HB_DIRECTION_TTB:
1012         pos[i].y_advance  = round (exit_y) + pos[i].y_offset;
1013
1014         d = round (entry_y) + pos[j].y_offset;
1015         pos[j].y_advance -= d;
1016         pos[j].y_offset  -= d;
1017         break;
1018       case HB_DIRECTION_BTT:
1019         d = round (exit_y) + pos[i].y_offset;
1020         pos[i].y_advance -= d;
1021         pos[i].y_offset  -= d;
1022
1023         pos[j].y_advance  = round (entry_y);
1024         break;
1025       case HB_DIRECTION_INVALID:
1026       default:
1027         break;
1028     }
1029
1030     /* Cross-direction adjustment */
1031
1032     /* We attach child to parent (think graph theory and rooted trees whereas
1033      * the root stays on baseline and each node aligns itself against its
1034      * parent.
1035      *
1036      * Optimize things for the case of RightToLeft, as that's most common in
1037      * Arabic. */
1038     unsigned int child  = i;
1039     unsigned int parent = j;
1040     hb_position_t x_offset = entry_x - exit_x;
1041     hb_position_t y_offset = entry_y - exit_y;
1042     if  (!(c->lookup_props & LookupFlag::RightToLeft))
1043     {
1044       unsigned int k = child;
1045       child = parent;
1046       parent = k;
1047       x_offset = -x_offset;
1048       y_offset = -y_offset;
1049     }
1050
1051     /* If child was already connected to someone else, walk through its old
1052      * chain and reverse the link direction, such that the whole tree of its
1053      * previous connection now attaches to new parent.  Watch out for case
1054      * where new parent is on the path from old chain...
1055      */
1056     reverse_cursive_minor_offset (pos, child, c->direction, parent);
1057
1058     pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
1059     pos[child].attach_chain() = (int) parent - (int) child;
1060     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
1061     if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
1062       pos[child].y_offset = y_offset;
1063     else
1064       pos[child].x_offset = x_offset;
1065
1066     buffer->idx++;
1067     return_trace (true);
1068   }
1069
1070   bool subset (hb_subset_context_t *c) const
1071   {
1072     TRACE_SUBSET (this);
1073     // TODO(subset)
1074     return_trace (false);
1075   }
1076
1077   bool sanitize (hb_sanitize_context_t *c) const
1078   {
1079     TRACE_SANITIZE (this);
1080     return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
1081   }
1082
1083   protected:
1084   HBUINT16      format;                 /* Format identifier--format = 1 */
1085   OffsetTo<Coverage>
1086                 coverage;               /* Offset to Coverage table--from
1087                                          * beginning of subtable */
1088   ArrayOf<EntryExitRecord>
1089                 entryExitRecord;        /* Array of EntryExit records--in
1090                                          * Coverage Index order */
1091   public:
1092   DEFINE_SIZE_ARRAY (6, entryExitRecord);
1093 };
1094
1095 struct CursivePos
1096 {
1097   template <typename context_t>
1098   typename context_t::return_t dispatch (context_t *c) const
1099   {
1100     TRACE_DISPATCH (this, u.format);
1101     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1102     switch (u.format) {
1103     case 1: return_trace (c->dispatch (u.format1));
1104     default:return_trace (c->default_return_value ());
1105     }
1106   }
1107
1108   protected:
1109   union {
1110   HBUINT16              format;         /* Format identifier */
1111   CursivePosFormat1     format1;
1112   } u;
1113 };
1114
1115
1116 typedef AnchorMatrix BaseArray;         /* base-major--
1117                                          * in order of BaseCoverage Index--,
1118                                          * mark-minor--
1119                                          * ordered by class--zero-based. */
1120
1121 struct MarkBasePosFormat1
1122 {
1123   bool intersects (const hb_set_t *glyphs) const
1124   { return (this+markCoverage).intersects (glyphs) &&
1125            (this+baseCoverage).intersects (glyphs); }
1126
1127   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1128   {
1129     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
1130     if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
1131   }
1132
1133   const Coverage &get_coverage () const { return this+markCoverage; }
1134
1135   bool apply (hb_ot_apply_context_t *c) const
1136   {
1137     TRACE_APPLY (this);
1138     hb_buffer_t *buffer = c->buffer;
1139     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
1140     if (likely (mark_index == NOT_COVERED)) return_trace (false);
1141
1142     /* Now we search backwards for a non-mark glyph */
1143     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1144     skippy_iter.reset (buffer->idx, 1);
1145     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
1146     do {
1147       if (!skippy_iter.prev ()) return_trace (false);
1148       /* We only want to attach to the first of a MultipleSubst sequence.
1149        * https://github.com/harfbuzz/harfbuzz/issues/740
1150        * Reject others...
1151        * ...but stop if we find a mark in the MultipleSubst sequence:
1152        * https://github.com/harfbuzz/harfbuzz/issues/1020 */
1153       if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
1154           0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
1155           (skippy_iter.idx == 0 ||
1156            _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
1157            _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
1158            _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
1159            _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
1160            _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
1161            ))
1162         break;
1163       skippy_iter.reject ();
1164     } while (true);
1165
1166     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
1167     //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
1168
1169     unsigned int base_index = (this+baseCoverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint);
1170     if (base_index == NOT_COVERED) return_trace (false);
1171
1172     return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
1173   }
1174
1175   bool subset (hb_subset_context_t *c) const
1176   {
1177     TRACE_SUBSET (this);
1178     // TODO(subset)
1179     return_trace (false);
1180   }
1181
1182   bool sanitize (hb_sanitize_context_t *c) const
1183   {
1184     TRACE_SANITIZE (this);
1185     return_trace (c->check_struct (this) &&
1186                   markCoverage.sanitize (c, this) &&
1187                   baseCoverage.sanitize (c, this) &&
1188                   markArray.sanitize (c, this) &&
1189                   baseArray.sanitize (c, this, (unsigned int) classCount));
1190   }
1191
1192   protected:
1193   HBUINT16      format;                 /* Format identifier--format = 1 */
1194   OffsetTo<Coverage>
1195                 markCoverage;           /* Offset to MarkCoverage table--from
1196                                          * beginning of MarkBasePos subtable */
1197   OffsetTo<Coverage>
1198                 baseCoverage;           /* Offset to BaseCoverage table--from
1199                                          * beginning of MarkBasePos subtable */
1200   HBUINT16      classCount;             /* Number of classes defined for marks */
1201   OffsetTo<MarkArray>
1202                 markArray;              /* Offset to MarkArray table--from
1203                                          * beginning of MarkBasePos subtable */
1204   OffsetTo<BaseArray>
1205                 baseArray;              /* Offset to BaseArray table--from
1206                                          * beginning of MarkBasePos subtable */
1207   public:
1208   DEFINE_SIZE_STATIC (12);
1209 };
1210
1211 struct MarkBasePos
1212 {
1213   template <typename context_t>
1214   typename context_t::return_t dispatch (context_t *c) const
1215   {
1216     TRACE_DISPATCH (this, u.format);
1217     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1218     switch (u.format) {
1219     case 1: return_trace (c->dispatch (u.format1));
1220     default:return_trace (c->default_return_value ());
1221     }
1222   }
1223
1224   protected:
1225   union {
1226   HBUINT16              format;         /* Format identifier */
1227   MarkBasePosFormat1    format1;
1228   } u;
1229 };
1230
1231
1232 typedef AnchorMatrix LigatureAttach;    /* component-major--
1233                                          * in order of writing direction--,
1234                                          * mark-minor--
1235                                          * ordered by class--zero-based. */
1236
1237 typedef OffsetListOf<LigatureAttach> LigatureArray;
1238                                         /* Array of LigatureAttach
1239                                          * tables ordered by
1240                                          * LigatureCoverage Index */
1241
1242 struct MarkLigPosFormat1
1243 {
1244   bool intersects (const hb_set_t *glyphs) const
1245   { return (this+markCoverage).intersects (glyphs) &&
1246            (this+ligatureCoverage).intersects (glyphs); }
1247
1248   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1249   {
1250     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
1251     if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
1252   }
1253
1254   const Coverage &get_coverage () const { return this+markCoverage; }
1255
1256   bool apply (hb_ot_apply_context_t *c) const
1257   {
1258     TRACE_APPLY (this);
1259     hb_buffer_t *buffer = c->buffer;
1260     unsigned int mark_index = (this+markCoverage).get_coverage  (buffer->cur().codepoint);
1261     if (likely (mark_index == NOT_COVERED)) return_trace (false);
1262
1263     /* Now we search backwards for a non-mark glyph */
1264     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1265     skippy_iter.reset (buffer->idx, 1);
1266     skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
1267     if (!skippy_iter.prev ()) return_trace (false);
1268
1269     /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
1270     //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
1271
1272     unsigned int j = skippy_iter.idx;
1273     unsigned int lig_index = (this+ligatureCoverage).get_coverage  (buffer->info[j].codepoint);
1274     if (lig_index == NOT_COVERED) return_trace (false);
1275
1276     const LigatureArray& lig_array = this+ligatureArray;
1277     const LigatureAttach& lig_attach = lig_array[lig_index];
1278
1279     /* Find component to attach to */
1280     unsigned int comp_count = lig_attach.rows;
1281     if (unlikely (!comp_count)) return_trace (false);
1282
1283     /* We must now check whether the ligature ID of the current mark glyph
1284      * is identical to the ligature ID of the found ligature.  If yes, we
1285      * can directly use the component index.  If not, we attach the mark
1286      * glyph to the last component of the ligature. */
1287     unsigned int comp_index;
1288     unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
1289     unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1290     unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
1291     if (lig_id && lig_id == mark_id && mark_comp > 0)
1292       comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
1293     else
1294       comp_index = comp_count - 1;
1295
1296     return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
1297   }
1298
1299   bool subset (hb_subset_context_t *c) const
1300   {
1301     TRACE_SUBSET (this);
1302     // TODO(subset)
1303     return_trace (false);
1304   }
1305
1306   bool sanitize (hb_sanitize_context_t *c) const
1307   {
1308     TRACE_SANITIZE (this);
1309     return_trace (c->check_struct (this) &&
1310                   markCoverage.sanitize (c, this) &&
1311                   ligatureCoverage.sanitize (c, this) &&
1312                   markArray.sanitize (c, this) &&
1313                   ligatureArray.sanitize (c, this, (unsigned int) classCount));
1314   }
1315
1316   protected:
1317   HBUINT16      format;                 /* Format identifier--format = 1 */
1318   OffsetTo<Coverage>
1319                 markCoverage;           /* Offset to Mark Coverage table--from
1320                                          * beginning of MarkLigPos subtable */
1321   OffsetTo<Coverage>
1322                 ligatureCoverage;       /* Offset to Ligature Coverage
1323                                          * table--from beginning of MarkLigPos
1324                                          * subtable */
1325   HBUINT16      classCount;             /* Number of defined mark classes */
1326   OffsetTo<MarkArray>
1327                 markArray;              /* Offset to MarkArray table--from
1328                                          * beginning of MarkLigPos subtable */
1329   OffsetTo<LigatureArray>
1330                 ligatureArray;          /* Offset to LigatureArray table--from
1331                                          * beginning of MarkLigPos subtable */
1332   public:
1333   DEFINE_SIZE_STATIC (12);
1334 };
1335
1336 struct MarkLigPos
1337 {
1338   template <typename context_t>
1339   typename context_t::return_t dispatch (context_t *c) const
1340   {
1341     TRACE_DISPATCH (this, u.format);
1342     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1343     switch (u.format) {
1344     case 1: return_trace (c->dispatch (u.format1));
1345     default:return_trace (c->default_return_value ());
1346     }
1347   }
1348
1349   protected:
1350   union {
1351   HBUINT16              format;         /* Format identifier */
1352   MarkLigPosFormat1     format1;
1353   } u;
1354 };
1355
1356
1357 typedef AnchorMatrix Mark2Array;        /* mark2-major--
1358                                          * in order of Mark2Coverage Index--,
1359                                          * mark1-minor--
1360                                          * ordered by class--zero-based. */
1361
1362 struct MarkMarkPosFormat1
1363 {
1364   bool intersects (const hb_set_t *glyphs) const
1365   { return (this+mark1Coverage).intersects (glyphs) &&
1366            (this+mark2Coverage).intersects (glyphs); }
1367
1368   void collect_glyphs (hb_collect_glyphs_context_t *c) const
1369   {
1370     if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
1371     if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
1372   }
1373
1374   const Coverage &get_coverage () const { return this+mark1Coverage; }
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 mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
1381     if (likely (mark1_index == NOT_COVERED)) return_trace (false);
1382
1383     /* now we search backwards for a suitable mark glyph until a non-mark glyph */
1384     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
1385     skippy_iter.reset (buffer->idx, 1);
1386     skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
1387     if (!skippy_iter.prev ()) return_trace (false);
1388
1389     if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return_trace (false); }
1390
1391     unsigned int j = skippy_iter.idx;
1392
1393     unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
1394     unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
1395     unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
1396     unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
1397
1398     if (likely (id1 == id2)) {
1399       if (id1 == 0) /* Marks belonging to the same base. */
1400         goto good;
1401       else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
1402         goto good;
1403     } else {
1404       /* If ligature ids don't match, it may be the case that one of the marks
1405        * itself is a ligature.  In which case match. */
1406       if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
1407         goto good;
1408     }
1409
1410     /* Didn't match. */
1411     return_trace (false);
1412
1413     good:
1414     unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
1415     if (mark2_index == NOT_COVERED) return_trace (false);
1416
1417     return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
1418   }
1419
1420   bool subset (hb_subset_context_t *c) const
1421   {
1422     TRACE_SUBSET (this);
1423     // TODO(subset)
1424     return_trace (false);
1425   }
1426
1427   bool sanitize (hb_sanitize_context_t *c) const
1428   {
1429     TRACE_SANITIZE (this);
1430     return_trace (c->check_struct (this) &&
1431                   mark1Coverage.sanitize (c, this) &&
1432                   mark2Coverage.sanitize (c, this) &&
1433                   mark1Array.sanitize (c, this) &&
1434                   mark2Array.sanitize (c, this, (unsigned int) classCount));
1435   }
1436
1437   protected:
1438   HBUINT16      format;                 /* Format identifier--format = 1 */
1439   OffsetTo<Coverage>
1440                 mark1Coverage;          /* Offset to Combining Mark1 Coverage
1441                                          * table--from beginning of MarkMarkPos
1442                                          * subtable */
1443   OffsetTo<Coverage>
1444                 mark2Coverage;          /* Offset to Combining Mark2 Coverage
1445                                          * table--from beginning of MarkMarkPos
1446                                          * subtable */
1447   HBUINT16      classCount;             /* Number of defined mark classes */
1448   OffsetTo<MarkArray>
1449                 mark1Array;             /* Offset to Mark1Array table--from
1450                                          * beginning of MarkMarkPos subtable */
1451   OffsetTo<Mark2Array>
1452                 mark2Array;             /* Offset to Mark2Array table--from
1453                                          * beginning of MarkMarkPos subtable */
1454   public:
1455   DEFINE_SIZE_STATIC (12);
1456 };
1457
1458 struct MarkMarkPos
1459 {
1460   template <typename context_t>
1461   typename context_t::return_t dispatch (context_t *c) const
1462   {
1463     TRACE_DISPATCH (this, u.format);
1464     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1465     switch (u.format) {
1466     case 1: return_trace (c->dispatch (u.format1));
1467     default:return_trace (c->default_return_value ());
1468     }
1469   }
1470
1471   protected:
1472   union {
1473   HBUINT16              format;         /* Format identifier */
1474   MarkMarkPosFormat1    format1;
1475   } u;
1476 };
1477
1478
1479 struct ContextPos : Context {};
1480
1481 struct ChainContextPos : ChainContext {};
1482
1483 struct ExtensionPos : Extension<ExtensionPos>
1484 {
1485   typedef struct PosLookupSubTable SubTable;
1486 };
1487
1488
1489
1490 /*
1491  * PosLookup
1492  */
1493
1494
1495 struct PosLookupSubTable
1496 {
1497   friend struct Lookup;
1498   friend struct PosLookup;
1499
1500   enum Type {
1501     Single              = 1,
1502     Pair                = 2,
1503     Cursive             = 3,
1504     MarkBase            = 4,
1505     MarkLig             = 5,
1506     MarkMark            = 6,
1507     Context             = 7,
1508     ChainContext        = 8,
1509     Extension           = 9
1510   };
1511
1512   template <typename context_t>
1513   typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
1514   {
1515     TRACE_DISPATCH (this, lookup_type);
1516     switch (lookup_type) {
1517     case Single:                return_trace (u.single.dispatch (c));
1518     case Pair:                  return_trace (u.pair.dispatch (c));
1519     case Cursive:               return_trace (u.cursive.dispatch (c));
1520     case MarkBase:              return_trace (u.markBase.dispatch (c));
1521     case MarkLig:               return_trace (u.markLig.dispatch (c));
1522     case MarkMark:              return_trace (u.markMark.dispatch (c));
1523     case Context:               return_trace (u.context.dispatch (c));
1524     case ChainContext:          return_trace (u.chainContext.dispatch (c));
1525     case Extension:             return_trace (u.extension.dispatch (c));
1526     default:                    return_trace (c->default_return_value ());
1527     }
1528   }
1529
1530   protected:
1531   union {
1532   SinglePos             single;
1533   PairPos               pair;
1534   CursivePos            cursive;
1535   MarkBasePos           markBase;
1536   MarkLigPos            markLig;
1537   MarkMarkPos           markMark;
1538   ContextPos            context;
1539   ChainContextPos       chainContext;
1540   ExtensionPos          extension;
1541   } u;
1542   public:
1543   DEFINE_SIZE_MIN (0);
1544 };
1545
1546
1547 struct PosLookup : Lookup
1548 {
1549   typedef struct PosLookupSubTable SubTable;
1550
1551   const SubTable& get_subtable (unsigned int i) const
1552   { return Lookup::get_subtable<SubTable> (i); }
1553
1554   bool is_reverse () const
1555   {
1556     return false;
1557   }
1558
1559   bool apply (hb_ot_apply_context_t *c) const
1560   {
1561     TRACE_APPLY (this);
1562     return_trace (dispatch (c));
1563   }
1564
1565   bool intersects (const hb_set_t *glyphs) const
1566   {
1567     hb_intersects_context_t c (glyphs);
1568     return dispatch (&c);
1569   }
1570
1571   hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
1572   { return dispatch (c); }
1573
1574   template <typename set_t>
1575   void add_coverage (set_t *glyphs) const
1576   {
1577     hb_add_coverage_context_t<set_t> c (glyphs);
1578     dispatch (&c);
1579   }
1580
1581   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
1582
1583   template <typename context_t>
1584   static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
1585
1586   template <typename context_t>
1587   typename context_t::return_t dispatch (context_t *c) const
1588   { return Lookup::dispatch<SubTable> (c); }
1589
1590   bool subset (hb_subset_context_t *c) const
1591   { return Lookup::subset<SubTable> (c); }
1592
1593   bool sanitize (hb_sanitize_context_t *c) const
1594   { return Lookup::sanitize<SubTable> (c); }
1595 };
1596
1597 /*
1598  * GPOS -- Glyph Positioning
1599  * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
1600  */
1601
1602 struct GPOS : GSUBGPOS
1603 {
1604   static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
1605
1606   const PosLookup& get_lookup (unsigned int i) const
1607   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
1608
1609   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
1610   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
1611   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
1612
1613   bool subset (hb_subset_context_t *c) const
1614   { return GSUBGPOS::subset<PosLookup> (c); }
1615
1616   bool sanitize (hb_sanitize_context_t *c) const
1617   { return GSUBGPOS::sanitize<PosLookup> (c); }
1618
1619   HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
1620                                    hb_face_t *face) const;
1621
1622   typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
1623 };
1624
1625
1626 static void
1627 reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
1628 {
1629   int chain = pos[i].attach_chain(), type = pos[i].attach_type();
1630   if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
1631     return;
1632
1633   pos[i].attach_chain() = 0;
1634
1635   unsigned int j = (int) i + chain;
1636
1637   /* Stop if we see new parent in the chain. */
1638   if (j == new_parent)
1639     return;
1640
1641   reverse_cursive_minor_offset (pos, j, direction, new_parent);
1642
1643   if (HB_DIRECTION_IS_HORIZONTAL (direction))
1644     pos[j].y_offset = -pos[i].y_offset;
1645   else
1646     pos[j].x_offset = -pos[i].x_offset;
1647
1648   pos[j].attach_chain() = -chain;
1649   pos[j].attach_type() = type;
1650 }
1651 static void
1652 propagate_attachment_offsets (hb_glyph_position_t *pos,
1653                               unsigned int len,
1654                               unsigned int i,
1655                               hb_direction_t direction)
1656 {
1657   /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
1658    * offset of glyph they are attached to. */
1659   int chain = pos[i].attach_chain(), type = pos[i].attach_type();
1660   if (likely (!chain))
1661     return;
1662
1663   pos[i].attach_chain() = 0;
1664
1665   unsigned int j = (int) i + chain;
1666
1667   if (unlikely (j >= len))
1668     return;
1669
1670   propagate_attachment_offsets (pos, len, j, direction);
1671
1672   assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
1673
1674   if (type & ATTACH_TYPE_CURSIVE)
1675   {
1676     if (HB_DIRECTION_IS_HORIZONTAL (direction))
1677       pos[i].y_offset += pos[j].y_offset;
1678     else
1679       pos[i].x_offset += pos[j].x_offset;
1680   }
1681   else /*if (type & ATTACH_TYPE_MARK)*/
1682   {
1683     pos[i].x_offset += pos[j].x_offset;
1684     pos[i].y_offset += pos[j].y_offset;
1685
1686     assert (j < i);
1687     if (HB_DIRECTION_IS_FORWARD (direction))
1688       for (unsigned int k = j; k < i; k++) {
1689         pos[i].x_offset -= pos[k].x_advance;
1690         pos[i].y_offset -= pos[k].y_advance;
1691       }
1692     else
1693       for (unsigned int k = j + 1; k < i + 1; k++) {
1694         pos[i].x_offset += pos[k].x_advance;
1695         pos[i].y_offset += pos[k].y_advance;
1696       }
1697   }
1698 }
1699
1700 void
1701 GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
1702 {
1703   unsigned int count = buffer->len;
1704   for (unsigned int i = 0; i < count; i++)
1705     buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
1706 }
1707
1708 void
1709 GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
1710 {
1711   //_hb_buffer_assert_gsubgpos_vars (buffer);
1712 }
1713
1714 void
1715 GPOS::position_finish_offsets (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
1716 {
1717   _hb_buffer_assert_gsubgpos_vars (buffer);
1718
1719   unsigned int len;
1720   hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
1721   hb_direction_t direction = buffer->props.direction;
1722
1723   /* Handle attachments */
1724   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
1725     for (unsigned int i = 0; i < len; i++)
1726       propagate_attachment_offsets (pos, len, i, direction);
1727 }
1728
1729
1730 struct GPOS_accelerator_t : GPOS::accelerator_t {};
1731
1732
1733 /* Out-of-class implementation for methods recursing */
1734
1735 template <typename context_t>
1736 /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
1737 {
1738   const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
1739   return l.dispatch (c);
1740 }
1741
1742 /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
1743 {
1744   const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
1745   unsigned int saved_lookup_props = c->lookup_props;
1746   unsigned int saved_lookup_index = c->lookup_index;
1747   c->set_lookup_index (lookup_index);
1748   c->set_lookup_props (l.get_props ());
1749   bool ret = l.dispatch (c);
1750   c->set_lookup_index (saved_lookup_index);
1751   c->set_lookup_props (saved_lookup_props);
1752   return ret;
1753 }
1754
1755
1756 } /* namespace OT */
1757
1758
1759 #endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */