gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos-private.hh	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2297 @@
     1.4 +/*
     1.5 + * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
     1.6 + * Copyright © 2010,2012  Google, Inc.
     1.7 + *
     1.8 + *  This is part of HarfBuzz, a text shaping library.
     1.9 + *
    1.10 + * Permission is hereby granted, without written agreement and without
    1.11 + * license or royalty fees, to use, copy, modify, and distribute this
    1.12 + * software and its documentation for any purpose, provided that the
    1.13 + * above copyright notice and the following two paragraphs appear in
    1.14 + * all copies of this software.
    1.15 + *
    1.16 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    1.17 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    1.18 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    1.19 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    1.20 + * DAMAGE.
    1.21 + *
    1.22 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    1.23 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    1.24 + * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    1.25 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    1.26 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    1.27 + *
    1.28 + * Red Hat Author(s): Behdad Esfahbod
    1.29 + * Google Author(s): Behdad Esfahbod
    1.30 + */
    1.31 +
    1.32 +#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
    1.33 +#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
    1.34 +
    1.35 +#include "hb-buffer-private.hh"
    1.36 +#include "hb-ot-layout-gdef-table.hh"
    1.37 +#include "hb-set-private.hh"
    1.38 +
    1.39 +
    1.40 +namespace OT {
    1.41 +
    1.42 +
    1.43 +
    1.44 +#define TRACE_DISPATCH(this) \
    1.45 +	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
    1.46 +	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
    1.47 +	 "");
    1.48 +
    1.49 +#ifndef HB_DEBUG_CLOSURE
    1.50 +#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
    1.51 +#endif
    1.52 +
    1.53 +#define TRACE_CLOSURE(this) \
    1.54 +	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
    1.55 +	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
    1.56 +	 "");
    1.57 +
    1.58 +struct hb_closure_context_t
    1.59 +{
    1.60 +  inline const char *get_name (void) { return "CLOSURE"; }
    1.61 +  static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
    1.62 +  typedef hb_void_t return_t;
    1.63 +  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
    1.64 +  template <typename T>
    1.65 +  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
    1.66 +  static return_t default_return_value (void) { return HB_VOID; }
    1.67 +  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
    1.68 +  return_t recurse (unsigned int lookup_index)
    1.69 +  {
    1.70 +    if (unlikely (nesting_level_left == 0 || !recurse_func))
    1.71 +      return default_return_value ();
    1.72 +
    1.73 +    nesting_level_left--;
    1.74 +    recurse_func (this, lookup_index);
    1.75 +    nesting_level_left++;
    1.76 +    return HB_VOID;
    1.77 +  }
    1.78 +
    1.79 +  hb_face_t *face;
    1.80 +  hb_set_t *glyphs;
    1.81 +  recurse_func_t recurse_func;
    1.82 +  unsigned int nesting_level_left;
    1.83 +  unsigned int debug_depth;
    1.84 +
    1.85 +  hb_closure_context_t (hb_face_t *face_,
    1.86 +			hb_set_t *glyphs_,
    1.87 +		        unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
    1.88 +			  face (face_),
    1.89 +			  glyphs (glyphs_),
    1.90 +			  recurse_func (NULL),
    1.91 +			  nesting_level_left (nesting_level_left_),
    1.92 +			  debug_depth (0) {}
    1.93 +
    1.94 +  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
    1.95 +};
    1.96 +
    1.97 +
    1.98 +
    1.99 +#ifndef HB_DEBUG_WOULD_APPLY
   1.100 +#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
   1.101 +#endif
   1.102 +
   1.103 +#define TRACE_WOULD_APPLY(this) \
   1.104 +	hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
   1.105 +	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
   1.106 +	 "%d glyphs", c->len);
   1.107 +
   1.108 +struct hb_would_apply_context_t
   1.109 +{
   1.110 +  inline const char *get_name (void) { return "WOULD_APPLY"; }
   1.111 +  static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
   1.112 +  typedef bool return_t;
   1.113 +  template <typename T>
   1.114 +  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
   1.115 +  static return_t default_return_value (void) { return false; }
   1.116 +  bool stop_sublookup_iteration (return_t r) const { return r; }
   1.117 +
   1.118 +  hb_face_t *face;
   1.119 +  const hb_codepoint_t *glyphs;
   1.120 +  unsigned int len;
   1.121 +  bool zero_context;
   1.122 +  unsigned int debug_depth;
   1.123 +
   1.124 +  hb_would_apply_context_t (hb_face_t *face_,
   1.125 +			    const hb_codepoint_t *glyphs_,
   1.126 +			    unsigned int len_,
   1.127 +			    bool zero_context_) :
   1.128 +			      face (face_),
   1.129 +			      glyphs (glyphs_),
   1.130 +			      len (len_),
   1.131 +			      zero_context (zero_context_),
   1.132 +			      debug_depth (0) {}
   1.133 +};
   1.134 +
   1.135 +
   1.136 +
   1.137 +#ifndef HB_DEBUG_COLLECT_GLYPHS
   1.138 +#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
   1.139 +#endif
   1.140 +
   1.141 +#define TRACE_COLLECT_GLYPHS(this) \
   1.142 +	hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
   1.143 +	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
   1.144 +	 "");
   1.145 +
   1.146 +struct hb_collect_glyphs_context_t
   1.147 +{
   1.148 +  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
   1.149 +  static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
   1.150 +  typedef hb_void_t return_t;
   1.151 +  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
   1.152 +  template <typename T>
   1.153 +  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
   1.154 +  static return_t default_return_value (void) { return HB_VOID; }
   1.155 +  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
   1.156 +  return_t recurse (unsigned int lookup_index)
   1.157 +  {
   1.158 +    if (unlikely (nesting_level_left == 0 || !recurse_func))
   1.159 +      return default_return_value ();
   1.160 +
   1.161 +    /* Note that GPOS sets recurse_func to NULL already, so it doesn't get
   1.162 +     * past the previous check.  For GSUB, we only want to collect the output
   1.163 +     * glyphs in the recursion.  If output is not requested, we can go home now.
   1.164 +     *
   1.165 +     * Note further, that the above is not exactly correct.  A recursed lookup
   1.166 +     * is allowed to match input that is not matched in the context, but that's
   1.167 +     * not how most fonts are built.  It's possible to relax that and recurse
   1.168 +     * with all sets here if it proves to be an issue.
   1.169 +     */
   1.170 +
   1.171 +    if (output == hb_set_get_empty ())
   1.172 +      return HB_VOID;
   1.173 +
   1.174 +    hb_set_t *old_before = before;
   1.175 +    hb_set_t *old_input  = input;
   1.176 +    hb_set_t *old_after  = after;
   1.177 +    before = input = after = hb_set_get_empty ();
   1.178 +
   1.179 +    nesting_level_left--;
   1.180 +    recurse_func (this, lookup_index);
   1.181 +    nesting_level_left++;
   1.182 +
   1.183 +    before = old_before;
   1.184 +    input  = old_input;
   1.185 +    after  = old_after;
   1.186 +
   1.187 +    return HB_VOID;
   1.188 +  }
   1.189 +
   1.190 +  hb_face_t *face;
   1.191 +  hb_set_t *before;
   1.192 +  hb_set_t *input;
   1.193 +  hb_set_t *after;
   1.194 +  hb_set_t *output;
   1.195 +  recurse_func_t recurse_func;
   1.196 +  unsigned int nesting_level_left;
   1.197 +  unsigned int debug_depth;
   1.198 +
   1.199 +  hb_collect_glyphs_context_t (hb_face_t *face_,
   1.200 +			       hb_set_t  *glyphs_before, /* OUT. May be NULL */
   1.201 +			       hb_set_t  *glyphs_input,  /* OUT. May be NULL */
   1.202 +			       hb_set_t  *glyphs_after,  /* OUT. May be NULL */
   1.203 +			       hb_set_t  *glyphs_output, /* OUT. May be NULL */
   1.204 +			       unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
   1.205 +			      face (face_),
   1.206 +			      before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
   1.207 +			      input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
   1.208 +			      after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
   1.209 +			      output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
   1.210 +			      recurse_func (NULL),
   1.211 +			      nesting_level_left (nesting_level_left_),
   1.212 +			      debug_depth (0) {}
   1.213 +
   1.214 +  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
   1.215 +};
   1.216 +
   1.217 +
   1.218 +
   1.219 +struct hb_get_coverage_context_t
   1.220 +{
   1.221 +  inline const char *get_name (void) { return "GET_COVERAGE"; }
   1.222 +  static const unsigned int max_debug_depth = 0;
   1.223 +  typedef const Coverage &return_t;
   1.224 +  template <typename T>
   1.225 +  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
   1.226 +  static return_t default_return_value (void) { return Null(Coverage); }
   1.227 +
   1.228 +  hb_get_coverage_context_t (void) :
   1.229 +			    debug_depth (0) {}
   1.230 +
   1.231 +  unsigned int debug_depth;
   1.232 +};
   1.233 +
   1.234 +
   1.235 +
   1.236 +#ifndef HB_DEBUG_APPLY
   1.237 +#define HB_DEBUG_APPLY (HB_DEBUG+0)
   1.238 +#endif
   1.239 +
   1.240 +#define TRACE_APPLY(this) \
   1.241 +	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
   1.242 +	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
   1.243 +	 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
   1.244 +
   1.245 +struct hb_apply_context_t
   1.246 +{
   1.247 +  inline const char *get_name (void) { return "APPLY"; }
   1.248 +  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
   1.249 +  typedef bool return_t;
   1.250 +  typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
   1.251 +  template <typename T>
   1.252 +  inline return_t dispatch (const T &obj) { return obj.apply (this); }
   1.253 +  static return_t default_return_value (void) { return false; }
   1.254 +  bool stop_sublookup_iteration (return_t r) const { return r; }
   1.255 +  return_t recurse (unsigned int lookup_index)
   1.256 +  {
   1.257 +    if (unlikely (nesting_level_left == 0 || !recurse_func))
   1.258 +      return default_return_value ();
   1.259 +
   1.260 +    nesting_level_left--;
   1.261 +    bool ret = recurse_func (this, lookup_index);
   1.262 +    nesting_level_left++;
   1.263 +    return ret;
   1.264 +  }
   1.265 +
   1.266 +  unsigned int table_index; /* GSUB/GPOS */
   1.267 +  hb_font_t *font;
   1.268 +  hb_face_t *face;
   1.269 +  hb_buffer_t *buffer;
   1.270 +  hb_direction_t direction;
   1.271 +  hb_mask_t lookup_mask;
   1.272 +  bool auto_zwj;
   1.273 +  recurse_func_t recurse_func;
   1.274 +  unsigned int nesting_level_left;
   1.275 +  unsigned int lookup_props;
   1.276 +  const GDEF &gdef;
   1.277 +  bool has_glyph_classes;
   1.278 +  unsigned int debug_depth;
   1.279 +
   1.280 +
   1.281 +  hb_apply_context_t (unsigned int table_index_,
   1.282 +		      hb_font_t *font_,
   1.283 +		      hb_buffer_t *buffer_) :
   1.284 +			table_index (table_index_),
   1.285 +			font (font_), face (font->face), buffer (buffer_),
   1.286 +			direction (buffer_->props.direction),
   1.287 +			lookup_mask (1),
   1.288 +			auto_zwj (true),
   1.289 +			recurse_func (NULL),
   1.290 +			nesting_level_left (MAX_NESTING_LEVEL),
   1.291 +			lookup_props (0),
   1.292 +			gdef (*hb_ot_layout_from_face (face)->gdef),
   1.293 +			has_glyph_classes (gdef.has_glyph_classes ()),
   1.294 +			debug_depth (0) {}
   1.295 +
   1.296 +  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
   1.297 +  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
   1.298 +  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
   1.299 +  inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
   1.300 +  inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
   1.301 +
   1.302 +  struct matcher_t
   1.303 +  {
   1.304 +    inline matcher_t (void) :
   1.305 +	     lookup_props (0),
   1.306 +	     ignore_zwnj (false),
   1.307 +	     ignore_zwj (false),
   1.308 +	     mask (-1),
   1.309 +#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
   1.310 +	     syllable arg1(0),
   1.311 +#undef arg1
   1.312 +	     match_func (NULL),
   1.313 +	     match_data (NULL) {};
   1.314 +
   1.315 +    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
   1.316 +
   1.317 +    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
   1.318 +    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
   1.319 +    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
   1.320 +    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
   1.321 +    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
   1.322 +    inline void set_match_func (match_func_t match_func_,
   1.323 +				const void *match_data_)
   1.324 +    { match_func = match_func_; match_data = match_data_; }
   1.325 +
   1.326 +    enum may_match_t {
   1.327 +      MATCH_NO,
   1.328 +      MATCH_YES,
   1.329 +      MATCH_MAYBE
   1.330 +    };
   1.331 +
   1.332 +    inline may_match_t may_match (const hb_glyph_info_t &info,
   1.333 +				  const USHORT          *glyph_data) const
   1.334 +    {
   1.335 +      if (!(info.mask & mask) ||
   1.336 +	  (syllable && syllable != info.syllable ()))
   1.337 +	return MATCH_NO;
   1.338 +
   1.339 +      if (match_func)
   1.340 +        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
   1.341 +
   1.342 +      return MATCH_MAYBE;
   1.343 +    }
   1.344 +
   1.345 +    enum may_skip_t {
   1.346 +      SKIP_NO,
   1.347 +      SKIP_YES,
   1.348 +      SKIP_MAYBE
   1.349 +    };
   1.350 +
   1.351 +    inline may_skip_t
   1.352 +    may_skip (const hb_apply_context_t *c,
   1.353 +	      const hb_glyph_info_t    &info) const
   1.354 +    {
   1.355 +      unsigned int property;
   1.356 +
   1.357 +      property = _hb_glyph_info_get_glyph_props (&info);
   1.358 +
   1.359 +      if (!c->match_properties (info.codepoint, property, lookup_props))
   1.360 +	return SKIP_YES;
   1.361 +
   1.362 +      if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
   1.363 +		    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
   1.364 +		    (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
   1.365 +		    !_hb_glyph_info_ligated (&info)))
   1.366 +	return SKIP_MAYBE;
   1.367 +
   1.368 +      return SKIP_NO;
   1.369 +    }
   1.370 +
   1.371 +    protected:
   1.372 +    unsigned int lookup_props;
   1.373 +    bool ignore_zwnj;
   1.374 +    bool ignore_zwj;
   1.375 +    hb_mask_t mask;
   1.376 +    uint8_t syllable;
   1.377 +    match_func_t match_func;
   1.378 +    const void *match_data;
   1.379 +  };
   1.380 +
   1.381 +  struct skipping_forward_iterator_t
   1.382 +  {
   1.383 +    inline skipping_forward_iterator_t (hb_apply_context_t *c_,
   1.384 +					unsigned int start_index_,
   1.385 +					unsigned int num_items_,
   1.386 +					bool context_match = false) :
   1.387 +					 idx (start_index_),
   1.388 +					 c (c_),
   1.389 +					 match_glyph_data (NULL),
   1.390 +					 num_items (num_items_),
   1.391 +					 end (c->buffer->len)
   1.392 +    {
   1.393 +      matcher.set_lookup_props (c->lookup_props);
   1.394 +      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
   1.395 +      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
   1.396 +      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
   1.397 +      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
   1.398 +      if (!context_match)
   1.399 +	matcher.set_mask (c->lookup_mask);
   1.400 +      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
   1.401 +    }
   1.402 +    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
   1.403 +    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
   1.404 +    inline void set_match_func (matcher_t::match_func_t match_func,
   1.405 +				const void *match_data,
   1.406 +				const USHORT glyph_data[])
   1.407 +    {
   1.408 +      matcher.set_match_func (match_func, match_data);
   1.409 +      match_glyph_data = glyph_data;
   1.410 +    }
   1.411 +
   1.412 +    inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); }
   1.413 +    inline void reject (void) { num_items++; match_glyph_data--; }
   1.414 +    inline bool next (void)
   1.415 +    {
   1.416 +      assert (num_items > 0);
   1.417 +      while (!has_no_chance ())
   1.418 +      {
   1.419 +	idx++;
   1.420 +	const hb_glyph_info_t &info = c->buffer->info[idx];
   1.421 +
   1.422 +	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
   1.423 +	if (unlikely (skip == matcher_t::SKIP_YES))
   1.424 +	  continue;
   1.425 +
   1.426 +	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
   1.427 +	if (match == matcher_t::MATCH_YES ||
   1.428 +	    (match == matcher_t::MATCH_MAYBE &&
   1.429 +	     skip == matcher_t::SKIP_NO))
   1.430 +	{
   1.431 +	  num_items--;
   1.432 +	  match_glyph_data++;
   1.433 +	  return true;
   1.434 +	}
   1.435 +
   1.436 +	if (skip == matcher_t::SKIP_NO)
   1.437 +	  return false;
   1.438 +      }
   1.439 +      return false;
   1.440 +    }
   1.441 +
   1.442 +    unsigned int idx;
   1.443 +    protected:
   1.444 +    hb_apply_context_t *c;
   1.445 +    matcher_t matcher;
   1.446 +    const USHORT *match_glyph_data;
   1.447 +
   1.448 +    unsigned int num_items;
   1.449 +    unsigned int end;
   1.450 +  };
   1.451 +
   1.452 +  struct skipping_backward_iterator_t
   1.453 +  {
   1.454 +    inline skipping_backward_iterator_t (hb_apply_context_t *c_,
   1.455 +					 unsigned int start_index_,
   1.456 +					 unsigned int num_items_,
   1.457 +					 bool context_match = false) :
   1.458 +					  idx (start_index_),
   1.459 +					  c (c_),
   1.460 +					  match_glyph_data (NULL),
   1.461 +					  num_items (num_items_)
   1.462 +    {
   1.463 +      matcher.set_lookup_props (c->lookup_props);
   1.464 +      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
   1.465 +      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
   1.466 +      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
   1.467 +      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
   1.468 +      if (!context_match)
   1.469 +	matcher.set_mask (c->lookup_mask);
   1.470 +      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
   1.471 +    }
   1.472 +    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
   1.473 +    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
   1.474 +    inline void set_match_func (matcher_t::match_func_t match_func,
   1.475 +				const void *match_data,
   1.476 +				const USHORT glyph_data[])
   1.477 +    {
   1.478 +      matcher.set_match_func (match_func, match_data);
   1.479 +      match_glyph_data = glyph_data;
   1.480 +    }
   1.481 +
   1.482 +    inline bool has_no_chance (void) const { return unlikely (idx < num_items); }
   1.483 +    inline void reject (void) { num_items++; }
   1.484 +    inline bool prev (void)
   1.485 +    {
   1.486 +      assert (num_items > 0);
   1.487 +      while (!has_no_chance ())
   1.488 +      {
   1.489 +	idx--;
   1.490 +	const hb_glyph_info_t &info = c->buffer->out_info[idx];
   1.491 +
   1.492 +	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
   1.493 +
   1.494 +	if (unlikely (skip == matcher_t::SKIP_YES))
   1.495 +	  continue;
   1.496 +
   1.497 +	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
   1.498 +	if (match == matcher_t::MATCH_YES ||
   1.499 +	    (match == matcher_t::MATCH_MAYBE &&
   1.500 +	     skip == matcher_t::SKIP_NO))
   1.501 +	{
   1.502 +	  num_items--;
   1.503 +	  match_glyph_data++;
   1.504 +	  return true;
   1.505 +	}
   1.506 +
   1.507 +	if (skip == matcher_t::SKIP_NO)
   1.508 +	  return false;
   1.509 +      }
   1.510 +      return false;
   1.511 +    }
   1.512 +
   1.513 +    unsigned int idx;
   1.514 +    protected:
   1.515 +    hb_apply_context_t *c;
   1.516 +    matcher_t matcher;
   1.517 +    const USHORT *match_glyph_data;
   1.518 +
   1.519 +    unsigned int num_items;
   1.520 +  };
   1.521 +
   1.522 +  inline bool
   1.523 +  match_properties_mark (hb_codepoint_t  glyph,
   1.524 +			 unsigned int    glyph_props,
   1.525 +			 unsigned int    lookup_props) const
   1.526 +  {
   1.527 +    /* If using mark filtering sets, the high short of
   1.528 +     * lookup_props has the set index.
   1.529 +     */
   1.530 +    if (lookup_props & LookupFlag::UseMarkFilteringSet)
   1.531 +      return gdef.mark_set_covers (lookup_props >> 16, glyph);
   1.532 +
   1.533 +    /* The second byte of lookup_props has the meaning
   1.534 +     * "ignore marks of attachment type different than
   1.535 +     * the attachment type specified."
   1.536 +     */
   1.537 +    if (lookup_props & LookupFlag::MarkAttachmentType)
   1.538 +      return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
   1.539 +
   1.540 +    return true;
   1.541 +  }
   1.542 +
   1.543 +  inline bool
   1.544 +  match_properties (hb_codepoint_t  glyph,
   1.545 +		    unsigned int    glyph_props,
   1.546 +		    unsigned int    lookup_props) const
   1.547 +  {
   1.548 +    /* Not covered, if, for example, glyph class is ligature and
   1.549 +     * lookup_props includes LookupFlags::IgnoreLigatures
   1.550 +     */
   1.551 +    if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
   1.552 +      return false;
   1.553 +
   1.554 +    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
   1.555 +      return match_properties_mark (glyph, glyph_props, lookup_props);
   1.556 +
   1.557 +    return true;
   1.558 +  }
   1.559 +
   1.560 +  inline bool
   1.561 +  check_glyph_property (hb_glyph_info_t *info,
   1.562 +			unsigned int  lookup_props) const
   1.563 +  {
   1.564 +    unsigned int property;
   1.565 +
   1.566 +    property = _hb_glyph_info_get_glyph_props (info);
   1.567 +
   1.568 +    return match_properties (info->codepoint, property, lookup_props);
   1.569 +  }
   1.570 +
   1.571 +  inline void _set_glyph_props (hb_codepoint_t glyph_index,
   1.572 +			  unsigned int class_guess = 0,
   1.573 +			  bool ligature = false) const
   1.574 +  {
   1.575 +    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
   1.576 +			  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
   1.577 +    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
   1.578 +    if (ligature)
   1.579 +      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
   1.580 +    if (likely (has_glyph_classes))
   1.581 +      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
   1.582 +    else if (class_guess)
   1.583 +      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
   1.584 +  }
   1.585 +
   1.586 +  inline void replace_glyph (hb_codepoint_t glyph_index) const
   1.587 +  {
   1.588 +    _set_glyph_props (glyph_index);
   1.589 +    buffer->replace_glyph (glyph_index);
   1.590 +  }
   1.591 +  inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
   1.592 +  {
   1.593 +    _set_glyph_props (glyph_index);
   1.594 +    buffer->cur().codepoint = glyph_index;
   1.595 +  }
   1.596 +  inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
   1.597 +					   unsigned int class_guess) const
   1.598 +  {
   1.599 +    _set_glyph_props (glyph_index, class_guess, true);
   1.600 +    buffer->replace_glyph (glyph_index);
   1.601 +  }
   1.602 +  inline void output_glyph (hb_codepoint_t glyph_index,
   1.603 +			    unsigned int class_guess) const
   1.604 +  {
   1.605 +    _set_glyph_props (glyph_index, class_guess);
   1.606 +    buffer->output_glyph (glyph_index);
   1.607 +  }
   1.608 +};
   1.609 +
   1.610 +
   1.611 +
   1.612 +typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
   1.613 +typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
   1.614 +typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
   1.615 +
   1.616 +struct ContextClosureFuncs
   1.617 +{
   1.618 +  intersects_func_t intersects;
   1.619 +};
   1.620 +struct ContextCollectGlyphsFuncs
   1.621 +{
   1.622 +  collect_glyphs_func_t collect;
   1.623 +};
   1.624 +struct ContextApplyFuncs
   1.625 +{
   1.626 +  match_func_t match;
   1.627 +};
   1.628 +
   1.629 +
   1.630 +static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
   1.631 +{
   1.632 +  return glyphs->has (value);
   1.633 +}
   1.634 +static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
   1.635 +{
   1.636 +  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   1.637 +  return class_def.intersects_class (glyphs, value);
   1.638 +}
   1.639 +static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
   1.640 +{
   1.641 +  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   1.642 +  return (data+coverage).intersects (glyphs);
   1.643 +}
   1.644 +
   1.645 +static inline bool intersects_array (hb_closure_context_t *c,
   1.646 +				     unsigned int count,
   1.647 +				     const USHORT values[],
   1.648 +				     intersects_func_t intersects_func,
   1.649 +				     const void *intersects_data)
   1.650 +{
   1.651 +  for (unsigned int i = 0; i < count; i++)
   1.652 +    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
   1.653 +      return false;
   1.654 +  return true;
   1.655 +}
   1.656 +
   1.657 +
   1.658 +static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
   1.659 +{
   1.660 +  glyphs->add (value);
   1.661 +}
   1.662 +static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
   1.663 +{
   1.664 +  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   1.665 +  class_def.add_class (glyphs, value);
   1.666 +}
   1.667 +static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
   1.668 +{
   1.669 +  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   1.670 +  (data+coverage).add_coverage (glyphs);
   1.671 +}
   1.672 +static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
   1.673 +				  hb_set_t *glyphs,
   1.674 +				  unsigned int count,
   1.675 +				  const USHORT values[],
   1.676 +				  collect_glyphs_func_t collect_func,
   1.677 +				  const void *collect_data)
   1.678 +{
   1.679 +  for (unsigned int i = 0; i < count; i++)
   1.680 +    collect_func (glyphs, values[i], collect_data);
   1.681 +}
   1.682 +
   1.683 +
   1.684 +static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
   1.685 +{
   1.686 +  return glyph_id == value;
   1.687 +}
   1.688 +static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
   1.689 +{
   1.690 +  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   1.691 +  return class_def.get_class (glyph_id) == value;
   1.692 +}
   1.693 +static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
   1.694 +{
   1.695 +  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   1.696 +  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
   1.697 +}
   1.698 +
   1.699 +static inline bool would_match_input (hb_would_apply_context_t *c,
   1.700 +				      unsigned int count, /* Including the first glyph (not matched) */
   1.701 +				      const USHORT input[], /* Array of input values--start with second glyph */
   1.702 +				      match_func_t match_func,
   1.703 +				      const void *match_data)
   1.704 +{
   1.705 +  if (count != c->len)
   1.706 +    return false;
   1.707 +
   1.708 +  for (unsigned int i = 1; i < count; i++)
   1.709 +    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
   1.710 +      return false;
   1.711 +
   1.712 +  return true;
   1.713 +}
   1.714 +static inline bool match_input (hb_apply_context_t *c,
   1.715 +				unsigned int count, /* Including the first glyph (not matched) */
   1.716 +				const USHORT input[], /* Array of input values--start with second glyph */
   1.717 +				match_func_t match_func,
   1.718 +				const void *match_data,
   1.719 +				unsigned int *end_offset,
   1.720 +				unsigned int match_positions[MAX_CONTEXT_LENGTH],
   1.721 +				bool *p_is_mark_ligature = NULL,
   1.722 +				unsigned int *p_total_component_count = NULL)
   1.723 +{
   1.724 +  TRACE_APPLY (NULL);
   1.725 +
   1.726 +  if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false);
   1.727 +
   1.728 +  hb_buffer_t *buffer = c->buffer;
   1.729 +
   1.730 +  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1);
   1.731 +  skippy_iter.set_match_func (match_func, match_data, input);
   1.732 +  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
   1.733 +
   1.734 +  /*
   1.735 +   * This is perhaps the trickiest part of OpenType...  Remarks:
   1.736 +   *
   1.737 +   * - If all components of the ligature were marks, we call this a mark ligature.
   1.738 +   *
   1.739 +   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
   1.740 +   *   it as a ligature glyph.
   1.741 +   *
   1.742 +   * - Ligatures cannot be formed across glyphs attached to different components
   1.743 +   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
   1.744 +   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
   1.745 +   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.o
   1.746 +   *   There is an exception to this: If a ligature tries ligating with marks that
   1.747 +   *   belong to it itself, go ahead, assuming that the font designer knows what
   1.748 +   *   they are doing (otherwise it can break Indic stuff when a matra wants to
   1.749 +   *   ligate with a conjunct...)
   1.750 +   */
   1.751 +
   1.752 +  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
   1.753 +
   1.754 +  unsigned int total_component_count = 0;
   1.755 +  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
   1.756 +
   1.757 +  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
   1.758 +  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
   1.759 +
   1.760 +  match_positions[0] = buffer->idx;
   1.761 +  for (unsigned int i = 1; i < count; i++)
   1.762 +  {
   1.763 +    if (!skippy_iter.next ()) return TRACE_RETURN (false);
   1.764 +
   1.765 +    match_positions[i] = skippy_iter.idx;
   1.766 +
   1.767 +    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
   1.768 +    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
   1.769 +
   1.770 +    if (first_lig_id && first_lig_comp) {
   1.771 +      /* If first component was attached to a previous ligature component,
   1.772 +       * all subsequent components should be attached to the same ligature
   1.773 +       * component, otherwise we shouldn't ligate them. */
   1.774 +      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
   1.775 +	return TRACE_RETURN (false);
   1.776 +    } else {
   1.777 +      /* If first component was NOT attached to a previous ligature component,
   1.778 +       * all subsequent components should also NOT be attached to any ligature
   1.779 +       * component, unless they are attached to the first component itself! */
   1.780 +      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
   1.781 +	return TRACE_RETURN (false);
   1.782 +    }
   1.783 +
   1.784 +    is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
   1.785 +    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
   1.786 +  }
   1.787 +
   1.788 +  *end_offset = skippy_iter.idx - buffer->idx + 1;
   1.789 +
   1.790 +  if (p_is_mark_ligature)
   1.791 +    *p_is_mark_ligature = is_mark_ligature;
   1.792 +
   1.793 +  if (p_total_component_count)
   1.794 +    *p_total_component_count = total_component_count;
   1.795 +
   1.796 +  return TRACE_RETURN (true);
   1.797 +}
   1.798 +static inline void ligate_input (hb_apply_context_t *c,
   1.799 +				 unsigned int count, /* Including the first glyph */
   1.800 +				 unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
   1.801 +				 unsigned int match_length,
   1.802 +				 hb_codepoint_t lig_glyph,
   1.803 +				 bool is_mark_ligature,
   1.804 +				 unsigned int total_component_count)
   1.805 +{
   1.806 +  TRACE_APPLY (NULL);
   1.807 +
   1.808 +  hb_buffer_t *buffer = c->buffer;
   1.809 +
   1.810 +  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
   1.811 +
   1.812 +  /*
   1.813 +   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
   1.814 +   *   the ligature to keep its old ligature id.  This will allow it to attach to
   1.815 +   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
   1.816 +   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
   1.817 +   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
   1.818 +   *   later, we don't want them to lose their ligature id/component, otherwise
   1.819 +   *   GPOS will fail to correctly position the mark ligature on top of the
   1.820 +   *   LAM,LAM,HEH ligature.  See:
   1.821 +   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
   1.822 +   *
   1.823 +   * - If a ligature is formed of components that some of which are also ligatures
   1.824 +   *   themselves, and those ligature components had marks attached to *their*
   1.825 +   *   components, we have to attach the marks to the new ligature component
   1.826 +   *   positions!  Now *that*'s tricky!  And these marks may be following the
   1.827 +   *   last component of the whole sequence, so we should loop forward looking
   1.828 +   *   for them and update them.
   1.829 +   *
   1.830 +   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
   1.831 +   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
   1.832 +   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
   1.833 +   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
   1.834 +   *   the new ligature with a component value of 2.
   1.835 +   *
   1.836 +   *   This in fact happened to a font...  See:
   1.837 +   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
   1.838 +   */
   1.839 +
   1.840 +  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
   1.841 +  unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
   1.842 +  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
   1.843 +  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
   1.844 +  unsigned int components_so_far = last_num_components;
   1.845 +
   1.846 +  if (!is_mark_ligature)
   1.847 +  {
   1.848 +    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
   1.849 +    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
   1.850 +    {
   1.851 +      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
   1.852 +      _hb_glyph_info_set_modified_combining_class (&buffer->cur(), 0);
   1.853 +    }
   1.854 +  }
   1.855 +  c->replace_glyph_with_ligature (lig_glyph, klass);
   1.856 +
   1.857 +  for (unsigned int i = 1; i < count; i++)
   1.858 +  {
   1.859 +    while (buffer->idx < match_positions[i])
   1.860 +    {
   1.861 +      if (!is_mark_ligature) {
   1.862 +	unsigned int new_lig_comp = components_so_far - last_num_components +
   1.863 +				    MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components);
   1.864 +	_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
   1.865 +      }
   1.866 +      buffer->next_glyph ();
   1.867 +    }
   1.868 +
   1.869 +    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
   1.870 +    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
   1.871 +    components_so_far += last_num_components;
   1.872 +
   1.873 +    /* Skip the base glyph */
   1.874 +    buffer->idx++;
   1.875 +  }
   1.876 +
   1.877 +  if (!is_mark_ligature && last_lig_id) {
   1.878 +    /* Re-adjust components for any marks following. */
   1.879 +    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
   1.880 +      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
   1.881 +	unsigned int new_lig_comp = components_so_far - last_num_components +
   1.882 +				    MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components);
   1.883 +	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
   1.884 +      } else
   1.885 +	break;
   1.886 +    }
   1.887 +  }
   1.888 +}
   1.889 +
   1.890 +static inline bool match_backtrack (hb_apply_context_t *c,
   1.891 +				    unsigned int count,
   1.892 +				    const USHORT backtrack[],
   1.893 +				    match_func_t match_func,
   1.894 +				    const void *match_data)
   1.895 +{
   1.896 +  TRACE_APPLY (NULL);
   1.897 +
   1.898 +  hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
   1.899 +  skippy_iter.set_match_func (match_func, match_data, backtrack);
   1.900 +  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
   1.901 +
   1.902 +  for (unsigned int i = 0; i < count; i++)
   1.903 +    if (!skippy_iter.prev ())
   1.904 +      return TRACE_RETURN (false);
   1.905 +
   1.906 +  return TRACE_RETURN (true);
   1.907 +}
   1.908 +
   1.909 +static inline bool match_lookahead (hb_apply_context_t *c,
   1.910 +				    unsigned int count,
   1.911 +				    const USHORT lookahead[],
   1.912 +				    match_func_t match_func,
   1.913 +				    const void *match_data,
   1.914 +				    unsigned int offset)
   1.915 +{
   1.916 +  TRACE_APPLY (NULL);
   1.917 +
   1.918 +  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
   1.919 +  skippy_iter.set_match_func (match_func, match_data, lookahead);
   1.920 +  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
   1.921 +
   1.922 +  for (unsigned int i = 0; i < count; i++)
   1.923 +    if (!skippy_iter.next ())
   1.924 +      return TRACE_RETURN (false);
   1.925 +
   1.926 +  return TRACE_RETURN (true);
   1.927 +}
   1.928 +
   1.929 +
   1.930 +
   1.931 +struct LookupRecord
   1.932 +{
   1.933 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.934 +    TRACE_SANITIZE (this);
   1.935 +    return TRACE_RETURN (c->check_struct (this));
   1.936 +  }
   1.937 +
   1.938 +  USHORT	sequenceIndex;		/* Index into current glyph
   1.939 +					 * sequence--first glyph = 0 */
   1.940 +  USHORT	lookupListIndex;	/* Lookup to apply to that
   1.941 +					 * position--zero--based */
   1.942 +  public:
   1.943 +  DEFINE_SIZE_STATIC (4);
   1.944 +};
   1.945 +
   1.946 +
   1.947 +template <typename context_t>
   1.948 +static inline void recurse_lookups (context_t *c,
   1.949 +				    unsigned int lookupCount,
   1.950 +				    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
   1.951 +{
   1.952 +  for (unsigned int i = 0; i < lookupCount; i++)
   1.953 +    c->recurse (lookupRecord[i].lookupListIndex);
   1.954 +}
   1.955 +
   1.956 +static inline bool apply_lookup (hb_apply_context_t *c,
   1.957 +				 unsigned int count, /* Including the first glyph */
   1.958 +				 unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
   1.959 +				 unsigned int lookupCount,
   1.960 +				 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
   1.961 +				 unsigned int match_length)
   1.962 +{
   1.963 +  TRACE_APPLY (NULL);
   1.964 +
   1.965 +  hb_buffer_t *buffer = c->buffer;
   1.966 +  unsigned int end;
   1.967 +
   1.968 +  /* All positions are distance from beginning of *output* buffer.
   1.969 +   * Adjust. */
   1.970 +  {
   1.971 +    unsigned int bl = buffer->backtrack_len ();
   1.972 +    end = bl + match_length;
   1.973 +
   1.974 +    int delta = bl - buffer->idx;
   1.975 +    /* Convert positions to new indexing. */
   1.976 +    for (unsigned int j = 0; j < count; j++)
   1.977 +      match_positions[j] += delta;
   1.978 +  }
   1.979 +
   1.980 +  for (unsigned int i = 0; i < lookupCount; i++)
   1.981 +  {
   1.982 +    unsigned int idx = lookupRecord[i].sequenceIndex;
   1.983 +    if (idx >= count)
   1.984 +      continue;
   1.985 +
   1.986 +    buffer->move_to (match_positions[idx]);
   1.987 +
   1.988 +    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
   1.989 +    if (!c->recurse (lookupRecord[i].lookupListIndex))
   1.990 +      continue;
   1.991 +
   1.992 +    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
   1.993 +    int delta = new_len - orig_len;
   1.994 +
   1.995 +    if (!delta)
   1.996 +        continue;
   1.997 +
   1.998 +    /* Recursed lookup changed buffer len.  Adjust. */
   1.999 +
  1.1000 +    /* end can't go back past the current match position. */
  1.1001 +    end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
  1.1002 +
  1.1003 +    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
  1.1004 +
  1.1005 +    if (delta > 0)
  1.1006 +    {
  1.1007 +      if (unlikely (delta + count > MAX_CONTEXT_LENGTH))
  1.1008 +	break;
  1.1009 +    }
  1.1010 +    else
  1.1011 +    {
  1.1012 +      /* NOTE: delta is negative. */
  1.1013 +      delta = MAX (delta, (int) next - (int) count);
  1.1014 +      next -= delta;
  1.1015 +    }
  1.1016 +
  1.1017 +    /* Shift! */
  1.1018 +    memmove (match_positions + next + delta, match_positions + next,
  1.1019 +	     (count - next) * sizeof (match_positions[0]));
  1.1020 +    next += delta;
  1.1021 +    count += delta;
  1.1022 +
  1.1023 +    /* Fill in new entries. */
  1.1024 +    for (unsigned int j = idx + 1; j < next; j++)
  1.1025 +      match_positions[j] = match_positions[j - 1] + 1;
  1.1026 +
  1.1027 +    /* And fixup the rest. */
  1.1028 +    for (; next < count; next++)
  1.1029 +      match_positions[next] += delta;
  1.1030 +  }
  1.1031 +
  1.1032 +  buffer->move_to (end);
  1.1033 +
  1.1034 +  return TRACE_RETURN (true);
  1.1035 +}
  1.1036 +
  1.1037 +
  1.1038 +
  1.1039 +/* Contextual lookups */
  1.1040 +
  1.1041 +struct ContextClosureLookupContext
  1.1042 +{
  1.1043 +  ContextClosureFuncs funcs;
  1.1044 +  const void *intersects_data;
  1.1045 +};
  1.1046 +
  1.1047 +struct ContextCollectGlyphsLookupContext
  1.1048 +{
  1.1049 +  ContextCollectGlyphsFuncs funcs;
  1.1050 +  const void *collect_data;
  1.1051 +};
  1.1052 +
  1.1053 +struct ContextApplyLookupContext
  1.1054 +{
  1.1055 +  ContextApplyFuncs funcs;
  1.1056 +  const void *match_data;
  1.1057 +};
  1.1058 +
  1.1059 +static inline void context_closure_lookup (hb_closure_context_t *c,
  1.1060 +					   unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1061 +					   const USHORT input[], /* Array of input values--start with second glyph */
  1.1062 +					   unsigned int lookupCount,
  1.1063 +					   const LookupRecord lookupRecord[],
  1.1064 +					   ContextClosureLookupContext &lookup_context)
  1.1065 +{
  1.1066 +  if (intersects_array (c,
  1.1067 +			inputCount ? inputCount - 1 : 0, input,
  1.1068 +			lookup_context.funcs.intersects, lookup_context.intersects_data))
  1.1069 +    recurse_lookups (c,
  1.1070 +		     lookupCount, lookupRecord);
  1.1071 +}
  1.1072 +
  1.1073 +static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
  1.1074 +						  unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1075 +						  const USHORT input[], /* Array of input values--start with second glyph */
  1.1076 +						  unsigned int lookupCount,
  1.1077 +						  const LookupRecord lookupRecord[],
  1.1078 +						  ContextCollectGlyphsLookupContext &lookup_context)
  1.1079 +{
  1.1080 +  collect_array (c, c->input,
  1.1081 +		 inputCount ? inputCount - 1 : 0, input,
  1.1082 +		 lookup_context.funcs.collect, lookup_context.collect_data);
  1.1083 +  recurse_lookups (c,
  1.1084 +		   lookupCount, lookupRecord);
  1.1085 +}
  1.1086 +
  1.1087 +static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
  1.1088 +					       unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1089 +					       const USHORT input[], /* Array of input values--start with second glyph */
  1.1090 +					       unsigned int lookupCount HB_UNUSED,
  1.1091 +					       const LookupRecord lookupRecord[] HB_UNUSED,
  1.1092 +					       ContextApplyLookupContext &lookup_context)
  1.1093 +{
  1.1094 +  return would_match_input (c,
  1.1095 +			    inputCount, input,
  1.1096 +			    lookup_context.funcs.match, lookup_context.match_data);
  1.1097 +}
  1.1098 +static inline bool context_apply_lookup (hb_apply_context_t *c,
  1.1099 +					 unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1100 +					 const USHORT input[], /* Array of input values--start with second glyph */
  1.1101 +					 unsigned int lookupCount,
  1.1102 +					 const LookupRecord lookupRecord[],
  1.1103 +					 ContextApplyLookupContext &lookup_context)
  1.1104 +{
  1.1105 +  unsigned int match_length = 0;
  1.1106 +  unsigned int match_positions[MAX_CONTEXT_LENGTH];
  1.1107 +  return match_input (c,
  1.1108 +		      inputCount, input,
  1.1109 +		      lookup_context.funcs.match, lookup_context.match_data,
  1.1110 +		      &match_length, match_positions)
  1.1111 +      && apply_lookup (c,
  1.1112 +		       inputCount, match_positions,
  1.1113 +		       lookupCount, lookupRecord,
  1.1114 +		       match_length);
  1.1115 +}
  1.1116 +
  1.1117 +struct Rule
  1.1118 +{
  1.1119 +  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
  1.1120 +  {
  1.1121 +    TRACE_CLOSURE (this);
  1.1122 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
  1.1123 +    context_closure_lookup (c,
  1.1124 +			    inputCount, input,
  1.1125 +			    lookupCount, lookupRecord,
  1.1126 +			    lookup_context);
  1.1127 +  }
  1.1128 +
  1.1129 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
  1.1130 +  {
  1.1131 +    TRACE_COLLECT_GLYPHS (this);
  1.1132 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
  1.1133 +    context_collect_glyphs_lookup (c,
  1.1134 +				   inputCount, input,
  1.1135 +				   lookupCount, lookupRecord,
  1.1136 +				   lookup_context);
  1.1137 +  }
  1.1138 +
  1.1139 +  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1.1140 +  {
  1.1141 +    TRACE_WOULD_APPLY (this);
  1.1142 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
  1.1143 +    return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
  1.1144 +  }
  1.1145 +
  1.1146 +  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1.1147 +  {
  1.1148 +    TRACE_APPLY (this);
  1.1149 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
  1.1150 +    return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
  1.1151 +  }
  1.1152 +
  1.1153 +  public:
  1.1154 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1155 +    TRACE_SANITIZE (this);
  1.1156 +    return inputCount.sanitize (c)
  1.1157 +	&& lookupCount.sanitize (c)
  1.1158 +	&& c->check_range (input,
  1.1159 +			   input[0].static_size * inputCount
  1.1160 +			   + lookupRecordX[0].static_size * lookupCount);
  1.1161 +  }
  1.1162 +
  1.1163 +  protected:
  1.1164 +  USHORT	inputCount;		/* Total number of glyphs in input
  1.1165 +					 * glyph sequence--includes the first
  1.1166 +					 * glyph */
  1.1167 +  USHORT	lookupCount;		/* Number of LookupRecords */
  1.1168 +  USHORT	input[VAR];		/* Array of match inputs--start with
  1.1169 +					 * second glyph */
  1.1170 +  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
  1.1171 +					 * design order */
  1.1172 +  public:
  1.1173 +  DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
  1.1174 +};
  1.1175 +
  1.1176 +struct RuleSet
  1.1177 +{
  1.1178 +  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
  1.1179 +  {
  1.1180 +    TRACE_CLOSURE (this);
  1.1181 +    unsigned int num_rules = rule.len;
  1.1182 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1183 +      (this+rule[i]).closure (c, lookup_context);
  1.1184 +  }
  1.1185 +
  1.1186 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
  1.1187 +  {
  1.1188 +    TRACE_COLLECT_GLYPHS (this);
  1.1189 +    unsigned int num_rules = rule.len;
  1.1190 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1191 +      (this+rule[i]).collect_glyphs (c, lookup_context);
  1.1192 +  }
  1.1193 +
  1.1194 +  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1.1195 +  {
  1.1196 +    TRACE_WOULD_APPLY (this);
  1.1197 +    unsigned int num_rules = rule.len;
  1.1198 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1199 +    {
  1.1200 +      if ((this+rule[i]).would_apply (c, lookup_context))
  1.1201 +        return TRACE_RETURN (true);
  1.1202 +    }
  1.1203 +    return TRACE_RETURN (false);
  1.1204 +  }
  1.1205 +
  1.1206 +  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
  1.1207 +  {
  1.1208 +    TRACE_APPLY (this);
  1.1209 +    unsigned int num_rules = rule.len;
  1.1210 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1211 +    {
  1.1212 +      if ((this+rule[i]).apply (c, lookup_context))
  1.1213 +        return TRACE_RETURN (true);
  1.1214 +    }
  1.1215 +    return TRACE_RETURN (false);
  1.1216 +  }
  1.1217 +
  1.1218 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1219 +    TRACE_SANITIZE (this);
  1.1220 +    return TRACE_RETURN (rule.sanitize (c, this));
  1.1221 +  }
  1.1222 +
  1.1223 +  protected:
  1.1224 +  OffsetArrayOf<Rule>
  1.1225 +		rule;			/* Array of Rule tables
  1.1226 +					 * ordered by preference */
  1.1227 +  public:
  1.1228 +  DEFINE_SIZE_ARRAY (2, rule);
  1.1229 +};
  1.1230 +
  1.1231 +
  1.1232 +struct ContextFormat1
  1.1233 +{
  1.1234 +  inline void closure (hb_closure_context_t *c) const
  1.1235 +  {
  1.1236 +    TRACE_CLOSURE (this);
  1.1237 +
  1.1238 +    const Coverage &cov = (this+coverage);
  1.1239 +
  1.1240 +    struct ContextClosureLookupContext lookup_context = {
  1.1241 +      {intersects_glyph},
  1.1242 +      NULL
  1.1243 +    };
  1.1244 +
  1.1245 +    unsigned int count = ruleSet.len;
  1.1246 +    for (unsigned int i = 0; i < count; i++)
  1.1247 +      if (cov.intersects_coverage (c->glyphs, i)) {
  1.1248 +	const RuleSet &rule_set = this+ruleSet[i];
  1.1249 +	rule_set.closure (c, lookup_context);
  1.1250 +      }
  1.1251 +  }
  1.1252 +
  1.1253 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1.1254 +  {
  1.1255 +    TRACE_COLLECT_GLYPHS (this);
  1.1256 +    (this+coverage).add_coverage (c->input);
  1.1257 +
  1.1258 +    struct ContextCollectGlyphsLookupContext lookup_context = {
  1.1259 +      {collect_glyph},
  1.1260 +      NULL
  1.1261 +    };
  1.1262 +
  1.1263 +    unsigned int count = ruleSet.len;
  1.1264 +    for (unsigned int i = 0; i < count; i++)
  1.1265 +      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
  1.1266 +  }
  1.1267 +
  1.1268 +  inline bool would_apply (hb_would_apply_context_t *c) const
  1.1269 +  {
  1.1270 +    TRACE_WOULD_APPLY (this);
  1.1271 +
  1.1272 +    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
  1.1273 +    struct ContextApplyLookupContext lookup_context = {
  1.1274 +      {match_glyph},
  1.1275 +      NULL
  1.1276 +    };
  1.1277 +    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
  1.1278 +  }
  1.1279 +
  1.1280 +  inline const Coverage &get_coverage (void) const
  1.1281 +  {
  1.1282 +    return this+coverage;
  1.1283 +  }
  1.1284 +
  1.1285 +  inline bool apply (hb_apply_context_t *c) const
  1.1286 +  {
  1.1287 +    TRACE_APPLY (this);
  1.1288 +    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1.1289 +    if (likely (index == NOT_COVERED))
  1.1290 +      return TRACE_RETURN (false);
  1.1291 +
  1.1292 +    const RuleSet &rule_set = this+ruleSet[index];
  1.1293 +    struct ContextApplyLookupContext lookup_context = {
  1.1294 +      {match_glyph},
  1.1295 +      NULL
  1.1296 +    };
  1.1297 +    return TRACE_RETURN (rule_set.apply (c, lookup_context));
  1.1298 +  }
  1.1299 +
  1.1300 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1301 +    TRACE_SANITIZE (this);
  1.1302 +    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
  1.1303 +  }
  1.1304 +
  1.1305 +  protected:
  1.1306 +  USHORT	format;			/* Format identifier--format = 1 */
  1.1307 +  OffsetTo<Coverage>
  1.1308 +		coverage;		/* Offset to Coverage table--from
  1.1309 +					 * beginning of table */
  1.1310 +  OffsetArrayOf<RuleSet>
  1.1311 +		ruleSet;		/* Array of RuleSet tables
  1.1312 +					 * ordered by Coverage Index */
  1.1313 +  public:
  1.1314 +  DEFINE_SIZE_ARRAY (6, ruleSet);
  1.1315 +};
  1.1316 +
  1.1317 +
  1.1318 +struct ContextFormat2
  1.1319 +{
  1.1320 +  inline void closure (hb_closure_context_t *c) const
  1.1321 +  {
  1.1322 +    TRACE_CLOSURE (this);
  1.1323 +    if (!(this+coverage).intersects (c->glyphs))
  1.1324 +      return;
  1.1325 +
  1.1326 +    const ClassDef &class_def = this+classDef;
  1.1327 +
  1.1328 +    struct ContextClosureLookupContext lookup_context = {
  1.1329 +      {intersects_class},
  1.1330 +      &class_def
  1.1331 +    };
  1.1332 +
  1.1333 +    unsigned int count = ruleSet.len;
  1.1334 +    for (unsigned int i = 0; i < count; i++)
  1.1335 +      if (class_def.intersects_class (c->glyphs, i)) {
  1.1336 +	const RuleSet &rule_set = this+ruleSet[i];
  1.1337 +	rule_set.closure (c, lookup_context);
  1.1338 +      }
  1.1339 +  }
  1.1340 +
  1.1341 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1.1342 +  {
  1.1343 +    TRACE_COLLECT_GLYPHS (this);
  1.1344 +    (this+coverage).add_coverage (c->input);
  1.1345 +
  1.1346 +    const ClassDef &class_def = this+classDef;
  1.1347 +    struct ContextCollectGlyphsLookupContext lookup_context = {
  1.1348 +      {collect_class},
  1.1349 +      &class_def
  1.1350 +    };
  1.1351 +
  1.1352 +    unsigned int count = ruleSet.len;
  1.1353 +    for (unsigned int i = 0; i < count; i++)
  1.1354 +      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
  1.1355 +  }
  1.1356 +
  1.1357 +  inline bool would_apply (hb_would_apply_context_t *c) const
  1.1358 +  {
  1.1359 +    TRACE_WOULD_APPLY (this);
  1.1360 +
  1.1361 +    const ClassDef &class_def = this+classDef;
  1.1362 +    unsigned int index = class_def.get_class (c->glyphs[0]);
  1.1363 +    const RuleSet &rule_set = this+ruleSet[index];
  1.1364 +    struct ContextApplyLookupContext lookup_context = {
  1.1365 +      {match_class},
  1.1366 +      &class_def
  1.1367 +    };
  1.1368 +    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
  1.1369 +  }
  1.1370 +
  1.1371 +  inline const Coverage &get_coverage (void) const
  1.1372 +  {
  1.1373 +    return this+coverage;
  1.1374 +  }
  1.1375 +
  1.1376 +  inline bool apply (hb_apply_context_t *c) const
  1.1377 +  {
  1.1378 +    TRACE_APPLY (this);
  1.1379 +    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1.1380 +    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
  1.1381 +
  1.1382 +    const ClassDef &class_def = this+classDef;
  1.1383 +    index = class_def.get_class (c->buffer->cur().codepoint);
  1.1384 +    const RuleSet &rule_set = this+ruleSet[index];
  1.1385 +    struct ContextApplyLookupContext lookup_context = {
  1.1386 +      {match_class},
  1.1387 +      &class_def
  1.1388 +    };
  1.1389 +    return TRACE_RETURN (rule_set.apply (c, lookup_context));
  1.1390 +  }
  1.1391 +
  1.1392 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1393 +    TRACE_SANITIZE (this);
  1.1394 +    return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
  1.1395 +  }
  1.1396 +
  1.1397 +  protected:
  1.1398 +  USHORT	format;			/* Format identifier--format = 2 */
  1.1399 +  OffsetTo<Coverage>
  1.1400 +		coverage;		/* Offset to Coverage table--from
  1.1401 +					 * beginning of table */
  1.1402 +  OffsetTo<ClassDef>
  1.1403 +		classDef;		/* Offset to glyph ClassDef table--from
  1.1404 +					 * beginning of table */
  1.1405 +  OffsetArrayOf<RuleSet>
  1.1406 +		ruleSet;		/* Array of RuleSet tables
  1.1407 +					 * ordered by class */
  1.1408 +  public:
  1.1409 +  DEFINE_SIZE_ARRAY (8, ruleSet);
  1.1410 +};
  1.1411 +
  1.1412 +
  1.1413 +struct ContextFormat3
  1.1414 +{
  1.1415 +  inline void closure (hb_closure_context_t *c) const
  1.1416 +  {
  1.1417 +    TRACE_CLOSURE (this);
  1.1418 +    if (!(this+coverage[0]).intersects (c->glyphs))
  1.1419 +      return;
  1.1420 +
  1.1421 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
  1.1422 +    struct ContextClosureLookupContext lookup_context = {
  1.1423 +      {intersects_coverage},
  1.1424 +      this
  1.1425 +    };
  1.1426 +    context_closure_lookup (c,
  1.1427 +			    glyphCount, (const USHORT *) (coverage + 1),
  1.1428 +			    lookupCount, lookupRecord,
  1.1429 +			    lookup_context);
  1.1430 +  }
  1.1431 +
  1.1432 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1.1433 +  {
  1.1434 +    TRACE_COLLECT_GLYPHS (this);
  1.1435 +    (this+coverage[0]).add_coverage (c->input);
  1.1436 +
  1.1437 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
  1.1438 +    struct ContextCollectGlyphsLookupContext lookup_context = {
  1.1439 +      {collect_coverage},
  1.1440 +      this
  1.1441 +    };
  1.1442 +
  1.1443 +    context_collect_glyphs_lookup (c,
  1.1444 +				   glyphCount, (const USHORT *) (coverage + 1),
  1.1445 +				   lookupCount, lookupRecord,
  1.1446 +				   lookup_context);
  1.1447 +  }
  1.1448 +
  1.1449 +  inline bool would_apply (hb_would_apply_context_t *c) const
  1.1450 +  {
  1.1451 +    TRACE_WOULD_APPLY (this);
  1.1452 +
  1.1453 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
  1.1454 +    struct ContextApplyLookupContext lookup_context = {
  1.1455 +      {match_coverage},
  1.1456 +      this
  1.1457 +    };
  1.1458 +    return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
  1.1459 +  }
  1.1460 +
  1.1461 +  inline const Coverage &get_coverage (void) const
  1.1462 +  {
  1.1463 +    return this+coverage[0];
  1.1464 +  }
  1.1465 +
  1.1466 +  inline bool apply (hb_apply_context_t *c) const
  1.1467 +  {
  1.1468 +    TRACE_APPLY (this);
  1.1469 +    unsigned int index = (this+coverage[0]).get_coverage (c->buffer->cur().codepoint);
  1.1470 +    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
  1.1471 +
  1.1472 +    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
  1.1473 +    struct ContextApplyLookupContext lookup_context = {
  1.1474 +      {match_coverage},
  1.1475 +      this
  1.1476 +    };
  1.1477 +    return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
  1.1478 +  }
  1.1479 +
  1.1480 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1481 +    TRACE_SANITIZE (this);
  1.1482 +    if (!c->check_struct (this)) return TRACE_RETURN (false);
  1.1483 +    unsigned int count = glyphCount;
  1.1484 +    if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
  1.1485 +    for (unsigned int i = 0; i < count; i++)
  1.1486 +      if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
  1.1487 +    LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
  1.1488 +    return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
  1.1489 +  }
  1.1490 +
  1.1491 +  protected:
  1.1492 +  USHORT	format;			/* Format identifier--format = 3 */
  1.1493 +  USHORT	glyphCount;		/* Number of glyphs in the input glyph
  1.1494 +					 * sequence */
  1.1495 +  USHORT	lookupCount;		/* Number of LookupRecords */
  1.1496 +  OffsetTo<Coverage>
  1.1497 +		coverage[VAR];		/* Array of offsets to Coverage
  1.1498 +					 * table in glyph sequence order */
  1.1499 +  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
  1.1500 +					 * design order */
  1.1501 +  public:
  1.1502 +  DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
  1.1503 +};
  1.1504 +
  1.1505 +struct Context
  1.1506 +{
  1.1507 +  template <typename context_t>
  1.1508 +  inline typename context_t::return_t dispatch (context_t *c) const
  1.1509 +  {
  1.1510 +    TRACE_DISPATCH (this);
  1.1511 +    switch (u.format) {
  1.1512 +    case 1: return TRACE_RETURN (c->dispatch (u.format1));
  1.1513 +    case 2: return TRACE_RETURN (c->dispatch (u.format2));
  1.1514 +    case 3: return TRACE_RETURN (c->dispatch (u.format3));
  1.1515 +    default:return TRACE_RETURN (c->default_return_value ());
  1.1516 +    }
  1.1517 +  }
  1.1518 +
  1.1519 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1520 +    TRACE_SANITIZE (this);
  1.1521 +    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
  1.1522 +    switch (u.format) {
  1.1523 +    case 1: return TRACE_RETURN (u.format1.sanitize (c));
  1.1524 +    case 2: return TRACE_RETURN (u.format2.sanitize (c));
  1.1525 +    case 3: return TRACE_RETURN (u.format3.sanitize (c));
  1.1526 +    default:return TRACE_RETURN (true);
  1.1527 +    }
  1.1528 +  }
  1.1529 +
  1.1530 +  protected:
  1.1531 +  union {
  1.1532 +  USHORT		format;		/* Format identifier */
  1.1533 +  ContextFormat1	format1;
  1.1534 +  ContextFormat2	format2;
  1.1535 +  ContextFormat3	format3;
  1.1536 +  } u;
  1.1537 +};
  1.1538 +
  1.1539 +
  1.1540 +/* Chaining Contextual lookups */
  1.1541 +
  1.1542 +struct ChainContextClosureLookupContext
  1.1543 +{
  1.1544 +  ContextClosureFuncs funcs;
  1.1545 +  const void *intersects_data[3];
  1.1546 +};
  1.1547 +
  1.1548 +struct ChainContextCollectGlyphsLookupContext
  1.1549 +{
  1.1550 +  ContextCollectGlyphsFuncs funcs;
  1.1551 +  const void *collect_data[3];
  1.1552 +};
  1.1553 +
  1.1554 +struct ChainContextApplyLookupContext
  1.1555 +{
  1.1556 +  ContextApplyFuncs funcs;
  1.1557 +  const void *match_data[3];
  1.1558 +};
  1.1559 +
  1.1560 +static inline void chain_context_closure_lookup (hb_closure_context_t *c,
  1.1561 +						 unsigned int backtrackCount,
  1.1562 +						 const USHORT backtrack[],
  1.1563 +						 unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1564 +						 const USHORT input[], /* Array of input values--start with second glyph */
  1.1565 +						 unsigned int lookaheadCount,
  1.1566 +						 const USHORT lookahead[],
  1.1567 +						 unsigned int lookupCount,
  1.1568 +						 const LookupRecord lookupRecord[],
  1.1569 +						 ChainContextClosureLookupContext &lookup_context)
  1.1570 +{
  1.1571 +  if (intersects_array (c,
  1.1572 +			backtrackCount, backtrack,
  1.1573 +			lookup_context.funcs.intersects, lookup_context.intersects_data[0])
  1.1574 +   && intersects_array (c,
  1.1575 +			inputCount ? inputCount - 1 : 0, input,
  1.1576 +			lookup_context.funcs.intersects, lookup_context.intersects_data[1])
  1.1577 +   && intersects_array (c,
  1.1578 +		       lookaheadCount, lookahead,
  1.1579 +		       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
  1.1580 +    recurse_lookups (c,
  1.1581 +		     lookupCount, lookupRecord);
  1.1582 +}
  1.1583 +
  1.1584 +static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
  1.1585 +						        unsigned int backtrackCount,
  1.1586 +						        const USHORT backtrack[],
  1.1587 +						        unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1588 +						        const USHORT input[], /* Array of input values--start with second glyph */
  1.1589 +						        unsigned int lookaheadCount,
  1.1590 +						        const USHORT lookahead[],
  1.1591 +						        unsigned int lookupCount,
  1.1592 +						        const LookupRecord lookupRecord[],
  1.1593 +						        ChainContextCollectGlyphsLookupContext &lookup_context)
  1.1594 +{
  1.1595 +  collect_array (c, c->before,
  1.1596 +		 backtrackCount, backtrack,
  1.1597 +		 lookup_context.funcs.collect, lookup_context.collect_data[0]);
  1.1598 +  collect_array (c, c->input,
  1.1599 +		 inputCount ? inputCount - 1 : 0, input,
  1.1600 +		 lookup_context.funcs.collect, lookup_context.collect_data[1]);
  1.1601 +  collect_array (c, c->after,
  1.1602 +		 lookaheadCount, lookahead,
  1.1603 +		 lookup_context.funcs.collect, lookup_context.collect_data[2]);
  1.1604 +  recurse_lookups (c,
  1.1605 +		   lookupCount, lookupRecord);
  1.1606 +}
  1.1607 +
  1.1608 +static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
  1.1609 +						     unsigned int backtrackCount,
  1.1610 +						     const USHORT backtrack[] HB_UNUSED,
  1.1611 +						     unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1612 +						     const USHORT input[], /* Array of input values--start with second glyph */
  1.1613 +						     unsigned int lookaheadCount,
  1.1614 +						     const USHORT lookahead[] HB_UNUSED,
  1.1615 +						     unsigned int lookupCount HB_UNUSED,
  1.1616 +						     const LookupRecord lookupRecord[] HB_UNUSED,
  1.1617 +						     ChainContextApplyLookupContext &lookup_context)
  1.1618 +{
  1.1619 +  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
  1.1620 +      && would_match_input (c,
  1.1621 +			    inputCount, input,
  1.1622 +			    lookup_context.funcs.match, lookup_context.match_data[1]);
  1.1623 +}
  1.1624 +
  1.1625 +static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
  1.1626 +					       unsigned int backtrackCount,
  1.1627 +					       const USHORT backtrack[],
  1.1628 +					       unsigned int inputCount, /* Including the first glyph (not matched) */
  1.1629 +					       const USHORT input[], /* Array of input values--start with second glyph */
  1.1630 +					       unsigned int lookaheadCount,
  1.1631 +					       const USHORT lookahead[],
  1.1632 +					       unsigned int lookupCount,
  1.1633 +					       const LookupRecord lookupRecord[],
  1.1634 +					       ChainContextApplyLookupContext &lookup_context)
  1.1635 +{
  1.1636 +  unsigned int match_length = 0;
  1.1637 +  unsigned int match_positions[MAX_CONTEXT_LENGTH];
  1.1638 +  return match_input (c,
  1.1639 +		      inputCount, input,
  1.1640 +		      lookup_context.funcs.match, lookup_context.match_data[1],
  1.1641 +		      &match_length, match_positions)
  1.1642 +      && match_backtrack (c,
  1.1643 +			  backtrackCount, backtrack,
  1.1644 +			  lookup_context.funcs.match, lookup_context.match_data[0])
  1.1645 +      && match_lookahead (c,
  1.1646 +			  lookaheadCount, lookahead,
  1.1647 +			  lookup_context.funcs.match, lookup_context.match_data[2],
  1.1648 +			  match_length)
  1.1649 +      && apply_lookup (c,
  1.1650 +		       inputCount, match_positions,
  1.1651 +		       lookupCount, lookupRecord,
  1.1652 +		       match_length);
  1.1653 +}
  1.1654 +
  1.1655 +struct ChainRule
  1.1656 +{
  1.1657 +  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
  1.1658 +  {
  1.1659 +    TRACE_CLOSURE (this);
  1.1660 +    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1.1661 +    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1.1662 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.1663 +    chain_context_closure_lookup (c,
  1.1664 +				  backtrack.len, backtrack.array,
  1.1665 +				  input.len, input.array,
  1.1666 +				  lookahead.len, lookahead.array,
  1.1667 +				  lookup.len, lookup.array,
  1.1668 +				  lookup_context);
  1.1669 +  }
  1.1670 +
  1.1671 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
  1.1672 +  {
  1.1673 +    TRACE_COLLECT_GLYPHS (this);
  1.1674 +    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1.1675 +    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1.1676 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.1677 +    chain_context_collect_glyphs_lookup (c,
  1.1678 +					 backtrack.len, backtrack.array,
  1.1679 +					 input.len, input.array,
  1.1680 +					 lookahead.len, lookahead.array,
  1.1681 +					 lookup.len, lookup.array,
  1.1682 +					 lookup_context);
  1.1683 +  }
  1.1684 +
  1.1685 +  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1.1686 +  {
  1.1687 +    TRACE_WOULD_APPLY (this);
  1.1688 +    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1.1689 +    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1.1690 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.1691 +    return TRACE_RETURN (chain_context_would_apply_lookup (c,
  1.1692 +							   backtrack.len, backtrack.array,
  1.1693 +							   input.len, input.array,
  1.1694 +							   lookahead.len, lookahead.array, lookup.len,
  1.1695 +							   lookup.array, lookup_context));
  1.1696 +  }
  1.1697 +
  1.1698 +  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1.1699 +  {
  1.1700 +    TRACE_APPLY (this);
  1.1701 +    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1.1702 +    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1.1703 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.1704 +    return TRACE_RETURN (chain_context_apply_lookup (c,
  1.1705 +						     backtrack.len, backtrack.array,
  1.1706 +						     input.len, input.array,
  1.1707 +						     lookahead.len, lookahead.array, lookup.len,
  1.1708 +						     lookup.array, lookup_context));
  1.1709 +  }
  1.1710 +
  1.1711 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1712 +    TRACE_SANITIZE (this);
  1.1713 +    if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
  1.1714 +    HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
  1.1715 +    if (!input.sanitize (c)) return TRACE_RETURN (false);
  1.1716 +    ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
  1.1717 +    if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
  1.1718 +    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.1719 +    return TRACE_RETURN (lookup.sanitize (c));
  1.1720 +  }
  1.1721 +
  1.1722 +  protected:
  1.1723 +  ArrayOf<USHORT>
  1.1724 +		backtrack;		/* Array of backtracking values
  1.1725 +					 * (to be matched before the input
  1.1726 +					 * sequence) */
  1.1727 +  HeadlessArrayOf<USHORT>
  1.1728 +		inputX;			/* Array of input values (start with
  1.1729 +					 * second glyph) */
  1.1730 +  ArrayOf<USHORT>
  1.1731 +		lookaheadX;		/* Array of lookahead values's (to be
  1.1732 +					 * matched after the input sequence) */
  1.1733 +  ArrayOf<LookupRecord>
  1.1734 +		lookupX;		/* Array of LookupRecords--in
  1.1735 +					 * design order) */
  1.1736 +  public:
  1.1737 +  DEFINE_SIZE_MIN (8);
  1.1738 +};
  1.1739 +
  1.1740 +struct ChainRuleSet
  1.1741 +{
  1.1742 +  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
  1.1743 +  {
  1.1744 +    TRACE_CLOSURE (this);
  1.1745 +    unsigned int num_rules = rule.len;
  1.1746 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1747 +      (this+rule[i]).closure (c, lookup_context);
  1.1748 +  }
  1.1749 +
  1.1750 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
  1.1751 +  {
  1.1752 +    TRACE_COLLECT_GLYPHS (this);
  1.1753 +    unsigned int num_rules = rule.len;
  1.1754 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1755 +      (this+rule[i]).collect_glyphs (c, lookup_context);
  1.1756 +  }
  1.1757 +
  1.1758 +  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1.1759 +  {
  1.1760 +    TRACE_WOULD_APPLY (this);
  1.1761 +    unsigned int num_rules = rule.len;
  1.1762 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1763 +      if ((this+rule[i]).would_apply (c, lookup_context))
  1.1764 +        return TRACE_RETURN (true);
  1.1765 +
  1.1766 +    return TRACE_RETURN (false);
  1.1767 +  }
  1.1768 +
  1.1769 +  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
  1.1770 +  {
  1.1771 +    TRACE_APPLY (this);
  1.1772 +    unsigned int num_rules = rule.len;
  1.1773 +    for (unsigned int i = 0; i < num_rules; i++)
  1.1774 +      if ((this+rule[i]).apply (c, lookup_context))
  1.1775 +        return TRACE_RETURN (true);
  1.1776 +
  1.1777 +    return TRACE_RETURN (false);
  1.1778 +  }
  1.1779 +
  1.1780 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1781 +    TRACE_SANITIZE (this);
  1.1782 +    return TRACE_RETURN (rule.sanitize (c, this));
  1.1783 +  }
  1.1784 +
  1.1785 +  protected:
  1.1786 +  OffsetArrayOf<ChainRule>
  1.1787 +		rule;			/* Array of ChainRule tables
  1.1788 +					 * ordered by preference */
  1.1789 +  public:
  1.1790 +  DEFINE_SIZE_ARRAY (2, rule);
  1.1791 +};
  1.1792 +
  1.1793 +struct ChainContextFormat1
  1.1794 +{
  1.1795 +  inline void closure (hb_closure_context_t *c) const
  1.1796 +  {
  1.1797 +    TRACE_CLOSURE (this);
  1.1798 +    const Coverage &cov = (this+coverage);
  1.1799 +
  1.1800 +    struct ChainContextClosureLookupContext lookup_context = {
  1.1801 +      {intersects_glyph},
  1.1802 +      {NULL, NULL, NULL}
  1.1803 +    };
  1.1804 +
  1.1805 +    unsigned int count = ruleSet.len;
  1.1806 +    for (unsigned int i = 0; i < count; i++)
  1.1807 +      if (cov.intersects_coverage (c->glyphs, i)) {
  1.1808 +	const ChainRuleSet &rule_set = this+ruleSet[i];
  1.1809 +	rule_set.closure (c, lookup_context);
  1.1810 +      }
  1.1811 +  }
  1.1812 +
  1.1813 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1.1814 +  {
  1.1815 +    TRACE_COLLECT_GLYPHS (this);
  1.1816 +    (this+coverage).add_coverage (c->input);
  1.1817 +
  1.1818 +    struct ChainContextCollectGlyphsLookupContext lookup_context = {
  1.1819 +      {collect_glyph},
  1.1820 +      {NULL, NULL, NULL}
  1.1821 +    };
  1.1822 +
  1.1823 +    unsigned int count = ruleSet.len;
  1.1824 +    for (unsigned int i = 0; i < count; i++)
  1.1825 +      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
  1.1826 +  }
  1.1827 +
  1.1828 +  inline bool would_apply (hb_would_apply_context_t *c) const
  1.1829 +  {
  1.1830 +    TRACE_WOULD_APPLY (this);
  1.1831 +
  1.1832 +    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
  1.1833 +    struct ChainContextApplyLookupContext lookup_context = {
  1.1834 +      {match_glyph},
  1.1835 +      {NULL, NULL, NULL}
  1.1836 +    };
  1.1837 +    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
  1.1838 +  }
  1.1839 +
  1.1840 +  inline const Coverage &get_coverage (void) const
  1.1841 +  {
  1.1842 +    return this+coverage;
  1.1843 +  }
  1.1844 +
  1.1845 +  inline bool apply (hb_apply_context_t *c) const
  1.1846 +  {
  1.1847 +    TRACE_APPLY (this);
  1.1848 +    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1.1849 +    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
  1.1850 +
  1.1851 +    const ChainRuleSet &rule_set = this+ruleSet[index];
  1.1852 +    struct ChainContextApplyLookupContext lookup_context = {
  1.1853 +      {match_glyph},
  1.1854 +      {NULL, NULL, NULL}
  1.1855 +    };
  1.1856 +    return TRACE_RETURN (rule_set.apply (c, lookup_context));
  1.1857 +  }
  1.1858 +
  1.1859 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1860 +    TRACE_SANITIZE (this);
  1.1861 +    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
  1.1862 +  }
  1.1863 +
  1.1864 +  protected:
  1.1865 +  USHORT	format;			/* Format identifier--format = 1 */
  1.1866 +  OffsetTo<Coverage>
  1.1867 +		coverage;		/* Offset to Coverage table--from
  1.1868 +					 * beginning of table */
  1.1869 +  OffsetArrayOf<ChainRuleSet>
  1.1870 +		ruleSet;		/* Array of ChainRuleSet tables
  1.1871 +					 * ordered by Coverage Index */
  1.1872 +  public:
  1.1873 +  DEFINE_SIZE_ARRAY (6, ruleSet);
  1.1874 +};
  1.1875 +
  1.1876 +struct ChainContextFormat2
  1.1877 +{
  1.1878 +  inline void closure (hb_closure_context_t *c) const
  1.1879 +  {
  1.1880 +    TRACE_CLOSURE (this);
  1.1881 +    if (!(this+coverage).intersects (c->glyphs))
  1.1882 +      return;
  1.1883 +
  1.1884 +    const ClassDef &backtrack_class_def = this+backtrackClassDef;
  1.1885 +    const ClassDef &input_class_def = this+inputClassDef;
  1.1886 +    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
  1.1887 +
  1.1888 +    struct ChainContextClosureLookupContext lookup_context = {
  1.1889 +      {intersects_class},
  1.1890 +      {&backtrack_class_def,
  1.1891 +       &input_class_def,
  1.1892 +       &lookahead_class_def}
  1.1893 +    };
  1.1894 +
  1.1895 +    unsigned int count = ruleSet.len;
  1.1896 +    for (unsigned int i = 0; i < count; i++)
  1.1897 +      if (input_class_def.intersects_class (c->glyphs, i)) {
  1.1898 +	const ChainRuleSet &rule_set = this+ruleSet[i];
  1.1899 +	rule_set.closure (c, lookup_context);
  1.1900 +      }
  1.1901 +  }
  1.1902 +
  1.1903 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1.1904 +  {
  1.1905 +    TRACE_COLLECT_GLYPHS (this);
  1.1906 +    (this+coverage).add_coverage (c->input);
  1.1907 +
  1.1908 +    const ClassDef &backtrack_class_def = this+backtrackClassDef;
  1.1909 +    const ClassDef &input_class_def = this+inputClassDef;
  1.1910 +    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
  1.1911 +
  1.1912 +    struct ChainContextCollectGlyphsLookupContext lookup_context = {
  1.1913 +      {collect_class},
  1.1914 +      {&backtrack_class_def,
  1.1915 +       &input_class_def,
  1.1916 +       &lookahead_class_def}
  1.1917 +    };
  1.1918 +
  1.1919 +    unsigned int count = ruleSet.len;
  1.1920 +    for (unsigned int i = 0; i < count; i++)
  1.1921 +      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
  1.1922 +  }
  1.1923 +
  1.1924 +  inline bool would_apply (hb_would_apply_context_t *c) const
  1.1925 +  {
  1.1926 +    TRACE_WOULD_APPLY (this);
  1.1927 +
  1.1928 +    const ClassDef &backtrack_class_def = this+backtrackClassDef;
  1.1929 +    const ClassDef &input_class_def = this+inputClassDef;
  1.1930 +    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
  1.1931 +
  1.1932 +    unsigned int index = input_class_def.get_class (c->glyphs[0]);
  1.1933 +    const ChainRuleSet &rule_set = this+ruleSet[index];
  1.1934 +    struct ChainContextApplyLookupContext lookup_context = {
  1.1935 +      {match_class},
  1.1936 +      {&backtrack_class_def,
  1.1937 +       &input_class_def,
  1.1938 +       &lookahead_class_def}
  1.1939 +    };
  1.1940 +    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
  1.1941 +  }
  1.1942 +
  1.1943 +  inline const Coverage &get_coverage (void) const
  1.1944 +  {
  1.1945 +    return this+coverage;
  1.1946 +  }
  1.1947 +
  1.1948 +  inline bool apply (hb_apply_context_t *c) const
  1.1949 +  {
  1.1950 +    TRACE_APPLY (this);
  1.1951 +    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
  1.1952 +    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
  1.1953 +
  1.1954 +    const ClassDef &backtrack_class_def = this+backtrackClassDef;
  1.1955 +    const ClassDef &input_class_def = this+inputClassDef;
  1.1956 +    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
  1.1957 +
  1.1958 +    index = input_class_def.get_class (c->buffer->cur().codepoint);
  1.1959 +    const ChainRuleSet &rule_set = this+ruleSet[index];
  1.1960 +    struct ChainContextApplyLookupContext lookup_context = {
  1.1961 +      {match_class},
  1.1962 +      {&backtrack_class_def,
  1.1963 +       &input_class_def,
  1.1964 +       &lookahead_class_def}
  1.1965 +    };
  1.1966 +    return TRACE_RETURN (rule_set.apply (c, lookup_context));
  1.1967 +  }
  1.1968 +
  1.1969 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1970 +    TRACE_SANITIZE (this);
  1.1971 +    return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
  1.1972 +			 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
  1.1973 +			 ruleSet.sanitize (c, this));
  1.1974 +  }
  1.1975 +
  1.1976 +  protected:
  1.1977 +  USHORT	format;			/* Format identifier--format = 2 */
  1.1978 +  OffsetTo<Coverage>
  1.1979 +		coverage;		/* Offset to Coverage table--from
  1.1980 +					 * beginning of table */
  1.1981 +  OffsetTo<ClassDef>
  1.1982 +		backtrackClassDef;	/* Offset to glyph ClassDef table
  1.1983 +					 * containing backtrack sequence
  1.1984 +					 * data--from beginning of table */
  1.1985 +  OffsetTo<ClassDef>
  1.1986 +		inputClassDef;		/* Offset to glyph ClassDef
  1.1987 +					 * table containing input sequence
  1.1988 +					 * data--from beginning of table */
  1.1989 +  OffsetTo<ClassDef>
  1.1990 +		lookaheadClassDef;	/* Offset to glyph ClassDef table
  1.1991 +					 * containing lookahead sequence
  1.1992 +					 * data--from beginning of table */
  1.1993 +  OffsetArrayOf<ChainRuleSet>
  1.1994 +		ruleSet;		/* Array of ChainRuleSet tables
  1.1995 +					 * ordered by class */
  1.1996 +  public:
  1.1997 +  DEFINE_SIZE_ARRAY (12, ruleSet);
  1.1998 +};
  1.1999 +
  1.2000 +struct ChainContextFormat3
  1.2001 +{
  1.2002 +  inline void closure (hb_closure_context_t *c) const
  1.2003 +  {
  1.2004 +    TRACE_CLOSURE (this);
  1.2005 +    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  1.2006 +
  1.2007 +    if (!(this+input[0]).intersects (c->glyphs))
  1.2008 +      return;
  1.2009 +
  1.2010 +    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
  1.2011 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.2012 +    struct ChainContextClosureLookupContext lookup_context = {
  1.2013 +      {intersects_coverage},
  1.2014 +      {this, this, this}
  1.2015 +    };
  1.2016 +    chain_context_closure_lookup (c,
  1.2017 +				  backtrack.len, (const USHORT *) backtrack.array,
  1.2018 +				  input.len, (const USHORT *) input.array + 1,
  1.2019 +				  lookahead.len, (const USHORT *) lookahead.array,
  1.2020 +				  lookup.len, lookup.array,
  1.2021 +				  lookup_context);
  1.2022 +  }
  1.2023 +
  1.2024 +  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
  1.2025 +  {
  1.2026 +    TRACE_COLLECT_GLYPHS (this);
  1.2027 +    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  1.2028 +
  1.2029 +    (this+input[0]).add_coverage (c->input);
  1.2030 +
  1.2031 +    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
  1.2032 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.2033 +    struct ChainContextCollectGlyphsLookupContext lookup_context = {
  1.2034 +      {collect_coverage},
  1.2035 +      {this, this, this}
  1.2036 +    };
  1.2037 +    chain_context_collect_glyphs_lookup (c,
  1.2038 +					 backtrack.len, (const USHORT *) backtrack.array,
  1.2039 +					 input.len, (const USHORT *) input.array + 1,
  1.2040 +					 lookahead.len, (const USHORT *) lookahead.array,
  1.2041 +					 lookup.len, lookup.array,
  1.2042 +					 lookup_context);
  1.2043 +  }
  1.2044 +
  1.2045 +  inline bool would_apply (hb_would_apply_context_t *c) const
  1.2046 +  {
  1.2047 +    TRACE_WOULD_APPLY (this);
  1.2048 +
  1.2049 +    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  1.2050 +    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
  1.2051 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.2052 +    struct ChainContextApplyLookupContext lookup_context = {
  1.2053 +      {match_coverage},
  1.2054 +      {this, this, this}
  1.2055 +    };
  1.2056 +    return TRACE_RETURN (chain_context_would_apply_lookup (c,
  1.2057 +							   backtrack.len, (const USHORT *) backtrack.array,
  1.2058 +							   input.len, (const USHORT *) input.array + 1,
  1.2059 +							   lookahead.len, (const USHORT *) lookahead.array,
  1.2060 +							   lookup.len, lookup.array, lookup_context));
  1.2061 +  }
  1.2062 +
  1.2063 +  inline const Coverage &get_coverage (void) const
  1.2064 +  {
  1.2065 +    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  1.2066 +    return this+input[0];
  1.2067 +  }
  1.2068 +
  1.2069 +  inline bool apply (hb_apply_context_t *c) const
  1.2070 +  {
  1.2071 +    TRACE_APPLY (this);
  1.2072 +    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  1.2073 +
  1.2074 +    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
  1.2075 +    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
  1.2076 +
  1.2077 +    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
  1.2078 +    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.2079 +    struct ChainContextApplyLookupContext lookup_context = {
  1.2080 +      {match_coverage},
  1.2081 +      {this, this, this}
  1.2082 +    };
  1.2083 +    return TRACE_RETURN (chain_context_apply_lookup (c,
  1.2084 +						     backtrack.len, (const USHORT *) backtrack.array,
  1.2085 +						     input.len, (const USHORT *) input.array + 1,
  1.2086 +						     lookahead.len, (const USHORT *) lookahead.array,
  1.2087 +						     lookup.len, lookup.array, lookup_context));
  1.2088 +  }
  1.2089 +
  1.2090 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.2091 +    TRACE_SANITIZE (this);
  1.2092 +    if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
  1.2093 +    OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
  1.2094 +    if (!input.sanitize (c, this)) return TRACE_RETURN (false);
  1.2095 +    OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
  1.2096 +    if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
  1.2097 +    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
  1.2098 +    return TRACE_RETURN (lookup.sanitize (c));
  1.2099 +  }
  1.2100 +
  1.2101 +  protected:
  1.2102 +  USHORT	format;			/* Format identifier--format = 3 */
  1.2103 +  OffsetArrayOf<Coverage>
  1.2104 +		backtrack;		/* Array of coverage tables
  1.2105 +					 * in backtracking sequence, in  glyph
  1.2106 +					 * sequence order */
  1.2107 +  OffsetArrayOf<Coverage>
  1.2108 +		inputX		;	/* Array of coverage
  1.2109 +					 * tables in input sequence, in glyph
  1.2110 +					 * sequence order */
  1.2111 +  OffsetArrayOf<Coverage>
  1.2112 +		lookaheadX;		/* Array of coverage tables
  1.2113 +					 * in lookahead sequence, in glyph
  1.2114 +					 * sequence order */
  1.2115 +  ArrayOf<LookupRecord>
  1.2116 +		lookupX;		/* Array of LookupRecords--in
  1.2117 +					 * design order) */
  1.2118 +  public:
  1.2119 +  DEFINE_SIZE_MIN (10);
  1.2120 +};
  1.2121 +
  1.2122 +struct ChainContext
  1.2123 +{
  1.2124 +  template <typename context_t>
  1.2125 +  inline typename context_t::return_t dispatch (context_t *c) const
  1.2126 +  {
  1.2127 +    TRACE_DISPATCH (this);
  1.2128 +    switch (u.format) {
  1.2129 +    case 1: return TRACE_RETURN (c->dispatch (u.format1));
  1.2130 +    case 2: return TRACE_RETURN (c->dispatch (u.format2));
  1.2131 +    case 3: return TRACE_RETURN (c->dispatch (u.format3));
  1.2132 +    default:return TRACE_RETURN (c->default_return_value ());
  1.2133 +    }
  1.2134 +  }
  1.2135 +
  1.2136 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.2137 +    TRACE_SANITIZE (this);
  1.2138 +    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
  1.2139 +    switch (u.format) {
  1.2140 +    case 1: return TRACE_RETURN (u.format1.sanitize (c));
  1.2141 +    case 2: return TRACE_RETURN (u.format2.sanitize (c));
  1.2142 +    case 3: return TRACE_RETURN (u.format3.sanitize (c));
  1.2143 +    default:return TRACE_RETURN (true);
  1.2144 +    }
  1.2145 +  }
  1.2146 +
  1.2147 +  protected:
  1.2148 +  union {
  1.2149 +  USHORT		format;	/* Format identifier */
  1.2150 +  ChainContextFormat1	format1;
  1.2151 +  ChainContextFormat2	format2;
  1.2152 +  ChainContextFormat3	format3;
  1.2153 +  } u;
  1.2154 +};
  1.2155 +
  1.2156 +
  1.2157 +struct ExtensionFormat1
  1.2158 +{
  1.2159 +  inline unsigned int get_type (void) const { return extensionLookupType; }
  1.2160 +  inline unsigned int get_offset (void) const { return extensionOffset; }
  1.2161 +
  1.2162 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.2163 +    TRACE_SANITIZE (this);
  1.2164 +    return TRACE_RETURN (c->check_struct (this));
  1.2165 +  }
  1.2166 +
  1.2167 +  protected:
  1.2168 +  USHORT	format;			/* Format identifier. Set to 1. */
  1.2169 +  USHORT	extensionLookupType;	/* Lookup type of subtable referenced
  1.2170 +					 * by ExtensionOffset (i.e. the
  1.2171 +					 * extension subtable). */
  1.2172 +  ULONG		extensionOffset;	/* Offset to the extension subtable,
  1.2173 +					 * of lookup type subtable. */
  1.2174 +  public:
  1.2175 +  DEFINE_SIZE_STATIC (8);
  1.2176 +};
  1.2177 +
  1.2178 +template <typename T>
  1.2179 +struct Extension
  1.2180 +{
  1.2181 +  inline unsigned int get_type (void) const
  1.2182 +  {
  1.2183 +    switch (u.format) {
  1.2184 +    case 1: return u.format1.get_type ();
  1.2185 +    default:return 0;
  1.2186 +    }
  1.2187 +  }
  1.2188 +  inline unsigned int get_offset (void) const
  1.2189 +  {
  1.2190 +    switch (u.format) {
  1.2191 +    case 1: return u.format1.get_offset ();
  1.2192 +    default:return 0;
  1.2193 +    }
  1.2194 +  }
  1.2195 +
  1.2196 +  template <typename X>
  1.2197 +  inline const X& get_subtable (void) const
  1.2198 +  {
  1.2199 +    unsigned int offset = get_offset ();
  1.2200 +    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
  1.2201 +    return StructAtOffset<typename T::LookupSubTable> (this, offset);
  1.2202 +  }
  1.2203 +
  1.2204 +  template <typename context_t>
  1.2205 +  inline typename context_t::return_t dispatch (context_t *c) const
  1.2206 +  {
  1.2207 +    return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
  1.2208 +  }
  1.2209 +
  1.2210 +  inline bool sanitize_self (hb_sanitize_context_t *c) {
  1.2211 +    TRACE_SANITIZE (this);
  1.2212 +    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
  1.2213 +    switch (u.format) {
  1.2214 +    case 1: return TRACE_RETURN (u.format1.sanitize (c));
  1.2215 +    default:return TRACE_RETURN (true);
  1.2216 +    }
  1.2217 +  }
  1.2218 +
  1.2219 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.2220 +    TRACE_SANITIZE (this);
  1.2221 +    if (!sanitize_self (c)) return TRACE_RETURN (false);
  1.2222 +    unsigned int offset = get_offset ();
  1.2223 +    if (unlikely (!offset)) return TRACE_RETURN (true);
  1.2224 +    return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
  1.2225 +  }
  1.2226 +
  1.2227 +  protected:
  1.2228 +  union {
  1.2229 +  USHORT		format;		/* Format identifier */
  1.2230 +  ExtensionFormat1	format1;
  1.2231 +  } u;
  1.2232 +};
  1.2233 +
  1.2234 +
  1.2235 +/*
  1.2236 + * GSUB/GPOS Common
  1.2237 + */
  1.2238 +
  1.2239 +struct GSUBGPOS
  1.2240 +{
  1.2241 +  static const hb_tag_t GSUBTag	= HB_OT_TAG_GSUB;
  1.2242 +  static const hb_tag_t GPOSTag	= HB_OT_TAG_GPOS;
  1.2243 +
  1.2244 +  inline unsigned int get_script_count (void) const
  1.2245 +  { return (this+scriptList).len; }
  1.2246 +  inline const Tag& get_script_tag (unsigned int i) const
  1.2247 +  { return (this+scriptList).get_tag (i); }
  1.2248 +  inline unsigned int get_script_tags (unsigned int start_offset,
  1.2249 +				       unsigned int *script_count /* IN/OUT */,
  1.2250 +				       hb_tag_t     *script_tags /* OUT */) const
  1.2251 +  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
  1.2252 +  inline const Script& get_script (unsigned int i) const
  1.2253 +  { return (this+scriptList)[i]; }
  1.2254 +  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
  1.2255 +  { return (this+scriptList).find_index (tag, index); }
  1.2256 +
  1.2257 +  inline unsigned int get_feature_count (void) const
  1.2258 +  { return (this+featureList).len; }
  1.2259 +  inline const Tag& get_feature_tag (unsigned int i) const
  1.2260 +  { return (this+featureList).get_tag (i); }
  1.2261 +  inline unsigned int get_feature_tags (unsigned int start_offset,
  1.2262 +					unsigned int *feature_count /* IN/OUT */,
  1.2263 +					hb_tag_t     *feature_tags /* OUT */) const
  1.2264 +  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
  1.2265 +  inline const Feature& get_feature (unsigned int i) const
  1.2266 +  { return (this+featureList)[i]; }
  1.2267 +  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
  1.2268 +  { return (this+featureList).find_index (tag, index); }
  1.2269 +
  1.2270 +  inline unsigned int get_lookup_count (void) const
  1.2271 +  { return (this+lookupList).len; }
  1.2272 +  inline const Lookup& get_lookup (unsigned int i) const
  1.2273 +  { return (this+lookupList)[i]; }
  1.2274 +
  1.2275 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.2276 +    TRACE_SANITIZE (this);
  1.2277 +    return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
  1.2278 +			 scriptList.sanitize (c, this) &&
  1.2279 +			 featureList.sanitize (c, this) &&
  1.2280 +			 lookupList.sanitize (c, this));
  1.2281 +  }
  1.2282 +
  1.2283 +  protected:
  1.2284 +  FixedVersion	version;	/* Version of the GSUB/GPOS table--initially set
  1.2285 +				 * to 0x00010000 */
  1.2286 +  OffsetTo<ScriptList>
  1.2287 +		scriptList;  	/* ScriptList table */
  1.2288 +  OffsetTo<FeatureList>
  1.2289 +		featureList; 	/* FeatureList table */
  1.2290 +  OffsetTo<LookupList>
  1.2291 +		lookupList; 	/* LookupList table */
  1.2292 +  public:
  1.2293 +  DEFINE_SIZE_STATIC (10);
  1.2294 +};
  1.2295 +
  1.2296 +
  1.2297 +} /* namespace OT */
  1.2298 +
  1.2299 +
  1.2300 +#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */

mercurial