gfx/harfbuzz/src/hb-ot-layout-common-private.hh

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/harfbuzz/src/hb-ot-layout-common-private.hh	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1172 @@
     1.4 +/*
     1.5 + * Copyright © 2007,2008,2009  Red Hat, Inc.
     1.6 + * Copyright © 2010,2012  Google, Inc.
     1.7 + *
     1.8 + *  This is part of HarfBuzz, a text shaping library.
     1.9 + *
    1.10 + * Permission is hereby granted, without written agreement and without
    1.11 + * license or royalty fees, to use, copy, modify, and distribute this
    1.12 + * software and its documentation for any purpose, provided that the
    1.13 + * above copyright notice and the following two paragraphs appear in
    1.14 + * all copies of this software.
    1.15 + *
    1.16 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    1.17 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    1.18 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    1.19 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    1.20 + * DAMAGE.
    1.21 + *
    1.22 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    1.23 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    1.24 + * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    1.25 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    1.26 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    1.27 + *
    1.28 + * Red Hat Author(s): Behdad Esfahbod
    1.29 + * Google Author(s): Behdad Esfahbod
    1.30 + */
    1.31 +
    1.32 +#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
    1.33 +#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
    1.34 +
    1.35 +#include "hb-ot-layout-private.hh"
    1.36 +#include "hb-open-type-private.hh"
    1.37 +#include "hb-set-private.hh"
    1.38 +
    1.39 +
    1.40 +namespace OT {
    1.41 +
    1.42 +
    1.43 +#define NOT_COVERED		((unsigned int) -1)
    1.44 +#define MAX_NESTING_LEVEL	8
    1.45 +#define MAX_CONTEXT_LENGTH	64
    1.46 +
    1.47 +
    1.48 +
    1.49 +/*
    1.50 + *
    1.51 + * OpenType Layout Common Table Formats
    1.52 + *
    1.53 + */
    1.54 +
    1.55 +
    1.56 +/*
    1.57 + * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
    1.58 + */
    1.59 +
    1.60 +template <typename Type>
    1.61 +struct Record
    1.62 +{
    1.63 +  inline int cmp (hb_tag_t a) const {
    1.64 +    return tag.cmp (a);
    1.65 +  }
    1.66 +
    1.67 +  struct sanitize_closure_t {
    1.68 +    hb_tag_t tag;
    1.69 +    void *list_base;
    1.70 +  };
    1.71 +  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
    1.72 +    TRACE_SANITIZE (this);
    1.73 +    const sanitize_closure_t closure = {tag, base};
    1.74 +    return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
    1.75 +  }
    1.76 +
    1.77 +  Tag		tag;		/* 4-byte Tag identifier */
    1.78 +  OffsetTo<Type>
    1.79 +		offset;		/* Offset from beginning of object holding
    1.80 +				 * the Record */
    1.81 +  public:
    1.82 +  DEFINE_SIZE_STATIC (6);
    1.83 +};
    1.84 +
    1.85 +template <typename Type>
    1.86 +struct RecordArrayOf : SortedArrayOf<Record<Type> > {
    1.87 +  inline const Tag& get_tag (unsigned int i) const
    1.88 +  {
    1.89 +    /* We cheat slightly and don't define separate Null objects
    1.90 +     * for Record types.  Instead, we return the correct Null(Tag)
    1.91 +     * here. */
    1.92 +    if (unlikely (i >= this->len)) return Null(Tag);
    1.93 +    return (*this)[i].tag;
    1.94 +  }
    1.95 +  inline unsigned int get_tags (unsigned int start_offset,
    1.96 +				unsigned int *record_count /* IN/OUT */,
    1.97 +				hb_tag_t     *record_tags /* OUT */) const
    1.98 +  {
    1.99 +    if (record_count) {
   1.100 +      const Record<Type> *arr = this->sub_array (start_offset, record_count);
   1.101 +      unsigned int count = *record_count;
   1.102 +      for (unsigned int i = 0; i < count; i++)
   1.103 +	record_tags[i] = arr[i].tag;
   1.104 +    }
   1.105 +    return this->len;
   1.106 +  }
   1.107 +  inline bool find_index (hb_tag_t tag, unsigned int *index) const
   1.108 +  {
   1.109 +    int i = this->search (tag);
   1.110 +    if (i != -1) {
   1.111 +        if (index) *index = i;
   1.112 +        return true;
   1.113 +    } else {
   1.114 +      if (index) *index = Index::NOT_FOUND_INDEX;
   1.115 +      return false;
   1.116 +    }
   1.117 +  }
   1.118 +};
   1.119 +
   1.120 +template <typename Type>
   1.121 +struct RecordListOf : RecordArrayOf<Type>
   1.122 +{
   1.123 +  inline const Type& operator [] (unsigned int i) const
   1.124 +  { return this+RecordArrayOf<Type>::operator [](i).offset; }
   1.125 +
   1.126 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.127 +    TRACE_SANITIZE (this);
   1.128 +    return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
   1.129 +  }
   1.130 +};
   1.131 +
   1.132 +
   1.133 +struct RangeRecord
   1.134 +{
   1.135 +  inline int cmp (hb_codepoint_t g) const {
   1.136 +    return g < start ? -1 : g <= end ? 0 : +1 ;
   1.137 +  }
   1.138 +
   1.139 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.140 +    TRACE_SANITIZE (this);
   1.141 +    return TRACE_RETURN (c->check_struct (this));
   1.142 +  }
   1.143 +
   1.144 +  inline bool intersects (const hb_set_t *glyphs) const {
   1.145 +    return glyphs->intersects (start, end);
   1.146 +  }
   1.147 +
   1.148 +  template <typename set_t>
   1.149 +  inline void add_coverage (set_t *glyphs) const {
   1.150 +    glyphs->add_range (start, end);
   1.151 +  }
   1.152 +
   1.153 +  GlyphID	start;		/* First GlyphID in the range */
   1.154 +  GlyphID	end;		/* Last GlyphID in the range */
   1.155 +  USHORT	value;		/* Value */
   1.156 +  public:
   1.157 +  DEFINE_SIZE_STATIC (6);
   1.158 +};
   1.159 +DEFINE_NULL_DATA (RangeRecord, "\000\001");
   1.160 +
   1.161 +
   1.162 +struct IndexArray : ArrayOf<Index>
   1.163 +{
   1.164 +  inline unsigned int get_indexes (unsigned int start_offset,
   1.165 +				   unsigned int *_count /* IN/OUT */,
   1.166 +				   unsigned int *_indexes /* OUT */) const
   1.167 +  {
   1.168 +    if (_count) {
   1.169 +      const USHORT *arr = this->sub_array (start_offset, _count);
   1.170 +      unsigned int count = *_count;
   1.171 +      for (unsigned int i = 0; i < count; i++)
   1.172 +	_indexes[i] = arr[i];
   1.173 +    }
   1.174 +    return this->len;
   1.175 +  }
   1.176 +};
   1.177 +
   1.178 +
   1.179 +struct Script;
   1.180 +struct LangSys;
   1.181 +struct Feature;
   1.182 +
   1.183 +
   1.184 +struct LangSys
   1.185 +{
   1.186 +  inline unsigned int get_feature_count (void) const
   1.187 +  { return featureIndex.len; }
   1.188 +  inline hb_tag_t get_feature_index (unsigned int i) const
   1.189 +  { return featureIndex[i]; }
   1.190 +  inline unsigned int get_feature_indexes (unsigned int start_offset,
   1.191 +					   unsigned int *feature_count /* IN/OUT */,
   1.192 +					   unsigned int *feature_indexes /* OUT */) const
   1.193 +  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
   1.194 +
   1.195 +  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
   1.196 +  inline unsigned int get_required_feature_index (void) const
   1.197 +  {
   1.198 +    if (reqFeatureIndex == 0xffff)
   1.199 +      return Index::NOT_FOUND_INDEX;
   1.200 +   return reqFeatureIndex;;
   1.201 +  }
   1.202 +
   1.203 +  inline bool sanitize (hb_sanitize_context_t *c,
   1.204 +			const Record<LangSys>::sanitize_closure_t * = NULL) {
   1.205 +    TRACE_SANITIZE (this);
   1.206 +    return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
   1.207 +  }
   1.208 +
   1.209 +  Offset	lookupOrder;	/* = Null (reserved for an offset to a
   1.210 +				 * reordering table) */
   1.211 +  USHORT	reqFeatureIndex;/* Index of a feature required for this
   1.212 +				 * language system--if no required features
   1.213 +				 * = 0xFFFF */
   1.214 +  IndexArray	featureIndex;	/* Array of indices into the FeatureList */
   1.215 +  public:
   1.216 +  DEFINE_SIZE_ARRAY (6, featureIndex);
   1.217 +};
   1.218 +DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
   1.219 +
   1.220 +
   1.221 +struct Script
   1.222 +{
   1.223 +  inline unsigned int get_lang_sys_count (void) const
   1.224 +  { return langSys.len; }
   1.225 +  inline const Tag& get_lang_sys_tag (unsigned int i) const
   1.226 +  { return langSys.get_tag (i); }
   1.227 +  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
   1.228 +					 unsigned int *lang_sys_count /* IN/OUT */,
   1.229 +					 hb_tag_t     *lang_sys_tags /* OUT */) const
   1.230 +  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
   1.231 +  inline const LangSys& get_lang_sys (unsigned int i) const
   1.232 +  {
   1.233 +    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
   1.234 +    return this+langSys[i].offset;
   1.235 +  }
   1.236 +  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
   1.237 +  { return langSys.find_index (tag, index); }
   1.238 +
   1.239 +  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
   1.240 +  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
   1.241 +
   1.242 +  inline bool sanitize (hb_sanitize_context_t *c,
   1.243 +			const Record<Script>::sanitize_closure_t * = NULL) {
   1.244 +    TRACE_SANITIZE (this);
   1.245 +    return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
   1.246 +  }
   1.247 +
   1.248 +  protected:
   1.249 +  OffsetTo<LangSys>
   1.250 +		defaultLangSys;	/* Offset to DefaultLangSys table--from
   1.251 +				 * beginning of Script table--may be Null */
   1.252 +  RecordArrayOf<LangSys>
   1.253 +		langSys;	/* Array of LangSysRecords--listed
   1.254 +				 * alphabetically by LangSysTag */
   1.255 +  public:
   1.256 +  DEFINE_SIZE_ARRAY (4, langSys);
   1.257 +};
   1.258 +
   1.259 +typedef RecordListOf<Script> ScriptList;
   1.260 +
   1.261 +
   1.262 +/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
   1.263 +struct FeatureParamsSize
   1.264 +{
   1.265 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.266 +    TRACE_SANITIZE (this);
   1.267 +    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
   1.268 +
   1.269 +    /* This subtable has some "history", if you will.  Some earlier versions of
   1.270 +     * Adobe tools calculated the offset of the FeatureParams sutable from the
   1.271 +     * beginning of the FeatureList table!  Now, that is dealt with in the
   1.272 +     * Feature implementation.  But we still need to be able to tell junk from
   1.273 +     * real data.  Note: We don't check that the nameID actually exists.
   1.274 +     *
   1.275 +     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
   1.276 +     *
   1.277 +     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
   1.278 +     * coming out soon, and that the makeotf program will build a font with a
   1.279 +     * 'size' feature that is correct by the specification.
   1.280 +     *
   1.281 +     * The specification for this feature tag is in the "OpenType Layout Tag
   1.282 +     * Registry". You can see a copy of this at:
   1.283 +     * http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
   1.284 +     *
   1.285 +     * Here is one set of rules to determine if the 'size' feature is built
   1.286 +     * correctly, or as by the older versions of MakeOTF. You may be able to do
   1.287 +     * better.
   1.288 +     *
   1.289 +     * Assume that the offset to the size feature is according to specification,
   1.290 +     * and make the following value checks. If it fails, assume the the size
   1.291 +     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
   1.292 +     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
   1.293 +     * offset from the beginning of the FeatureList table, rather than from the
   1.294 +     * beginning of the 'size' Feature table.
   1.295 +     *
   1.296 +     * If "design size" == 0:
   1.297 +     *     fails check
   1.298 +     *
   1.299 +     * Else if ("subfamily identifier" == 0 and
   1.300 +     *     "range start" == 0 and
   1.301 +     *     "range end" == 0 and
   1.302 +     *     "range start" == 0 and
   1.303 +     *     "menu name ID" == 0)
   1.304 +     *     passes check: this is the format used when there is a design size
   1.305 +     * specified, but there is no recommended size range.
   1.306 +     *
   1.307 +     * Else if ("design size" <  "range start" or
   1.308 +     *     "design size" >   "range end" or
   1.309 +     *     "range end" <= "range start" or
   1.310 +     *     "menu name ID"  < 256 or
   1.311 +     *     "menu name ID"  > 32767 or
   1.312 +     *     menu name ID is not a name ID which is actually in the name table)
   1.313 +     *     fails test
   1.314 +     * Else
   1.315 +     *     passes test.
   1.316 +     */
   1.317 +
   1.318 +    if (!designSize)
   1.319 +      return TRACE_RETURN (false);
   1.320 +    else if (subfamilyID == 0 &&
   1.321 +	     subfamilyNameID == 0 &&
   1.322 +	     rangeStart == 0 &&
   1.323 +	     rangeEnd == 0)
   1.324 +      return TRACE_RETURN (true);
   1.325 +    else if (designSize < rangeStart ||
   1.326 +	     designSize > rangeEnd ||
   1.327 +	     subfamilyNameID < 256 ||
   1.328 +	     subfamilyNameID > 32767)
   1.329 +      return TRACE_RETURN (false);
   1.330 +    else
   1.331 +      return TRACE_RETURN (true);
   1.332 +  }
   1.333 +
   1.334 +  USHORT	designSize;	/* Represents the design size in 720/inch
   1.335 +				 * units (decipoints).  The design size entry
   1.336 +				 * must be non-zero.  When there is a design
   1.337 +				 * size but no recommended size range, the
   1.338 +				 * rest of the array will consist of zeros. */
   1.339 +  USHORT	subfamilyID;	/* Has no independent meaning, but serves
   1.340 +				 * as an identifier that associates fonts
   1.341 +				 * in a subfamily. All fonts which share a
   1.342 +				 * Preferred or Font Family name and which
   1.343 +				 * differ only by size range shall have the
   1.344 +				 * same subfamily value, and no fonts which
   1.345 +				 * differ in weight or style shall have the
   1.346 +				 * same subfamily value. If this value is
   1.347 +				 * zero, the remaining fields in the array
   1.348 +				 * will be ignored. */
   1.349 +  USHORT	subfamilyNameID;/* If the preceding value is non-zero, this
   1.350 +				 * value must be set in the range 256 - 32767
   1.351 +				 * (inclusive). It records the value of a
   1.352 +				 * field in the name table, which must
   1.353 +				 * contain English-language strings encoded
   1.354 +				 * in Windows Unicode and Macintosh Roman,
   1.355 +				 * and may contain additional strings
   1.356 +				 * localized to other scripts and languages.
   1.357 +				 * Each of these strings is the name an
   1.358 +				 * application should use, in combination
   1.359 +				 * with the family name, to represent the
   1.360 +				 * subfamily in a menu.  Applications will
   1.361 +				 * choose the appropriate version based on
   1.362 +				 * their selection criteria. */
   1.363 +  USHORT	rangeStart;	/* Large end of the recommended usage range
   1.364 +				 * (inclusive), stored in 720/inch units
   1.365 +				 * (decipoints). */
   1.366 +  USHORT	rangeEnd;	/* Small end of the recommended usage range
   1.367 +				   (exclusive), stored in 720/inch units
   1.368 +				 * (decipoints). */
   1.369 +  public:
   1.370 +  DEFINE_SIZE_STATIC (10);
   1.371 +};
   1.372 +
   1.373 +/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
   1.374 +struct FeatureParamsStylisticSet
   1.375 +{
   1.376 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.377 +    TRACE_SANITIZE (this);
   1.378 +    /* Right now minorVersion is at zero.  Which means, any table supports
   1.379 +     * the uiNameID field. */
   1.380 +    return TRACE_RETURN (c->check_struct (this));
   1.381 +  }
   1.382 +
   1.383 +  USHORT	version;	/* (set to 0): This corresponds to a “minor”
   1.384 +				 * version number. Additional data may be
   1.385 +				 * added to the end of this Feature Parameters
   1.386 +				 * table in the future. */
   1.387 +
   1.388 +  USHORT	uiNameID;	/* The 'name' table name ID that specifies a
   1.389 +				 * string (or strings, for multiple languages)
   1.390 +				 * for a user-interface label for this
   1.391 +				 * feature.  The values of uiLabelNameId and
   1.392 +				 * sampleTextNameId are expected to be in the
   1.393 +				 * font-specific name ID range (256-32767),
   1.394 +				 * though that is not a requirement in this
   1.395 +				 * Feature Parameters specification. The
   1.396 +				 * user-interface label for the feature can
   1.397 +				 * be provided in multiple languages. An
   1.398 +				 * English string should be included as a
   1.399 +				 * fallback. The string should be kept to a
   1.400 +				 * minimal length to fit comfortably with
   1.401 +				 * different application interfaces. */
   1.402 +  public:
   1.403 +  DEFINE_SIZE_STATIC (4);
   1.404 +};
   1.405 +
   1.406 +/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
   1.407 +struct FeatureParamsCharacterVariants
   1.408 +{
   1.409 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.410 +    TRACE_SANITIZE (this);
   1.411 +    return TRACE_RETURN (c->check_struct (this) &&
   1.412 +			 characters.sanitize (c));
   1.413 +  }
   1.414 +
   1.415 +  USHORT	format;			/* Format number is set to 0. */
   1.416 +  USHORT	featUILableNameID;	/* The ‘name’ table name ID that
   1.417 +					 * specifies a string (or strings,
   1.418 +					 * for multiple languages) for a
   1.419 +					 * user-interface label for this
   1.420 +					 * feature. (May be NULL.) */
   1.421 +  USHORT	featUITooltipTextNameID;/* The ‘name’ table name ID that
   1.422 +					 * specifies a string (or strings,
   1.423 +					 * for multiple languages) that an
   1.424 +					 * application can use for tooltip
   1.425 +					 * text for this feature. (May be
   1.426 +					 * NULL.) */
   1.427 +  USHORT	sampleTextNameID;	/* The ‘name’ table name ID that
   1.428 +					 * specifies sample text that
   1.429 +					 * illustrates the effect of this
   1.430 +					 * feature. (May be NULL.) */
   1.431 +  USHORT	numNamedParameters;	/* Number of named parameters. (May
   1.432 +					 * be zero.) */
   1.433 +  USHORT	firstParamUILabelNameID;/* The first ‘name’ table name ID
   1.434 +					 * used to specify strings for
   1.435 +					 * user-interface labels for the
   1.436 +					 * feature parameters. (Must be zero
   1.437 +					 * if numParameters is zero.) */
   1.438 +  ArrayOf<UINT24>
   1.439 +		characters;		/* Array of the Unicode Scalar Value
   1.440 +					 * of the characters for which this
   1.441 +					 * feature provides glyph variants.
   1.442 +					 * (May be zero.) */
   1.443 +  public:
   1.444 +  DEFINE_SIZE_ARRAY (14, characters);
   1.445 +};
   1.446 +
   1.447 +struct FeatureParams
   1.448 +{
   1.449 +  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) {
   1.450 +    TRACE_SANITIZE (this);
   1.451 +    if (tag == HB_TAG ('s','i','z','e'))
   1.452 +      return TRACE_RETURN (u.size.sanitize (c));
   1.453 +    if ((tag & 0xFFFF0000) == HB_TAG ('s','s','\0','\0')) /* ssXX */
   1.454 +      return TRACE_RETURN (u.stylisticSet.sanitize (c));
   1.455 +    if ((tag & 0xFFFF0000) == HB_TAG ('c','v','\0','\0')) /* cvXX */
   1.456 +      return TRACE_RETURN (u.characterVariants.sanitize (c));
   1.457 +    return TRACE_RETURN (true);
   1.458 +  }
   1.459 +
   1.460 +  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
   1.461 +  {
   1.462 +    if (tag == HB_TAG ('s','i','z','e'))
   1.463 +      return u.size;
   1.464 +    return Null(FeatureParamsSize);
   1.465 +  }
   1.466 +
   1.467 +  private:
   1.468 +  union {
   1.469 +  FeatureParamsSize			size;
   1.470 +  FeatureParamsStylisticSet		stylisticSet;
   1.471 +  FeatureParamsCharacterVariants	characterVariants;
   1.472 +  } u;
   1.473 +  DEFINE_SIZE_STATIC (17);
   1.474 +};
   1.475 +
   1.476 +struct Feature
   1.477 +{
   1.478 +  inline unsigned int get_lookup_count (void) const
   1.479 +  { return lookupIndex.len; }
   1.480 +  inline hb_tag_t get_lookup_index (unsigned int i) const
   1.481 +  { return lookupIndex[i]; }
   1.482 +  inline unsigned int get_lookup_indexes (unsigned int start_index,
   1.483 +					  unsigned int *lookup_count /* IN/OUT */,
   1.484 +					  unsigned int *lookup_tags /* OUT */) const
   1.485 +  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
   1.486 +
   1.487 +  inline const FeatureParams &get_feature_params (void) const
   1.488 +  { return this+featureParams; }
   1.489 +
   1.490 +  inline bool sanitize (hb_sanitize_context_t *c,
   1.491 +			const Record<Feature>::sanitize_closure_t *closure) {
   1.492 +    TRACE_SANITIZE (this);
   1.493 +    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
   1.494 +      return TRACE_RETURN (false);
   1.495 +
   1.496 +    /* Some earlier versions of Adobe tools calculated the offset of the
   1.497 +     * FeatureParams subtable from the beginning of the FeatureList table!
   1.498 +     *
   1.499 +     * If sanitizing "failed" for the FeatureParams subtable, try it with the
   1.500 +     * alternative location.  We would know sanitize "failed" if old value
   1.501 +     * of the offset was non-zero, but it's zeroed now.
   1.502 +     *
   1.503 +     * Only do this for the 'size' feature, since at the time of the faulty
   1.504 +     * Adobe tools, only the 'size' feature had FeatureParams defined.
   1.505 +     */
   1.506 +
   1.507 +    Offset orig_offset = featureParams;
   1.508 +    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
   1.509 +      return TRACE_RETURN (false);
   1.510 +
   1.511 +    if (likely (!orig_offset))
   1.512 +      return TRACE_RETURN (true);
   1.513 +
   1.514 +    if (featureParams == 0 && closure &&
   1.515 +	closure->tag == HB_TAG ('s','i','z','e') &&
   1.516 +	closure->list_base && closure->list_base < this)
   1.517 +    {
   1.518 +      unsigned int new_offset_int = (unsigned int) orig_offset -
   1.519 +				    ((char *) this - (char *) closure->list_base);
   1.520 +
   1.521 +      Offset new_offset;
   1.522 +      /* Check that it did not overflow. */
   1.523 +      new_offset.set (new_offset_int);
   1.524 +      if (new_offset == new_offset_int &&
   1.525 +	  featureParams.try_set (c, new_offset) &&
   1.526 +	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
   1.527 +	return TRACE_RETURN (false);
   1.528 +    }
   1.529 +
   1.530 +    return TRACE_RETURN (true);
   1.531 +  }
   1.532 +
   1.533 +  OffsetTo<FeatureParams>
   1.534 +		 featureParams;	/* Offset to Feature Parameters table (if one
   1.535 +				 * has been defined for the feature), relative
   1.536 +				 * to the beginning of the Feature Table; = Null
   1.537 +				 * if not required */
   1.538 +  IndexArray	 lookupIndex;	/* Array of LookupList indices */
   1.539 +  public:
   1.540 +  DEFINE_SIZE_ARRAY (4, lookupIndex);
   1.541 +};
   1.542 +
   1.543 +typedef RecordListOf<Feature> FeatureList;
   1.544 +
   1.545 +
   1.546 +struct LookupFlag : USHORT
   1.547 +{
   1.548 +  enum Flags {
   1.549 +    RightToLeft		= 0x0001u,
   1.550 +    IgnoreBaseGlyphs	= 0x0002u,
   1.551 +    IgnoreLigatures	= 0x0004u,
   1.552 +    IgnoreMarks		= 0x0008u,
   1.553 +    IgnoreFlags		= 0x000Eu,
   1.554 +    UseMarkFilteringSet	= 0x0010u,
   1.555 +    Reserved		= 0x00E0u,
   1.556 +    MarkAttachmentType	= 0xFF00u
   1.557 +  };
   1.558 +  public:
   1.559 +  DEFINE_SIZE_STATIC (2);
   1.560 +};
   1.561 +
   1.562 +struct Lookup
   1.563 +{
   1.564 +  inline unsigned int get_subtable_count (void) const { return subTable.len; }
   1.565 +
   1.566 +  inline unsigned int get_type (void) const { return lookupType; }
   1.567 +
   1.568 +  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
   1.569 +   * higher 16-bit is mark-filtering-set if the lookup uses one.
   1.570 +   * Not to be confused with glyph_props which is very similar. */
   1.571 +  inline uint32_t get_props (void) const
   1.572 +  {
   1.573 +    unsigned int flag = lookupFlag;
   1.574 +    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
   1.575 +    {
   1.576 +      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
   1.577 +      flag += (markFilteringSet << 16);
   1.578 +    }
   1.579 +    return flag;
   1.580 +  }
   1.581 +
   1.582 +  inline bool serialize (hb_serialize_context_t *c,
   1.583 +			 unsigned int lookup_type,
   1.584 +			 uint32_t lookup_props,
   1.585 +			 unsigned int num_subtables)
   1.586 +  {
   1.587 +    TRACE_SERIALIZE (this);
   1.588 +    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
   1.589 +    lookupType.set (lookup_type);
   1.590 +    lookupFlag.set (lookup_props & 0xFFFF);
   1.591 +    if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
   1.592 +    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
   1.593 +    {
   1.594 +      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
   1.595 +      markFilteringSet.set (lookup_props >> 16);
   1.596 +    }
   1.597 +    return TRACE_RETURN (true);
   1.598 +  }
   1.599 +
   1.600 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.601 +    TRACE_SANITIZE (this);
   1.602 +    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
   1.603 +    if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
   1.604 +    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
   1.605 +    {
   1.606 +      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
   1.607 +      if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
   1.608 +    }
   1.609 +    return TRACE_RETURN (true);
   1.610 +  }
   1.611 +
   1.612 +  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
   1.613 +  USHORT	lookupFlag;		/* Lookup qualifiers */
   1.614 +  ArrayOf<Offset>
   1.615 +		subTable;		/* Array of SubTables */
   1.616 +  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
   1.617 +					 * structure. This field is only present if bit
   1.618 +					 * UseMarkFilteringSet of lookup flags is set. */
   1.619 +  public:
   1.620 +  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
   1.621 +};
   1.622 +
   1.623 +typedef OffsetListOf<Lookup> LookupList;
   1.624 +
   1.625 +
   1.626 +/*
   1.627 + * Coverage Table
   1.628 + */
   1.629 +
   1.630 +struct CoverageFormat1
   1.631 +{
   1.632 +  friend struct Coverage;
   1.633 +
   1.634 +  private:
   1.635 +  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   1.636 +  {
   1.637 +    int i = glyphArray.search (glyph_id);
   1.638 +    ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
   1.639 +    return i;
   1.640 +  }
   1.641 +
   1.642 +  inline bool serialize (hb_serialize_context_t *c,
   1.643 +			 Supplier<GlyphID> &glyphs,
   1.644 +			 unsigned int num_glyphs)
   1.645 +  {
   1.646 +    TRACE_SERIALIZE (this);
   1.647 +    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
   1.648 +    glyphArray.len.set (num_glyphs);
   1.649 +    if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
   1.650 +    for (unsigned int i = 0; i < num_glyphs; i++)
   1.651 +      glyphArray[i] = glyphs[i];
   1.652 +    glyphs.advance (num_glyphs);
   1.653 +    return TRACE_RETURN (true);
   1.654 +  }
   1.655 +
   1.656 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.657 +    TRACE_SANITIZE (this);
   1.658 +    return TRACE_RETURN (glyphArray.sanitize (c));
   1.659 +  }
   1.660 +
   1.661 +  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
   1.662 +    return glyphs->has (glyphArray[index]);
   1.663 +  }
   1.664 +
   1.665 +  template <typename set_t>
   1.666 +  inline void add_coverage (set_t *glyphs) const {
   1.667 +    unsigned int count = glyphArray.len;
   1.668 +    for (unsigned int i = 0; i < count; i++)
   1.669 +      glyphs->add (glyphArray[i]);
   1.670 +  }
   1.671 +
   1.672 +  public:
   1.673 +  /* Older compilers need this to be public. */
   1.674 +  struct Iter {
   1.675 +    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
   1.676 +    inline bool more (void) { return i < c->glyphArray.len; }
   1.677 +    inline void next (void) { i++; }
   1.678 +    inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
   1.679 +    inline uint16_t get_coverage (void) { return i; }
   1.680 +
   1.681 +    private:
   1.682 +    const struct CoverageFormat1 *c;
   1.683 +    unsigned int i;
   1.684 +  };
   1.685 +  private:
   1.686 +
   1.687 +  protected:
   1.688 +  USHORT	coverageFormat;	/* Format identifier--format = 1 */
   1.689 +  SortedArrayOf<GlyphID>
   1.690 +		glyphArray;	/* Array of GlyphIDs--in numerical order */
   1.691 +  public:
   1.692 +  DEFINE_SIZE_ARRAY (4, glyphArray);
   1.693 +};
   1.694 +
   1.695 +struct CoverageFormat2
   1.696 +{
   1.697 +  friend struct Coverage;
   1.698 +
   1.699 +  private:
   1.700 +  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   1.701 +  {
   1.702 +    int i = rangeRecord.search (glyph_id);
   1.703 +    if (i != -1) {
   1.704 +      const RangeRecord &range = rangeRecord[i];
   1.705 +      return (unsigned int) range.value + (glyph_id - range.start);
   1.706 +    }
   1.707 +    return NOT_COVERED;
   1.708 +  }
   1.709 +
   1.710 +  inline bool serialize (hb_serialize_context_t *c,
   1.711 +			 Supplier<GlyphID> &glyphs,
   1.712 +			 unsigned int num_glyphs)
   1.713 +  {
   1.714 +    TRACE_SERIALIZE (this);
   1.715 +    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
   1.716 +
   1.717 +    if (unlikely (!num_glyphs)) return TRACE_RETURN (true);
   1.718 +
   1.719 +    unsigned int num_ranges = 1;
   1.720 +    for (unsigned int i = 1; i < num_glyphs; i++)
   1.721 +      if (glyphs[i - 1] + 1 != glyphs[i])
   1.722 +        num_ranges++;
   1.723 +    rangeRecord.len.set (num_ranges);
   1.724 +    if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false);
   1.725 +
   1.726 +    unsigned int range = 0;
   1.727 +    rangeRecord[range].start = glyphs[0];
   1.728 +    rangeRecord[range].value.set (0);
   1.729 +    for (unsigned int i = 1; i < num_glyphs; i++)
   1.730 +      if (glyphs[i - 1] + 1 != glyphs[i]) {
   1.731 +	range++;
   1.732 +	rangeRecord[range].start = glyphs[i];
   1.733 +	rangeRecord[range].value.set (i);
   1.734 +        rangeRecord[range].end = glyphs[i];
   1.735 +      } else {
   1.736 +        rangeRecord[range].end = glyphs[i];
   1.737 +      }
   1.738 +    glyphs.advance (num_glyphs);
   1.739 +    return TRACE_RETURN (true);
   1.740 +  }
   1.741 +
   1.742 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.743 +    TRACE_SANITIZE (this);
   1.744 +    return TRACE_RETURN (rangeRecord.sanitize (c));
   1.745 +  }
   1.746 +
   1.747 +  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
   1.748 +    unsigned int i;
   1.749 +    unsigned int count = rangeRecord.len;
   1.750 +    for (i = 0; i < count; i++) {
   1.751 +      const RangeRecord &range = rangeRecord[i];
   1.752 +      if (range.value <= index &&
   1.753 +	  index < (unsigned int) range.value + (range.end - range.start) &&
   1.754 +	  range.intersects (glyphs))
   1.755 +        return true;
   1.756 +      else if (index < range.value)
   1.757 +        return false;
   1.758 +    }
   1.759 +    return false;
   1.760 +  }
   1.761 +
   1.762 +  template <typename set_t>
   1.763 +  inline void add_coverage (set_t *glyphs) const {
   1.764 +    unsigned int count = rangeRecord.len;
   1.765 +    for (unsigned int i = 0; i < count; i++)
   1.766 +      rangeRecord[i].add_coverage (glyphs);
   1.767 +  }
   1.768 +
   1.769 +  public:
   1.770 +  /* Older compilers need this to be public. */
   1.771 +  struct Iter {
   1.772 +    inline void init (const CoverageFormat2 &c_) {
   1.773 +      c = &c_;
   1.774 +      coverage = 0;
   1.775 +      i = 0;
   1.776 +      j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
   1.777 +    }
   1.778 +    inline bool more (void) { return i < c->rangeRecord.len; }
   1.779 +    inline void next (void) {
   1.780 +      coverage++;
   1.781 +      if (j == c->rangeRecord[i].end) {
   1.782 +        i++;
   1.783 +	if (more ())
   1.784 +	  j = c->rangeRecord[i].start;
   1.785 +	return;
   1.786 +      }
   1.787 +      j++;
   1.788 +    }
   1.789 +    inline uint16_t get_glyph (void) { return j; }
   1.790 +    inline uint16_t get_coverage (void) { return coverage; }
   1.791 +
   1.792 +    private:
   1.793 +    const struct CoverageFormat2 *c;
   1.794 +    unsigned int i, j, coverage;
   1.795 +  };
   1.796 +  private:
   1.797 +
   1.798 +  protected:
   1.799 +  USHORT	coverageFormat;	/* Format identifier--format = 2 */
   1.800 +  SortedArrayOf<RangeRecord>
   1.801 +		rangeRecord;	/* Array of glyph ranges--ordered by
   1.802 +				 * Start GlyphID. rangeCount entries
   1.803 +				 * long */
   1.804 +  public:
   1.805 +  DEFINE_SIZE_ARRAY (4, rangeRecord);
   1.806 +};
   1.807 +
   1.808 +struct Coverage
   1.809 +{
   1.810 +  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   1.811 +  {
   1.812 +    switch (u.format) {
   1.813 +    case 1: return u.format1.get_coverage(glyph_id);
   1.814 +    case 2: return u.format2.get_coverage(glyph_id);
   1.815 +    default:return NOT_COVERED;
   1.816 +    }
   1.817 +  }
   1.818 +
   1.819 +  inline bool serialize (hb_serialize_context_t *c,
   1.820 +			 Supplier<GlyphID> &glyphs,
   1.821 +			 unsigned int num_glyphs)
   1.822 +  {
   1.823 +    TRACE_SERIALIZE (this);
   1.824 +    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
   1.825 +    unsigned int num_ranges = 1;
   1.826 +    for (unsigned int i = 1; i < num_glyphs; i++)
   1.827 +      if (glyphs[i - 1] + 1 != glyphs[i])
   1.828 +        num_ranges++;
   1.829 +    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
   1.830 +    switch (u.format) {
   1.831 +    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
   1.832 +    case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
   1.833 +    default:return TRACE_RETURN (false);
   1.834 +    }
   1.835 +  }
   1.836 +
   1.837 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.838 +    TRACE_SANITIZE (this);
   1.839 +    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
   1.840 +    switch (u.format) {
   1.841 +    case 1: return TRACE_RETURN (u.format1.sanitize (c));
   1.842 +    case 2: return TRACE_RETURN (u.format2.sanitize (c));
   1.843 +    default:return TRACE_RETURN (true);
   1.844 +    }
   1.845 +  }
   1.846 +
   1.847 +  inline bool intersects (const hb_set_t *glyphs) const {
   1.848 +    /* TODO speed this up */
   1.849 +    Coverage::Iter iter;
   1.850 +    for (iter.init (*this); iter.more (); iter.next ()) {
   1.851 +      if (glyphs->has (iter.get_glyph ()))
   1.852 +        return true;
   1.853 +    }
   1.854 +    return false;
   1.855 +  }
   1.856 +
   1.857 +  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
   1.858 +    switch (u.format) {
   1.859 +    case 1: return u.format1.intersects_coverage (glyphs, index);
   1.860 +    case 2: return u.format2.intersects_coverage (glyphs, index);
   1.861 +    default:return false;
   1.862 +    }
   1.863 +  }
   1.864 +
   1.865 +  template <typename set_t>
   1.866 +  inline void add_coverage (set_t *glyphs) const {
   1.867 +    switch (u.format) {
   1.868 +    case 1: u.format1.add_coverage (glyphs); break;
   1.869 +    case 2: u.format2.add_coverage (glyphs); break;
   1.870 +    default:                                 break;
   1.871 +    }
   1.872 +  }
   1.873 +
   1.874 +  struct Iter {
   1.875 +    Iter (void) : format (0) {};
   1.876 +    inline void init (const Coverage &c_) {
   1.877 +      format = c_.u.format;
   1.878 +      switch (format) {
   1.879 +      case 1: u.format1.init (c_.u.format1); return;
   1.880 +      case 2: u.format2.init (c_.u.format2); return;
   1.881 +      default:                               return;
   1.882 +      }
   1.883 +    }
   1.884 +    inline bool more (void) {
   1.885 +      switch (format) {
   1.886 +      case 1: return u.format1.more ();
   1.887 +      case 2: return u.format2.more ();
   1.888 +      default:return false;
   1.889 +      }
   1.890 +    }
   1.891 +    inline void next (void) {
   1.892 +      switch (format) {
   1.893 +      case 1: u.format1.next (); break;
   1.894 +      case 2: u.format2.next (); break;
   1.895 +      default:                   break;
   1.896 +      }
   1.897 +    }
   1.898 +    inline uint16_t get_glyph (void) {
   1.899 +      switch (format) {
   1.900 +      case 1: return u.format1.get_glyph ();
   1.901 +      case 2: return u.format2.get_glyph ();
   1.902 +      default:return 0;
   1.903 +      }
   1.904 +    }
   1.905 +    inline uint16_t get_coverage (void) {
   1.906 +      switch (format) {
   1.907 +      case 1: return u.format1.get_coverage ();
   1.908 +      case 2: return u.format2.get_coverage ();
   1.909 +      default:return -1;
   1.910 +      }
   1.911 +    }
   1.912 +
   1.913 +    private:
   1.914 +    unsigned int format;
   1.915 +    union {
   1.916 +    CoverageFormat1::Iter	format1;
   1.917 +    CoverageFormat2::Iter	format2;
   1.918 +    } u;
   1.919 +  };
   1.920 +
   1.921 +  protected:
   1.922 +  union {
   1.923 +  USHORT		format;		/* Format identifier */
   1.924 +  CoverageFormat1	format1;
   1.925 +  CoverageFormat2	format2;
   1.926 +  } u;
   1.927 +  public:
   1.928 +  DEFINE_SIZE_UNION (2, format);
   1.929 +};
   1.930 +
   1.931 +
   1.932 +/*
   1.933 + * Class Definition Table
   1.934 + */
   1.935 +
   1.936 +struct ClassDefFormat1
   1.937 +{
   1.938 +  friend struct ClassDef;
   1.939 +
   1.940 +  private:
   1.941 +  inline unsigned int get_class (hb_codepoint_t glyph_id) const
   1.942 +  {
   1.943 +    if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len))
   1.944 +      return classValue[glyph_id - startGlyph];
   1.945 +    return 0;
   1.946 +  }
   1.947 +
   1.948 +  inline bool sanitize (hb_sanitize_context_t *c) {
   1.949 +    TRACE_SANITIZE (this);
   1.950 +    return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
   1.951 +  }
   1.952 +
   1.953 +  template <typename set_t>
   1.954 +  inline void add_class (set_t *glyphs, unsigned int klass) const {
   1.955 +    unsigned int count = classValue.len;
   1.956 +    for (unsigned int i = 0; i < count; i++)
   1.957 +      if (classValue[i] == klass)
   1.958 +        glyphs->add (startGlyph + i);
   1.959 +  }
   1.960 +
   1.961 +  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
   1.962 +    unsigned int count = classValue.len;
   1.963 +    if (klass == 0)
   1.964 +    {
   1.965 +      /* Match if there's any glyph that is not listed! */
   1.966 +      hb_codepoint_t g = -1;
   1.967 +      if (!hb_set_next (glyphs, &g))
   1.968 +        return false;
   1.969 +      if (g < startGlyph)
   1.970 +        return true;
   1.971 +      g = startGlyph + count - 1;
   1.972 +      if (hb_set_next (glyphs, &g))
   1.973 +        return true;
   1.974 +      /* Fall through. */
   1.975 +    }
   1.976 +    for (unsigned int i = 0; i < count; i++)
   1.977 +      if (classValue[i] == klass && glyphs->has (startGlyph + i))
   1.978 +        return true;
   1.979 +    return false;
   1.980 +  }
   1.981 +
   1.982 +  protected:
   1.983 +  USHORT	classFormat;		/* Format identifier--format = 1 */
   1.984 +  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
   1.985 +  ArrayOf<USHORT>
   1.986 +		classValue;		/* Array of Class Values--one per GlyphID */
   1.987 +  public:
   1.988 +  DEFINE_SIZE_ARRAY (6, classValue);
   1.989 +};
   1.990 +
   1.991 +struct ClassDefFormat2
   1.992 +{
   1.993 +  friend struct ClassDef;
   1.994 +
   1.995 +  private:
   1.996 +  inline unsigned int get_class (hb_codepoint_t glyph_id) const
   1.997 +  {
   1.998 +    int i = rangeRecord.search (glyph_id);
   1.999 +    if (i != -1)
  1.1000 +      return rangeRecord[i].value;
  1.1001 +    return 0;
  1.1002 +  }
  1.1003 +
  1.1004 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1005 +    TRACE_SANITIZE (this);
  1.1006 +    return TRACE_RETURN (rangeRecord.sanitize (c));
  1.1007 +  }
  1.1008 +
  1.1009 +  template <typename set_t>
  1.1010 +  inline void add_class (set_t *glyphs, unsigned int klass) const {
  1.1011 +    unsigned int count = rangeRecord.len;
  1.1012 +    for (unsigned int i = 0; i < count; i++)
  1.1013 +      if (rangeRecord[i].value == klass)
  1.1014 +        rangeRecord[i].add_coverage (glyphs);
  1.1015 +  }
  1.1016 +
  1.1017 +  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
  1.1018 +    unsigned int count = rangeRecord.len;
  1.1019 +    if (klass == 0)
  1.1020 +    {
  1.1021 +      /* Match if there's any glyph that is not listed! */
  1.1022 +      hb_codepoint_t g = (hb_codepoint_t) -1;
  1.1023 +      for (unsigned int i = 0; i < count; i++)
  1.1024 +      {
  1.1025 +	if (!hb_set_next (glyphs, &g))
  1.1026 +	  break;
  1.1027 +	if (g < rangeRecord[i].start)
  1.1028 +	  return true;
  1.1029 +	g = rangeRecord[i].end;
  1.1030 +      }
  1.1031 +      if (g != (hb_codepoint_t) -1 && hb_set_next (glyphs, &g))
  1.1032 +        return true;
  1.1033 +      /* Fall through. */
  1.1034 +    }
  1.1035 +    for (unsigned int i = 0; i < count; i++)
  1.1036 +      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
  1.1037 +        return true;
  1.1038 +    return false;
  1.1039 +  }
  1.1040 +
  1.1041 +  protected:
  1.1042 +  USHORT	classFormat;	/* Format identifier--format = 2 */
  1.1043 +  SortedArrayOf<RangeRecord>
  1.1044 +		rangeRecord;	/* Array of glyph ranges--ordered by
  1.1045 +				 * Start GlyphID */
  1.1046 +  public:
  1.1047 +  DEFINE_SIZE_ARRAY (4, rangeRecord);
  1.1048 +};
  1.1049 +
  1.1050 +struct ClassDef
  1.1051 +{
  1.1052 +  inline unsigned int get_class (hb_codepoint_t glyph_id) const
  1.1053 +  {
  1.1054 +    switch (u.format) {
  1.1055 +    case 1: return u.format1.get_class(glyph_id);
  1.1056 +    case 2: return u.format2.get_class(glyph_id);
  1.1057 +    default:return 0;
  1.1058 +    }
  1.1059 +  }
  1.1060 +
  1.1061 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1062 +    TRACE_SANITIZE (this);
  1.1063 +    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
  1.1064 +    switch (u.format) {
  1.1065 +    case 1: return TRACE_RETURN (u.format1.sanitize (c));
  1.1066 +    case 2: return TRACE_RETURN (u.format2.sanitize (c));
  1.1067 +    default:return TRACE_RETURN (true);
  1.1068 +    }
  1.1069 +  }
  1.1070 +
  1.1071 +  inline void add_class (hb_set_t *glyphs, unsigned int klass) const {
  1.1072 +    switch (u.format) {
  1.1073 +    case 1: u.format1.add_class (glyphs, klass); return;
  1.1074 +    case 2: u.format2.add_class (glyphs, klass); return;
  1.1075 +    default:return;
  1.1076 +    }
  1.1077 +  }
  1.1078 +
  1.1079 +  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
  1.1080 +    switch (u.format) {
  1.1081 +    case 1: return u.format1.intersects_class (glyphs, klass);
  1.1082 +    case 2: return u.format2.intersects_class (glyphs, klass);
  1.1083 +    default:return false;
  1.1084 +    }
  1.1085 +  }
  1.1086 +
  1.1087 +  protected:
  1.1088 +  union {
  1.1089 +  USHORT		format;		/* Format identifier */
  1.1090 +  ClassDefFormat1	format1;
  1.1091 +  ClassDefFormat2	format2;
  1.1092 +  } u;
  1.1093 +  public:
  1.1094 +  DEFINE_SIZE_UNION (2, format);
  1.1095 +};
  1.1096 +
  1.1097 +
  1.1098 +/*
  1.1099 + * Device Tables
  1.1100 + */
  1.1101 +
  1.1102 +struct Device
  1.1103 +{
  1.1104 +
  1.1105 +  inline hb_position_t get_x_delta (hb_font_t *font) const
  1.1106 +  { return get_delta (font->x_ppem, font->x_scale); }
  1.1107 +
  1.1108 +  inline hb_position_t get_y_delta (hb_font_t *font) const
  1.1109 +  { return get_delta (font->y_ppem, font->y_scale); }
  1.1110 +
  1.1111 +  inline int get_delta (unsigned int ppem, int scale) const
  1.1112 +  {
  1.1113 +    if (!ppem) return 0;
  1.1114 +
  1.1115 +    int pixels = get_delta_pixels (ppem);
  1.1116 +
  1.1117 +    if (!pixels) return 0;
  1.1118 +
  1.1119 +    return (int) (pixels * (int64_t) scale / ppem);
  1.1120 +  }
  1.1121 +
  1.1122 +
  1.1123 +  inline int get_delta_pixels (unsigned int ppem_size) const
  1.1124 +  {
  1.1125 +    unsigned int f = deltaFormat;
  1.1126 +    if (unlikely (f < 1 || f > 3))
  1.1127 +      return 0;
  1.1128 +
  1.1129 +    if (ppem_size < startSize || ppem_size > endSize)
  1.1130 +      return 0;
  1.1131 +
  1.1132 +    unsigned int s = ppem_size - startSize;
  1.1133 +
  1.1134 +    unsigned int byte = deltaValue[s >> (4 - f)];
  1.1135 +    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
  1.1136 +    unsigned int mask = (0xFFFF >> (16 - (1 << f)));
  1.1137 +
  1.1138 +    int delta = bits & mask;
  1.1139 +
  1.1140 +    if ((unsigned int) delta >= ((mask + 1) >> 1))
  1.1141 +      delta -= mask + 1;
  1.1142 +
  1.1143 +    return delta;
  1.1144 +  }
  1.1145 +
  1.1146 +  inline unsigned int get_size (void) const
  1.1147 +  {
  1.1148 +    unsigned int f = deltaFormat;
  1.1149 +    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
  1.1150 +    return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
  1.1151 +  }
  1.1152 +
  1.1153 +  inline bool sanitize (hb_sanitize_context_t *c) {
  1.1154 +    TRACE_SANITIZE (this);
  1.1155 +    return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
  1.1156 +  }
  1.1157 +
  1.1158 +  protected:
  1.1159 +  USHORT	startSize;		/* Smallest size to correct--in ppem */
  1.1160 +  USHORT	endSize;		/* Largest size to correct--in ppem */
  1.1161 +  USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
  1.1162 +					 * 1	Signed 2-bit value, 8 values per uint16
  1.1163 +					 * 2	Signed 4-bit value, 4 values per uint16
  1.1164 +					 * 3	Signed 8-bit value, 2 values per uint16
  1.1165 +					 */
  1.1166 +  USHORT	deltaValue[VAR];	/* Array of compressed data */
  1.1167 +  public:
  1.1168 +  DEFINE_SIZE_ARRAY (6, deltaValue);
  1.1169 +};
  1.1170 +
  1.1171 +
  1.1172 +} /* namespace OT */
  1.1173 +
  1.1174 +
  1.1175 +#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */

mercurial