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