src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos-private.hh
changeset 50352 25db2c8f3cf8
parent 48274 51772bf1fb0c
child 50826 f5b95be8b6e2
equal deleted inserted replaced
50351:9289c4214a35 50352:25db2c8f3cf8
   216   set_t *set;
   216   set_t *set;
   217   unsigned int debug_depth;
   217   unsigned int debug_depth;
   218 };
   218 };
   219 
   219 
   220 
   220 
   221 struct hb_apply_context_t :
   221 struct hb_ot_apply_context_t :
   222        hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY>
   222        hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
   223 {
   223 {
   224   struct matcher_t
   224   struct matcher_t
   225   {
   225   {
   226     inline matcher_t (void) :
   226     inline matcher_t (void) :
   227              lookup_props (0),
   227              lookup_props (0),
   232              syllable arg1(0),
   232              syllable arg1(0),
   233 #undef arg1
   233 #undef arg1
   234              match_func (nullptr),
   234              match_func (nullptr),
   235              match_data (nullptr) {};
   235              match_data (nullptr) {};
   236 
   236 
   237     typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
   237     typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
   238 
   238 
   239     inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
   239     inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
   240     inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
   240     inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
   241     inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
   241     inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
   242     inline void set_mask (hb_mask_t mask_) { mask = mask_; }
   242     inline void set_mask (hb_mask_t mask_) { mask = mask_; }
   250       MATCH_YES,
   250       MATCH_YES,
   251       MATCH_MAYBE
   251       MATCH_MAYBE
   252     };
   252     };
   253 
   253 
   254     inline may_match_t may_match (const hb_glyph_info_t &info,
   254     inline may_match_t may_match (const hb_glyph_info_t &info,
   255                                   const USHORT          *glyph_data) const
   255                                   const HBUINT16          *glyph_data) const
   256     {
   256     {
   257       if (!(info.mask & mask) ||
   257       if (!(info.mask & mask) ||
   258           (syllable && syllable != info.syllable ()))
   258           (syllable && syllable != info.syllable ()))
   259         return MATCH_NO;
   259         return MATCH_NO;
   260 
   260 
   269       SKIP_YES,
   269       SKIP_YES,
   270       SKIP_MAYBE
   270       SKIP_MAYBE
   271     };
   271     };
   272 
   272 
   273     inline may_skip_t
   273     inline may_skip_t
   274     may_skip (const hb_apply_context_t *c,
   274     may_skip (const hb_ot_apply_context_t *c,
   275               const hb_glyph_info_t    &info) const
   275               const hb_glyph_info_t    &info) const
   276     {
   276     {
   277       if (!c->check_glyph_property (&info, lookup_props))
   277       if (!c->check_glyph_property (&info, lookup_props))
   278         return SKIP_YES;
   278         return SKIP_YES;
   279 
   279 
   295     const void *match_data;
   295     const void *match_data;
   296   };
   296   };
   297 
   297 
   298   struct skipping_iterator_t
   298   struct skipping_iterator_t
   299   {
   299   {
   300     inline void init (hb_apply_context_t *c_, bool context_match = false)
   300     inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
   301     {
   301     {
   302       c = c_;
   302       c = c_;
   303       match_glyph_data = nullptr;
   303       match_glyph_data = nullptr;
   304       matcher.set_match_func (nullptr, nullptr);
   304       matcher.set_match_func (nullptr, nullptr);
   305       matcher.set_lookup_props (c->lookup_props);
   305       matcher.set_lookup_props (c->lookup_props);
   313     {
   313     {
   314       matcher.set_lookup_props (lookup_props);
   314       matcher.set_lookup_props (lookup_props);
   315     }
   315     }
   316     inline void set_match_func (matcher_t::match_func_t match_func_,
   316     inline void set_match_func (matcher_t::match_func_t match_func_,
   317                                 const void *match_data_,
   317                                 const void *match_data_,
   318                                 const USHORT glyph_data[])
   318                                 const HBUINT16 glyph_data[])
   319     {
   319     {
   320       matcher.set_match_func (match_func_, match_data_);
   320       matcher.set_match_func (match_func_, match_data_);
   321       match_glyph_data = glyph_data;
   321       match_glyph_data = glyph_data;
   322     }
   322     }
   323 
   323 
   331     }
   331     }
   332 
   332 
   333     inline void reject (void) { num_items++; match_glyph_data--; }
   333     inline void reject (void) { num_items++; match_glyph_data--; }
   334 
   334 
   335     inline matcher_t::may_skip_t
   335     inline matcher_t::may_skip_t
   336     may_skip (const hb_apply_context_t *c,
   336     may_skip (const hb_glyph_info_t    &info) const
   337               const hb_glyph_info_t    &info) const
       
   338     {
   337     {
   339       return matcher.may_skip (c, info);
   338       return matcher.may_skip (c, info);
   340     }
   339     }
   341 
   340 
   342     inline bool next (void)
   341     inline bool next (void)
   394       return false;
   393       return false;
   395     }
   394     }
   396 
   395 
   397     unsigned int idx;
   396     unsigned int idx;
   398     protected:
   397     protected:
   399     hb_apply_context_t *c;
   398     hb_ot_apply_context_t *c;
   400     matcher_t matcher;
   399     matcher_t matcher;
   401     const USHORT *match_glyph_data;
   400     const HBUINT16 *match_glyph_data;
   402 
   401 
   403     unsigned int num_items;
   402     unsigned int num_items;
   404     unsigned int end;
   403     unsigned int end;
   405   };
   404   };
   406 
   405 
   407 
   406 
   408   inline const char *get_name (void) { return "APPLY"; }
   407   inline const char *get_name (void) { return "APPLY"; }
   409   typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
   408   typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
   410   template <typename T>
   409   template <typename T>
   411   inline return_t dispatch (const T &obj) { return obj.apply (this); }
   410   inline return_t dispatch (const T &obj) { return obj.apply (this); }
   412   static return_t default_return_value (void) { return false; }
   411   static return_t default_return_value (void) { return false; }
   413   bool stop_sublookup_iteration (return_t r) const { return r; }
   412   bool stop_sublookup_iteration (return_t r) const { return r; }
   414   return_t recurse (unsigned int lookup_index)
   413   return_t recurse (unsigned int sub_lookup_index)
   415   {
   414   {
   416     if (unlikely (nesting_level_left == 0 || !recurse_func))
   415     if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
   417       return default_return_value ();
   416       return default_return_value ();
   418 
   417 
   419     nesting_level_left--;
   418     nesting_level_left--;
   420     bool ret = recurse_func (this, lookup_index);
   419     bool ret = recurse_func (this, sub_lookup_index);
   421     nesting_level_left++;
   420     nesting_level_left++;
   422     return ret;
   421     return ret;
   423   }
   422   }
   424 
   423 
   425   skipping_iterator_t iter_input, iter_context;
   424   skipping_iterator_t iter_input, iter_context;
   442   bool auto_zwnj;
   441   bool auto_zwnj;
   443   bool auto_zwj;
   442   bool auto_zwj;
   444   bool has_glyph_classes;
   443   bool has_glyph_classes;
   445 
   444 
   446 
   445 
   447   hb_apply_context_t (unsigned int table_index_,
   446   hb_ot_apply_context_t (unsigned int table_index_,
   448                       hb_font_t *font_,
   447                       hb_font_t *font_,
   449                       hb_buffer_t *buffer_) :
   448                       hb_buffer_t *buffer_) :
   450                         iter_input (), iter_context (),
   449                         iter_input (), iter_context (),
   451                         font (font_), face (font->face), buffer (buffer_),
   450                         font (font_), face (font->face), buffer (buffer_),
   452                         recurse_func (nullptr),
   451                         recurse_func (nullptr),
   566   }
   565   }
   567 };
   566 };
   568 
   567 
   569 
   568 
   570 
   569 
   571 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
   570 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
   572 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
   571 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
   573 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
   572 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
   574 
   573 
   575 struct ContextClosureFuncs
   574 struct ContextClosureFuncs
   576 {
   575 {
   577   intersects_func_t intersects;
   576   intersects_func_t intersects;
   578 };
   577 };
   584 {
   583 {
   585   match_func_t match;
   584   match_func_t match;
   586 };
   585 };
   587 
   586 
   588 
   587 
   589 static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
   588 static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
   590 {
   589 {
   591   return glyphs->has (value);
   590   return glyphs->has (value);
   592 }
   591 }
   593 static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
   592 static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
   594 {
   593 {
   595   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   594   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   596   return class_def.intersects_class (glyphs, value);
   595   return class_def.intersects_class (glyphs, value);
   597 }
   596 }
   598 static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
   597 static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
   599 {
   598 {
   600   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   599   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   601   return (data+coverage).intersects (glyphs);
   600   return (data+coverage).intersects (glyphs);
   602 }
   601 }
   603 
   602 
   604 static inline bool intersects_array (hb_closure_context_t *c,
   603 static inline bool intersects_array (hb_closure_context_t *c,
   605                                      unsigned int count,
   604                                      unsigned int count,
   606                                      const USHORT values[],
   605                                      const HBUINT16 values[],
   607                                      intersects_func_t intersects_func,
   606                                      intersects_func_t intersects_func,
   608                                      const void *intersects_data)
   607                                      const void *intersects_data)
   609 {
   608 {
   610   for (unsigned int i = 0; i < count; i++)
   609   for (unsigned int i = 0; i < count; i++)
   611     if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
   610     if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
   612       return false;
   611       return false;
   613   return true;
   612   return true;
   614 }
   613 }
   615 
   614 
   616 
   615 
   617 static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
   616 static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
   618 {
   617 {
   619   glyphs->add (value);
   618   glyphs->add (value);
   620 }
   619 }
   621 static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
   620 static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
   622 {
   621 {
   623   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   622   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   624   class_def.add_class (glyphs, value);
   623   class_def.add_class (glyphs, value);
   625 }
   624 }
   626 static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
   625 static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
   627 {
   626 {
   628   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   627   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   629   (data+coverage).add_coverage (glyphs);
   628   (data+coverage).add_coverage (glyphs);
   630 }
   629 }
   631 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
   630 static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
   632                                   hb_set_t *glyphs,
   631                                   hb_set_t *glyphs,
   633                                   unsigned int count,
   632                                   unsigned int count,
   634                                   const USHORT values[],
   633                                   const HBUINT16 values[],
   635                                   collect_glyphs_func_t collect_func,
   634                                   collect_glyphs_func_t collect_func,
   636                                   const void *collect_data)
   635                                   const void *collect_data)
   637 {
   636 {
   638   for (unsigned int i = 0; i < count; i++)
   637   for (unsigned int i = 0; i < count; i++)
   639     collect_func (glyphs, values[i], collect_data);
   638     collect_func (glyphs, values[i], collect_data);
   640 }
   639 }
   641 
   640 
   642 
   641 
   643 static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
   642 static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
   644 {
   643 {
   645   return glyph_id == value;
   644   return glyph_id == value;
   646 }
   645 }
   647 static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
   646 static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
   648 {
   647 {
   649   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   648   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   650   return class_def.get_class (glyph_id) == value;
   649   return class_def.get_class (glyph_id) == value;
   651 }
   650 }
   652 static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
   651 static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
   653 {
   652 {
   654   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   653   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   655   return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
   654   return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
   656 }
   655 }
   657 
   656 
   658 static inline bool would_match_input (hb_would_apply_context_t *c,
   657 static inline bool would_match_input (hb_would_apply_context_t *c,
   659                                       unsigned int count, /* Including the first glyph (not matched) */
   658                                       unsigned int count, /* Including the first glyph (not matched) */
   660                                       const USHORT input[], /* Array of input values--start with second glyph */
   659                                       const HBUINT16 input[], /* Array of input values--start with second glyph */
   661                                       match_func_t match_func,
   660                                       match_func_t match_func,
   662                                       const void *match_data)
   661                                       const void *match_data)
   663 {
   662 {
   664   if (count != c->len)
   663   if (count != c->len)
   665     return false;
   664     return false;
   668     if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
   667     if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
   669       return false;
   668       return false;
   670 
   669 
   671   return true;
   670   return true;
   672 }
   671 }
   673 static inline bool match_input (hb_apply_context_t *c,
   672 static inline bool match_input (hb_ot_apply_context_t *c,
   674                                 unsigned int count, /* Including the first glyph (not matched) */
   673                                 unsigned int count, /* Including the first glyph (not matched) */
   675                                 const USHORT input[], /* Array of input values--start with second glyph */
   674                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
   676                                 match_func_t match_func,
   675                                 match_func_t match_func,
   677                                 const void *match_data,
   676                                 const void *match_data,
   678                                 unsigned int *end_offset,
   677                                 unsigned int *end_offset,
   679                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
   678                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
   680                                 bool *p_is_mark_ligature = nullptr,
   679                                 bool *p_is_mark_ligature = nullptr,
   684 
   683 
   685   if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
   684   if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
   686 
   685 
   687   hb_buffer_t *buffer = c->buffer;
   686   hb_buffer_t *buffer = c->buffer;
   688 
   687 
   689   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
   688   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
   690   skippy_iter.reset (buffer->idx, count - 1);
   689   skippy_iter.reset (buffer->idx, count - 1);
   691   skippy_iter.set_match_func (match_func, match_data, input);
   690   skippy_iter.set_match_func (match_func, match_data, input);
   692 
   691 
   693   /*
   692   /*
   694    * This is perhaps the trickiest part of OpenType...  Remarks:
   693    * This is perhaps the trickiest part of OpenType...  Remarks:
   709    *     break Indic stuff when a matra wants to ligate with a conjunct,
   708    *     break Indic stuff when a matra wants to ligate with a conjunct,
   710    *
   709    *
   711    *   o If two marks want to ligate and they belong to different components of the
   710    *   o If two marks want to ligate and they belong to different components of the
   712    *     same ligature glyph, and said ligature glyph is to be ignored according to
   711    *     same ligature glyph, and said ligature glyph is to be ignored according to
   713    *     mark-filtering rules, then allow.
   712    *     mark-filtering rules, then allow.
   714    *     https://github.com/behdad/harfbuzz/issues/545
   713    *     https://github.com/harfbuzz/harfbuzz/issues/545
   715    */
   714    */
   716 
   715 
   717   bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
   716   bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
   718 
   717 
   719   unsigned int total_component_count = 0;
   718   unsigned int total_component_count = 0;
   761               break;
   760               break;
   762             }
   761             }
   763             j--;
   762             j--;
   764           }
   763           }
   765 
   764 
   766           if (found && skippy_iter.may_skip (c, out[j]) == hb_apply_context_t::matcher_t::SKIP_YES)
   765           if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
   767             ligbase = LIGBASE_MAY_SKIP;
   766             ligbase = LIGBASE_MAY_SKIP;
   768           else
   767           else
   769             ligbase = LIGBASE_MAY_NOT_SKIP;
   768             ligbase = LIGBASE_MAY_NOT_SKIP;
   770         }
   769         }
   771 
   770 
   794   if (p_total_component_count)
   793   if (p_total_component_count)
   795     *p_total_component_count = total_component_count;
   794     *p_total_component_count = total_component_count;
   796 
   795 
   797   return_trace (true);
   796   return_trace (true);
   798 }
   797 }
   799 static inline bool ligate_input (hb_apply_context_t *c,
   798 static inline bool ligate_input (hb_ot_apply_context_t *c,
   800                                  unsigned int count, /* Including the first glyph */
   799                                  unsigned int count, /* Including the first glyph */
   801                                  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
   800                                  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
   802                                  unsigned int match_length,
   801                                  unsigned int match_length,
   803                                  hb_codepoint_t lig_glyph,
   802                                  hb_codepoint_t lig_glyph,
   804                                  bool is_mark_ligature,
   803                                  bool is_mark_ligature,
   892     }
   891     }
   893   }
   892   }
   894   return_trace (true);
   893   return_trace (true);
   895 }
   894 }
   896 
   895 
   897 static inline bool match_backtrack (hb_apply_context_t *c,
   896 static inline bool match_backtrack (hb_ot_apply_context_t *c,
   898                                     unsigned int count,
   897                                     unsigned int count,
   899                                     const USHORT backtrack[],
   898                                     const HBUINT16 backtrack[],
   900                                     match_func_t match_func,
   899                                     match_func_t match_func,
   901                                     const void *match_data,
   900                                     const void *match_data,
   902                                     unsigned int *match_start)
   901                                     unsigned int *match_start)
   903 {
   902 {
   904   TRACE_APPLY (nullptr);
   903   TRACE_APPLY (nullptr);
   905 
   904 
   906   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   905   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   907   skippy_iter.reset (c->buffer->backtrack_len (), count);
   906   skippy_iter.reset (c->buffer->backtrack_len (), count);
   908   skippy_iter.set_match_func (match_func, match_data, backtrack);
   907   skippy_iter.set_match_func (match_func, match_data, backtrack);
   909 
   908 
   910   for (unsigned int i = 0; i < count; i++)
   909   for (unsigned int i = 0; i < count; i++)
   911     if (!skippy_iter.prev ())
   910     if (!skippy_iter.prev ())
   914   *match_start = skippy_iter.idx;
   913   *match_start = skippy_iter.idx;
   915 
   914 
   916   return_trace (true);
   915   return_trace (true);
   917 }
   916 }
   918 
   917 
   919 static inline bool match_lookahead (hb_apply_context_t *c,
   918 static inline bool match_lookahead (hb_ot_apply_context_t *c,
   920                                     unsigned int count,
   919                                     unsigned int count,
   921                                     const USHORT lookahead[],
   920                                     const HBUINT16 lookahead[],
   922                                     match_func_t match_func,
   921                                     match_func_t match_func,
   923                                     const void *match_data,
   922                                     const void *match_data,
   924                                     unsigned int offset,
   923                                     unsigned int offset,
   925                                     unsigned int *end_index)
   924                                     unsigned int *end_index)
   926 {
   925 {
   927   TRACE_APPLY (nullptr);
   926   TRACE_APPLY (nullptr);
   928 
   927 
   929   hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   928   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
   930   skippy_iter.reset (c->buffer->idx + offset - 1, count);
   929   skippy_iter.reset (c->buffer->idx + offset - 1, count);
   931   skippy_iter.set_match_func (match_func, match_data, lookahead);
   930   skippy_iter.set_match_func (match_func, match_data, lookahead);
   932 
   931 
   933   for (unsigned int i = 0; i < count; i++)
   932   for (unsigned int i = 0; i < count; i++)
   934     if (!skippy_iter.next ())
   933     if (!skippy_iter.next ())
   947   {
   946   {
   948     TRACE_SANITIZE (this);
   947     TRACE_SANITIZE (this);
   949     return_trace (c->check_struct (this));
   948     return_trace (c->check_struct (this));
   950   }
   949   }
   951 
   950 
   952   USHORT        sequenceIndex;          /* Index into current glyph
   951   HBUINT16      sequenceIndex;          /* Index into current glyph
   953                                          * sequence--first glyph = 0 */
   952                                          * sequence--first glyph = 0 */
   954   USHORT        lookupListIndex;        /* Lookup to apply to that
   953   HBUINT16      lookupListIndex;        /* Lookup to apply to that
   955                                          * position--zero--based */
   954                                          * position--zero--based */
   956   public:
   955   public:
   957   DEFINE_SIZE_STATIC (4);
   956   DEFINE_SIZE_STATIC (4);
   958 };
   957 };
   959 
   958 
   965 {
   964 {
   966   for (unsigned int i = 0; i < lookupCount; i++)
   965   for (unsigned int i = 0; i < lookupCount; i++)
   967     c->recurse (lookupRecord[i].lookupListIndex);
   966     c->recurse (lookupRecord[i].lookupListIndex);
   968 }
   967 }
   969 
   968 
   970 static inline bool apply_lookup (hb_apply_context_t *c,
   969 static inline bool apply_lookup (hb_ot_apply_context_t *c,
   971                                  unsigned int count, /* Including the first glyph */
   970                                  unsigned int count, /* Including the first glyph */
   972                                  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
   971                                  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
   973                                  unsigned int lookupCount,
   972                                  unsigned int lookupCount,
   974                                  const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
   973                                  const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
   975                                  unsigned int match_length)
   974                                  unsigned int match_length)
  1000     /* Don't recurse to ourself at same position.
   999     /* Don't recurse to ourself at same position.
  1001      * Note that this test is too naive, it doesn't catch longer loops. */
  1000      * Note that this test is too naive, it doesn't catch longer loops. */
  1002     if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
  1001     if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
  1003       continue;
  1002       continue;
  1004 
  1003 
  1005     buffer->move_to (match_positions[idx]);
  1004     if (unlikely (!buffer->move_to (match_positions[idx])))
       
  1005       break;
       
  1006 
       
  1007     if (unlikely (buffer->max_ops <= 0))
       
  1008       break;
  1006 
  1009 
  1007     unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
  1010     unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
  1008     if (!c->recurse (lookupRecord[i].lookupListIndex))
  1011     if (!c->recurse (lookupRecord[i].lookupListIndex))
  1009       continue;
  1012       continue;
  1010 
  1013 
  1106   const void *match_data;
  1109   const void *match_data;
  1107 };
  1110 };
  1108 
  1111 
  1109 static inline void context_closure_lookup (hb_closure_context_t *c,
  1112 static inline void context_closure_lookup (hb_closure_context_t *c,
  1110                                            unsigned int inputCount, /* Including the first glyph (not matched) */
  1113                                            unsigned int inputCount, /* Including the first glyph (not matched) */
  1111                                            const USHORT input[], /* Array of input values--start with second glyph */
  1114                                            const HBUINT16 input[], /* Array of input values--start with second glyph */
  1112                                            unsigned int lookupCount,
  1115                                            unsigned int lookupCount,
  1113                                            const LookupRecord lookupRecord[],
  1116                                            const LookupRecord lookupRecord[],
  1114                                            ContextClosureLookupContext &lookup_context)
  1117                                            ContextClosureLookupContext &lookup_context)
  1115 {
  1118 {
  1116   if (intersects_array (c,
  1119   if (intersects_array (c,
  1120                      lookupCount, lookupRecord);
  1123                      lookupCount, lookupRecord);
  1121 }
  1124 }
  1122 
  1125 
  1123 static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
  1126 static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
  1124                                                   unsigned int inputCount, /* Including the first glyph (not matched) */
  1127                                                   unsigned int inputCount, /* Including the first glyph (not matched) */
  1125                                                   const USHORT input[], /* Array of input values--start with second glyph */
  1128                                                   const HBUINT16 input[], /* Array of input values--start with second glyph */
  1126                                                   unsigned int lookupCount,
  1129                                                   unsigned int lookupCount,
  1127                                                   const LookupRecord lookupRecord[],
  1130                                                   const LookupRecord lookupRecord[],
  1128                                                   ContextCollectGlyphsLookupContext &lookup_context)
  1131                                                   ContextCollectGlyphsLookupContext &lookup_context)
  1129 {
  1132 {
  1130   collect_array (c, c->input,
  1133   collect_array (c, c->input,
  1134                    lookupCount, lookupRecord);
  1137                    lookupCount, lookupRecord);
  1135 }
  1138 }
  1136 
  1139 
  1137 static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
  1140 static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
  1138                                                unsigned int inputCount, /* Including the first glyph (not matched) */
  1141                                                unsigned int inputCount, /* Including the first glyph (not matched) */
  1139                                                const USHORT input[], /* Array of input values--start with second glyph */
  1142                                                const HBUINT16 input[], /* Array of input values--start with second glyph */
  1140                                                unsigned int lookupCount HB_UNUSED,
  1143                                                unsigned int lookupCount HB_UNUSED,
  1141                                                const LookupRecord lookupRecord[] HB_UNUSED,
  1144                                                const LookupRecord lookupRecord[] HB_UNUSED,
  1142                                                ContextApplyLookupContext &lookup_context)
  1145                                                ContextApplyLookupContext &lookup_context)
  1143 {
  1146 {
  1144   return would_match_input (c,
  1147   return would_match_input (c,
  1145                             inputCount, input,
  1148                             inputCount, input,
  1146                             lookup_context.funcs.match, lookup_context.match_data);
  1149                             lookup_context.funcs.match, lookup_context.match_data);
  1147 }
  1150 }
  1148 static inline bool context_apply_lookup (hb_apply_context_t *c,
  1151 static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
  1149                                          unsigned int inputCount, /* Including the first glyph (not matched) */
  1152                                          unsigned int inputCount, /* Including the first glyph (not matched) */
  1150                                          const USHORT input[], /* Array of input values--start with second glyph */
  1153                                          const HBUINT16 input[], /* Array of input values--start with second glyph */
  1151                                          unsigned int lookupCount,
  1154                                          unsigned int lookupCount,
  1152                                          const LookupRecord lookupRecord[],
  1155                                          const LookupRecord lookupRecord[],
  1153                                          ContextApplyLookupContext &lookup_context)
  1156                                          ContextApplyLookupContext &lookup_context)
  1154 {
  1157 {
  1155   unsigned int match_length = 0;
  1158   unsigned int match_length = 0;
  1192     TRACE_WOULD_APPLY (this);
  1195     TRACE_WOULD_APPLY (this);
  1193     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
  1196     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
  1194     return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
  1197     return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
  1195   }
  1198   }
  1196 
  1199 
  1197   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1200   inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1198   {
  1201   {
  1199     TRACE_APPLY (this);
  1202     TRACE_APPLY (this);
  1200     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
  1203     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
  1201     return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
  1204     return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
  1202   }
  1205   }
  1207     TRACE_SANITIZE (this);
  1210     TRACE_SANITIZE (this);
  1208     return_trace (inputCount.sanitize (c) &&
  1211     return_trace (inputCount.sanitize (c) &&
  1209                   lookupCount.sanitize (c) &&
  1212                   lookupCount.sanitize (c) &&
  1210                   c->check_range (inputZ,
  1213                   c->check_range (inputZ,
  1211                                   inputZ[0].static_size * inputCount +
  1214                                   inputZ[0].static_size * inputCount +
  1212                                   lookupRecordX[0].static_size * lookupCount));
  1215                                   LookupRecord::static_size * lookupCount));
  1213   }
  1216   }
  1214 
  1217 
  1215   protected:
  1218   protected:
  1216   USHORT        inputCount;             /* Total number of glyphs in input
  1219   HBUINT16      inputCount;             /* Total number of glyphs in input
  1217                                          * glyph sequence--includes the first
  1220                                          * glyph sequence--includes the first
  1218                                          * glyph */
  1221                                          * glyph */
  1219   USHORT        lookupCount;            /* Number of LookupRecords */
  1222   HBUINT16      lookupCount;            /* Number of LookupRecords */
  1220   USHORT        inputZ[VAR];            /* Array of match inputs--start with
  1223   HBUINT16      inputZ[VAR];            /* Array of match inputs--start with
  1221                                          * second glyph */
  1224                                          * second glyph */
  1222   LookupRecord  lookupRecordX[VAR];     /* Array of LookupRecords--in
  1225 /*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
  1223                                          * design order */
  1226                                          * design order */
  1224   public:
  1227   public:
  1225   DEFINE_SIZE_ARRAY2 (4, inputZ, lookupRecordX);
  1228   DEFINE_SIZE_ARRAY (4, inputZ);
  1226 };
  1229 };
  1227 
  1230 
  1228 struct RuleSet
  1231 struct RuleSet
  1229 {
  1232 {
  1230   inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
  1233   inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
  1253         return_trace (true);
  1256         return_trace (true);
  1254     }
  1257     }
  1255     return_trace (false);
  1258     return_trace (false);
  1256   }
  1259   }
  1257 
  1260 
  1258   inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1261   inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1259   {
  1262   {
  1260     TRACE_APPLY (this);
  1263     TRACE_APPLY (this);
  1261     unsigned int num_rules = rule.len;
  1264     unsigned int num_rules = rule.len;
  1262     for (unsigned int i = 0; i < num_rules; i++)
  1265     for (unsigned int i = 0; i < num_rules; i++)
  1263     {
  1266     {
  1333   inline const Coverage &get_coverage (void) const
  1336   inline const Coverage &get_coverage (void) const
  1334   {
  1337   {
  1335     return this+coverage;
  1338     return this+coverage;
  1336   }
  1339   }
  1337 
  1340 
  1338   inline bool apply (hb_apply_context_t *c) const
  1341   inline bool apply (hb_ot_apply_context_t *c) const
  1339   {
  1342   {
  1340     TRACE_APPLY (this);
  1343     TRACE_APPLY (this);
  1341     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1344     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1342     if (likely (index == NOT_COVERED))
  1345     if (likely (index == NOT_COVERED))
  1343       return_trace (false);
  1346       return_trace (false);
  1355     TRACE_SANITIZE (this);
  1358     TRACE_SANITIZE (this);
  1356     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
  1359     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
  1357   }
  1360   }
  1358 
  1361 
  1359   protected:
  1362   protected:
  1360   USHORT        format;                 /* Format identifier--format = 1 */
  1363   HBUINT16      format;                 /* Format identifier--format = 1 */
  1361   OffsetTo<Coverage>
  1364   OffsetTo<Coverage>
  1362                 coverage;               /* Offset to Coverage table--from
  1365                 coverage;               /* Offset to Coverage table--from
  1363                                          * beginning of table */
  1366                                          * beginning of table */
  1364   OffsetArrayOf<RuleSet>
  1367   OffsetArrayOf<RuleSet>
  1365                 ruleSet;                /* Array of RuleSet tables
  1368                 ruleSet;                /* Array of RuleSet tables
  1425   inline const Coverage &get_coverage (void) const
  1428   inline const Coverage &get_coverage (void) const
  1426   {
  1429   {
  1427     return this+coverage;
  1430     return this+coverage;
  1428   }
  1431   }
  1429 
  1432 
  1430   inline bool apply (hb_apply_context_t *c) const
  1433   inline bool apply (hb_ot_apply_context_t *c) const
  1431   {
  1434   {
  1432     TRACE_APPLY (this);
  1435     TRACE_APPLY (this);
  1433     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1436     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1434     if (likely (index == NOT_COVERED)) return_trace (false);
  1437     if (likely (index == NOT_COVERED)) return_trace (false);
  1435 
  1438 
  1448     TRACE_SANITIZE (this);
  1451     TRACE_SANITIZE (this);
  1449     return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
  1452     return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
  1450   }
  1453   }
  1451 
  1454 
  1452   protected:
  1455   protected:
  1453   USHORT        format;                 /* Format identifier--format = 2 */
  1456   HBUINT16      format;                 /* Format identifier--format = 2 */
  1454   OffsetTo<Coverage>
  1457   OffsetTo<Coverage>
  1455                 coverage;               /* Offset to Coverage table--from
  1458                 coverage;               /* Offset to Coverage table--from
  1456                                          * beginning of table */
  1459                                          * beginning of table */
  1457   OffsetTo<ClassDef>
  1460   OffsetTo<ClassDef>
  1458                 classDef;               /* Offset to glyph ClassDef table--from
  1461                 classDef;               /* Offset to glyph ClassDef table--from
  1477     struct ContextClosureLookupContext lookup_context = {
  1480     struct ContextClosureLookupContext lookup_context = {
  1478       {intersects_coverage},
  1481       {intersects_coverage},
  1479       this
  1482       this
  1480     };
  1483     };
  1481     context_closure_lookup (c,
  1484     context_closure_lookup (c,
  1482                             glyphCount, (const USHORT *) (coverageZ + 1),
  1485                             glyphCount, (const HBUINT16 *) (coverageZ + 1),
  1483                             lookupCount, lookupRecord,
  1486                             lookupCount, lookupRecord,
  1484                             lookup_context);
  1487                             lookup_context);
  1485   }
  1488   }
  1486 
  1489 
  1487   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1490   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1494       {collect_coverage},
  1497       {collect_coverage},
  1495       this
  1498       this
  1496     };
  1499     };
  1497 
  1500 
  1498     context_collect_glyphs_lookup (c,
  1501     context_collect_glyphs_lookup (c,
  1499                                    glyphCount, (const USHORT *) (coverageZ + 1),
  1502                                    glyphCount, (const HBUINT16 *) (coverageZ + 1),
  1500                                    lookupCount, lookupRecord,
  1503                                    lookupCount, lookupRecord,
  1501                                    lookup_context);
  1504                                    lookup_context);
  1502   }
  1505   }
  1503 
  1506 
  1504   inline bool would_apply (hb_would_apply_context_t *c) const
  1507   inline bool would_apply (hb_would_apply_context_t *c) const
  1508     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
  1511     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
  1509     struct ContextApplyLookupContext lookup_context = {
  1512     struct ContextApplyLookupContext lookup_context = {
  1510       {match_coverage},
  1513       {match_coverage},
  1511       this
  1514       this
  1512     };
  1515     };
  1513     return_trace (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
  1516     return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
  1514   }
  1517   }
  1515 
  1518 
  1516   inline const Coverage &get_coverage (void) const
  1519   inline const Coverage &get_coverage (void) const
  1517   {
  1520   {
  1518     return this+coverageZ[0];
  1521     return this+coverageZ[0];
  1519   }
  1522   }
  1520 
  1523 
  1521   inline bool apply (hb_apply_context_t *c) const
  1524   inline bool apply (hb_ot_apply_context_t *c) const
  1522   {
  1525   {
  1523     TRACE_APPLY (this);
  1526     TRACE_APPLY (this);
  1524     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
  1527     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
  1525     if (likely (index == NOT_COVERED)) return_trace (false);
  1528     if (likely (index == NOT_COVERED)) return_trace (false);
  1526 
  1529 
  1527     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
  1530     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
  1528     struct ContextApplyLookupContext lookup_context = {
  1531     struct ContextApplyLookupContext lookup_context = {
  1529       {match_coverage},
  1532       {match_coverage},
  1530       this
  1533       this
  1531     };
  1534     };
  1532     return_trace (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
  1535     return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
  1533   }
  1536   }
  1534 
  1537 
  1535   inline bool sanitize (hb_sanitize_context_t *c) const
  1538   inline bool sanitize (hb_sanitize_context_t *c) const
  1536   {
  1539   {
  1537     TRACE_SANITIZE (this);
  1540     TRACE_SANITIZE (this);
  1544     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
  1547     const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
  1545     return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
  1548     return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
  1546   }
  1549   }
  1547 
  1550 
  1548   protected:
  1551   protected:
  1549   USHORT        format;                 /* Format identifier--format = 3 */
  1552   HBUINT16      format;                 /* Format identifier--format = 3 */
  1550   USHORT        glyphCount;             /* Number of glyphs in the input glyph
  1553   HBUINT16      glyphCount;             /* Number of glyphs in the input glyph
  1551                                          * sequence */
  1554                                          * sequence */
  1552   USHORT        lookupCount;            /* Number of LookupRecords */
  1555   HBUINT16      lookupCount;            /* Number of LookupRecords */
  1553   OffsetTo<Coverage>
  1556   OffsetTo<Coverage>
  1554                 coverageZ[VAR];         /* Array of offsets to Coverage
  1557                 coverageZ[VAR];         /* Array of offsets to Coverage
  1555                                          * table in glyph sequence order */
  1558                                          * table in glyph sequence order */
  1556   LookupRecord  lookupRecordX[VAR];     /* Array of LookupRecords--in
  1559 /*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
  1557                                          * design order */
  1560                                          * design order */
  1558   public:
  1561   public:
  1559   DEFINE_SIZE_ARRAY2 (6, coverageZ, lookupRecordX);
  1562   DEFINE_SIZE_ARRAY (6, coverageZ);
  1560 };
  1563 };
  1561 
  1564 
  1562 struct Context
  1565 struct Context
  1563 {
  1566 {
  1564   template <typename context_t>
  1567   template <typename context_t>
  1574     }
  1577     }
  1575   }
  1578   }
  1576 
  1579 
  1577   protected:
  1580   protected:
  1578   union {
  1581   union {
  1579   USHORT                format;         /* Format identifier */
  1582   HBUINT16              format;         /* Format identifier */
  1580   ContextFormat1        format1;
  1583   ContextFormat1        format1;
  1581   ContextFormat2        format2;
  1584   ContextFormat2        format2;
  1582   ContextFormat3        format3;
  1585   ContextFormat3        format3;
  1583   } u;
  1586   } u;
  1584 };
  1587 };
  1604   const void *match_data[3];
  1607   const void *match_data[3];
  1605 };
  1608 };
  1606 
  1609 
  1607 static inline void chain_context_closure_lookup (hb_closure_context_t *c,
  1610 static inline void chain_context_closure_lookup (hb_closure_context_t *c,
  1608                                                  unsigned int backtrackCount,
  1611                                                  unsigned int backtrackCount,
  1609                                                  const USHORT backtrack[],
  1612                                                  const HBUINT16 backtrack[],
  1610                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
  1613                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
  1611                                                  const USHORT input[], /* Array of input values--start with second glyph */
  1614                                                  const HBUINT16 input[], /* Array of input values--start with second glyph */
  1612                                                  unsigned int lookaheadCount,
  1615                                                  unsigned int lookaheadCount,
  1613                                                  const USHORT lookahead[],
  1616                                                  const HBUINT16 lookahead[],
  1614                                                  unsigned int lookupCount,
  1617                                                  unsigned int lookupCount,
  1615                                                  const LookupRecord lookupRecord[],
  1618                                                  const LookupRecord lookupRecord[],
  1616                                                  ChainContextClosureLookupContext &lookup_context)
  1619                                                  ChainContextClosureLookupContext &lookup_context)
  1617 {
  1620 {
  1618   if (intersects_array (c,
  1621   if (intersects_array (c,
  1628                      lookupCount, lookupRecord);
  1631                      lookupCount, lookupRecord);
  1629 }
  1632 }
  1630 
  1633 
  1631 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
  1634 static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
  1632                                                         unsigned int backtrackCount,
  1635                                                         unsigned int backtrackCount,
  1633                                                         const USHORT backtrack[],
  1636                                                         const HBUINT16 backtrack[],
  1634                                                         unsigned int inputCount, /* Including the first glyph (not matched) */
  1637                                                         unsigned int inputCount, /* Including the first glyph (not matched) */
  1635                                                         const USHORT input[], /* Array of input values--start with second glyph */
  1638                                                         const HBUINT16 input[], /* Array of input values--start with second glyph */
  1636                                                         unsigned int lookaheadCount,
  1639                                                         unsigned int lookaheadCount,
  1637                                                         const USHORT lookahead[],
  1640                                                         const HBUINT16 lookahead[],
  1638                                                         unsigned int lookupCount,
  1641                                                         unsigned int lookupCount,
  1639                                                         const LookupRecord lookupRecord[],
  1642                                                         const LookupRecord lookupRecord[],
  1640                                                         ChainContextCollectGlyphsLookupContext &lookup_context)
  1643                                                         ChainContextCollectGlyphsLookupContext &lookup_context)
  1641 {
  1644 {
  1642   collect_array (c, c->before,
  1645   collect_array (c, c->before,
  1652                    lookupCount, lookupRecord);
  1655                    lookupCount, lookupRecord);
  1653 }
  1656 }
  1654 
  1657 
  1655 static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
  1658 static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
  1656                                                      unsigned int backtrackCount,
  1659                                                      unsigned int backtrackCount,
  1657                                                      const USHORT backtrack[] HB_UNUSED,
  1660                                                      const HBUINT16 backtrack[] HB_UNUSED,
  1658                                                      unsigned int inputCount, /* Including the first glyph (not matched) */
  1661                                                      unsigned int inputCount, /* Including the first glyph (not matched) */
  1659                                                      const USHORT input[], /* Array of input values--start with second glyph */
  1662                                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
  1660                                                      unsigned int lookaheadCount,
  1663                                                      unsigned int lookaheadCount,
  1661                                                      const USHORT lookahead[] HB_UNUSED,
  1664                                                      const HBUINT16 lookahead[] HB_UNUSED,
  1662                                                      unsigned int lookupCount HB_UNUSED,
  1665                                                      unsigned int lookupCount HB_UNUSED,
  1663                                                      const LookupRecord lookupRecord[] HB_UNUSED,
  1666                                                      const LookupRecord lookupRecord[] HB_UNUSED,
  1664                                                      ChainContextApplyLookupContext &lookup_context)
  1667                                                      ChainContextApplyLookupContext &lookup_context)
  1665 {
  1668 {
  1666   return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
  1669   return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
  1667       && would_match_input (c,
  1670       && would_match_input (c,
  1668                             inputCount, input,
  1671                             inputCount, input,
  1669                             lookup_context.funcs.match, lookup_context.match_data[1]);
  1672                             lookup_context.funcs.match, lookup_context.match_data[1]);
  1670 }
  1673 }
  1671 
  1674 
  1672 static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
  1675 static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
  1673                                                unsigned int backtrackCount,
  1676                                                unsigned int backtrackCount,
  1674                                                const USHORT backtrack[],
  1677                                                const HBUINT16 backtrack[],
  1675                                                unsigned int inputCount, /* Including the first glyph (not matched) */
  1678                                                unsigned int inputCount, /* Including the first glyph (not matched) */
  1676                                                const USHORT input[], /* Array of input values--start with second glyph */
  1679                                                const HBUINT16 input[], /* Array of input values--start with second glyph */
  1677                                                unsigned int lookaheadCount,
  1680                                                unsigned int lookaheadCount,
  1678                                                const USHORT lookahead[],
  1681                                                const HBUINT16 lookahead[],
  1679                                                unsigned int lookupCount,
  1682                                                unsigned int lookupCount,
  1680                                                const LookupRecord lookupRecord[],
  1683                                                const LookupRecord lookupRecord[],
  1681                                                ChainContextApplyLookupContext &lookup_context)
  1684                                                ChainContextApplyLookupContext &lookup_context)
  1682 {
  1685 {
  1683   unsigned int start_index = 0, match_length = 0, end_index = 0;
  1686   unsigned int start_index = 0, match_length = 0, end_index = 0;
  1704 struct ChainRule
  1707 struct ChainRule
  1705 {
  1708 {
  1706   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
  1709   inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
  1707   {
  1710   {
  1708     TRACE_CLOSURE (this);
  1711     TRACE_CLOSURE (this);
  1709     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1712     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
  1710     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1713     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
  1711     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1714     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1712     chain_context_closure_lookup (c,
  1715     chain_context_closure_lookup (c,
  1713                                   backtrack.len, backtrack.array,
  1716                                   backtrack.len, backtrack.array,
  1714                                   input.len, input.array,
  1717                                   input.len, input.array,
  1715                                   lookahead.len, lookahead.array,
  1718                                   lookahead.len, lookahead.array,
  1718   }
  1721   }
  1719 
  1722 
  1720   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
  1723   inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
  1721   {
  1724   {
  1722     TRACE_COLLECT_GLYPHS (this);
  1725     TRACE_COLLECT_GLYPHS (this);
  1723     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1726     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
  1724     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1727     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
  1725     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1728     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1726     chain_context_collect_glyphs_lookup (c,
  1729     chain_context_collect_glyphs_lookup (c,
  1727                                          backtrack.len, backtrack.array,
  1730                                          backtrack.len, backtrack.array,
  1728                                          input.len, input.array,
  1731                                          input.len, input.array,
  1729                                          lookahead.len, lookahead.array,
  1732                                          lookahead.len, lookahead.array,
  1732   }
  1735   }
  1733 
  1736 
  1734   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1737   inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1735   {
  1738   {
  1736     TRACE_WOULD_APPLY (this);
  1739     TRACE_WOULD_APPLY (this);
  1737     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1740     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
  1738     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1741     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
  1739     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1742     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1740     return_trace (chain_context_would_apply_lookup (c,
  1743     return_trace (chain_context_would_apply_lookup (c,
  1741                                                     backtrack.len, backtrack.array,
  1744                                                     backtrack.len, backtrack.array,
  1742                                                     input.len, input.array,
  1745                                                     input.len, input.array,
  1743                                                     lookahead.len, lookahead.array, lookup.len,
  1746                                                     lookahead.len, lookahead.array, lookup.len,
  1744                                                     lookup.array, lookup_context));
  1747                                                     lookup.array, lookup_context));
  1745   }
  1748   }
  1746 
  1749 
  1747   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1750   inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1748   {
  1751   {
  1749     TRACE_APPLY (this);
  1752     TRACE_APPLY (this);
  1750     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1753     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
  1751     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1754     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
  1752     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1755     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1753     return_trace (chain_context_apply_lookup (c,
  1756     return_trace (chain_context_apply_lookup (c,
  1754                                               backtrack.len, backtrack.array,
  1757                                               backtrack.len, backtrack.array,
  1755                                               input.len, input.array,
  1758                                               input.len, input.array,
  1756                                               lookahead.len, lookahead.array, lookup.len,
  1759                                               lookahead.len, lookahead.array, lookup.len,
  1759 
  1762 
  1760   inline bool sanitize (hb_sanitize_context_t *c) const
  1763   inline bool sanitize (hb_sanitize_context_t *c) const
  1761   {
  1764   {
  1762     TRACE_SANITIZE (this);
  1765     TRACE_SANITIZE (this);
  1763     if (!backtrack.sanitize (c)) return_trace (false);
  1766     if (!backtrack.sanitize (c)) return_trace (false);
  1764     const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1767     const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
  1765     if (!input.sanitize (c)) return_trace (false);
  1768     if (!input.sanitize (c)) return_trace (false);
  1766     const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1769     const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
  1767     if (!lookahead.sanitize (c)) return_trace (false);
  1770     if (!lookahead.sanitize (c)) return_trace (false);
  1768     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1771     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1769     return_trace (lookup.sanitize (c));
  1772     return_trace (lookup.sanitize (c));
  1770   }
  1773   }
  1771 
  1774 
  1772   protected:
  1775   protected:
  1773   ArrayOf<USHORT>
  1776   ArrayOf<HBUINT16>
  1774                 backtrack;              /* Array of backtracking values
  1777                 backtrack;              /* Array of backtracking values
  1775                                          * (to be matched before the input
  1778                                          * (to be matched before the input
  1776                                          * sequence) */
  1779                                          * sequence) */
  1777   HeadlessArrayOf<USHORT>
  1780   HeadlessArrayOf<HBUINT16>
  1778                 inputX;                 /* Array of input values (start with
  1781                 inputX;                 /* Array of input values (start with
  1779                                          * second glyph) */
  1782                                          * second glyph) */
  1780   ArrayOf<USHORT>
  1783   ArrayOf<HBUINT16>
  1781                 lookaheadX;             /* Array of lookahead values's (to be
  1784                 lookaheadX;             /* Array of lookahead values's (to be
  1782                                          * matched after the input sequence) */
  1785                                          * matched after the input sequence) */
  1783   ArrayOf<LookupRecord>
  1786   ArrayOf<LookupRecord>
  1784                 lookupX;                /* Array of LookupRecords--in
  1787                 lookupX;                /* Array of LookupRecords--in
  1785                                          * design order) */
  1788                                          * design order) */
  1814         return_trace (true);
  1817         return_trace (true);
  1815 
  1818 
  1816     return_trace (false);
  1819     return_trace (false);
  1817   }
  1820   }
  1818 
  1821 
  1819   inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1822   inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1820   {
  1823   {
  1821     TRACE_APPLY (this);
  1824     TRACE_APPLY (this);
  1822     unsigned int num_rules = rule.len;
  1825     unsigned int num_rules = rule.len;
  1823     for (unsigned int i = 0; i < num_rules; i++)
  1826     for (unsigned int i = 0; i < num_rules; i++)
  1824       if ((this+rule[i]).apply (c, lookup_context))
  1827       if ((this+rule[i]).apply (c, lookup_context))
  1891   inline const Coverage &get_coverage (void) const
  1894   inline const Coverage &get_coverage (void) const
  1892   {
  1895   {
  1893     return this+coverage;
  1896     return this+coverage;
  1894   }
  1897   }
  1895 
  1898 
  1896   inline bool apply (hb_apply_context_t *c) const
  1899   inline bool apply (hb_ot_apply_context_t *c) const
  1897   {
  1900   {
  1898     TRACE_APPLY (this);
  1901     TRACE_APPLY (this);
  1899     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1902     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1900     if (likely (index == NOT_COVERED)) return_trace (false);
  1903     if (likely (index == NOT_COVERED)) return_trace (false);
  1901 
  1904 
  1912     TRACE_SANITIZE (this);
  1915     TRACE_SANITIZE (this);
  1913     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
  1916     return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
  1914   }
  1917   }
  1915 
  1918 
  1916   protected:
  1919   protected:
  1917   USHORT        format;                 /* Format identifier--format = 1 */
  1920   HBUINT16      format;                 /* Format identifier--format = 1 */
  1918   OffsetTo<Coverage>
  1921   OffsetTo<Coverage>
  1919                 coverage;               /* Offset to Coverage table--from
  1922                 coverage;               /* Offset to Coverage table--from
  1920                                          * beginning of table */
  1923                                          * beginning of table */
  1921   OffsetArrayOf<ChainRuleSet>
  1924   OffsetArrayOf<ChainRuleSet>
  1922                 ruleSet;                /* Array of ChainRuleSet tables
  1925                 ruleSet;                /* Array of ChainRuleSet tables
  1995   inline const Coverage &get_coverage (void) const
  1998   inline const Coverage &get_coverage (void) const
  1996   {
  1999   {
  1997     return this+coverage;
  2000     return this+coverage;
  1998   }
  2001   }
  1999 
  2002 
  2000   inline bool apply (hb_apply_context_t *c) const
  2003   inline bool apply (hb_ot_apply_context_t *c) const
  2001   {
  2004   {
  2002     TRACE_APPLY (this);
  2005     TRACE_APPLY (this);
  2003     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  2006     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  2004     if (likely (index == NOT_COVERED)) return_trace (false);
  2007     if (likely (index == NOT_COVERED)) return_trace (false);
  2005 
  2008 
  2027                   lookaheadClassDef.sanitize (c, this) &&
  2030                   lookaheadClassDef.sanitize (c, this) &&
  2028                   ruleSet.sanitize (c, this));
  2031                   ruleSet.sanitize (c, this));
  2029   }
  2032   }
  2030 
  2033 
  2031   protected:
  2034   protected:
  2032   USHORT        format;                 /* Format identifier--format = 2 */
  2035   HBUINT16      format;                 /* Format identifier--format = 2 */
  2033   OffsetTo<Coverage>
  2036   OffsetTo<Coverage>
  2034                 coverage;               /* Offset to Coverage table--from
  2037                 coverage;               /* Offset to Coverage table--from
  2035                                          * beginning of table */
  2038                                          * beginning of table */
  2036   OffsetTo<ClassDef>
  2039   OffsetTo<ClassDef>
  2037                 backtrackClassDef;      /* Offset to glyph ClassDef table
  2040                 backtrackClassDef;      /* Offset to glyph ClassDef table
  2067     struct ChainContextClosureLookupContext lookup_context = {
  2070     struct ChainContextClosureLookupContext lookup_context = {
  2068       {intersects_coverage},
  2071       {intersects_coverage},
  2069       {this, this, this}
  2072       {this, this, this}
  2070     };
  2073     };
  2071     chain_context_closure_lookup (c,
  2074     chain_context_closure_lookup (c,
  2072                                   backtrack.len, (const USHORT *) backtrack.array,
  2075                                   backtrack.len, (const HBUINT16 *) backtrack.array,
  2073                                   input.len, (const USHORT *) input.array + 1,
  2076                                   input.len, (const HBUINT16 *) input.array + 1,
  2074                                   lookahead.len, (const USHORT *) lookahead.array,
  2077                                   lookahead.len, (const HBUINT16 *) lookahead.array,
  2075                                   lookup.len, lookup.array,
  2078                                   lookup.len, lookup.array,
  2076                                   lookup_context);
  2079                                   lookup_context);
  2077   }
  2080   }
  2078 
  2081 
  2079   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  2082   inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  2088     struct ChainContextCollectGlyphsLookupContext lookup_context = {
  2091     struct ChainContextCollectGlyphsLookupContext lookup_context = {
  2089       {collect_coverage},
  2092       {collect_coverage},
  2090       {this, this, this}
  2093       {this, this, this}
  2091     };
  2094     };
  2092     chain_context_collect_glyphs_lookup (c,
  2095     chain_context_collect_glyphs_lookup (c,
  2093                                          backtrack.len, (const USHORT *) backtrack.array,
  2096                                          backtrack.len, (const HBUINT16 *) backtrack.array,
  2094                                          input.len, (const USHORT *) input.array + 1,
  2097                                          input.len, (const HBUINT16 *) input.array + 1,
  2095                                          lookahead.len, (const USHORT *) lookahead.array,
  2098                                          lookahead.len, (const HBUINT16 *) lookahead.array,
  2096                                          lookup.len, lookup.array,
  2099                                          lookup.len, lookup.array,
  2097                                          lookup_context);
  2100                                          lookup_context);
  2098   }
  2101   }
  2099 
  2102 
  2100   inline bool would_apply (hb_would_apply_context_t *c) const
  2103   inline bool would_apply (hb_would_apply_context_t *c) const
  2107     struct ChainContextApplyLookupContext lookup_context = {
  2110     struct ChainContextApplyLookupContext lookup_context = {
  2108       {match_coverage},
  2111       {match_coverage},
  2109       {this, this, this}
  2112       {this, this, this}
  2110     };
  2113     };
  2111     return_trace (chain_context_would_apply_lookup (c,
  2114     return_trace (chain_context_would_apply_lookup (c,
  2112                                                     backtrack.len, (const USHORT *) backtrack.array,
  2115                                                     backtrack.len, (const HBUINT16 *) backtrack.array,
  2113                                                     input.len, (const USHORT *) input.array + 1,
  2116                                                     input.len, (const HBUINT16 *) input.array + 1,
  2114                                                     lookahead.len, (const USHORT *) lookahead.array,
  2117                                                     lookahead.len, (const HBUINT16 *) lookahead.array,
  2115                                                     lookup.len, lookup.array, lookup_context));
  2118                                                     lookup.len, lookup.array, lookup_context));
  2116   }
  2119   }
  2117 
  2120 
  2118   inline const Coverage &get_coverage (void) const
  2121   inline const Coverage &get_coverage (void) const
  2119   {
  2122   {
  2120     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  2123     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  2121     return this+input[0];
  2124     return this+input[0];
  2122   }
  2125   }
  2123 
  2126 
  2124   inline bool apply (hb_apply_context_t *c) const
  2127   inline bool apply (hb_ot_apply_context_t *c) const
  2125   {
  2128   {
  2126     TRACE_APPLY (this);
  2129     TRACE_APPLY (this);
  2127     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  2130     const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  2128 
  2131 
  2129     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
  2132     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
  2134     struct ChainContextApplyLookupContext lookup_context = {
  2137     struct ChainContextApplyLookupContext lookup_context = {
  2135       {match_coverage},
  2138       {match_coverage},
  2136       {this, this, this}
  2139       {this, this, this}
  2137     };
  2140     };
  2138     return_trace (chain_context_apply_lookup (c,
  2141     return_trace (chain_context_apply_lookup (c,
  2139                                               backtrack.len, (const USHORT *) backtrack.array,
  2142                                               backtrack.len, (const HBUINT16 *) backtrack.array,
  2140                                               input.len, (const USHORT *) input.array + 1,
  2143                                               input.len, (const HBUINT16 *) input.array + 1,
  2141                                               lookahead.len, (const USHORT *) lookahead.array,
  2144                                               lookahead.len, (const HBUINT16 *) lookahead.array,
  2142                                               lookup.len, lookup.array, lookup_context));
  2145                                               lookup.len, lookup.array, lookup_context));
  2143   }
  2146   }
  2144 
  2147 
  2145   inline bool sanitize (hb_sanitize_context_t *c) const
  2148   inline bool sanitize (hb_sanitize_context_t *c) const
  2146   {
  2149   {
  2154     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  2157     const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  2155     return_trace (lookup.sanitize (c));
  2158     return_trace (lookup.sanitize (c));
  2156   }
  2159   }
  2157 
  2160 
  2158   protected:
  2161   protected:
  2159   USHORT        format;                 /* Format identifier--format = 3 */
  2162   HBUINT16      format;                 /* Format identifier--format = 3 */
  2160   OffsetArrayOf<Coverage>
  2163   OffsetArrayOf<Coverage>
  2161                 backtrack;              /* Array of coverage tables
  2164                 backtrack;              /* Array of coverage tables
  2162                                          * in backtracking sequence, in  glyph
  2165                                          * in backtracking sequence, in  glyph
  2163                                          * sequence order */
  2166                                          * sequence order */
  2164   OffsetArrayOf<Coverage>
  2167   OffsetArrayOf<Coverage>
  2191     }
  2194     }
  2192   }
  2195   }
  2193 
  2196 
  2194   protected:
  2197   protected:
  2195   union {
  2198   union {
  2196   USHORT                format; /* Format identifier */
  2199   HBUINT16              format; /* Format identifier */
  2197   ChainContextFormat1   format1;
  2200   ChainContextFormat1   format1;
  2198   ChainContextFormat2   format2;
  2201   ChainContextFormat2   format2;
  2199   ChainContextFormat3   format3;
  2202   ChainContextFormat3   format3;
  2200   } u;
  2203   } u;
  2201 };
  2204 };
  2224 
  2227 
  2225   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
  2228   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
  2226   inline bool sanitize (hb_sanitize_context_t *c) const
  2229   inline bool sanitize (hb_sanitize_context_t *c) const
  2227   {
  2230   {
  2228     TRACE_SANITIZE (this);
  2231     TRACE_SANITIZE (this);
  2229     return_trace (c->check_struct (this) && extensionOffset != 0);
  2232     return_trace (c->check_struct (this) &&
       
  2233                   extensionOffset != 0 &&
       
  2234                   extensionLookupType != T::LookupSubTable::Extension);
  2230   }
  2235   }
  2231 
  2236 
  2232   protected:
  2237   protected:
  2233   USHORT        format;                 /* Format identifier. Set to 1. */
  2238   HBUINT16      format;                 /* Format identifier. Set to 1. */
  2234   USHORT        extensionLookupType;    /* Lookup type of subtable referenced
  2239   HBUINT16      extensionLookupType;    /* Lookup type of subtable referenced
  2235                                          * by ExtensionOffset (i.e. the
  2240                                          * by ExtensionOffset (i.e. the
  2236                                          * extension subtable). */
  2241                                          * extension subtable). */
  2237   ULONG         extensionOffset;        /* Offset to the extension subtable,
  2242   HBUINT32      extensionOffset;        /* Offset to the extension subtable,
  2238                                          * of lookup type subtable. */
  2243                                          * of lookup type subtable. */
  2239   public:
  2244   public:
  2240   DEFINE_SIZE_STATIC (8);
  2245   DEFINE_SIZE_STATIC (8);
  2241 };
  2246 };
  2242 
  2247 
  2270     }
  2275     }
  2271   }
  2276   }
  2272 
  2277 
  2273   protected:
  2278   protected:
  2274   union {
  2279   union {
  2275   USHORT                format;         /* Format identifier */
  2280   HBUINT16              format;         /* Format identifier */
  2276   ExtensionFormat1<T>   format1;
  2281   ExtensionFormat1<T>   format1;
  2277   } u;
  2282   } u;
  2278 };
  2283 };
  2279 
  2284 
  2280 
  2285 
  2282  * GSUB/GPOS Common
  2287  * GSUB/GPOS Common
  2283  */
  2288  */
  2284 
  2289 
  2285 struct GSUBGPOS
  2290 struct GSUBGPOS
  2286 {
  2291 {
  2287   static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
       
  2288   static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
       
  2289 
       
  2290   inline unsigned int get_script_count (void) const
  2292   inline unsigned int get_script_count (void) const
  2291   { return (this+scriptList).len; }
  2293   { return (this+scriptList).len; }
  2292   inline const Tag& get_script_tag (unsigned int i) const
  2294   inline const Tag& get_script_tag (unsigned int i) const
  2293   { return (this+scriptList).get_tag (i); }
  2295   { return (this+scriptList).get_tag (i); }
  2294   inline unsigned int get_script_tags (unsigned int start_offset,
  2296   inline unsigned int get_script_tags (unsigned int start_offset,