Imported Upstream version 2.6.7
[platform/upstream/harfbuzz.git] / src / hb-ot-layout-common.hh
1 /*
2  * Copyright © 2007,2008,2009  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_COMMON_HH
30 #define HB_OT_LAYOUT_COMMON_HH
31
32 #include "hb.hh"
33 #include "hb-ot-layout.hh"
34 #include "hb-open-type.hh"
35 #include "hb-set.hh"
36 #include "hb-bimap.hh"
37
38
39 #ifndef HB_MAX_NESTING_LEVEL
40 #define HB_MAX_NESTING_LEVEL    6
41 #endif
42 #ifndef HB_MAX_CONTEXT_LENGTH
43 #define HB_MAX_CONTEXT_LENGTH   64
44 #endif
45 #ifndef HB_CLOSURE_MAX_STAGES
46 /*
47  * The maximum number of times a lookup can be applied during shaping.
48  * Used to limit the number of iterations of the closure algorithm.
49  * This must be larger than the number of times add_pause() is
50  * called in a collect_features call of any shaper.
51  */
52 #define HB_CLOSURE_MAX_STAGES   32
53 #endif
54
55 #ifndef HB_MAX_SCRIPTS
56 #define HB_MAX_SCRIPTS  500
57 #endif
58
59 #ifndef HB_MAX_LANGSYS
60 #define HB_MAX_LANGSYS  2000
61 #endif
62
63 #ifndef HB_MAX_FEATURES
64 #define HB_MAX_FEATURES 750
65 #endif
66
67 #ifndef HB_MAX_FEATURE_INDICES
68 #define HB_MAX_FEATURE_INDICES  1500
69 #endif
70
71 #ifndef HB_MAX_LOOKUP_INDICES
72 #define HB_MAX_LOOKUP_INDICES   20000
73 #endif
74
75
76 namespace OT {
77
78
79 #define NOT_COVERED             ((unsigned int) -1)
80
81
82 template<typename Iterator>
83 static inline void Coverage_serialize (hb_serialize_context_t *c,
84                                        Iterator it);
85
86 template<typename Iterator>
87 static inline void ClassDef_serialize (hb_serialize_context_t *c,
88                                        Iterator it);
89
90 static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
91                                           const hb_set_t &glyphset,
92                                           const hb_map_t &gid_klass_map,
93                                           hb_sorted_vector_t<HBGlyphID> &glyphs,
94                                           const hb_set_t &klasses,
95                                           hb_map_t *klass_map /*INOUT*/);
96
97 struct hb_subset_layout_context_t :
98   hb_dispatch_context_t<hb_subset_layout_context_t, hb_empty_t, HB_DEBUG_SUBSET>
99 {
100   const char *get_name () { return "SUBSET_LAYOUT"; }
101   static return_t default_return_value () { return hb_empty_t (); }
102
103   bool visitScript ()
104   {
105     return script_count++ < HB_MAX_SCRIPTS;
106   }
107
108   bool visitLangSys ()
109   {
110     return langsys_count++ < HB_MAX_LANGSYS;
111   }
112
113   bool visitFeatureIndex (int count)
114   {
115     feature_index_count += count;
116     return feature_index_count < HB_MAX_FEATURE_INDICES;
117   }
118
119   bool visitLookupIndex()
120   {
121     lookup_index_count++;
122     return lookup_index_count < HB_MAX_LOOKUP_INDICES;
123   }
124
125   hb_subset_context_t *subset_context;
126   const hb_tag_t table_tag;
127   const hb_map_t *lookup_index_map;
128   const hb_map_t *feature_index_map;
129   unsigned debug_depth;
130
131   hb_subset_layout_context_t (hb_subset_context_t *c_,
132                               hb_tag_t tag_,
133                               hb_map_t *lookup_map_,
134                               hb_map_t *feature_map_) :
135                                 subset_context (c_),
136                                 table_tag (tag_),
137                                 lookup_index_map (lookup_map_),
138                                 feature_index_map (feature_map_),
139                                 debug_depth (0),
140                                 script_count (0),
141                                 langsys_count (0),
142                                 feature_index_count (0),
143                                 lookup_index_count (0)
144   {}
145
146   private:
147   unsigned script_count;
148   unsigned langsys_count;
149   unsigned feature_index_count;
150   unsigned lookup_index_count;
151 };
152
153 struct hb_collect_variation_indices_context_t :
154        hb_dispatch_context_t<hb_collect_variation_indices_context_t, hb_empty_t, 0>
155 {
156   const char *get_name () { return "CLOSURE_LAYOUT_VARIATION_IDXES"; }
157   template <typename T>
158   return_t dispatch (const T &obj) { obj.collect_variation_indices (this); return hb_empty_t (); }
159   static return_t default_return_value () { return hb_empty_t (); }
160
161   hb_set_t *layout_variation_indices;
162   const hb_set_t *glyph_set;
163   const hb_map_t *gpos_lookups;
164   unsigned int debug_depth;
165
166   hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
167                                           const hb_set_t *glyph_set_,
168                                           const hb_map_t *gpos_lookups_) :
169                                         layout_variation_indices (layout_variation_indices_),
170                                         glyph_set (glyph_set_),
171                                         gpos_lookups (gpos_lookups_),
172                                         debug_depth (0) {}
173 };
174
175 template<typename OutputArray>
176 struct subset_offset_array_t
177 {
178   subset_offset_array_t (hb_subset_context_t *subset_context_,
179                          OutputArray& out_,
180                          const void *base_) : subset_context (subset_context_),
181                                               out (out_), base (base_) {}
182
183   template <typename T>
184   bool operator () (T&& offset)
185   {
186     auto *o = out.serialize_append (subset_context->serializer);
187     if (unlikely (!o)) return false;
188     auto snap = subset_context->serializer->snapshot ();
189     bool ret = o->serialize_subset (subset_context, offset, base);
190     if (!ret)
191     {
192       out.pop ();
193       subset_context->serializer->revert (snap);
194     }
195     return ret;
196   }
197
198   private:
199   hb_subset_context_t *subset_context;
200   OutputArray &out;
201   const void *base;
202 };
203
204
205 template<typename OutputArray, typename Arg>
206 struct subset_offset_array_arg_t
207 {
208   subset_offset_array_arg_t (hb_subset_context_t *subset_context_,
209                              OutputArray& out_,
210                              const void *base_,
211                              Arg &&arg_) : subset_context (subset_context_), out (out_),
212                                           base (base_), arg (arg_) {}
213
214   template <typename T>
215   bool operator () (T&& offset)
216   {
217     auto *o = out.serialize_append (subset_context->serializer);
218     if (unlikely (!o)) return false;
219     auto snap = subset_context->serializer->snapshot ();
220     bool ret = o->serialize_subset (subset_context, offset, base, arg);
221     if (!ret)
222     {
223       out.pop ();
224       subset_context->serializer->revert (snap);
225     }
226     return ret;
227   }
228
229   private:
230   hb_subset_context_t *subset_context;
231   OutputArray &out;
232   const void *base;
233   Arg &&arg;
234 };
235
236 /*
237  * Helper to subset an array of offsets. Subsets the thing pointed to by each offset
238  * and discards the offset in the array if the subset operation results in an empty
239  * thing.
240  */
241 struct
242 {
243   template<typename OutputArray>
244   subset_offset_array_t<OutputArray>
245   operator () (hb_subset_context_t *subset_context, OutputArray& out,
246                const void *base) const
247   { return subset_offset_array_t<OutputArray> (subset_context, out, base); }
248
249   /* Variant with one extra argument passed to serialize_subset */
250   template<typename OutputArray, typename Arg>
251   subset_offset_array_arg_t<OutputArray, Arg>
252   operator () (hb_subset_context_t *subset_context, OutputArray& out,
253                const void *base, Arg &&arg) const
254   { return subset_offset_array_arg_t<OutputArray, Arg> (subset_context, out, base, arg); }
255 }
256 HB_FUNCOBJ (subset_offset_array);
257
258 template<typename OutputArray>
259 struct subset_record_array_t
260 {
261   subset_record_array_t (hb_subset_layout_context_t *c_, OutputArray* out_,
262                          const void *base_) : subset_layout_context (c_),
263                                               out (out_), base (base_) {}
264
265   template <typename T>
266   void
267   operator () (T&& record)
268   {
269     auto snap = subset_layout_context->subset_context->serializer->snapshot ();
270     bool ret = record.subset (subset_layout_context, base);
271     if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
272     else out->len++;
273   }
274
275   private:
276   hb_subset_layout_context_t *subset_layout_context;
277   OutputArray *out;
278   const void *base;
279 };
280
281 /*
282  * Helper to subset a RecordList/record array. Subsets each Record in the array and
283  * discards the record if the subset operation returns false.
284  */
285 struct
286 {
287   template<typename OutputArray>
288   subset_record_array_t<OutputArray>
289   operator () (hb_subset_layout_context_t *c, OutputArray* out,
290                const void *base) const
291   { return subset_record_array_t<OutputArray> (c, out, base); }
292 }
293 HB_FUNCOBJ (subset_record_array);
294
295 /*
296  *
297  * OpenType Layout Common Table Formats
298  *
299  */
300
301
302 /*
303  * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
304  */
305
306 struct Record_sanitize_closure_t {
307   hb_tag_t tag;
308   const void *list_base;
309 };
310
311 template <typename Type>
312 struct Record
313 {
314   int cmp (hb_tag_t a) const { return tag.cmp (a); }
315
316   bool subset (hb_subset_layout_context_t *c, const void *base) const
317   {
318     TRACE_SUBSET (this);
319     auto *out = c->subset_context->serializer->embed (this);
320     if (unlikely (!out)) return_trace (false);
321     bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
322     return_trace (ret);
323   }
324
325   bool sanitize (hb_sanitize_context_t *c, const void *base) const
326   {
327     TRACE_SANITIZE (this);
328     const Record_sanitize_closure_t closure = {tag, base};
329     return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
330   }
331
332   Tag           tag;            /* 4-byte Tag identifier */
333   OffsetTo<Type>
334                 offset;         /* Offset from beginning of object holding
335                                  * the Record */
336   public:
337   DEFINE_SIZE_STATIC (6);
338 };
339
340 template <typename Type>
341 struct RecordArrayOf : SortedArrayOf<Record<Type>>
342 {
343   const OffsetTo<Type>& get_offset (unsigned int i) const
344   { return (*this)[i].offset; }
345   OffsetTo<Type>& get_offset (unsigned int i)
346   { return (*this)[i].offset; }
347   const Tag& get_tag (unsigned int i) const
348   { return (*this)[i].tag; }
349   unsigned int get_tags (unsigned int start_offset,
350                          unsigned int *record_count /* IN/OUT */,
351                          hb_tag_t     *record_tags /* OUT */) const
352   {
353     if (record_count) {
354       const Record<Type> *arr = this->sub_array (start_offset, record_count);
355       unsigned int count = *record_count;
356       for (unsigned int i = 0; i < count; i++)
357         record_tags[i] = arr[i].tag;
358     }
359     return this->len;
360   }
361   bool find_index (hb_tag_t tag, unsigned int *index) const
362   {
363     return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
364   }
365 };
366
367 template <typename Type>
368 struct RecordListOf : RecordArrayOf<Type>
369 {
370   const Type& operator [] (unsigned int i) const
371   { return this+this->get_offset (i); }
372
373   bool subset (hb_subset_context_t *c,
374                hb_subset_layout_context_t *l) const
375   {
376     TRACE_SUBSET (this);
377     auto *out = c->serializer->start_embed (*this);
378     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
379
380     + this->iter ()
381     | hb_apply (subset_record_array (l, out, this))
382     ;
383     return_trace (true);
384   }
385
386   bool sanitize (hb_sanitize_context_t *c) const
387   {
388     TRACE_SANITIZE (this);
389     return_trace (RecordArrayOf<Type>::sanitize (c, this));
390   }
391 };
392
393 struct Feature;
394
395 struct RecordListOfFeature : RecordListOf<Feature>
396 {
397   bool subset (hb_subset_context_t *c,
398                hb_subset_layout_context_t *l) const
399   {
400     TRACE_SUBSET (this);
401     auto *out = c->serializer->start_embed (*this);
402     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
403
404     unsigned count = this->len;
405     + hb_zip (*this, hb_range (count))
406     | hb_filter (l->feature_index_map, hb_second)
407     | hb_map (hb_first)
408     | hb_apply (subset_record_array (l, out, this))
409     ;
410     return_trace (true);
411   }
412 };
413
414 struct RangeRecord
415 {
416   int cmp (hb_codepoint_t g) const
417   { return g < first ? -1 : g <= last ? 0 : +1; }
418
419   bool sanitize (hb_sanitize_context_t *c) const
420   {
421     TRACE_SANITIZE (this);
422     return_trace (c->check_struct (this));
423   }
424
425   bool intersects (const hb_set_t *glyphs) const
426   { return glyphs->intersects (first, last); }
427
428   template <typename set_t>
429   bool collect_coverage (set_t *glyphs) const
430   { return glyphs->add_range (first, last); }
431
432   HBGlyphID     first;          /* First GlyphID in the range */
433   HBGlyphID     last;           /* Last GlyphID in the range */
434   HBUINT16      value;          /* Value */
435   public:
436   DEFINE_SIZE_STATIC (6);
437 };
438 DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
439
440
441 struct IndexArray : ArrayOf<Index>
442 {
443   bool intersects (const hb_map_t *indexes) const
444   { return hb_any (*this, indexes); }
445
446   template <typename Iterator,
447             hb_requires (hb_is_iterator (Iterator))>
448   void serialize (hb_serialize_context_t *c,
449                   hb_subset_layout_context_t *l,
450                   Iterator it)
451   {
452     if (!it) return;
453     if (unlikely (!c->extend_min ((*this)))) return;
454
455     for (const auto _ : it)
456     {
457       if (!l->visitLookupIndex()) break;
458
459       Index i;
460       i = _;
461       c->copy (i);
462       this->len++;
463     }
464   }
465
466   unsigned int get_indexes (unsigned int start_offset,
467                             unsigned int *_count /* IN/OUT */,
468                             unsigned int *_indexes /* OUT */) const
469   {
470     if (_count) {
471       const HBUINT16 *arr = this->sub_array (start_offset, _count);
472       unsigned int count = *_count;
473       for (unsigned int i = 0; i < count; i++)
474         _indexes[i] = arr[i];
475     }
476     return this->len;
477   }
478
479   void add_indexes_to (hb_set_t* output /* OUT */) const
480   {
481     output->add_array (arrayZ, len);
482   }
483 };
484
485
486 struct LangSys
487 {
488   unsigned int get_feature_count () const
489   { return featureIndex.len; }
490   hb_tag_t get_feature_index (unsigned int i) const
491   { return featureIndex[i]; }
492   unsigned int get_feature_indexes (unsigned int start_offset,
493                                     unsigned int *feature_count /* IN/OUT */,
494                                     unsigned int *feature_indexes /* OUT */) const
495   { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
496   void add_feature_indexes_to (hb_set_t *feature_indexes) const
497   { featureIndex.add_indexes_to (feature_indexes); }
498
499   bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
500   unsigned int get_required_feature_index () const
501   {
502     if (reqFeatureIndex == 0xFFFFu)
503       return Index::NOT_FOUND_INDEX;
504    return reqFeatureIndex;
505   }
506
507   LangSys* copy (hb_serialize_context_t *c) const
508   {
509     TRACE_SERIALIZE (this);
510     return_trace (c->embed (*this));
511   }
512
513   bool operator == (const LangSys& o) const
514   {
515     if (featureIndex.len != o.featureIndex.len ||
516         reqFeatureIndex != o.reqFeatureIndex)
517       return false;
518
519     for (const auto _ : + hb_zip (featureIndex, o.featureIndex))
520       if (_.first != _.second) return false;
521
522     return true;
523   }
524
525   bool subset (hb_subset_context_t        *c,
526                hb_subset_layout_context_t *l,
527                const Tag                  *tag = nullptr) const
528   {
529     TRACE_SUBSET (this);
530     auto *out = c->serializer->start_embed (*this);
531     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
532
533     out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex) ? l->feature_index_map->get (reqFeatureIndex) : 0xFFFFu;
534
535     if (!l->visitFeatureIndex (featureIndex.len))
536       return_trace (false);
537
538     auto it =
539     + hb_iter (featureIndex)
540     | hb_filter (l->feature_index_map)
541     | hb_map (l->feature_index_map)
542     ;
543
544     bool ret = bool (it);
545     out->featureIndex.serialize (c->serializer, l, it);
546     return_trace (ret);
547   }
548
549   bool sanitize (hb_sanitize_context_t *c,
550                  const Record_sanitize_closure_t * = nullptr) const
551   {
552     TRACE_SANITIZE (this);
553     return_trace (c->check_struct (this) && featureIndex.sanitize (c));
554   }
555
556   Offset16      lookupOrderZ;   /* = Null (reserved for an offset to a
557                                  * reordering table) */
558   HBUINT16      reqFeatureIndex;/* Index of a feature required for this
559                                  * language system--if no required features
560                                  * = 0xFFFFu */
561   IndexArray    featureIndex;   /* Array of indices into the FeatureList */
562   public:
563   DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
564 };
565 DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
566
567 struct Script
568 {
569   unsigned int get_lang_sys_count () const
570   { return langSys.len; }
571   const Tag& get_lang_sys_tag (unsigned int i) const
572   { return langSys.get_tag (i); }
573   unsigned int get_lang_sys_tags (unsigned int start_offset,
574                                   unsigned int *lang_sys_count /* IN/OUT */,
575                                   hb_tag_t     *lang_sys_tags /* OUT */) const
576   { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
577   const LangSys& get_lang_sys (unsigned int i) const
578   {
579     if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
580     return this+langSys[i].offset;
581   }
582   bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
583   { return langSys.find_index (tag, index); }
584
585   bool has_default_lang_sys () const           { return defaultLangSys != 0; }
586   const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
587
588   bool subset (hb_subset_context_t         *c,
589                hb_subset_layout_context_t  *l,
590                const Tag                   *tag) const
591   {
592     TRACE_SUBSET (this);
593     if (!l->visitScript ()) return_trace (false);
594
595     auto *out = c->serializer->start_embed (*this);
596     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
597
598     bool defaultLang = false;
599     if (has_default_lang_sys ())
600     {
601       c->serializer->push ();
602       const LangSys& ls = this+defaultLangSys;
603       bool ret = ls.subset (c, l);
604       if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
605       {
606         c->serializer->pop_discard ();
607         out->defaultLangSys = 0;
608       }
609       else
610       {
611         c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
612         defaultLang = true;
613       }
614     }
615
616     + langSys.iter ()
617     | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
618     | hb_filter ([&] (const Record<LangSys>& record)
619                  {
620                    const LangSys& d = this+defaultLangSys;
621                    const LangSys& l = this+record.offset;
622                    return !(l == d);
623                  })
624     | hb_apply (subset_record_array (l, &(out->langSys), this))
625     ;
626
627     return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
628   }
629
630   bool sanitize (hb_sanitize_context_t *c,
631                  const Record_sanitize_closure_t * = nullptr) const
632   {
633     TRACE_SANITIZE (this);
634     return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
635   }
636
637   protected:
638   OffsetTo<LangSys>
639                 defaultLangSys; /* Offset to DefaultLangSys table--from
640                                  * beginning of Script table--may be Null */
641   RecordArrayOf<LangSys>
642                 langSys;        /* Array of LangSysRecords--listed
643                                  * alphabetically by LangSysTag */
644   public:
645   DEFINE_SIZE_ARRAY_SIZED (4, langSys);
646 };
647
648 typedef RecordListOf<Script> ScriptList;
649
650
651 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
652 struct FeatureParamsSize
653 {
654   bool sanitize (hb_sanitize_context_t *c) const
655   {
656     TRACE_SANITIZE (this);
657     if (unlikely (!c->check_struct (this))) return_trace (false);
658
659     /* This subtable has some "history", if you will.  Some earlier versions of
660      * Adobe tools calculated the offset of the FeatureParams sutable from the
661      * beginning of the FeatureList table!  Now, that is dealt with in the
662      * Feature implementation.  But we still need to be able to tell junk from
663      * real data.  Note: We don't check that the nameID actually exists.
664      *
665      * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
666      *
667      * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
668      * coming out soon, and that the makeotf program will build a font with a
669      * 'size' feature that is correct by the specification.
670      *
671      * The specification for this feature tag is in the "OpenType Layout Tag
672      * Registry". You can see a copy of this at:
673      * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
674      *
675      * Here is one set of rules to determine if the 'size' feature is built
676      * correctly, or as by the older versions of MakeOTF. You may be able to do
677      * better.
678      *
679      * Assume that the offset to the size feature is according to specification,
680      * and make the following value checks. If it fails, assume the size
681      * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
682      * If this fails, reject the 'size' feature. The older makeOTF's calculated the
683      * offset from the beginning of the FeatureList table, rather than from the
684      * beginning of the 'size' Feature table.
685      *
686      * If "design size" == 0:
687      *     fails check
688      *
689      * Else if ("subfamily identifier" == 0 and
690      *     "range start" == 0 and
691      *     "range end" == 0 and
692      *     "range start" == 0 and
693      *     "menu name ID" == 0)
694      *     passes check: this is the format used when there is a design size
695      * specified, but there is no recommended size range.
696      *
697      * Else if ("design size" <  "range start" or
698      *     "design size" >   "range end" or
699      *     "range end" <= "range start" or
700      *     "menu name ID"  < 256 or
701      *     "menu name ID"  > 32767 or
702      *     menu name ID is not a name ID which is actually in the name table)
703      *     fails test
704      * Else
705      *     passes test.
706      */
707
708     if (!designSize)
709       return_trace (false);
710     else if (subfamilyID == 0 &&
711              subfamilyNameID == 0 &&
712              rangeStart == 0 &&
713              rangeEnd == 0)
714       return_trace (true);
715     else if (designSize < rangeStart ||
716              designSize > rangeEnd ||
717              subfamilyNameID < 256 ||
718              subfamilyNameID > 32767)
719       return_trace (false);
720     else
721       return_trace (true);
722   }
723
724   bool subset (hb_subset_context_t *c) const
725   {
726     TRACE_SUBSET (this);
727     return_trace ((bool) c->serializer->embed (*this));
728   }
729
730   HBUINT16      designSize;     /* Represents the design size in 720/inch
731                                  * units (decipoints).  The design size entry
732                                  * must be non-zero.  When there is a design
733                                  * size but no recommended size range, the
734                                  * rest of the array will consist of zeros. */
735   HBUINT16      subfamilyID;    /* Has no independent meaning, but serves
736                                  * as an identifier that associates fonts
737                                  * in a subfamily. All fonts which share a
738                                  * Preferred or Font Family name and which
739                                  * differ only by size range shall have the
740                                  * same subfamily value, and no fonts which
741                                  * differ in weight or style shall have the
742                                  * same subfamily value. If this value is
743                                  * zero, the remaining fields in the array
744                                  * will be ignored. */
745   NameID        subfamilyNameID;/* If the preceding value is non-zero, this
746                                  * value must be set in the range 256 - 32767
747                                  * (inclusive). It records the value of a
748                                  * field in the name table, which must
749                                  * contain English-language strings encoded
750                                  * in Windows Unicode and Macintosh Roman,
751                                  * and may contain additional strings
752                                  * localized to other scripts and languages.
753                                  * Each of these strings is the name an
754                                  * application should use, in combination
755                                  * with the family name, to represent the
756                                  * subfamily in a menu.  Applications will
757                                  * choose the appropriate version based on
758                                  * their selection criteria. */
759   HBUINT16      rangeStart;     /* Large end of the recommended usage range
760                                  * (inclusive), stored in 720/inch units
761                                  * (decipoints). */
762   HBUINT16      rangeEnd;       /* Small end of the recommended usage range
763                                    (exclusive), stored in 720/inch units
764                                  * (decipoints). */
765   public:
766   DEFINE_SIZE_STATIC (10);
767 };
768
769 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
770 struct FeatureParamsStylisticSet
771 {
772   bool sanitize (hb_sanitize_context_t *c) const
773   {
774     TRACE_SANITIZE (this);
775     /* Right now minorVersion is at zero.  Which means, any table supports
776      * the uiNameID field. */
777     return_trace (c->check_struct (this));
778   }
779
780   bool subset (hb_subset_context_t *c) const
781   {
782     TRACE_SUBSET (this);
783     return_trace ((bool) c->serializer->embed (*this));
784   }
785
786   HBUINT16      version;        /* (set to 0): This corresponds to a “minor”
787                                  * version number. Additional data may be
788                                  * added to the end of this Feature Parameters
789                                  * table in the future. */
790
791   NameID        uiNameID;       /* The 'name' table name ID that specifies a
792                                  * string (or strings, for multiple languages)
793                                  * for a user-interface label for this
794                                  * feature.  The values of uiLabelNameId and
795                                  * sampleTextNameId are expected to be in the
796                                  * font-specific name ID range (256-32767),
797                                  * though that is not a requirement in this
798                                  * Feature Parameters specification. The
799                                  * user-interface label for the feature can
800                                  * be provided in multiple languages. An
801                                  * English string should be included as a
802                                  * fallback. The string should be kept to a
803                                  * minimal length to fit comfortably with
804                                  * different application interfaces. */
805   public:
806   DEFINE_SIZE_STATIC (4);
807 };
808
809 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
810 struct FeatureParamsCharacterVariants
811 {
812   bool sanitize (hb_sanitize_context_t *c) const
813   {
814     TRACE_SANITIZE (this);
815     return_trace (c->check_struct (this) &&
816                   characters.sanitize (c));
817   }
818
819   unsigned get_size () const
820   { return min_size + characters.len * HBUINT24::static_size; }
821
822   bool subset (hb_subset_context_t *c) const
823   {
824     TRACE_SUBSET (this);
825     return_trace ((bool) c->serializer->embed (*this));
826   }
827
828   HBUINT16      format;                 /* Format number is set to 0. */
829   NameID        featUILableNameID;      /* The ‘name’ table name ID that
830                                          * specifies a string (or strings,
831                                          * for multiple languages) for a
832                                          * user-interface label for this
833                                          * feature. (May be NULL.) */
834   NameID        featUITooltipTextNameID;/* The ‘name’ table name ID that
835                                          * specifies a string (or strings,
836                                          * for multiple languages) that an
837                                          * application can use for tooltip
838                                          * text for this feature. (May be
839                                          * nullptr.) */
840   NameID        sampleTextNameID;       /* The ‘name’ table name ID that
841                                          * specifies sample text that
842                                          * illustrates the effect of this
843                                          * feature. (May be NULL.) */
844   HBUINT16      numNamedParameters;     /* Number of named parameters. (May
845                                          * be zero.) */
846   NameID        firstParamUILabelNameID;/* The first ‘name’ table name ID
847                                          * used to specify strings for
848                                          * user-interface labels for the
849                                          * feature parameters. (Must be zero
850                                          * if numParameters is zero.) */
851   ArrayOf<HBUINT24>
852                 characters;             /* Array of the Unicode Scalar Value
853                                          * of the characters for which this
854                                          * feature provides glyph variants.
855                                          * (May be zero.) */
856   public:
857   DEFINE_SIZE_ARRAY (14, characters);
858 };
859
860 struct FeatureParams
861 {
862   bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
863   {
864 #ifdef HB_NO_LAYOUT_FEATURE_PARAMS
865     return true;
866 #endif
867     TRACE_SANITIZE (this);
868     if (tag == HB_TAG ('s','i','z','e'))
869       return_trace (u.size.sanitize (c));
870     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
871       return_trace (u.stylisticSet.sanitize (c));
872     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
873       return_trace (u.characterVariants.sanitize (c));
874     return_trace (true);
875   }
876
877   bool subset (hb_subset_context_t *c, const Tag* tag) const
878   {
879     TRACE_SUBSET (this);
880     if (!tag) return_trace (false);
881     if (*tag == HB_TAG ('s','i','z','e'))
882       return_trace (u.size.subset (c));
883     if ((*tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
884       return_trace (u.stylisticSet.subset (c));
885     if ((*tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
886       return_trace (u.characterVariants.subset (c));
887     return_trace (false);
888   }
889
890 #ifndef HB_NO_LAYOUT_FEATURE_PARAMS
891   const FeatureParamsSize& get_size_params (hb_tag_t tag) const
892   {
893     if (tag == HB_TAG ('s','i','z','e'))
894       return u.size;
895     return Null (FeatureParamsSize);
896   }
897   const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
898   {
899     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
900       return u.stylisticSet;
901     return Null (FeatureParamsStylisticSet);
902   }
903   const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
904   {
905     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
906       return u.characterVariants;
907     return Null (FeatureParamsCharacterVariants);
908   }
909 #endif
910
911   private:
912   union {
913   FeatureParamsSize                     size;
914   FeatureParamsStylisticSet             stylisticSet;
915   FeatureParamsCharacterVariants        characterVariants;
916   } u;
917   public:
918   DEFINE_SIZE_MIN (0);
919 };
920
921 struct Feature
922 {
923   unsigned int get_lookup_count () const
924   { return lookupIndex.len; }
925   hb_tag_t get_lookup_index (unsigned int i) const
926   { return lookupIndex[i]; }
927   unsigned int get_lookup_indexes (unsigned int start_index,
928                                    unsigned int *lookup_count /* IN/OUT */,
929                                    unsigned int *lookup_tags /* OUT */) const
930   { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
931   void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
932   { lookupIndex.add_indexes_to (lookup_indexes); }
933
934   const FeatureParams &get_feature_params () const
935   { return this+featureParams; }
936
937   bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
938   { return lookupIndex.intersects (lookup_indexes); }
939
940   bool subset (hb_subset_context_t         *c,
941                hb_subset_layout_context_t  *l,
942                const Tag                   *tag = nullptr) const
943   {
944     TRACE_SUBSET (this);
945     auto *out = c->serializer->start_embed (*this);
946     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
947
948     bool subset_featureParams = out->featureParams.serialize_subset (c, featureParams, this, tag);
949
950     auto it =
951     + hb_iter (lookupIndex)
952     | hb_filter (l->lookup_index_map)
953     | hb_map (l->lookup_index_map)
954     ;
955
956     out->lookupIndex.serialize (c->serializer, l, it);
957     return_trace (bool (it) || subset_featureParams
958                   || (tag && *tag == HB_TAG ('p', 'r', 'e', 'f')));
959   }
960
961   bool sanitize (hb_sanitize_context_t *c,
962                  const Record_sanitize_closure_t *closure = nullptr) const
963   {
964     TRACE_SANITIZE (this);
965     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
966       return_trace (false);
967
968     /* Some earlier versions of Adobe tools calculated the offset of the
969      * FeatureParams subtable from the beginning of the FeatureList table!
970      *
971      * If sanitizing "failed" for the FeatureParams subtable, try it with the
972      * alternative location.  We would know sanitize "failed" if old value
973      * of the offset was non-zero, but it's zeroed now.
974      *
975      * Only do this for the 'size' feature, since at the time of the faulty
976      * Adobe tools, only the 'size' feature had FeatureParams defined.
977      */
978
979     if (likely (featureParams.is_null ()))
980       return_trace (true);
981
982     unsigned int orig_offset = featureParams;
983     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
984       return_trace (false);
985
986     if (featureParams == 0 && closure &&
987         closure->tag == HB_TAG ('s','i','z','e') &&
988         closure->list_base && closure->list_base < this)
989     {
990       unsigned int new_offset_int = orig_offset -
991                                     (((char *) this) - ((char *) closure->list_base));
992
993       OffsetTo<FeatureParams> new_offset;
994       /* Check that it would not overflow. */
995       new_offset = new_offset_int;
996       if (new_offset == new_offset_int &&
997           c->try_set (&featureParams, new_offset_int) &&
998           !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
999         return_trace (false);
1000     }
1001
1002     return_trace (true);
1003   }
1004
1005   OffsetTo<FeatureParams>
1006                  featureParams; /* Offset to Feature Parameters table (if one
1007                                  * has been defined for the feature), relative
1008                                  * to the beginning of the Feature Table; = Null
1009                                  * if not required */
1010   IndexArray     lookupIndex;   /* Array of LookupList indices */
1011   public:
1012   DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
1013 };
1014
1015 typedef RecordListOf<Feature> FeatureList;
1016
1017
1018 struct LookupFlag : HBUINT16
1019 {
1020   enum Flags {
1021     RightToLeft         = 0x0001u,
1022     IgnoreBaseGlyphs    = 0x0002u,
1023     IgnoreLigatures     = 0x0004u,
1024     IgnoreMarks         = 0x0008u,
1025     IgnoreFlags         = 0x000Eu,
1026     UseMarkFilteringSet = 0x0010u,
1027     Reserved            = 0x00E0u,
1028     MarkAttachmentType  = 0xFF00u
1029   };
1030   public:
1031   DEFINE_SIZE_STATIC (2);
1032 };
1033
1034 } /* namespace OT */
1035 /* This has to be outside the namespace. */
1036 HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
1037 namespace OT {
1038
1039 struct Lookup
1040 {
1041   unsigned int get_subtable_count () const { return subTable.len; }
1042
1043   template <typename TSubTable>
1044   const OffsetArrayOf<TSubTable>& get_subtables () const
1045   { return reinterpret_cast<const OffsetArrayOf<TSubTable> &> (subTable); }
1046   template <typename TSubTable>
1047   OffsetArrayOf<TSubTable>& get_subtables ()
1048   { return reinterpret_cast<OffsetArrayOf<TSubTable> &> (subTable); }
1049
1050   template <typename TSubTable>
1051   const TSubTable& get_subtable (unsigned int i) const
1052   { return this+get_subtables<TSubTable> ()[i]; }
1053   template <typename TSubTable>
1054   TSubTable& get_subtable (unsigned int i)
1055   { return this+get_subtables<TSubTable> ()[i]; }
1056
1057   unsigned int get_size () const
1058   {
1059     const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
1060     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1061       return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
1062     return (const char *) &markFilteringSet - (const char *) this;
1063   }
1064
1065   unsigned int get_type () const { return lookupType; }
1066
1067   /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
1068    * higher 16-bit is mark-filtering-set if the lookup uses one.
1069    * Not to be confused with glyph_props which is very similar. */
1070   uint32_t get_props () const
1071   {
1072     unsigned int flag = lookupFlag;
1073     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
1074     {
1075       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1076       flag += (markFilteringSet << 16);
1077     }
1078     return flag;
1079   }
1080
1081   template <typename TSubTable, typename context_t, typename ...Ts>
1082   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
1083   {
1084     unsigned int lookup_type = get_type ();
1085     TRACE_DISPATCH (this, lookup_type);
1086     unsigned int count = get_subtable_count ();
1087     for (unsigned int i = 0; i < count; i++) {
1088       typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...);
1089       if (c->stop_sublookup_iteration (r))
1090         return_trace (r);
1091     }
1092     return_trace (c->default_return_value ());
1093   }
1094
1095   bool serialize (hb_serialize_context_t *c,
1096                   unsigned int lookup_type,
1097                   uint32_t lookup_props,
1098                   unsigned int num_subtables)
1099   {
1100     TRACE_SERIALIZE (this);
1101     if (unlikely (!c->extend_min (*this))) return_trace (false);
1102     lookupType = lookup_type;
1103     lookupFlag = lookup_props & 0xFFFFu;
1104     if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
1105     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1106     {
1107       if (unlikely (!c->extend (*this))) return_trace (false);
1108       HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1109       markFilteringSet = lookup_props >> 16;
1110     }
1111     return_trace (true);
1112   }
1113
1114   template <typename TSubTable>
1115   bool subset (hb_subset_context_t *c) const
1116   {
1117     TRACE_SUBSET (this);
1118     auto *out = c->serializer->start_embed (*this);
1119     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
1120     out->lookupType = lookupType;
1121     out->lookupFlag = lookupFlag;
1122
1123     const hb_set_t *glyphset = c->plan->glyphset ();
1124     unsigned int lookup_type = get_type ();
1125     + hb_iter (get_subtables <TSubTable> ())
1126     | hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
1127     | hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, lookup_type))
1128     ;
1129
1130     return_trace (true);
1131   }
1132
1133   template <typename TSubTable>
1134   bool sanitize (hb_sanitize_context_t *c) const
1135   {
1136     TRACE_SANITIZE (this);
1137     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1138
1139     unsigned subtables = get_subtable_count ();
1140     if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1141
1142     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1143     {
1144       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1145       if (!markFilteringSet.sanitize (c)) return_trace (false);
1146     }
1147
1148     if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1149       return_trace (false);
1150
1151     if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
1152     {
1153       /* The spec says all subtables of an Extension lookup should
1154        * have the same type, which shall not be the Extension type
1155        * itself (but we already checked for that).
1156        * This is specially important if one has a reverse type!
1157        *
1158        * We only do this if sanitizer edit_count is zero.  Otherwise,
1159        * some of the subtables might have become insane after they
1160        * were sanity-checked by the edits of subsequent subtables.
1161        * https://bugs.chromium.org/p/chromium/issues/detail?id=960331
1162        */
1163       unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1164       for (unsigned int i = 1; i < subtables; i++)
1165         if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1166           return_trace (false);
1167     }
1168     return_trace (true);
1169   }
1170
1171   private:
1172   HBUINT16      lookupType;             /* Different enumerations for GSUB and GPOS */
1173   HBUINT16      lookupFlag;             /* Lookup qualifiers */
1174   ArrayOf<Offset16>
1175                 subTable;               /* Array of SubTables */
1176 /*HBUINT16      markFilteringSetX[HB_VAR_ARRAY];*//* Index (base 0) into GDEF mark glyph sets
1177                                          * structure. This field is only present if bit
1178                                          * UseMarkFilteringSet of lookup flags is set. */
1179   public:
1180   DEFINE_SIZE_ARRAY (6, subTable);
1181 };
1182
1183 typedef OffsetListOf<Lookup> LookupList;
1184
1185 template <typename TLookup>
1186 struct LookupOffsetList : OffsetListOf<TLookup>
1187 {
1188   bool subset (hb_subset_context_t        *c,
1189                hb_subset_layout_context_t *l) const
1190   {
1191     TRACE_SUBSET (this);
1192     auto *out = c->serializer->start_embed (this);
1193     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
1194
1195     unsigned count = this->len;
1196     + hb_zip (*this, hb_range (count))
1197     | hb_filter (l->lookup_index_map, hb_second)
1198     | hb_map (hb_first)
1199     | hb_apply (subset_offset_array (c, *out, this))
1200     ;
1201     return_trace (true);
1202   }
1203
1204   bool sanitize (hb_sanitize_context_t *c) const
1205   {
1206     TRACE_SANITIZE (this);
1207     return_trace (OffsetListOf<TLookup>::sanitize (c, this));
1208   }
1209 };
1210
1211
1212 /*
1213  * Coverage Table
1214  */
1215
1216 struct CoverageFormat1
1217 {
1218   friend struct Coverage;
1219
1220   private:
1221   unsigned int get_coverage (hb_codepoint_t glyph_id) const
1222   {
1223     unsigned int i;
1224     glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
1225     return i;
1226   }
1227
1228   template <typename Iterator,
1229       hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1230   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
1231   {
1232     TRACE_SERIALIZE (this);
1233     return_trace (glyphArray.serialize (c, glyphs));
1234   }
1235
1236   bool sanitize (hb_sanitize_context_t *c) const
1237   {
1238     TRACE_SANITIZE (this);
1239     return_trace (glyphArray.sanitize (c));
1240   }
1241
1242   bool intersects (const hb_set_t *glyphs) const
1243   {
1244     /* TODO Speed up, using hb_set_next() and bsearch()? */
1245     unsigned int count = glyphArray.len;
1246     for (unsigned int i = 0; i < count; i++)
1247       if (glyphs->has (glyphArray[i]))
1248         return true;
1249     return false;
1250   }
1251   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
1252   { return glyphs->has (glyphArray[index]); }
1253
1254   template <typename set_t>
1255   bool collect_coverage (set_t *glyphs) const
1256   { return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len); }
1257
1258   public:
1259   /* Older compilers need this to be public. */
1260   struct iter_t
1261   {
1262     void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
1263     void fini () {}
1264     bool more () const { return i < c->glyphArray.len; }
1265     void next () { i++; }
1266     hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
1267     bool operator != (const iter_t& o) const
1268     { return i != o.i || c != o.c; }
1269
1270     private:
1271     const struct CoverageFormat1 *c;
1272     unsigned int i;
1273   };
1274   private:
1275
1276   protected:
1277   HBUINT16      coverageFormat; /* Format identifier--format = 1 */
1278   SortedArrayOf<HBGlyphID>
1279                 glyphArray;     /* Array of GlyphIDs--in numerical order */
1280   public:
1281   DEFINE_SIZE_ARRAY (4, glyphArray);
1282 };
1283
1284 struct CoverageFormat2
1285 {
1286   friend struct Coverage;
1287
1288   private:
1289   unsigned int get_coverage (hb_codepoint_t glyph_id) const
1290   {
1291     const RangeRecord &range = rangeRecord.bsearch (glyph_id);
1292     return likely (range.first <= range.last) ?
1293            (unsigned int) range.value + (glyph_id - range.first) :
1294            NOT_COVERED;
1295   }
1296
1297   template <typename Iterator,
1298       hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1299   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
1300   {
1301     TRACE_SERIALIZE (this);
1302     if (unlikely (!c->extend_min (*this))) return_trace (false);
1303
1304     if (unlikely (!glyphs))
1305     {
1306       rangeRecord.len = 0;
1307       return_trace (true);
1308     }
1309
1310     /* TODO(iter) Write more efficiently? */
1311
1312     unsigned num_ranges = 0;
1313     hb_codepoint_t last = (hb_codepoint_t) -2;
1314     for (auto g: glyphs)
1315     {
1316       if (last + 1 != g)
1317         num_ranges++;
1318       last = g;
1319     }
1320
1321     if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
1322
1323     unsigned count = 0;
1324     unsigned range = (unsigned) -1;
1325     last = (hb_codepoint_t) -2;
1326     for (auto g: glyphs)
1327     {
1328       if (last + 1 != g)
1329       {
1330         range++;
1331         rangeRecord[range].first = g;
1332         rangeRecord[range].value = count;
1333       }
1334       rangeRecord[range].last = g;
1335       last = g;
1336       count++;
1337     }
1338
1339     return_trace (true);
1340   }
1341
1342   bool sanitize (hb_sanitize_context_t *c) const
1343   {
1344     TRACE_SANITIZE (this);
1345     return_trace (rangeRecord.sanitize (c));
1346   }
1347
1348   bool intersects (const hb_set_t *glyphs) const
1349   {
1350     /* TODO Speed up, using hb_set_next() and bsearch()? */
1351     unsigned int count = rangeRecord.len;
1352     for (unsigned int i = 0; i < count; i++)
1353       if (rangeRecord[i].intersects (glyphs))
1354         return true;
1355     return false;
1356   }
1357   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
1358   {
1359     unsigned int i;
1360     unsigned int count = rangeRecord.len;
1361     for (i = 0; i < count; i++) {
1362       const RangeRecord &range = rangeRecord[i];
1363       if (range.value <= index &&
1364           index < (unsigned int) range.value + (range.last - range.first) &&
1365           range.intersects (glyphs))
1366         return true;
1367       else if (index < range.value)
1368         return false;
1369     }
1370     return false;
1371   }
1372
1373   template <typename set_t>
1374   bool collect_coverage (set_t *glyphs) const
1375   {
1376     unsigned int count = rangeRecord.len;
1377     for (unsigned int i = 0; i < count; i++)
1378       if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
1379         return false;
1380     return true;
1381   }
1382
1383   public:
1384   /* Older compilers need this to be public. */
1385   struct iter_t
1386   {
1387     void init (const CoverageFormat2 &c_)
1388     {
1389       c = &c_;
1390       coverage = 0;
1391       i = 0;
1392       j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
1393       if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
1394       {
1395         /* Broken table. Skip. */
1396         i = c->rangeRecord.len;
1397       }
1398     }
1399     void fini () {}
1400     bool more () const { return i < c->rangeRecord.len; }
1401     void next ()
1402     {
1403       if (j >= c->rangeRecord[i].last)
1404       {
1405         i++;
1406         if (more ())
1407         {
1408           unsigned int old = coverage;
1409           j = c->rangeRecord[i].first;
1410           coverage = c->rangeRecord[i].value;
1411           if (unlikely (coverage != old + 1))
1412           {
1413             /* Broken table. Skip. Important to avoid DoS.
1414              * Also, our callers depend on coverage being
1415              * consecutive and monotonically increasing,
1416              * ie. iota(). */
1417            i = c->rangeRecord.len;
1418            return;
1419           }
1420         }
1421         return;
1422       }
1423       coverage++;
1424       j++;
1425     }
1426     hb_codepoint_t get_glyph () const { return j; }
1427     bool operator != (const iter_t& o) const
1428     { return i != o.i || j != o.j || c != o.c; }
1429
1430     private:
1431     const struct CoverageFormat2 *c;
1432     unsigned int i, coverage;
1433     hb_codepoint_t j;
1434   };
1435   private:
1436
1437   protected:
1438   HBUINT16      coverageFormat; /* Format identifier--format = 2 */
1439   SortedArrayOf<RangeRecord>
1440                 rangeRecord;    /* Array of glyph ranges--ordered by
1441                                  * Start GlyphID. rangeCount entries
1442                                  * long */
1443   public:
1444   DEFINE_SIZE_ARRAY (4, rangeRecord);
1445 };
1446
1447 struct Coverage
1448 {
1449   /* Has interface. */
1450   static constexpr unsigned SENTINEL = NOT_COVERED;
1451   typedef unsigned int value_t;
1452   value_t operator [] (hb_codepoint_t k) const { return get (k); }
1453   bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
1454   /* Predicate. */
1455   bool operator () (hb_codepoint_t k) const { return has (k); }
1456
1457   unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
1458   unsigned int get_coverage (hb_codepoint_t glyph_id) const
1459   {
1460     switch (u.format) {
1461     case 1: return u.format1.get_coverage (glyph_id);
1462     case 2: return u.format2.get_coverage (glyph_id);
1463     default:return NOT_COVERED;
1464     }
1465   }
1466
1467   template <typename Iterator,
1468       hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1469   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
1470   {
1471     TRACE_SERIALIZE (this);
1472     if (unlikely (!c->extend_min (*this))) return_trace (false);
1473
1474     unsigned count = 0;
1475     unsigned num_ranges = 0;
1476     hb_codepoint_t last = (hb_codepoint_t) -2;
1477     for (auto g: glyphs)
1478     {
1479       if (last + 1 != g)
1480         num_ranges++;
1481       last = g;
1482       count++;
1483     }
1484     u.format = count <= num_ranges * 3 ? 1 : 2;
1485
1486     switch (u.format)
1487     {
1488     case 1: return_trace (u.format1.serialize (c, glyphs));
1489     case 2: return_trace (u.format2.serialize (c, glyphs));
1490     default:return_trace (false);
1491     }
1492   }
1493
1494   bool subset (hb_subset_context_t *c) const
1495   {
1496     TRACE_SUBSET (this);
1497     const hb_set_t &glyphset = *c->plan->glyphset ();
1498     const hb_map_t &glyph_map = *c->plan->glyph_map;
1499
1500     auto it =
1501     + iter ()
1502     | hb_filter (glyphset)
1503     | hb_map_retains_sorting (glyph_map)
1504     ;
1505
1506     bool ret = bool (it);
1507     Coverage_serialize (c->serializer, it);
1508     return_trace (ret);
1509   }
1510
1511   bool sanitize (hb_sanitize_context_t *c) const
1512   {
1513     TRACE_SANITIZE (this);
1514     if (!u.format.sanitize (c)) return_trace (false);
1515     switch (u.format)
1516     {
1517     case 1: return_trace (u.format1.sanitize (c));
1518     case 2: return_trace (u.format2.sanitize (c));
1519     default:return_trace (true);
1520     }
1521   }
1522
1523   bool intersects (const hb_set_t *glyphs) const
1524   {
1525     switch (u.format)
1526     {
1527     case 1: return u.format1.intersects (glyphs);
1528     case 2: return u.format2.intersects (glyphs);
1529     default:return false;
1530     }
1531   }
1532   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
1533   {
1534     switch (u.format)
1535     {
1536     case 1: return u.format1.intersects_coverage (glyphs, index);
1537     case 2: return u.format2.intersects_coverage (glyphs, index);
1538     default:return false;
1539     }
1540   }
1541
1542   /* Might return false if array looks unsorted.
1543    * Used for faster rejection of corrupt data. */
1544   template <typename set_t>
1545   bool collect_coverage (set_t *glyphs) const
1546   {
1547     switch (u.format)
1548     {
1549     case 1: return u.format1.collect_coverage (glyphs);
1550     case 2: return u.format2.collect_coverage (glyphs);
1551     default:return false;
1552     }
1553   }
1554
1555   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
1556   {
1557     static constexpr bool is_sorted_iterator = true;
1558     iter_t (const Coverage &c_ = Null (Coverage))
1559     {
1560       memset (this, 0, sizeof (*this));
1561       format = c_.u.format;
1562       switch (format)
1563       {
1564       case 1: u.format1.init (c_.u.format1); return;
1565       case 2: u.format2.init (c_.u.format2); return;
1566       default:                               return;
1567       }
1568     }
1569     bool __more__ () const
1570     {
1571       switch (format)
1572       {
1573       case 1: return u.format1.more ();
1574       case 2: return u.format2.more ();
1575       default:return false;
1576       }
1577     }
1578     void __next__ ()
1579     {
1580       switch (format)
1581       {
1582       case 1: u.format1.next (); break;
1583       case 2: u.format2.next (); break;
1584       default:                   break;
1585       }
1586     }
1587     typedef hb_codepoint_t __item_t__;
1588     __item_t__ __item__ () const { return get_glyph (); }
1589
1590     hb_codepoint_t get_glyph () const
1591     {
1592       switch (format)
1593       {
1594       case 1: return u.format1.get_glyph ();
1595       case 2: return u.format2.get_glyph ();
1596       default:return 0;
1597       }
1598     }
1599     bool operator != (const iter_t& o) const
1600     {
1601       if (format != o.format) return true;
1602       switch (format)
1603       {
1604       case 1: return u.format1 != o.u.format1;
1605       case 2: return u.format2 != o.u.format2;
1606       default:return false;
1607       }
1608     }
1609
1610     private:
1611     unsigned int format;
1612     union {
1613     CoverageFormat2::iter_t     format2; /* Put this one first since it's larger; helps shut up compiler. */
1614     CoverageFormat1::iter_t     format1;
1615     } u;
1616   };
1617   iter_t iter () const { return iter_t (*this); }
1618
1619   protected:
1620   union {
1621   HBUINT16              format;         /* Format identifier */
1622   CoverageFormat1       format1;
1623   CoverageFormat2       format2;
1624   } u;
1625   public:
1626   DEFINE_SIZE_UNION (2, format);
1627 };
1628
1629 template<typename Iterator>
1630 static inline void
1631 Coverage_serialize (hb_serialize_context_t *c,
1632                     Iterator it)
1633 { c->start_embed<Coverage> ()->serialize (c, it); }
1634
1635 static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
1636                                           const hb_set_t &glyphset,
1637                                           const hb_map_t &gid_klass_map,
1638                                           hb_sorted_vector_t<HBGlyphID> &glyphs,
1639                                           const hb_set_t &klasses,
1640                                           hb_map_t *klass_map /*INOUT*/)
1641 {
1642   if (!klass_map)
1643   {
1644     ClassDef_serialize (c, hb_zip (glyphs.iter (), + glyphs.iter ()
1645                                                    | hb_map (gid_klass_map)));
1646     return;
1647   }
1648
1649   /* any glyph not assigned a class value falls into Class zero (0),
1650    * if any glyph assigned to class 0, remapping must start with 0->0*/
1651   if (glyphset.get_population () > gid_klass_map.get_population ())
1652     klass_map->set (0, 0);
1653
1654   unsigned idx = klass_map->has (0) ? 1 : 0;
1655   for (const unsigned k: klasses.iter ())
1656   {
1657     if (klass_map->has (k)) continue;
1658     klass_map->set (k, idx);
1659     idx++;
1660   }
1661
1662   auto it =
1663   + glyphs.iter ()
1664   | hb_map_retains_sorting ([&] (const HBGlyphID& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
1665                             {
1666                               unsigned new_klass = klass_map->get (gid_klass_map[gid]);
1667                               return hb_pair ((hb_codepoint_t)gid, new_klass);
1668                             })
1669   ;
1670
1671   c->propagate_error (glyphs, klasses);
1672   ClassDef_serialize (c, it);
1673 }
1674
1675 /*
1676  * Class Definition Table
1677  */
1678
1679 struct ClassDefFormat1
1680 {
1681   friend struct ClassDef;
1682
1683   private:
1684   unsigned int get_class (hb_codepoint_t glyph_id) const
1685   {
1686     return classValue[(unsigned int) (glyph_id - startGlyph)];
1687   }
1688
1689   template<typename Iterator,
1690            hb_requires (hb_is_iterator (Iterator))>
1691   bool serialize (hb_serialize_context_t *c,
1692                   Iterator it)
1693   {
1694     TRACE_SERIALIZE (this);
1695     if (unlikely (!c->extend_min (*this))) return_trace (false);
1696
1697     if (unlikely (!it))
1698     {
1699       startGlyph = 0;
1700       classValue.len = 0;
1701       return_trace (true);
1702     }
1703
1704     hb_codepoint_t glyph_min = (*it).first;
1705     hb_codepoint_t glyph_max = + it
1706                                | hb_map (hb_first)
1707                                | hb_reduce (hb_max, 0u);
1708     unsigned glyph_count = glyph_max - glyph_min + 1;
1709
1710     startGlyph = glyph_min;
1711     if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
1712     for (const hb_pair_t<hb_codepoint_t, unsigned>& gid_klass_pair : + it)
1713     {
1714       unsigned idx = gid_klass_pair.first - glyph_min;
1715       classValue[idx] = gid_klass_pair.second;
1716     }
1717     return_trace (true);
1718   }
1719
1720   bool subset (hb_subset_context_t *c,
1721                hb_map_t *klass_map = nullptr /*OUT*/) const
1722   {
1723     TRACE_SUBSET (this);
1724     const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
1725     const hb_map_t &glyph_map = *c->plan->glyph_map;
1726
1727     hb_sorted_vector_t<HBGlyphID> glyphs;
1728     hb_set_t orig_klasses;
1729     hb_map_t gid_org_klass_map;
1730
1731     hb_codepoint_t start = startGlyph;
1732     hb_codepoint_t end   = start + classValue.len;
1733     for (const hb_codepoint_t gid : + hb_range (start, end)
1734                                     | hb_filter (glyphset))
1735     {
1736       unsigned klass = classValue[gid - start];
1737       if (!klass) continue;
1738
1739       glyphs.push (glyph_map[gid]);
1740       gid_org_klass_map.set (glyph_map[gid], klass);
1741       orig_klasses.add (klass);
1742     }
1743
1744     ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
1745                                   glyphs, orig_klasses, klass_map);
1746     return_trace ((bool) glyphs);
1747   }
1748
1749   bool sanitize (hb_sanitize_context_t *c) const
1750   {
1751     TRACE_SANITIZE (this);
1752     return_trace (c->check_struct (this) && classValue.sanitize (c));
1753   }
1754
1755   template <typename set_t>
1756   bool collect_coverage (set_t *glyphs) const
1757   {
1758     unsigned int start = 0;
1759     unsigned int count = classValue.len;
1760     for (unsigned int i = 0; i < count; i++)
1761     {
1762       if (classValue[i])
1763         continue;
1764
1765       if (start != i)
1766         if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
1767           return false;
1768
1769       start = i + 1;
1770     }
1771     if (start != count)
1772       if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
1773         return false;
1774
1775     return true;
1776   }
1777
1778   template <typename set_t>
1779   bool collect_class (set_t *glyphs, unsigned int klass) const
1780   {
1781     unsigned int count = classValue.len;
1782     for (unsigned int i = 0; i < count; i++)
1783       if (classValue[i] == klass) glyphs->add (startGlyph + i);
1784     return true;
1785   }
1786
1787   bool intersects (const hb_set_t *glyphs) const
1788   {
1789     /* TODO Speed up, using hb_set_next()? */
1790     hb_codepoint_t start = startGlyph;
1791     hb_codepoint_t end = startGlyph + classValue.len;
1792     for (hb_codepoint_t iter = startGlyph - 1;
1793          hb_set_next (glyphs, &iter) && iter < end;)
1794       if (classValue[iter - start]) return true;
1795     return false;
1796   }
1797   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
1798   {
1799     unsigned int count = classValue.len;
1800     if (klass == 0)
1801     {
1802       /* Match if there's any glyph that is not listed! */
1803       hb_codepoint_t g = HB_SET_VALUE_INVALID;
1804       if (!hb_set_next (glyphs, &g)) return false;
1805       if (g < startGlyph) return true;
1806       g = startGlyph + count - 1;
1807       if (hb_set_next (glyphs, &g)) return true;
1808       /* Fall through. */
1809     }
1810     for (unsigned int i = 0; i < count; i++)
1811       if (classValue[i] == klass && glyphs->has (startGlyph + i))
1812         return true;
1813     return false;
1814   }
1815
1816   protected:
1817   HBUINT16      classFormat;    /* Format identifier--format = 1 */
1818   HBGlyphID     startGlyph;     /* First GlyphID of the classValueArray */
1819   ArrayOf<HBUINT16>
1820                 classValue;     /* Array of Class Values--one per GlyphID */
1821   public:
1822   DEFINE_SIZE_ARRAY (6, classValue);
1823 };
1824
1825 struct ClassDefFormat2
1826 {
1827   friend struct ClassDef;
1828
1829   private:
1830   unsigned int get_class (hb_codepoint_t glyph_id) const
1831   {
1832     return rangeRecord.bsearch (glyph_id).value;
1833   }
1834
1835   template<typename Iterator,
1836            hb_requires (hb_is_iterator (Iterator))>
1837   bool serialize (hb_serialize_context_t *c,
1838                   Iterator it)
1839   {
1840     TRACE_SERIALIZE (this);
1841     if (unlikely (!c->extend_min (*this))) return_trace (false);
1842
1843     if (unlikely (!it))
1844     {
1845       rangeRecord.len = 0;
1846       return_trace (true);
1847     }
1848
1849     unsigned num_ranges = 1;
1850     hb_codepoint_t prev_gid = (*it).first;
1851     unsigned prev_klass = (*it).second;
1852
1853     RangeRecord range_rec;
1854     range_rec.first = prev_gid;
1855     range_rec.last = prev_gid;
1856     range_rec.value = prev_klass;
1857
1858     RangeRecord *record = c->copy (range_rec);
1859     if (unlikely (!record)) return_trace (false);
1860
1861     for (const auto gid_klass_pair : + (++it))
1862     {
1863       hb_codepoint_t cur_gid = gid_klass_pair.first;
1864       unsigned cur_klass = gid_klass_pair.second;
1865
1866       if (cur_gid != prev_gid + 1 ||
1867           cur_klass != prev_klass)
1868       {
1869         if (unlikely (!record)) break;
1870         record->last = prev_gid;
1871         num_ranges++;
1872
1873         range_rec.first = cur_gid;
1874         range_rec.last = cur_gid;
1875         range_rec.value = cur_klass;
1876
1877         record = c->copy (range_rec);
1878       }
1879
1880       prev_klass = cur_klass;
1881       prev_gid = cur_gid;
1882     }
1883
1884     if (likely (record)) record->last = prev_gid;
1885     rangeRecord.len = num_ranges;
1886     return_trace (true);
1887   }
1888
1889   bool subset (hb_subset_context_t *c,
1890                hb_map_t *klass_map = nullptr /*OUT*/) const
1891   {
1892     TRACE_SUBSET (this);
1893     const hb_set_t &glyphset = *c->plan->_glyphset_gsub;
1894     const hb_map_t &glyph_map = *c->plan->glyph_map;
1895
1896     hb_sorted_vector_t<HBGlyphID> glyphs;
1897     hb_set_t orig_klasses;
1898     hb_map_t gid_org_klass_map;
1899
1900     unsigned count = rangeRecord.len;
1901     for (unsigned i = 0; i < count; i++)
1902     {
1903       unsigned klass = rangeRecord[i].value;
1904       if (!klass) continue;
1905       hb_codepoint_t start = rangeRecord[i].first;
1906       hb_codepoint_t end   = rangeRecord[i].last + 1;
1907       for (hb_codepoint_t g = start; g < end; g++)
1908       {
1909         if (!glyphset.has (g)) continue;
1910         glyphs.push (glyph_map[g]);
1911         gid_org_klass_map.set (glyph_map[g], klass);
1912         orig_klasses.add (klass);
1913       }
1914     }
1915
1916     ClassDef_remap_and_serialize (c->serializer, glyphset, gid_org_klass_map,
1917                                   glyphs, orig_klasses, klass_map);
1918     return_trace ((bool) glyphs);
1919   }
1920
1921   bool sanitize (hb_sanitize_context_t *c) const
1922   {
1923     TRACE_SANITIZE (this);
1924     return_trace (rangeRecord.sanitize (c));
1925   }
1926
1927   template <typename set_t>
1928   bool collect_coverage (set_t *glyphs) const
1929   {
1930     unsigned int count = rangeRecord.len;
1931     for (unsigned int i = 0; i < count; i++)
1932       if (rangeRecord[i].value)
1933         if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
1934           return false;
1935     return true;
1936   }
1937
1938   template <typename set_t>
1939   bool collect_class (set_t *glyphs, unsigned int klass) const
1940   {
1941     unsigned int count = rangeRecord.len;
1942     for (unsigned int i = 0; i < count; i++)
1943     {
1944       if (rangeRecord[i].value == klass)
1945         if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
1946           return false;
1947     }
1948     return true;
1949   }
1950
1951   bool intersects (const hb_set_t *glyphs) const
1952   {
1953     /* TODO Speed up, using hb_set_next() and bsearch()? */
1954     unsigned int count = rangeRecord.len;
1955     for (unsigned int i = 0; i < count; i++)
1956       if (rangeRecord[i].intersects (glyphs))
1957         return true;
1958     return false;
1959   }
1960   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
1961   {
1962     unsigned int count = rangeRecord.len;
1963     if (klass == 0)
1964     {
1965       /* Match if there's any glyph that is not listed! */
1966       hb_codepoint_t g = HB_SET_VALUE_INVALID;
1967       for (unsigned int i = 0; i < count; i++)
1968       {
1969         if (!hb_set_next (glyphs, &g))
1970           break;
1971         if (g < rangeRecord[i].first)
1972           return true;
1973         g = rangeRecord[i].last;
1974       }
1975       if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
1976         return true;
1977       /* Fall through. */
1978     }
1979     for (unsigned int i = 0; i < count; i++)
1980       if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
1981         return true;
1982     return false;
1983   }
1984
1985   protected:
1986   HBUINT16      classFormat;    /* Format identifier--format = 2 */
1987   SortedArrayOf<RangeRecord>
1988                 rangeRecord;    /* Array of glyph ranges--ordered by
1989                                  * Start GlyphID */
1990   public:
1991   DEFINE_SIZE_ARRAY (4, rangeRecord);
1992 };
1993
1994 struct ClassDef
1995 {
1996   /* Has interface. */
1997   static constexpr unsigned SENTINEL = 0;
1998   typedef unsigned int value_t;
1999   value_t operator [] (hb_codepoint_t k) const { return get (k); }
2000   bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
2001   /* Projection. */
2002   hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
2003
2004   unsigned int get (hb_codepoint_t k) const { return get_class (k); }
2005   unsigned int get_class (hb_codepoint_t glyph_id) const
2006   {
2007     switch (u.format) {
2008     case 1: return u.format1.get_class (glyph_id);
2009     case 2: return u.format2.get_class (glyph_id);
2010     default:return 0;
2011     }
2012   }
2013
2014   template<typename Iterator,
2015            hb_requires (hb_is_iterator (Iterator))>
2016   bool serialize (hb_serialize_context_t *c, Iterator it)
2017   {
2018     TRACE_SERIALIZE (this);
2019     if (unlikely (!c->extend_min (*this))) return_trace (false);
2020
2021     unsigned format = 2;
2022     if (likely (it))
2023     {
2024       hb_codepoint_t glyph_min = (*it).first;
2025       hb_codepoint_t glyph_max = + it
2026                                  | hb_map (hb_first)
2027                                  | hb_reduce (hb_max, 0u);
2028
2029       unsigned num_ranges = 1;
2030       hb_codepoint_t prev_gid = glyph_min;
2031       unsigned prev_klass = (*it).second;
2032
2033       for (const auto gid_klass_pair : it)
2034       {
2035         hb_codepoint_t cur_gid = gid_klass_pair.first;
2036         unsigned cur_klass = gid_klass_pair.second;
2037         if (cur_gid == glyph_min || !cur_klass) continue;
2038         if (cur_gid != prev_gid + 1 ||
2039             cur_klass != prev_klass)
2040           num_ranges++;
2041
2042         prev_gid = cur_gid;
2043         prev_klass = cur_klass;
2044       }
2045
2046       if (1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
2047         format = 1;
2048     }
2049     u.format = format;
2050
2051     switch (u.format)
2052     {
2053     case 1: return_trace (u.format1.serialize (c, it));
2054     case 2: return_trace (u.format2.serialize (c, it));
2055     default:return_trace (false);
2056     }
2057   }
2058
2059   bool subset (hb_subset_context_t *c,
2060                hb_map_t *klass_map = nullptr /*OUT*/) const
2061   {
2062     TRACE_SUBSET (this);
2063     switch (u.format) {
2064     case 1: return_trace (u.format1.subset (c, klass_map));
2065     case 2: return_trace (u.format2.subset (c, klass_map));
2066     default:return_trace (false);
2067     }
2068   }
2069
2070   bool sanitize (hb_sanitize_context_t *c) const
2071   {
2072     TRACE_SANITIZE (this);
2073     if (!u.format.sanitize (c)) return_trace (false);
2074     switch (u.format) {
2075     case 1: return_trace (u.format1.sanitize (c));
2076     case 2: return_trace (u.format2.sanitize (c));
2077     default:return_trace (true);
2078     }
2079   }
2080
2081   /* Might return false if array looks unsorted.
2082    * Used for faster rejection of corrupt data. */
2083   template <typename set_t>
2084   bool collect_coverage (set_t *glyphs) const
2085   {
2086     switch (u.format) {
2087     case 1: return u.format1.collect_coverage (glyphs);
2088     case 2: return u.format2.collect_coverage (glyphs);
2089     default:return false;
2090     }
2091   }
2092
2093   /* Might return false if array looks unsorted.
2094    * Used for faster rejection of corrupt data. */
2095   template <typename set_t>
2096   bool collect_class (set_t *glyphs, unsigned int klass) const
2097   {
2098     switch (u.format) {
2099     case 1: return u.format1.collect_class (glyphs, klass);
2100     case 2: return u.format2.collect_class (glyphs, klass);
2101     default:return false;
2102     }
2103   }
2104
2105   bool intersects (const hb_set_t *glyphs) const
2106   {
2107     switch (u.format) {
2108     case 1: return u.format1.intersects (glyphs);
2109     case 2: return u.format2.intersects (glyphs);
2110     default:return false;
2111     }
2112   }
2113   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
2114   {
2115     switch (u.format) {
2116     case 1: return u.format1.intersects_class (glyphs, klass);
2117     case 2: return u.format2.intersects_class (glyphs, klass);
2118     default:return false;
2119     }
2120   }
2121
2122   protected:
2123   union {
2124   HBUINT16              format;         /* Format identifier */
2125   ClassDefFormat1       format1;
2126   ClassDefFormat2       format2;
2127   } u;
2128   public:
2129   DEFINE_SIZE_UNION (2, format);
2130 };
2131
2132 template<typename Iterator>
2133 static inline void ClassDef_serialize (hb_serialize_context_t *c,
2134                                        Iterator it)
2135 { c->start_embed<ClassDef> ()->serialize (c, it); }
2136
2137
2138 /*
2139  * Item Variation Store
2140  */
2141
2142 struct VarRegionAxis
2143 {
2144   float evaluate (int coord) const
2145   {
2146     int start = startCoord, peak = peakCoord, end = endCoord;
2147
2148     /* TODO Move these to sanitize(). */
2149     if (unlikely (start > peak || peak > end))
2150       return 1.;
2151     if (unlikely (start < 0 && end > 0 && peak != 0))
2152       return 1.;
2153
2154     if (peak == 0 || coord == peak)
2155       return 1.;
2156
2157     if (coord <= start || end <= coord)
2158       return 0.;
2159
2160     /* Interpolate */
2161     if (coord < peak)
2162       return float (coord - start) / (peak - start);
2163     else
2164       return float (end - coord) / (end - peak);
2165   }
2166
2167   bool sanitize (hb_sanitize_context_t *c) const
2168   {
2169     TRACE_SANITIZE (this);
2170     return_trace (c->check_struct (this));
2171     /* TODO Handle invalid start/peak/end configs, so we don't
2172      * have to do that at runtime. */
2173   }
2174
2175   public:
2176   F2DOT14       startCoord;
2177   F2DOT14       peakCoord;
2178   F2DOT14       endCoord;
2179   public:
2180   DEFINE_SIZE_STATIC (6);
2181 };
2182
2183 struct VarRegionList
2184 {
2185   float evaluate (unsigned int region_index,
2186                          const int *coords, unsigned int coord_len) const
2187   {
2188     if (unlikely (region_index >= regionCount))
2189       return 0.;
2190
2191     const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
2192
2193     float v = 1.;
2194     unsigned int count = axisCount;
2195     for (unsigned int i = 0; i < count; i++)
2196     {
2197       int coord = i < coord_len ? coords[i] : 0;
2198       float factor = axes[i].evaluate (coord);
2199       if (factor == 0.f)
2200         return 0.;
2201       v *= factor;
2202     }
2203     return v;
2204   }
2205
2206   bool sanitize (hb_sanitize_context_t *c) const
2207   {
2208     TRACE_SANITIZE (this);
2209     return_trace (c->check_struct (this) &&
2210                   axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
2211   }
2212
2213   bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_bimap_t &region_map)
2214   {
2215     TRACE_SERIALIZE (this);
2216     VarRegionList *out = c->allocate_min<VarRegionList> ();
2217     if (unlikely (!out)) return_trace (false);
2218     axisCount = src->axisCount;
2219     regionCount = region_map.get_population ();
2220     if (unlikely (!c->allocate_size<VarRegionList> (get_size () - min_size))) return_trace (false);
2221     unsigned int region_count = src->get_region_count ();
2222     for (unsigned int r = 0; r < regionCount; r++)
2223     {
2224       unsigned int backward = region_map.backward (r);
2225       if (backward >= region_count) return_trace (false);
2226       memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
2227     }
2228
2229     return_trace (true);
2230   }
2231
2232   unsigned int get_size () const { return min_size + VarRegionAxis::static_size * axisCount * regionCount; }
2233   unsigned int get_region_count () const { return regionCount; }
2234
2235   protected:
2236   HBUINT16      axisCount;
2237   HBUINT16      regionCount;
2238   UnsizedArrayOf<VarRegionAxis>
2239                 axesZ;
2240   public:
2241   DEFINE_SIZE_ARRAY (4, axesZ);
2242 };
2243
2244 struct VarData
2245 {
2246   unsigned int get_region_index_count () const
2247   { return regionIndices.len; }
2248
2249   unsigned int get_row_size () const
2250   { return shortCount + regionIndices.len; }
2251
2252   unsigned int get_size () const
2253   { return itemCount * get_row_size (); }
2254
2255   float get_delta (unsigned int inner,
2256                           const int *coords, unsigned int coord_count,
2257                           const VarRegionList &regions) const
2258   {
2259     if (unlikely (inner >= itemCount))
2260       return 0.;
2261
2262    unsigned int count = regionIndices.len;
2263    unsigned int scount = shortCount;
2264
2265    const HBUINT8 *bytes = get_delta_bytes ();
2266    const HBUINT8 *row = bytes + inner * (scount + count);
2267
2268    float delta = 0.;
2269    unsigned int i = 0;
2270
2271    const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
2272    for (; i < scount; i++)
2273    {
2274      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
2275      delta += scalar * *scursor++;
2276    }
2277    const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
2278    for (; i < count; i++)
2279    {
2280      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
2281      delta += scalar * *bcursor++;
2282    }
2283
2284    return delta;
2285   }
2286
2287   void get_scalars (const int *coords, unsigned int coord_count,
2288                     const VarRegionList &regions,
2289                     float *scalars /*OUT */,
2290                     unsigned int num_scalars) const
2291   {
2292     unsigned count = hb_min (num_scalars, regionIndices.len);
2293     for (unsigned int i = 0; i < count; i++)
2294       scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
2295     for (unsigned int i = count; i < num_scalars; i++)
2296       scalars[i] = 0.f;
2297   }
2298
2299   bool sanitize (hb_sanitize_context_t *c) const
2300   {
2301     TRACE_SANITIZE (this);
2302     return_trace (c->check_struct (this) &&
2303                   regionIndices.sanitize (c) &&
2304                   shortCount <= regionIndices.len &&
2305                   c->check_range (get_delta_bytes (),
2306                                   itemCount,
2307                                   get_row_size ()));
2308   }
2309
2310   bool serialize (hb_serialize_context_t *c,
2311                   const VarData *src,
2312                   const hb_inc_bimap_t &inner_map,
2313                   const hb_bimap_t &region_map)
2314   {
2315     TRACE_SERIALIZE (this);
2316     if (unlikely (!c->extend_min (*this))) return_trace (false);
2317     itemCount = inner_map.get_next_value ();
2318
2319     /* Optimize short count */
2320     unsigned short ri_count = src->regionIndices.len;
2321     enum delta_size_t { kZero=0, kByte, kShort };
2322     hb_vector_t<delta_size_t> delta_sz;
2323     hb_vector_t<unsigned int> ri_map;   /* maps old index to new index */
2324     delta_sz.resize (ri_count);
2325     ri_map.resize (ri_count);
2326     unsigned int new_short_count = 0;
2327     unsigned int r;
2328     for (r = 0; r < ri_count; r++)
2329     {
2330       delta_sz[r] = kZero;
2331       for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
2332       {
2333         unsigned int old = inner_map.backward (i);
2334         int16_t delta = src->get_item_delta (old, r);
2335         if (delta < -128 || 127 < delta)
2336         {
2337           delta_sz[r] = kShort;
2338           new_short_count++;
2339           break;
2340         }
2341         else if (delta != 0)
2342           delta_sz[r] = kByte;
2343       }
2344     }
2345     unsigned int short_index = 0;
2346     unsigned int byte_index = new_short_count;
2347     unsigned int new_ri_count = 0;
2348     for (r = 0; r < ri_count; r++)
2349       if (delta_sz[r])
2350       {
2351         ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++;
2352         new_ri_count++;
2353       }
2354
2355     shortCount = new_short_count;
2356     regionIndices.len = new_ri_count;
2357
2358     unsigned int size = regionIndices.get_size () - HBUINT16::static_size/*regionIndices.len*/ + (get_row_size () * itemCount);
2359     if (unlikely (!c->allocate_size<HBUINT8> (size)))
2360       return_trace (false);
2361
2362     for (r = 0; r < ri_count; r++)
2363       if (delta_sz[r]) regionIndices[ri_map[r]] = region_map[src->regionIndices[r]];
2364
2365     for (unsigned int i = 0; i < itemCount; i++)
2366     {
2367       unsigned int      old = inner_map.backward (i);
2368       for (unsigned int r = 0; r < ri_count; r++)
2369         if (delta_sz[r]) set_item_delta (i, ri_map[r], src->get_item_delta (old, r));
2370     }
2371
2372     return_trace (true);
2373   }
2374
2375   void collect_region_refs (hb_inc_bimap_t &region_map, const hb_inc_bimap_t &inner_map) const
2376   {
2377     for (unsigned int r = 0; r < regionIndices.len; r++)
2378     {
2379       unsigned int region = regionIndices[r];
2380       if (region_map.has (region)) continue;
2381       for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
2382         if (get_item_delta (inner_map.backward (i), r) != 0)
2383         {
2384           region_map.add (region);
2385           break;
2386         }
2387     }
2388   }
2389
2390   protected:
2391   const HBUINT8 *get_delta_bytes () const
2392   { return &StructAfter<HBUINT8> (regionIndices); }
2393
2394   HBUINT8 *get_delta_bytes ()
2395   { return &StructAfter<HBUINT8> (regionIndices); }
2396
2397   int16_t get_item_delta (unsigned int item, unsigned int region) const
2398   {
2399     if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
2400     const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size ();
2401     if (region < shortCount)
2402       return ((const HBINT16 *)p)[region];
2403     else
2404       return (p + HBINT16::static_size * shortCount)[region - shortCount];
2405   }
2406
2407   void set_item_delta (unsigned int item, unsigned int region, int16_t delta)
2408   {
2409     HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
2410     if (region < shortCount)
2411       ((HBINT16 *)p)[region] = delta;
2412     else
2413       (p + HBINT16::static_size * shortCount)[region - shortCount] = delta;
2414   }
2415
2416   protected:
2417   HBUINT16              itemCount;
2418   HBUINT16              shortCount;
2419   ArrayOf<HBUINT16>     regionIndices;
2420 /*UnsizedArrayOf<HBUINT8>bytesX;*/
2421   public:
2422   DEFINE_SIZE_ARRAY (6, regionIndices);
2423 };
2424
2425 struct VariationStore
2426 {
2427   float get_delta (unsigned int outer, unsigned int inner,
2428                    const int *coords, unsigned int coord_count) const
2429   {
2430 #ifdef HB_NO_VAR
2431     return 0.f;
2432 #endif
2433
2434     if (unlikely (outer >= dataSets.len))
2435       return 0.f;
2436
2437     return (this+dataSets[outer]).get_delta (inner,
2438                                              coords, coord_count,
2439                                              this+regions);
2440   }
2441
2442   float get_delta (unsigned int index,
2443                    const int *coords, unsigned int coord_count) const
2444   {
2445     unsigned int outer = index >> 16;
2446     unsigned int inner = index & 0xFFFF;
2447     return get_delta (outer, inner, coords, coord_count);
2448   }
2449
2450   bool sanitize (hb_sanitize_context_t *c) const
2451   {
2452 #ifdef HB_NO_VAR
2453     return true;
2454 #endif
2455
2456     TRACE_SANITIZE (this);
2457     return_trace (c->check_struct (this) &&
2458                   format == 1 &&
2459                   regions.sanitize (c, this) &&
2460                   dataSets.sanitize (c, this));
2461   }
2462
2463   bool serialize (hb_serialize_context_t *c,
2464                   const VariationStore *src,
2465                   const hb_array_t <hb_inc_bimap_t> &inner_maps)
2466   {
2467     TRACE_SERIALIZE (this);
2468     unsigned int set_count = 0;
2469     for (unsigned int i = 0; i < inner_maps.length; i++)
2470       if (inner_maps[i].get_population () > 0) set_count++;
2471
2472     unsigned int size = min_size + HBUINT32::static_size * set_count;
2473     if (unlikely (!c->allocate_size<HBUINT32> (size))) return_trace (false);
2474     format = 1;
2475
2476     hb_inc_bimap_t region_map;
2477     for (unsigned int i = 0; i < inner_maps.length; i++)
2478       (src+src->dataSets[i]).collect_region_refs (region_map, inner_maps[i]);
2479     region_map.sort ();
2480
2481     if (unlikely (!regions.serialize (c, this)
2482                   .serialize (c, &(src+src->regions), region_map))) return_trace (false);
2483
2484     /* TODO: The following code could be simplified when
2485      * OffsetListOf::subset () can take a custom param to be passed to VarData::serialize ()
2486      */
2487     dataSets.len = set_count;
2488     unsigned int set_index = 0;
2489     for (unsigned int i = 0; i < inner_maps.length; i++)
2490     {
2491       if (inner_maps[i].get_population () == 0) continue;
2492       if (unlikely (!dataSets[set_index++].serialize (c, this)
2493                       .serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
2494         return_trace (false);
2495     }
2496
2497     return_trace (true);
2498   }
2499
2500   bool subset (hb_subset_context_t *c) const
2501   {
2502     TRACE_SUBSET (this);
2503
2504     VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
2505     if (unlikely (!varstore_prime)) return_trace (false);
2506
2507     const hb_set_t *variation_indices = c->plan->layout_variation_indices;
2508     if (variation_indices->is_empty ()) return_trace (false);
2509
2510     hb_vector_t<hb_inc_bimap_t> inner_maps;
2511     inner_maps.resize ((unsigned) dataSets.len);
2512     for (unsigned i = 0; i < inner_maps.length; i++)
2513       inner_maps[i].init ();
2514
2515     for (unsigned idx : c->plan->layout_variation_indices->iter ())
2516     {
2517       uint16_t major = idx >> 16;
2518       uint16_t minor = idx & 0xFFFF;
2519
2520       if (major >= inner_maps.length)
2521       {
2522         for (unsigned i = 0; i < inner_maps.length; i++)
2523           inner_maps[i].fini ();
2524         return_trace (false);
2525       }
2526       inner_maps[major].add (minor);
2527     }
2528     varstore_prime->serialize (c->serializer, this, inner_maps.as_array ());
2529
2530     for (unsigned i = 0; i < inner_maps.length; i++)
2531       inner_maps[i].fini ();
2532     return_trace (bool (varstore_prime->dataSets));
2533   }
2534
2535   unsigned int get_region_index_count (unsigned int ivs) const
2536   { return (this+dataSets[ivs]).get_region_index_count (); }
2537
2538   void get_scalars (unsigned int ivs,
2539                     const int *coords, unsigned int coord_count,
2540                     float *scalars /*OUT*/,
2541                     unsigned int num_scalars) const
2542   {
2543 #ifdef HB_NO_VAR
2544     for (unsigned i = 0; i < num_scalars; i++)
2545       scalars[i] = 0.f;
2546     return;
2547 #endif
2548
2549     (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
2550                                       &scalars[0], num_scalars);
2551   }
2552
2553   unsigned int get_sub_table_count () const { return dataSets.len; }
2554
2555   protected:
2556   HBUINT16                              format;
2557   LOffsetTo<VarRegionList>              regions;
2558   LOffsetArrayOf<VarData>               dataSets;
2559   public:
2560   DEFINE_SIZE_ARRAY (8, dataSets);
2561 };
2562
2563 /*
2564  * Feature Variations
2565  */
2566
2567 struct ConditionFormat1
2568 {
2569   friend struct Condition;
2570
2571   bool subset (hb_subset_context_t *c) const
2572   {
2573     TRACE_SUBSET (this);
2574     auto *out = c->serializer->embed (this);
2575     if (unlikely (!out)) return_trace (false);
2576     return_trace (true);
2577   }
2578
2579   private:
2580   bool evaluate (const int *coords, unsigned int coord_len) const
2581   {
2582     int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
2583     return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
2584   }
2585
2586   bool sanitize (hb_sanitize_context_t *c) const
2587   {
2588     TRACE_SANITIZE (this);
2589     return_trace (c->check_struct (this));
2590   }
2591
2592   protected:
2593   HBUINT16      format;         /* Format identifier--format = 1 */
2594   HBUINT16      axisIndex;
2595   F2DOT14       filterRangeMinValue;
2596   F2DOT14       filterRangeMaxValue;
2597   public:
2598   DEFINE_SIZE_STATIC (8);
2599 };
2600
2601 struct Condition
2602 {
2603   bool evaluate (const int *coords, unsigned int coord_len) const
2604   {
2605     switch (u.format) {
2606     case 1: return u.format1.evaluate (coords, coord_len);
2607     default:return false;
2608     }
2609   }
2610
2611   template <typename context_t, typename ...Ts>
2612   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
2613   {
2614     TRACE_DISPATCH (this, u.format);
2615     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
2616     switch (u.format) {
2617     case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
2618     default:return_trace (c->default_return_value ());
2619     }
2620   }
2621
2622   bool sanitize (hb_sanitize_context_t *c) const
2623   {
2624     TRACE_SANITIZE (this);
2625     if (!u.format.sanitize (c)) return_trace (false);
2626     switch (u.format) {
2627     case 1: return_trace (u.format1.sanitize (c));
2628     default:return_trace (true);
2629     }
2630   }
2631
2632   protected:
2633   union {
2634   HBUINT16              format;         /* Format identifier */
2635   ConditionFormat1      format1;
2636   } u;
2637   public:
2638   DEFINE_SIZE_UNION (2, format);
2639 };
2640
2641 struct ConditionSet
2642 {
2643   bool evaluate (const int *coords, unsigned int coord_len) const
2644   {
2645     unsigned int count = conditions.len;
2646     for (unsigned int i = 0; i < count; i++)
2647       if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
2648         return false;
2649     return true;
2650   }
2651
2652   bool subset (hb_subset_context_t *c) const
2653   {
2654     TRACE_SUBSET (this);
2655     auto *out = c->serializer->start_embed (this);
2656     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
2657
2658     + conditions.iter ()
2659     | hb_apply (subset_offset_array (c, out->conditions, this))
2660     ;
2661     return_trace (true);
2662   }
2663
2664   bool sanitize (hb_sanitize_context_t *c) const
2665   {
2666     TRACE_SANITIZE (this);
2667     return_trace (conditions.sanitize (c, this));
2668   }
2669
2670   protected:
2671   LOffsetArrayOf<Condition>     conditions;
2672   public:
2673   DEFINE_SIZE_ARRAY (2, conditions);
2674 };
2675
2676 struct FeatureTableSubstitutionRecord
2677 {
2678   friend struct FeatureTableSubstitution;
2679
2680   void collect_lookups (const void *base, hb_set_t *lookup_indexes /* OUT */) const
2681   {
2682     return (base+feature).add_lookup_indexes_to (lookup_indexes);
2683   }
2684
2685   void closure_features (const void *base,
2686                          const hb_map_t *lookup_indexes,
2687                          hb_set_t       *feature_indexes /* OUT */) const
2688   {
2689     if ((base+feature).intersects_lookup_indexes (lookup_indexes))
2690       feature_indexes->add (featureIndex);
2691   }
2692
2693   bool subset (hb_subset_layout_context_t *c, const void *base) const
2694   {
2695     TRACE_SUBSET (this);
2696     auto *out = c->subset_context->serializer->embed (this);
2697     if (unlikely (!out)) return_trace (false);
2698
2699     out->featureIndex = c->feature_index_map->get (featureIndex);
2700     bool ret = out->feature.serialize_subset (c->subset_context, feature, base, c);
2701     return_trace (ret);
2702   }
2703
2704   bool sanitize (hb_sanitize_context_t *c, const void *base) const
2705   {
2706     TRACE_SANITIZE (this);
2707     return_trace (c->check_struct (this) && feature.sanitize (c, base));
2708   }
2709
2710   protected:
2711   HBUINT16              featureIndex;
2712   LOffsetTo<Feature>    feature;
2713   public:
2714   DEFINE_SIZE_STATIC (6);
2715 };
2716
2717 struct FeatureTableSubstitution
2718 {
2719   const Feature *find_substitute (unsigned int feature_index) const
2720   {
2721     unsigned int count = substitutions.len;
2722     for (unsigned int i = 0; i < count; i++)
2723     {
2724       const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
2725       if (record.featureIndex == feature_index)
2726         return &(this+record.feature);
2727     }
2728     return nullptr;
2729   }
2730
2731   void collect_lookups (const hb_set_t *feature_indexes,
2732                         hb_set_t       *lookup_indexes /* OUT */) const
2733   {
2734     + hb_iter (substitutions)
2735     | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
2736     | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
2737                 { r.collect_lookups (this, lookup_indexes); })
2738     ;
2739   }
2740
2741   void closure_features (const hb_map_t *lookup_indexes,
2742                          hb_set_t       *feature_indexes /* OUT */) const
2743   {
2744     for (const FeatureTableSubstitutionRecord& record : substitutions)
2745       record.closure_features (this, lookup_indexes, feature_indexes);
2746   }
2747
2748   bool subset (hb_subset_context_t        *c,
2749                hb_subset_layout_context_t *l) const
2750   {
2751     TRACE_SUBSET (this);
2752     auto *out = c->serializer->start_embed (*this);
2753     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
2754
2755     out->version.major = version.major;
2756     out->version.minor = version.minor;
2757
2758     + substitutions.iter ()
2759     | hb_apply (subset_record_array (l, &(out->substitutions), this))
2760     ;
2761     return_trace (true);
2762   }
2763
2764   bool sanitize (hb_sanitize_context_t *c) const
2765   {
2766     TRACE_SANITIZE (this);
2767     return_trace (version.sanitize (c) &&
2768                   likely (version.major == 1) &&
2769                   substitutions.sanitize (c, this));
2770   }
2771
2772   protected:
2773   FixedVersion<>        version;        /* Version--0x00010000u */
2774   ArrayOf<FeatureTableSubstitutionRecord>
2775                         substitutions;
2776   public:
2777   DEFINE_SIZE_ARRAY (6, substitutions);
2778 };
2779
2780 struct FeatureVariationRecord
2781 {
2782   friend struct FeatureVariations;
2783
2784   void collect_lookups (const void     *base,
2785                         const hb_set_t *feature_indexes,
2786                         hb_set_t       *lookup_indexes /* OUT */) const
2787   {
2788     return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
2789   }
2790
2791   void closure_features (const void     *base,
2792                          const hb_map_t *lookup_indexes,
2793                          hb_set_t       *feature_indexes /* OUT */) const
2794   {
2795     (base+substitutions).closure_features (lookup_indexes, feature_indexes);
2796   }
2797
2798   bool subset (hb_subset_layout_context_t *c, const void *base) const
2799   {
2800     TRACE_SUBSET (this);
2801     auto *out = c->subset_context->serializer->embed (this);
2802     if (unlikely (!out)) return_trace (false);
2803
2804     out->conditions.serialize_subset (c->subset_context, conditions, base);
2805     out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
2806
2807     return_trace (true);
2808   }
2809
2810   bool sanitize (hb_sanitize_context_t *c, const void *base) const
2811   {
2812     TRACE_SANITIZE (this);
2813     return_trace (conditions.sanitize (c, base) &&
2814                   substitutions.sanitize (c, base));
2815   }
2816
2817   protected:
2818   LOffsetTo<ConditionSet>
2819                         conditions;
2820   LOffsetTo<FeatureTableSubstitution>
2821                         substitutions;
2822   public:
2823   DEFINE_SIZE_STATIC (8);
2824 };
2825
2826 struct FeatureVariations
2827 {
2828   static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
2829
2830   bool find_index (const int *coords, unsigned int coord_len,
2831                           unsigned int *index) const
2832   {
2833     unsigned int count = varRecords.len;
2834     for (unsigned int i = 0; i < count; i++)
2835     {
2836       const FeatureVariationRecord &record = varRecords.arrayZ[i];
2837       if ((this+record.conditions).evaluate (coords, coord_len))
2838       {
2839         *index = i;
2840         return true;
2841       }
2842     }
2843     *index = NOT_FOUND_INDEX;
2844     return false;
2845   }
2846
2847   const Feature *find_substitute (unsigned int variations_index,
2848                                   unsigned int feature_index) const
2849   {
2850     const FeatureVariationRecord &record = varRecords[variations_index];
2851     return (this+record.substitutions).find_substitute (feature_index);
2852   }
2853
2854   FeatureVariations* copy (hb_serialize_context_t *c) const
2855   {
2856     TRACE_SERIALIZE (this);
2857     return_trace (c->embed (*this));
2858   }
2859
2860   void collect_lookups (const hb_set_t *feature_indexes,
2861                         hb_set_t       *lookup_indexes /* OUT */) const
2862   {
2863     for (const FeatureVariationRecord& r : varRecords)
2864       r.collect_lookups (this, feature_indexes, lookup_indexes);
2865   }
2866
2867   void closure_features (const hb_map_t *lookup_indexes,
2868                          hb_set_t       *feature_indexes /* OUT */) const
2869   {
2870     for (const FeatureVariationRecord& record : varRecords)
2871       record.closure_features (this, lookup_indexes, feature_indexes);
2872   }
2873
2874   bool subset (hb_subset_context_t *c,
2875                hb_subset_layout_context_t *l) const
2876   {
2877     TRACE_SUBSET (this);
2878     auto *out = c->serializer->start_embed (*this);
2879     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
2880
2881     out->version.major = version.major;
2882     out->version.minor = version.minor;
2883
2884     + varRecords.iter ()
2885     | hb_apply (subset_record_array (l, &(out->varRecords), this))
2886     ;
2887     return_trace (bool (out->varRecords));
2888   }
2889
2890   bool sanitize (hb_sanitize_context_t *c) const
2891   {
2892     TRACE_SANITIZE (this);
2893     return_trace (version.sanitize (c) &&
2894                   likely (version.major == 1) &&
2895                   varRecords.sanitize (c, this));
2896   }
2897
2898   protected:
2899   FixedVersion<>        version;        /* Version--0x00010000u */
2900   LArrayOf<FeatureVariationRecord>
2901                         varRecords;
2902   public:
2903   DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
2904 };
2905
2906
2907 /*
2908  * Device Tables
2909  */
2910
2911 struct HintingDevice
2912 {
2913   friend struct Device;
2914
2915   private:
2916
2917   hb_position_t get_x_delta (hb_font_t *font) const
2918   { return get_delta (font->x_ppem, font->x_scale); }
2919
2920   hb_position_t get_y_delta (hb_font_t *font) const
2921   { return get_delta (font->y_ppem, font->y_scale); }
2922
2923   public:
2924
2925   unsigned int get_size () const
2926   {
2927     unsigned int f = deltaFormat;
2928     if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
2929     return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
2930   }
2931
2932   bool sanitize (hb_sanitize_context_t *c) const
2933   {
2934     TRACE_SANITIZE (this);
2935     return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
2936   }
2937
2938   HintingDevice* copy (hb_serialize_context_t *c) const
2939   {
2940     TRACE_SERIALIZE (this);
2941     return_trace (c->embed<HintingDevice> (this));
2942   }
2943
2944   private:
2945
2946   int get_delta (unsigned int ppem, int scale) const
2947   {
2948     if (!ppem) return 0;
2949
2950     int pixels = get_delta_pixels (ppem);
2951
2952     if (!pixels) return 0;
2953
2954     return (int) (pixels * (int64_t) scale / ppem);
2955   }
2956   int get_delta_pixels (unsigned int ppem_size) const
2957   {
2958     unsigned int f = deltaFormat;
2959     if (unlikely (f < 1 || f > 3))
2960       return 0;
2961
2962     if (ppem_size < startSize || ppem_size > endSize)
2963       return 0;
2964
2965     unsigned int s = ppem_size - startSize;
2966
2967     unsigned int byte = deltaValueZ[s >> (4 - f)];
2968     unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
2969     unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
2970
2971     int delta = bits & mask;
2972
2973     if ((unsigned int) delta >= ((mask + 1) >> 1))
2974       delta -= mask + 1;
2975
2976     return delta;
2977   }
2978
2979   protected:
2980   HBUINT16      startSize;              /* Smallest size to correct--in ppem */
2981   HBUINT16      endSize;                /* Largest size to correct--in ppem */
2982   HBUINT16      deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
2983                                          * 1    Signed 2-bit value, 8 values per uint16
2984                                          * 2    Signed 4-bit value, 4 values per uint16
2985                                          * 3    Signed 8-bit value, 2 values per uint16
2986                                          */
2987   UnsizedArrayOf<HBUINT16>
2988                 deltaValueZ;            /* Array of compressed data */
2989   public:
2990   DEFINE_SIZE_ARRAY (6, deltaValueZ);
2991 };
2992
2993 struct VariationDevice
2994 {
2995   friend struct Device;
2996
2997   private:
2998
2999   hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
3000   { return font->em_scalef_x (get_delta (font, store)); }
3001
3002   hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
3003   { return font->em_scalef_y (get_delta (font, store)); }
3004
3005   VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
3006   {
3007     TRACE_SERIALIZE (this);
3008     auto snap = c->snapshot ();
3009     auto *out = c->embed (this);
3010     if (unlikely (!out)) return_trace (nullptr);
3011     if (!layout_variation_idx_map || layout_variation_idx_map->is_empty ()) return_trace (out);
3012
3013     unsigned org_idx = (outerIndex << 16) + innerIndex;
3014     if (!layout_variation_idx_map->has (org_idx))
3015     {
3016       c->revert (snap);
3017       return_trace (nullptr);
3018     }
3019     unsigned new_idx = layout_variation_idx_map->get (org_idx);
3020     out->outerIndex = new_idx >> 16;
3021     out->innerIndex = new_idx & 0xFFFF;
3022     return_trace (out);
3023   }
3024
3025   void record_variation_index (hb_set_t *layout_variation_indices) const
3026   {
3027     unsigned var_idx = (outerIndex << 16) + innerIndex;
3028     layout_variation_indices->add (var_idx);
3029   }
3030
3031   bool sanitize (hb_sanitize_context_t *c) const
3032   {
3033     TRACE_SANITIZE (this);
3034     return_trace (c->check_struct (this));
3035   }
3036
3037   private:
3038
3039   float get_delta (hb_font_t *font, const VariationStore &store) const
3040   {
3041     return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
3042   }
3043
3044   protected:
3045   HBUINT16      outerIndex;
3046   HBUINT16      innerIndex;
3047   HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
3048   public:
3049   DEFINE_SIZE_STATIC (6);
3050 };
3051
3052 struct DeviceHeader
3053 {
3054   protected:
3055   HBUINT16              reserved1;
3056   HBUINT16              reserved2;
3057   public:
3058   HBUINT16              format;         /* Format identifier */
3059   public:
3060   DEFINE_SIZE_STATIC (6);
3061 };
3062
3063 struct Device
3064 {
3065   hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
3066   {
3067     switch (u.b.format)
3068     {
3069 #ifndef HB_NO_HINTING
3070     case 1: case 2: case 3:
3071       return u.hinting.get_x_delta (font);
3072 #endif
3073 #ifndef HB_NO_VAR
3074     case 0x8000:
3075       return u.variation.get_x_delta (font, store);
3076 #endif
3077     default:
3078       return 0;
3079     }
3080   }
3081   hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
3082   {
3083     switch (u.b.format)
3084     {
3085     case 1: case 2: case 3:
3086 #ifndef HB_NO_HINTING
3087       return u.hinting.get_y_delta (font);
3088 #endif
3089 #ifndef HB_NO_VAR
3090     case 0x8000:
3091       return u.variation.get_y_delta (font, store);
3092 #endif
3093     default:
3094       return 0;
3095     }
3096   }
3097
3098   bool sanitize (hb_sanitize_context_t *c) const
3099   {
3100     TRACE_SANITIZE (this);
3101     if (!u.b.format.sanitize (c)) return_trace (false);
3102     switch (u.b.format) {
3103 #ifndef HB_NO_HINTING
3104     case 1: case 2: case 3:
3105       return_trace (u.hinting.sanitize (c));
3106 #endif
3107 #ifndef HB_NO_VAR
3108     case 0x8000:
3109       return_trace (u.variation.sanitize (c));
3110 #endif
3111     default:
3112       return_trace (true);
3113     }
3114   }
3115
3116   Device* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map=nullptr) const
3117   {
3118     TRACE_SERIALIZE (this);
3119     switch (u.b.format) {
3120 #ifndef HB_NO_HINTING
3121     case 1:
3122     case 2:
3123     case 3:
3124       return_trace (reinterpret_cast<Device *> (u.hinting.copy (c)));
3125 #endif
3126 #ifndef HB_NO_VAR
3127     case 0x8000:
3128       return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_map)));
3129 #endif
3130     default:
3131       return_trace (nullptr);
3132     }
3133   }
3134
3135   void collect_variation_indices (hb_set_t *layout_variation_indices) const
3136   {
3137     switch (u.b.format) {
3138 #ifndef HB_NO_HINTING
3139     case 1:
3140     case 2:
3141     case 3:
3142       return;
3143 #endif
3144 #ifndef HB_NO_VAR
3145     case 0x8000:
3146       u.variation.record_variation_index (layout_variation_indices);
3147       return;
3148 #endif
3149     default:
3150       return;
3151     }
3152   }
3153
3154   protected:
3155   union {
3156   DeviceHeader          b;
3157   HintingDevice         hinting;
3158 #ifndef HB_NO_VAR
3159   VariationDevice       variation;
3160 #endif
3161   } u;
3162   public:
3163   DEFINE_SIZE_UNION (6, b);
3164 };
3165
3166
3167 } /* namespace OT */
3168
3169
3170 #endif /* HB_OT_LAYOUT_COMMON_HH */