hb-ot-layout-gsubgpos-private.hh revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2010,2012  Google, Inc.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-buffer-private.hh"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-layout-gdef-table.hh"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-set-private.hh"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace OT {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define TRACE_DISPATCH(this) \
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_CLOSURE
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_CLOSURE(this) \
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_closure_context_t
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "CLOSURE"; }
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef hb_void_t return_t;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return HB_VOID; }
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return_t recurse (unsigned int lookup_index)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (nesting_level_left == 0 || !recurse_func))
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return default_return_value ();
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nesting_level_left--;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    recurse_func (this, lookup_index);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nesting_level_left++;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HB_VOID;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_set_t *glyphs;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recurse_func_t recurse_func;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int nesting_level_left;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int debug_depth;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_closure_context_t (hb_face_t *face_,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			hb_set_t *glyphs_,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		        unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  face (face_),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  glyphs (glyphs_),
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			  recurse_func (NULL),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  nesting_level_left (nesting_level_left_),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  debug_depth (0) {}
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_WOULD_APPLY
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_WOULD_APPLY(this) \
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "%d glyphs", c->len);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_would_apply_context_t
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "WOULD_APPLY"; }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef bool return_t;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return false; }
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool stop_sublookup_iteration (return_t r) const { return r; }
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const hb_codepoint_t *glyphs;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool zero_context;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int debug_depth;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_would_apply_context_t (hb_face_t *face_,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    const hb_codepoint_t *glyphs_,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    unsigned int len_,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    bool zero_context_) :
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      face (face_),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      glyphs (glyphs_),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      len (len_),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      zero_context (zero_context_),
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      debug_depth (0) {}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef HB_DEBUG_COLLECT_GLYPHS
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_COLLECT_GLYPHS(this) \
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "");
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_collect_glyphs_context_t
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef hb_void_t return_t;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return HB_VOID; }
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return_t recurse (unsigned int lookup_index)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (nesting_level_left == 0 || !recurse_func))
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return default_return_value ();
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Note that GPOS sets recurse_func to NULL already, so it doesn't get
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * past the previous check.  For GSUB, we only want to collect the output
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * glyphs in the recursion.  If output is not requested, we can go home now. */
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (output == hb_set_get_empty ())
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return HB_VOID;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_set_t *old_before = before;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_set_t *old_input  = input;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_set_t *old_after  = after;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    before = input = after = hb_set_get_empty ();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nesting_level_left--;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    recurse_func (this, lookup_index);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nesting_level_left++;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    before = old_before;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    input  = old_input;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    after  = old_after;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return HB_VOID;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_face_t *face;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_set_t *before;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_set_t *input;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_set_t *after;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_set_t *output;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recurse_func_t recurse_func;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int nesting_level_left;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int debug_depth;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_collect_glyphs_context_t (hb_face_t *face_,
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       hb_set_t  *glyphs_before, /* OUT. May be NULL */
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       hb_set_t  *glyphs_input,  /* OUT. May be NULL */
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       hb_set_t  *glyphs_after,  /* OUT. May be NULL */
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       hb_set_t  *glyphs_output, /* OUT. May be NULL */
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      face (face_),
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      recurse_func (NULL),
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      nesting_level_left (nesting_level_left_),
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      debug_depth (0) {}
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct hb_get_coverage_context_t
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "GET_COVERAGE"; }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = 0;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef const Coverage &return_t;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return Null(Coverage); }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_get_coverage_context_t (void) :
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    debug_depth (0) {}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int debug_depth;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_APPLY
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_APPLY (HB_DEBUG+0)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TRACE_APPLY(this) \
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_apply_context_t
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const char *get_name (void) { return "APPLY"; }
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef bool return_t;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename T>
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline return_t dispatch (const T &obj) { return obj.apply (this); }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static return_t default_return_value (void) { return false; }
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool stop_sublookup_iteration (return_t r) const { return r; }
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return_t recurse (unsigned int lookup_index)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (nesting_level_left == 0 || !recurse_func))
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return default_return_value ();
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nesting_level_left--;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool ret = recurse_func (this, lookup_index);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    nesting_level_left++;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ret;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned int table_index; /* GSUB/GPOS */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_font_t *font;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_buffer_t *buffer;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_direction_t direction;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_mask_t lookup_mask;
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool auto_zwj;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recurse_func_t recurse_func;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int nesting_level_left;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int lookup_props;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GDEF &gdef;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_glyph_classes;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int debug_depth;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_apply_context_t (unsigned int table_index_,
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		      hb_font_t *font_,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      hb_buffer_t *buffer_,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		      hb_mask_t lookup_mask_,
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		      bool auto_zwj_) :
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			table_index (table_index_),
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			font (font_), face (font->face), buffer (buffer_),
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			direction (buffer_->props.direction),
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			lookup_mask (lookup_mask_),
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			auto_zwj (auto_zwj_),
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			recurse_func (NULL),
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			nesting_level_left (MAX_NESTING_LEVEL),
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			lookup_props (0),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			gdef (*hb_ot_layout_from_face (face)->gdef),
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			has_glyph_classes (gdef.has_glyph_classes ()),
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			debug_depth (0) {}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct matcher_t
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline matcher_t (void) :
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     lookup_props (0),
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     ignore_zwnj (false),
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     ignore_zwj (false),
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     mask (-1),
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     syllable arg1(0),
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#undef arg1
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     match_func (NULL),
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     match_data (NULL) {};
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_match_func (match_func_t match_func_,
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				const void *match_data_)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { match_func = match_func_; match_data = match_data_; }
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    enum may_match_t {
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      MATCH_NO,
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      MATCH_YES,
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      MATCH_MAYBE
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    };
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline may_match_t may_match (const hb_glyph_info_t &info,
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				  const USHORT          *glyph_data) const
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    {
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!(info.mask & mask) ||
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  (syllable && syllable != info.syllable ()))
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	return MATCH_NO;
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (match_func)
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return MATCH_MAYBE;
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    enum may_skip_t {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SKIP_NO,
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SKIP_YES,
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SKIP_MAYBE
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    };
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline may_skip_t
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    may_skip (const hb_apply_context_t *c,
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	      const hb_glyph_info_t    &info) const
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      unsigned int property;
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      property = info.glyph_props();
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!c->match_properties (info.codepoint, property, lookup_props))
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	return SKIP_YES;
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		    (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		    !is_a_ligature (info)))
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	return SKIP_MAYBE;
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SKIP_NO;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    protected:
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned int lookup_props;
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool ignore_zwnj;
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool ignore_zwj;
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    hb_mask_t mask;
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint8_t syllable;
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    match_func_t match_func;
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const void *match_data;
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct skipping_forward_iterator_t
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline skipping_forward_iterator_t (hb_apply_context_t *c_,
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					unsigned int start_index_,
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					unsigned int num_items_,
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					bool context_match = false) :
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 idx (start_index_),
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 c (c_),
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 match_glyph_data (NULL),
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 num_items (num_items_),
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 end (c->buffer->len)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_lookup_props (c->lookup_props);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!context_match)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	matcher.set_mask (c->lookup_mask);
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_match_func (matcher_t::match_func_t match_func,
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				const void *match_data,
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				const USHORT glyph_data[])
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_match_func (match_func, match_data);
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      match_glyph_data = glyph_data;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); }
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void reject (void) { num_items++; match_glyph_data--; }
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline bool next (void)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert (num_items > 0);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      while (!has_no_chance ())
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	idx++;
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	const hb_glyph_info_t &info = c->buffer->info[idx];
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (unlikely (skip == matcher_t::SKIP_YES))
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  continue;
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (match == matcher_t::MATCH_YES ||
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    (match == matcher_t::MATCH_MAYBE &&
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     skip == matcher_t::SKIP_NO))
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  num_items--;
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  match_glyph_data++;
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  return true;
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	}
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (skip == matcher_t::SKIP_NO)
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  return false;
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int idx;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protected:
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_apply_context_t *c;
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    matcher_t matcher;
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const USHORT *match_glyph_data;
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_items;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int end;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct skipping_backward_iterator_t
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline skipping_backward_iterator_t (hb_apply_context_t *c_,
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 unsigned int start_index_,
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 unsigned int num_items_,
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					 bool context_match = false) :
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					  idx (start_index_),
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					  c (c_),
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					  match_glyph_data (NULL),
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					  num_items (num_items_)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_lookup_props (c->lookup_props);
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!context_match)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	matcher.set_mask (c->lookup_mask);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void set_match_func (matcher_t::match_func_t match_func,
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				const void *match_data,
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				const USHORT glyph_data[])
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matcher.set_match_func (match_func, match_data);
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      match_glyph_data = glyph_data;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline bool has_no_chance (void) const { return unlikely (idx < num_items); }
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline void reject (void) { num_items++; }
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    inline bool prev (void)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert (num_items > 0);
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      while (!has_no_chance ())
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	idx--;
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	const hb_glyph_info_t &info = c->buffer->out_info[idx];
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (unlikely (skip == matcher_t::SKIP_YES))
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  continue;
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (match == matcher_t::MATCH_YES ||
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    (match == matcher_t::MATCH_MAYBE &&
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     skip == matcher_t::SKIP_NO))
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  num_items--;
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  match_glyph_data++;
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  return true;
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	}
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (skip == matcher_t::SKIP_NO)
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	  return false;
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int idx;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protected:
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_apply_context_t *c;
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    matcher_t matcher;
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const USHORT *match_glyph_data;
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_items;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  match_properties_mark (hb_codepoint_t  glyph,
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int    glyph_props,
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int    lookup_props) const
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If using mark filtering sets, the high short of
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * lookup_props has the set index.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookup_props & LookupFlag::UseMarkFilteringSet)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return gdef.mark_set_covers (lookup_props >> 16, glyph);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The second byte of lookup_props has the meaning
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * "ignore marks of attachment type different than
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the attachment type specified."
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookup_props & LookupFlag::MarkAttachmentType)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  match_properties (hb_codepoint_t  glyph,
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    unsigned int    glyph_props,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    unsigned int    lookup_props) const
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Not covered, if, for example, glyph class is ligature and
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * lookup_props includes LookupFlags::IgnoreLigatures
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return match_properties_mark (glyph, glyph_props, lookup_props);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  check_glyph_property (hb_glyph_info_t *info,
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			unsigned int  lookup_props) const
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int property;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    property = info->glyph_props();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return match_properties (info->codepoint, property, lookup_props);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (has_glyph_classes))
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (class_guess)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer->cur().glyph_props() = class_guess;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void output_glyph (hb_codepoint_t glyph_index,
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    unsigned int class_guess = 0) const
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_class (glyph_index, class_guess);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->output_glyph (glyph_index);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void replace_glyph (hb_codepoint_t glyph_index,
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     unsigned int class_guess = 0) const
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_class (glyph_index, class_guess);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->replace_glyph (glyph_index);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void replace_glyph_inplace (hb_codepoint_t glyph_index,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     unsigned int class_guess = 0) const
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_class (glyph_index, class_guess);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->cur().codepoint = glyph_index;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextClosureFuncs
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intersects_func_t intersects;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ContextCollectGlyphsFuncs
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  collect_glyphs_func_t collect;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextApplyFuncs
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  match_func_t match;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return glyphs->has (value);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return class_def.intersects_class (glyphs, value);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (data+coverage).intersects (glyphs);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool intersects_array (hb_closure_context_t *c,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     unsigned int count,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     const USHORT values[],
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     intersects_func_t intersects_func,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     const void *intersects_data)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < count; i++)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  glyphs->add (value);
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class_def.add_class (glyphs, value);
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  (data+coverage).add_coverage (glyphs);
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  hb_set_t *glyphs,
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  unsigned int count,
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  const USHORT values[],
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  collect_glyphs_func_t collect_func,
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  const void *collect_data)
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned int i = 0; i < count; i++)
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    collect_func (glyphs, values[i], collect_data);
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return glyph_id == value;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return class_def.get_class (glyph_id) == value;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool would_match_input (hb_would_apply_context_t *c,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      unsigned int count, /* Including the first glyph (not matched) */
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      const USHORT input[], /* Array of input values--start with second glyph */
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      match_func_t match_func,
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      const void *match_data)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (count != c->len)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 1; i < count; i++)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool match_input (hb_apply_context_t *c,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int count, /* Including the first glyph (not matched) */
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				const USHORT input[], /* Array of input values--start with second glyph */
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				match_func_t match_func,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				const void *match_data,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int *end_offset = NULL,
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				bool *p_is_mark_ligature = NULL,
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int *p_total_component_count = NULL)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_APPLY (NULL);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  skippy_iter.set_match_func (match_func, match_data, input);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This is perhaps the trickiest part of OpenType...  Remarks:
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * - If all components of the ligature were marks, we call this a mark ligature.
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   it as a ligature glyph.
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * - Ligatures cannot be formed across glyphs attached to different components
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.o
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   There is an exception to this: If a ligature tries ligating with marks that
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   belong to it itself, go ahead, assuming that the font designer knows what
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   they are doing (otherwise it can break Indic stuff when a matra wants to
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   ligate with a conjunct...)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int total_component_count = 0;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  total_component_count += get_lig_num_comps (c->buffer->cur());
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int first_lig_id = get_lig_id (c->buffer->cur());
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int first_lig_comp = get_lig_comp (c->buffer->cur());
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 1; i < count; i++)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!skippy_iter.next ()) return TRACE_RETURN (false);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (first_lig_id && first_lig_comp) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If first component was attached to a previous ligature component,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * all subsequent components should be attached to the same ligature
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * component, otherwise we shouldn't ligate them. */
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRACE_RETURN (false);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If first component was NOT attached to a previous ligature component,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * all subsequent components should also NOT be attached to any ligature
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * component, unless they are attached to the first component itself! */
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TRACE_RETURN (false);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (end_offset)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *end_offset = skippy_iter.idx - c->buffer->idx + 1;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p_is_mark_ligature)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *p_is_mark_ligature = is_mark_ligature;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p_total_component_count)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *p_total_component_count = total_component_count;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRACE_RETURN (true);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void ligate_input (hb_apply_context_t *c,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 unsigned int count, /* Including the first glyph (not matched) */
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 const USHORT input[], /* Array of input values--start with second glyph */
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 match_func_t match_func,
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 const void *match_data,
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 hb_codepoint_t lig_glyph,
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 bool is_mark_ligature,
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 unsigned int total_component_count)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  skippy_iter.set_match_func (match_func, match_data, input);
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (skippy_iter.has_no_chance ()) return;
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   the ligature to keep its old ligature id.  This will allow it to attach to
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   later, we don't want them to lose their ligature id/component, otherwise
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   GPOS will fail to correctly position the mark ligature on top of the
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   LAM,LAM,HEH ligature.  See:
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * - If a ligature is formed of components that some of which are also ligatures
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   themselves, and those ligature components had marks attached to *their*
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   components, we have to attach the marks to the new ligature component
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   positions!  Now *that*'s tricky!  And these marks may be following the
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   last component of the whole sequence, so we should loop forward looking
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   for them and update them.
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   the new ligature with a component value of 2.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   This in fact happened to a font...  See:
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int last_lig_id = get_lig_id (c->buffer->cur());
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int last_num_components = get_lig_num_comps (c->buffer->cur());
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int components_so_far = last_num_components;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_mark_ligature)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  c->replace_glyph (lig_glyph, klass);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 1; i < count; i++)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!skippy_iter.next ()) return;
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (c->buffer->idx < skippy_iter.idx)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!is_mark_ligature) {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int new_lig_comp = components_so_far - last_num_components +
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->buffer->next_glyph ();
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_lig_id = get_lig_id (c->buffer->cur());
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_num_components = get_lig_num_comps (c->buffer->cur());
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    components_so_far += last_num_components;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Skip the base glyph */
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->buffer->idx++;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_mark_ligature && last_lig_id) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Re-adjust components for any marks following. */
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (last_lig_id == get_lig_id (c->buffer->info[i])) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int new_lig_comp = components_so_far - last_num_components +
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	break;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool match_backtrack (hb_apply_context_t *c,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int count,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    const USHORT backtrack[],
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    match_func_t match_func,
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    const void *match_data)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_APPLY (NULL);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  skippy_iter.set_match_func (match_func, match_data, backtrack);
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < count; i++)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!skippy_iter.prev ())
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TRACE_RETURN (false);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRACE_RETURN (true);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool match_lookahead (hb_apply_context_t *c,
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int count,
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    const USHORT lookahead[],
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    match_func_t match_func,
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    const void *match_data,
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int offset)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_APPLY (NULL);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  skippy_iter.set_match_func (match_func, match_data, lookahead);
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < count; i++)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!skippy_iter.next ())
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TRACE_RETURN (false);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRACE_RETURN (true);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LookupRecord
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	sequenceIndex;		/* Index into current glyph
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * sequence--first glyph = 0 */
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupListIndex;	/* Lookup to apply to that
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * position--zero--based */
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (4);
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename context_t>
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void recurse_lookups (context_t *c,
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    unsigned int lookupCount,
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < lookupCount; i++)
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c->recurse (lookupRecord->lookupListIndex);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool apply_lookup (hb_apply_context_t *c,
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 unsigned int count, /* Including the first glyph */
926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 const USHORT input[], /* Array of input values--start with second glyph */
927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 match_func_t match_func,
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 const void *match_data,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 unsigned int lookupCount,
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_APPLY (NULL);
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int end = c->buffer->len;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (count == 0 || c->buffer->idx + count > end))
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (false);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* TODO We don't support lookupRecord arrays that are not increasing:
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *      Should be easy for in_place ones at least. */
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Note: If sublookup is reverse, it will underflow after the first loop
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * and we jump out of it.  Not entirely disastrous.  So we don't check
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * for reverse lookup here.
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
945c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
946c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
947c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  skippy_iter.set_match_func (match_func, match_data, input);
948c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint8_t syllable = c->buffer->cur().syllable();
949c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned int i = 0;
951c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (lookupCount && 0 == lookupRecord->sequenceIndex)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned int old_pos = c->buffer->idx;
954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Apply a lookup */
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool done = c->recurse (lookupRecord->lookupListIndex);
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    lookupRecord++;
959c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    lookupCount--;
960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Err, this is wrong if the lookup jumped over some glyphs */
961c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    i += c->buffer->idx - old_pos;
962c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!done)
964c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      goto not_applied;
965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Reinitialize iterator. */
968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i);
969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tmp.set_syllable (syllable);
970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      skippy_iter = tmp;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  not_applied:
976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* No lookup applied for this index */
977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    c->buffer->next_glyph ();
978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    i++;
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (i < count)
981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!skippy_iter.next ()) return TRACE_RETURN (true);
983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (c->buffer->idx < skippy_iter.idx)
984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      c->buffer->next_glyph ();
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookupCount && i == lookupRecord->sequenceIndex)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int old_pos = c->buffer->idx;
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Apply a lookup */
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool done = c->recurse (lookupRecord->lookupListIndex);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lookupRecord++;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lookupCount--;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Err, this is wrong if the lookup jumped over some glyphs */
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i += c->buffer->idx - old_pos;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!done)
999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	goto not_applied2;
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      else
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      {
1002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        /* Reinitialize iterator. */
1003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i);
1004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	tmp.set_syllable (syllable);
1005c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	skippy_iter = tmp;
1006c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    not_applied2:
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* No lookup applied for this index */
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->buffer->next_glyph ();
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRACE_RETURN (true);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Contextual lookups */
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextClosureLookupContext
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextClosureFuncs funcs;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *intersects_data;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ContextCollectGlyphsLookupContext
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContextCollectGlyphsFuncs funcs;
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const void *collect_data;
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextApplyLookupContext
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextApplyFuncs funcs;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *match_data;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void context_closure_lookup (hb_closure_context_t *c,
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int inputCount, /* Including the first glyph (not matched) */
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   const USHORT input[], /* Array of input values--start with second glyph */
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int lookupCount,
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   const LookupRecord lookupRecord[],
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   ContextClosureLookupContext &lookup_context)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (intersects_array (c,
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			inputCount ? inputCount - 1 : 0, input,
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			lookup_context.funcs.intersects, lookup_context.intersects_data))
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    recurse_lookups (c,
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		     lookupCount, lookupRecord);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						  unsigned int inputCount, /* Including the first glyph (not matched) */
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						  const USHORT input[], /* Array of input values--start with second glyph */
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						  unsigned int lookupCount,
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						  const LookupRecord lookupRecord[],
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						  ContextCollectGlyphsLookupContext &lookup_context)
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  collect_array (c, c->input,
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 inputCount ? inputCount - 1 : 0, input,
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 lookup_context.funcs.collect, lookup_context.collect_data);
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recurse_lookups (c,
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   lookupCount, lookupRecord);
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       unsigned int inputCount, /* Including the first glyph (not matched) */
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       const USHORT input[], /* Array of input values--start with second glyph */
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       unsigned int lookupCount HB_UNUSED,
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       const LookupRecord lookupRecord[] HB_UNUSED,
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       ContextApplyLookupContext &lookup_context)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return would_match_input (c,
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    inputCount, input,
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    lookup_context.funcs.match, lookup_context.match_data);
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool context_apply_lookup (hb_apply_context_t *c,
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 unsigned int inputCount, /* Including the first glyph (not matched) */
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 const USHORT input[], /* Array of input values--start with second glyph */
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 unsigned int lookupCount,
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 const LookupRecord lookupRecord[],
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 ContextApplyLookupContext &lookup_context)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return match_input (c,
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      inputCount, input,
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      lookup_context.funcs.match, lookup_context.match_data)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && apply_lookup (c,
1092c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		       inputCount, input,
1093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		       lookup_context.funcs.match, lookup_context.match_data,
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       lookupCount, lookupRecord);
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Rule
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_closure_lookup (c,
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    inputCount, input,
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    lookupCount, lookupRecord,
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    lookup_context);
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_collect_glyphs_lookup (c,
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   inputCount, input,
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   lookupCount, lookupRecord,
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   lookup_context);
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return inputCount.sanitize (c)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&& lookupCount.sanitize (c)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	&& c->check_range (input,
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   input[0].static_size * inputCount
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   + lookupRecordX[0].static_size * lookupCount);
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	inputCount;		/* Total number of glyphs in input
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * glyph sequence--includes the first
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * glyph */
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupCount;		/* Number of LookupRecords */
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	input[VAR];		/* Array of match inputs--start with
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * second glyph */
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * design order */
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RuleSet
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_rules = rule.len;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (this+rule[i]).closure (c, lookup_context);
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
11682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
11692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int num_rules = rule.len;
11702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (this+rule[i]).collect_glyphs (c, lookup_context);
11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_rules = rule.len;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((this+rule[i]).would_apply (c, lookup_context))
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (true);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (false);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_rules = rule.len;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((this+rule[i]).apply (c, lookup_context))
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (true);
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (false);
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule.sanitize (c, this));
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<Rule>
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rule;			/* Array of Rule tables
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * ordered by preference */
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (2, rule);
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextFormat1
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void closure (hb_closure_context_t *c) const
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Coverage &cov = (this+coverage);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextClosureLookupContext lookup_context = {
12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {intersects_glyph},
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = ruleSet.len;
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cov.intersects_coverage (c->glyphs, i)) {
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const RuleSet &rule_set = this+ruleSet[i];
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rule_set.closure (c, lookup_context);
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (this+coverage).add_coverage (c->input);
12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct ContextCollectGlyphsLookupContext lookup_context = {
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {collect_glyph},
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NULL
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = ruleSet.len;
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c) const
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextApplyLookupContext lookup_context = {
12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_glyph},
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const Coverage &get_coverage (void) const
12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return this+coverage;
12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool apply (hb_apply_context_t *c) const
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (index == NOT_COVERED))
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TRACE_RETURN (false);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RuleSet &rule_set = this+ruleSet[index];
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextApplyLookupContext lookup_context = {
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_glyph},
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.apply (c, lookup_context));
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
12812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier--format = 1 */
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Coverage>
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		coverage;		/* Offset to Coverage table--from
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * beginning of table */
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<RuleSet>
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ruleSet;		/* Array of RuleSet tables
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * ordered by Coverage Index */
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, ruleSet);
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextFormat2
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void closure (hb_closure_context_t *c) const
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(this+coverage).intersects (c->glyphs))
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &class_def = this+classDef;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextClosureLookupContext lookup_context = {
13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {intersects_class},
13102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &class_def
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = ruleSet.len;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (class_def.intersects_class (c->glyphs, i)) {
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const RuleSet &rule_set = this+ruleSet[i];
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rule_set.closure (c, lookup_context);
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (this+coverage).add_coverage (c->input);
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ClassDef &class_def = this+classDef;
13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct ContextCollectGlyphsLookupContext lookup_context = {
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {collect_class},
13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &class_def
13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
13312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = ruleSet.len;
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
13342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c) const
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &class_def = this+classDef;
13422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = class_def.get_class (c->glyphs[0]);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RuleSet &rule_set = this+ruleSet[index];
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextApplyLookupContext lookup_context = {
13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_class},
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &class_def
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const Coverage &get_coverage (void) const
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return this+coverage;
13542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool apply (hb_apply_context_t *c) const
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
13592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &class_def = this+classDef;
13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    index = class_def.get_class (c->buffer->cur().codepoint);
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RuleSet &rule_set = this+ruleSet[index];
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextApplyLookupContext lookup_context = {
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_class},
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &class_def
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.apply (c, lookup_context));
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier--format = 2 */
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Coverage>
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		coverage;		/* Offset to Coverage table--from
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * beginning of table */
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<ClassDef>
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		classDef;		/* Offset to glyph ClassDef table--from
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * beginning of table */
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<RuleSet>
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ruleSet;		/* Array of RuleSet tables
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * ordered by class */
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (8, ruleSet);
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ContextFormat3
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void closure (hb_closure_context_t *c) const
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(this+coverage[0]).intersects (c->glyphs))
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextClosureLookupContext lookup_context = {
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {intersects_coverage},
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_closure_lookup (c,
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    glyphCount, (const USHORT *) (coverage + 1),
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    lookupCount, lookupRecord,
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    lookup_context);
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
14142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (this+coverage[0]).add_coverage (c->input);
14162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct ContextCollectGlyphsLookupContext lookup_context = {
14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {collect_coverage},
14202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this
14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_collect_glyphs_lookup (c,
14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   glyphCount, (const USHORT *) (coverage + 1),
14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   lookupCount, lookupRecord,
14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   lookup_context);
14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c) const
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextApplyLookupContext lookup_context = {
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_coverage},
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const Coverage &get_coverage (void) const
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
14432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return this+coverage[0];
14442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool apply (hb_apply_context_t *c) const
14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
14482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
14492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = (this+coverage[0]).get_coverage (c->buffer->cur().codepoint);
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ContextApplyLookupContext lookup_context = {
14542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_coverage},
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
14612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!c->check_struct (this)) return TRACE_RETURN (false);
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = glyphCount;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier--format = 3 */
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	glyphCount;		/* Number of glyphs in the input glyph
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * sequence */
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupCount;		/* Number of LookupRecords */
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Coverage>
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		coverage[VAR];		/* Array of offsets to Coverage
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * table in glyph sequence order */
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * design order */
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Context
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
14872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename context_t>
1488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline typename context_t::return_t dispatch (context_t *c) const
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TRACE_DISPATCH (this);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
1492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 1: return TRACE_RETURN (c->dispatch (u.format1));
1493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 2: return TRACE_RETURN (c->dispatch (u.format2));
1494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 3: return TRACE_RETURN (c->dispatch (u.format3));
14952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:return TRACE_RETURN (c->default_return_value ());
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.sanitize (c));
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3: return TRACE_RETURN (u.format3.sanitize (c));
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;		/* Format identifier */
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextFormat1	format1;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextFormat2	format2;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextFormat3	format3;
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Chaining Contextual lookups */
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainContextClosureLookupContext
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextClosureFuncs funcs;
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *intersects_data[3];
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ChainContextCollectGlyphsLookupContext
15292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
15302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ContextCollectGlyphsFuncs funcs;
15312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const void *collect_data[3];
15322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
15332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainContextApplyLookupContext
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ContextApplyFuncs funcs;
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *match_data[3];
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void chain_context_closure_lookup (hb_closure_context_t *c,
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 unsigned int backtrackCount,
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 const USHORT backtrack[],
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 unsigned int inputCount, /* Including the first glyph (not matched) */
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 const USHORT input[], /* Array of input values--start with second glyph */
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 unsigned int lookaheadCount,
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 const USHORT lookahead[],
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 unsigned int lookupCount,
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 const LookupRecord lookupRecord[],
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 ChainContextClosureLookupContext &lookup_context)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (intersects_array (c,
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			backtrackCount, backtrack,
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			lookup_context.funcs.intersects, lookup_context.intersects_data[0])
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   && intersects_array (c,
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			inputCount ? inputCount - 1 : 0, input,
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			lookup_context.funcs.intersects, lookup_context.intersects_data[1])
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  && intersects_array (c,
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       lookaheadCount, lookahead,
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
15602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    recurse_lookups (c,
15612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		     lookupCount, lookupRecord);
15622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
15652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        unsigned int backtrackCount,
15662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        const USHORT backtrack[],
15672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        unsigned int inputCount, /* Including the first glyph (not matched) */
15682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        const USHORT input[], /* Array of input values--start with second glyph */
15692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        unsigned int lookaheadCount,
15702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        const USHORT lookahead[],
15712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        unsigned int lookupCount,
15722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        const LookupRecord lookupRecord[],
15732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						        ChainContextCollectGlyphsLookupContext &lookup_context)
15742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
15752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  collect_array (c, c->before,
15762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 backtrackCount, backtrack,
15772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 lookup_context.funcs.collect, lookup_context.collect_data[0]);
15782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  collect_array (c, c->input,
15792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 inputCount ? inputCount - 1 : 0, input,
15802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 lookup_context.funcs.collect, lookup_context.collect_data[1]);
15812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  collect_array (c, c->after,
15822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 lookaheadCount, lookahead,
15832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 lookup_context.funcs.collect, lookup_context.collect_data[2]);
15842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recurse_lookups (c,
15852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   lookupCount, lookupRecord);
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     unsigned int backtrackCount,
15902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						     const USHORT backtrack[] HB_UNUSED,
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     unsigned int inputCount, /* Including the first glyph (not matched) */
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     const USHORT input[], /* Array of input values--start with second glyph */
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     unsigned int lookaheadCount,
15942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						     const USHORT lookahead[] HB_UNUSED,
15952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						     unsigned int lookupCount HB_UNUSED,
15962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						     const LookupRecord lookupRecord[] HB_UNUSED,
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     ChainContextApplyLookupContext &lookup_context)
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && would_match_input (c,
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    inputCount, input,
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    lookup_context.funcs.match, lookup_context.match_data[1]);
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       unsigned int backtrackCount,
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       const USHORT backtrack[],
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       unsigned int inputCount, /* Including the first glyph (not matched) */
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       const USHORT input[], /* Array of input values--start with second glyph */
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       unsigned int lookaheadCount,
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       const USHORT lookahead[],
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       unsigned int lookupCount,
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       const LookupRecord lookupRecord[],
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       ChainContextApplyLookupContext &lookup_context)
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int lookahead_offset = 0;
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return match_input (c,
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      inputCount, input,
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      lookup_context.funcs.match, lookup_context.match_data[1],
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      &lookahead_offset)
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && match_backtrack (c,
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  backtrackCount, backtrack,
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  lookup_context.funcs.match, lookup_context.match_data[0])
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && match_lookahead (c,
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  lookaheadCount, lookahead,
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  lookup_context.funcs.match, lookup_context.match_data[2],
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  lookahead_offset)
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && apply_lookup (c,
1629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		       inputCount, input,
1630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		       lookup_context.funcs.match, lookup_context.match_data[1],
16312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		       lookupCount, lookupRecord);
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainRule
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
16382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chain_context_closure_lookup (c,
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  backtrack.len, backtrack.array,
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  input.len, input.array,
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  lookahead.len, lookahead.array,
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  lookup.len, lookup.array,
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  lookup_context);
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
16542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
16552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
16562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chain_context_collect_glyphs_lookup (c,
16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 backtrack.len, backtrack.array,
16582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 input.len, input.array,
16592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 lookahead.len, lookahead.array,
16602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 lookup.len, lookup.array,
16612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 lookup_context);
16622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
16632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
16662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (chain_context_would_apply_lookup (c,
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   backtrack.len, backtrack.array,
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   input.len, input.array,
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   lookahead.len, lookahead.array, lookup.len,
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   lookup.array, lookup_context));
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
16792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (chain_context_apply_lookup (c,
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     backtrack.len, backtrack.array,
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     input.len, input.array,
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     lookahead.len, lookahead.array, lookup.len,
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     lookup.array, lookup_context));
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
16912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!input.sanitize (c)) return TRACE_RETURN (false);
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (lookup.sanitize (c));
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<USHORT>
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		backtrack;		/* Array of backtracking values
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * (to be matched before the input
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * sequence) */
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeadlessArrayOf<USHORT>
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		inputX;			/* Array of input values (start with
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * second glyph) */
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<USHORT>
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lookaheadX;		/* Array of lookahead values's (to be
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * matched after the input sequence) */
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<LookupRecord>
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lookupX;		/* Array of LookupRecords--in
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * design order) */
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_MIN (8);
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainRuleSet
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
17232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_rules = rule.len;
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (this+rule[i]).closure (c, lookup_context);
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
17312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
17322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int num_rules = rule.len;
17332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (this+rule[i]).collect_glyphs (c, lookup_context);
17352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
17362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_rules = rule.len;
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((this+rule[i]).would_apply (c, lookup_context))
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (true);
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (false);
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
17502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_rules = rule.len;
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_rules; i++)
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((this+rule[i]).apply (c, lookup_context))
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TRACE_RETURN (true);
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (false);
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule.sanitize (c, this));
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<ChainRule>
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rule;			/* Array of ChainRule tables
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * ordered by preference */
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (2, rule);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainContextFormat1
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void closure (hb_closure_context_t *c) const
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
17762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Coverage &cov = (this+coverage);
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextClosureLookupContext lookup_context = {
17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {intersects_glyph},
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {NULL, NULL, NULL}
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = ruleSet.len;
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (cov.intersects_coverage (c->glyphs, i)) {
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const ChainRuleSet &rule_set = this+ruleSet[i];
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rule_set.closure (c, lookup_context);
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (this+coverage).add_coverage (c->input);
17962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct ChainContextCollectGlyphsLookupContext lookup_context = {
17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {collect_glyph},
17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {NULL, NULL, NULL}
18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = ruleSet.len;
18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
18042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c) const
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextApplyLookupContext lookup_context = {
18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_glyph},
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {NULL, NULL, NULL}
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const Coverage &get_coverage (void) const
18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return this+coverage;
18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool apply (hb_apply_context_t *c) const
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ChainRuleSet &rule_set = this+ruleSet[index];
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextApplyLookupContext lookup_context = {
18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_glyph},
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {NULL, NULL, NULL}
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.apply (c, lookup_context));
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
18392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier--format = 1 */
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Coverage>
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		coverage;		/* Offset to Coverage table--from
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * beginning of table */
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<ChainRuleSet>
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ruleSet;		/* Array of ChainRuleSet tables
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * ordered by Coverage Index */
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, ruleSet);
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainContextFormat2
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void closure (hb_closure_context_t *c) const
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(this+coverage).intersects (c->glyphs))
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &backtrack_class_def = this+backtrackClassDef;
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &input_class_def = this+inputClassDef;
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextClosureLookupContext lookup_context = {
18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {intersects_class},
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {&backtrack_class_def,
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       &input_class_def,
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       &lookahead_class_def}
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = ruleSet.len;
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (input_class_def.intersects_class (c->glyphs, i)) {
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const ChainRuleSet &rule_set = this+ruleSet[i];
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rule_set.closure (c, lookup_context);
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (this+coverage).add_coverage (c->input);
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ClassDef &backtrack_class_def = this+backtrackClassDef;
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ClassDef &input_class_def = this+inputClassDef;
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct ChainContextCollectGlyphsLookupContext lookup_context = {
18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {collect_class},
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {&backtrack_class_def,
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       &input_class_def,
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       &lookahead_class_def}
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = ruleSet.len;
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c) const
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ClassDef &backtrack_class_def = this+backtrackClassDef;
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &input_class_def = this+inputClassDef;
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = input_class_def.get_class (c->glyphs[0]);
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ChainRuleSet &rule_set = this+ruleSet[index];
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextApplyLookupContext lookup_context = {
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_class},
19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {&backtrack_class_def,
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       &input_class_def,
19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       &lookahead_class_def}
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const Coverage &get_coverage (void) const
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return this+coverage;
19252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool apply (hb_apply_context_t *c) const
19282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
19292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
19302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &backtrack_class_def = this+backtrackClassDef;
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &input_class_def = this+inputClassDef;
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    index = input_class_def.get_class (c->buffer->cur().codepoint);
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ChainRuleSet &rule_set = this+ruleSet[index];
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextApplyLookupContext lookup_context = {
19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_class},
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {&backtrack_class_def,
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       &input_class_def,
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       &lookahead_class_def}
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rule_set.apply (c, lookup_context));
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
19492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 ruleSet.sanitize (c, this));
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier--format = 2 */
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Coverage>
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		coverage;		/* Offset to Coverage table--from
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * beginning of table */
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<ClassDef>
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		backtrackClassDef;	/* Offset to glyph ClassDef table
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * containing backtrack sequence
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * data--from beginning of table */
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<ClassDef>
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		inputClassDef;		/* Offset to glyph ClassDef
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * table containing input sequence
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * data--from beginning of table */
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<ClassDef>
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lookaheadClassDef;	/* Offset to glyph ClassDef table
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * containing lookahead sequence
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * data--from beginning of table */
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<ChainRuleSet>
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ruleSet;		/* Array of ChainRuleSet tables
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * ordered by class */
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (12, ruleSet);
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainContextFormat3
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void closure (hb_closure_context_t *c) const
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_CLOSURE (this);
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(this+input[0]).intersects (c->glyphs))
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextClosureLookupContext lookup_context = {
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {intersects_coverage},
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {this, this, this}
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chain_context_closure_lookup (c,
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  backtrack.len, (const USHORT *) backtrack.array,
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  input.len, (const USHORT *) input.array + 1,
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  lookahead.len, (const USHORT *) lookahead.array,
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  lookup.len, lookup.array,
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  lookup_context);
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
20052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_COLLECT_GLYPHS (this);
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (this+input[0]).add_coverage (c->input);
20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
20112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
20122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct ChainContextCollectGlyphsLookupContext lookup_context = {
20132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {collect_coverage},
20142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {this, this, this}
20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    chain_context_collect_glyphs_lookup (c,
20172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 backtrack.len, (const USHORT *) backtrack.array,
20182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 input.len, (const USHORT *) input.array + 1,
20192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 lookahead.len, (const USHORT *) lookahead.array,
20202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 lookup.len, lookup.array,
20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 lookup_context);
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool would_apply (hb_would_apply_context_t *c) const
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
20262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_WOULD_APPLY (this);
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextApplyLookupContext lookup_context = {
20322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_coverage},
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {this, this, this}
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (chain_context_would_apply_lookup (c,
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   backtrack.len, (const USHORT *) backtrack.array,
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   input.len, (const USHORT *) input.array + 1,
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   lookahead.len, (const USHORT *) lookahead.array,
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)							   lookup.len, lookup.array, lookup_context));
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const Coverage &get_coverage (void) const
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
20452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return this+input[0];
20462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool apply (hb_apply_context_t *c) const
20492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
20502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_APPLY (this);
20512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
20522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ChainContextApplyLookupContext lookup_context = {
20592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {match_coverage},
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {this, this, this}
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (chain_context_apply_lookup (c,
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     backtrack.len, (const USHORT *) backtrack.array,
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     input.len, (const USHORT *) input.array + 1,
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     lookahead.len, (const USHORT *) lookahead.array,
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						     lookup.len, lookup.array, lookup_context));
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
20702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!input.sanitize (c, this)) return TRACE_RETURN (false);
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (lookup.sanitize (c));
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier--format = 3 */
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<Coverage>
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		backtrack;		/* Array of coverage tables
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * in backtracking sequence, in  glyph
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * sequence order */
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<Coverage>
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		inputX		;	/* Array of coverage
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * tables in input sequence, in glyph
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * sequence order */
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetArrayOf<Coverage>
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lookaheadX;		/* Array of coverage tables
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * in lookahead sequence, in glyph
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * sequence order */
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<LookupRecord>
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lookupX;		/* Array of LookupRecords--in
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * design order) */
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_MIN (10);
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChainContext
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
21032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename context_t>
2104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline typename context_t::return_t dispatch (context_t *c) const
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TRACE_DISPATCH (this);
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
2108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 1: return TRACE_RETURN (c->dispatch (u.format1));
2109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 2: return TRACE_RETURN (c->dispatch (u.format2));
2110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 3: return TRACE_RETURN (c->dispatch (u.format3));
21112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:return TRACE_RETURN (c->default_return_value ());
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
21162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.sanitize (c));
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3: return TRACE_RETURN (u.format3.sanitize (c));
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;	/* Format identifier */
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChainContextFormat1	format1;
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChainContextFormat2	format2;
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChainContextFormat3	format3;
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionFormat1
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_type (void) const { return extensionLookupType; }
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_offset (void) const { return extensionOffset; }
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
21422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	format;			/* Format identifier. Set to 1. */
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	extensionLookupType;	/* Lookup type of subtable referenced
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * by ExtensionOffset (i.e. the
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * extension subtable). */
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG		extensionOffset;	/* Offset to the extension subtable,
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * of lookup type subtable. */
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (8);
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <typename T>
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Extension
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_type (void) const
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.get_type ();
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return 0;
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_offset (void) const
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.get_offset ();
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return 0;
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename X>
21762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const X& get_subtable (void) const
21772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
21782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int offset = get_offset ();
21792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
21802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return StructAtOffset<typename T::LookupSubTable> (this, offset);
21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
21822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename context_t>
2184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  inline typename context_t::return_t dispatch (context_t *c) const
21852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
21872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize_self (hb_sanitize_context_t *c) {
21902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
21992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
22002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!sanitize_self (c)) return TRACE_RETURN (false);
22012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int offset = get_offset ();
22022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!offset)) return TRACE_RETURN (true);
22032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
22042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
22052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;		/* Format identifier */
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionFormat1	format1;
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * GSUB/GPOS Common
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct GSUBGPOS
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const hb_tag_t GSUBTag	= HB_OT_TAG_GSUB;
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const hb_tag_t GPOSTag	= HB_OT_TAG_GPOS;
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_script_count (void) const
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+scriptList).len; }
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Tag& get_script_tag (unsigned int i) const
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+scriptList).get_tag (i); }
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_script_tags (unsigned int start_offset,
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       unsigned int *script_count /* IN/OUT */,
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       hb_tag_t     *script_tags /* OUT */) const
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Script& get_script (unsigned int i) const
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+scriptList)[i]; }
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+scriptList).find_index (tag, index); }
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_feature_count (void) const
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+featureList).len; }
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Tag& get_feature_tag (unsigned int i) const
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+featureList).get_tag (i); }
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_feature_tags (unsigned int start_offset,
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					unsigned int *feature_count /* IN/OUT */,
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					hb_tag_t     *feature_tags /* OUT */) const
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Feature& get_feature (unsigned int i) const
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+featureList)[i]; }
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+featureList).find_index (tag, index); }
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lookup_count (void) const
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+lookupList).len; }
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Lookup& get_lookup (unsigned int i) const
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return (this+lookupList)[i]; }
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
22552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 scriptList.sanitize (c, this) &&
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 featureList.sanitize (c, this) &&
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 lookupList.sanitize (c, this));
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FixedVersion	version;	/* Version of the GSUB/GPOS table--initially set
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * to 0x00010000 */
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<ScriptList>
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		scriptList;  	/* ScriptList table */
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<FeatureList>
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		featureList; 	/* FeatureList table */
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<LookupList>
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lookupList; 	/* LookupList table */
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (10);
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} /* namespace OT */
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
2280