Imported Upstream version 1.8.1
[platform/upstream/harfbuzz.git] / src / hb-ot-layout-gsubgpos-private.hh
1 /*
2  * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
3  * Copyright © 2010,2012  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_GSUBGPOS_PRIVATE_HH
30 #define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
31
32 #include "hb-private.hh"
33 #include "hb-debug.hh"
34 #include "hb-buffer-private.hh"
35 #include "hb-map-private.hh"
36 #include "hb-ot-layout-gdef-table.hh"
37 #include "hb-set-private.hh"
38
39
40 namespace OT {
41
42
43 struct hb_closure_context_t :
44        hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
45 {
46   inline const char *get_name (void) { return "CLOSURE"; }
47   typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
48   template <typename T>
49   inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
50   static return_t default_return_value (void) { return HB_VOID; }
51   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
52   return_t recurse (unsigned int lookup_index)
53   {
54     if (unlikely (nesting_level_left == 0 || !recurse_func))
55       return default_return_value ();
56
57     nesting_level_left--;
58     recurse_func (this, lookup_index);
59     nesting_level_left++;
60     return HB_VOID;
61   }
62
63   bool should_visit_lookup (unsigned int lookup_index)
64   {
65     if (is_lookup_done (lookup_index))
66       return false;
67     done_lookups->set (lookup_index, glyphs->get_population ());
68     return true;
69   }
70
71   bool is_lookup_done (unsigned int lookup_index)
72   {
73     // Have we visited this lookup with the current set of glyphs?
74     return done_lookups->get (lookup_index) == glyphs->get_population ();
75   }
76
77   hb_face_t *face;
78   hb_set_t *glyphs;
79   recurse_func_t recurse_func;
80   unsigned int nesting_level_left;
81   unsigned int debug_depth;
82
83   hb_closure_context_t (hb_face_t *face_,
84                         hb_set_t *glyphs_,
85                         hb_map_t *done_lookups_,
86                         unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
87                           face (face_),
88                           glyphs (glyphs_),
89                           recurse_func (nullptr),
90                           nesting_level_left (nesting_level_left_),
91                           debug_depth (0),
92                           done_lookups (done_lookups_) {}
93
94   void set_recurse_func (recurse_func_t func) { recurse_func = func; }
95
96   private:
97   hb_map_t *done_lookups;
98 };
99
100
101 struct hb_would_apply_context_t :
102        hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
103 {
104   inline const char *get_name (void) { return "WOULD_APPLY"; }
105   template <typename T>
106   inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
107   static return_t default_return_value (void) { return false; }
108   bool stop_sublookup_iteration (return_t r) const { return r; }
109
110   hb_face_t *face;
111   const hb_codepoint_t *glyphs;
112   unsigned int len;
113   bool zero_context;
114   unsigned int debug_depth;
115
116   hb_would_apply_context_t (hb_face_t *face_,
117                             const hb_codepoint_t *glyphs_,
118                             unsigned int len_,
119                             bool zero_context_) :
120                               face (face_),
121                               glyphs (glyphs_),
122                               len (len_),
123                               zero_context (zero_context_),
124                               debug_depth (0) {}
125 };
126
127
128 struct hb_collect_glyphs_context_t :
129        hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
130 {
131   inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
132   typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
133   template <typename T>
134   inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
135   static return_t default_return_value (void) { return HB_VOID; }
136   bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
137   return_t recurse (unsigned int lookup_index)
138   {
139     if (unlikely (nesting_level_left == 0 || !recurse_func))
140       return default_return_value ();
141
142     /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
143      * past the previous check.  For GSUB, we only want to collect the output
144      * glyphs in the recursion.  If output is not requested, we can go home now.
145      *
146      * Note further, that the above is not exactly correct.  A recursed lookup
147      * is allowed to match input that is not matched in the context, but that's
148      * not how most fonts are built.  It's possible to relax that and recurse
149      * with all sets here if it proves to be an issue.
150      */
151
152     if (output == hb_set_get_empty ())
153       return HB_VOID;
154
155     /* Return if new lookup was recursed to before. */
156     if (recursed_lookups->has (lookup_index))
157       return HB_VOID;
158
159     hb_set_t *old_before = before;
160     hb_set_t *old_input  = input;
161     hb_set_t *old_after  = after;
162     before = input = after = hb_set_get_empty ();
163
164     nesting_level_left--;
165     recurse_func (this, lookup_index);
166     nesting_level_left++;
167
168     before = old_before;
169     input  = old_input;
170     after  = old_after;
171
172     recursed_lookups->add (lookup_index);
173
174     return HB_VOID;
175   }
176
177   hb_face_t *face;
178   hb_set_t *before;
179   hb_set_t *input;
180   hb_set_t *after;
181   hb_set_t *output;
182   recurse_func_t recurse_func;
183   hb_set_t *recursed_lookups;
184   unsigned int nesting_level_left;
185   unsigned int debug_depth;
186
187   hb_collect_glyphs_context_t (hb_face_t *face_,
188                                hb_set_t  *glyphs_before, /* OUT. May be nullptr */
189                                hb_set_t  *glyphs_input,  /* OUT. May be nullptr */
190                                hb_set_t  *glyphs_after,  /* OUT. May be nullptr */
191                                hb_set_t  *glyphs_output, /* OUT. May be nullptr */
192                                unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
193                               face (face_),
194                               before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
195                               input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
196                               after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
197                               output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
198                               recurse_func (nullptr),
199                               recursed_lookups (nullptr),
200                               nesting_level_left (nesting_level_left_),
201                               debug_depth (0)
202   {
203     recursed_lookups = hb_set_create ();
204   }
205   ~hb_collect_glyphs_context_t (void)
206   {
207     hb_set_destroy (recursed_lookups);
208   }
209
210   void set_recurse_func (recurse_func_t func) { recurse_func = func; }
211 };
212
213
214
215 /* XXX Can we remove this? */
216
217 template <typename set_t>
218 struct hb_add_coverage_context_t :
219        hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
220 {
221   inline const char *get_name (void) { return "GET_COVERAGE"; }
222   typedef const Coverage &return_t;
223   template <typename T>
224   inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
225   static return_t default_return_value (void) { return Null(Coverage); }
226   bool stop_sublookup_iteration (return_t r) const
227   {
228     r.add_coverage (set);
229     return false;
230   }
231
232   hb_add_coverage_context_t (set_t *set_) :
233                             set (set_),
234                             debug_depth (0) {}
235
236   set_t *set;
237   unsigned int debug_depth;
238 };
239
240
241 struct hb_ot_apply_context_t :
242        hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
243 {
244   struct matcher_t
245   {
246     inline matcher_t (void) :
247              lookup_props (0),
248              ignore_zwnj (false),
249              ignore_zwj (false),
250              mask (-1),
251 #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
252              syllable arg1(0),
253 #undef arg1
254              match_func (nullptr),
255              match_data (nullptr) {};
256
257     typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
258
259     inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
260     inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
261     inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
262     inline void set_mask (hb_mask_t mask_) { mask = mask_; }
263     inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
264     inline void set_match_func (match_func_t match_func_,
265                                 const void *match_data_)
266     { match_func = match_func_; match_data = match_data_; }
267
268     enum may_match_t {
269       MATCH_NO,
270       MATCH_YES,
271       MATCH_MAYBE
272     };
273
274     inline may_match_t may_match (const hb_glyph_info_t &info,
275                                   const HBUINT16          *glyph_data) const
276     {
277       if (!(info.mask & mask) ||
278           (syllable && syllable != info.syllable ()))
279         return MATCH_NO;
280
281       if (match_func)
282         return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
283
284       return MATCH_MAYBE;
285     }
286
287     enum may_skip_t {
288       SKIP_NO,
289       SKIP_YES,
290       SKIP_MAYBE
291     };
292
293     inline may_skip_t
294     may_skip (const hb_ot_apply_context_t *c,
295               const hb_glyph_info_t    &info) const
296     {
297       if (!c->check_glyph_property (&info, lookup_props))
298         return SKIP_YES;
299
300       if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
301                     (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
302                     (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
303         return SKIP_MAYBE;
304
305       return SKIP_NO;
306     }
307
308     protected:
309     unsigned int lookup_props;
310     bool ignore_zwnj;
311     bool ignore_zwj;
312     hb_mask_t mask;
313     uint8_t syllable;
314     match_func_t match_func;
315     const void *match_data;
316   };
317
318   struct skipping_iterator_t
319   {
320     inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
321     {
322       c = c_;
323       match_glyph_data = nullptr;
324       matcher.set_match_func (nullptr, nullptr);
325       matcher.set_lookup_props (c->lookup_props);
326       /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
327       matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
328       /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
329       matcher.set_ignore_zwj  (c->table_index == 1 || (context_match || c->auto_zwj));
330       matcher.set_mask (context_match ? -1 : c->lookup_mask);
331     }
332     inline void set_lookup_props (unsigned int lookup_props)
333     {
334       matcher.set_lookup_props (lookup_props);
335     }
336     inline void set_match_func (matcher_t::match_func_t match_func_,
337                                 const void *match_data_,
338                                 const HBUINT16 glyph_data[])
339     {
340       matcher.set_match_func (match_func_, match_data_);
341       match_glyph_data = glyph_data;
342     }
343
344     inline void reset (unsigned int start_index_,
345                        unsigned int num_items_)
346     {
347       idx = start_index_;
348       num_items = num_items_;
349       end = c->buffer->len;
350       matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
351     }
352
353     inline void reject (void) { num_items++; match_glyph_data--; }
354
355     inline matcher_t::may_skip_t
356     may_skip (const hb_glyph_info_t    &info) const
357     {
358       return matcher.may_skip (c, info);
359     }
360
361     inline bool next (void)
362     {
363       assert (num_items > 0);
364       while (idx + num_items < end)
365       {
366         idx++;
367         const hb_glyph_info_t &info = c->buffer->info[idx];
368
369         matcher_t::may_skip_t skip = matcher.may_skip (c, info);
370         if (unlikely (skip == matcher_t::SKIP_YES))
371           continue;
372
373         matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
374         if (match == matcher_t::MATCH_YES ||
375             (match == matcher_t::MATCH_MAYBE &&
376              skip == matcher_t::SKIP_NO))
377         {
378           num_items--;
379           match_glyph_data++;
380           return true;
381         }
382
383         if (skip == matcher_t::SKIP_NO)
384           return false;
385       }
386       return false;
387     }
388     inline bool prev (void)
389     {
390       assert (num_items > 0);
391       while (idx >= num_items)
392       {
393         idx--;
394         const hb_glyph_info_t &info = c->buffer->out_info[idx];
395
396         matcher_t::may_skip_t skip = matcher.may_skip (c, info);
397         if (unlikely (skip == matcher_t::SKIP_YES))
398           continue;
399
400         matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
401         if (match == matcher_t::MATCH_YES ||
402             (match == matcher_t::MATCH_MAYBE &&
403              skip == matcher_t::SKIP_NO))
404         {
405           num_items--;
406           match_glyph_data++;
407           return true;
408         }
409
410         if (skip == matcher_t::SKIP_NO)
411           return false;
412       }
413       return false;
414     }
415
416     unsigned int idx;
417     protected:
418     hb_ot_apply_context_t *c;
419     matcher_t matcher;
420     const HBUINT16 *match_glyph_data;
421
422     unsigned int num_items;
423     unsigned int end;
424   };
425
426
427   inline const char *get_name (void) { return "APPLY"; }
428   typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
429   template <typename T>
430   inline return_t dispatch (const T &obj) { return obj.apply (this); }
431   static return_t default_return_value (void) { return false; }
432   bool stop_sublookup_iteration (return_t r) const { return r; }
433   return_t recurse (unsigned int sub_lookup_index)
434   {
435     if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
436       return default_return_value ();
437
438     nesting_level_left--;
439     bool ret = recurse_func (this, sub_lookup_index);
440     nesting_level_left++;
441     return ret;
442   }
443
444   skipping_iterator_t iter_input, iter_context;
445
446   hb_font_t *font;
447   hb_face_t *face;
448   hb_buffer_t *buffer;
449   recurse_func_t recurse_func;
450   const GDEF &gdef;
451   const VariationStore &var_store;
452
453   hb_direction_t direction;
454   hb_mask_t lookup_mask;
455   unsigned int table_index; /* GSUB/GPOS */
456   unsigned int lookup_index;
457   unsigned int lookup_props;
458   unsigned int nesting_level_left;
459   unsigned int debug_depth;
460
461   bool auto_zwnj;
462   bool auto_zwj;
463   bool has_glyph_classes;
464
465
466   hb_ot_apply_context_t (unsigned int table_index_,
467                       hb_font_t *font_,
468                       hb_buffer_t *buffer_) :
469                         iter_input (), iter_context (),
470                         font (font_), face (font->face), buffer (buffer_),
471                         recurse_func (nullptr),
472                         gdef (*hb_ot_layout_from_face (face)->gdef),
473                         var_store (gdef.get_var_store ()),
474                         direction (buffer_->props.direction),
475                         lookup_mask (1),
476                         table_index (table_index_),
477                         lookup_index ((unsigned int) -1),
478                         lookup_props (0),
479                         nesting_level_left (HB_MAX_NESTING_LEVEL),
480                         debug_depth (0),
481                         auto_zwnj (true),
482                         auto_zwj (true),
483                         has_glyph_classes (gdef.has_glyph_classes ()) {}
484
485   inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
486   inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
487   inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
488   inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
489   inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
490   inline void set_lookup_props (unsigned int lookup_props_)
491   {
492     lookup_props = lookup_props_;
493     iter_input.init (this, false);
494     iter_context.init (this, true);
495   }
496
497   inline bool
498   match_properties_mark (hb_codepoint_t  glyph,
499                          unsigned int    glyph_props,
500                          unsigned int    match_props) const
501   {
502     /* If using mark filtering sets, the high short of
503      * match_props has the set index.
504      */
505     if (match_props & LookupFlag::UseMarkFilteringSet)
506       return gdef.mark_set_covers (match_props >> 16, glyph);
507
508     /* The second byte of match_props has the meaning
509      * "ignore marks of attachment type different than
510      * the attachment type specified."
511      */
512     if (match_props & LookupFlag::MarkAttachmentType)
513       return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
514
515     return true;
516   }
517
518   inline bool
519   check_glyph_property (const hb_glyph_info_t *info,
520                         unsigned int  match_props) const
521   {
522     hb_codepoint_t glyph = info->codepoint;
523     unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
524
525     /* Not covered, if, for example, glyph class is ligature and
526      * match_props includes LookupFlags::IgnoreLigatures
527      */
528     if (glyph_props & match_props & LookupFlag::IgnoreFlags)
529       return false;
530
531     if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
532       return match_properties_mark (glyph, glyph_props, match_props);
533
534     return true;
535   }
536
537   inline void _set_glyph_props (hb_codepoint_t glyph_index,
538                           unsigned int class_guess = 0,
539                           bool ligature = false,
540                           bool component = false) const
541   {
542     unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
543                           HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
544     add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
545     if (ligature)
546     {
547       add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
548       /* In the only place that the MULTIPLIED bit is used, Uniscribe
549        * seems to only care about the "last" transformation between
550        * Ligature and Multiple substitions.  Ie. if you ligate, expand,
551        * and ligate again, it forgives the multiplication and acts as
552        * if only ligation happened.  As such, clear MULTIPLIED bit.
553        */
554       add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
555     }
556     if (component)
557       add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
558     if (likely (has_glyph_classes))
559       _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
560     else if (class_guess)
561       _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
562   }
563
564   inline void replace_glyph (hb_codepoint_t glyph_index) const
565   {
566     _set_glyph_props (glyph_index);
567     buffer->replace_glyph (glyph_index);
568   }
569   inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
570   {
571     _set_glyph_props (glyph_index);
572     buffer->cur().codepoint = glyph_index;
573   }
574   inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
575                                            unsigned int class_guess) const
576   {
577     _set_glyph_props (glyph_index, class_guess, true);
578     buffer->replace_glyph (glyph_index);
579   }
580   inline void output_glyph_for_component (hb_codepoint_t glyph_index,
581                                           unsigned int class_guess) const
582   {
583     _set_glyph_props (glyph_index, class_guess, false, true);
584     buffer->output_glyph (glyph_index);
585   }
586 };
587
588
589
590 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
591 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
592 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
593
594 struct ContextClosureFuncs
595 {
596   intersects_func_t intersects;
597 };
598 struct ContextCollectGlyphsFuncs
599 {
600   collect_glyphs_func_t collect;
601 };
602 struct ContextApplyFuncs
603 {
604   match_func_t match;
605 };
606
607
608 static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
609 {
610   return glyphs->has (value);
611 }
612 static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
613 {
614   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
615   return class_def.intersects_class (glyphs, value);
616 }
617 static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
618 {
619   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
620   return (data+coverage).intersects (glyphs);
621 }
622
623 static inline bool intersects_array (hb_closure_context_t *c,
624                                      unsigned int count,
625                                      const HBUINT16 values[],
626                                      intersects_func_t intersects_func,
627                                      const void *intersects_data)
628 {
629   for (unsigned int i = 0; i < count; i++)
630     if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
631       return false;
632   return true;
633 }
634
635
636 static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
637 {
638   glyphs->add (value);
639 }
640 static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
641 {
642   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
643   class_def.add_class (glyphs, value);
644 }
645 static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
646 {
647   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
648   (data+coverage).add_coverage (glyphs);
649 }
650 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
651                                   hb_set_t *glyphs,
652                                   unsigned int count,
653                                   const HBUINT16 values[],
654                                   collect_glyphs_func_t collect_func,
655                                   const void *collect_data)
656 {
657   for (unsigned int i = 0; i < count; i++)
658     collect_func (glyphs, values[i], collect_data);
659 }
660
661
662 static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
663 {
664   return glyph_id == value;
665 }
666 static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
667 {
668   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
669   return class_def.get_class (glyph_id) == value;
670 }
671 static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
672 {
673   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
674   return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
675 }
676
677 static inline bool would_match_input (hb_would_apply_context_t *c,
678                                       unsigned int count, /* Including the first glyph (not matched) */
679                                       const HBUINT16 input[], /* Array of input values--start with second glyph */
680                                       match_func_t match_func,
681                                       const void *match_data)
682 {
683   if (count != c->len)
684     return false;
685
686   for (unsigned int i = 1; i < count; i++)
687     if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
688       return false;
689
690   return true;
691 }
692 static inline bool match_input (hb_ot_apply_context_t *c,
693                                 unsigned int count, /* Including the first glyph (not matched) */
694                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
695                                 match_func_t match_func,
696                                 const void *match_data,
697                                 unsigned int *end_offset,
698                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
699                                 bool *p_is_mark_ligature = nullptr,
700                                 unsigned int *p_total_component_count = nullptr)
701 {
702   TRACE_APPLY (nullptr);
703
704   if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
705
706   hb_buffer_t *buffer = c->buffer;
707
708   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
709   skippy_iter.reset (buffer->idx, count - 1);
710   skippy_iter.set_match_func (match_func, match_data, input);
711
712   /*
713    * This is perhaps the trickiest part of OpenType...  Remarks:
714    *
715    * - If all components of the ligature were marks, we call this a mark ligature.
716    *
717    * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
718    *   it as a ligature glyph.
719    *
720    * - Ligatures cannot be formed across glyphs attached to different components
721    *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
722    *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
723    *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
724    *   There are a couple of exceptions to this:
725    *
726    *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
727    *     assuming that the font designer knows what they are doing (otherwise it can
728    *     break Indic stuff when a matra wants to ligate with a conjunct,
729    *
730    *   o If two marks want to ligate and they belong to different components of the
731    *     same ligature glyph, and said ligature glyph is to be ignored according to
732    *     mark-filtering rules, then allow.
733    *     https://github.com/harfbuzz/harfbuzz/issues/545
734    */
735
736   bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
737
738   unsigned int total_component_count = 0;
739   total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
740
741   unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
742   unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
743
744   enum {
745     LIGBASE_NOT_CHECKED,
746     LIGBASE_MAY_NOT_SKIP,
747     LIGBASE_MAY_SKIP
748   } ligbase = LIGBASE_NOT_CHECKED;
749
750   match_positions[0] = buffer->idx;
751   for (unsigned int i = 1; i < count; i++)
752   {
753     if (!skippy_iter.next ()) return_trace (false);
754
755     match_positions[i] = skippy_iter.idx;
756
757     unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
758     unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
759
760     if (first_lig_id && first_lig_comp)
761     {
762       /* If first component was attached to a previous ligature component,
763        * all subsequent components should be attached to the same ligature
764        * component, otherwise we shouldn't ligate them... */
765       if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
766       {
767         /* ...unless, we are attached to a base ligature and that base
768          * ligature is ignorable. */
769         if (ligbase == LIGBASE_NOT_CHECKED)
770         {
771           bool found = false;
772           const hb_glyph_info_t *out = buffer->out_info;
773           unsigned int j = buffer->out_len;
774           while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
775           {
776             if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
777             {
778               j--;
779               found = true;
780               break;
781             }
782             j--;
783           }
784
785           if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
786             ligbase = LIGBASE_MAY_SKIP;
787           else
788             ligbase = LIGBASE_MAY_NOT_SKIP;
789         }
790
791         if (ligbase == LIGBASE_MAY_NOT_SKIP)
792           return_trace (false);
793       }
794     }
795     else
796     {
797       /* If first component was NOT attached to a previous ligature component,
798        * all subsequent components should also NOT be attached to any ligature
799        * component, unless they are attached to the first component itself! */
800       if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
801         return_trace (false);
802     }
803
804     is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
805     total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
806   }
807
808   *end_offset = skippy_iter.idx - buffer->idx + 1;
809
810   if (p_is_mark_ligature)
811     *p_is_mark_ligature = is_mark_ligature;
812
813   if (p_total_component_count)
814     *p_total_component_count = total_component_count;
815
816   return_trace (true);
817 }
818 static inline bool ligate_input (hb_ot_apply_context_t *c,
819                                  unsigned int count, /* Including the first glyph */
820                                  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
821                                  unsigned int match_length,
822                                  hb_codepoint_t lig_glyph,
823                                  bool is_mark_ligature,
824                                  unsigned int total_component_count)
825 {
826   TRACE_APPLY (nullptr);
827
828   hb_buffer_t *buffer = c->buffer;
829
830   buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
831
832   /*
833    * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
834    *   the ligature to keep its old ligature id.  This will allow it to attach to
835    *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
836    *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
837    *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
838    *   later, we don't want them to lose their ligature id/component, otherwise
839    *   GPOS will fail to correctly position the mark ligature on top of the
840    *   LAM,LAM,HEH ligature.  See:
841    *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
842    *
843    * - If a ligature is formed of components that some of which are also ligatures
844    *   themselves, and those ligature components had marks attached to *their*
845    *   components, we have to attach the marks to the new ligature component
846    *   positions!  Now *that*'s tricky!  And these marks may be following the
847    *   last component of the whole sequence, so we should loop forward looking
848    *   for them and update them.
849    *
850    *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
851    *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
852    *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
853    *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
854    *   the new ligature with a component value of 2.
855    *
856    *   This in fact happened to a font...  See:
857    *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
858    */
859
860   unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
861   unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
862   unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
863   unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
864   unsigned int components_so_far = last_num_components;
865
866   if (!is_mark_ligature)
867   {
868     _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
869     if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
870     {
871       _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
872     }
873   }
874   c->replace_glyph_with_ligature (lig_glyph, klass);
875
876   for (unsigned int i = 1; i < count; i++)
877   {
878     while (buffer->idx < match_positions[i] && buffer->successful)
879     {
880       if (!is_mark_ligature) {
881         unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
882         if (this_comp == 0)
883           this_comp = last_num_components;
884         unsigned int new_lig_comp = components_so_far - last_num_components +
885                                     MIN (this_comp, last_num_components);
886           _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
887       }
888       buffer->next_glyph ();
889     }
890
891     last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
892     last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
893     components_so_far += last_num_components;
894
895     /* Skip the base glyph */
896     buffer->idx++;
897   }
898
899   if (!is_mark_ligature && last_lig_id) {
900     /* Re-adjust components for any marks following. */
901     for (unsigned int i = buffer->idx; i < buffer->len; i++) {
902       if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
903         unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
904         if (!this_comp)
905           break;
906         unsigned int new_lig_comp = components_so_far - last_num_components +
907                                     MIN (this_comp, last_num_components);
908         _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
909       } else
910         break;
911     }
912   }
913   return_trace (true);
914 }
915
916 static inline bool match_backtrack (hb_ot_apply_context_t *c,
917                                     unsigned int count,
918                                     const HBUINT16 backtrack[],
919                                     match_func_t match_func,
920                                     const void *match_data,
921                                     unsigned int *match_start)
922 {
923   TRACE_APPLY (nullptr);
924
925   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
926   skippy_iter.reset (c->buffer->backtrack_len (), count);
927   skippy_iter.set_match_func (match_func, match_data, backtrack);
928
929   for (unsigned int i = 0; i < count; i++)
930     if (!skippy_iter.prev ())
931       return_trace (false);
932
933   *match_start = skippy_iter.idx;
934
935   return_trace (true);
936 }
937
938 static inline bool match_lookahead (hb_ot_apply_context_t *c,
939                                     unsigned int count,
940                                     const HBUINT16 lookahead[],
941                                     match_func_t match_func,
942                                     const void *match_data,
943                                     unsigned int offset,
944                                     unsigned int *end_index)
945 {
946   TRACE_APPLY (nullptr);
947
948   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
949   skippy_iter.reset (c->buffer->idx + offset - 1, count);
950   skippy_iter.set_match_func (match_func, match_data, lookahead);
951
952   for (unsigned int i = 0; i < count; i++)
953     if (!skippy_iter.next ())
954       return_trace (false);
955
956   *end_index = skippy_iter.idx + 1;
957
958   return_trace (true);
959 }
960
961
962
963 struct LookupRecord
964 {
965   inline bool sanitize (hb_sanitize_context_t *c) const
966   {
967     TRACE_SANITIZE (this);
968     return_trace (c->check_struct (this));
969   }
970
971   HBUINT16      sequenceIndex;          /* Index into current glyph
972                                          * sequence--first glyph = 0 */
973   HBUINT16      lookupListIndex;        /* Lookup to apply to that
974                                          * position--zero--based */
975   public:
976   DEFINE_SIZE_STATIC (4);
977 };
978
979
980 template <typename context_t>
981 static inline void recurse_lookups (context_t *c,
982                                     unsigned int lookupCount,
983                                     const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
984 {
985   for (unsigned int i = 0; i < lookupCount; i++)
986     c->recurse (lookupRecord[i].lookupListIndex);
987 }
988
989 static inline bool apply_lookup (hb_ot_apply_context_t *c,
990                                  unsigned int count, /* Including the first glyph */
991                                  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
992                                  unsigned int lookupCount,
993                                  const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
994                                  unsigned int match_length)
995 {
996   TRACE_APPLY (nullptr);
997
998   hb_buffer_t *buffer = c->buffer;
999   int end;
1000
1001   /* All positions are distance from beginning of *output* buffer.
1002    * Adjust. */
1003   {
1004     unsigned int bl = buffer->backtrack_len ();
1005     end = bl + match_length;
1006
1007     int delta = bl - buffer->idx;
1008     /* Convert positions to new indexing. */
1009     for (unsigned int j = 0; j < count; j++)
1010       match_positions[j] += delta;
1011   }
1012
1013   for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
1014   {
1015     unsigned int idx = lookupRecord[i].sequenceIndex;
1016     if (idx >= count)
1017       continue;
1018
1019     /* Don't recurse to ourself at same position.
1020      * Note that this test is too naive, it doesn't catch longer loops. */
1021     if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
1022       continue;
1023
1024     if (unlikely (!buffer->move_to (match_positions[idx])))
1025       break;
1026
1027     if (unlikely (buffer->max_ops <= 0))
1028       break;
1029
1030     unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
1031     if (!c->recurse (lookupRecord[i].lookupListIndex))
1032       continue;
1033
1034     unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
1035     int delta = new_len - orig_len;
1036
1037     if (!delta)
1038         continue;
1039
1040     /* Recursed lookup changed buffer len.  Adjust.
1041      *
1042      * TODO:
1043      *
1044      * Right now, if buffer length increased by n, we assume n new glyphs
1045      * were added right after the current position, and if buffer length
1046      * was decreased by n, we assume n match positions after the current
1047      * one where removed.  The former (buffer length increased) case is
1048      * fine, but the decrease case can be improved in at least two ways,
1049      * both of which are significant:
1050      *
1051      *   - If recursed-to lookup is MultipleSubst and buffer length
1052      *     decreased, then it's current match position that was deleted,
1053      *     NOT the one after it.
1054      *
1055      *   - If buffer length was decreased by n, it does not necessarily
1056      *     mean that n match positions where removed, as there might
1057      *     have been marks and default-ignorables in the sequence.  We
1058      *     should instead drop match positions between current-position
1059      *     and current-position + n instead.
1060      *
1061      * It should be possible to construct tests for both of these cases.
1062      */
1063
1064     end += delta;
1065     if (end <= int (match_positions[idx]))
1066     {
1067       /* End might end up being smaller than match_positions[idx] if the recursed
1068        * lookup ended up removing many items, more than we have had matched.
1069        * Just never rewind end back and get out of here.
1070        * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
1071       end = match_positions[idx];
1072       /* There can't be any further changes. */
1073       break;
1074     }
1075
1076     unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
1077
1078     if (delta > 0)
1079     {
1080       if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
1081         break;
1082     }
1083     else
1084     {
1085       /* NOTE: delta is negative. */
1086       delta = MAX (delta, (int) next - (int) count);
1087       next -= delta;
1088     }
1089
1090     /* Shift! */
1091     memmove (match_positions + next + delta, match_positions + next,
1092              (count - next) * sizeof (match_positions[0]));
1093     next += delta;
1094     count += delta;
1095
1096     /* Fill in new entries. */
1097     for (unsigned int j = idx + 1; j < next; j++)
1098       match_positions[j] = match_positions[j - 1] + 1;
1099
1100     /* And fixup the rest. */
1101     for (; next < count; next++)
1102       match_positions[next] += delta;
1103   }
1104
1105   buffer->move_to (end);
1106
1107   return_trace (true);
1108 }
1109
1110
1111
1112 /* Contextual lookups */
1113
1114 struct ContextClosureLookupContext
1115 {
1116   ContextClosureFuncs funcs;
1117   const void *intersects_data;
1118 };
1119
1120 struct ContextCollectGlyphsLookupContext
1121 {
1122   ContextCollectGlyphsFuncs funcs;
1123   const void *collect_data;
1124 };
1125
1126 struct ContextApplyLookupContext
1127 {
1128   ContextApplyFuncs funcs;
1129   const void *match_data;
1130 };
1131
1132 static inline void context_closure_lookup (hb_closure_context_t *c,
1133                                            unsigned int inputCount, /* Including the first glyph (not matched) */
1134                                            const HBUINT16 input[], /* Array of input values--start with second glyph */
1135                                            unsigned int lookupCount,
1136                                            const LookupRecord lookupRecord[],
1137                                            ContextClosureLookupContext &lookup_context)
1138 {
1139   if (intersects_array (c,
1140                         inputCount ? inputCount - 1 : 0, input,
1141                         lookup_context.funcs.intersects, lookup_context.intersects_data))
1142     recurse_lookups (c,
1143                      lookupCount, lookupRecord);
1144 }
1145
1146 static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1147                                                   unsigned int inputCount, /* Including the first glyph (not matched) */
1148                                                   const HBUINT16 input[], /* Array of input values--start with second glyph */
1149                                                   unsigned int lookupCount,
1150                                                   const LookupRecord lookupRecord[],
1151                                                   ContextCollectGlyphsLookupContext &lookup_context)
1152 {
1153   collect_array (c, c->input,
1154                  inputCount ? inputCount - 1 : 0, input,
1155                  lookup_context.funcs.collect, lookup_context.collect_data);
1156   recurse_lookups (c,
1157                    lookupCount, lookupRecord);
1158 }
1159
1160 static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
1161                                                unsigned int inputCount, /* Including the first glyph (not matched) */
1162                                                const HBUINT16 input[], /* Array of input values--start with second glyph */
1163                                                unsigned int lookupCount HB_UNUSED,
1164                                                const LookupRecord lookupRecord[] HB_UNUSED,
1165                                                ContextApplyLookupContext &lookup_context)
1166 {
1167   return would_match_input (c,
1168                             inputCount, input,
1169                             lookup_context.funcs.match, lookup_context.match_data);
1170 }
1171 static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
1172                                          unsigned int inputCount, /* Including the first glyph (not matched) */
1173                                          const HBUINT16 input[], /* Array of input values--start with second glyph */
1174                                          unsigned int lookupCount,
1175                                          const LookupRecord lookupRecord[],
1176                                          ContextApplyLookupContext &lookup_context)
1177 {
1178   unsigned int match_length = 0;
1179   unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
1180   return match_input (c,
1181                       inputCount, input,
1182                       lookup_context.funcs.match, lookup_context.match_data,
1183                       &match_length, match_positions)
1184       && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
1185           apply_lookup (c,
1186                        inputCount, match_positions,
1187                        lookupCount, lookupRecord,
1188                        match_length));
1189 }
1190
1191 struct Rule
1192 {
1193   inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
1194   {
1195     TRACE_CLOSURE (this);
1196     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1197     context_closure_lookup (c,
1198                             inputCount, inputZ,
1199                             lookupCount, lookupRecord,
1200                             lookup_context);
1201   }
1202
1203   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1204   {
1205     TRACE_COLLECT_GLYPHS (this);
1206     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1207     context_collect_glyphs_lookup (c,
1208                                    inputCount, inputZ,
1209                                    lookupCount, lookupRecord,
1210                                    lookup_context);
1211   }
1212
1213   inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1214   {
1215     TRACE_WOULD_APPLY (this);
1216     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1217     return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
1218   }
1219
1220   inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1221   {
1222     TRACE_APPLY (this);
1223     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1224     return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
1225   }
1226
1227   public:
1228   inline bool sanitize (hb_sanitize_context_t *c) const
1229   {
1230     TRACE_SANITIZE (this);
1231     return_trace (inputCount.sanitize (c) &&
1232                   lookupCount.sanitize (c) &&
1233                   c->check_range (inputZ,
1234                                   inputZ[0].static_size * inputCount +
1235                                   LookupRecord::static_size * lookupCount));
1236   }
1237
1238   protected:
1239   HBUINT16      inputCount;             /* Total number of glyphs in input
1240                                          * glyph sequence--includes the first
1241                                          * glyph */
1242   HBUINT16      lookupCount;            /* Number of LookupRecords */
1243   HBUINT16      inputZ[VAR];            /* Array of match inputs--start with
1244                                          * second glyph */
1245 /*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
1246                                          * design order */
1247   public:
1248   DEFINE_SIZE_ARRAY (4, inputZ);
1249 };
1250
1251 struct RuleSet
1252 {
1253   inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
1254   {
1255     TRACE_CLOSURE (this);
1256     unsigned int num_rules = rule.len;
1257     for (unsigned int i = 0; i < num_rules; i++)
1258       (this+rule[i]).closure (c, lookup_context);
1259   }
1260
1261   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1262   {
1263     TRACE_COLLECT_GLYPHS (this);
1264     unsigned int num_rules = rule.len;
1265     for (unsigned int i = 0; i < num_rules; i++)
1266       (this+rule[i]).collect_glyphs (c, lookup_context);
1267   }
1268
1269   inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1270   {
1271     TRACE_WOULD_APPLY (this);
1272     unsigned int num_rules = rule.len;
1273     for (unsigned int i = 0; i < num_rules; i++)
1274     {
1275       if ((this+rule[i]).would_apply (c, lookup_context))
1276         return_trace (true);
1277     }
1278     return_trace (false);
1279   }
1280
1281   inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1282   {
1283     TRACE_APPLY (this);
1284     unsigned int num_rules = rule.len;
1285     for (unsigned int i = 0; i < num_rules; i++)
1286     {
1287       if ((this+rule[i]).apply (c, lookup_context))
1288         return_trace (true);
1289     }
1290     return_trace (false);
1291   }
1292
1293   inline bool sanitize (hb_sanitize_context_t *c) const
1294   {
1295     TRACE_SANITIZE (this);
1296     return_trace (rule.sanitize (c, this));
1297   }
1298
1299   protected:
1300   OffsetArrayOf<Rule>
1301                 rule;                   /* Array of Rule tables
1302                                          * ordered by preference */
1303   public:
1304   DEFINE_SIZE_ARRAY (2, rule);
1305 };
1306
1307
1308 struct ContextFormat1
1309 {
1310   inline void closure (hb_closure_context_t *c) const
1311   {
1312     TRACE_CLOSURE (this);
1313
1314     const Coverage &cov = (this+coverage);
1315
1316     struct ContextClosureLookupContext lookup_context = {
1317       {intersects_glyph},
1318       nullptr
1319     };
1320
1321     unsigned int count = ruleSet.len;
1322     for (unsigned int i = 0; i < count; i++)
1323       if (cov.intersects_coverage (c->glyphs, i)) {
1324         const RuleSet &rule_set = this+ruleSet[i];
1325         rule_set.closure (c, lookup_context);
1326       }
1327   }
1328
1329   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1330   {
1331     TRACE_COLLECT_GLYPHS (this);
1332     (this+coverage).add_coverage (c->input);
1333
1334     struct ContextCollectGlyphsLookupContext lookup_context = {
1335       {collect_glyph},
1336       nullptr
1337     };
1338
1339     unsigned int count = ruleSet.len;
1340     for (unsigned int i = 0; i < count; i++)
1341       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
1342   }
1343
1344   inline bool would_apply (hb_would_apply_context_t *c) const
1345   {
1346     TRACE_WOULD_APPLY (this);
1347
1348     const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
1349     struct ContextApplyLookupContext lookup_context = {
1350       {match_glyph},
1351       nullptr
1352     };
1353     return_trace (rule_set.would_apply (c, lookup_context));
1354   }
1355
1356   inline const Coverage &get_coverage (void) const
1357   {
1358     return this+coverage;
1359   }
1360
1361   inline bool apply (hb_ot_apply_context_t *c) const
1362   {
1363     TRACE_APPLY (this);
1364     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
1365     if (likely (index == NOT_COVERED))
1366       return_trace (false);
1367
1368     const RuleSet &rule_set = this+ruleSet[index];
1369     struct ContextApplyLookupContext lookup_context = {
1370       {match_glyph},
1371       nullptr
1372     };
1373     return_trace (rule_set.apply (c, lookup_context));
1374   }
1375
1376   inline bool sanitize (hb_sanitize_context_t *c) const
1377   {
1378     TRACE_SANITIZE (this);
1379     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
1380   }
1381
1382   protected:
1383   HBUINT16      format;                 /* Format identifier--format = 1 */
1384   OffsetTo<Coverage>
1385                 coverage;               /* Offset to Coverage table--from
1386                                          * beginning of table */
1387   OffsetArrayOf<RuleSet>
1388                 ruleSet;                /* Array of RuleSet tables
1389                                          * ordered by Coverage Index */
1390   public:
1391   DEFINE_SIZE_ARRAY (6, ruleSet);
1392 };
1393
1394
1395 struct ContextFormat2
1396 {
1397   inline void closure (hb_closure_context_t *c) const
1398   {
1399     TRACE_CLOSURE (this);
1400     if (!(this+coverage).intersects (c->glyphs))
1401       return;
1402
1403     const ClassDef &class_def = this+classDef;
1404
1405     struct ContextClosureLookupContext lookup_context = {
1406       {intersects_class},
1407       &class_def
1408     };
1409
1410     unsigned int count = ruleSet.len;
1411     for (unsigned int i = 0; i < count; i++)
1412       if (class_def.intersects_class (c->glyphs, i)) {
1413         const RuleSet &rule_set = this+ruleSet[i];
1414         rule_set.closure (c, lookup_context);
1415       }
1416   }
1417
1418   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1419   {
1420     TRACE_COLLECT_GLYPHS (this);
1421     (this+coverage).add_coverage (c->input);
1422
1423     const ClassDef &class_def = this+classDef;
1424     struct ContextCollectGlyphsLookupContext lookup_context = {
1425       {collect_class},
1426       &class_def
1427     };
1428
1429     unsigned int count = ruleSet.len;
1430     for (unsigned int i = 0; i < count; i++)
1431       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
1432   }
1433
1434   inline bool would_apply (hb_would_apply_context_t *c) const
1435   {
1436     TRACE_WOULD_APPLY (this);
1437
1438     const ClassDef &class_def = this+classDef;
1439     unsigned int index = class_def.get_class (c->glyphs[0]);
1440     const RuleSet &rule_set = this+ruleSet[index];
1441     struct ContextApplyLookupContext lookup_context = {
1442       {match_class},
1443       &class_def
1444     };
1445     return_trace (rule_set.would_apply (c, lookup_context));
1446   }
1447
1448   inline const Coverage &get_coverage (void) const
1449   {
1450     return this+coverage;
1451   }
1452
1453   inline bool apply (hb_ot_apply_context_t *c) const
1454   {
1455     TRACE_APPLY (this);
1456     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
1457     if (likely (index == NOT_COVERED)) return_trace (false);
1458
1459     const ClassDef &class_def = this+classDef;
1460     index = class_def.get_class (c->buffer->cur().codepoint);
1461     const RuleSet &rule_set = this+ruleSet[index];
1462     struct ContextApplyLookupContext lookup_context = {
1463       {match_class},
1464       &class_def
1465     };
1466     return_trace (rule_set.apply (c, lookup_context));
1467   }
1468
1469   inline bool sanitize (hb_sanitize_context_t *c) const
1470   {
1471     TRACE_SANITIZE (this);
1472     return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
1473   }
1474
1475   protected:
1476   HBUINT16      format;                 /* Format identifier--format = 2 */
1477   OffsetTo<Coverage>
1478                 coverage;               /* Offset to Coverage table--from
1479                                          * beginning of table */
1480   OffsetTo<ClassDef>
1481                 classDef;               /* Offset to glyph ClassDef table--from
1482                                          * beginning of table */
1483   OffsetArrayOf<RuleSet>
1484                 ruleSet;                /* Array of RuleSet tables
1485                                          * ordered by class */
1486   public:
1487   DEFINE_SIZE_ARRAY (8, ruleSet);
1488 };
1489
1490
1491 struct ContextFormat3
1492 {
1493   inline void closure (hb_closure_context_t *c) const
1494   {
1495     TRACE_CLOSURE (this);
1496     if (!(this+coverageZ[0]).intersects (c->glyphs))
1497       return;
1498
1499     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
1500     struct ContextClosureLookupContext lookup_context = {
1501       {intersects_coverage},
1502       this
1503     };
1504     context_closure_lookup (c,
1505                             glyphCount, (const HBUINT16 *) (coverageZ + 1),
1506                             lookupCount, lookupRecord,
1507                             lookup_context);
1508   }
1509
1510   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1511   {
1512     TRACE_COLLECT_GLYPHS (this);
1513     (this+coverageZ[0]).add_coverage (c->input);
1514
1515     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
1516     struct ContextCollectGlyphsLookupContext lookup_context = {
1517       {collect_coverage},
1518       this
1519     };
1520
1521     context_collect_glyphs_lookup (c,
1522                                    glyphCount, (const HBUINT16 *) (coverageZ + 1),
1523                                    lookupCount, lookupRecord,
1524                                    lookup_context);
1525   }
1526
1527   inline bool would_apply (hb_would_apply_context_t *c) const
1528   {
1529     TRACE_WOULD_APPLY (this);
1530
1531     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
1532     struct ContextApplyLookupContext lookup_context = {
1533       {match_coverage},
1534       this
1535     };
1536     return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
1537   }
1538
1539   inline const Coverage &get_coverage (void) const
1540   {
1541     return this+coverageZ[0];
1542   }
1543
1544   inline bool apply (hb_ot_apply_context_t *c) const
1545   {
1546     TRACE_APPLY (this);
1547     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
1548     if (likely (index == NOT_COVERED)) return_trace (false);
1549
1550     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
1551     struct ContextApplyLookupContext lookup_context = {
1552       {match_coverage},
1553       this
1554     };
1555     return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
1556   }
1557
1558   inline bool sanitize (hb_sanitize_context_t *c) const
1559   {
1560     TRACE_SANITIZE (this);
1561     if (!c->check_struct (this)) return_trace (false);
1562     unsigned int count = glyphCount;
1563     if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
1564     if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
1565     for (unsigned int i = 0; i < count; i++)
1566       if (!coverageZ[i].sanitize (c, this)) return_trace (false);
1567     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
1568     return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
1569   }
1570
1571   protected:
1572   HBUINT16      format;                 /* Format identifier--format = 3 */
1573   HBUINT16      glyphCount;             /* Number of glyphs in the input glyph
1574                                          * sequence */
1575   HBUINT16      lookupCount;            /* Number of LookupRecords */
1576   OffsetTo<Coverage>
1577                 coverageZ[VAR];         /* Array of offsets to Coverage
1578                                          * table in glyph sequence order */
1579 /*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
1580                                          * design order */
1581   public:
1582   DEFINE_SIZE_ARRAY (6, coverageZ);
1583 };
1584
1585 struct Context
1586 {
1587   template <typename context_t>
1588   inline typename context_t::return_t dispatch (context_t *c) const
1589   {
1590     TRACE_DISPATCH (this, u.format);
1591     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
1592     switch (u.format) {
1593     case 1: return_trace (c->dispatch (u.format1));
1594     case 2: return_trace (c->dispatch (u.format2));
1595     case 3: return_trace (c->dispatch (u.format3));
1596     default:return_trace (c->default_return_value ());
1597     }
1598   }
1599
1600   protected:
1601   union {
1602   HBUINT16              format;         /* Format identifier */
1603   ContextFormat1        format1;
1604   ContextFormat2        format2;
1605   ContextFormat3        format3;
1606   } u;
1607 };
1608
1609
1610 /* Chaining Contextual lookups */
1611
1612 struct ChainContextClosureLookupContext
1613 {
1614   ContextClosureFuncs funcs;
1615   const void *intersects_data[3];
1616 };
1617
1618 struct ChainContextCollectGlyphsLookupContext
1619 {
1620   ContextCollectGlyphsFuncs funcs;
1621   const void *collect_data[3];
1622 };
1623
1624 struct ChainContextApplyLookupContext
1625 {
1626   ContextApplyFuncs funcs;
1627   const void *match_data[3];
1628 };
1629
1630 static inline void chain_context_closure_lookup (hb_closure_context_t *c,
1631                                                  unsigned int backtrackCount,
1632                                                  const HBUINT16 backtrack[],
1633                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
1634                                                  const HBUINT16 input[], /* Array of input values--start with second glyph */
1635                                                  unsigned int lookaheadCount,
1636                                                  const HBUINT16 lookahead[],
1637                                                  unsigned int lookupCount,
1638                                                  const LookupRecord lookupRecord[],
1639                                                  ChainContextClosureLookupContext &lookup_context)
1640 {
1641   if (intersects_array (c,
1642                         backtrackCount, backtrack,
1643                         lookup_context.funcs.intersects, lookup_context.intersects_data[0])
1644    && intersects_array (c,
1645                         inputCount ? inputCount - 1 : 0, input,
1646                         lookup_context.funcs.intersects, lookup_context.intersects_data[1])
1647    && intersects_array (c,
1648                        lookaheadCount, lookahead,
1649                        lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
1650     recurse_lookups (c,
1651                      lookupCount, lookupRecord);
1652 }
1653
1654 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1655                                                         unsigned int backtrackCount,
1656                                                         const HBUINT16 backtrack[],
1657                                                         unsigned int inputCount, /* Including the first glyph (not matched) */
1658                                                         const HBUINT16 input[], /* Array of input values--start with second glyph */
1659                                                         unsigned int lookaheadCount,
1660                                                         const HBUINT16 lookahead[],
1661                                                         unsigned int lookupCount,
1662                                                         const LookupRecord lookupRecord[],
1663                                                         ChainContextCollectGlyphsLookupContext &lookup_context)
1664 {
1665   collect_array (c, c->before,
1666                  backtrackCount, backtrack,
1667                  lookup_context.funcs.collect, lookup_context.collect_data[0]);
1668   collect_array (c, c->input,
1669                  inputCount ? inputCount - 1 : 0, input,
1670                  lookup_context.funcs.collect, lookup_context.collect_data[1]);
1671   collect_array (c, c->after,
1672                  lookaheadCount, lookahead,
1673                  lookup_context.funcs.collect, lookup_context.collect_data[2]);
1674   recurse_lookups (c,
1675                    lookupCount, lookupRecord);
1676 }
1677
1678 static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1679                                                      unsigned int backtrackCount,
1680                                                      const HBUINT16 backtrack[] HB_UNUSED,
1681                                                      unsigned int inputCount, /* Including the first glyph (not matched) */
1682                                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
1683                                                      unsigned int lookaheadCount,
1684                                                      const HBUINT16 lookahead[] HB_UNUSED,
1685                                                      unsigned int lookupCount HB_UNUSED,
1686                                                      const LookupRecord lookupRecord[] HB_UNUSED,
1687                                                      ChainContextApplyLookupContext &lookup_context)
1688 {
1689   return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
1690       && would_match_input (c,
1691                             inputCount, input,
1692                             lookup_context.funcs.match, lookup_context.match_data[1]);
1693 }
1694
1695 static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
1696                                                unsigned int backtrackCount,
1697                                                const HBUINT16 backtrack[],
1698                                                unsigned int inputCount, /* Including the first glyph (not matched) */
1699                                                const HBUINT16 input[], /* Array of input values--start with second glyph */
1700                                                unsigned int lookaheadCount,
1701                                                const HBUINT16 lookahead[],
1702                                                unsigned int lookupCount,
1703                                                const LookupRecord lookupRecord[],
1704                                                ChainContextApplyLookupContext &lookup_context)
1705 {
1706   unsigned int start_index = 0, match_length = 0, end_index = 0;
1707   unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
1708   return match_input (c,
1709                       inputCount, input,
1710                       lookup_context.funcs.match, lookup_context.match_data[1],
1711                       &match_length, match_positions)
1712       && match_backtrack (c,
1713                           backtrackCount, backtrack,
1714                           lookup_context.funcs.match, lookup_context.match_data[0],
1715                           &start_index)
1716       && match_lookahead (c,
1717                           lookaheadCount, lookahead,
1718                           lookup_context.funcs.match, lookup_context.match_data[2],
1719                           match_length, &end_index)
1720       && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
1721           apply_lookup (c,
1722                        inputCount, match_positions,
1723                        lookupCount, lookupRecord,
1724                        match_length));
1725 }
1726
1727 struct ChainRule
1728 {
1729   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
1730   {
1731     TRACE_CLOSURE (this);
1732     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1733     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
1734     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1735     chain_context_closure_lookup (c,
1736                                   backtrack.len, backtrack.arrayZ,
1737                                   input.len, input.arrayZ,
1738                                   lookahead.len, lookahead.arrayZ,
1739                                   lookup.len, lookup.arrayZ,
1740                                   lookup_context);
1741   }
1742
1743   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1744   {
1745     TRACE_COLLECT_GLYPHS (this);
1746     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1747     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
1748     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1749     chain_context_collect_glyphs_lookup (c,
1750                                          backtrack.len, backtrack.arrayZ,
1751                                          input.len, input.arrayZ,
1752                                          lookahead.len, lookahead.arrayZ,
1753                                          lookup.len, lookup.arrayZ,
1754                                          lookup_context);
1755   }
1756
1757   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1758   {
1759     TRACE_WOULD_APPLY (this);
1760     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1761     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
1762     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1763     return_trace (chain_context_would_apply_lookup (c,
1764                                                     backtrack.len, backtrack.arrayZ,
1765                                                     input.len, input.arrayZ,
1766                                                     lookahead.len, lookahead.arrayZ, lookup.len,
1767                                                     lookup.arrayZ, lookup_context));
1768   }
1769
1770   inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1771   {
1772     TRACE_APPLY (this);
1773     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1774     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
1775     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1776     return_trace (chain_context_apply_lookup (c,
1777                                               backtrack.len, backtrack.arrayZ,
1778                                               input.len, input.arrayZ,
1779                                               lookahead.len, lookahead.arrayZ, lookup.len,
1780                                               lookup.arrayZ, lookup_context));
1781   }
1782
1783   inline bool sanitize (hb_sanitize_context_t *c) const
1784   {
1785     TRACE_SANITIZE (this);
1786     if (!backtrack.sanitize (c)) return_trace (false);
1787     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1788     if (!input.sanitize (c)) return_trace (false);
1789     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
1790     if (!lookahead.sanitize (c)) return_trace (false);
1791     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1792     return_trace (lookup.sanitize (c));
1793   }
1794
1795   protected:
1796   ArrayOf<HBUINT16>
1797                 backtrack;              /* Array of backtracking values
1798                                          * (to be matched before the input
1799                                          * sequence) */
1800   HeadlessArrayOf<HBUINT16>
1801                 inputX;                 /* Array of input values (start with
1802                                          * second glyph) */
1803   ArrayOf<HBUINT16>
1804                 lookaheadX;             /* Array of lookahead values's (to be
1805                                          * matched after the input sequence) */
1806   ArrayOf<LookupRecord>
1807                 lookupX;                /* Array of LookupRecords--in
1808                                          * design order) */
1809   public:
1810   DEFINE_SIZE_MIN (8);
1811 };
1812
1813 struct ChainRuleSet
1814 {
1815   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
1816   {
1817     TRACE_CLOSURE (this);
1818     unsigned int num_rules = rule.len;
1819     for (unsigned int i = 0; i < num_rules; i++)
1820       (this+rule[i]).closure (c, lookup_context);
1821   }
1822
1823   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1824   {
1825     TRACE_COLLECT_GLYPHS (this);
1826     unsigned int num_rules = rule.len;
1827     for (unsigned int i = 0; i < num_rules; i++)
1828       (this+rule[i]).collect_glyphs (c, lookup_context);
1829   }
1830
1831   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1832   {
1833     TRACE_WOULD_APPLY (this);
1834     unsigned int num_rules = rule.len;
1835     for (unsigned int i = 0; i < num_rules; i++)
1836       if ((this+rule[i]).would_apply (c, lookup_context))
1837         return_trace (true);
1838
1839     return_trace (false);
1840   }
1841
1842   inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1843   {
1844     TRACE_APPLY (this);
1845     unsigned int num_rules = rule.len;
1846     for (unsigned int i = 0; i < num_rules; i++)
1847       if ((this+rule[i]).apply (c, lookup_context))
1848         return_trace (true);
1849
1850     return_trace (false);
1851   }
1852
1853   inline bool sanitize (hb_sanitize_context_t *c) const
1854   {
1855     TRACE_SANITIZE (this);
1856     return_trace (rule.sanitize (c, this));
1857   }
1858
1859   protected:
1860   OffsetArrayOf<ChainRule>
1861                 rule;                   /* Array of ChainRule tables
1862                                          * ordered by preference */
1863   public:
1864   DEFINE_SIZE_ARRAY (2, rule);
1865 };
1866
1867 struct ChainContextFormat1
1868 {
1869   inline void closure (hb_closure_context_t *c) const
1870   {
1871     TRACE_CLOSURE (this);
1872     const Coverage &cov = (this+coverage);
1873
1874     struct ChainContextClosureLookupContext lookup_context = {
1875       {intersects_glyph},
1876       {nullptr, nullptr, nullptr}
1877     };
1878
1879     unsigned int count = ruleSet.len;
1880     for (unsigned int i = 0; i < count; i++)
1881       if (cov.intersects_coverage (c->glyphs, i)) {
1882         const ChainRuleSet &rule_set = this+ruleSet[i];
1883         rule_set.closure (c, lookup_context);
1884       }
1885   }
1886
1887   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1888   {
1889     TRACE_COLLECT_GLYPHS (this);
1890     (this+coverage).add_coverage (c->input);
1891
1892     struct ChainContextCollectGlyphsLookupContext lookup_context = {
1893       {collect_glyph},
1894       {nullptr, nullptr, nullptr}
1895     };
1896
1897     unsigned int count = ruleSet.len;
1898     for (unsigned int i = 0; i < count; i++)
1899       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
1900   }
1901
1902   inline bool would_apply (hb_would_apply_context_t *c) const
1903   {
1904     TRACE_WOULD_APPLY (this);
1905
1906     const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
1907     struct ChainContextApplyLookupContext lookup_context = {
1908       {match_glyph},
1909       {nullptr, nullptr, nullptr}
1910     };
1911     return_trace (rule_set.would_apply (c, lookup_context));
1912   }
1913
1914   inline const Coverage &get_coverage (void) const
1915   {
1916     return this+coverage;
1917   }
1918
1919   inline bool apply (hb_ot_apply_context_t *c) const
1920   {
1921     TRACE_APPLY (this);
1922     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
1923     if (likely (index == NOT_COVERED)) return_trace (false);
1924
1925     const ChainRuleSet &rule_set = this+ruleSet[index];
1926     struct ChainContextApplyLookupContext lookup_context = {
1927       {match_glyph},
1928       {nullptr, nullptr, nullptr}
1929     };
1930     return_trace (rule_set.apply (c, lookup_context));
1931   }
1932
1933   inline bool sanitize (hb_sanitize_context_t *c) const
1934   {
1935     TRACE_SANITIZE (this);
1936     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
1937   }
1938
1939   protected:
1940   HBUINT16      format;                 /* Format identifier--format = 1 */
1941   OffsetTo<Coverage>
1942                 coverage;               /* Offset to Coverage table--from
1943                                          * beginning of table */
1944   OffsetArrayOf<ChainRuleSet>
1945                 ruleSet;                /* Array of ChainRuleSet tables
1946                                          * ordered by Coverage Index */
1947   public:
1948   DEFINE_SIZE_ARRAY (6, ruleSet);
1949 };
1950
1951 struct ChainContextFormat2
1952 {
1953   inline void closure (hb_closure_context_t *c) const
1954   {
1955     TRACE_CLOSURE (this);
1956     if (!(this+coverage).intersects (c->glyphs))
1957       return;
1958
1959     const ClassDef &backtrack_class_def = this+backtrackClassDef;
1960     const ClassDef &input_class_def = this+inputClassDef;
1961     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1962
1963     struct ChainContextClosureLookupContext lookup_context = {
1964       {intersects_class},
1965       {&backtrack_class_def,
1966        &input_class_def,
1967        &lookahead_class_def}
1968     };
1969
1970     unsigned int count = ruleSet.len;
1971     for (unsigned int i = 0; i < count; i++)
1972       if (input_class_def.intersects_class (c->glyphs, i)) {
1973         const ChainRuleSet &rule_set = this+ruleSet[i];
1974         rule_set.closure (c, lookup_context);
1975       }
1976   }
1977
1978   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1979   {
1980     TRACE_COLLECT_GLYPHS (this);
1981     (this+coverage).add_coverage (c->input);
1982
1983     const ClassDef &backtrack_class_def = this+backtrackClassDef;
1984     const ClassDef &input_class_def = this+inputClassDef;
1985     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1986
1987     struct ChainContextCollectGlyphsLookupContext lookup_context = {
1988       {collect_class},
1989       {&backtrack_class_def,
1990        &input_class_def,
1991        &lookahead_class_def}
1992     };
1993
1994     unsigned int count = ruleSet.len;
1995     for (unsigned int i = 0; i < count; i++)
1996       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
1997   }
1998
1999   inline bool would_apply (hb_would_apply_context_t *c) const
2000   {
2001     TRACE_WOULD_APPLY (this);
2002
2003     const ClassDef &backtrack_class_def = this+backtrackClassDef;
2004     const ClassDef &input_class_def = this+inputClassDef;
2005     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2006
2007     unsigned int index = input_class_def.get_class (c->glyphs[0]);
2008     const ChainRuleSet &rule_set = this+ruleSet[index];
2009     struct ChainContextApplyLookupContext lookup_context = {
2010       {match_class},
2011       {&backtrack_class_def,
2012        &input_class_def,
2013        &lookahead_class_def}
2014     };
2015     return_trace (rule_set.would_apply (c, lookup_context));
2016   }
2017
2018   inline const Coverage &get_coverage (void) const
2019   {
2020     return this+coverage;
2021   }
2022
2023   inline bool apply (hb_ot_apply_context_t *c) const
2024   {
2025     TRACE_APPLY (this);
2026     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
2027     if (likely (index == NOT_COVERED)) return_trace (false);
2028
2029     const ClassDef &backtrack_class_def = this+backtrackClassDef;
2030     const ClassDef &input_class_def = this+inputClassDef;
2031     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2032
2033     index = input_class_def.get_class (c->buffer->cur().codepoint);
2034     const ChainRuleSet &rule_set = this+ruleSet[index];
2035     struct ChainContextApplyLookupContext lookup_context = {
2036       {match_class},
2037       {&backtrack_class_def,
2038        &input_class_def,
2039        &lookahead_class_def}
2040     };
2041     return_trace (rule_set.apply (c, lookup_context));
2042   }
2043
2044   inline bool sanitize (hb_sanitize_context_t *c) const
2045   {
2046     TRACE_SANITIZE (this);
2047     return_trace (coverage.sanitize (c, this) &&
2048                   backtrackClassDef.sanitize (c, this) &&
2049                   inputClassDef.sanitize (c, this) &&
2050                   lookaheadClassDef.sanitize (c, this) &&
2051                   ruleSet.sanitize (c, this));
2052   }
2053
2054   protected:
2055   HBUINT16      format;                 /* Format identifier--format = 2 */
2056   OffsetTo<Coverage>
2057                 coverage;               /* Offset to Coverage table--from
2058                                          * beginning of table */
2059   OffsetTo<ClassDef>
2060                 backtrackClassDef;      /* Offset to glyph ClassDef table
2061                                          * containing backtrack sequence
2062                                          * data--from beginning of table */
2063   OffsetTo<ClassDef>
2064                 inputClassDef;          /* Offset to glyph ClassDef
2065                                          * table containing input sequence
2066                                          * data--from beginning of table */
2067   OffsetTo<ClassDef>
2068                 lookaheadClassDef;      /* Offset to glyph ClassDef table
2069                                          * containing lookahead sequence
2070                                          * data--from beginning of table */
2071   OffsetArrayOf<ChainRuleSet>
2072                 ruleSet;                /* Array of ChainRuleSet tables
2073                                          * ordered by class */
2074   public:
2075   DEFINE_SIZE_ARRAY (12, ruleSet);
2076 };
2077
2078 struct ChainContextFormat3
2079 {
2080   inline void closure (hb_closure_context_t *c) const
2081   {
2082     TRACE_CLOSURE (this);
2083     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2084
2085     if (!(this+input[0]).intersects (c->glyphs))
2086       return;
2087
2088     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2089     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2090     struct ChainContextClosureLookupContext lookup_context = {
2091       {intersects_coverage},
2092       {this, this, this}
2093     };
2094     chain_context_closure_lookup (c,
2095                                   backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2096                                   input.len, (const HBUINT16 *) input.arrayZ + 1,
2097                                   lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2098                                   lookup.len, lookup.arrayZ,
2099                                   lookup_context);
2100   }
2101
2102   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
2103   {
2104     TRACE_COLLECT_GLYPHS (this);
2105     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2106
2107     (this+input[0]).add_coverage (c->input);
2108
2109     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2110     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2111     struct ChainContextCollectGlyphsLookupContext lookup_context = {
2112       {collect_coverage},
2113       {this, this, this}
2114     };
2115     chain_context_collect_glyphs_lookup (c,
2116                                          backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2117                                          input.len, (const HBUINT16 *) input.arrayZ + 1,
2118                                          lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2119                                          lookup.len, lookup.arrayZ,
2120                                          lookup_context);
2121   }
2122
2123   inline bool would_apply (hb_would_apply_context_t *c) const
2124   {
2125     TRACE_WOULD_APPLY (this);
2126
2127     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2128     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2129     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2130     struct ChainContextApplyLookupContext lookup_context = {
2131       {match_coverage},
2132       {this, this, this}
2133     };
2134     return_trace (chain_context_would_apply_lookup (c,
2135                                                     backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2136                                                     input.len, (const HBUINT16 *) input.arrayZ + 1,
2137                                                     lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2138                                                     lookup.len, lookup.arrayZ, lookup_context));
2139   }
2140
2141   inline const Coverage &get_coverage (void) const
2142   {
2143     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2144     return this+input[0];
2145   }
2146
2147   inline bool apply (hb_ot_apply_context_t *c) const
2148   {
2149     TRACE_APPLY (this);
2150     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2151
2152     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
2153     if (likely (index == NOT_COVERED)) return_trace (false);
2154
2155     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2156     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2157     struct ChainContextApplyLookupContext lookup_context = {
2158       {match_coverage},
2159       {this, this, this}
2160     };
2161     return_trace (chain_context_apply_lookup (c,
2162                                               backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2163                                               input.len, (const HBUINT16 *) input.arrayZ + 1,
2164                                               lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2165                                               lookup.len, lookup.arrayZ, lookup_context));
2166   }
2167
2168   inline bool sanitize (hb_sanitize_context_t *c) const
2169   {
2170     TRACE_SANITIZE (this);
2171     if (!backtrack.sanitize (c, this)) return_trace (false);
2172     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2173     if (!input.sanitize (c, this)) return_trace (false);
2174     if (!input.len) return_trace (false); /* To be consistent with Context. */
2175     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2176     if (!lookahead.sanitize (c, this)) return_trace (false);
2177     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2178     return_trace (lookup.sanitize (c));
2179   }
2180
2181   protected:
2182   HBUINT16      format;                 /* Format identifier--format = 3 */
2183   OffsetArrayOf<Coverage>
2184                 backtrack;              /* Array of coverage tables
2185                                          * in backtracking sequence, in  glyph
2186                                          * sequence order */
2187   OffsetArrayOf<Coverage>
2188                 inputX          ;       /* Array of coverage
2189                                          * tables in input sequence, in glyph
2190                                          * sequence order */
2191   OffsetArrayOf<Coverage>
2192                 lookaheadX;             /* Array of coverage tables
2193                                          * in lookahead sequence, in glyph
2194                                          * sequence order */
2195   ArrayOf<LookupRecord>
2196                 lookupX;                /* Array of LookupRecords--in
2197                                          * design order) */
2198   public:
2199   DEFINE_SIZE_MIN (10);
2200 };
2201
2202 struct ChainContext
2203 {
2204   template <typename context_t>
2205   inline typename context_t::return_t dispatch (context_t *c) const
2206   {
2207     TRACE_DISPATCH (this, u.format);
2208     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
2209     switch (u.format) {
2210     case 1: return_trace (c->dispatch (u.format1));
2211     case 2: return_trace (c->dispatch (u.format2));
2212     case 3: return_trace (c->dispatch (u.format3));
2213     default:return_trace (c->default_return_value ());
2214     }
2215   }
2216
2217   protected:
2218   union {
2219   HBUINT16              format; /* Format identifier */
2220   ChainContextFormat1   format1;
2221   ChainContextFormat2   format2;
2222   ChainContextFormat3   format3;
2223   } u;
2224 };
2225
2226
2227 template <typename T>
2228 struct ExtensionFormat1
2229 {
2230   inline unsigned int get_type (void) const { return extensionLookupType; }
2231
2232   template <typename X>
2233   inline const X& get_subtable (void) const
2234   {
2235     unsigned int offset = extensionOffset;
2236     if (unlikely (!offset)) return Null(typename T::LookupSubTable);
2237     return StructAtOffset<typename T::LookupSubTable> (this, offset);
2238   }
2239
2240   template <typename context_t>
2241   inline typename context_t::return_t dispatch (context_t *c) const
2242   {
2243     TRACE_DISPATCH (this, format);
2244     if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
2245     return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
2246   }
2247
2248   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
2249   inline bool sanitize (hb_sanitize_context_t *c) const
2250   {
2251     TRACE_SANITIZE (this);
2252     return_trace (c->check_struct (this) &&
2253                   extensionOffset != 0 &&
2254                   extensionLookupType != T::LookupSubTable::Extension);
2255   }
2256
2257   protected:
2258   HBUINT16      format;                 /* Format identifier. Set to 1. */
2259   HBUINT16      extensionLookupType;    /* Lookup type of subtable referenced
2260                                          * by ExtensionOffset (i.e. the
2261                                          * extension subtable). */
2262   HBUINT32      extensionOffset;        /* Offset to the extension subtable,
2263                                          * of lookup type subtable. */
2264   public:
2265   DEFINE_SIZE_STATIC (8);
2266 };
2267
2268 template <typename T>
2269 struct Extension
2270 {
2271   inline unsigned int get_type (void) const
2272   {
2273     switch (u.format) {
2274     case 1: return u.format1.get_type ();
2275     default:return 0;
2276     }
2277   }
2278   template <typename X>
2279   inline const X& get_subtable (void) const
2280   {
2281     switch (u.format) {
2282     case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
2283     default:return Null(typename T::LookupSubTable);
2284     }
2285   }
2286
2287   template <typename context_t>
2288   inline typename context_t::return_t dispatch (context_t *c) const
2289   {
2290     TRACE_DISPATCH (this, u.format);
2291     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
2292     switch (u.format) {
2293     case 1: return_trace (u.format1.dispatch (c));
2294     default:return_trace (c->default_return_value ());
2295     }
2296   }
2297
2298   protected:
2299   union {
2300   HBUINT16              format;         /* Format identifier */
2301   ExtensionFormat1<T>   format1;
2302   } u;
2303 };
2304
2305
2306 /*
2307  * GSUB/GPOS Common
2308  */
2309
2310 struct GSUBGPOS
2311 {
2312   inline unsigned int get_script_count (void) const
2313   { return (this+scriptList).len; }
2314   inline const Tag& get_script_tag (unsigned int i) const
2315   { return (this+scriptList).get_tag (i); }
2316   inline unsigned int get_script_tags (unsigned int start_offset,
2317                                        unsigned int *script_count /* IN/OUT */,
2318                                        hb_tag_t     *script_tags /* OUT */) const
2319   { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
2320   inline const Script& get_script (unsigned int i) const
2321   { return (this+scriptList)[i]; }
2322   inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
2323   { return (this+scriptList).find_index (tag, index); }
2324
2325   inline unsigned int get_feature_count (void) const
2326   { return (this+featureList).len; }
2327   inline hb_tag_t get_feature_tag (unsigned int i) const
2328   { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
2329   inline unsigned int get_feature_tags (unsigned int start_offset,
2330                                         unsigned int *feature_count /* IN/OUT */,
2331                                         hb_tag_t     *feature_tags /* OUT */) const
2332   { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
2333   inline const Feature& get_feature (unsigned int i) const
2334   { return (this+featureList)[i]; }
2335   inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
2336   { return (this+featureList).find_index (tag, index); }
2337
2338   inline unsigned int get_lookup_count (void) const
2339   { return (this+lookupList).len; }
2340   inline const Lookup& get_lookup (unsigned int i) const
2341   { return (this+lookupList)[i]; }
2342
2343   inline bool find_variations_index (const int *coords, unsigned int num_coords,
2344                                      unsigned int *index) const
2345   { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
2346            .find_index (coords, num_coords, index); }
2347   inline const Feature& get_feature_variation (unsigned int feature_index,
2348                                                unsigned int variations_index) const
2349   {
2350     if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
2351         version.to_int () >= 0x00010001u)
2352     {
2353       const Feature *feature = (this+featureVars).find_substitute (variations_index,
2354                                                                    feature_index);
2355       if (feature)
2356         return *feature;
2357     }
2358     return get_feature (feature_index);
2359   }
2360
2361   inline bool sanitize (hb_sanitize_context_t *c) const
2362   {
2363     TRACE_SANITIZE (this);
2364     return_trace (version.sanitize (c) &&
2365                   likely (version.major == 1) &&
2366                   scriptList.sanitize (c, this) &&
2367                   featureList.sanitize (c, this) &&
2368                   lookupList.sanitize (c, this) &&
2369                   (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
2370   }
2371
2372   protected:
2373   FixedVersion<>version;        /* Version of the GSUB/GPOS table--initially set
2374                                  * to 0x00010000u */
2375   OffsetTo<ScriptList>
2376                 scriptList;     /* ScriptList table */
2377   OffsetTo<FeatureList>
2378                 featureList;    /* FeatureList table */
2379   OffsetTo<LookupList>
2380                 lookupList;     /* LookupList table */
2381   LOffsetTo<FeatureVariations>
2382                 featureVars;    /* Offset to Feature Variations
2383                                    table--from beginning of table
2384                                  * (may be NULL).  Introduced
2385                                  * in version 0x00010001. */
2386   public:
2387   DEFINE_SIZE_MIN (10);
2388 };
2389
2390
2391 } /* namespace OT */
2392
2393
2394 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */