Home | History | Annotate | Download | only in src
      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, HB_DEBUG_CLOSURE>
     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, HB_DEBUG_COLLECT_GLYPHS>
    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, 2> 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     TRACE_CLOSURE (this);
   1300     const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
   1301 						       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
   1302     context_closure_lookup (c,
   1303 			    inputCount, inputZ.arrayZ,
   1304 			    lookupCount, lookupRecord.arrayZ,
   1305 			    lookup_context);
   1306   }
   1307 
   1308   void collect_glyphs (hb_collect_glyphs_context_t *c,
   1309 		       ContextCollectGlyphsLookupContext &lookup_context) const
   1310   {
   1311     TRACE_COLLECT_GLYPHS (this);
   1312     const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
   1313 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
   1314     context_collect_glyphs_lookup (c,
   1315 				   inputCount, inputZ.arrayZ,
   1316 				   lookupCount, lookupRecord.arrayZ,
   1317 				   lookup_context);
   1318   }
   1319 
   1320   bool would_apply (hb_would_apply_context_t *c,
   1321 		    ContextApplyLookupContext &lookup_context) const
   1322   {
   1323     TRACE_WOULD_APPLY (this);
   1324     const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
   1325 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
   1326     return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
   1327   }
   1328 
   1329   bool apply (hb_ot_apply_context_t *c,
   1330 	      ContextApplyLookupContext &lookup_context) const
   1331   {
   1332     TRACE_APPLY (this);
   1333     const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
   1334 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
   1335     return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
   1336   }
   1337 
   1338   public:
   1339   bool sanitize (hb_sanitize_context_t *c) const
   1340   {
   1341     TRACE_SANITIZE (this);
   1342     return_trace (inputCount.sanitize (c) &&
   1343 		  lookupCount.sanitize (c) &&
   1344 		  c->check_range (inputZ.arrayZ,
   1345 				  inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
   1346 				  LookupRecord::static_size * lookupCount));
   1347   }
   1348 
   1349   protected:
   1350   HBUINT16	inputCount;		/* Total number of glyphs in input
   1351 					 * glyph sequence--includes the first
   1352 					 * glyph */
   1353   HBUINT16	lookupCount;		/* Number of LookupRecords */
   1354   UnsizedArrayOf<HBUINT16>
   1355  		inputZ;			/* Array of match inputs--start with
   1356 					 * second glyph */
   1357 /*UnsizedArrayOf<LookupRecord>
   1358 		lookupRecordX;*/	/* Array of LookupRecords--in
   1359 					 * design order */
   1360   public:
   1361   DEFINE_SIZE_ARRAY (4, inputZ);
   1362 };
   1363 
   1364 struct RuleSet
   1365 {
   1366   bool intersects (const hb_set_t *glyphs,
   1367 		   ContextClosureLookupContext &lookup_context) const
   1368   {
   1369     unsigned int num_rules = rule.len;
   1370     for (unsigned int i = 0; i < num_rules; i++)
   1371       if ((this+rule[i]).intersects (glyphs, lookup_context))
   1372 	return true;
   1373     return false;
   1374   }
   1375 
   1376   void closure (hb_closure_context_t *c,
   1377 		ContextClosureLookupContext &lookup_context) const
   1378   {
   1379     TRACE_CLOSURE (this);
   1380     unsigned int num_rules = rule.len;
   1381     for (unsigned int i = 0; i < num_rules; i++)
   1382       (this+rule[i]).closure (c, lookup_context);
   1383   }
   1384 
   1385   void collect_glyphs (hb_collect_glyphs_context_t *c,
   1386 		       ContextCollectGlyphsLookupContext &lookup_context) const
   1387   {
   1388     TRACE_COLLECT_GLYPHS (this);
   1389     unsigned int num_rules = rule.len;
   1390     for (unsigned int i = 0; i < num_rules; i++)
   1391       (this+rule[i]).collect_glyphs (c, lookup_context);
   1392   }
   1393 
   1394   bool would_apply (hb_would_apply_context_t *c,
   1395 		    ContextApplyLookupContext &lookup_context) const
   1396   {
   1397     TRACE_WOULD_APPLY (this);
   1398     unsigned int num_rules = rule.len;
   1399     for (unsigned int i = 0; i < num_rules; i++)
   1400     {
   1401       if ((this+rule[i]).would_apply (c, lookup_context))
   1402 	return_trace (true);
   1403     }
   1404     return_trace (false);
   1405   }
   1406 
   1407   bool apply (hb_ot_apply_context_t *c,
   1408 	      ContextApplyLookupContext &lookup_context) const
   1409   {
   1410     TRACE_APPLY (this);
   1411     unsigned int num_rules = rule.len;
   1412     for (unsigned int i = 0; i < num_rules; i++)
   1413     {
   1414       if ((this+rule[i]).apply (c, lookup_context))
   1415 	return_trace (true);
   1416     }
   1417     return_trace (false);
   1418   }
   1419 
   1420   bool sanitize (hb_sanitize_context_t *c) const
   1421   {
   1422     TRACE_SANITIZE (this);
   1423     return_trace (rule.sanitize (c, this));
   1424   }
   1425 
   1426   protected:
   1427   OffsetArrayOf<Rule>
   1428 		rule;			/* Array of Rule tables
   1429 					 * ordered by preference */
   1430   public:
   1431   DEFINE_SIZE_ARRAY (2, rule);
   1432 };
   1433 
   1434 
   1435 struct ContextFormat1
   1436 {
   1437   bool intersects (const hb_set_t *glyphs) const
   1438   {
   1439     struct ContextClosureLookupContext lookup_context = {
   1440       {intersects_glyph},
   1441       nullptr
   1442     };
   1443 
   1444     unsigned int count = ruleSet.len;
   1445     for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
   1446     {
   1447       if (unlikely (iter.get_coverage () >= count))
   1448 	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
   1449       if (glyphs->has (iter.get_glyph ()) &&
   1450 	  (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
   1451 	return true;
   1452     }
   1453     return false;
   1454   }
   1455 
   1456   void closure (hb_closure_context_t *c) const
   1457   {
   1458     TRACE_CLOSURE (this);
   1459 
   1460     struct ContextClosureLookupContext lookup_context = {
   1461       {intersects_glyph},
   1462       nullptr
   1463     };
   1464 
   1465     unsigned int count = ruleSet.len;
   1466     for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
   1467     {
   1468       if (unlikely (iter.get_coverage () >= count))
   1469 	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
   1470       if (c->glyphs->has (iter.get_glyph ()))
   1471 	(this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
   1472     }
   1473   }
   1474 
   1475   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   1476   {
   1477     TRACE_COLLECT_GLYPHS (this);
   1478     (this+coverage).add_coverage (c->input);
   1479 
   1480     struct ContextCollectGlyphsLookupContext lookup_context = {
   1481       {collect_glyph},
   1482       nullptr
   1483     };
   1484 
   1485     unsigned int count = ruleSet.len;
   1486     for (unsigned int i = 0; i < count; i++)
   1487       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
   1488   }
   1489 
   1490   bool would_apply (hb_would_apply_context_t *c) const
   1491   {
   1492     TRACE_WOULD_APPLY (this);
   1493 
   1494     const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
   1495     struct ContextApplyLookupContext lookup_context = {
   1496       {match_glyph},
   1497       nullptr
   1498     };
   1499     return_trace (rule_set.would_apply (c, lookup_context));
   1500   }
   1501 
   1502   const Coverage &get_coverage () const { return this+coverage; }
   1503 
   1504   bool apply (hb_ot_apply_context_t *c) const
   1505   {
   1506     TRACE_APPLY (this);
   1507     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
   1508     if (likely (index == NOT_COVERED))
   1509       return_trace (false);
   1510 
   1511     const RuleSet &rule_set = this+ruleSet[index];
   1512     struct ContextApplyLookupContext lookup_context = {
   1513       {match_glyph},
   1514       nullptr
   1515     };
   1516     return_trace (rule_set.apply (c, lookup_context));
   1517   }
   1518 
   1519   bool subset (hb_subset_context_t *c) const
   1520   {
   1521     TRACE_SUBSET (this);
   1522     // TODO(subset)
   1523     return_trace (false);
   1524   }
   1525 
   1526   bool sanitize (hb_sanitize_context_t *c) const
   1527   {
   1528     TRACE_SANITIZE (this);
   1529     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   1530   }
   1531 
   1532   protected:
   1533   HBUINT16	format;			/* Format identifier--format = 1 */
   1534   OffsetTo<Coverage>
   1535 		coverage;		/* Offset to Coverage table--from
   1536 					 * beginning of table */
   1537   OffsetArrayOf<RuleSet>
   1538 		ruleSet;		/* Array of RuleSet tables
   1539 					 * ordered by Coverage Index */
   1540   public:
   1541   DEFINE_SIZE_ARRAY (6, ruleSet);
   1542 };
   1543 
   1544 
   1545 struct ContextFormat2
   1546 {
   1547   bool intersects (const hb_set_t *glyphs) const
   1548   {
   1549     if (!(this+coverage).intersects (glyphs))
   1550       return false;
   1551 
   1552     const ClassDef &class_def = this+classDef;
   1553 
   1554     struct ContextClosureLookupContext lookup_context = {
   1555       {intersects_class},
   1556       &class_def
   1557     };
   1558 
   1559     unsigned int count = ruleSet.len;
   1560     for (unsigned int i = 0; i < count; i++)
   1561       if (class_def.intersects_class (glyphs, i) &&
   1562 	  (this+ruleSet[i]).intersects (glyphs, lookup_context))
   1563 	return true;
   1564 
   1565     return false;
   1566   }
   1567 
   1568   void closure (hb_closure_context_t *c) const
   1569   {
   1570     TRACE_CLOSURE (this);
   1571     if (!(this+coverage).intersects (c->glyphs))
   1572       return;
   1573 
   1574     const ClassDef &class_def = this+classDef;
   1575 
   1576     struct ContextClosureLookupContext lookup_context = {
   1577       {intersects_class},
   1578       &class_def
   1579     };
   1580 
   1581     unsigned int count = ruleSet.len;
   1582     for (unsigned int i = 0; i < count; i++)
   1583       if (class_def.intersects_class (c->glyphs, i)) {
   1584 	const RuleSet &rule_set = this+ruleSet[i];
   1585 	rule_set.closure (c, lookup_context);
   1586       }
   1587   }
   1588 
   1589   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   1590   {
   1591     TRACE_COLLECT_GLYPHS (this);
   1592     (this+coverage).add_coverage (c->input);
   1593 
   1594     const ClassDef &class_def = this+classDef;
   1595     struct ContextCollectGlyphsLookupContext lookup_context = {
   1596       {collect_class},
   1597       &class_def
   1598     };
   1599 
   1600     unsigned int count = ruleSet.len;
   1601     for (unsigned int i = 0; i < count; i++)
   1602       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
   1603   }
   1604 
   1605   bool would_apply (hb_would_apply_context_t *c) const
   1606   {
   1607     TRACE_WOULD_APPLY (this);
   1608 
   1609     const ClassDef &class_def = this+classDef;
   1610     unsigned int index = class_def.get_class (c->glyphs[0]);
   1611     const RuleSet &rule_set = this+ruleSet[index];
   1612     struct ContextApplyLookupContext lookup_context = {
   1613       {match_class},
   1614       &class_def
   1615     };
   1616     return_trace (rule_set.would_apply (c, lookup_context));
   1617   }
   1618 
   1619   const Coverage &get_coverage () const { return this+coverage; }
   1620 
   1621   bool apply (hb_ot_apply_context_t *c) const
   1622   {
   1623     TRACE_APPLY (this);
   1624     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
   1625     if (likely (index == NOT_COVERED)) return_trace (false);
   1626 
   1627     const ClassDef &class_def = this+classDef;
   1628     index = class_def.get_class (c->buffer->cur().codepoint);
   1629     const RuleSet &rule_set = this+ruleSet[index];
   1630     struct ContextApplyLookupContext lookup_context = {
   1631       {match_class},
   1632       &class_def
   1633     };
   1634     return_trace (rule_set.apply (c, lookup_context));
   1635   }
   1636 
   1637   bool subset (hb_subset_context_t *c) const
   1638   {
   1639     TRACE_SUBSET (this);
   1640     // TODO(subset)
   1641     return_trace (false);
   1642   }
   1643 
   1644   bool sanitize (hb_sanitize_context_t *c) const
   1645   {
   1646     TRACE_SANITIZE (this);
   1647     return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
   1648   }
   1649 
   1650   protected:
   1651   HBUINT16	format;			/* Format identifier--format = 2 */
   1652   OffsetTo<Coverage>
   1653 		coverage;		/* Offset to Coverage table--from
   1654 					 * beginning of table */
   1655   OffsetTo<ClassDef>
   1656 		classDef;		/* Offset to glyph ClassDef table--from
   1657 					 * beginning of table */
   1658   OffsetArrayOf<RuleSet>
   1659 		ruleSet;		/* Array of RuleSet tables
   1660 					 * ordered by class */
   1661   public:
   1662   DEFINE_SIZE_ARRAY (8, ruleSet);
   1663 };
   1664 
   1665 
   1666 struct ContextFormat3
   1667 {
   1668   bool intersects (const hb_set_t *glyphs) const
   1669   {
   1670     if (!(this+coverageZ[0]).intersects (glyphs))
   1671       return false;
   1672 
   1673     struct ContextClosureLookupContext lookup_context = {
   1674       {intersects_coverage},
   1675       this
   1676     };
   1677     return context_intersects (glyphs,
   1678 			       glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
   1679 			       lookup_context);
   1680   }
   1681 
   1682   void closure (hb_closure_context_t *c) const
   1683   {
   1684     TRACE_CLOSURE (this);
   1685     if (!(this+coverageZ[0]).intersects (c->glyphs))
   1686       return;
   1687 
   1688     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
   1689     struct ContextClosureLookupContext lookup_context = {
   1690       {intersects_coverage},
   1691       this
   1692     };
   1693     context_closure_lookup (c,
   1694 			    glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
   1695 			    lookupCount, lookupRecord,
   1696 			    lookup_context);
   1697   }
   1698 
   1699   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   1700   {
   1701     TRACE_COLLECT_GLYPHS (this);
   1702     (this+coverageZ[0]).add_coverage (c->input);
   1703 
   1704     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
   1705     struct ContextCollectGlyphsLookupContext lookup_context = {
   1706       {collect_coverage},
   1707       this
   1708     };
   1709 
   1710     context_collect_glyphs_lookup (c,
   1711 				   glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
   1712 				   lookupCount, lookupRecord,
   1713 				   lookup_context);
   1714   }
   1715 
   1716   bool would_apply (hb_would_apply_context_t *c) const
   1717   {
   1718     TRACE_WOULD_APPLY (this);
   1719 
   1720     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
   1721     struct ContextApplyLookupContext lookup_context = {
   1722       {match_coverage},
   1723       this
   1724     };
   1725     return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
   1726   }
   1727 
   1728   const Coverage &get_coverage () const { return this+coverageZ[0]; }
   1729 
   1730   bool apply (hb_ot_apply_context_t *c) const
   1731   {
   1732     TRACE_APPLY (this);
   1733     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
   1734     if (likely (index == NOT_COVERED)) return_trace (false);
   1735 
   1736     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
   1737     struct ContextApplyLookupContext lookup_context = {
   1738       {match_coverage},
   1739       this
   1740     };
   1741     return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
   1742   }
   1743 
   1744   bool subset (hb_subset_context_t *c) const
   1745   {
   1746     TRACE_SUBSET (this);
   1747     // TODO(subset)
   1748     return_trace (false);
   1749   }
   1750 
   1751   bool sanitize (hb_sanitize_context_t *c) const
   1752   {
   1753     TRACE_SANITIZE (this);
   1754     if (!c->check_struct (this)) return_trace (false);
   1755     unsigned int count = glyphCount;
   1756     if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
   1757     if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
   1758     for (unsigned int i = 0; i < count; i++)
   1759       if (!coverageZ[i].sanitize (c, this)) return_trace (false);
   1760     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
   1761     return_trace (c->check_array (lookupRecord, lookupCount));
   1762   }
   1763 
   1764   protected:
   1765   HBUINT16	format;			/* Format identifier--format = 3 */
   1766   HBUINT16	glyphCount;		/* Number of glyphs in the input glyph
   1767 					 * sequence */
   1768   HBUINT16	lookupCount;		/* Number of LookupRecords */
   1769   UnsizedArrayOf<OffsetTo<Coverage> >
   1770 		coverageZ;		/* Array of offsets to Coverage
   1771 					 * table in glyph sequence order */
   1772 /*UnsizedArrayOf<LookupRecord>
   1773 		lookupRecordX;*/	/* Array of LookupRecords--in
   1774 					 * design order */
   1775   public:
   1776   DEFINE_SIZE_ARRAY (6, coverageZ);
   1777 };
   1778 
   1779 struct Context
   1780 {
   1781   template <typename context_t>
   1782   typename context_t::return_t dispatch (context_t *c) const
   1783   {
   1784     TRACE_DISPATCH (this, u.format);
   1785     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
   1786     switch (u.format) {
   1787     case 1: return_trace (c->dispatch (u.format1));
   1788     case 2: return_trace (c->dispatch (u.format2));
   1789     case 3: return_trace (c->dispatch (u.format3));
   1790     default:return_trace (c->default_return_value ());
   1791     }
   1792   }
   1793 
   1794   protected:
   1795   union {
   1796   HBUINT16		format;		/* Format identifier */
   1797   ContextFormat1	format1;
   1798   ContextFormat2	format2;
   1799   ContextFormat3	format3;
   1800   } u;
   1801 };
   1802 
   1803 
   1804 /* Chaining Contextual lookups */
   1805 
   1806 struct ChainContextClosureLookupContext
   1807 {
   1808   ContextClosureFuncs funcs;
   1809   const void *intersects_data[3];
   1810 };
   1811 
   1812 struct ChainContextCollectGlyphsLookupContext
   1813 {
   1814   ContextCollectGlyphsFuncs funcs;
   1815   const void *collect_data[3];
   1816 };
   1817 
   1818 struct ChainContextApplyLookupContext
   1819 {
   1820   ContextApplyFuncs funcs;
   1821   const void *match_data[3];
   1822 };
   1823 
   1824 static inline bool chain_context_intersects (const hb_set_t *glyphs,
   1825 					     unsigned int backtrackCount,
   1826 					     const HBUINT16 backtrack[],
   1827 					     unsigned int inputCount, /* Including the first glyph (not matched) */
   1828 					     const HBUINT16 input[], /* Array of input values--start with second glyph */
   1829 					     unsigned int lookaheadCount,
   1830 					     const HBUINT16 lookahead[],
   1831 					     ChainContextClosureLookupContext &lookup_context)
   1832 {
   1833   return intersects_array (glyphs,
   1834 			   backtrackCount, backtrack,
   1835 			   lookup_context.funcs.intersects, lookup_context.intersects_data[0])
   1836       && intersects_array (glyphs,
   1837 			   inputCount ? inputCount - 1 : 0, input,
   1838 			   lookup_context.funcs.intersects, lookup_context.intersects_data[1])
   1839       && intersects_array (glyphs,
   1840 			  lookaheadCount, lookahead,
   1841 			  lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
   1842 }
   1843 
   1844 static inline void chain_context_closure_lookup (hb_closure_context_t *c,
   1845 						 unsigned int backtrackCount,
   1846 						 const HBUINT16 backtrack[],
   1847 						 unsigned int inputCount, /* Including the first glyph (not matched) */
   1848 						 const HBUINT16 input[], /* Array of input values--start with second glyph */
   1849 						 unsigned int lookaheadCount,
   1850 						 const HBUINT16 lookahead[],
   1851 						 unsigned int lookupCount,
   1852 						 const LookupRecord lookupRecord[],
   1853 						 ChainContextClosureLookupContext &lookup_context)
   1854 {
   1855   if (chain_context_intersects (c->glyphs,
   1856 				backtrackCount, backtrack,
   1857 				inputCount, input,
   1858 				lookaheadCount, lookahead,
   1859 				lookup_context))
   1860     recurse_lookups (c,
   1861 		     lookupCount, lookupRecord);
   1862 }
   1863 
   1864 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
   1865 							unsigned int backtrackCount,
   1866 							const HBUINT16 backtrack[],
   1867 							unsigned int inputCount, /* Including the first glyph (not matched) */
   1868 							const HBUINT16 input[], /* Array of input values--start with second glyph */
   1869 							unsigned int lookaheadCount,
   1870 							const HBUINT16 lookahead[],
   1871 							unsigned int lookupCount,
   1872 							const LookupRecord lookupRecord[],
   1873 							ChainContextCollectGlyphsLookupContext &lookup_context)
   1874 {
   1875   collect_array (c, c->before,
   1876 		 backtrackCount, backtrack,
   1877 		 lookup_context.funcs.collect, lookup_context.collect_data[0]);
   1878   collect_array (c, c->input,
   1879 		 inputCount ? inputCount - 1 : 0, input,
   1880 		 lookup_context.funcs.collect, lookup_context.collect_data[1]);
   1881   collect_array (c, c->after,
   1882 		 lookaheadCount, lookahead,
   1883 		 lookup_context.funcs.collect, lookup_context.collect_data[2]);
   1884   recurse_lookups (c,
   1885 		   lookupCount, lookupRecord);
   1886 }
   1887 
   1888 static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
   1889 						     unsigned int backtrackCount,
   1890 						     const HBUINT16 backtrack[] HB_UNUSED,
   1891 						     unsigned int inputCount, /* Including the first glyph (not matched) */
   1892 						     const HBUINT16 input[], /* Array of input values--start with second glyph */
   1893 						     unsigned int lookaheadCount,
   1894 						     const HBUINT16 lookahead[] HB_UNUSED,
   1895 						     unsigned int lookupCount HB_UNUSED,
   1896 						     const LookupRecord lookupRecord[] HB_UNUSED,
   1897 						     ChainContextApplyLookupContext &lookup_context)
   1898 {
   1899   return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
   1900       && would_match_input (c,
   1901 			    inputCount, input,
   1902 			    lookup_context.funcs.match, lookup_context.match_data[1]);
   1903 }
   1904 
   1905 static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
   1906 					       unsigned int backtrackCount,
   1907 					       const HBUINT16 backtrack[],
   1908 					       unsigned int inputCount, /* Including the first glyph (not matched) */
   1909 					       const HBUINT16 input[], /* Array of input values--start with second glyph */
   1910 					       unsigned int lookaheadCount,
   1911 					       const HBUINT16 lookahead[],
   1912 					       unsigned int lookupCount,
   1913 					       const LookupRecord lookupRecord[],
   1914 					       ChainContextApplyLookupContext &lookup_context)
   1915 {
   1916   unsigned int start_index = 0, match_length = 0, end_index = 0;
   1917   unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
   1918   return match_input (c,
   1919 		      inputCount, input,
   1920 		      lookup_context.funcs.match, lookup_context.match_data[1],
   1921 		      &match_length, match_positions)
   1922       && match_backtrack (c,
   1923 			  backtrackCount, backtrack,
   1924 			  lookup_context.funcs.match, lookup_context.match_data[0],
   1925 			  &start_index)
   1926       && match_lookahead (c,
   1927 			  lookaheadCount, lookahead,
   1928 			  lookup_context.funcs.match, lookup_context.match_data[2],
   1929 			  match_length, &end_index)
   1930       && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
   1931 	  apply_lookup (c,
   1932 			inputCount, match_positions,
   1933 			lookupCount, lookupRecord,
   1934 			match_length));
   1935 }
   1936 
   1937 struct ChainRule
   1938 {
   1939   bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
   1940   {
   1941     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
   1942     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
   1943     return chain_context_intersects (glyphs,
   1944 				     backtrack.len, backtrack.arrayZ,
   1945 				     input.lenP1, input.arrayZ,
   1946 				     lookahead.len, lookahead.arrayZ,
   1947 				     lookup_context);
   1948   }
   1949 
   1950   void closure (hb_closure_context_t *c,
   1951 		ChainContextClosureLookupContext &lookup_context) const
   1952   {
   1953     TRACE_CLOSURE (this);
   1954     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
   1955     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
   1956     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   1957     chain_context_closure_lookup (c,
   1958 				  backtrack.len, backtrack.arrayZ,
   1959 				  input.lenP1, input.arrayZ,
   1960 				  lookahead.len, lookahead.arrayZ,
   1961 				  lookup.len, lookup.arrayZ,
   1962 				  lookup_context);
   1963   }
   1964 
   1965   void collect_glyphs (hb_collect_glyphs_context_t *c,
   1966 		       ChainContextCollectGlyphsLookupContext &lookup_context) const
   1967   {
   1968     TRACE_COLLECT_GLYPHS (this);
   1969     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
   1970     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
   1971     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   1972     chain_context_collect_glyphs_lookup (c,
   1973 					 backtrack.len, backtrack.arrayZ,
   1974 					 input.lenP1, input.arrayZ,
   1975 					 lookahead.len, lookahead.arrayZ,
   1976 					 lookup.len, lookup.arrayZ,
   1977 					 lookup_context);
   1978   }
   1979 
   1980   bool would_apply (hb_would_apply_context_t *c,
   1981 		    ChainContextApplyLookupContext &lookup_context) const
   1982   {
   1983     TRACE_WOULD_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_would_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 apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   1995   {
   1996     TRACE_APPLY (this);
   1997     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
   1998     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
   1999     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2000     return_trace (chain_context_apply_lookup (c,
   2001 					      backtrack.len, backtrack.arrayZ,
   2002 					      input.lenP1, input.arrayZ,
   2003 					      lookahead.len, lookahead.arrayZ, lookup.len,
   2004 					      lookup.arrayZ, lookup_context));
   2005   }
   2006 
   2007   bool sanitize (hb_sanitize_context_t *c) const
   2008   {
   2009     TRACE_SANITIZE (this);
   2010     if (!backtrack.sanitize (c)) return_trace (false);
   2011     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
   2012     if (!input.sanitize (c)) return_trace (false);
   2013     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
   2014     if (!lookahead.sanitize (c)) return_trace (false);
   2015     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2016     return_trace (lookup.sanitize (c));
   2017   }
   2018 
   2019   protected:
   2020   ArrayOf<HBUINT16>
   2021 		backtrack;		/* Array of backtracking values
   2022 					 * (to be matched before the input
   2023 					 * sequence) */
   2024   HeadlessArrayOf<HBUINT16>
   2025 		inputX;			/* Array of input values (start with
   2026 					 * second glyph) */
   2027   ArrayOf<HBUINT16>
   2028 		lookaheadX;		/* Array of lookahead values's (to be
   2029 					 * matched after the input sequence) */
   2030   ArrayOf<LookupRecord>
   2031 		lookupX;		/* Array of LookupRecords--in
   2032 					 * design order) */
   2033   public:
   2034   DEFINE_SIZE_MIN (8);
   2035 };
   2036 
   2037 struct ChainRuleSet
   2038 {
   2039   bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
   2040   {
   2041     unsigned int num_rules = rule.len;
   2042     for (unsigned int i = 0; i < num_rules; i++)
   2043       if ((this+rule[i]).intersects (glyphs, lookup_context))
   2044 	return true;
   2045     return false;
   2046   }
   2047   void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
   2048   {
   2049     TRACE_CLOSURE (this);
   2050     unsigned int num_rules = rule.len;
   2051     for (unsigned int i = 0; i < num_rules; i++)
   2052       (this+rule[i]).closure (c, lookup_context);
   2053   }
   2054 
   2055   void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
   2056   {
   2057     TRACE_COLLECT_GLYPHS (this);
   2058     unsigned int num_rules = rule.len;
   2059     for (unsigned int i = 0; i < num_rules; i++)
   2060       (this+rule[i]).collect_glyphs (c, lookup_context);
   2061   }
   2062 
   2063   bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   2064   {
   2065     TRACE_WOULD_APPLY (this);
   2066     unsigned int num_rules = rule.len;
   2067     for (unsigned int i = 0; i < num_rules; i++)
   2068       if ((this+rule[i]).would_apply (c, lookup_context))
   2069 	return_trace (true);
   2070 
   2071     return_trace (false);
   2072   }
   2073 
   2074   bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
   2075   {
   2076     TRACE_APPLY (this);
   2077     unsigned int num_rules = rule.len;
   2078     for (unsigned int i = 0; i < num_rules; i++)
   2079       if ((this+rule[i]).apply (c, lookup_context))
   2080 	return_trace (true);
   2081 
   2082     return_trace (false);
   2083   }
   2084 
   2085   bool sanitize (hb_sanitize_context_t *c) const
   2086   {
   2087     TRACE_SANITIZE (this);
   2088     return_trace (rule.sanitize (c, this));
   2089   }
   2090 
   2091   protected:
   2092   OffsetArrayOf<ChainRule>
   2093 		rule;			/* Array of ChainRule tables
   2094 					 * ordered by preference */
   2095   public:
   2096   DEFINE_SIZE_ARRAY (2, rule);
   2097 };
   2098 
   2099 struct ChainContextFormat1
   2100 {
   2101   bool intersects (const hb_set_t *glyphs) const
   2102   {
   2103     struct ChainContextClosureLookupContext lookup_context = {
   2104       {intersects_glyph},
   2105       {nullptr, nullptr, nullptr}
   2106     };
   2107 
   2108     unsigned int count = ruleSet.len;
   2109     for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
   2110     {
   2111       if (unlikely (iter.get_coverage () >= count))
   2112 	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
   2113       if (glyphs->has (iter.get_glyph ()) &&
   2114 	  (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
   2115 	return true;
   2116     }
   2117     return false;
   2118   }
   2119 
   2120   void closure (hb_closure_context_t *c) const
   2121   {
   2122     TRACE_CLOSURE (this);
   2123 
   2124     struct ChainContextClosureLookupContext lookup_context = {
   2125       {intersects_glyph},
   2126       {nullptr, nullptr, nullptr}
   2127     };
   2128 
   2129     unsigned int count = ruleSet.len;
   2130     for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
   2131     {
   2132       if (unlikely (iter.get_coverage () >= count))
   2133 	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
   2134       if (c->glyphs->has (iter.get_glyph ()))
   2135 	(this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
   2136     }
   2137   }
   2138 
   2139   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   2140   {
   2141     TRACE_COLLECT_GLYPHS (this);
   2142     (this+coverage).add_coverage (c->input);
   2143 
   2144     struct ChainContextCollectGlyphsLookupContext lookup_context = {
   2145       {collect_glyph},
   2146       {nullptr, nullptr, nullptr}
   2147     };
   2148 
   2149     unsigned int count = ruleSet.len;
   2150     for (unsigned int i = 0; i < count; i++)
   2151       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
   2152   }
   2153 
   2154   bool would_apply (hb_would_apply_context_t *c) const
   2155   {
   2156     TRACE_WOULD_APPLY (this);
   2157 
   2158     const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
   2159     struct ChainContextApplyLookupContext lookup_context = {
   2160       {match_glyph},
   2161       {nullptr, nullptr, nullptr}
   2162     };
   2163     return_trace (rule_set.would_apply (c, lookup_context));
   2164   }
   2165 
   2166   const Coverage &get_coverage () const { return this+coverage; }
   2167 
   2168   bool apply (hb_ot_apply_context_t *c) const
   2169   {
   2170     TRACE_APPLY (this);
   2171     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
   2172     if (likely (index == NOT_COVERED)) return_trace (false);
   2173 
   2174     const ChainRuleSet &rule_set = this+ruleSet[index];
   2175     struct ChainContextApplyLookupContext lookup_context = {
   2176       {match_glyph},
   2177       {nullptr, nullptr, nullptr}
   2178     };
   2179     return_trace (rule_set.apply (c, lookup_context));
   2180   }
   2181 
   2182   bool subset (hb_subset_context_t *c) const
   2183   {
   2184     TRACE_SUBSET (this);
   2185     // TODO(subset)
   2186     return_trace (false);
   2187   }
   2188 
   2189   bool sanitize (hb_sanitize_context_t *c) const
   2190   {
   2191     TRACE_SANITIZE (this);
   2192     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
   2193   }
   2194 
   2195   protected:
   2196   HBUINT16	format;			/* Format identifier--format = 1 */
   2197   OffsetTo<Coverage>
   2198 		coverage;		/* Offset to Coverage table--from
   2199 					 * beginning of table */
   2200   OffsetArrayOf<ChainRuleSet>
   2201 		ruleSet;		/* Array of ChainRuleSet tables
   2202 					 * ordered by Coverage Index */
   2203   public:
   2204   DEFINE_SIZE_ARRAY (6, ruleSet);
   2205 };
   2206 
   2207 struct ChainContextFormat2
   2208 {
   2209   bool intersects (const hb_set_t *glyphs) const
   2210   {
   2211     if (!(this+coverage).intersects (glyphs))
   2212       return false;
   2213 
   2214     const ClassDef &backtrack_class_def = this+backtrackClassDef;
   2215     const ClassDef &input_class_def = this+inputClassDef;
   2216     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
   2217 
   2218     struct ChainContextClosureLookupContext lookup_context = {
   2219       {intersects_class},
   2220       {&backtrack_class_def,
   2221        &input_class_def,
   2222        &lookahead_class_def}
   2223     };
   2224 
   2225     unsigned int count = ruleSet.len;
   2226     for (unsigned int i = 0; i < count; i++)
   2227       if (input_class_def.intersects_class (glyphs, i) &&
   2228 	  (this+ruleSet[i]).intersects (glyphs, lookup_context))
   2229 	return true;
   2230 
   2231     return false;
   2232   }
   2233   void closure (hb_closure_context_t *c) const
   2234   {
   2235     TRACE_CLOSURE (this);
   2236     if (!(this+coverage).intersects (c->glyphs))
   2237       return;
   2238 
   2239     const ClassDef &backtrack_class_def = this+backtrackClassDef;
   2240     const ClassDef &input_class_def = this+inputClassDef;
   2241     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
   2242 
   2243     struct ChainContextClosureLookupContext lookup_context = {
   2244       {intersects_class},
   2245       {&backtrack_class_def,
   2246        &input_class_def,
   2247        &lookahead_class_def}
   2248     };
   2249 
   2250     unsigned int count = ruleSet.len;
   2251     for (unsigned int i = 0; i < count; i++)
   2252       if (input_class_def.intersects_class (c->glyphs, i)) {
   2253 	const ChainRuleSet &rule_set = this+ruleSet[i];
   2254 	rule_set.closure (c, lookup_context);
   2255       }
   2256   }
   2257 
   2258   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   2259   {
   2260     TRACE_COLLECT_GLYPHS (this);
   2261     (this+coverage).add_coverage (c->input);
   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     struct ChainContextCollectGlyphsLookupContext lookup_context = {
   2268       {collect_class},
   2269       {&backtrack_class_def,
   2270        &input_class_def,
   2271        &lookahead_class_def}
   2272     };
   2273 
   2274     unsigned int count = ruleSet.len;
   2275     for (unsigned int i = 0; i < count; i++)
   2276       (this+ruleSet[i]).collect_glyphs (c, lookup_context);
   2277   }
   2278 
   2279   bool would_apply (hb_would_apply_context_t *c) const
   2280   {
   2281     TRACE_WOULD_APPLY (this);
   2282 
   2283     const ClassDef &backtrack_class_def = this+backtrackClassDef;
   2284     const ClassDef &input_class_def = this+inputClassDef;
   2285     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
   2286 
   2287     unsigned int index = input_class_def.get_class (c->glyphs[0]);
   2288     const ChainRuleSet &rule_set = this+ruleSet[index];
   2289     struct ChainContextApplyLookupContext lookup_context = {
   2290       {match_class},
   2291       {&backtrack_class_def,
   2292        &input_class_def,
   2293        &lookahead_class_def}
   2294     };
   2295     return_trace (rule_set.would_apply (c, lookup_context));
   2296   }
   2297 
   2298   const Coverage &get_coverage () const { return this+coverage; }
   2299 
   2300   bool apply (hb_ot_apply_context_t *c) const
   2301   {
   2302     TRACE_APPLY (this);
   2303     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
   2304     if (likely (index == NOT_COVERED)) return_trace (false);
   2305 
   2306     const ClassDef &backtrack_class_def = this+backtrackClassDef;
   2307     const ClassDef &input_class_def = this+inputClassDef;
   2308     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
   2309 
   2310     index = input_class_def.get_class (c->buffer->cur().codepoint);
   2311     const ChainRuleSet &rule_set = this+ruleSet[index];
   2312     struct ChainContextApplyLookupContext lookup_context = {
   2313       {match_class},
   2314       {&backtrack_class_def,
   2315        &input_class_def,
   2316        &lookahead_class_def}
   2317     };
   2318     return_trace (rule_set.apply (c, lookup_context));
   2319   }
   2320 
   2321   bool subset (hb_subset_context_t *c) const
   2322   {
   2323     TRACE_SUBSET (this);
   2324     // TODO(subset)
   2325     return_trace (false);
   2326   }
   2327 
   2328   bool sanitize (hb_sanitize_context_t *c) const
   2329   {
   2330     TRACE_SANITIZE (this);
   2331     return_trace (coverage.sanitize (c, this) &&
   2332 		  backtrackClassDef.sanitize (c, this) &&
   2333 		  inputClassDef.sanitize (c, this) &&
   2334 		  lookaheadClassDef.sanitize (c, this) &&
   2335 		  ruleSet.sanitize (c, this));
   2336   }
   2337 
   2338   protected:
   2339   HBUINT16	format;			/* Format identifier--format = 2 */
   2340   OffsetTo<Coverage>
   2341 		coverage;		/* Offset to Coverage table--from
   2342 					 * beginning of table */
   2343   OffsetTo<ClassDef>
   2344 		backtrackClassDef;	/* Offset to glyph ClassDef table
   2345 					 * containing backtrack sequence
   2346 					 * data--from beginning of table */
   2347   OffsetTo<ClassDef>
   2348 		inputClassDef;		/* Offset to glyph ClassDef
   2349 					 * table containing input sequence
   2350 					 * data--from beginning of table */
   2351   OffsetTo<ClassDef>
   2352 		lookaheadClassDef;	/* Offset to glyph ClassDef table
   2353 					 * containing lookahead sequence
   2354 					 * data--from beginning of table */
   2355   OffsetArrayOf<ChainRuleSet>
   2356 		ruleSet;		/* Array of ChainRuleSet tables
   2357 					 * ordered by class */
   2358   public:
   2359   DEFINE_SIZE_ARRAY (12, ruleSet);
   2360 };
   2361 
   2362 struct ChainContextFormat3
   2363 {
   2364   bool intersects (const hb_set_t *glyphs) const
   2365   {
   2366     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2367 
   2368     if (!(this+input[0]).intersects (glyphs))
   2369       return false;
   2370 
   2371     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
   2372     struct ChainContextClosureLookupContext lookup_context = {
   2373       {intersects_coverage},
   2374       {this, this, this}
   2375     };
   2376     return chain_context_intersects (glyphs,
   2377 				     backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
   2378 				     input.len, (const HBUINT16 *) input.arrayZ + 1,
   2379 				     lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
   2380 				     lookup_context);
   2381   }
   2382 
   2383   void closure (hb_closure_context_t *c) const
   2384   {
   2385     TRACE_CLOSURE (this);
   2386     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2387 
   2388     if (!(this+input[0]).intersects (c->glyphs))
   2389       return;
   2390 
   2391     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
   2392     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2393     struct ChainContextClosureLookupContext lookup_context = {
   2394       {intersects_coverage},
   2395       {this, this, this}
   2396     };
   2397     chain_context_closure_lookup (c,
   2398 				  backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
   2399 				  input.len, (const HBUINT16 *) input.arrayZ + 1,
   2400 				  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
   2401 				  lookup.len, lookup.arrayZ,
   2402 				  lookup_context);
   2403   }
   2404 
   2405   void collect_glyphs (hb_collect_glyphs_context_t *c) const
   2406   {
   2407     TRACE_COLLECT_GLYPHS (this);
   2408     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2409 
   2410     (this+input[0]).add_coverage (c->input);
   2411 
   2412     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
   2413     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2414     struct ChainContextCollectGlyphsLookupContext lookup_context = {
   2415       {collect_coverage},
   2416       {this, this, this}
   2417     };
   2418     chain_context_collect_glyphs_lookup (c,
   2419 					 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
   2420 					 input.len, (const HBUINT16 *) input.arrayZ + 1,
   2421 					 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
   2422 					 lookup.len, lookup.arrayZ,
   2423 					 lookup_context);
   2424   }
   2425 
   2426   bool would_apply (hb_would_apply_context_t *c) const
   2427   {
   2428     TRACE_WOULD_APPLY (this);
   2429 
   2430     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2431     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
   2432     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2433     struct ChainContextApplyLookupContext lookup_context = {
   2434       {match_coverage},
   2435       {this, this, this}
   2436     };
   2437     return_trace (chain_context_would_apply_lookup (c,
   2438 						    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
   2439 						    input.len, (const HBUINT16 *) input.arrayZ + 1,
   2440 						    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
   2441 						    lookup.len, lookup.arrayZ, lookup_context));
   2442   }
   2443 
   2444   const Coverage &get_coverage () const
   2445   {
   2446     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2447     return this+input[0];
   2448   }
   2449 
   2450   bool apply (hb_ot_apply_context_t *c) const
   2451   {
   2452     TRACE_APPLY (this);
   2453     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2454 
   2455     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
   2456     if (likely (index == NOT_COVERED)) return_trace (false);
   2457 
   2458     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
   2459     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2460     struct ChainContextApplyLookupContext lookup_context = {
   2461       {match_coverage},
   2462       {this, this, this}
   2463     };
   2464     return_trace (chain_context_apply_lookup (c,
   2465 					      backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
   2466 					      input.len, (const HBUINT16 *) input.arrayZ + 1,
   2467 					      lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
   2468 					      lookup.len, lookup.arrayZ, lookup_context));
   2469   }
   2470 
   2471   bool subset (hb_subset_context_t *c) const
   2472   {
   2473     TRACE_SUBSET (this);
   2474     // TODO(subset)
   2475     return_trace (false);
   2476   }
   2477 
   2478   bool sanitize (hb_sanitize_context_t *c) const
   2479   {
   2480     TRACE_SANITIZE (this);
   2481     if (!backtrack.sanitize (c, this)) return_trace (false);
   2482     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
   2483     if (!input.sanitize (c, this)) return_trace (false);
   2484     if (!input.len) return_trace (false); /* To be consistent with Context. */
   2485     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
   2486     if (!lookahead.sanitize (c, this)) return_trace (false);
   2487     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
   2488     return_trace (lookup.sanitize (c));
   2489   }
   2490 
   2491   protected:
   2492   HBUINT16	format;			/* Format identifier--format = 3 */
   2493   OffsetArrayOf<Coverage>
   2494 		backtrack;		/* Array of coverage tables
   2495 					 * in backtracking sequence, in  glyph
   2496 					 * sequence order */
   2497   OffsetArrayOf<Coverage>
   2498 		inputX		;	/* Array of coverage
   2499 					 * tables in input sequence, in glyph
   2500 					 * sequence order */
   2501   OffsetArrayOf<Coverage>
   2502 		lookaheadX;		/* Array of coverage tables
   2503 					 * in lookahead sequence, in glyph
   2504 					 * sequence order */
   2505   ArrayOf<LookupRecord>
   2506 		lookupX;		/* Array of LookupRecords--in
   2507 					 * design order) */
   2508   public:
   2509   DEFINE_SIZE_MIN (10);
   2510 };
   2511 
   2512 struct ChainContext
   2513 {
   2514   template <typename context_t>
   2515   typename context_t::return_t dispatch (context_t *c) const
   2516   {
   2517     TRACE_DISPATCH (this, u.format);
   2518     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
   2519     switch (u.format) {
   2520     case 1: return_trace (c->dispatch (u.format1));
   2521     case 2: return_trace (c->dispatch (u.format2));
   2522     case 3: return_trace (c->dispatch (u.format3));
   2523     default:return_trace (c->default_return_value ());
   2524     }
   2525   }
   2526 
   2527   protected:
   2528   union {
   2529   HBUINT16		format;	/* Format identifier */
   2530   ChainContextFormat1	format1;
   2531   ChainContextFormat2	format2;
   2532   ChainContextFormat3	format3;
   2533   } u;
   2534 };
   2535 
   2536 
   2537 template <typename T>
   2538 struct ExtensionFormat1
   2539 {
   2540   unsigned int get_type () const { return extensionLookupType; }
   2541 
   2542   template <typename X>
   2543   const X& get_subtable () const
   2544   {
   2545     unsigned int offset = extensionOffset;
   2546     if (unlikely (!offset)) return Null(typename T::SubTable);
   2547     return StructAtOffset<typename T::SubTable> (this, offset);
   2548   }
   2549 
   2550   template <typename context_t>
   2551   typename context_t::return_t dispatch (context_t *c) const
   2552   {
   2553     TRACE_DISPATCH (this, format);
   2554     if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
   2555     return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
   2556   }
   2557 
   2558   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
   2559   bool sanitize (hb_sanitize_context_t *c) const
   2560   {
   2561     TRACE_SANITIZE (this);
   2562     return_trace (c->check_struct (this) &&
   2563 		  extensionOffset != 0 &&
   2564 		  extensionLookupType != T::SubTable::Extension);
   2565   }
   2566 
   2567   protected:
   2568   HBUINT16	format;			/* Format identifier. Set to 1. */
   2569   HBUINT16	extensionLookupType;	/* Lookup type of subtable referenced
   2570 					 * by ExtensionOffset (i.e. the
   2571 					 * extension subtable). */
   2572   HBUINT32	extensionOffset;	/* Offset to the extension subtable,
   2573 					 * of lookup type subtable. */
   2574   public:
   2575   DEFINE_SIZE_STATIC (8);
   2576 };
   2577 
   2578 template <typename T>
   2579 struct Extension
   2580 {
   2581   unsigned int get_type () const
   2582   {
   2583     switch (u.format) {
   2584     case 1: return u.format1.get_type ();
   2585     default:return 0;
   2586     }
   2587   }
   2588   template <typename X>
   2589   const X& get_subtable () const
   2590   {
   2591     switch (u.format) {
   2592     case 1: return u.format1.template get_subtable<typename T::SubTable> ();
   2593     default:return Null(typename T::SubTable);
   2594     }
   2595   }
   2596 
   2597   template <typename context_t>
   2598   typename context_t::return_t dispatch (context_t *c) const
   2599   {
   2600     TRACE_DISPATCH (this, u.format);
   2601     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
   2602     switch (u.format) {
   2603     case 1: return_trace (u.format1.dispatch (c));
   2604     default:return_trace (c->default_return_value ());
   2605     }
   2606   }
   2607 
   2608   protected:
   2609   union {
   2610   HBUINT16		format;		/* Format identifier */
   2611   ExtensionFormat1<T>	format1;
   2612   } u;
   2613 };
   2614 
   2615 
   2616 /*
   2617  * GSUB/GPOS Common
   2618  */
   2619 
   2620 struct hb_ot_layout_lookup_accelerator_t
   2621 {
   2622   template <typename TLookup>
   2623   void init (const TLookup &lookup)
   2624   {
   2625     digest.init ();
   2626     lookup.add_coverage (&digest);
   2627 
   2628     subtables.init ();
   2629     OT::hb_get_subtables_context_t c_get_subtables (subtables);
   2630     lookup.dispatch (&c_get_subtables);
   2631   }
   2632   void fini () { subtables.fini (); }
   2633 
   2634   bool may_have (hb_codepoint_t g) const
   2635   { return digest.may_have (g); }
   2636 
   2637   bool apply (hb_ot_apply_context_t *c) const
   2638   {
   2639     for (unsigned int i = 0; i < subtables.len; i++)
   2640       if (subtables[i].apply (c))
   2641 	return true;
   2642     return false;
   2643   }
   2644 
   2645   private:
   2646   hb_set_digest_t digest;
   2647   hb_get_subtables_context_t::array_t subtables;
   2648 };
   2649 
   2650 struct GSUBGPOS
   2651 {
   2652   bool has_data () const { return version.to_int (); }
   2653   unsigned int get_script_count () const
   2654   { return (this+scriptList).len; }
   2655   const Tag& get_script_tag (unsigned int i) const
   2656   { return (this+scriptList).get_tag (i); }
   2657   unsigned int get_script_tags (unsigned int start_offset,
   2658 				unsigned int *script_count /* IN/OUT */,
   2659 				hb_tag_t     *script_tags /* OUT */) const
   2660   { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
   2661   const Script& get_script (unsigned int i) const
   2662   { return (this+scriptList)[i]; }
   2663   bool find_script_index (hb_tag_t tag, unsigned int *index) const
   2664   { return (this+scriptList).find_index (tag, index); }
   2665 
   2666   unsigned int get_feature_count () const
   2667   { return (this+featureList).len; }
   2668   hb_tag_t get_feature_tag (unsigned int i) const
   2669   { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
   2670   unsigned int get_feature_tags (unsigned int start_offset,
   2671 				 unsigned int *feature_count /* IN/OUT */,
   2672 				 hb_tag_t     *feature_tags /* OUT */) const
   2673   { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
   2674   const Feature& get_feature (unsigned int i) const
   2675   { return (this+featureList)[i]; }
   2676   bool find_feature_index (hb_tag_t tag, unsigned int *index) const
   2677   { return (this+featureList).find_index (tag, index); }
   2678 
   2679   unsigned int get_lookup_count () const
   2680   { return (this+lookupList).len; }
   2681   const Lookup& get_lookup (unsigned int i) const
   2682   { return (this+lookupList)[i]; }
   2683 
   2684   bool find_variations_index (const int *coords, unsigned int num_coords,
   2685 			      unsigned int *index) const
   2686   { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
   2687 	   .find_index (coords, num_coords, index); }
   2688   const Feature& get_feature_variation (unsigned int feature_index,
   2689 					       unsigned int variations_index) const
   2690   {
   2691     if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
   2692 	version.to_int () >= 0x00010001u)
   2693     {
   2694       const Feature *feature = (this+featureVars).find_substitute (variations_index,
   2695 								   feature_index);
   2696       if (feature)
   2697 	return *feature;
   2698     }
   2699     return get_feature (feature_index);
   2700   }
   2701 
   2702   template <typename TLookup>
   2703   bool subset (hb_subset_context_t *c) const
   2704   {
   2705     TRACE_SUBSET (this);
   2706     struct GSUBGPOS *out = c->serializer->embed (*this);
   2707     if (unlikely (!out)) return_trace (false);
   2708 
   2709     out->scriptList.serialize_subset (c, this+scriptList, out);
   2710     out->featureList.serialize_subset (c, this+featureList, out);
   2711 
   2712     typedef OffsetListOf<TLookup> TLookupList;
   2713     /* TODO Use intersects() to count how many subtables survive? */
   2714     CastR<OffsetTo<TLookupList> > (out->lookupList)
   2715       .serialize_subset (c,
   2716 			 this+CastR<const OffsetTo<TLookupList> > (lookupList),
   2717 			 out);
   2718 
   2719     if (version.to_int () >= 0x00010001u)
   2720      out->featureVars.serialize_subset (c, this+featureVars, out);
   2721 
   2722     return_trace (true);
   2723   }
   2724 
   2725   unsigned int get_size () const
   2726   {
   2727     return min_size +
   2728 	   (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
   2729   }
   2730 
   2731   template <typename TLookup>
   2732   bool sanitize (hb_sanitize_context_t *c) const
   2733   {
   2734     TRACE_SANITIZE (this);
   2735     typedef OffsetListOf<TLookup> TLookupList;
   2736     return_trace (version.sanitize (c) &&
   2737 		  likely (version.major == 1) &&
   2738 		  scriptList.sanitize (c, this) &&
   2739 		  featureList.sanitize (c, this) &&
   2740 		  CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
   2741 		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
   2742   }
   2743 
   2744   template <typename T>
   2745   struct accelerator_t
   2746   {
   2747     void init (hb_face_t *face)
   2748     {
   2749       this->table = hb_sanitize_context_t().reference_table<T> (face);
   2750       if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
   2751       {
   2752 	hb_blob_destroy (this->table.get_blob ());
   2753 	this->table = hb_blob_get_empty ();
   2754       }
   2755 
   2756       this->lookup_count = table->get_lookup_count ();
   2757 
   2758       this->accels = (hb_ot_layout_lookup_accelerator_t *) calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
   2759       if (unlikely (!this->accels))
   2760 	this->lookup_count = 0;
   2761 
   2762       for (unsigned int i = 0; i < this->lookup_count; i++)
   2763 	this->accels[i].init (table->get_lookup (i));
   2764     }
   2765 
   2766     void fini ()
   2767     {
   2768       for (unsigned int i = 0; i < this->lookup_count; i++)
   2769 	this->accels[i].fini ();
   2770       free (this->accels);
   2771       this->table.destroy ();
   2772     }
   2773 
   2774     hb_blob_ptr_t<T> table;
   2775     unsigned int lookup_count;
   2776     hb_ot_layout_lookup_accelerator_t *accels;
   2777   };
   2778 
   2779   protected:
   2780   FixedVersion<>version;	/* Version of the GSUB/GPOS table--initially set
   2781 				 * to 0x00010000u */
   2782   OffsetTo<ScriptList>
   2783 		scriptList;  	/* ScriptList table */
   2784   OffsetTo<FeatureList>
   2785 		featureList; 	/* FeatureList table */
   2786   OffsetTo<LookupList>
   2787 		lookupList; 	/* LookupList table */
   2788   LOffsetTo<FeatureVariations>
   2789 		featureVars;	/* Offset to Feature Variations
   2790 				   table--from beginning of table
   2791 				 * (may be NULL).  Introduced
   2792 				 * in version 0x00010001. */
   2793   public:
   2794   DEFINE_SIZE_MIN (10);
   2795 };
   2796 
   2797 
   2798 } /* namespace OT */
   2799 
   2800 
   2801 #endif /* HB_OT_LAYOUT_GSUBGPOS_HH */
   2802