hb-ot-layout-common-private.hh revision c755cb3e3ac55156d0d2ec05adea7a650b97cc41
16f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
26f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Copyright (C) 2007,2008,2009  Red Hat, Inc.
36f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
4c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
56f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
66f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Permission is hereby granted, without written agreement and without
76f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
86f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * software and its documentation for any purpose, provided that the
96f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * above copyright notice and the following two paragraphs appear in
106f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * all copies of this software.
116f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
146f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * DAMAGE.
176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
206f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
226f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
236f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
256f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
266f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
275f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
285f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
296f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
302098a021a826e76ee27d5db74e32738d7d1c3d30Behdad Esfahbod#include "hb-ot-layout-private.h"
312098a021a826e76ee27d5db74e32738d7d1c3d30Behdad Esfahbod
327edb430f9182723b7b720708c56088cec1200a70Behdad Esfahbod#include "hb-open-type-private.hh"
336f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
346f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
35cd33cb9ed84308da72bd7c64b9355dc2410c63ecBehdad Esfahbod#define NO_CONTEXT		((unsigned int) 0x110000)
36cd33cb9ed84308da72bd7c64b9355dc2410c63ecBehdad Esfahbod#define NOT_COVERED		((unsigned int) 0x110000)
37cd33cb9ed84308da72bd7c64b9355dc2410c63ecBehdad Esfahbod#define MAX_NESTING_LEVEL	8
38cd33cb9ed84308da72bd7c64b9355dc2410c63ecBehdad Esfahbod
39cd33cb9ed84308da72bd7c64b9355dc2410c63ecBehdad Esfahbod
406f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
416f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
426f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * OpenType Layout Common Table Formats
436f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod *
446f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
462e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod
476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
486f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
496f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
506f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
516f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtemplate <typename Type>
5260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Record
5360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
544b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  static inline unsigned int get_size () { return sizeof (Record<Type>); }
554b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod
5662c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF, void *base) {
573e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5862ed5850d9e0e0d0231889470d58e815420c21e5Behdad Esfahbod    return SANITIZE (tag) && SANITIZE_BASE (offset, base);
59cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
60cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
616f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  Tag		tag;		/* 4-byte Tag identifier */
626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  OffsetTo<Type>
636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		offset;		/* Offset from beginning of object holding
646f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * the Record */
656f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
666f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
676f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtemplate <typename Type>
68bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodstruct RecordArrayOf : ArrayOf<Record<Type> > {
6960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Tag& get_tag (unsigned int i) const
7060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (HB_UNLIKELY (i >= this->len)) return Null(Tag);
72d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod    return (*this)[i].tag;
736f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
74e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_tags (unsigned int start_offset,
75e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int *record_count /* IN/OUT */,
76e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				hb_tag_t     *record_tags /* OUT */) const
77bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
78e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    if (record_count) {
7948de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      const Record<Type> *array = this->const_sub_array (start_offset, record_count);
8048de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      unsigned int count = *record_count;
81e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod      for (unsigned int i = 0; i < count; i++)
82e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod	record_tags[i] = array[i].tag;
83e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    }
84e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    return this->len;
85bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
86bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline bool find_index (hb_tag_t tag, unsigned int *index) const
87bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
88ffd321afd91429c5de7ab03d71ef1030044f53cbBehdad Esfahbod    Tag t;
89ffd321afd91429c5de7ab03d71ef1030044f53cbBehdad Esfahbod    t.set (tag);
90bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    // TODO bsearch
912cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    const Record<Type> *a = this->array();
92bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    unsigned int count = this->len;
93bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
94bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    {
95d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (t == a[i].tag)
96bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod      {
97bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod        if (index) *index = i;
98bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod        return true;
99bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod      }
100bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    }
101bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    if (index) *index = NO_INDEX;
102bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    return false;
103bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
104bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod};
105bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
106bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodtemplate <typename Type>
107bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodstruct RecordListOf : RecordArrayOf<Type>
108bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod{
109bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
1106bec81aa3a58b8be255568b2ea63b7854e1b0ea7Behdad Esfahbod  { return this+RecordArrayOf<Type>::operator [](i).offset; }
111cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
112cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
1133e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
11462c0fd75737a69721dbf29e773405a4c529f8b6dBehdad Esfahbod    return RecordArrayOf<Type>::sanitize (SANITIZE_ARG, CharP(this));
115cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
1166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
1176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
1186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
119bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodstruct IndexArray : ArrayOf<USHORT>
120bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod{
121bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int operator [] (unsigned int i) const
122bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
123bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    if (HB_UNLIKELY (i >= this->len))
124bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod      return NO_INDEX;
1252cb08458f674301cde9d962c13911035a251f7c5Behdad Esfahbod    return this->array()[i];
126bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
127e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_indexes (unsigned int start_offset,
128e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				   unsigned int *_count /* IN/OUT */,
129e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				   unsigned int *_indexes /* OUT */) const
130bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
131e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    if (_count) {
13248de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      const USHORT *array = this->const_sub_array (start_offset, _count);
13348de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      unsigned int count = *_count;
134e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod      for (unsigned int i = 0; i < count; i++)
135e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod	_indexes[i] = array[i];
136e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    }
137e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    return this->len;
138bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
139bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod};
140bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
141bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
1426f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodstruct Script;
1436f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodstruct LangSys;
1446f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodstruct Feature;
1456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
1466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
14760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct LangSys
14860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
149bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_feature_count (void) const
150bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return featureIndex.len; }
151bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline hb_tag_t get_feature_index (unsigned int i) const
152bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return featureIndex[i]; }
153e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_feature_indexes (unsigned int start_offset,
154e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
155e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */) const
156e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
1576f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
158cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
15960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline int get_required_feature_index (void) const
16060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1616f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (reqFeatureIndex == 0xffff)
1626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return NO_INDEX;
1636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod   return reqFeatureIndex;;
1646f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
1656f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
166cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
1673e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
168cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_SELF () && SANITIZE (featureIndex);
169cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
170cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
1716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  Offset	lookupOrder;	/* = Null (reserved for an offset to a
1726f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * reordering table) */
1736f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	reqFeatureIndex;/* Index of a feature required for this
1746f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * language system--if no required features
1756f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * = 0xFFFF */
176bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  IndexArray	featureIndex;	/* Array of indices into the FeatureList */
1776f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
17853d237ec6352d7c6fab3b2805b48154a25506bebBehdad EsfahbodASSERT_SIZE (LangSys, 6);
17953d237ec6352d7c6fab3b2805b48154a25506bebBehdad EsfahbodDEFINE_NULL_DATA (LangSys, 6, "\0\0\xFF\xFF");
1806f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
1816f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
18260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Script
18360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
184bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_lang_sys_count (void) const
185bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return langSys.len; }
186bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Tag& get_lang_sys_tag (unsigned int i) const
187bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return langSys.get_tag (i); }
188e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
189e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					 unsigned int *lang_sys_count /* IN/OUT */,
190e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					 hb_tag_t     *lang_sys_tags /* OUT */) const
191e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
19260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const LangSys& get_lang_sys (unsigned int i) const
19360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1946f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (i == NO_INDEX) return get_default_lang_sys ();
1956f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return this+langSys[i].offset;
1966f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
197bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
198bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return langSys.find_index (tag, index); }
1996f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
200cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
20160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
2026f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
203cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
2043e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
205cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_THIS (defaultLangSys) && SANITIZE_THIS (langSys);
206cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
207cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
2086f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
2096f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  OffsetTo<LangSys>
2106f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		defaultLangSys;	/* Offset to DefaultLangSys table--from
2116f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * beginning of Script table--may be Null */
212cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  RecordArrayOf<LangSys>
2136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		langSys;	/* Array of LangSysRecords--listed
2146f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * alphabetically by LangSysTag */
2156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (Script, 4);
2176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtypedef RecordListOf<Script> ScriptList;
2196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (ScriptList, 2);
2206f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
22260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Feature
22360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
224bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_lookup_count (void) const
225bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return lookupIndex.len; }
226bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline hb_tag_t get_lookup_index (unsigned int i) const
227bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return lookupIndex[i]; }
228e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_lookup_indexes (unsigned int start_index,
229e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					  unsigned int *lookup_count /* IN/OUT */,
230e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					  unsigned int *lookup_tags /* OUT */) const
231e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
2326f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
233cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
2343e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
235cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_SELF () && SANITIZE (lookupIndex);
236cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
237cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
2386f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  /* TODO: implement get_feature_parameters() */
2396f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  /* TODO: implement FeatureSize and other special features? */
2406f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  Offset	featureParams;	/* Offset to Feature Parameters table (if one
2416f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * has been defined for the feature), relative
2426f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * to the beginning of the Feature Table; = Null
2436f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * if not required */
244bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  IndexArray	 lookupIndex;	/* Array of LookupList indices */
2456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (Feature, 4);
2476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2486f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtypedef RecordListOf<Feature> FeatureList;
2496f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (FeatureList, 2);
2506f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2516f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
25260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct LookupFlag : USHORT
25360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
2544fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod  enum {
2554fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    RightToLeft		= 0x0001u,
2564fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    IgnoreBaseGlyphs	= 0x0002u,
2574fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    IgnoreLigatures	= 0x0004u,
2584fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    IgnoreMarks		= 0x0008u,
259aa87d951739f6beacb66daa235cd033fdcfcadd7Behdad Esfahbod    IgnoreFlags		= 0x000Eu,
260d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    UseMarkFilteringSet	= 0x0010u,
261d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    Reserved		= 0x00E0u,
2628f034d5849627ee95a5889fa34c9ba294fff13caBehdad Esfahbod    MarkAttachmentType	= 0xFF00u
2634fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod  };
2646f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2656f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (LookupFlag, 2);
2666f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
26760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct LookupSubTable
26860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
269cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
2703e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
271cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return SANITIZE_SELF ();
272cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
273cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
2746f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
2756f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	format;		/* Subtable format.  Different for GSUB and GPOS */
2766f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2776f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (LookupSubTable, 2);
2786f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
27960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Lookup
28060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
28160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const LookupSubTable& get_subtable (unsigned int i) const { return this+subTable[i]; }
28260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_subtable_count (void) const { return subTable.len; }
2836f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2846f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  inline unsigned int get_type (void) const { return lookupType; }
285d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  inline unsigned int get_flag (void) const
286d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  {
287d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    unsigned int flag = lookupFlag;
288d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    if (HB_UNLIKELY (flag & LookupFlag::UseMarkFilteringSet))
289d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    {
290e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
29109c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod      flag += (markFilteringSet << 16);
292d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    }
293d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    return flag;
294d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  }
2956f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
296cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
2973e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
298d6387757de2c27867d6f57c4ee7c4ef436b3a74fBehdad Esfahbod    if (!(SANITIZE (lookupType) && SANITIZE (lookupFlag) && SANITIZE_THIS (subTable))) return false;
299cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    if (HB_UNLIKELY (lookupFlag & LookupFlag::UseMarkFilteringSet))
300cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    {
301e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
302cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod      if (!SANITIZE (markFilteringSet)) return false;
303cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    }
304cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return true;
305cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
306cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
307d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
308d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  USHORT	lookupFlag;		/* Lookup qualifiers */
3096f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  OffsetArrayOf<LookupSubTable>
310d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod		subTable;		/* Array of SubTables */
311d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
312d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod					 * structure. This field is only present if bit
313d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod					 * UseMarkFilteringSet of lookup flags is set. */
3146f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
315d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad EsfahbodASSERT_SIZE_VAR (Lookup, 6, USHORT);
3166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtypedef OffsetListOf<Lookup> LookupList;
3186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (LookupList, 2);
3196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3206f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
3226f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Coverage Table
3236f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
3246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
32560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CoverageFormat1
32660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
3276f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct Coverage;
3286f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3296f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
33060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
33160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
3322e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod    if (HB_UNLIKELY (glyph_id > 0xFFFF))
3336f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return NOT_COVERED;
3342e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod    GlyphID gid;
335807b8aa486753474e05e09f4fcca8ac94021b97cBehdad Esfahbod    gid.set (glyph_id);
3366f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    // TODO: bsearch
3376f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    unsigned int num_glyphs = glyphArray.len;
3386f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    for (unsigned int i = 0; i < num_glyphs; i++)
3396f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      if (gid == glyphArray[i])
3406f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod        return i;
3416f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return NOT_COVERED;
3426f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
3436f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
34470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
3453e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
34670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    return SANITIZE (glyphArray);
34770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
34870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
34970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  private:
3506f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	coverageFormat;	/* Format identifier--format = 1 */
3516f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<GlyphID>
3526f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		glyphArray;	/* Array of GlyphIDs--in numerical order */
3536f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
3546f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (CoverageFormat1, 4);
3556f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
35660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CoverageRangeRecord
35760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
3586f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct CoverageFormat2;
3596f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3604b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  static inline unsigned int get_size () { return sizeof (CoverageRangeRecord); }
3614b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod
3626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
36360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
36460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
3656f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (glyph_id >= start && glyph_id <= end)
3662e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod      return (unsigned int) startCoverageIndex + (glyph_id - start);
3676f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return NOT_COVERED;
3686f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
3696f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
370cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  public:
37170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
3723e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
37370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    return SANITIZE_SELF ();
37470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
37570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
3766f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
3776f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	start;			/* First GlyphID in the range */
3786f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	end;			/* Last GlyphID in the range */
3796f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	startCoverageIndex;	/* Coverage Index of first GlyphID in
3806f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod					 * range */
3816f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
38253d237ec6352d7c6fab3b2805b48154a25506bebBehdad EsfahbodASSERT_SIZE (CoverageRangeRecord, 6);
38353d237ec6352d7c6fab3b2805b48154a25506bebBehdad EsfahbodDEFINE_NULL_DATA (CoverageRangeRecord, 6, "\000\001");
3846f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
38560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CoverageFormat2
38660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
3876f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct Coverage;
3886f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3896f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
39060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
39160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
3926f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    // TODO: bsearch
3936f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    unsigned int count = rangeRecord.len;
39460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
39560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    {
3962e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod      unsigned int coverage = rangeRecord[i].get_coverage (glyph_id);
3972e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod      if (coverage != NOT_COVERED)
3986f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod        return coverage;
3996f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
4006f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return NOT_COVERED;
4016f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4026f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
40370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
4043e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
40570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    return SANITIZE (rangeRecord);
40670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
40770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
40870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  private:
4096f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	coverageFormat;	/* Format identifier--format = 2 */
4106f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<CoverageRangeRecord>
4116f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		rangeRecord;	/* Array of glyph ranges--ordered by
4126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * Start GlyphID. rangeCount entries
4136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * long */
4146f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
4156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (CoverageFormat2, 4);
4166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
41760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Coverage
41860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
41900e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
42070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
42120b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
42260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4236f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    switch (u.format) {
4246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    case 1: return u.format1->get_coverage(glyph_id);
4256f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    case 2: return u.format2->get_coverage(glyph_id);
4266f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    default:return NOT_COVERED;
4276f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
4286f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4296f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
43020b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
4313e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
43270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    if (!SANITIZE (u.format)) return false;
43370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
43470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    case 1: return u.format1->sanitize (SANITIZE_ARG);
43570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    case 2: return u.format2->sanitize (SANITIZE_ARG);
43670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    default:return true;
43770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    }
43870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
4396f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4406f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
4416f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  union {
4426f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT		format;		/* Format identifier */
443d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  CoverageFormat1	format1[VAR];
444d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  CoverageFormat2	format2[VAR];
4456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  } u;
4466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
4476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4486f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4496f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
4506f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Class Definition Table
4516f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
4526f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
45360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassDefFormat1
45460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
4556f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct ClassDef;
4566f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4576f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
45860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
45960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4606f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if ((unsigned int) (glyph_id - startGlyph) < classValue.len)
4616f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return classValue[glyph_id - startGlyph];
4626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return 0;
4636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4646f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
46570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
4663e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
46770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    return SANITIZE_SELF () && SANITIZE (classValue);
46870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
46970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
4706f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	classFormat;		/* Format identifier--format = 1 */
4716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
4726f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<USHORT>
4736f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		classValue;		/* Array of Class Values--one per GlyphID */
4746f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
4756f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (ClassDefFormat1, 6);
4766f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
47760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassRangeRecord
47860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
4796f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct ClassDefFormat2;
4806f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4814b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod  static inline unsigned int get_size () { return sizeof (ClassRangeRecord); }
4824b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod
4836f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
48460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
48560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4866f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (glyph_id >= start && glyph_id <= end)
4876f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return classValue;
4886f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return 0;
4896f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4906f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
491cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  public:
49270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
4933e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
49470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    return SANITIZE_SELF ();
49570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
49670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
4976f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
4986f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	start;		/* First GlyphID in the range */
4996f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	end;		/* Last GlyphID in the range */
5006f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	classValue;	/* Applied to all glyphs in the range */
5016f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
50253d237ec6352d7c6fab3b2805b48154a25506bebBehdad EsfahbodASSERT_SIZE (ClassRangeRecord, 6);
50353d237ec6352d7c6fab3b2805b48154a25506bebBehdad EsfahbodDEFINE_NULL_DATA (ClassRangeRecord, 6, "\000\001");
5046f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
50560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassDefFormat2
50660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
5076f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct ClassDef;
5086f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
5096f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
51060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
51160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
5126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    // TODO: bsearch
5136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    unsigned int count = rangeRecord.len;
51460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
51560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    {
5166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      int classValue = rangeRecord[i].get_class (glyph_id);
5176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      if (classValue > 0)
5186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod        return classValue;
5196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
5206f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return 0;
5216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
5226f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
52370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
5243e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
52570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    return SANITIZE (rangeRecord);
52670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
52770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
5286f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	classFormat;	/* Format identifier--format = 2 */
5296f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<ClassRangeRecord>
5306f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		rangeRecord;	/* Array of glyph ranges--ordered by
5316f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * Start GlyphID */
5326f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
5336f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad EsfahbodASSERT_SIZE (ClassDefFormat2, 4);
5346f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
53560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassDef
53660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
53700e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline hb_ot_layout_class_t operator () (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
53870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
53920b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
54060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
5416f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    switch (u.format) {
5426f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    case 1: return u.format1->get_class(glyph_id);
5436f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    case 2: return u.format2->get_class(glyph_id);
5446f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    default:return 0;
5456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
5466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
5476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
54820b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
5493e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
55070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    if (!SANITIZE (u.format)) return false;
55170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
55270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    case 1: return u.format1->sanitize (SANITIZE_ARG);
55370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    case 2: return u.format2->sanitize (SANITIZE_ARG);
55470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    default:return true;
55570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    }
55670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
557aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
5586f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
5596f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  union {
5606f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT		format;		/* Format identifier */
561d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  ClassDefFormat1	format1[VAR];
562d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  ClassDefFormat2	format2[VAR];
5636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  } u;
5646f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
5656f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
5666f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
5676f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
5686f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Device Tables
5696f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
5706f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
57160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Device
57260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
57300e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline int operator () (unsigned int ppem_size) const { return get_delta (ppem_size); }
574dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod
57520b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline int get_delta (unsigned int ppem_size) const
57660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
577056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    unsigned int f = deltaFormat;
578056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    if (HB_UNLIKELY (f < 1 || f > 3))
579056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod      return 0;
5806f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
581056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    if (ppem_size < startSize || ppem_size > endSize)
582056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod      return 0;
5836f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
584056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    unsigned int s = ppem_size - startSize;
5856f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
586056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    unsigned int byte = deltaValue[s >> (4 - f)];
58709c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
58809c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod    unsigned int mask = (0xFFFF >> (16 - (1 << f)));
589056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
590056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    int delta = bits & mask;
591056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
59215164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod    if ((unsigned int) delta >= ((mask + 1) >> 1))
593056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod      delta -= mask + 1;
594056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
595056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    return delta;
596056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod  }
597056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
598dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  inline unsigned int get_size () const
599dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  {
600dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod    unsigned int f = deltaFormat;
6014b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod    if (HB_UNLIKELY (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::get_size ();
6024b8487d83e0c10076a6c573cb3487790ce366607Behdad Esfahbod    return 3 * USHORT::get_size () + ((endSize - startSize + (1 << (4 - f)) - 1) >> (4 - f));
603dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  }
604dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod
60520b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline bool sanitize (SANITIZE_ARG_DEF) {
6063e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
607dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod    return SANITIZE_GET_SIZE ();
608dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  }
6096f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
6106f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
6116f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	startSize;	/* Smallest size to correct--in ppem */
6126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	endSize;	/* Largest size to correct--in ppem */
6136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	deltaFormat;	/* Format of DeltaValue array data: 1, 2, or 3 */
614d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  USHORT	deltaValue[VAR];	/* Array of compressed data */
6156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
616d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad EsfahbodASSERT_SIZE_VAR (Device, 6, USHORT);
6176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
6186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
6195f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
620