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