blob: f5a067aec9d21315b6a39afa0a7ccc15a3e36e86 [file] [log] [blame]
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04001/*
Behdad Esfahbod2409d5f2011-04-21 17:14:28 -04002 * Copyright © 2007,2008,2009 Red Hat, Inc.
Behdad Esfahbod5b93e8d2012-04-23 22:26:13 -04003 * Copyright © 2010,2012 Google, Inc.
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04004 *
Behdad Esfahbodc755cb32010-04-22 00:11:43 -04005 * This is part of HarfBuzz, a text shaping library.
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04006 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
Behdad Esfahbod5bd1e952010-09-22 16:46:18 -040026 * Google Author(s): Behdad Esfahbod
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040027 */
28
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -040029#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
30#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040031
Behdad Esfahbod22da7fd2010-05-12 18:23:21 -040032#include "hb-ot-layout-private.hh"
Behdad Esfahbod7edb4302009-08-04 22:06:57 -040033#include "hb-open-type-private.hh"
Behdad Esfahbod0b08adb2012-04-23 22:41:09 -040034#include "hb-set-private.hh"
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040035
36
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -040037namespace OT {
38
39
Behdad Esfahboddadede02012-07-28 18:03:20 -040040#define NOT_COVERED ((unsigned int) -1)
Behdad Esfahbodcd33cb92009-08-14 18:42:42 -040041#define MAX_NESTING_LEVEL 8
42
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040043
Behdad Esfahbodcd33cb92009-08-14 18:42:42 -040044
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040045/*
46 *
47 * OpenType Layout Common Table Formats
48 *
49 */
50
Behdad Esfahbod2e8fb6c2009-05-18 04:37:37 -040051
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040052/*
53 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
54 */
55
56template <typename Type>
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -040057struct Record
58{
Behdad Esfahbod4e573712010-09-28 16:23:58 -040059 inline int cmp (hb_tag_t a) const {
Behdad Esfahbod36b38622010-09-29 12:10:24 -040060 return tag.cmp (a);
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -040061 }
62
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -040063 inline bool sanitize (hb_sanitize_context_t *c, void *base) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -040064 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +020065 return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -040066 }
67
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040068 Tag tag; /* 4-byte Tag identifier */
69 OffsetTo<Type>
70 offset; /* Offset from beginning of object holding
71 * the Record */
Behdad Esfahbod569da922010-05-10 16:38:32 -040072 public:
73 DEFINE_SIZE_STATIC (6);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040074};
75
76template <typename Type>
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -040077struct RecordArrayOf : SortedArrayOf<Record<Type> > {
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -040078 inline const Tag& get_tag (unsigned int i) const
79 {
Behdad Esfahbod4e22c7e2010-11-03 15:47:12 -040080 /* We cheat slightly and don't define separate Null objects
81 * for Record types. Instead, we return the correct Null(Tag)
82 * here. */
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -040083 if (unlikely (i >= this->len)) return Null(Tag);
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -050084 return (*this)[i].tag;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -040085 }
Behdad Esfahbode21899b2009-11-04 16:36:14 -050086 inline unsigned int get_tags (unsigned int start_offset,
87 unsigned int *record_count /* IN/OUT */,
88 hb_tag_t *record_tags /* OUT */) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -040089 {
Behdad Esfahbode21899b2009-11-04 16:36:14 -050090 if (record_count) {
Behdad Esfahbod31f18ab2011-06-15 09:49:58 -040091 const Record<Type> *arr = this->sub_array (start_offset, record_count);
Behdad Esfahbod48de3732009-11-04 16:59:50 -050092 unsigned int count = *record_count;
Behdad Esfahbode21899b2009-11-04 16:36:14 -050093 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod31f18ab2011-06-15 09:49:58 -040094 record_tags[i] = arr[i].tag;
Behdad Esfahbode21899b2009-11-04 16:36:14 -050095 }
96 return this->len;
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -040097 }
98 inline bool find_index (hb_tag_t tag, unsigned int *index) const
99 {
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400100 int i = this->search (tag);
101 if (i != -1) {
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400102 if (index) *index = i;
103 return true;
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400104 } else {
105 if (index) *index = Index::NOT_FOUND_INDEX;
106 return false;
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400107 }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400108 }
109};
110
111template <typename Type>
112struct RecordListOf : RecordArrayOf<Type>
113{
114 inline const Type& operator [] (unsigned int i) const
Behdad Esfahbod6bec81a2009-11-02 19:17:36 -0500115 { return this+RecordArrayOf<Type>::operator [](i).offset; }
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400116
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400117 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400118 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200119 return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400120 }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400121};
122
123
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400124struct RangeRecord
125{
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400126 inline int cmp (hb_codepoint_t g) const {
127 hb_codepoint_t a = start, b = end;
128 return g < a ? -1 : g <= b ? 0 : +1 ;
129 }
130
131 inline bool sanitize (hb_sanitize_context_t *c) {
132 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200133 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400134 }
135
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400136 inline bool intersects (const hb_set_t *glyphs) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400137 return glyphs->intersects (start, end);
138 }
139
Behdad Esfahbodc8accf12012-08-01 21:05:57 -0400140 template <typename set_t>
141 inline void add_coverage (set_t *glyphs) const {
Behdad Esfahbod67bb9e82012-06-09 02:02:46 -0400142 glyphs->add_range (start, end);
143 }
144
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400145 GlyphID start; /* First GlyphID in the range */
146 GlyphID end; /* Last GlyphID in the range */
147 USHORT value; /* Value */
148 public:
149 DEFINE_SIZE_STATIC (6);
150};
151DEFINE_NULL_DATA (RangeRecord, "\000\001");
152
153
Behdad Esfahbodb5db4f12010-05-10 22:22:22 -0400154struct IndexArray : ArrayOf<Index>
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400155{
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500156 inline unsigned int get_indexes (unsigned int start_offset,
157 unsigned int *_count /* IN/OUT */,
158 unsigned int *_indexes /* OUT */) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400159 {
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500160 if (_count) {
Behdad Esfahbod31f18ab2011-06-15 09:49:58 -0400161 const USHORT *arr = this->sub_array (start_offset, _count);
Behdad Esfahbod48de3732009-11-04 16:59:50 -0500162 unsigned int count = *_count;
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500163 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod31f18ab2011-06-15 09:49:58 -0400164 _indexes[i] = arr[i];
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500165 }
166 return this->len;
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400167 }
168};
169
170
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400171struct Script;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400172struct LangSys;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400173struct Feature;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400174
175
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400176struct LangSys
177{
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400178 inline unsigned int get_feature_count (void) const
179 { return featureIndex.len; }
180 inline hb_tag_t get_feature_index (unsigned int i) const
181 { return featureIndex[i]; }
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500182 inline unsigned int get_feature_indexes (unsigned int start_offset,
183 unsigned int *feature_count /* IN/OUT */,
184 unsigned int *feature_indexes /* OUT */) const
185 { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400186
Behdad Esfahbodcc6c6442009-05-25 03:10:06 -0400187 inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
Behdad Esfahbod3d44fb62010-05-10 22:22:54 -0400188 inline unsigned int get_required_feature_index (void) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400189 {
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400190 if (reqFeatureIndex == 0xffff)
Behdad Esfahbodb5db4f12010-05-10 22:22:22 -0400191 return Index::NOT_FOUND_INDEX;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400192 return reqFeatureIndex;;
193 }
194
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400195 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400196 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200197 return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400198 }
199
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400200 Offset lookupOrder; /* = Null (reserved for an offset to a
201 * reordering table) */
202 USHORT reqFeatureIndex;/* Index of a feature required for this
203 * language system--if no required features
204 * = 0xFFFF */
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400205 IndexArray featureIndex; /* Array of indices into the FeatureList */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400206 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400207 DEFINE_SIZE_ARRAY (6, featureIndex);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400208};
Behdad Esfahbod65f46b02010-05-06 19:35:19 -0400209DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400210
211
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400212struct Script
213{
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400214 inline unsigned int get_lang_sys_count (void) const
215 { return langSys.len; }
216 inline const Tag& get_lang_sys_tag (unsigned int i) const
217 { return langSys.get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500218 inline unsigned int get_lang_sys_tags (unsigned int start_offset,
219 unsigned int *lang_sys_count /* IN/OUT */,
220 hb_tag_t *lang_sys_tags /* OUT */) const
221 { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400222 inline const LangSys& get_lang_sys (unsigned int i) const
223 {
Behdad Esfahbodb5db4f12010-05-10 22:22:22 -0400224 if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400225 return this+langSys[i].offset;
226 }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400227 inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
228 { return langSys.find_index (tag, index); }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400229
Behdad Esfahbodcc6c6442009-05-25 03:10:06 -0400230 inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400231 inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400232
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400233 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400234 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200235 return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400236 }
237
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400238 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400239 OffsetTo<LangSys>
240 defaultLangSys; /* Offset to DefaultLangSys table--from
241 * beginning of Script table--may be Null */
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400242 RecordArrayOf<LangSys>
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400243 langSys; /* Array of LangSysRecords--listed
244 * alphabetically by LangSysTag */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400245 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400246 DEFINE_SIZE_ARRAY (4, langSys);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400247};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400248
249typedef RecordListOf<Script> ScriptList;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400250
251
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400252struct Feature
253{
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400254 inline unsigned int get_lookup_count (void) const
255 { return lookupIndex.len; }
256 inline hb_tag_t get_lookup_index (unsigned int i) const
257 { return lookupIndex[i]; }
Behdad Esfahbode21899b2009-11-04 16:36:14 -0500258 inline unsigned int get_lookup_indexes (unsigned int start_index,
259 unsigned int *lookup_count /* IN/OUT */,
260 unsigned int *lookup_tags /* OUT */) const
261 { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400262
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400263 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400264 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200265 return TRACE_RETURN (c->check_struct (this) && lookupIndex.sanitize (c));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400266 }
267
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400268 Offset featureParams; /* Offset to Feature Parameters table (if one
269 * has been defined for the feature), relative
270 * to the beginning of the Feature Table; = Null
271 * if not required */
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400272 IndexArray lookupIndex; /* Array of LookupList indices */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400273 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400274 DEFINE_SIZE_ARRAY (4, lookupIndex);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400275};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400276
277typedef RecordListOf<Feature> FeatureList;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400278
279
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400280struct LookupFlag : USHORT
281{
Behdad Esfahbodc6035cf2012-04-12 13:23:59 -0400282 enum Flags {
Behdad Esfahbod4fa77d32009-05-18 18:44:54 -0400283 RightToLeft = 0x0001u,
284 IgnoreBaseGlyphs = 0x0002u,
285 IgnoreLigatures = 0x0004u,
286 IgnoreMarks = 0x0008u,
Behdad Esfahbodaa87d952009-10-29 03:00:44 -0400287 IgnoreFlags = 0x000Eu,
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400288 UseMarkFilteringSet = 0x0010u,
289 Reserved = 0x00E0u,
Behdad Esfahbod8f034d52009-08-18 16:41:59 -0400290 MarkAttachmentType = 0xFF00u
Behdad Esfahbod4fa77d32009-05-18 18:44:54 -0400291 };
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400292 public:
293 DEFINE_SIZE_STATIC (2);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400294};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400295
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400296struct Lookup
297{
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400298 inline unsigned int get_subtable_count (void) const { return subTable.len; }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400299
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400300 inline unsigned int get_type (void) const { return lookupType; }
Behdad Esfahbod8c69e652010-10-27 22:07:49 -0400301
302 /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
303 * higher 16-bit is mark-filtering-set if the lookup uses one.
304 * Not to be confused with glyph_props which is very similar. */
305 inline uint32_t get_props (void) const
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400306 {
307 unsigned int flag = lookupFlag;
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -0400308 if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400309 {
Behdad Esfahbode961c862010-04-21 15:56:11 -0400310 const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
Behdad Esfahbod09c292e2009-05-26 19:48:16 -0400311 flag += (markFilteringSet << 16);
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400312 }
313 return flag;
314 }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400315
Behdad Esfahbod652d1e02012-09-04 20:00:44 -0400316 inline bool serialize (hb_serialize_context_t *c,
317 unsigned int lookup_type,
318 uint32_t lookup_props,
319 unsigned int num_subtables)
320 {
321 TRACE_SERIALIZE ();
322 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
323 lookupType.set (lookup_type);
324 lookupFlag.set (lookup_props & 0xFFFF);
325 if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
Behdad Esfahbodb3b89b62012-09-04 21:13:17 -0400326 if (lookupFlag & LookupFlag::UseMarkFilteringSet)
Behdad Esfahbod652d1e02012-09-04 20:00:44 -0400327 {
328 USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
329 markFilteringSet.set (lookup_props >> 16);
330 }
331 return TRACE_RETURN (true);
332 }
333
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400334 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400335 TRACE_SANITIZE ();
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -0400336 /* Real sanitize of the subtables is done by GSUB/GPOS/... */
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200337 if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
Behdad Esfahbod652d1e02012-09-04 20:00:44 -0400338 if (lookupFlag & LookupFlag::UseMarkFilteringSet)
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400339 {
Behdad Esfahbode961c862010-04-21 15:56:11 -0400340 USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200341 if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400342 }
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200343 return TRACE_RETURN (true);
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400344 }
345
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400346 USHORT lookupType; /* Different enumerations for GSUB and GPOS */
347 USHORT lookupFlag; /* Lookup qualifiers */
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -0400348 ArrayOf<Offset>
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400349 subTable; /* Array of SubTables */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500350 USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
Behdad Esfahbodd7df42d2009-05-26 13:04:59 -0400351 * structure. This field is only present if bit
352 * UseMarkFilteringSet of lookup flags is set. */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400353 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400354 DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400355};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400356
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400357typedef OffsetListOf<Lookup> LookupList;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400358
359
360/*
361 * Coverage Table
362 */
363
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400364struct CoverageFormat1
365{
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400366 friend struct Coverage;
367
368 private:
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400369 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
370 {
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400371 int i = glyphArray.search (glyph_id);
Behdad Esfahboddadede02012-07-28 18:03:20 -0400372 ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
373 return i;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400374 }
375
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400376 inline bool serialize (hb_serialize_context_t *c,
Behdad Esfahboda930c682012-09-04 18:17:57 -0400377 Supplier<GlyphID> &glyphs,
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400378 unsigned int num_glyphs)
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400379 {
380 TRACE_SERIALIZE ();
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400381 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
382 glyphArray.len.set (num_glyphs);
383 if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400384 for (unsigned int i = 0; i < num_glyphs; i++)
Behdad Esfahbodfabd3112012-09-05 22:19:28 -0400385 glyphArray[i] = glyphs[i];
Behdad Esfahboda930c682012-09-04 18:17:57 -0400386 glyphs.advance (num_glyphs);
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400387 return TRACE_RETURN (true);
388 }
389
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400390 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400391 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200392 return TRACE_RETURN (glyphArray.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400393 }
394
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400395 inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400396 return glyphs->has (glyphArray[index]);
397 }
398
Behdad Esfahbodc8accf12012-08-01 21:05:57 -0400399 template <typename set_t>
400 inline void add_coverage (set_t *glyphs) const {
Behdad Esfahbod67bb9e82012-06-09 02:02:46 -0400401 unsigned int count = glyphArray.len;
402 for (unsigned int i = 0; i < count; i++)
403 glyphs->add (glyphArray[i]);
404 }
405
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400406 struct Iter {
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400407 inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
408 inline bool more (void) { return i < c->glyphArray.len; }
409 inline void next (void) { i++; }
410 inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
411 inline uint16_t get_coverage (void) { return i; }
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400412
413 private:
414 const struct CoverageFormat1 *c;
415 unsigned int i;
416 };
417
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400418 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400419 USHORT coverageFormat; /* Format identifier--format = 1 */
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400420 SortedArrayOf<GlyphID>
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400421 glyphArray; /* Array of GlyphIDs--in numerical order */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400422 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400423 DEFINE_SIZE_ARRAY (4, glyphArray);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400424};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400425
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400426struct CoverageFormat2
427{
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400428 friend struct Coverage;
429
430 private:
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400431 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
432 {
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400433 int i = rangeRecord.search (glyph_id);
434 if (i != -1) {
435 const RangeRecord &range = rangeRecord[i];
436 return (unsigned int) range.value + (glyph_id - range.start);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400437 }
438 return NOT_COVERED;
439 }
440
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400441 inline bool serialize (hb_serialize_context_t *c,
Behdad Esfahboda930c682012-09-04 18:17:57 -0400442 Supplier<GlyphID> &glyphs,
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400443 unsigned int num_glyphs)
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400444 {
445 TRACE_SERIALIZE ();
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400446 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
447
448 if (unlikely (!num_glyphs)) return TRACE_RETURN (true);
449
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400450 unsigned int num_ranges = 1;
451 for (unsigned int i = 1; i < num_glyphs; i++)
452 if (glyphs[i - 1] + 1 != glyphs[i])
453 num_ranges++;
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400454 rangeRecord.len.set (num_ranges);
455 if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false);
456
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400457 unsigned int range = 0;
Behdad Esfahbodfabd3112012-09-05 22:19:28 -0400458 rangeRecord[range].start = glyphs[0];
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400459 rangeRecord[range].value.set (0);
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400460 for (unsigned int i = 1; i < num_glyphs; i++)
461 if (glyphs[i - 1] + 1 != glyphs[i]) {
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400462 range++;
Behdad Esfahbodfabd3112012-09-05 22:19:28 -0400463 rangeRecord[range].start = glyphs[i];
464 rangeRecord[range].value.set (i);
465 rangeRecord[range].end = glyphs[i];
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400466 } else {
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400467 rangeRecord[range].end = glyphs[i];
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400468 }
Behdad Esfahboda930c682012-09-04 18:17:57 -0400469 glyphs.advance (num_glyphs);
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400470 return TRACE_RETURN (true);
471 }
472
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400473 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400474 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200475 return TRACE_RETURN (rangeRecord.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400476 }
477
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400478 inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400479 unsigned int i;
480 unsigned int count = rangeRecord.len;
481 for (i = 0; i < count; i++) {
482 const RangeRecord &range = rangeRecord[i];
483 if (range.value <= index &&
Behdad Esfahbod3f182362012-05-13 16:20:10 +0200484 index < (unsigned int) range.value + (range.end - range.start) &&
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400485 range.intersects (glyphs))
486 return true;
487 else if (index < range.value)
488 return false;
489 }
490 return false;
491 }
492
Behdad Esfahbodc8accf12012-08-01 21:05:57 -0400493 template <typename set_t>
494 inline void add_coverage (set_t *glyphs) const {
Behdad Esfahbod67bb9e82012-06-09 02:02:46 -0400495 unsigned int count = rangeRecord.len;
496 for (unsigned int i = 0; i < count; i++)
497 rangeRecord[i].add_coverage (glyphs);
498 }
499
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400500 struct Iter {
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400501 inline void init (const CoverageFormat2 &c_) {
502 c = &c_;
503 coverage = 0;
504 i = 0;
505 j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
506 }
507 inline bool more (void) { return i < c->rangeRecord.len; }
508 inline void next (void) {
509 coverage++;
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400510 if (j == c->rangeRecord[i].end) {
511 i++;
Behdad Esfahbod0da132b2012-04-23 14:21:33 -0400512 if (more ())
513 j = c->rangeRecord[i].start;
514 return;
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400515 }
Behdad Esfahbod0da132b2012-04-23 14:21:33 -0400516 j++;
517 }
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400518 inline uint16_t get_glyph (void) { return j; }
519 inline uint16_t get_coverage (void) { return coverage; }
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400520
521 private:
522 const struct CoverageFormat2 *c;
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400523 unsigned int i, j, coverage;
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400524 };
525
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400526 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400527 USHORT coverageFormat; /* Format identifier--format = 2 */
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400528 SortedArrayOf<RangeRecord>
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400529 rangeRecord; /* Array of glyph ranges--ordered by
530 * Start GlyphID. rangeCount entries
531 * long */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400532 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400533 DEFINE_SIZE_ARRAY (4, rangeRecord);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400534};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400535
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400536struct Coverage
537{
Behdad Esfahbod00e23fc2010-04-20 23:50:45 -0400538 inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400539
Behdad Esfahbod20b035d2009-08-10 19:00:36 -0400540 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400541 {
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400542 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400543 case 1: return u.format1.get_coverage(glyph_id);
544 case 2: return u.format2.get_coverage(glyph_id);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400545 default:return NOT_COVERED;
546 }
547 }
548
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400549 inline bool serialize (hb_serialize_context_t *c,
Behdad Esfahboda930c682012-09-04 18:17:57 -0400550 Supplier<GlyphID> &glyphs,
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400551 unsigned int num_glyphs)
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400552 {
553 TRACE_SERIALIZE ();
Behdad Esfahbodc61be032012-09-01 21:43:38 -0400554 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400555 unsigned int num_ranges = 1;
556 for (unsigned int i = 1; i < num_glyphs; i++)
557 if (glyphs[i - 1] + 1 != glyphs[i])
558 num_ranges++;
Behdad Esfahbodbc5be242012-09-01 20:48:22 -0400559 u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
560 switch (u.format) {
561 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
562 case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
Behdad Esfahbod9f2348d2012-08-29 21:08:59 -0400563 default:return TRACE_RETURN (false);
564 }
565 }
566
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400567 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400568 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200569 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400570 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200571 case 1: return TRACE_RETURN (u.format1.sanitize (c));
572 case 2: return TRACE_RETURN (u.format2.sanitize (c));
573 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400574 }
575 }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400576
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400577 inline bool intersects (const hb_set_t *glyphs) const {
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400578 /* TODO speed this up */
579 Coverage::Iter iter;
580 for (iter.init (*this); iter.more (); iter.next ()) {
581 if (glyphs->has (iter.get_glyph ()))
582 return true;
583 }
584 return false;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400585 }
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400586
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400587 inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400588 switch (u.format) {
589 case 1: return u.format1.intersects_coverage (glyphs, index);
590 case 2: return u.format2.intersects_coverage (glyphs, index);
591 default:return false;
592 }
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400593 }
594
Behdad Esfahbodc8accf12012-08-01 21:05:57 -0400595 template <typename set_t>
596 inline void add_coverage (set_t *glyphs) const {
Behdad Esfahbod67bb9e82012-06-09 02:02:46 -0400597 switch (u.format) {
598 case 1: u.format1.add_coverage (glyphs); break;
599 case 2: u.format2.add_coverage (glyphs); break;
600 default: break;
601 }
602 }
603
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400604 struct Iter {
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400605 Iter (void) : format (0) {};
606 inline void init (const Coverage &c_) {
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400607 format = c_.u.format;
608 switch (format) {
609 case 1: return u.format1.init (c_.u.format1);
610 case 2: return u.format2.init (c_.u.format2);
611 default:return;
612 }
613 }
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400614 inline bool more (void) {
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400615 switch (format) {
616 case 1: return u.format1.more ();
617 case 2: return u.format2.more ();
618 default:return true;
619 }
620 }
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400621 inline void next (void) {
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400622 switch (format) {
Behdad Esfahbod0da132b2012-04-23 14:21:33 -0400623 case 1: u.format1.next (); break;
624 case 2: u.format2.next (); break;
625 default: break;
626 }
627 }
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400628 inline uint16_t get_glyph (void) {
Behdad Esfahbod0da132b2012-04-23 14:21:33 -0400629 switch (format) {
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400630 case 1: return u.format1.get_glyph ();
631 case 2: return u.format2.get_glyph ();
632 default:return true;
633 }
634 }
635 inline uint16_t get_coverage (void) {
636 switch (format) {
637 case 1: return u.format1.get_coverage ();
638 case 2: return u.format2.get_coverage ();
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400639 default:return true;
640 }
641 }
642
643 private:
Behdad Esfahbodc64ddab2012-04-23 15:28:35 -0400644 unsigned int format;
Behdad Esfahbod7d50d502012-04-23 13:02:14 -0400645 union {
646 CoverageFormat1::Iter format1;
647 CoverageFormat2::Iter format2;
648 } u;
649 };
650
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400651 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400652 union {
653 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400654 CoverageFormat1 format1;
655 CoverageFormat2 format2;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400656 } u;
Behdad Esfahboded074222010-05-10 18:08:46 -0400657 public:
Behdad Esfahbod596e4712010-05-10 18:47:48 -0400658 DEFINE_SIZE_UNION (2, format);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400659};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400660
661
662/*
663 * Class Definition Table
664 */
665
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400666struct ClassDefFormat1
667{
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400668 friend struct ClassDef;
669
670 private:
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400671 inline unsigned int get_class (hb_codepoint_t glyph_id) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400672 {
Behdad Esfahbodcaf04122012-06-09 00:26:32 -0400673 if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len))
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400674 return classValue[glyph_id - startGlyph];
675 return 0;
676 }
677
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400678 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400679 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200680 return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400681 }
682
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400683 inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400684 unsigned int count = classValue.len;
685 for (unsigned int i = 0; i < count; i++)
686 if (classValue[i] == klass && glyphs->has (startGlyph + i))
687 return true;
688 return false;
689 }
690
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400691 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400692 USHORT classFormat; /* Format identifier--format = 1 */
693 GlyphID startGlyph; /* First GlyphID of the classValueArray */
694 ArrayOf<USHORT>
695 classValue; /* Array of Class Values--one per GlyphID */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400696 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400697 DEFINE_SIZE_ARRAY (6, classValue);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400698};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400699
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400700struct ClassDefFormat2
701{
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400702 friend struct ClassDef;
703
704 private:
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400705 inline unsigned int get_class (hb_codepoint_t glyph_id) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400706 {
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400707 int i = rangeRecord.search (glyph_id);
708 if (i != -1)
709 return rangeRecord[i].value;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400710 return 0;
711 }
712
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400713 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400714 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200715 return TRACE_RETURN (rangeRecord.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400716 }
717
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400718 inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400719 unsigned int count = rangeRecord.len;
720 for (unsigned int i = 0; i < count; i++)
721 if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
722 return true;
723 return false;
724 }
725
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400726 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400727 USHORT classFormat; /* Format identifier--format = 2 */
Behdad Esfahbodcc8a4ab2010-07-08 00:40:04 -0400728 SortedArrayOf<RangeRecord>
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400729 rangeRecord; /* Array of glyph ranges--ordered by
730 * Start GlyphID */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400731 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400732 DEFINE_SIZE_ARRAY (4, rangeRecord);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400733};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400734
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400735struct ClassDef
736{
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400737 inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400738
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400739 inline unsigned int get_class (hb_codepoint_t glyph_id) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400740 {
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400741 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400742 case 1: return u.format1.get_class(glyph_id);
743 case 2: return u.format2.get_class(glyph_id);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400744 default:return 0;
745 }
746 }
747
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400748 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400749 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200750 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400751 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200752 case 1: return TRACE_RETURN (u.format1.sanitize (c));
753 case 2: return TRACE_RETURN (u.format2.sanitize (c));
754 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400755 }
756 }
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400757
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400758 inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400759 switch (u.format) {
760 case 1: return u.format1.intersects_class (glyphs, klass);
761 case 2: return u.format2.intersects_class (glyphs, klass);
762 default:return false;
763 }
764 }
765
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400766 protected:
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400767 union {
768 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400769 ClassDefFormat1 format1;
770 ClassDefFormat2 format2;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400771 } u;
Behdad Esfahboded074222010-05-10 18:08:46 -0400772 public:
Behdad Esfahbod596e4712010-05-10 18:47:48 -0400773 DEFINE_SIZE_UNION (2, format);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400774};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400775
776
777/*
778 * Device Tables
779 */
780
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400781struct Device
782{
Behdad Esfahbodb634beb2010-05-20 17:44:52 +0100783
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400784 inline hb_position_t get_x_delta (hb_font_t *font) const
785 { return get_delta (font->x_ppem, font->x_scale); }
Behdad Esfahbodb634beb2010-05-20 17:44:52 +0100786
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400787 inline hb_position_t get_y_delta (hb_font_t *font) const
788 { return get_delta (font->y_ppem, font->y_scale); }
Behdad Esfahbodb634beb2010-05-20 17:44:52 +0100789
Behdad Esfahbodda975412011-04-21 15:08:01 -0400790 inline int get_delta (unsigned int ppem, int scale) const
Behdad Esfahbod5bd1e952010-09-22 16:46:18 -0400791 {
792 if (!ppem) return 0;
793
794 int pixels = get_delta_pixels (ppem);
795
796 if (!pixels) return 0;
797
Behdad Esfahbod5bd1e952010-09-22 16:46:18 -0400798 return pixels * (int64_t) scale / ppem;
799 }
800
801
802 inline int get_delta_pixels (unsigned int ppem_size) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400803 {
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400804 unsigned int f = deltaFormat;
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -0400805 if (unlikely (f < 1 || f > 3))
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400806 return 0;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400807
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400808 if (ppem_size < startSize || ppem_size > endSize)
809 return 0;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400810
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400811 unsigned int s = ppem_size - startSize;
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400812
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400813 unsigned int byte = deltaValue[s >> (4 - f)];
Behdad Esfahbod09c292e2009-05-26 19:48:16 -0400814 unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
815 unsigned int mask = (0xFFFF >> (16 - (1 << f)));
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400816
817 int delta = bits & mask;
818
Behdad Esfahbod15164d92009-08-04 13:57:41 -0400819 if ((unsigned int) delta >= ((mask + 1) >> 1))
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400820 delta -= mask + 1;
821
822 return delta;
823 }
824
Behdad Esfahbod7f97d2c2010-10-01 18:58:50 -0400825 inline unsigned int get_size (void) const
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -0400826 {
827 unsigned int f = deltaFormat;
Behdad Esfahbodb9615182010-05-10 18:20:54 -0400828 if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
829 return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -0400830 }
831
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400832 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400833 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200834 return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
Behdad Esfahboddc9c4d92009-08-04 12:26:26 -0400835 }
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400836
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400837 protected:
Behdad Esfahbod0795b782010-04-22 00:23:14 -0400838 USHORT startSize; /* Smallest size to correct--in ppem */
839 USHORT endSize; /* Largest size to correct--in ppem */
Behdad Esfahbodcaff7db2010-04-26 10:07:35 -0400840 USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3
841 * 1 Signed 2-bit value, 8 values per uint16
842 * 2 Signed 4-bit value, 4 values per uint16
843 * 3 Signed 8-bit value, 2 values per uint16
844 */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500845 USHORT deltaValue[VAR]; /* Array of compressed data */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400846 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400847 DEFINE_SIZE_ARRAY (6, deltaValue);
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400848};
Behdad Esfahbod6f20f722009-05-17 20:28:01 -0400849
850
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -0400851} // namespace OT
852
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400853
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -0400854#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */