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