e6018db124352f91464f93a3b95032e10ea6aa22
[platform/upstream/harfbuzz.git] / src / hb-ot-layout-common-private.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_PRIVATE_HH
30 #define HB_OT_LAYOUT_COMMON_PRIVATE_HH
31
32 #include "hb-ot-layout-private.hh"
33 #include "hb-open-type-private.hh"
34 #include "hb-set-private.hh"
35
36
37 namespace OT {
38
39
40 #define NOT_COVERED             ((unsigned int) -1)
41 #define MAX_NESTING_LEVEL       8
42
43
44
45 /*
46  *
47  * OpenType Layout Common Table Formats
48  *
49  */
50
51
52 /*
53  * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
54  */
55
56 template <typename Type>
57 struct Record
58 {
59   inline int cmp (hb_tag_t a) const {
60     return tag.cmp (a);
61   }
62
63   struct sanitize_closure_t {
64     hb_tag_t tag;
65     void *list_base;
66   };
67   inline bool sanitize (hb_sanitize_context_t *c, void *base) {
68     TRACE_SANITIZE (this);
69     const sanitize_closure_t closure = {tag, base};
70     return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
71   }
72
73   Tag           tag;            /* 4-byte Tag identifier */
74   OffsetTo<Type>
75                 offset;         /* Offset from beginning of object holding
76                                  * the Record */
77   public:
78   DEFINE_SIZE_STATIC (6);
79 };
80
81 template <typename Type>
82 struct RecordArrayOf : SortedArrayOf<Record<Type> > {
83   inline const Tag& get_tag (unsigned int i) const
84   {
85     /* We cheat slightly and don't define separate Null objects
86      * for Record types.  Instead, we return the correct Null(Tag)
87      * here. */
88     if (unlikely (i >= this->len)) return Null(Tag);
89     return (*this)[i].tag;
90   }
91   inline unsigned int get_tags (unsigned int start_offset,
92                                 unsigned int *record_count /* IN/OUT */,
93                                 hb_tag_t     *record_tags /* OUT */) const
94   {
95     if (record_count) {
96       const Record<Type> *arr = this->sub_array (start_offset, record_count);
97       unsigned int count = *record_count;
98       for (unsigned int i = 0; i < count; i++)
99         record_tags[i] = arr[i].tag;
100     }
101     return this->len;
102   }
103   inline bool find_index (hb_tag_t tag, unsigned int *index) const
104   {
105     int i = this->search (tag);
106     if (i != -1) {
107         if (index) *index = i;
108         return true;
109     } else {
110       if (index) *index = Index::NOT_FOUND_INDEX;
111       return false;
112     }
113   }
114 };
115
116 template <typename Type>
117 struct RecordListOf : RecordArrayOf<Type>
118 {
119   inline const Type& operator [] (unsigned int i) const
120   { return this+RecordArrayOf<Type>::operator [](i).offset; }
121
122   inline bool sanitize (hb_sanitize_context_t *c) {
123     TRACE_SANITIZE (this);
124     return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
125   }
126 };
127
128
129 struct RangeRecord
130 {
131   inline int cmp (hb_codepoint_t g) const {
132     hb_codepoint_t a = start, b = end;
133     return g < a ? -1 : g <= b ? 0 : +1 ;
134   }
135
136   inline bool sanitize (hb_sanitize_context_t *c) {
137     TRACE_SANITIZE (this);
138     return TRACE_RETURN (c->check_struct (this));
139   }
140
141   inline bool intersects (const hb_set_t *glyphs) const {
142     return glyphs->intersects (start, end);
143   }
144
145   template <typename set_t>
146   inline void add_coverage (set_t *glyphs) const {
147     glyphs->add_range (start, end);
148   }
149
150   GlyphID       start;          /* First GlyphID in the range */
151   GlyphID       end;            /* Last GlyphID in the range */
152   USHORT        value;          /* Value */
153   public:
154   DEFINE_SIZE_STATIC (6);
155 };
156 DEFINE_NULL_DATA (RangeRecord, "\000\001");
157
158
159 struct IndexArray : ArrayOf<Index>
160 {
161   inline unsigned int get_indexes (unsigned int start_offset,
162                                    unsigned int *_count /* IN/OUT */,
163                                    unsigned int *_indexes /* OUT */) const
164   {
165     if (_count) {
166       const USHORT *arr = this->sub_array (start_offset, _count);
167       unsigned int count = *_count;
168       for (unsigned int i = 0; i < count; i++)
169         _indexes[i] = arr[i];
170     }
171     return this->len;
172   }
173 };
174
175
176 struct Script;
177 struct LangSys;
178 struct Feature;
179
180
181 struct LangSys
182 {
183   inline unsigned int get_feature_count (void) const
184   { return featureIndex.len; }
185   inline hb_tag_t get_feature_index (unsigned int i) const
186   { return featureIndex[i]; }
187   inline unsigned int get_feature_indexes (unsigned int start_offset,
188                                            unsigned int *feature_count /* IN/OUT */,
189                                            unsigned int *feature_indexes /* OUT */) const
190   { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
191
192   inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
193   inline unsigned int get_required_feature_index (void) const
194   {
195     if (reqFeatureIndex == 0xffff)
196       return Index::NOT_FOUND_INDEX;
197    return reqFeatureIndex;;
198   }
199
200   inline bool sanitize (hb_sanitize_context_t *c,
201                         const Record<LangSys>::sanitize_closure_t * = NULL) {
202     TRACE_SANITIZE (this);
203     return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
204   }
205
206   Offset        lookupOrder;    /* = Null (reserved for an offset to a
207                                  * reordering table) */
208   USHORT        reqFeatureIndex;/* Index of a feature required for this
209                                  * language system--if no required features
210                                  * = 0xFFFF */
211   IndexArray    featureIndex;   /* Array of indices into the FeatureList */
212   public:
213   DEFINE_SIZE_ARRAY (6, featureIndex);
214 };
215 DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
216
217
218 struct Script
219 {
220   inline unsigned int get_lang_sys_count (void) const
221   { return langSys.len; }
222   inline const Tag& get_lang_sys_tag (unsigned int i) const
223   { return langSys.get_tag (i); }
224   inline unsigned int get_lang_sys_tags (unsigned int start_offset,
225                                          unsigned int *lang_sys_count /* IN/OUT */,
226                                          hb_tag_t     *lang_sys_tags /* OUT */) const
227   { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
228   inline const LangSys& get_lang_sys (unsigned int i) const
229   {
230     if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
231     return this+langSys[i].offset;
232   }
233   inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
234   { return langSys.find_index (tag, index); }
235
236   inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
237   inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
238
239   inline bool sanitize (hb_sanitize_context_t *c,
240                         const Record<Script>::sanitize_closure_t * = NULL) {
241     TRACE_SANITIZE (this);
242     return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
243   }
244
245   protected:
246   OffsetTo<LangSys>
247                 defaultLangSys; /* Offset to DefaultLangSys table--from
248                                  * beginning of Script table--may be Null */
249   RecordArrayOf<LangSys>
250                 langSys;        /* Array of LangSysRecords--listed
251                                  * alphabetically by LangSysTag */
252   public:
253   DEFINE_SIZE_ARRAY (4, langSys);
254 };
255
256 typedef RecordListOf<Script> ScriptList;
257
258
259 /* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
260 struct FeatureParamsSize
261 {
262   inline bool sanitize (hb_sanitize_context_t *c) {
263     TRACE_SANITIZE (this);
264     if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
265
266     /* This subtable has some "history", if you will.  Some earlier versions of
267      * Adobe tools calculated the offset of the FeatureParams sutable from the
268      * beginning of the FeatureList table!  Now, that is dealt with in the
269      * Feature implementation.  But we still need to be able to tell junk from
270      * real data.  Note: We don't check that the nameID actually exists.
271      *
272      * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
273      *
274      * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
275      * coming out soon, and that the makeotf program will build a font with a
276      * 'size' feature that is correct by the specification.
277      *
278      * The specification for this feature tag is in the "OpenType Layout Tag
279      * Registry". You can see a copy of this at:
280      * http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
281      *
282      * Here is one set of rules to determine if the 'size' feature is built
283      * correctly, or as by the older versions of MakeOTF. You may be able to do
284      * better.
285      *
286      * Assume that the offset to the size feature is according to specification,
287      * and make the following value checks. If it fails, assume the the size
288      * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
289      * If this fails, reject the 'size' feature. The older makeOTF's calculated the
290      * offset from the beginning of the FeatureList table, rather than from the
291      * beginning of the 'size' Feature table.
292      *
293      * If "design size" == 0:
294      *     fails check
295      *
296      * Else if ("subfamily identifier" == 0 and
297      *     "range start" == 0 and
298      *     "range end" == 0 and
299      *     "range start" == 0 and
300      *     "menu name ID" == 0)
301      *     passes check: this is the format used when there is a design size
302      * specified, but there is no recommended size range.
303      *
304      * Else if ("design size" <  "range start" or
305      *     "design size" >   "range end" or
306      *     "range end" <= "range start" or
307      *     "menu name ID"  < 256 or
308      *     "menu name ID"  > 32767 or
309      *     menu name ID is not a name ID which is actually in the name table)
310      *     fails test
311      * Else
312      *     passes test.
313      */
314
315     if (!designSize)
316       return TRACE_RETURN (false);
317     else if (subfamilyID == 0 &&
318              subfamilyNameID == 0 &&
319              rangeStart == 0 &&
320              rangeEnd == 0)
321       return TRACE_RETURN (true);
322     else if (designSize < rangeStart ||
323              designSize > rangeEnd ||
324              subfamilyNameID < 256 ||
325              subfamilyNameID > 32767)
326       return TRACE_RETURN (false);
327     else
328       return TRACE_RETURN (true);
329   }
330
331   USHORT        designSize;     /* Represents the design size in 720/inch
332                                  * units (decipoints).  The design size entry
333                                  * must be non-zero.  When there is a design
334                                  * size but no recommended size range, the
335                                  * rest of the array will consist of zeros. */
336   USHORT        subfamilyID;    /* Has no independent meaning, but serves
337                                  * as an identifier that associates fonts
338                                  * in a subfamily. All fonts which share a
339                                  * Preferred or Font Family name and which
340                                  * differ only by size range shall have the
341                                  * same subfamily value, and no fonts which
342                                  * differ in weight or style shall have the
343                                  * same subfamily value. If this value is
344                                  * zero, the remaining fields in the array
345                                  * will be ignored. */
346   USHORT        subfamilyNameID;/* If the preceding value is non-zero, this
347                                  * value must be set in the range 256 - 32767
348                                  * (inclusive). It records the value of a
349                                  * field in the name table, which must
350                                  * contain English-language strings encoded
351                                  * in Windows Unicode and Macintosh Roman,
352                                  * and may contain additional strings
353                                  * localized to other scripts and languages.
354                                  * Each of these strings is the name an
355                                  * application should use, in combination
356                                  * with the family name, to represent the
357                                  * subfamily in a menu.  Applications will
358                                  * choose the appropriate version based on
359                                  * their selection criteria. */
360   USHORT        rangeStart;     /* Large end of the recommended usage range
361                                  * (inclusive), stored in 720/inch units
362                                  * (decipoints). */
363   USHORT        rangeEnd;       /* Small end of the recommended usage range
364                                    (exclusive), stored in 720/inch units
365                                  * (decipoints). */
366   public:
367   DEFINE_SIZE_STATIC (10);
368 };
369
370 /* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
371 struct FeatureParamsStylisticSet
372 {
373   inline bool sanitize (hb_sanitize_context_t *c) {
374     TRACE_SANITIZE (this);
375     /* Right now minorVersion is at zero.  Which means, any table supports
376      * the uiNameID field. */
377     return TRACE_RETURN (c->check_struct (this));
378   }
379
380   USHORT        minorVersion;   /* (set to 0): This corresponds to a “minor”
381                                  * version number. Additional data may be
382                                  * added to the end of this Feature Parameters
383                                  * table in the future. */
384
385   USHORT        uiNameID;       /* The 'name' table name ID that specifies a
386                                  * string (or strings, for multiple languages)
387                                  * for a user-interface label for this
388                                  * feature.  The values of uiLabelNameId and
389                                  * sampleTextNameId are expected to be in the
390                                  * font-specific name ID range (256-32767),
391                                  * though that is not a requirement in this
392                                  * Feature Parameters specification. The
393                                  * user-interface label for the feature can
394                                  * be provided in multiple languages. An
395                                  * English string should be included as a
396                                  * fallback. The string should be kept to a
397                                  * minimal length to fit comfortably with
398                                  * different application interfaces. */
399   public:
400   DEFINE_SIZE_STATIC (4);
401 };
402
403 struct FeatureParamsCharacterVariants
404 {
405   inline bool sanitize (hb_sanitize_context_t *c) {
406     TRACE_SANITIZE (this);
407     return TRACE_RETURN (c->check_struct (this) &&
408                          characters.sanitize (c));
409   }
410
411   USHORT        format;                 /* Format number is set to 0. */
412   USHORT        featUILableNameID;      /* The ‘name’ table name ID that
413                                          * specifies a string (or strings,
414                                          * for multiple languages) for a
415                                          * user-interface label for this
416                                          * feature. (May be NULL.) */
417   USHORT        featUITooltipTextNameID;/* The ‘name’ table name ID that
418                                          * specifies a string (or strings,
419                                          * for multiple languages) that an
420                                          * application can use for tooltip
421                                          * text for this feature. (May be
422                                          * NULL.) */
423   USHORT        sampleTextNameID;       /* The ‘name’ table name ID that
424                                          * specifies sample text that
425                                          * illustrates the effect of this
426                                          * feature. (May be NULL.) */
427   USHORT        numNamedParameters;     /* Number of named parameters. (May
428                                          * be zero.) */
429   USHORT        firstParamUILabelNameID;/* The first ‘name’ table name ID
430                                          * used to specify strings for
431                                          * user-interface labels for the
432                                          * feature parameters. (Must be zero
433                                          * if numParameters is zero.) */
434   ArrayOf<UINT24>
435                 characters;             /* Array of the Unicode Scalar Value
436                                          * of the characters for which this
437                                          * feature provides glyph variants.
438                                          * (May be zero.) */
439   public:
440   DEFINE_SIZE_ARRAY (14, characters);
441 };
442
443 struct FeatureParams
444 {
445   inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) {
446     TRACE_SANITIZE (this);
447     if (tag == HB_TAG ('s','i','z','e'))
448       return TRACE_RETURN (u.size.sanitize (c));
449     if ((tag & 0xFFFF0000) == HB_TAG ('s','s','\0','\0')) /* ssXX */
450       return TRACE_RETURN (u.stylisticSet.sanitize (c));
451     if ((tag & 0xFFFF0000) == HB_TAG ('c','v','\0','\0')) /* cvXX */
452       return TRACE_RETURN (u.characterVariants.sanitize (c));
453     return TRACE_RETURN (true);
454   }
455
456   inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
457   {
458     if (tag == HB_TAG ('s','i','z','e'))
459       return u.size;
460     return Null(FeatureParamsSize);
461   }
462
463   private:
464   union {
465   FeatureParamsSize                     size;
466   FeatureParamsStylisticSet             stylisticSet;
467   FeatureParamsCharacterVariants        characterVariants;
468   } u;
469   DEFINE_SIZE_STATIC (17);
470 };
471
472 struct Feature
473 {
474   inline unsigned int get_lookup_count (void) const
475   { return lookupIndex.len; }
476   inline hb_tag_t get_lookup_index (unsigned int i) const
477   { return lookupIndex[i]; }
478   inline unsigned int get_lookup_indexes (unsigned int start_index,
479                                           unsigned int *lookup_count /* IN/OUT */,
480                                           unsigned int *lookup_tags /* OUT */) const
481   { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
482
483   inline const FeatureParams &get_feature_params (void) const
484   { return this+featureParams; }
485
486   inline bool sanitize (hb_sanitize_context_t *c,
487                         const Record<Feature>::sanitize_closure_t *closure) {
488     TRACE_SANITIZE (this);
489     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
490       return TRACE_RETURN (false);
491
492     /* Some earlier versions of Adobe tools calculated the offset of the
493      * FeatureParams subtable from the beginning of the FeatureList table!
494      *
495      * If sanitizing "failed" for the FeatureParams subtable, try it with the
496      * alternative location.  We would know sanitize "failed" if old value
497      * of the offset was non-zero, but it's zeroed now.
498      *
499      * Only do this for the 'size' feature, since at the time of the faulty
500      * Adobe tools, only the 'size' feature had FeatureParams defined.
501      */
502
503     Offset orig_offset = featureParams;
504     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
505       return TRACE_RETURN (false);
506
507     if (likely (!orig_offset))
508       return TRACE_RETURN (true);
509
510     if (featureParams == 0 && closure &&
511         closure->tag == HB_TAG ('s','i','z','e') &&
512         closure->list_base && closure->list_base < this)
513     {
514       unsigned int new_offset_int = (unsigned int) orig_offset -
515                                     ((char *) this - (char *) closure->list_base);
516
517       Offset new_offset;
518       /* Check that it did not overflow. */
519       new_offset.set (new_offset_int);
520       if (new_offset == new_offset_int &&
521           featureParams.try_set (c, new_offset) &&
522           !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
523         return TRACE_RETURN (false);
524     }
525
526     return TRACE_RETURN (true);
527   }
528
529   OffsetTo<FeatureParams>
530                  featureParams; /* Offset to Feature Parameters table (if one
531                                  * has been defined for the feature), relative
532                                  * to the beginning of the Feature Table; = Null
533                                  * if not required */
534   IndexArray     lookupIndex;   /* Array of LookupList indices */
535   public:
536   DEFINE_SIZE_ARRAY (4, lookupIndex);
537 };
538
539 typedef RecordListOf<Feature> FeatureList;
540
541
542 struct LookupFlag : USHORT
543 {
544   enum Flags {
545     RightToLeft         = 0x0001u,
546     IgnoreBaseGlyphs    = 0x0002u,
547     IgnoreLigatures     = 0x0004u,
548     IgnoreMarks         = 0x0008u,
549     IgnoreFlags         = 0x000Eu,
550     UseMarkFilteringSet = 0x0010u,
551     Reserved            = 0x00E0u,
552     MarkAttachmentType  = 0xFF00u
553   };
554   public:
555   DEFINE_SIZE_STATIC (2);
556 };
557
558 struct Lookup
559 {
560   inline unsigned int get_subtable_count (void) const { return subTable.len; }
561
562   inline unsigned int get_type (void) const { return lookupType; }
563
564   /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
565    * higher 16-bit is mark-filtering-set if the lookup uses one.
566    * Not to be confused with glyph_props which is very similar. */
567   inline uint32_t get_props (void) const
568   {
569     unsigned int flag = lookupFlag;
570     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
571     {
572       const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
573       flag += (markFilteringSet << 16);
574     }
575     return flag;
576   }
577
578   inline bool serialize (hb_serialize_context_t *c,
579                          unsigned int lookup_type,
580                          uint32_t lookup_props,
581                          unsigned int num_subtables)
582   {
583     TRACE_SERIALIZE (this);
584     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
585     lookupType.set (lookup_type);
586     lookupFlag.set (lookup_props & 0xFFFF);
587     if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
588     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
589     {
590       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
591       markFilteringSet.set (lookup_props >> 16);
592     }
593     return TRACE_RETURN (true);
594   }
595
596   inline bool sanitize (hb_sanitize_context_t *c) {
597     TRACE_SANITIZE (this);
598     /* Real sanitize of the subtables is done by GSUB/GPOS/... */
599     if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
600     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
601     {
602       USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
603       if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
604     }
605     return TRACE_RETURN (true);
606   }
607
608   USHORT        lookupType;             /* Different enumerations for GSUB and GPOS */
609   USHORT        lookupFlag;             /* Lookup qualifiers */
610   ArrayOf<Offset>
611                 subTable;               /* Array of SubTables */
612   USHORT        markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
613                                          * structure. This field is only present if bit
614                                          * UseMarkFilteringSet of lookup flags is set. */
615   public:
616   DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
617 };
618
619 typedef OffsetListOf<Lookup> LookupList;
620
621
622 /*
623  * Coverage Table
624  */
625
626 struct CoverageFormat1
627 {
628   friend struct Coverage;
629
630   private:
631   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
632   {
633     int i = glyphArray.search (glyph_id);
634     ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
635     return i;
636   }
637
638   inline bool serialize (hb_serialize_context_t *c,
639                          Supplier<GlyphID> &glyphs,
640                          unsigned int num_glyphs)
641   {
642     TRACE_SERIALIZE (this);
643     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
644     glyphArray.len.set (num_glyphs);
645     if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
646     for (unsigned int i = 0; i < num_glyphs; i++)
647       glyphArray[i] = glyphs[i];
648     glyphs.advance (num_glyphs);
649     return TRACE_RETURN (true);
650   }
651
652   inline bool sanitize (hb_sanitize_context_t *c) {
653     TRACE_SANITIZE (this);
654     return TRACE_RETURN (glyphArray.sanitize (c));
655   }
656
657   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
658     return glyphs->has (glyphArray[index]);
659   }
660
661   template <typename set_t>
662   inline void add_coverage (set_t *glyphs) const {
663     unsigned int count = glyphArray.len;
664     for (unsigned int i = 0; i < count; i++)
665       glyphs->add (glyphArray[i]);
666   }
667
668   public:
669   /* Older compilers need this to be public. */
670   struct Iter {
671     inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
672     inline bool more (void) { return i < c->glyphArray.len; }
673     inline void next (void) { i++; }
674     inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
675     inline uint16_t get_coverage (void) { return i; }
676
677     private:
678     const struct CoverageFormat1 *c;
679     unsigned int i;
680   };
681   private:
682
683   protected:
684   USHORT        coverageFormat; /* Format identifier--format = 1 */
685   SortedArrayOf<GlyphID>
686                 glyphArray;     /* Array of GlyphIDs--in numerical order */
687   public:
688   DEFINE_SIZE_ARRAY (4, glyphArray);
689 };
690
691 struct CoverageFormat2
692 {
693   friend struct Coverage;
694
695   private:
696   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
697   {
698     int i = rangeRecord.search (glyph_id);
699     if (i != -1) {
700       const RangeRecord &range = rangeRecord[i];
701       return (unsigned int) range.value + (glyph_id - range.start);
702     }
703     return NOT_COVERED;
704   }
705
706   inline bool serialize (hb_serialize_context_t *c,
707                          Supplier<GlyphID> &glyphs,
708                          unsigned int num_glyphs)
709   {
710     TRACE_SERIALIZE (this);
711     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
712
713     if (unlikely (!num_glyphs)) return TRACE_RETURN (true);
714
715     unsigned int num_ranges = 1;
716     for (unsigned int i = 1; i < num_glyphs; i++)
717       if (glyphs[i - 1] + 1 != glyphs[i])
718         num_ranges++;
719     rangeRecord.len.set (num_ranges);
720     if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false);
721
722     unsigned int range = 0;
723     rangeRecord[range].start = glyphs[0];
724     rangeRecord[range].value.set (0);
725     for (unsigned int i = 1; i < num_glyphs; i++)
726       if (glyphs[i - 1] + 1 != glyphs[i]) {
727         range++;
728         rangeRecord[range].start = glyphs[i];
729         rangeRecord[range].value.set (i);
730         rangeRecord[range].end = glyphs[i];
731       } else {
732         rangeRecord[range].end = glyphs[i];
733       }
734     glyphs.advance (num_glyphs);
735     return TRACE_RETURN (true);
736   }
737
738   inline bool sanitize (hb_sanitize_context_t *c) {
739     TRACE_SANITIZE (this);
740     return TRACE_RETURN (rangeRecord.sanitize (c));
741   }
742
743   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
744     unsigned int i;
745     unsigned int count = rangeRecord.len;
746     for (i = 0; i < count; i++) {
747       const RangeRecord &range = rangeRecord[i];
748       if (range.value <= index &&
749           index < (unsigned int) range.value + (range.end - range.start) &&
750           range.intersects (glyphs))
751         return true;
752       else if (index < range.value)
753         return false;
754     }
755     return false;
756   }
757
758   template <typename set_t>
759   inline void add_coverage (set_t *glyphs) const {
760     unsigned int count = rangeRecord.len;
761     for (unsigned int i = 0; i < count; i++)
762       rangeRecord[i].add_coverage (glyphs);
763   }
764
765   public:
766   /* Older compilers need this to be public. */
767   struct Iter {
768     inline void init (const CoverageFormat2 &c_) {
769       c = &c_;
770       coverage = 0;
771       i = 0;
772       j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
773     }
774     inline bool more (void) { return i < c->rangeRecord.len; }
775     inline void next (void) {
776       coverage++;
777       if (j == c->rangeRecord[i].end) {
778         i++;
779         if (more ())
780           j = c->rangeRecord[i].start;
781         return;
782       }
783       j++;
784     }
785     inline uint16_t get_glyph (void) { return j; }
786     inline uint16_t get_coverage (void) { return coverage; }
787
788     private:
789     const struct CoverageFormat2 *c;
790     unsigned int i, j, coverage;
791   };
792   private:
793
794   protected:
795   USHORT        coverageFormat; /* Format identifier--format = 2 */
796   SortedArrayOf<RangeRecord>
797                 rangeRecord;    /* Array of glyph ranges--ordered by
798                                  * Start GlyphID. rangeCount entries
799                                  * long */
800   public:
801   DEFINE_SIZE_ARRAY (4, rangeRecord);
802 };
803
804 struct Coverage
805 {
806   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
807   {
808     switch (u.format) {
809     case 1: return u.format1.get_coverage(glyph_id);
810     case 2: return u.format2.get_coverage(glyph_id);
811     default:return NOT_COVERED;
812     }
813   }
814
815   inline bool serialize (hb_serialize_context_t *c,
816                          Supplier<GlyphID> &glyphs,
817                          unsigned int num_glyphs)
818   {
819     TRACE_SERIALIZE (this);
820     if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
821     unsigned int num_ranges = 1;
822     for (unsigned int i = 1; i < num_glyphs; i++)
823       if (glyphs[i - 1] + 1 != glyphs[i])
824         num_ranges++;
825     u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
826     switch (u.format) {
827     case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
828     case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
829     default:return TRACE_RETURN (false);
830     }
831   }
832
833   inline bool sanitize (hb_sanitize_context_t *c) {
834     TRACE_SANITIZE (this);
835     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
836     switch (u.format) {
837     case 1: return TRACE_RETURN (u.format1.sanitize (c));
838     case 2: return TRACE_RETURN (u.format2.sanitize (c));
839     default:return TRACE_RETURN (true);
840     }
841   }
842
843   inline bool intersects (const hb_set_t *glyphs) const {
844     /* TODO speed this up */
845     Coverage::Iter iter;
846     for (iter.init (*this); iter.more (); iter.next ()) {
847       if (glyphs->has (iter.get_glyph ()))
848         return true;
849     }
850     return false;
851   }
852
853   inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
854     switch (u.format) {
855     case 1: return u.format1.intersects_coverage (glyphs, index);
856     case 2: return u.format2.intersects_coverage (glyphs, index);
857     default:return false;
858     }
859   }
860
861   template <typename set_t>
862   inline void add_coverage (set_t *glyphs) const {
863     switch (u.format) {
864     case 1: u.format1.add_coverage (glyphs); break;
865     case 2: u.format2.add_coverage (glyphs); break;
866     default:                                 break;
867     }
868   }
869
870   struct Iter {
871     Iter (void) : format (0) {};
872     inline void init (const Coverage &c_) {
873       format = c_.u.format;
874       switch (format) {
875       case 1: return u.format1.init (c_.u.format1);
876       case 2: return u.format2.init (c_.u.format2);
877       default:return;
878       }
879     }
880     inline bool more (void) {
881       switch (format) {
882       case 1: return u.format1.more ();
883       case 2: return u.format2.more ();
884       default:return true;
885       }
886     }
887     inline void next (void) {
888       switch (format) {
889       case 1: u.format1.next (); break;
890       case 2: u.format2.next (); break;
891       default:                   break;
892       }
893     }
894     inline uint16_t get_glyph (void) {
895       switch (format) {
896       case 1: return u.format1.get_glyph ();
897       case 2: return u.format2.get_glyph ();
898       default:return true;
899       }
900     }
901     inline uint16_t get_coverage (void) {
902       switch (format) {
903       case 1: return u.format1.get_coverage ();
904       case 2: return u.format2.get_coverage ();
905       default:return true;
906       }
907     }
908
909     private:
910     unsigned int format;
911     union {
912     CoverageFormat1::Iter       format1;
913     CoverageFormat2::Iter       format2;
914     } u;
915   };
916
917   protected:
918   union {
919   USHORT                format;         /* Format identifier */
920   CoverageFormat1       format1;
921   CoverageFormat2       format2;
922   } u;
923   public:
924   DEFINE_SIZE_UNION (2, format);
925 };
926
927
928 /*
929  * Class Definition Table
930  */
931
932 struct ClassDefFormat1
933 {
934   friend struct ClassDef;
935
936   private:
937   inline unsigned int get_class (hb_codepoint_t glyph_id) const
938   {
939     if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len))
940       return classValue[glyph_id - startGlyph];
941     return 0;
942   }
943
944   inline bool sanitize (hb_sanitize_context_t *c) {
945     TRACE_SANITIZE (this);
946     return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
947   }
948
949   template <typename set_t>
950   inline void add_class (set_t *glyphs, unsigned int klass) const {
951     unsigned int count = classValue.len;
952     for (unsigned int i = 0; i < count; i++)
953       if (classValue[i] == klass)
954         glyphs->add (startGlyph + i);
955   }
956
957   inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
958     unsigned int count = classValue.len;
959     for (unsigned int i = 0; i < count; i++)
960       if (classValue[i] == klass && glyphs->has (startGlyph + i))
961         return true;
962     return false;
963   }
964
965   protected:
966   USHORT        classFormat;            /* Format identifier--format = 1 */
967   GlyphID       startGlyph;             /* First GlyphID of the classValueArray */
968   ArrayOf<USHORT>
969                 classValue;             /* Array of Class Values--one per GlyphID */
970   public:
971   DEFINE_SIZE_ARRAY (6, classValue);
972 };
973
974 struct ClassDefFormat2
975 {
976   friend struct ClassDef;
977
978   private:
979   inline unsigned int get_class (hb_codepoint_t glyph_id) const
980   {
981     int i = rangeRecord.search (glyph_id);
982     if (i != -1)
983       return rangeRecord[i].value;
984     return 0;
985   }
986
987   inline bool sanitize (hb_sanitize_context_t *c) {
988     TRACE_SANITIZE (this);
989     return TRACE_RETURN (rangeRecord.sanitize (c));
990   }
991
992   template <typename set_t>
993   inline void add_class (set_t *glyphs, unsigned int klass) const {
994     unsigned int count = rangeRecord.len;
995     for (unsigned int i = 0; i < count; i++)
996       if (rangeRecord[i].value == klass)
997         rangeRecord[i].add_coverage (glyphs);
998   }
999
1000   inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
1001     unsigned int count = rangeRecord.len;
1002     for (unsigned int i = 0; i < count; i++)
1003       if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
1004         return true;
1005     return false;
1006   }
1007
1008   protected:
1009   USHORT        classFormat;    /* Format identifier--format = 2 */
1010   SortedArrayOf<RangeRecord>
1011                 rangeRecord;    /* Array of glyph ranges--ordered by
1012                                  * Start GlyphID */
1013   public:
1014   DEFINE_SIZE_ARRAY (4, rangeRecord);
1015 };
1016
1017 struct ClassDef
1018 {
1019   inline unsigned int get_class (hb_codepoint_t glyph_id) const
1020   {
1021     switch (u.format) {
1022     case 1: return u.format1.get_class(glyph_id);
1023     case 2: return u.format2.get_class(glyph_id);
1024     default:return 0;
1025     }
1026   }
1027
1028   inline bool sanitize (hb_sanitize_context_t *c) {
1029     TRACE_SANITIZE (this);
1030     if (!u.format.sanitize (c)) return TRACE_RETURN (false);
1031     switch (u.format) {
1032     case 1: return TRACE_RETURN (u.format1.sanitize (c));
1033     case 2: return TRACE_RETURN (u.format2.sanitize (c));
1034     default:return TRACE_RETURN (true);
1035     }
1036   }
1037
1038   inline void add_class (hb_set_t *glyphs, unsigned int klass) const {
1039     switch (u.format) {
1040     case 1: u.format1.add_class (glyphs, klass); return;
1041     case 2: u.format2.add_class (glyphs, klass); return;
1042     default:return;
1043     }
1044   }
1045
1046   inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
1047     switch (u.format) {
1048     case 1: return u.format1.intersects_class (glyphs, klass);
1049     case 2: return u.format2.intersects_class (glyphs, klass);
1050     default:return false;
1051     }
1052   }
1053
1054   protected:
1055   union {
1056   USHORT                format;         /* Format identifier */
1057   ClassDefFormat1       format1;
1058   ClassDefFormat2       format2;
1059   } u;
1060   public:
1061   DEFINE_SIZE_UNION (2, format);
1062 };
1063
1064
1065 /*
1066  * Device Tables
1067  */
1068
1069 struct Device
1070 {
1071
1072   inline hb_position_t get_x_delta (hb_font_t *font) const
1073   { return get_delta (font->x_ppem, font->x_scale); }
1074
1075   inline hb_position_t get_y_delta (hb_font_t *font) const
1076   { return get_delta (font->y_ppem, font->y_scale); }
1077
1078   inline int get_delta (unsigned int ppem, int scale) const
1079   {
1080     if (!ppem) return 0;
1081
1082     int pixels = get_delta_pixels (ppem);
1083
1084     if (!pixels) return 0;
1085
1086     return pixels * (int64_t) scale / ppem;
1087   }
1088
1089
1090   inline int get_delta_pixels (unsigned int ppem_size) const
1091   {
1092     unsigned int f = deltaFormat;
1093     if (unlikely (f < 1 || f > 3))
1094       return 0;
1095
1096     if (ppem_size < startSize || ppem_size > endSize)
1097       return 0;
1098
1099     unsigned int s = ppem_size - startSize;
1100
1101     unsigned int byte = deltaValue[s >> (4 - f)];
1102     unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
1103     unsigned int mask = (0xFFFF >> (16 - (1 << f)));
1104
1105     int delta = bits & mask;
1106
1107     if ((unsigned int) delta >= ((mask + 1) >> 1))
1108       delta -= mask + 1;
1109
1110     return delta;
1111   }
1112
1113   inline unsigned int get_size (void) const
1114   {
1115     unsigned int f = deltaFormat;
1116     if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
1117     return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
1118   }
1119
1120   inline bool sanitize (hb_sanitize_context_t *c) {
1121     TRACE_SANITIZE (this);
1122     return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
1123   }
1124
1125   protected:
1126   USHORT        startSize;              /* Smallest size to correct--in ppem */
1127   USHORT        endSize;                /* Largest size to correct--in ppem */
1128   USHORT        deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
1129                                          * 1    Signed 2-bit value, 8 values per uint16
1130                                          * 2    Signed 4-bit value, 4 values per uint16
1131                                          * 3    Signed 8-bit value, 2 values per uint16
1132                                          */
1133   USHORT        deltaValue[VAR];        /* Array of compressed data */
1134   public:
1135   DEFINE_SIZE_ARRAY (6, deltaValue);
1136 };
1137
1138
1139 } /* namespace OT */
1140
1141
1142 #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */