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