2 * Copyright (C) 2007,2008,2009 Red Hat, Inc.
4 * This is part of HarfBuzz, an OpenType Layout engine library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * Red Hat Author(s): Behdad Esfahbod
27 #ifndef HB_OT_LAYOUT_COMMON_PRIVATE_H
28 #define HB_OT_LAYOUT_COMMON_PRIVATE_H
30 #include "hb-ot-layout-open-private.h"
35 * OpenType Layout Common Table Formats
41 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
44 template <typename Type>
46 Tag tag; /* 4-byte Tag identifier */
48 offset; /* Offset from beginning of object holding
52 template <typename Type>
53 struct RecordListOf : ArrayOf<Record<Type> > {
54 inline const Type& operator [] (unsigned int i) const {
55 if (HB_UNLIKELY (i >= this->len)) return Null(Type);
56 return this+this->array[i].offset;
58 inline const Tag& get_tag (unsigned int i) const {
59 if (HB_UNLIKELY (i >= this->len)) return Null(Tag);
60 return this->array[i].tag;
66 typedef Record<Script> ScriptRecord;
67 ASSERT_SIZE (ScriptRecord, 6);
69 typedef Record<LangSys> LangSysRecord;
70 ASSERT_SIZE (LangSysRecord, 6);
72 typedef Record<Feature> FeatureRecord;
73 ASSERT_SIZE (FeatureRecord, 6);
78 inline const unsigned int get_feature_index (unsigned int i) const {
79 return featureIndex[i];
81 inline unsigned int get_feature_count (void) const {
82 return featureIndex.len;
85 inline const bool has_required_feature (void) const {
86 return reqFeatureIndex != 0xffff;
88 /* Returns NO_INDEX if none */
89 inline int get_required_feature_index (void) const {
90 if (reqFeatureIndex == 0xffff)
92 return reqFeatureIndex;;
95 Offset lookupOrder; /* = Null (reserved for an offset to a
96 * reordering table) */
97 USHORT reqFeatureIndex;/* Index of a feature required for this
98 * language system--if no required features
101 featureIndex; /* Array of indices into the FeatureList */
103 ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
108 inline const LangSys& get_lang_sys (unsigned int i) const {
109 if (i == NO_INDEX) return get_default_lang_sys ();
110 return this+langSys[i].offset;
112 inline unsigned int get_lang_sys_count (void) const {
115 inline const Tag& get_lang_sys_tag (unsigned int i) const {
116 return langSys[i].tag;
119 // LONGTERMTODO bsearch
120 DEFINE_TAG_FIND_INTERFACE (LangSys, lang_sys); /* find_lang_sys_index (), get_lang_sys_by_tag (tag) */
122 inline const bool has_default_lang_sys (void) const {
123 return defaultLangSys != 0;
125 inline const LangSys& get_default_lang_sys (void) const {
126 return this+defaultLangSys;
131 defaultLangSys; /* Offset to DefaultLangSys table--from
132 * beginning of Script table--may be Null */
133 ArrayOf<LangSysRecord>
134 langSys; /* Array of LangSysRecords--listed
135 * alphabetically by LangSysTag */
137 ASSERT_SIZE (Script, 4);
139 typedef RecordListOf<Script> ScriptList;
140 ASSERT_SIZE (ScriptList, 2);
145 inline const unsigned int get_lookup_index (unsigned int i) const {
146 return lookupIndex[i];
148 inline unsigned int get_lookup_count (void) const {
149 return lookupIndex.len;
152 /* TODO: implement get_feature_parameters() */
153 /* TODO: implement FeatureSize and other special features? */
154 Offset featureParams; /* Offset to Feature Parameters table (if one
155 * has been defined for the feature), relative
156 * to the beginning of the Feature Table; = Null
159 lookupIndex; /* Array of LookupList indices */
161 ASSERT_SIZE (Feature, 4);
163 typedef RecordListOf<Feature> FeatureList;
164 ASSERT_SIZE (FeatureList, 2);
167 struct LookupFlag : USHORT {
169 RightToLeft = 0x0001u,
170 IgnoreBaseGlyphs = 0x0002u,
171 IgnoreLigatures = 0x0004u,
172 IgnoreMarks = 0x0008u,
174 MarkAttachmentType = 0xFF00u,
177 ASSERT_SIZE (LookupFlag, 2);
179 struct LookupSubTable {
181 USHORT format; /* Subtable format. Different for GSUB and GPOS */
183 ASSERT_SIZE (LookupSubTable, 2);
187 inline const LookupSubTable& get_subtable (unsigned int i) const {
188 return this+subTable[i];
190 inline unsigned int get_subtable_count (void) const {
194 inline unsigned int get_type (void) const { return lookupType; }
195 inline unsigned int get_flag (void) const { return lookupFlag; }
197 USHORT lookupType; /* Different enumerations for GSUB and GPOS */
198 USHORT lookupFlag; /* Lookup qualifiers */
199 OffsetArrayOf<LookupSubTable>
200 subTable; /* Array of SubTables */
202 ASSERT_SIZE (Lookup, 6);
204 template <typename Type>
205 struct OffsetListOf : OffsetArrayOf<Type> {
206 inline const Type& operator [] (unsigned int i) const {
207 if (HB_UNLIKELY (i >= this->len)) return Null(Type);
208 return this+this->array[i];
212 typedef OffsetListOf<Lookup> LookupList;
213 ASSERT_SIZE (LookupList, 2);
220 struct CoverageFormat1 {
222 friend struct Coverage;
225 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
226 if (HB_UNLIKELY (glyph_id > 0xFFFF))
231 unsigned int num_glyphs = glyphArray.len;
232 for (unsigned int i = 0; i < num_glyphs; i++)
233 if (gid == glyphArray[i])
238 USHORT coverageFormat; /* Format identifier--format = 1 */
240 glyphArray; /* Array of GlyphIDs--in numerical order */
242 ASSERT_SIZE (CoverageFormat1, 4);
244 struct CoverageRangeRecord {
246 friend struct CoverageFormat2;
249 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
250 if (glyph_id >= start && glyph_id <= end)
251 return (unsigned int) startCoverageIndex + (glyph_id - start);
256 GlyphID start; /* First GlyphID in the range */
257 GlyphID end; /* Last GlyphID in the range */
258 USHORT startCoverageIndex; /* Coverage Index of first GlyphID in
261 ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\000\001");
263 struct CoverageFormat2 {
265 friend struct Coverage;
268 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
270 unsigned int count = rangeRecord.len;
271 for (unsigned int i = 0; i < count; i++) {
272 unsigned int coverage = rangeRecord[i].get_coverage (glyph_id);
273 if (coverage != NOT_COVERED)
279 USHORT coverageFormat; /* Format identifier--format = 2 */
280 ArrayOf<CoverageRangeRecord>
281 rangeRecord; /* Array of glyph ranges--ordered by
282 * Start GlyphID. rangeCount entries
285 ASSERT_SIZE (CoverageFormat2, 4);
288 unsigned int get_coverage (hb_codepoint_t glyph_id) const {
290 case 1: return u.format1->get_coverage(glyph_id);
291 case 2: return u.format2->get_coverage(glyph_id);
292 default:return NOT_COVERED;
296 inline unsigned int operator() (hb_codepoint_t glyph_id) const {
297 return get_coverage (glyph_id);
302 USHORT format; /* Format identifier */
303 CoverageFormat1 format1[];
304 CoverageFormat2 format2[];
307 ASSERT_SIZE (Coverage, 2);
311 * Class Definition Table
314 struct ClassDefFormat1 {
316 friend struct ClassDef;
319 inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
320 if ((unsigned int) (glyph_id - startGlyph) < classValue.len)
321 return classValue[glyph_id - startGlyph];
325 USHORT classFormat; /* Format identifier--format = 1 */
326 GlyphID startGlyph; /* First GlyphID of the classValueArray */
328 classValue; /* Array of Class Values--one per GlyphID */
330 ASSERT_SIZE (ClassDefFormat1, 6);
332 struct ClassRangeRecord {
334 friend struct ClassDefFormat2;
337 inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
338 if (glyph_id >= start && glyph_id <= end)
344 GlyphID start; /* First GlyphID in the range */
345 GlyphID end; /* Last GlyphID in the range */
346 USHORT classValue; /* Applied to all glyphs in the range */
348 ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\000\001");
350 struct ClassDefFormat2 {
352 friend struct ClassDef;
355 inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
357 unsigned int count = rangeRecord.len;
358 for (unsigned int i = 0; i < count; i++) {
359 int classValue = rangeRecord[i].get_class (glyph_id);
366 USHORT classFormat; /* Format identifier--format = 2 */
367 ArrayOf<ClassRangeRecord>
368 rangeRecord; /* Array of glyph ranges--ordered by
371 ASSERT_SIZE (ClassDefFormat2, 4);
374 hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
376 case 1: return u.format1->get_class(glyph_id);
377 case 2: return u.format2->get_class(glyph_id);
382 inline unsigned int operator() (hb_codepoint_t glyph_id) const {
383 return get_class (glyph_id);
388 USHORT format; /* Format identifier */
389 ClassDefFormat1 format1[];
390 ClassDefFormat2 format2[];
393 ASSERT_SIZE (ClassDef, 2);
401 int get_delta (unsigned int ppem_size) const {
403 unsigned int f = deltaFormat;
404 if (HB_UNLIKELY (f < 1 || f > 3))
407 if (ppem_size < startSize || ppem_size > endSize)
410 unsigned int s = ppem_size - startSize;
412 unsigned int byte = deltaValue[s >> (4 - f)];
413 unsigned int bits = byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f));
414 unsigned int mask = 0xFFFF >> (16 - (1 << f));
416 int delta = bits & mask;
418 if (delta >= ((mask + 1) >> 1))
424 inline int operator() (unsigned int ppem_size) const {
425 return get_delta (ppem_size);
429 USHORT startSize; /* Smallest size to correct--in ppem */
430 USHORT endSize; /* Largest size to correct--in ppem */
431 USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3 */
432 USHORT deltaValue[]; /* Array of compressed data */
434 ASSERT_SIZE (Device, 6);
437 #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_H */