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