hb-ot-layout-common-private.hh revision b961518b9611471ff7060e97686e5625974847eb
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{
5439840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context, void *base) {
553e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
56b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
5741a93d2c1ff175ef06328a99983577459c2d34b0Behdad Esfahbod	&& offset.sanitize (context, base);
58cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
59cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
606f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  Tag		tag;		/* 4-byte Tag identifier */
616f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  OffsetTo<Type>
626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		offset;		/* Offset from beginning of object holding
636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * the Record */
64569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
65569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  DEFINE_SIZE_STATIC (6);
666f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
676f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
686f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtemplate <typename Type>
69bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodstruct RecordArrayOf : ArrayOf<Record<Type> > {
7060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const Tag& get_tag (unsigned int i) const
7160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
7264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= this->len)) return Null(Tag);
73d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod    return (*this)[i].tag;
746f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
75e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_tags (unsigned int start_offset,
76e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int *record_count /* IN/OUT */,
77e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				hb_tag_t     *record_tags /* OUT */) const
78bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
79e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    if (record_count) {
804f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod      const Record<Type> *array = this->sub_array (start_offset, record_count);
8148de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      unsigned int count = *record_count;
82e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod      for (unsigned int i = 0; i < count; i++)
83e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod	record_tags[i] = array[i].tag;
84e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    }
85e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    return this->len;
86bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
87bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline bool find_index (hb_tag_t tag, unsigned int *index) const
88bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
89ffd321afd91429c5de7ab03d71ef1030044f53cbBehdad Esfahbod    Tag t;
90ffd321afd91429c5de7ab03d71ef1030044f53cbBehdad Esfahbod    t.set (tag);
91f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod    /* TODO: bsearch (need to sort in sanitize) */
92b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    const Record<Type> *a = this->array;
93bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    unsigned int count = this->len;
94bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
95bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    {
96d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod      if (t == a[i].tag)
97bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod      {
98bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod        if (index) *index = i;
99bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod        return true;
100bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod      }
101bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    }
102bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    if (index) *index = NO_INDEX;
103bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod    return false;
104bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
105bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod};
106bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
107bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodtemplate <typename Type>
108bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodstruct RecordListOf : RecordArrayOf<Type>
109bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod{
110bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Type& operator [] (unsigned int i) const
1116bec81aa3a58b8be255568b2ea63b7854e1b0ea7Behdad Esfahbod  { return this+RecordArrayOf<Type>::operator [](i).offset; }
112cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
11339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
1143e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
11540cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod    return RecordArrayOf<Type>::sanitize (context, this);
116cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
1176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
1186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
1196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
120bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodstruct IndexArray : ArrayOf<USHORT>
121bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod{
122bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int operator [] (unsigned int i) const
123bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
12464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (i >= this->len))
125bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod      return NO_INDEX;
126b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return this->array[i];
127bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
128e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_indexes (unsigned int start_offset,
129e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				   unsigned int *_count /* IN/OUT */,
130e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				   unsigned int *_indexes /* OUT */) const
131bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  {
132e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    if (_count) {
1334f5f1c34dda1e0629bfa6d7b0ffa2e1ce003b7c7Behdad Esfahbod      const USHORT *array = this->sub_array (start_offset, _count);
13448de3730cdf91b9f6473509e22260a902ccec992Behdad Esfahbod      unsigned int count = *_count;
135e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod      for (unsigned int i = 0; i < count; i++)
136e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod	_indexes[i] = array[i];
137e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    }
138e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod    return this->len;
139bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  }
140bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod};
141bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
142bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
1436f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodstruct Script;
1446f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodstruct LangSys;
1456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodstruct Feature;
1466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
1476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
14860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct LangSys
14960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
150bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_feature_count (void) const
151bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return featureIndex.len; }
152bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline hb_tag_t get_feature_index (unsigned int i) const
153bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return featureIndex[i]; }
154e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_feature_indexes (unsigned int start_offset,
155e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
156e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */) const
157e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
1586f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
159cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
16060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline int get_required_feature_index (void) const
16160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (reqFeatureIndex == 0xffff)
1636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return NO_INDEX;
1646f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod   return reqFeatureIndex;;
1656f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
1666f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
16739840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
1683e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
169b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
1704f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod	&& featureIndex.sanitize (context);
171cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
172cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
1736f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  Offset	lookupOrder;	/* = Null (reserved for an offset to a
1746f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * reordering table) */
1756f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	reqFeatureIndex;/* Index of a feature required for this
1766f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * language system--if no required features
1776f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * = 0xFFFF */
178bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  IndexArray	featureIndex;	/* Array of indices into the FeatureList */
179569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
180bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (6, USHORT);
1816f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
18265f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
1836f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
1846f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
18560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Script
18660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
187bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_lang_sys_count (void) const
188bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return langSys.len; }
189bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Tag& get_lang_sys_tag (unsigned int i) const
190bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return langSys.get_tag (i); }
191e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
192e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					 unsigned int *lang_sys_count /* IN/OUT */,
193e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					 hb_tag_t     *lang_sys_tags /* OUT */) const
194e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
19560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const LangSys& get_lang_sys (unsigned int i) const
19660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1976f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (i == NO_INDEX) return get_default_lang_sys ();
1986f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return this+langSys[i].offset;
1996f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
200bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
201bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return langSys.find_index (tag, index); }
2026f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
203cc6c644ff2af5f6669b6ec100ff13e904872b21cBehdad Esfahbod  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
20460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
2056f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
20639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
2073e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
20841a93d2c1ff175ef06328a99983577459c2d34b0Behdad Esfahbod    return defaultLangSys.sanitize (context, this)
20941a93d2c1ff175ef06328a99983577459c2d34b0Behdad Esfahbod	&& langSys.sanitize (context, this);
210cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
211cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
2126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
2136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  OffsetTo<LangSys>
2146f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		defaultLangSys;	/* Offset to DefaultLangSys table--from
2156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * beginning of Script table--may be Null */
216cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  RecordArrayOf<LangSys>
2176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		langSys;	/* Array of LangSysRecords--listed
2186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * alphabetically by LangSysTag */
219b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
220bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (4, Record<LangSys>);
2216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2226f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2236f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtypedef RecordListOf<Script> ScriptList;
2246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2256f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
22660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Feature
22760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
228bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_lookup_count (void) const
229bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return lookupIndex.len; }
230bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline hb_tag_t get_lookup_index (unsigned int i) const
231bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return lookupIndex[i]; }
232e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_lookup_indexes (unsigned int start_index,
233e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					  unsigned int *lookup_count /* IN/OUT */,
234e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					  unsigned int *lookup_tags /* OUT */) const
235e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
2366f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
23739840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
2383e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
239b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
2404f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod	&& lookupIndex.sanitize (context);
241cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
242cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
243f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod  /* LONGTERMTODO: implement get_feature_parameters() */
244f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod  /* LONGTERMTODO: implement FeatureSize and other special features? */
2456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  Offset	featureParams;	/* Offset to Feature Parameters table (if one
2466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * has been defined for the feature), relative
2476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * to the beginning of the Feature Table; = Null
2486f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * if not required */
249bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  IndexArray	 lookupIndex;	/* Array of LookupList indices */
250b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
251bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (4, USHORT);
2526f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2536f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2546f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtypedef RecordListOf<Feature> FeatureList;
2556f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2566f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
25760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct LookupFlag : USHORT
25860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
2594fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod  enum {
2604fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    RightToLeft		= 0x0001u,
2614fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    IgnoreBaseGlyphs	= 0x0002u,
2624fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    IgnoreLigatures	= 0x0004u,
2634fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod    IgnoreMarks		= 0x0008u,
264aa87d951739f6beacb66daa235cd033fdcfcadd7Behdad Esfahbod    IgnoreFlags		= 0x000Eu,
265d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    UseMarkFilteringSet	= 0x0010u,
266d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    Reserved		= 0x00E0u,
2678f034d5849627ee95a5889fa34c9ba294fff13caBehdad Esfahbod    MarkAttachmentType	= 0xFF00u
2684fa77d3c4305a76b956de8c1a9b83a961d035a80Behdad Esfahbod  };
269b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
270b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (2);
2716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
2726f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
27360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Lookup
27460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
27560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_subtable_count (void) const { return subTable.len; }
2766f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
2776f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  inline unsigned int get_type (void) const { return lookupType; }
278d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  inline unsigned int get_flag (void) const
279d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  {
280d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    unsigned int flag = lookupFlag;
28164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
282d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    {
283e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
28409c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod      flag += (markFilteringSet << 16);
285d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    }
286d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod    return flag;
287d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  }
2886f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
28939840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
2903e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
2913b2c2df41b90f2a1d9e33b3dc15a92cff58a689aBehdad Esfahbod    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
292b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    if (!(context->check_struct (this)
293583d7f9586ce69754f1354aa3895e6d732a0c2ceBehdad Esfahbod       && likely (subTable.sanitize (context)))) return false;
29464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet))
295cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    {
296e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
2974f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod      if (!markFilteringSet.sanitize (context)) return false;
298cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    }
299cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod    return true;
300cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
301cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
302d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
303d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod  USHORT	lookupFlag;		/* Lookup qualifiers */
3043b2c2df41b90f2a1d9e33b3dc15a92cff58a689aBehdad Esfahbod  ArrayOf<Offset>
305d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod		subTable;		/* Array of SubTables */
306d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
307d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod					 * structure. This field is only present if bit
308d7df42d7ee586219475878d160f85ae5a188bd59Behdad Esfahbod					 * UseMarkFilteringSet of lookup flags is set. */
309569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
310bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR2 (6, Offset, USHORT);
3116f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
3126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbodtypedef OffsetListOf<Lookup> LookupList;
3146f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
3176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Coverage Table
3186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
3196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
32060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CoverageFormat1
32160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
3226f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct Coverage;
3236f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
32560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
32660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
32764d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (glyph_id > 0xFFFF))
3286f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return NOT_COVERED;
3292e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod    GlyphID gid;
330807b8aa486753474e05e09f4fcca8ac94021b97cBehdad Esfahbod    gid.set (glyph_id);
331f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod    /* TODO: bsearch (need to sort in sanitize) */
3326f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    unsigned int num_glyphs = glyphArray.len;
3336f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    for (unsigned int i = 0; i < num_glyphs; i++)
3346f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      if (gid == glyphArray[i])
3356f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod        return i;
3366f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return NOT_COVERED;
3376f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
3386f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
33939840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
3403e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
3414f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod    return glyphArray.sanitize (context);
34270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
34370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
34470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  private:
3456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	coverageFormat;	/* Format identifier--format = 1 */
3466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<GlyphID>
3476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		glyphArray;	/* Array of GlyphIDs--in numerical order */
348b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
349bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (4, GlyphID);
3506f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
3516f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
35260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CoverageRangeRecord
35360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
3546f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct CoverageFormat2;
3556f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3566f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
35760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
35860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
3596f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (glyph_id >= start && glyph_id <= end)
3602e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod      return (unsigned int) startCoverageIndex + (glyph_id - start);
3616f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return NOT_COVERED;
3626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
3636f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
364cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  public:
36539840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
3663e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
367b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this);
36870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
36970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
3706f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
3716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	start;			/* First GlyphID in the range */
3726f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	end;			/* Last GlyphID in the range */
3736f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	startCoverageIndex;	/* Coverage Index of first GlyphID in
3746f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod					 * range */
375569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
376569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  DEFINE_SIZE_STATIC (6);
3776f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
37865f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (CoverageRangeRecord, "\000\001");
3796f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
38060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct CoverageFormat2
38160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
3826f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct Coverage;
3836f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
3846f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
38560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
38660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
387f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod    /* TODO: bsearch (need to sort in sanitize) */
3886f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    unsigned int count = rangeRecord.len;
38960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
39060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    {
3912e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod      unsigned int coverage = rangeRecord[i].get_coverage (glyph_id);
3922e8fb6c38dbc01cb77b384c0ae0212514dfbb588Behdad Esfahbod      if (coverage != NOT_COVERED)
3936f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod        return coverage;
3946f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
3956f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return NOT_COVERED;
3966f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
3976f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
39839840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
3993e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
4004f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod    return rangeRecord.sanitize (context);
40170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
40270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
40370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  private:
4046f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	coverageFormat;	/* Format identifier--format = 2 */
4056f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<CoverageRangeRecord>
4066f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		rangeRecord;	/* Array of glyph ranges--ordered by
4076f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * Start GlyphID. rangeCount entries
4086f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * long */
409b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
410bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (4, CoverageRangeRecord);
4116f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
4126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
41360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Coverage
41460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
41500e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
41670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
41720b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
41860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    switch (u.format) {
4206f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    case 1: return u.format1->get_coverage(glyph_id);
4216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    case 2: return u.format2->get_coverage(glyph_id);
4226f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    default:return NOT_COVERED;
4236f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
4246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4256f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
42639840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
4273e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
4284f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod    if (!u.format.sanitize (context)) return false;
42970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
43039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    case 1: return u.format1->sanitize (context);
43139840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    case 2: return u.format2->sanitize (context);
43270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    default:return true;
43370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    }
43470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
4356f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4366f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
4376f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  union {
4386f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT		format;		/* Format identifier */
439d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  CoverageFormat1	format1[VAR];
440d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  CoverageFormat2	format2[VAR];
4416f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  } u;
442ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  public:
443ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  DEFINE_SIZE_MIN (2);
4446f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
4456f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4466f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4476f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
4486f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Class Definition Table
4496f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
4506f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
45160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassDefFormat1
45260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
4536f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct ClassDef;
4546f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4556f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
45660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
45760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4586f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if ((unsigned int) (glyph_id - startGlyph) < classValue.len)
4596f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return classValue[glyph_id - startGlyph];
4606f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return 0;
4616f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4626f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
46339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
4643e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
465b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
4664f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod	&& classValue.sanitize (context);
46770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
46870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
4696f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	classFormat;		/* Format identifier--format = 1 */
4706f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
4716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<USHORT>
4726f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		classValue;		/* Array of Class Values--one per GlyphID */
473b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
474bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (6, USHORT);
4756f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
4766f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
47760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassRangeRecord
47860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
4796f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct ClassDefFormat2;
4806f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
4816f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
48260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
48360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
4846f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    if (glyph_id >= start && glyph_id <= end)
4856f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      return classValue;
4866f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return 0;
4876f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
4886f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
489cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  public:
49039840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
4913e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
492b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this);
49370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
49470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
4956f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
4966f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	start;		/* First GlyphID in the range */
4976f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  GlyphID	end;		/* Last GlyphID in the range */
4986f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	classValue;	/* Applied to all glyphs in the range */
499569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
500569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  DEFINE_SIZE_STATIC (6);
5016f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
50265f46b00333e20ab8a52a4b350747507541ec1dbBehdad EsfahbodDEFINE_NULL_DATA (ClassRangeRecord, "\000\001");
5036f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
50460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ClassDefFormat2
50560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
5066f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  friend struct ClassDef;
5076f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
5086f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
50960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
51060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
511f1aaa2a43654c28405ffd393de2cb127437c99a5Behdad Esfahbod    /* TODO: bsearch (need to sort in sanitize) */
5126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    unsigned int count = rangeRecord.len;
51360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
51460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    {
5156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      int classValue = rangeRecord[i].get_class (glyph_id);
5166f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod      if (classValue > 0)
5176f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod        return classValue;
5186f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    }
5196f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod    return 0;
5206f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  }
5216f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
52239840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
5233e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5244f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod    return rangeRecord.sanitize (context);
52570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
52670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
5276f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  USHORT	classFormat;	/* Format identifier--format = 2 */
5286f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  ArrayOf<ClassRangeRecord>
5296f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod		rangeRecord;	/* Array of glyph ranges--ordered by
5306f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod				 * Start GlyphID */
531b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
532bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_VAR (4, ClassRangeRecord);
5336f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
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
54839840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
5493e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
5504f252fedc7136c66a9d7fbcb2978581986da6227Behdad Esfahbod    if (!u.format.sanitize (context)) return false;
55170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
55239840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    case 1: return u.format1->sanitize (context);
55339840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod    case 2: return u.format2->sanitize (context);
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;
564ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  public:
565ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  DEFINE_SIZE_MIN (2);
5666f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
5676f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
5686f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
5696f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod/*
5706f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod * Device Tables
5716f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod */
5726f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
57360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Device
57460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
57500e23fcc6fd0eee5c582251bf3de6a2703fbbd3eBehdad Esfahbod  inline int operator () (unsigned int ppem_size) const { return get_delta (ppem_size); }
576dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod
57720b035dad41247076815a2bbb0346d63058b322fBehdad Esfahbod  inline int get_delta (unsigned int ppem_size) const
57860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
579056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    unsigned int f = deltaFormat;
58064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (f < 1 || f > 3))
581056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod      return 0;
5826f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
583056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    if (ppem_size < startSize || ppem_size > endSize)
584056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod      return 0;
5856f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
586056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    unsigned int s = ppem_size - startSize;
5876f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
588056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    unsigned int byte = deltaValue[s >> (4 - f)];
58909c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
59009c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod    unsigned int mask = (0xFFFF >> (16 - (1 << f)));
591056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
592056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    int delta = bits & mask;
593056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
59415164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod    if ((unsigned int) delta >= ((mask + 1) >> 1))
595056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod      delta -= mask + 1;
596056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
597056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod    return delta;
598056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod  }
599056c7ec1aea1eca60a3b20b583b8a8072be9d758Behdad Esfahbod
600dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  inline unsigned int get_size () const
601dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  {
602dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod    unsigned int f = deltaFormat;
603b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
604b961518b9611471ff7060e97686e5625974847ebBehdad Esfahbod    return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
605dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  }
606dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod
60739840474afd2cda9ff576c08aff9c87095496c27Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *context) {
6083e2401f6c53d2b047954d75c37aef5e5e7cdc51aBehdad Esfahbod    TRACE_SANITIZE ();
609b157617644d1e38f680163889d1dc2e2f64d9ba3Behdad Esfahbod    return context->check_struct (this)
610f5fab0c71837371cce32dc3e9edca1ccb8d44e29Behdad Esfahbod	&& context->check_range (this, this->get_size ());
611dc9c4d93cd0f3ac991f32df08c1c17fc389054c0Behdad Esfahbod  }
6126f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
6136f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod  private:
6140795b784dd1009976c185482a376df250167e73bBehdad Esfahbod  USHORT	startSize;		/* Smallest size to correct--in ppem */
6150795b784dd1009976c185482a376df250167e73bBehdad Esfahbod  USHORT	endSize;		/* Largest size to correct--in ppem */
616caff7db93d205e32a535d49e51a3cad70f91dfddBehdad Esfahbod  USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
617caff7db93d205e32a535d49e51a3cad70f91dfddBehdad Esfahbod					 * 1	Signed 2-bit value, 8 values per uint16
618caff7db93d205e32a535d49e51a3cad70f91dfddBehdad Esfahbod					 * 2	Signed 4-bit value, 4 values per uint16
619caff7db93d205e32a535d49e51a3cad70f91dfddBehdad Esfahbod					 * 3	Signed 8-bit value, 2 values per uint16
620caff7db93d205e32a535d49e51a3cad70f91dfddBehdad Esfahbod					 */
621d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  USHORT	deltaValue[VAR];	/* Array of compressed data */
622569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
623569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  DEFINE_SIZE_VAR (6, USHORT);
6246f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod};
6256f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
6266f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
6275f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
628