• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 
38 #ifndef HB_MAX_NESTING_LEVEL
39 #define HB_MAX_NESTING_LEVEL	6
40 #endif
41 #ifndef HB_MAX_CONTEXT_LENGTH
42 #define HB_MAX_CONTEXT_LENGTH	64
43 #endif
44 #ifndef HB_CLOSURE_MAX_STAGES
45 /*
46  * The maximum number of times a lookup can be applied during shaping.
47  * Used to limit the number of iterations of the closure algorithm.
48  * This must be larger than the number of times add_pause() is
49  * called in a collect_features call of any shaper.
50  */
51 #define HB_CLOSURE_MAX_STAGES	32
52 #endif
53 
54 #ifndef HB_MAX_SCRIPTS
55 #define HB_MAX_SCRIPTS	500
56 #endif
57 
58 #ifndef HB_MAX_LANGSYS
59 #define HB_MAX_LANGSYS	2000
60 #endif
61 
62 
63 namespace OT {
64 
65 
66 #define NOT_COVERED		((unsigned int) -1)
67 
68 
69 /*
70  *
71  * OpenType Layout Common Table Formats
72  *
73  */
74 
75 
76 /*
77  * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
78  */
79 
80 struct Record_sanitize_closure_t {
81   hb_tag_t tag;
82   const void *list_base;
83 };
84 
85 template <typename Type>
86 struct Record
87 {
cmpOT::Record88   int cmp (hb_tag_t a) const { return tag.cmp (a); }
89 
sanitizeOT::Record90   bool sanitize (hb_sanitize_context_t *c, const void *base) const
91   {
92     TRACE_SANITIZE (this);
93     const Record_sanitize_closure_t closure = {tag, base};
94     return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
95   }
96 
97   Tag		tag;		/* 4-byte Tag identifier */
98   OffsetTo<Type>
99 		offset;		/* Offset from beginning of object holding
100 				 * the Record */
101   public:
102   DEFINE_SIZE_STATIC (6);
103 };
104 
105 template <typename Type>
106 struct RecordArrayOf : SortedArrayOf<Record<Type>>
107 {
get_offsetOT::RecordArrayOf108   const OffsetTo<Type>& get_offset (unsigned int i) const
109   { return (*this)[i].offset; }
get_offsetOT::RecordArrayOf110   OffsetTo<Type>& get_offset (unsigned int i)
111   { return (*this)[i].offset; }
get_tagOT::RecordArrayOf112   const Tag& get_tag (unsigned int i) const
113   { return (*this)[i].tag; }
get_tagsOT::RecordArrayOf114   unsigned int get_tags (unsigned int start_offset,
115 			 unsigned int *record_count /* IN/OUT */,
116 			 hb_tag_t     *record_tags /* OUT */) const
117   {
118     if (record_count) {
119       const Record<Type> *arr = this->sub_array (start_offset, record_count);
120       unsigned int count = *record_count;
121       for (unsigned int i = 0; i < count; i++)
122 	record_tags[i] = arr[i].tag;
123     }
124     return this->len;
125   }
find_indexOT::RecordArrayOf126   bool find_index (hb_tag_t tag, unsigned int *index) const
127   {
128     return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
129   }
130 };
131 
132 template <typename Type>
133 struct RecordListOf : RecordArrayOf<Type>
134 {
operator []OT::RecordListOf135   const Type& operator [] (unsigned int i) const
136   { return this+this->get_offset (i); }
137 
subsetOT::RecordListOf138   bool subset (hb_subset_context_t *c) const
139   {
140     TRACE_SUBSET (this);
141     auto *out = c->serializer->embed (*this);
142     if (unlikely (!out)) return_trace (false);
143     unsigned int count = this->len;
144     for (unsigned int i = 0; i < count; i++)
145       out->get_offset (i).serialize_subset (c, this->get_offset (i), this, out);
146     return_trace (true);
147   }
148 
sanitizeOT::RecordListOf149   bool sanitize (hb_sanitize_context_t *c) const
150   {
151     TRACE_SANITIZE (this);
152     return_trace (RecordArrayOf<Type>::sanitize (c, this));
153   }
154 };
155 
156 
157 struct RangeRecord
158 {
cmpOT::RangeRecord159   int cmp (hb_codepoint_t g) const
160   { return g < start ? -1 : g <= end ? 0 : +1; }
161 
sanitizeOT::RangeRecord162   bool sanitize (hb_sanitize_context_t *c) const
163   {
164     TRACE_SANITIZE (this);
165     return_trace (c->check_struct (this));
166   }
167 
intersectsOT::RangeRecord168   bool intersects (const hb_set_t *glyphs) const
169   { return glyphs->intersects (start, end); }
170 
171   template <typename set_t>
add_coverageOT::RangeRecord172   bool add_coverage (set_t *glyphs) const
173   { return glyphs->add_range (start, end); }
174 
175   GlyphID	start;		/* First GlyphID in the range */
176   GlyphID	end;		/* Last GlyphID in the range */
177   HBUINT16	value;		/* Value */
178   public:
179   DEFINE_SIZE_STATIC (6);
180 };
181 DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
182 
183 
184 struct IndexArray : ArrayOf<Index>
185 {
get_indexesOT::IndexArray186   unsigned int get_indexes (unsigned int start_offset,
187 			    unsigned int *_count /* IN/OUT */,
188 			    unsigned int *_indexes /* OUT */) const
189   {
190     if (_count) {
191       const HBUINT16 *arr = this->sub_array (start_offset, _count);
192       unsigned int count = *_count;
193       for (unsigned int i = 0; i < count; i++)
194 	_indexes[i] = arr[i];
195     }
196     return this->len;
197   }
198 
add_indexes_toOT::IndexArray199   void add_indexes_to (hb_set_t* output /* OUT */) const
200   {
201     output->add_array (arrayZ, len);
202   }
203 };
204 
205 
206 struct Script;
207 struct LangSys;
208 struct Feature;
209 
210 
211 struct LangSys
212 {
get_feature_countOT::LangSys213   unsigned int get_feature_count () const
214   { return featureIndex.len; }
get_feature_indexOT::LangSys215   hb_tag_t get_feature_index (unsigned int i) const
216   { return featureIndex[i]; }
get_feature_indexesOT::LangSys217   unsigned int get_feature_indexes (unsigned int start_offset,
218 				    unsigned int *feature_count /* IN/OUT */,
219 				    unsigned int *feature_indexes /* OUT */) const
220   { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
add_feature_indexes_toOT::LangSys221   void add_feature_indexes_to (hb_set_t *feature_indexes) const
222   { featureIndex.add_indexes_to (feature_indexes); }
223 
has_required_featureOT::LangSys224   bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
get_required_feature_indexOT::LangSys225   unsigned int get_required_feature_index () const
226   {
227     if (reqFeatureIndex == 0xFFFFu)
228       return Index::NOT_FOUND_INDEX;
229    return reqFeatureIndex;
230   }
231 
copyOT::LangSys232   LangSys* copy (hb_serialize_context_t *c) const
233   {
234     TRACE_SERIALIZE (this);
235     return_trace (c->embed (*this));
236   }
237 
sanitizeOT::LangSys238   bool sanitize (hb_sanitize_context_t *c,
239 		 const Record_sanitize_closure_t * = nullptr) const
240   {
241     TRACE_SANITIZE (this);
242     return_trace (c->check_struct (this) && featureIndex.sanitize (c));
243   }
244 
245   Offset16	lookupOrderZ;	/* = Null (reserved for an offset to a
246 				 * reordering table) */
247   HBUINT16	reqFeatureIndex;/* Index of a feature required for this
248 				 * language system--if no required features
249 				 * = 0xFFFFu */
250   IndexArray	featureIndex;	/* Array of indices into the FeatureList */
251   public:
252   DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
253 };
254 DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
255 
256 struct Script
257 {
get_lang_sys_countOT::Script258   unsigned int get_lang_sys_count () const
259   { return langSys.len; }
get_lang_sys_tagOT::Script260   const Tag& get_lang_sys_tag (unsigned int i) const
261   { return langSys.get_tag (i); }
get_lang_sys_tagsOT::Script262   unsigned int get_lang_sys_tags (unsigned int start_offset,
263 				  unsigned int *lang_sys_count /* IN/OUT */,
264 				  hb_tag_t     *lang_sys_tags /* OUT */) const
265   { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
get_lang_sysOT::Script266   const LangSys& get_lang_sys (unsigned int i) const
267   {
268     if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
269     return this+langSys[i].offset;
270   }
find_lang_sys_indexOT::Script271   bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
272   { return langSys.find_index (tag, index); }
273 
has_default_lang_sysOT::Script274   bool has_default_lang_sys () const           { return defaultLangSys != 0; }
get_default_lang_sysOT::Script275   const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
276 
subsetOT::Script277   bool subset (hb_subset_context_t *c) const
278   {
279     TRACE_SUBSET (this);
280     auto *out = c->serializer->embed (*this);
281     if (unlikely (!out)) return_trace (false);
282     out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out);
283     unsigned int count = langSys.len;
284     for (unsigned int i = 0; i < count; i++)
285       out->langSys.arrayZ[i].offset.serialize_copy (c->serializer, langSys[i].offset, this, out);
286     return_trace (true);
287   }
288 
sanitizeOT::Script289   bool sanitize (hb_sanitize_context_t *c,
290 		 const Record_sanitize_closure_t * = nullptr) const
291   {
292     TRACE_SANITIZE (this);
293     return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
294   }
295 
296   protected:
297   OffsetTo<LangSys>
298 		defaultLangSys;	/* Offset to DefaultLangSys table--from
299 				 * beginning of Script table--may be Null */
300   RecordArrayOf<LangSys>
301 		langSys;	/* Array of LangSysRecords--listed
302 				 * alphabetically by LangSysTag */
303   public:
304   DEFINE_SIZE_ARRAY_SIZED (4, langSys);
305 };
306 
307 typedef RecordListOf<Script> ScriptList;
308 
309 
310 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
311 struct FeatureParamsSize
312 {
sanitizeOT::FeatureParamsSize313   bool sanitize (hb_sanitize_context_t *c) const
314   {
315     TRACE_SANITIZE (this);
316     if (unlikely (!c->check_struct (this))) return_trace (false);
317 
318     /* This subtable has some "history", if you will.  Some earlier versions of
319      * Adobe tools calculated the offset of the FeatureParams sutable from the
320      * beginning of the FeatureList table!  Now, that is dealt with in the
321      * Feature implementation.  But we still need to be able to tell junk from
322      * real data.  Note: We don't check that the nameID actually exists.
323      *
324      * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
325      *
326      * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
327      * coming out soon, and that the makeotf program will build a font with a
328      * 'size' feature that is correct by the specification.
329      *
330      * The specification for this feature tag is in the "OpenType Layout Tag
331      * Registry". You can see a copy of this at:
332      * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
333      *
334      * Here is one set of rules to determine if the 'size' feature is built
335      * correctly, or as by the older versions of MakeOTF. You may be able to do
336      * better.
337      *
338      * Assume that the offset to the size feature is according to specification,
339      * and make the following value checks. If it fails, assume the size
340      * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
341      * If this fails, reject the 'size' feature. The older makeOTF's calculated the
342      * offset from the beginning of the FeatureList table, rather than from the
343      * beginning of the 'size' Feature table.
344      *
345      * If "design size" == 0:
346      *     fails check
347      *
348      * Else if ("subfamily identifier" == 0 and
349      *     "range start" == 0 and
350      *     "range end" == 0 and
351      *     "range start" == 0 and
352      *     "menu name ID" == 0)
353      *     passes check: this is the format used when there is a design size
354      * specified, but there is no recommended size range.
355      *
356      * Else if ("design size" <  "range start" or
357      *     "design size" >   "range end" or
358      *     "range end" <= "range start" or
359      *     "menu name ID"  < 256 or
360      *     "menu name ID"  > 32767 or
361      *     menu name ID is not a name ID which is actually in the name table)
362      *     fails test
363      * Else
364      *     passes test.
365      */
366 
367     if (!designSize)
368       return_trace (false);
369     else if (subfamilyID == 0 &&
370 	     subfamilyNameID == 0 &&
371 	     rangeStart == 0 &&
372 	     rangeEnd == 0)
373       return_trace (true);
374     else if (designSize < rangeStart ||
375 	     designSize > rangeEnd ||
376 	     subfamilyNameID < 256 ||
377 	     subfamilyNameID > 32767)
378       return_trace (false);
379     else
380       return_trace (true);
381   }
382 
383   HBUINT16	designSize;	/* Represents the design size in 720/inch
384 				 * units (decipoints).  The design size entry
385 				 * must be non-zero.  When there is a design
386 				 * size but no recommended size range, the
387 				 * rest of the array will consist of zeros. */
388   HBUINT16	subfamilyID;	/* Has no independent meaning, but serves
389 				 * as an identifier that associates fonts
390 				 * in a subfamily. All fonts which share a
391 				 * Preferred or Font Family name and which
392 				 * differ only by size range shall have the
393 				 * same subfamily value, and no fonts which
394 				 * differ in weight or style shall have the
395 				 * same subfamily value. If this value is
396 				 * zero, the remaining fields in the array
397 				 * will be ignored. */
398   NameID	subfamilyNameID;/* If the preceding value is non-zero, this
399 				 * value must be set in the range 256 - 32767
400 				 * (inclusive). It records the value of a
401 				 * field in the name table, which must
402 				 * contain English-language strings encoded
403 				 * in Windows Unicode and Macintosh Roman,
404 				 * and may contain additional strings
405 				 * localized to other scripts and languages.
406 				 * Each of these strings is the name an
407 				 * application should use, in combination
408 				 * with the family name, to represent the
409 				 * subfamily in a menu.  Applications will
410 				 * choose the appropriate version based on
411 				 * their selection criteria. */
412   HBUINT16	rangeStart;	/* Large end of the recommended usage range
413 				 * (inclusive), stored in 720/inch units
414 				 * (decipoints). */
415   HBUINT16	rangeEnd;	/* Small end of the recommended usage range
416 				   (exclusive), stored in 720/inch units
417 				 * (decipoints). */
418   public:
419   DEFINE_SIZE_STATIC (10);
420 };
421 
422 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
423 struct FeatureParamsStylisticSet
424 {
sanitizeOT::FeatureParamsStylisticSet425   bool sanitize (hb_sanitize_context_t *c) const
426   {
427     TRACE_SANITIZE (this);
428     /* Right now minorVersion is at zero.  Which means, any table supports
429      * the uiNameID field. */
430     return_trace (c->check_struct (this));
431   }
432 
433   HBUINT16	version;	/* (set to 0): This corresponds to a “minor”
434 				 * version number. Additional data may be
435 				 * added to the end of this Feature Parameters
436 				 * table in the future. */
437 
438   NameID	uiNameID;	/* The 'name' table name ID that specifies a
439 				 * string (or strings, for multiple languages)
440 				 * for a user-interface label for this
441 				 * feature.  The values of uiLabelNameId and
442 				 * sampleTextNameId are expected to be in the
443 				 * font-specific name ID range (256-32767),
444 				 * though that is not a requirement in this
445 				 * Feature Parameters specification. The
446 				 * user-interface label for the feature can
447 				 * be provided in multiple languages. An
448 				 * English string should be included as a
449 				 * fallback. The string should be kept to a
450 				 * minimal length to fit comfortably with
451 				 * different application interfaces. */
452   public:
453   DEFINE_SIZE_STATIC (4);
454 };
455 
456 /* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
457 struct FeatureParamsCharacterVariants
458 {
sanitizeOT::FeatureParamsCharacterVariants459   bool sanitize (hb_sanitize_context_t *c) const
460   {
461     TRACE_SANITIZE (this);
462     return_trace (c->check_struct (this) &&
463 		  characters.sanitize (c));
464   }
465 
466   HBUINT16	format;			/* Format number is set to 0. */
467   NameID	featUILableNameID;	/* The ‘name’ table name ID that
468 					 * specifies a string (or strings,
469 					 * for multiple languages) for a
470 					 * user-interface label for this
471 					 * feature. (May be NULL.) */
472   NameID	featUITooltipTextNameID;/* The ‘name’ table name ID that
473 					 * specifies a string (or strings,
474 					 * for multiple languages) that an
475 					 * application can use for tooltip
476 					 * text for this feature. (May be
477 					 * nullptr.) */
478   NameID	sampleTextNameID;	/* The ‘name’ table name ID that
479 					 * specifies sample text that
480 					 * illustrates the effect of this
481 					 * feature. (May be NULL.) */
482   HBUINT16	numNamedParameters;	/* Number of named parameters. (May
483 					 * be zero.) */
484   NameID	firstParamUILabelNameID;/* The first ‘name’ table name ID
485 					 * used to specify strings for
486 					 * user-interface labels for the
487 					 * feature parameters. (Must be zero
488 					 * if numParameters is zero.) */
489   ArrayOf<HBUINT24>
490 		characters;		/* Array of the Unicode Scalar Value
491 					 * of the characters for which this
492 					 * feature provides glyph variants.
493 					 * (May be zero.) */
494   public:
495   DEFINE_SIZE_ARRAY (14, characters);
496 };
497 
498 struct FeatureParams
499 {
sanitizeOT::FeatureParams500   bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
501   {
502     TRACE_SANITIZE (this);
503     if (tag == HB_TAG ('s','i','z','e'))
504       return_trace (u.size.sanitize (c));
505     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
506       return_trace (u.stylisticSet.sanitize (c));
507     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
508       return_trace (u.characterVariants.sanitize (c));
509     return_trace (true);
510   }
511 
get_size_paramsOT::FeatureParams512   const FeatureParamsSize& get_size_params (hb_tag_t tag) const
513   {
514     if (tag == HB_TAG ('s','i','z','e'))
515       return u.size;
516     return Null (FeatureParamsSize);
517   }
518 
get_stylistic_set_paramsOT::FeatureParams519   const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
520   {
521     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
522       return u.stylisticSet;
523     return Null (FeatureParamsStylisticSet);
524   }
525 
get_character_variants_paramsOT::FeatureParams526   const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
527   {
528     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
529       return u.characterVariants;
530     return Null (FeatureParamsCharacterVariants);
531   }
532 
533   private:
534   union {
535   FeatureParamsSize			size;
536   FeatureParamsStylisticSet		stylisticSet;
537   FeatureParamsCharacterVariants	characterVariants;
538   } u;
539   public:
540   DEFINE_SIZE_STATIC (17);
541 };
542 
543 struct Feature
544 {
get_lookup_countOT::Feature545   unsigned int get_lookup_count () const
546   { return lookupIndex.len; }
get_lookup_indexOT::Feature547   hb_tag_t get_lookup_index (unsigned int i) const
548   { return lookupIndex[i]; }
get_lookup_indexesOT::Feature549   unsigned int get_lookup_indexes (unsigned int start_index,
550 				   unsigned int *lookup_count /* IN/OUT */,
551 				   unsigned int *lookup_tags /* OUT */) const
552   { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
add_lookup_indexes_toOT::Feature553   void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
554   { lookupIndex.add_indexes_to (lookup_indexes); }
555 
get_feature_paramsOT::Feature556   const FeatureParams &get_feature_params () const
557   { return this+featureParams; }
558 
subsetOT::Feature559   bool subset (hb_subset_context_t *c) const
560   {
561     TRACE_SUBSET (this);
562     auto *out = c->serializer->embed (*this);
563     if (unlikely (!out)) return_trace (false);
564     out->featureParams = 0; /* TODO(subset) FeatureParams. */
565     return_trace (true);
566   }
567 
sanitizeOT::Feature568   bool sanitize (hb_sanitize_context_t *c,
569 		 const Record_sanitize_closure_t *closure = nullptr) const
570   {
571     TRACE_SANITIZE (this);
572     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
573       return_trace (false);
574 
575     /* Some earlier versions of Adobe tools calculated the offset of the
576      * FeatureParams subtable from the beginning of the FeatureList table!
577      *
578      * If sanitizing "failed" for the FeatureParams subtable, try it with the
579      * alternative location.  We would know sanitize "failed" if old value
580      * of the offset was non-zero, but it's zeroed now.
581      *
582      * Only do this for the 'size' feature, since at the time of the faulty
583      * Adobe tools, only the 'size' feature had FeatureParams defined.
584      */
585 
586     if (likely (featureParams.is_null ()))
587       return_trace (true);
588 
589     unsigned int orig_offset = featureParams;
590     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
591       return_trace (false);
592 
593     if (featureParams == 0 && closure &&
594 	closure->tag == HB_TAG ('s','i','z','e') &&
595 	closure->list_base && closure->list_base < this)
596     {
597       unsigned int new_offset_int = orig_offset -
598 				    (((char *) this) - ((char *) closure->list_base));
599 
600       OffsetTo<FeatureParams> new_offset;
601       /* Check that it would not overflow. */
602       new_offset = new_offset_int;
603       if (new_offset == new_offset_int &&
604 	  c->try_set (&featureParams, new_offset_int) &&
605 	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
606 	return_trace (false);
607     }
608 
609     return_trace (true);
610   }
611 
612   OffsetTo<FeatureParams>
613 		 featureParams;	/* Offset to Feature Parameters table (if one
614 				 * has been defined for the feature), relative
615 				 * to the beginning of the Feature Table; = Null
616 				 * if not required */
617   IndexArray	 lookupIndex;	/* Array of LookupList indices */
618   public:
619   DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
620 };
621 
622 typedef RecordListOf<Feature> FeatureList;
623 
624 
625 struct LookupFlag : HBUINT16
626 {
627   enum Flags {
628     RightToLeft		= 0x0001u,
629     IgnoreBaseGlyphs	= 0x0002u,
630     IgnoreLigatures	= 0x0004u,
631     IgnoreMarks		= 0x0008u,
632     IgnoreFlags		= 0x000Eu,
633     UseMarkFilteringSet	= 0x0010u,
634     Reserved		= 0x00E0u,
635     MarkAttachmentType	= 0xFF00u
636   };
637   public:
638   DEFINE_SIZE_STATIC (2);
639 };
640 
641 } /* namespace OT */
642 /* This has to be outside the namespace. */
643 HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
644 namespace OT {
645 
646 struct Lookup
647 {
get_subtable_countOT::Lookup648   unsigned int get_subtable_count () const { return subTable.len; }
649 
650   template <typename TSubTable>
get_subtablesOT::Lookup651   const OffsetArrayOf<TSubTable>& get_subtables () const
652   { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
653   template <typename TSubTable>
get_subtablesOT::Lookup654   OffsetArrayOf<TSubTable>& get_subtables ()
655   { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
656 
657   template <typename TSubTable>
get_subtableOT::Lookup658   const TSubTable& get_subtable (unsigned int i) const
659   { return this+get_subtables<TSubTable> ()[i]; }
660   template <typename TSubTable>
get_subtableOT::Lookup661   TSubTable& get_subtable (unsigned int i)
662   { return this+get_subtables<TSubTable> ()[i]; }
663 
get_sizeOT::Lookup664   unsigned int get_size () const
665   {
666     const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
667     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
668       return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
669     return (const char *) &markFilteringSet - (const char *) this;
670   }
671 
get_typeOT::Lookup672   unsigned int get_type () const { return lookupType; }
673 
674   /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
675    * higher 16-bit is mark-filtering-set if the lookup uses one.
676    * Not to be confused with glyph_props which is very similar. */
get_propsOT::Lookup677   uint32_t get_props () const
678   {
679     unsigned int flag = lookupFlag;
680     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
681     {
682       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
683       flag += (markFilteringSet << 16);
684     }
685     return flag;
686   }
687 
688   template <typename TSubTable, typename context_t, typename ...Ts>
dispatchOT::Lookup689   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
690   {
691     unsigned int lookup_type = get_type ();
692     TRACE_DISPATCH (this, lookup_type);
693     unsigned int count = get_subtable_count ();
694     for (unsigned int i = 0; i < count; i++) {
695       typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...);
696       if (c->stop_sublookup_iteration (r))
697 	return_trace (r);
698     }
699     return_trace (c->default_return_value ());
700   }
701 
serializeOT::Lookup702   bool serialize (hb_serialize_context_t *c,
703 		  unsigned int lookup_type,
704 		  uint32_t lookup_props,
705 		  unsigned int num_subtables)
706   {
707     TRACE_SERIALIZE (this);
708     if (unlikely (!c->extend_min (*this))) return_trace (false);
709     lookupType = lookup_type;
710     lookupFlag = lookup_props & 0xFFFFu;
711     if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
712     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
713     {
714       if (unlikely (!c->extend (*this))) return_trace (false);
715       HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
716       markFilteringSet = lookup_props >> 16;
717     }
718     return_trace (true);
719   }
720 
721   template <typename TSubTable>
subsetOT::Lookup722   bool subset (hb_subset_context_t *c) const
723   {
724     TRACE_SUBSET (this);
725     auto *out = c->serializer->embed (*this);
726     if (unlikely (!out)) return_trace (false);
727 
728     /* Subset the actual subtables. */
729     /* TODO Drop empty ones, either by calling intersects() beforehand,
730      * or just dropping null offsets after. */
731     const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
732     OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
733     unsigned int count = subTable.len;
734     for (unsigned int i = 0; i < count; i++)
735       out_subtables[i].serialize_subset (c, subtables[i], this, out, get_type ());
736 
737     return_trace (true);
738   }
739 
740   template <typename TSubTable>
sanitizeOT::Lookup741   bool sanitize (hb_sanitize_context_t *c) const
742   {
743     TRACE_SANITIZE (this);
744     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
745     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
746     {
747       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
748       if (!markFilteringSet.sanitize (c)) return_trace (false);
749     }
750 
751     if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
752       return_trace (false);
753 
754     if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
755     {
756       /* The spec says all subtables of an Extension lookup should
757        * have the same type, which shall not be the Extension type
758        * itself (but we already checked for that).
759        * This is specially important if one has a reverse type!
760        *
761        * We only do this if sanitizer edit_count is zero.  Otherwise,
762        * some of the subtables might have become insane after they
763        * were sanity-checked by the edits of subsequent subtables.
764        * https://bugs.chromium.org/p/chromium/issues/detail?id=960331
765        */
766       unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
767       unsigned int count = get_subtable_count ();
768       for (unsigned int i = 1; i < count; i++)
769 	if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
770 	  return_trace (false);
771     }
772     return_trace (true);
773   }
774 
775   private:
776   HBUINT16	lookupType;		/* Different enumerations for GSUB and GPOS */
777   HBUINT16	lookupFlag;		/* Lookup qualifiers */
778   ArrayOf<Offset16>
779 		subTable;		/* Array of SubTables */
780 /*HBUINT16	markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
781 					 * structure. This field is only present if bit
782 					 * UseMarkFilteringSet of lookup flags is set. */
783   public:
784   DEFINE_SIZE_ARRAY (6, subTable);
785 };
786 
787 typedef OffsetListOf<Lookup> LookupList;
788 
789 
790 /*
791  * Coverage Table
792  */
793 
794 struct CoverageFormat1
795 {
796   friend struct Coverage;
797 
798   private:
get_coverageOT::CoverageFormat1799   unsigned int get_coverage (hb_codepoint_t glyph_id) const
800   {
801     unsigned int i;
802     glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
803     return i;
804   }
805 
806   template <typename Iterator,
807       hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
serializeOT::CoverageFormat1808   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
809   {
810     TRACE_SERIALIZE (this);
811     return_trace (glyphArray.serialize (c, glyphs));
812   }
813 
sanitizeOT::CoverageFormat1814   bool sanitize (hb_sanitize_context_t *c) const
815   {
816     TRACE_SANITIZE (this);
817     return_trace (glyphArray.sanitize (c));
818   }
819 
intersectsOT::CoverageFormat1820   bool intersects (const hb_set_t *glyphs) const
821   {
822     /* TODO Speed up, using hb_set_next() and bsearch()? */
823     unsigned int count = glyphArray.len;
824     for (unsigned int i = 0; i < count; i++)
825       if (glyphs->has (glyphArray[i]))
826 	return true;
827     return false;
828   }
intersects_coverageOT::CoverageFormat1829   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
830   { return glyphs->has (glyphArray[index]); }
831 
832   template <typename set_t>
add_coverageOT::CoverageFormat1833   bool add_coverage (set_t *glyphs) const
834   { return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len); }
835 
836   public:
837   /* Older compilers need this to be public. */
838   struct iter_t
839   {
initOT::CoverageFormat1::iter_t840     void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
finiOT::CoverageFormat1::iter_t841     void fini () {}
moreOT::CoverageFormat1::iter_t842     bool more () const { return i < c->glyphArray.len; }
nextOT::CoverageFormat1::iter_t843     void next () { i++; }
get_glyphOT::CoverageFormat1::iter_t844     hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
operator !=OT::CoverageFormat1::iter_t845     bool operator != (const iter_t& o) const
846     { return i != o.i || c != o.c; }
847 
848     private:
849     const struct CoverageFormat1 *c;
850     unsigned int i;
851   };
852   private:
853 
854   protected:
855   HBUINT16	coverageFormat;	/* Format identifier--format = 1 */
856   SortedArrayOf<GlyphID>
857 		glyphArray;	/* Array of GlyphIDs--in numerical order */
858   public:
859   DEFINE_SIZE_ARRAY (4, glyphArray);
860 };
861 
862 struct CoverageFormat2
863 {
864   friend struct Coverage;
865 
866   private:
get_coverageOT::CoverageFormat2867   unsigned int get_coverage (hb_codepoint_t glyph_id) const
868   {
869     const RangeRecord &range = rangeRecord.bsearch (glyph_id);
870     return likely (range.start <= range.end) ?
871 	   (unsigned int) range.value + (glyph_id - range.start) :
872 	   NOT_COVERED;
873   }
874 
875   template <typename Iterator,
876       hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
serializeOT::CoverageFormat2877   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
878   {
879     TRACE_SERIALIZE (this);
880     if (unlikely (!c->extend_min (*this))) return_trace (false);
881 
882     if (unlikely (!glyphs))
883     {
884       rangeRecord.len = 0;
885       return_trace (true);
886     }
887 
888     /* TODO(iter) Write more efficiently? */
889 
890     unsigned num_ranges = 0;
891     hb_codepoint_t last = (hb_codepoint_t) -2;
892     for (auto g: glyphs)
893     {
894       if (last + 1 != g)
895         num_ranges++;
896       last = g;
897     }
898 
899     if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
900 
901     unsigned count = 0;
902     unsigned range = (unsigned) -1;
903     last = (hb_codepoint_t) -2;
904     for (auto g: glyphs)
905     {
906       if (last + 1 != g)
907       {
908         range++;
909 	rangeRecord[range].start = g;
910 	rangeRecord[range].value = count;
911       }
912       rangeRecord[range].end = g;
913       last = g;
914       count++;
915     }
916 
917     return_trace (true);
918   }
919 
sanitizeOT::CoverageFormat2920   bool sanitize (hb_sanitize_context_t *c) const
921   {
922     TRACE_SANITIZE (this);
923     return_trace (rangeRecord.sanitize (c));
924   }
925 
intersectsOT::CoverageFormat2926   bool intersects (const hb_set_t *glyphs) const
927   {
928     /* TODO Speed up, using hb_set_next() and bsearch()? */
929     unsigned int count = rangeRecord.len;
930     for (unsigned int i = 0; i < count; i++)
931       if (rangeRecord[i].intersects (glyphs))
932 	return true;
933     return false;
934   }
intersects_coverageOT::CoverageFormat2935   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
936   {
937     unsigned int i;
938     unsigned int count = rangeRecord.len;
939     for (i = 0; i < count; i++) {
940       const RangeRecord &range = rangeRecord[i];
941       if (range.value <= index &&
942 	  index < (unsigned int) range.value + (range.end - range.start) &&
943 	  range.intersects (glyphs))
944 	return true;
945       else if (index < range.value)
946 	return false;
947     }
948     return false;
949   }
950 
951   template <typename set_t>
add_coverageOT::CoverageFormat2952   bool add_coverage (set_t *glyphs) const
953   {
954     unsigned int count = rangeRecord.len;
955     for (unsigned int i = 0; i < count; i++)
956       if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
957 	return false;
958     return true;
959   }
960 
961   public:
962   /* Older compilers need this to be public. */
963   struct iter_t
964   {
initOT::CoverageFormat2::iter_t965     void init (const CoverageFormat2 &c_)
966     {
967       c = &c_;
968       coverage = 0;
969       i = 0;
970       j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
971       if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
972       {
973 	/* Broken table. Skip. */
974 	i = c->rangeRecord.len;
975       }
976     }
finiOT::CoverageFormat2::iter_t977     void fini () {}
moreOT::CoverageFormat2::iter_t978     bool more () const { return i < c->rangeRecord.len; }
nextOT::CoverageFormat2::iter_t979     void next ()
980     {
981       if (j >= c->rangeRecord[i].end)
982       {
983 	i++;
984 	if (more ())
985 	{
986 	  unsigned int old = coverage;
987 	  j = c->rangeRecord[i].start;
988 	  coverage = c->rangeRecord[i].value;
989 	  if (unlikely (coverage != old + 1))
990 	  {
991 	    /* Broken table. Skip. Important to avoid DoS.
992 	     * Also, our callers depend on coverage being
993 	     * consecutive and monotonically increasing,
994 	     * ie. iota(). */
995 	   i = c->rangeRecord.len;
996 	   return;
997 	  }
998 	}
999 	return;
1000       }
1001       coverage++;
1002       j++;
1003     }
get_glyphOT::CoverageFormat2::iter_t1004     hb_codepoint_t get_glyph () const { return j; }
operator !=OT::CoverageFormat2::iter_t1005     bool operator != (const iter_t& o) const
1006     { return i != o.i || j != o.j || c != o.c; }
1007 
1008     private:
1009     const struct CoverageFormat2 *c;
1010     unsigned int i, coverage;
1011     hb_codepoint_t j;
1012   };
1013   private:
1014 
1015   protected:
1016   HBUINT16	coverageFormat;	/* Format identifier--format = 2 */
1017   SortedArrayOf<RangeRecord>
1018 		rangeRecord;	/* Array of glyph ranges--ordered by
1019 				 * Start GlyphID. rangeCount entries
1020 				 * long */
1021   public:
1022   DEFINE_SIZE_ARRAY (4, rangeRecord);
1023 };
1024 
1025 struct Coverage
1026 {
1027   /* Has interface. */
1028   static constexpr unsigned SENTINEL = NOT_COVERED;
1029   typedef unsigned int value_t;
operator []OT::Coverage1030   value_t operator [] (hb_codepoint_t k) const { return get (k); }
hasOT::Coverage1031   bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
1032   /* Predicate. */
operator ()OT::Coverage1033   bool operator () (hb_codepoint_t k) const { return has (k); }
1034 
getOT::Coverage1035   unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
get_coverageOT::Coverage1036   unsigned int get_coverage (hb_codepoint_t glyph_id) const
1037   {
1038     switch (u.format) {
1039     case 1: return u.format1.get_coverage (glyph_id);
1040     case 2: return u.format2.get_coverage (glyph_id);
1041     default:return NOT_COVERED;
1042     }
1043   }
1044 
1045   template <typename Iterator,
1046       hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
serializeOT::Coverage1047   bool serialize (hb_serialize_context_t *c, Iterator glyphs)
1048   {
1049     TRACE_SERIALIZE (this);
1050     if (unlikely (!c->extend_min (*this))) return_trace (false);
1051 
1052     unsigned count = 0;
1053     unsigned num_ranges = 0;
1054     hb_codepoint_t last = (hb_codepoint_t) -2;
1055     for (auto g: glyphs)
1056     {
1057       if (last + 1 != g)
1058         num_ranges++;
1059       last = g;
1060       count++;
1061     }
1062     u.format = count * 2 < num_ranges * 3 ? 1 : 2;
1063 
1064     switch (u.format)
1065     {
1066     case 1: return_trace (u.format1.serialize (c, glyphs));
1067     case 2: return_trace (u.format2.serialize (c, glyphs));
1068     default:return_trace (false);
1069     }
1070   }
1071 
sanitizeOT::Coverage1072   bool sanitize (hb_sanitize_context_t *c) const
1073   {
1074     TRACE_SANITIZE (this);
1075     if (!u.format.sanitize (c)) return_trace (false);
1076     switch (u.format)
1077     {
1078     case 1: return_trace (u.format1.sanitize (c));
1079     case 2: return_trace (u.format2.sanitize (c));
1080     default:return_trace (true);
1081     }
1082   }
1083 
intersectsOT::Coverage1084   bool intersects (const hb_set_t *glyphs) const
1085   {
1086     switch (u.format)
1087     {
1088     case 1: return u.format1.intersects (glyphs);
1089     case 2: return u.format2.intersects (glyphs);
1090     default:return false;
1091     }
1092   }
intersects_coverageOT::Coverage1093   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
1094   {
1095     switch (u.format)
1096     {
1097     case 1: return u.format1.intersects_coverage (glyphs, index);
1098     case 2: return u.format2.intersects_coverage (glyphs, index);
1099     default:return false;
1100     }
1101   }
1102 
1103   /* Might return false if array looks unsorted.
1104    * Used for faster rejection of corrupt data. */
1105   template <typename set_t>
add_coverageOT::Coverage1106   bool add_coverage (set_t *glyphs) const
1107   {
1108     switch (u.format)
1109     {
1110     case 1: return u.format1.add_coverage (glyphs);
1111     case 2: return u.format2.add_coverage (glyphs);
1112     default:return false;
1113     }
1114   }
1115 
1116   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
1117   {
1118     static constexpr bool is_sorted_iterator = true;
iter_tOT::Coverage::iter_t1119     iter_t (const Coverage &c_ = Null(Coverage))
1120     {
1121       memset (this, 0, sizeof (*this));
1122       format = c_.u.format;
1123       switch (format)
1124       {
1125       case 1: u.format1.init (c_.u.format1); return;
1126       case 2: u.format2.init (c_.u.format2); return;
1127       default:				     return;
1128       }
1129     }
__more__OT::Coverage::iter_t1130     bool __more__ () const
1131     {
1132       switch (format)
1133       {
1134       case 1: return u.format1.more ();
1135       case 2: return u.format2.more ();
1136       default:return false;
1137       }
1138     }
__next__OT::Coverage::iter_t1139     void __next__ ()
1140     {
1141       switch (format)
1142       {
1143       case 1: u.format1.next (); break;
1144       case 2: u.format2.next (); break;
1145       default:			 break;
1146       }
1147     }
1148     typedef hb_codepoint_t __item_t__;
__item__OT::Coverage::iter_t1149     __item_t__ __item__ () const { return get_glyph (); }
1150 
get_glyphOT::Coverage::iter_t1151     hb_codepoint_t get_glyph () const
1152     {
1153       switch (format)
1154       {
1155       case 1: return u.format1.get_glyph ();
1156       case 2: return u.format2.get_glyph ();
1157       default:return 0;
1158       }
1159     }
operator !=OT::Coverage::iter_t1160     bool operator != (const iter_t& o) const
1161     {
1162       if (format != o.format) return true;
1163       switch (format)
1164       {
1165       case 1: return u.format1 != o.u.format1;
1166       case 2: return u.format2 != o.u.format2;
1167       default:return false;
1168       }
1169     }
1170 
1171     private:
1172     unsigned int format;
1173     union {
1174     CoverageFormat2::iter_t	format2; /* Put this one first since it's larger; helps shut up compiler. */
1175     CoverageFormat1::iter_t	format1;
1176     } u;
1177   };
iterOT::Coverage1178   iter_t iter () const { return iter_t (*this); }
1179 
1180   protected:
1181   union {
1182   HBUINT16		format;		/* Format identifier */
1183   CoverageFormat1	format1;
1184   CoverageFormat2	format2;
1185   } u;
1186   public:
1187   DEFINE_SIZE_UNION (2, format);
1188 };
1189 
1190 
1191 /*
1192  * Class Definition Table
1193  */
1194 
1195 static inline void ClassDef_serialize (hb_serialize_context_t *c,
1196 				       hb_array_t<const GlyphID> glyphs,
1197 				       hb_array_t<const HBUINT16> klasses);
1198 
1199 struct ClassDefFormat1
1200 {
1201   friend struct ClassDef;
1202 
1203   private:
get_classOT::ClassDefFormat11204   unsigned int get_class (hb_codepoint_t glyph_id) const
1205   {
1206     return classValue[(unsigned int) (glyph_id - startGlyph)];
1207   }
1208 
serializeOT::ClassDefFormat11209   bool serialize (hb_serialize_context_t *c,
1210 		  hb_array_t<const GlyphID> glyphs,
1211 		  hb_array_t<const HBUINT16> klasses)
1212   {
1213     TRACE_SERIALIZE (this);
1214     if (unlikely (!c->extend_min (*this))) return_trace (false);
1215 
1216     if (unlikely (!glyphs))
1217     {
1218       startGlyph = 0;
1219       classValue.len = 0;
1220       return_trace (true);
1221     }
1222 
1223     hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu);
1224     hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
1225 
1226     startGlyph = glyph_min;
1227     c->check_assign (classValue.len, glyph_max - glyph_min + 1);
1228     if (unlikely (!c->extend (classValue))) return_trace (false);
1229 
1230     for (unsigned int i = 0; i < glyphs.length; i++)
1231       classValue[glyphs[i] - glyph_min] = klasses[i];
1232 
1233     return_trace (true);
1234   }
1235 
subsetOT::ClassDefFormat11236   bool subset (hb_subset_context_t *c) const
1237   {
1238     TRACE_SUBSET (this);
1239     const hb_set_t &glyphset = *c->plan->glyphset ();
1240     const hb_map_t &glyph_map = *c->plan->glyph_map;
1241     hb_sorted_vector_t<GlyphID> glyphs;
1242     hb_vector_t<HBUINT16> klasses;
1243 
1244     hb_codepoint_t start = startGlyph;
1245     hb_codepoint_t end   = start + classValue.len;
1246     for (hb_codepoint_t g = start; g < end; g++)
1247     {
1248       if (!glyphset.has (g)) continue;
1249       unsigned int value = classValue[g - start];
1250       if (!value) continue;
1251       glyphs.push(glyph_map[g]);
1252       klasses.push(value);
1253     }
1254     c->serializer->propagate_error (glyphs, klasses);
1255     ClassDef_serialize (c->serializer, glyphs, klasses);
1256     return_trace ((bool) glyphs);
1257   }
1258 
sanitizeOT::ClassDefFormat11259   bool sanitize (hb_sanitize_context_t *c) const
1260   {
1261     TRACE_SANITIZE (this);
1262     return_trace (c->check_struct (this) && classValue.sanitize (c));
1263   }
1264 
1265   template <typename set_t>
add_coverageOT::ClassDefFormat11266   bool add_coverage (set_t *glyphs) const
1267   {
1268     unsigned int start = 0;
1269     unsigned int count = classValue.len;
1270     for (unsigned int i = 0; i < count; i++)
1271     {
1272       if (classValue[i])
1273 	continue;
1274 
1275       if (start != i)
1276 	if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
1277 	  return false;
1278 
1279       start = i + 1;
1280     }
1281     if (start != count)
1282       if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
1283 	return false;
1284 
1285     return true;
1286   }
1287 
1288   template <typename set_t>
add_classOT::ClassDefFormat11289   bool add_class (set_t *glyphs, unsigned int klass) const
1290   {
1291     unsigned int count = classValue.len;
1292     for (unsigned int i = 0; i < count; i++)
1293       if (classValue[i] == klass) glyphs->add (startGlyph + i);
1294     return true;
1295   }
1296 
intersectsOT::ClassDefFormat11297   bool intersects (const hb_set_t *glyphs) const
1298   {
1299     /* TODO Speed up, using hb_set_next()? */
1300     hb_codepoint_t start = startGlyph;
1301     hb_codepoint_t end = startGlyph + classValue.len;
1302     for (hb_codepoint_t iter = startGlyph - 1;
1303 	 hb_set_next (glyphs, &iter) && iter < end;)
1304       if (classValue[iter - start]) return true;
1305     return false;
1306   }
intersects_classOT::ClassDefFormat11307   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
1308   {
1309     unsigned int count = classValue.len;
1310     if (klass == 0)
1311     {
1312       /* Match if there's any glyph that is not listed! */
1313       hb_codepoint_t g = HB_SET_VALUE_INVALID;
1314       if (!hb_set_next (glyphs, &g)) return false;
1315       if (g < startGlyph) return true;
1316       g = startGlyph + count - 1;
1317       if (hb_set_next (glyphs, &g)) return true;
1318       /* Fall through. */
1319     }
1320     for (unsigned int i = 0; i < count; i++)
1321       if (classValue[i] == klass && glyphs->has (startGlyph + i))
1322 	return true;
1323     return false;
1324   }
1325 
1326   protected:
1327   HBUINT16	classFormat;	/* Format identifier--format = 1 */
1328   GlyphID	startGlyph;	/* First GlyphID of the classValueArray */
1329   ArrayOf<HBUINT16>
1330 		classValue;	/* Array of Class Values--one per GlyphID */
1331   public:
1332   DEFINE_SIZE_ARRAY (6, classValue);
1333 };
1334 
1335 struct ClassDefFormat2
1336 {
1337   friend struct ClassDef;
1338 
1339   private:
get_classOT::ClassDefFormat21340   unsigned int get_class (hb_codepoint_t glyph_id) const
1341   {
1342     return rangeRecord.bsearch (glyph_id).value;
1343   }
1344 
serializeOT::ClassDefFormat21345   bool serialize (hb_serialize_context_t *c,
1346 		  hb_array_t<const GlyphID> glyphs,
1347 		  hb_array_t<const HBUINT16> klasses)
1348   {
1349     TRACE_SERIALIZE (this);
1350     if (unlikely (!c->extend_min (*this))) return_trace (false);
1351 
1352     if (unlikely (!glyphs))
1353     {
1354       rangeRecord.len = 0;
1355       return_trace (true);
1356     }
1357 
1358     unsigned int count = glyphs.len ();
1359     unsigned int num_ranges = 1;
1360     for (unsigned int i = 1; i < count; i++)
1361       if (glyphs[i - 1] + 1 != glyphs[i] ||
1362 	  klasses[i - 1] != klasses[i])
1363 	num_ranges++;
1364     rangeRecord.len = num_ranges;
1365     if (unlikely (!c->extend (rangeRecord))) return_trace (false);
1366 
1367     unsigned int range = 0;
1368     rangeRecord[range].start = glyphs[0];
1369     rangeRecord[range].value = klasses[0];
1370     for (unsigned int i = 1; i < count; i++)
1371     {
1372       if (glyphs[i - 1] + 1 != glyphs[i] ||
1373 	  klasses[i - 1] != klasses[i])
1374       {
1375 	rangeRecord[range].end = glyphs[i - 1];
1376 	range++;
1377 	rangeRecord[range].start = glyphs[i];
1378 	rangeRecord[range].value = klasses[i];
1379       }
1380     }
1381     rangeRecord[range].end = glyphs[count - 1];
1382     return_trace (true);
1383   }
1384 
subsetOT::ClassDefFormat21385   bool subset (hb_subset_context_t *c) const
1386   {
1387     TRACE_SUBSET (this);
1388     const hb_set_t &glyphset = *c->plan->glyphset ();
1389     const hb_map_t &glyph_map = *c->plan->glyph_map;
1390     hb_vector_t<GlyphID> glyphs;
1391     hb_vector_t<HBUINT16> klasses;
1392 
1393     unsigned int count = rangeRecord.len;
1394     for (unsigned int i = 0; i < count; i++)
1395     {
1396       unsigned int value = rangeRecord[i].value;
1397       if (!value) continue;
1398       hb_codepoint_t start = rangeRecord[i].start;
1399       hb_codepoint_t end   = rangeRecord[i].end + 1;
1400       for (hb_codepoint_t g = start; g < end; g++)
1401       {
1402 	if (!glyphset.has (g)) continue;
1403 	glyphs.push (glyph_map[g]);
1404 	klasses.push (value);
1405       }
1406     }
1407     c->serializer->propagate_error (glyphs, klasses);
1408     ClassDef_serialize (c->serializer, glyphs, klasses);
1409     return_trace ((bool) glyphs);
1410   }
1411 
sanitizeOT::ClassDefFormat21412   bool sanitize (hb_sanitize_context_t *c) const
1413   {
1414     TRACE_SANITIZE (this);
1415     return_trace (rangeRecord.sanitize (c));
1416   }
1417 
1418   template <typename set_t>
add_coverageOT::ClassDefFormat21419   bool add_coverage (set_t *glyphs) const
1420   {
1421     unsigned int count = rangeRecord.len;
1422     for (unsigned int i = 0; i < count; i++)
1423       if (rangeRecord[i].value)
1424 	if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
1425 	  return false;
1426     return true;
1427   }
1428 
1429   template <typename set_t>
add_classOT::ClassDefFormat21430   bool add_class (set_t *glyphs, unsigned int klass) const
1431   {
1432     unsigned int count = rangeRecord.len;
1433     for (unsigned int i = 0; i < count; i++)
1434     {
1435       if (rangeRecord[i].value == klass)
1436 	if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
1437 	  return false;
1438     }
1439     return true;
1440   }
1441 
intersectsOT::ClassDefFormat21442   bool intersects (const hb_set_t *glyphs) const
1443   {
1444     /* TODO Speed up, using hb_set_next() and bsearch()? */
1445     unsigned int count = rangeRecord.len;
1446     for (unsigned int i = 0; i < count; i++)
1447       if (rangeRecord[i].intersects (glyphs))
1448 	return true;
1449     return false;
1450   }
intersects_classOT::ClassDefFormat21451   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
1452   {
1453     unsigned int count = rangeRecord.len;
1454     if (klass == 0)
1455     {
1456       /* Match if there's any glyph that is not listed! */
1457       hb_codepoint_t g = HB_SET_VALUE_INVALID;
1458       for (unsigned int i = 0; i < count; i++)
1459       {
1460 	if (!hb_set_next (glyphs, &g))
1461 	  break;
1462 	if (g < rangeRecord[i].start)
1463 	  return true;
1464 	g = rangeRecord[i].end;
1465       }
1466       if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
1467 	return true;
1468       /* Fall through. */
1469     }
1470     for (unsigned int i = 0; i < count; i++)
1471       if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
1472 	return true;
1473     return false;
1474   }
1475 
1476   protected:
1477   HBUINT16	classFormat;	/* Format identifier--format = 2 */
1478   SortedArrayOf<RangeRecord>
1479 		rangeRecord;	/* Array of glyph ranges--ordered by
1480 				 * Start GlyphID */
1481   public:
1482   DEFINE_SIZE_ARRAY (4, rangeRecord);
1483 };
1484 
1485 struct ClassDef
1486 {
1487   /* Has interface. */
1488   static constexpr unsigned SENTINEL = 0;
1489   typedef unsigned int value_t;
operator []OT::ClassDef1490   value_t operator [] (hb_codepoint_t k) const { return get (k); }
hasOT::ClassDef1491   bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
1492   /* Projection. */
operator ()OT::ClassDef1493   hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
1494 
getOT::ClassDef1495   unsigned int get (hb_codepoint_t k) const { return get_class (k); }
get_classOT::ClassDef1496   unsigned int get_class (hb_codepoint_t glyph_id) const
1497   {
1498     switch (u.format) {
1499     case 1: return u.format1.get_class (glyph_id);
1500     case 2: return u.format2.get_class (glyph_id);
1501     default:return 0;
1502     }
1503   }
1504 
serializeOT::ClassDef1505   bool serialize (hb_serialize_context_t *c,
1506 		  hb_array_t<const GlyphID> glyphs,
1507 		  hb_array_t<const HBUINT16> klasses)
1508   {
1509     TRACE_SERIALIZE (this);
1510     if (unlikely (!c->extend_min (*this))) return_trace (false);
1511 
1512     unsigned int format = 2;
1513     if (likely (glyphs))
1514     {
1515       hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu);
1516       hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
1517 
1518       unsigned int count = glyphs.len ();
1519       unsigned int num_ranges = 1;
1520       for (unsigned int i = 1; i < count; i++)
1521 	if (glyphs[i - 1] + 1 != glyphs[i] ||
1522 	    klasses[i - 1] != klasses[i])
1523 	  num_ranges++;
1524 
1525       if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
1526         format = 1;
1527     }
1528     u.format = format;
1529 
1530     switch (u.format)
1531     {
1532     case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
1533     case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
1534     default:return_trace (false);
1535     }
1536   }
1537 
subsetOT::ClassDef1538   bool subset (hb_subset_context_t *c) const
1539   {
1540     TRACE_SUBSET (this);
1541     switch (u.format) {
1542     case 1: return_trace (u.format1.subset (c));
1543     case 2: return_trace (u.format2.subset (c));
1544     default:return_trace (false);
1545     }
1546   }
1547 
sanitizeOT::ClassDef1548   bool sanitize (hb_sanitize_context_t *c) const
1549   {
1550     TRACE_SANITIZE (this);
1551     if (!u.format.sanitize (c)) return_trace (false);
1552     switch (u.format) {
1553     case 1: return_trace (u.format1.sanitize (c));
1554     case 2: return_trace (u.format2.sanitize (c));
1555     default:return_trace (true);
1556     }
1557   }
1558 
1559   /* Might return false if array looks unsorted.
1560    * Used for faster rejection of corrupt data. */
1561   template <typename set_t>
add_coverageOT::ClassDef1562   bool add_coverage (set_t *glyphs) const
1563   {
1564     switch (u.format) {
1565     case 1: return u.format1.add_coverage (glyphs);
1566     case 2: return u.format2.add_coverage (glyphs);
1567     default:return false;
1568     }
1569   }
1570 
1571   /* Might return false if array looks unsorted.
1572    * Used for faster rejection of corrupt data. */
1573   template <typename set_t>
add_classOT::ClassDef1574   bool add_class (set_t *glyphs, unsigned int klass) const
1575   {
1576     switch (u.format) {
1577     case 1: return u.format1.add_class (glyphs, klass);
1578     case 2: return u.format2.add_class (glyphs, klass);
1579     default:return false;
1580     }
1581   }
1582 
intersectsOT::ClassDef1583   bool intersects (const hb_set_t *glyphs) const
1584   {
1585     switch (u.format) {
1586     case 1: return u.format1.intersects (glyphs);
1587     case 2: return u.format2.intersects (glyphs);
1588     default:return false;
1589     }
1590   }
intersects_classOT::ClassDef1591   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
1592   {
1593     switch (u.format) {
1594     case 1: return u.format1.intersects_class (glyphs, klass);
1595     case 2: return u.format2.intersects_class (glyphs, klass);
1596     default:return false;
1597     }
1598   }
1599 
1600   protected:
1601   union {
1602   HBUINT16		format;		/* Format identifier */
1603   ClassDefFormat1	format1;
1604   ClassDefFormat2	format2;
1605   } u;
1606   public:
1607   DEFINE_SIZE_UNION (2, format);
1608 };
1609 
ClassDef_serialize(hb_serialize_context_t * c,hb_array_t<const GlyphID> glyphs,hb_array_t<const HBUINT16> klasses)1610 static inline void ClassDef_serialize (hb_serialize_context_t *c,
1611 				       hb_array_t<const GlyphID> glyphs,
1612 				       hb_array_t<const HBUINT16> klasses)
1613 { c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); }
1614 
1615 
1616 /*
1617  * Item Variation Store
1618  */
1619 
1620 struct VarRegionAxis
1621 {
evaluateOT::VarRegionAxis1622   float evaluate (int coord) const
1623   {
1624     int start = startCoord, peak = peakCoord, end = endCoord;
1625 
1626     /* TODO Move these to sanitize(). */
1627     if (unlikely (start > peak || peak > end))
1628       return 1.;
1629     if (unlikely (start < 0 && end > 0 && peak != 0))
1630       return 1.;
1631 
1632     if (peak == 0 || coord == peak)
1633       return 1.;
1634 
1635     if (coord <= start || end <= coord)
1636       return 0.;
1637 
1638     /* Interpolate */
1639     if (coord < peak)
1640       return float (coord - start) / (peak - start);
1641     else
1642       return float (end - coord) / (end - peak);
1643   }
1644 
sanitizeOT::VarRegionAxis1645   bool sanitize (hb_sanitize_context_t *c) const
1646   {
1647     TRACE_SANITIZE (this);
1648     return_trace (c->check_struct (this));
1649     /* TODO Handle invalid start/peak/end configs, so we don't
1650      * have to do that at runtime. */
1651   }
1652 
1653   public:
1654   F2DOT14	startCoord;
1655   F2DOT14	peakCoord;
1656   F2DOT14	endCoord;
1657   public:
1658   DEFINE_SIZE_STATIC (6);
1659 };
1660 
1661 struct VarRegionList
1662 {
evaluateOT::VarRegionList1663   float evaluate (unsigned int region_index,
1664 			 const int *coords, unsigned int coord_len) const
1665   {
1666     if (unlikely (region_index >= regionCount))
1667       return 0.;
1668 
1669     const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
1670 
1671     float v = 1.;
1672     unsigned int count = axisCount;
1673     for (unsigned int i = 0; i < count; i++)
1674     {
1675       int coord = i < coord_len ? coords[i] : 0;
1676       float factor = axes[i].evaluate (coord);
1677       if (factor == 0.f)
1678 	return 0.;
1679       v *= factor;
1680     }
1681     return v;
1682   }
1683 
sanitizeOT::VarRegionList1684   bool sanitize (hb_sanitize_context_t *c) const
1685   {
1686     TRACE_SANITIZE (this);
1687     return_trace (c->check_struct (this) &&
1688 		  axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
1689   }
1690 
get_region_countOT::VarRegionList1691   unsigned int get_region_count () const { return regionCount; }
1692 
1693   protected:
1694   HBUINT16	axisCount;
1695   HBUINT16	regionCount;
1696   UnsizedArrayOf<VarRegionAxis>
1697 		axesZ;
1698   public:
1699   DEFINE_SIZE_ARRAY (4, axesZ);
1700 };
1701 
1702 struct VarData
1703 {
get_region_index_countOT::VarData1704   unsigned int get_region_index_count () const
1705   { return regionIndices.len; }
1706 
get_row_sizeOT::VarData1707   unsigned int get_row_size () const
1708   { return shortCount + regionIndices.len; }
1709 
get_sizeOT::VarData1710   unsigned int get_size () const
1711   { return itemCount * get_row_size (); }
1712 
get_deltaOT::VarData1713   float get_delta (unsigned int inner,
1714 			  const int *coords, unsigned int coord_count,
1715 			  const VarRegionList &regions) const
1716   {
1717     if (unlikely (inner >= itemCount))
1718       return 0.;
1719 
1720    unsigned int count = regionIndices.len;
1721    unsigned int scount = shortCount;
1722 
1723    const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
1724    const HBUINT8 *row = bytes + inner * (scount + count);
1725 
1726    float delta = 0.;
1727    unsigned int i = 0;
1728 
1729    const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
1730    for (; i < scount; i++)
1731    {
1732      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
1733      delta += scalar * *scursor++;
1734    }
1735    const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
1736    for (; i < count; i++)
1737    {
1738      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
1739      delta += scalar * *bcursor++;
1740    }
1741 
1742    return delta;
1743   }
1744 
get_scalarsOT::VarData1745   void get_scalars (int *coords, unsigned int coord_count,
1746                     const VarRegionList &regions,
1747                     float *scalars /*OUT */,
1748                     unsigned int num_scalars) const
1749   {
1750     assert (num_scalars == regionIndices.len);
1751    for (unsigned int i = 0; i < num_scalars; i++)
1752    {
1753      scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
1754    }
1755   }
1756 
sanitizeOT::VarData1757   bool sanitize (hb_sanitize_context_t *c) const
1758   {
1759     TRACE_SANITIZE (this);
1760     return_trace (c->check_struct (this) &&
1761 		  regionIndices.sanitize (c) &&
1762 		  shortCount <= regionIndices.len &&
1763 		  c->check_range (&StructAfter<HBUINT8> (regionIndices),
1764 				  itemCount,
1765 				  get_row_size ()));
1766   }
1767 
1768   protected:
1769   HBUINT16		itemCount;
1770   HBUINT16		shortCount;
1771   ArrayOf<HBUINT16>	regionIndices;
1772 /*UnsizedArrayOf<HBUINT8>bytesX;*/
1773   public:
1774   DEFINE_SIZE_ARRAY (6, regionIndices);
1775 };
1776 
1777 struct VariationStore
1778 {
get_deltaOT::VariationStore1779   float get_delta (unsigned int outer, unsigned int inner,
1780 		   const int *coords, unsigned int coord_count) const
1781   {
1782     if (unlikely (outer >= dataSets.len))
1783       return 0.;
1784 
1785     return (this+dataSets[outer]).get_delta (inner,
1786 					     coords, coord_count,
1787 					     this+regions);
1788   }
1789 
get_deltaOT::VariationStore1790   float get_delta (unsigned int index,
1791 		   const int *coords, unsigned int coord_count) const
1792   {
1793     unsigned int outer = index >> 16;
1794     unsigned int inner = index & 0xFFFF;
1795     return get_delta (outer, inner, coords, coord_count);
1796   }
1797 
sanitizeOT::VariationStore1798   bool sanitize (hb_sanitize_context_t *c) const
1799   {
1800     TRACE_SANITIZE (this);
1801     return_trace (c->check_struct (this) &&
1802 		  format == 1 &&
1803 		  regions.sanitize (c, this) &&
1804 		  dataSets.sanitize (c, this));
1805   }
1806 
get_region_index_countOT::VariationStore1807   unsigned int get_region_index_count (unsigned int ivs) const
1808   { return (this+dataSets[ivs]).get_region_index_count (); }
1809 
get_scalarsOT::VariationStore1810   void get_scalars (unsigned int ivs,
1811 		    int *coords, unsigned int coord_count,
1812 		    float *scalars /*OUT*/,
1813 		    unsigned int num_scalars) const
1814   {
1815     (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
1816                                       &scalars[0], num_scalars);
1817   }
1818 
1819   protected:
1820   HBUINT16				format;
1821   LOffsetTo<VarRegionList>		regions;
1822   LOffsetArrayOf<VarData>		dataSets;
1823   public:
1824   DEFINE_SIZE_ARRAY (8, dataSets);
1825 };
1826 
1827 /*
1828  * Feature Variations
1829  */
1830 
1831 struct ConditionFormat1
1832 {
1833   friend struct Condition;
1834 
1835   private:
evaluateOT::ConditionFormat11836   bool evaluate (const int *coords, unsigned int coord_len) const
1837   {
1838     int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
1839     return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
1840   }
1841 
sanitizeOT::ConditionFormat11842   bool sanitize (hb_sanitize_context_t *c) const
1843   {
1844     TRACE_SANITIZE (this);
1845     return_trace (c->check_struct (this));
1846   }
1847 
1848   protected:
1849   HBUINT16	format;		/* Format identifier--format = 1 */
1850   HBUINT16	axisIndex;
1851   F2DOT14	filterRangeMinValue;
1852   F2DOT14	filterRangeMaxValue;
1853   public:
1854   DEFINE_SIZE_STATIC (8);
1855 };
1856 
1857 struct Condition
1858 {
evaluateOT::Condition1859   bool evaluate (const int *coords, unsigned int coord_len) const
1860   {
1861     switch (u.format) {
1862     case 1: return u.format1.evaluate (coords, coord_len);
1863     default:return false;
1864     }
1865   }
1866 
sanitizeOT::Condition1867   bool sanitize (hb_sanitize_context_t *c) const
1868   {
1869     TRACE_SANITIZE (this);
1870     if (!u.format.sanitize (c)) return_trace (false);
1871     switch (u.format) {
1872     case 1: return_trace (u.format1.sanitize (c));
1873     default:return_trace (true);
1874     }
1875   }
1876 
1877   protected:
1878   union {
1879   HBUINT16		format;		/* Format identifier */
1880   ConditionFormat1	format1;
1881   } u;
1882   public:
1883   DEFINE_SIZE_UNION (2, format);
1884 };
1885 
1886 struct ConditionSet
1887 {
evaluateOT::ConditionSet1888   bool evaluate (const int *coords, unsigned int coord_len) const
1889   {
1890     unsigned int count = conditions.len;
1891     for (unsigned int i = 0; i < count; i++)
1892       if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
1893 	return false;
1894     return true;
1895   }
1896 
sanitizeOT::ConditionSet1897   bool sanitize (hb_sanitize_context_t *c) const
1898   {
1899     TRACE_SANITIZE (this);
1900     return_trace (conditions.sanitize (c, this));
1901   }
1902 
1903   protected:
1904   LOffsetArrayOf<Condition>	conditions;
1905   public:
1906   DEFINE_SIZE_ARRAY (2, conditions);
1907 };
1908 
1909 struct FeatureTableSubstitutionRecord
1910 {
1911   friend struct FeatureTableSubstitution;
1912 
sanitizeOT::FeatureTableSubstitutionRecord1913   bool sanitize (hb_sanitize_context_t *c, const void *base) const
1914   {
1915     TRACE_SANITIZE (this);
1916     return_trace (c->check_struct (this) && feature.sanitize (c, base));
1917   }
1918 
1919   protected:
1920   HBUINT16		featureIndex;
1921   LOffsetTo<Feature>	feature;
1922   public:
1923   DEFINE_SIZE_STATIC (6);
1924 };
1925 
1926 struct FeatureTableSubstitution
1927 {
find_substituteOT::FeatureTableSubstitution1928   const Feature *find_substitute (unsigned int feature_index) const
1929   {
1930     unsigned int count = substitutions.len;
1931     for (unsigned int i = 0; i < count; i++)
1932     {
1933       const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
1934       if (record.featureIndex == feature_index)
1935 	return &(this+record.feature);
1936     }
1937     return nullptr;
1938   }
1939 
sanitizeOT::FeatureTableSubstitution1940   bool sanitize (hb_sanitize_context_t *c) const
1941   {
1942     TRACE_SANITIZE (this);
1943     return_trace (version.sanitize (c) &&
1944 		  likely (version.major == 1) &&
1945 		  substitutions.sanitize (c, this));
1946   }
1947 
1948   protected:
1949   FixedVersion<>	version;	/* Version--0x00010000u */
1950   ArrayOf<FeatureTableSubstitutionRecord>
1951 			substitutions;
1952   public:
1953   DEFINE_SIZE_ARRAY (6, substitutions);
1954 };
1955 
1956 struct FeatureVariationRecord
1957 {
1958   friend struct FeatureVariations;
1959 
sanitizeOT::FeatureVariationRecord1960   bool sanitize (hb_sanitize_context_t *c, const void *base) const
1961   {
1962     TRACE_SANITIZE (this);
1963     return_trace (conditions.sanitize (c, base) &&
1964 		  substitutions.sanitize (c, base));
1965   }
1966 
1967   protected:
1968   LOffsetTo<ConditionSet>
1969 			conditions;
1970   LOffsetTo<FeatureTableSubstitution>
1971 			substitutions;
1972   public:
1973   DEFINE_SIZE_STATIC (8);
1974 };
1975 
1976 struct FeatureVariations
1977 {
1978   static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
1979 
find_indexOT::FeatureVariations1980   bool find_index (const int *coords, unsigned int coord_len,
1981 			  unsigned int *index) const
1982   {
1983     unsigned int count = varRecords.len;
1984     for (unsigned int i = 0; i < count; i++)
1985     {
1986       const FeatureVariationRecord &record = varRecords.arrayZ[i];
1987       if ((this+record.conditions).evaluate (coords, coord_len))
1988       {
1989 	*index = i;
1990 	return true;
1991       }
1992     }
1993     *index = NOT_FOUND_INDEX;
1994     return false;
1995   }
1996 
find_substituteOT::FeatureVariations1997   const Feature *find_substitute (unsigned int variations_index,
1998 				  unsigned int feature_index) const
1999   {
2000     const FeatureVariationRecord &record = varRecords[variations_index];
2001     return (this+record.substitutions).find_substitute (feature_index);
2002   }
2003 
copyOT::FeatureVariations2004   FeatureVariations* copy (hb_serialize_context_t *c) const
2005   {
2006     TRACE_SERIALIZE (this);
2007     return_trace (c->embed (*this));
2008   }
2009 
sanitizeOT::FeatureVariations2010   bool sanitize (hb_sanitize_context_t *c) const
2011   {
2012     TRACE_SANITIZE (this);
2013     return_trace (version.sanitize (c) &&
2014 		  likely (version.major == 1) &&
2015 		  varRecords.sanitize (c, this));
2016   }
2017 
2018   protected:
2019   FixedVersion<>	version;	/* Version--0x00010000u */
2020   LArrayOf<FeatureVariationRecord>
2021 			varRecords;
2022   public:
2023   DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
2024 };
2025 
2026 
2027 /*
2028  * Device Tables
2029  */
2030 
2031 struct HintingDevice
2032 {
2033   friend struct Device;
2034 
2035   private:
2036 
get_x_deltaOT::HintingDevice2037   hb_position_t get_x_delta (hb_font_t *font) const
2038   { return get_delta (font->x_ppem, font->x_scale); }
2039 
get_y_deltaOT::HintingDevice2040   hb_position_t get_y_delta (hb_font_t *font) const
2041   { return get_delta (font->y_ppem, font->y_scale); }
2042 
get_sizeOT::HintingDevice2043   unsigned int get_size () const
2044   {
2045     unsigned int f = deltaFormat;
2046     if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
2047     return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
2048   }
2049 
sanitizeOT::HintingDevice2050   bool sanitize (hb_sanitize_context_t *c) const
2051   {
2052     TRACE_SANITIZE (this);
2053     return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
2054   }
2055 
2056   private:
2057 
get_deltaOT::HintingDevice2058   int get_delta (unsigned int ppem, int scale) const
2059   {
2060     if (!ppem) return 0;
2061 
2062     int pixels = get_delta_pixels (ppem);
2063 
2064     if (!pixels) return 0;
2065 
2066     return (int) (pixels * (int64_t) scale / ppem);
2067   }
get_delta_pixelsOT::HintingDevice2068   int get_delta_pixels (unsigned int ppem_size) const
2069   {
2070     unsigned int f = deltaFormat;
2071     if (unlikely (f < 1 || f > 3))
2072       return 0;
2073 
2074     if (ppem_size < startSize || ppem_size > endSize)
2075       return 0;
2076 
2077     unsigned int s = ppem_size - startSize;
2078 
2079     unsigned int byte = deltaValueZ[s >> (4 - f)];
2080     unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
2081     unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
2082 
2083     int delta = bits & mask;
2084 
2085     if ((unsigned int) delta >= ((mask + 1) >> 1))
2086       delta -= mask + 1;
2087 
2088     return delta;
2089   }
2090 
2091   protected:
2092   HBUINT16	startSize;		/* Smallest size to correct--in ppem */
2093   HBUINT16	endSize;		/* Largest size to correct--in ppem */
2094   HBUINT16	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
2095 					 * 1	Signed 2-bit value, 8 values per uint16
2096 					 * 2	Signed 4-bit value, 4 values per uint16
2097 					 * 3	Signed 8-bit value, 2 values per uint16
2098 					 */
2099   UnsizedArrayOf<HBUINT16>
2100 		deltaValueZ;		/* Array of compressed data */
2101   public:
2102   DEFINE_SIZE_ARRAY (6, deltaValueZ);
2103 };
2104 
2105 struct VariationDevice
2106 {
2107   friend struct Device;
2108 
2109   private:
2110 
get_x_deltaOT::VariationDevice2111   hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
2112   { return font->em_scalef_x (get_delta (font, store)); }
2113 
get_y_deltaOT::VariationDevice2114   hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
2115   { return font->em_scalef_y (get_delta (font, store)); }
2116 
sanitizeOT::VariationDevice2117   bool sanitize (hb_sanitize_context_t *c) const
2118   {
2119     TRACE_SANITIZE (this);
2120     return_trace (c->check_struct (this));
2121   }
2122 
2123   private:
2124 
get_deltaOT::VariationDevice2125   float get_delta (hb_font_t *font, const VariationStore &store) const
2126   {
2127     return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
2128   }
2129 
2130   protected:
2131   HBUINT16	outerIndex;
2132   HBUINT16	innerIndex;
2133   HBUINT16	deltaFormat;	/* Format identifier for this table: 0x0x8000 */
2134   public:
2135   DEFINE_SIZE_STATIC (6);
2136 };
2137 
2138 struct DeviceHeader
2139 {
2140   protected:
2141   HBUINT16		reserved1;
2142   HBUINT16		reserved2;
2143   public:
2144   HBUINT16		format;		/* Format identifier */
2145   public:
2146   DEFINE_SIZE_STATIC (6);
2147 };
2148 
2149 struct Device
2150 {
get_x_deltaOT::Device2151   hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
2152   {
2153     switch (u.b.format)
2154     {
2155     case 1: case 2: case 3:
2156       return u.hinting.get_x_delta (font);
2157     case 0x8000:
2158       return u.variation.get_x_delta (font, store);
2159     default:
2160       return 0;
2161     }
2162   }
get_y_deltaOT::Device2163   hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
2164   {
2165     switch (u.b.format)
2166     {
2167     case 1: case 2: case 3:
2168       return u.hinting.get_y_delta (font);
2169     case 0x8000:
2170       return u.variation.get_y_delta (font, store);
2171     default:
2172       return 0;
2173     }
2174   }
2175 
sanitizeOT::Device2176   bool sanitize (hb_sanitize_context_t *c) const
2177   {
2178     TRACE_SANITIZE (this);
2179     if (!u.b.format.sanitize (c)) return_trace (false);
2180     switch (u.b.format) {
2181     case 1: case 2: case 3:
2182       return_trace (u.hinting.sanitize (c));
2183     case 0x8000:
2184       return_trace (u.variation.sanitize (c));
2185     default:
2186       return_trace (true);
2187     }
2188   }
2189 
2190   protected:
2191   union {
2192   DeviceHeader		b;
2193   HintingDevice		hinting;
2194   VariationDevice	variation;
2195   } u;
2196   public:
2197   DEFINE_SIZE_UNION (6, b);
2198 };
2199 
2200 
2201 } /* namespace OT */
2202 
2203 
2204 #endif /* HB_OT_LAYOUT_COMMON_HH */
2205