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