Home | History | Annotate | Download | only in src
      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 (at) 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 */
   1143