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