ded36ace50a2bc85c65ac0eab92cc278d3a6bc0d
[profile/ivi/org.tizen.video-player.git] / src / harfbuzz-open-private.h
1 #ifndef HARFBUZZ_OPEN_PRIVATE_H
2 #define HARFBUZZ_OPEN_PRIVATE_H
3
4 #include "harfbuzz-private.h"
5 #include "harfbuzz-open.h"
6
7 #include <glib.h>
8
9 /* Macros to convert to/from BigEndian */
10 #define hb_be_uint8_t
11 #define hb_be_int8_t
12 #define hb_be_uint16_t  GUINT16_TO_BE
13 #define hb_be_int16_t   GINT16_TO_BE
14 #define hb_be_uint32_t  GUINT32_TO_BE
15 #define hb_be_int32_t   GINT32_TO_BE
16 #define hb_be_uint64_t  GUINT64_TO_BE
17 #define hb_be_int64_t   GINT64_TO_BE
18
19 /*
20  * Int types
21  */
22
23 #define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN) \
24   inline NAME& operator = (TYPE i) { v = BIG_ENDIAN(i); return *this; } \
25   inline operator TYPE(void) const { return BIG_ENDIAN(v); } \
26   inline bool operator== (NAME o) const { return v == o.v; } \
27   private: TYPE v; \
28   public:
29 #define DEFINE_INT_TYPE0(NAME, type) DEFINE_INT_TYPE1 (NAME, type, hb_be_##type)
30 #define DEFINE_INT_TYPE(NAME, u, w)  DEFINE_INT_TYPE0 (NAME, u##int##w##_t)
31 #define DEFINE_INT_TYPE_STRUCT(NAME, u, w) \
32   struct NAME { \
33     DEFINE_INT_TYPE(NAME, u, w) \
34   }
35
36 /*
37  * Array types
38  */
39
40 /* get_len() is a method returning the number of items in an array-like object */
41 #define DEFINE_LEN(Type, array, num) \
42   inline unsigned int get_len(void) const { return num; } \
43
44 /* get_size() is a method returning the size in bytes of an array-like object */
45 #define DEFINE_SIZE(Type, array, num) \
46   inline unsigned int get_size(void) const { return sizeof (*this) + sizeof (Type) * num; }
47
48 #define DEFINE_LEN_AND_SIZE(Type, array, num) \
49   DEFINE_LEN(Type, array, num) \
50   DEFINE_SIZE(Type, array, num)
51
52 #define DEFINE_NON_INSTANTIABLE(Type) \
53   private: inline Type() {} /* cannot be instantiated */ \
54   public:
55
56 /* An array type is one that contains a variable number of objects
57  * as its last item.  An array object is extended with len() and size()
58  * methods, as well as overloaded [] operator. */
59 #define DEFINE_ARRAY_TYPE(Type, array, num) \
60   DEFINE_INDEX_OPERATOR(const, Type, array, num) \
61   DEFINE_INDEX_OPERATOR(     , Type, array, num) \
62   DEFINE_LEN_AND_SIZE(Type, array, num)
63 #define DEFINE_INDEX_OPERATOR(const, Type, array, num) \
64   inline const Type& operator[] (unsigned int i) const { \
65     assert (i < num); \
66     return array[i]; \
67   }
68
69 /* An offset array type is like an array type, but it contains a table
70  * of offsets to the objects, relative to the beginning of the current
71  * object. */
72 #define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
73   DEFINE_OFFSET_INDEX_OPERATOR(const, Type, array, num) \
74   DEFINE_OFFSET_INDEX_OPERATOR(     , Type, array, num) \
75   DEFINE_LEN_AND_SIZE(Offset, array, num)
76 #define DEFINE_OFFSET_INDEX_OPERATOR(const, Type, array, num) \
77   inline const Type& operator[] (unsigned int i) const { \
78     assert (i < num); \
79     assert (array[i]); /* TODO: should just skip them */ \
80     return *(const Type *)((const char*)this + array[i]); \
81   }
82
83 #define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \
84   DEFINE_RECORD_ACCESSOR(const, Type, array, num) \
85   DEFINE_RECORD_ACCESSOR(     , Type, array, num) \
86   DEFINE_LEN_AND_SIZE(Record, array, num)
87 #define DEFINE_RECORD_ACCESSOR(const, Type, array, num) \
88   inline const Type& operator[] (unsigned int i) const { \
89     assert (i < num); \
90     assert (array[i].offset); /* TODO: should just skip them */ \
91     return *(const Type *)((const char*)this + array[i].offset); \
92   } \
93   inline const Tag& get_tag (unsigned int i) const { \
94     assert (i < num); \
95     return array[i].tag; \
96   } \
97   /* TODO: implement find_tag() */
98
99
100
101 /*
102  *
103  * The OpenType Font File
104  *
105  */
106
107
108
109 /*
110  * Data Types
111  */
112
113
114 /* "The following data types are used in the OpenType font file.
115  *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
116
117
118 DEFINE_INT_TYPE_STRUCT (BYTE,    u,  8);        /*  8-bit unsigned integer. */
119 ASSERT_SIZE (BYTE, 1);
120 DEFINE_INT_TYPE_STRUCT (CHAR,     ,  8);        /*  8-bit signed integer. */
121 ASSERT_SIZE (CHAR, 1);
122 DEFINE_INT_TYPE_STRUCT (USHORT,  u, 16);        /* 16-bit unsigned integer. */
123 ASSERT_SIZE (USHORT, 2);
124 DEFINE_INT_TYPE_STRUCT (SHORT,    , 16);        /* 16-bit signed integer. */
125 ASSERT_SIZE (SHORT, 2);
126 DEFINE_INT_TYPE_STRUCT (ULONG,   u, 32);        /* 32-bit unsigned integer. */
127 ASSERT_SIZE (ULONG, 4);
128 DEFINE_INT_TYPE_STRUCT (LONG,     , 32);        /* 32-bit signed integer. */
129 ASSERT_SIZE (LONG, 4);
130
131 /* Date represented in number of seconds since 12:00 midnight, January 1,
132  * 1904. The value is represented as a signed 64-bit integer. */
133 DEFINE_INT_TYPE_STRUCT (LONGDATETIME, , 64);
134
135 /* 32-bit signed fixed-point number (16.16) */
136 struct Fixed {
137   inline Fixed& operator = (int32_t v) { i = (int16_t) (v >> 16); f = (uint16_t) v; return *this; } \
138   inline operator int32_t(void) const { return (((int32_t) i) << 16) + (uint16_t) f; } \
139   inline bool operator== (Fixed o) const { return i == o.i && f == o.f; } \
140
141   inline operator double(void) const { return (uint32_t) this / 65536.; }
142   inline int16_t int_part (void) const { return i; }
143   inline uint16_t frac_part (void) const { return f; }
144
145   private:
146   SHORT i;
147   USHORT f;
148 };
149 ASSERT_SIZE (Fixed, 4);
150
151 /* Smallest measurable distance in the em space. */
152 struct FUNIT;
153
154 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
155 struct FWORD : SHORT {
156 };
157 ASSERT_SIZE (FWORD, 2);
158
159 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
160 struct UFWORD : USHORT {
161 };
162 ASSERT_SIZE (UFWORD, 2);
163
164 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
165 struct F2DOT14 : SHORT {
166   inline operator double() const { return (uint32_t) this / 16384.; }
167 };
168 ASSERT_SIZE (F2DOT14, 2);
169
170 /* Array of four uint8s (length = 32 bits) used to identify a script, language
171  * system, feature, or baseline */
172 struct Tag {
173   inline Tag (void) { v[0] = v[1] = v[2] = v[3] = 0; }
174   inline Tag (uint32_t v) { (ULONG&)(*this) = v; }
175   inline Tag (const char *c) { v[0] = c[0]; v[1] = c[1]; v[2] = c[2]; v[3] = c[3]; }
176   inline bool operator== (Tag o) const { return v[0]==o.v[0]&&v[1]==o.v[1]&&v[2]==o.v[2]&&v[3]==o.v[3]; }
177   inline bool operator== (const char *c) const { return v[0]==c[0]&&v[1]==c[1]&&v[2]==c[2]&&v[3]==c[3]; }
178   inline operator uint32_t(void) const { return (v[0]<<24)+(v[1]<<16) +(v[2]<<8)+v[3]; }
179   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
180   inline operator const char* (void) const { return (const char *)this; }
181   inline operator char* (void) { return (char *)this; }
182
183   private:
184   char v[4];
185 };
186 ASSERT_SIZE (Tag, 4);
187
188 /* Glyph index number, same as uint16 (length = 16 bits) */
189 DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16);
190 ASSERT_SIZE (GlyphID, 2);
191
192 /* Offset to a table, same as uint16 (length = 16 bits), NULL offset = 0x0000 */
193 DEFINE_INT_TYPE_STRUCT (Offset, u, 16);
194 ASSERT_SIZE (Offset, 2);
195
196 /* CheckSum */
197 struct CheckSum : ULONG {
198   static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) {
199     uint32_t Sum = 0L;
200     ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
201
202     while (Table < EndPtr)
203       Sum += *Table++;
204     return Sum;
205   }
206 };
207 ASSERT_SIZE (CheckSum, 4);
208
209
210 /*
211  * Version Numbers
212  */
213
214 struct USHORT_Version : USHORT {
215 };
216 ASSERT_SIZE (USHORT_Version, 2);
217
218 struct Fixed_Version : Fixed {
219   inline int16_t major (void) const { return this->int_part(); }
220   inline int16_t minor (void) const { return this->frac_part(); }
221 };
222 ASSERT_SIZE (Fixed_Version, 4);
223
224
225 /*
226  * Organization of an OpenType Font
227  */
228
229 struct OpenTypeFontFile;
230 struct OffsetTable;
231 struct TTCHeader;
232
233 typedef struct TableDirectory {
234
235   friend struct OpenTypeFontFile;
236
237   inline const Tag& get_tag (void) const { return tag; }
238   inline unsigned long get_checksum (void) const { return checkSum; }
239   inline unsigned long get_offset (void) const { return offset; }
240   inline unsigned long get_length (void) const { return length; }
241
242   private:
243   Tag           tag;            /* 4-byte identifier. */
244   CheckSum      checkSum;       /* CheckSum for this table. */
245   ULONG         offset;         /* Offset from beginning of TrueType font
246                                  * file. */
247   ULONG         length;         /* Length of this table. */
248 } OpenTypeTable;
249 ASSERT_SIZE (TableDirectory, 16);
250
251 typedef struct OffsetTable {
252   /* OpenTypeTables, in no particular order */
253   DEFINE_ARRAY_TYPE (TableDirectory, tableDir, numTables);
254   // TODO: Implement find_table
255
256   private:
257   Tag           sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
258   USHORT        numTables;      /* Number of tables. */
259   USHORT        searchRange;    /* (Maximum power of 2 <= numTables) x 16 */
260   USHORT        entrySelector;  /* Log2(maximum power of 2 <= numTables). */
261   USHORT        rangeShift;     /* NumTables x 16-searchRange. */
262   TableDirectory tableDir[];    /* TableDirectory entries. numTables items */
263 } OpenTypeFontFace;
264 ASSERT_SIZE (OffsetTable, 12);
265
266 /*
267  * TrueType Collections
268  */
269
270 struct TTCHeader {
271   /* OpenTypeFontFaces, in no particular order */
272   DEFINE_OFFSET_ARRAY_TYPE (OffsetTable, offsetTable, numFonts);
273
274   private:
275   Tag   ttcTag;         /* TrueType Collection ID string: 'ttcf' */
276   ULONG version;        /* Version of the TTC Header (1.0 or 2.0),
277                          * 0x00010000 or 0x00020000 */
278   ULONG numFonts;       /* Number of fonts in TTC */
279   ULONG offsetTable[];  /* Array of offsets to the OffsetTable for each font
280                          * from the beginning of the file */
281 };
282 ASSERT_SIZE (TTCHeader, 12);
283
284
285 /*
286  * OpenType Font File
287  */
288
289 struct OpenTypeFontFile {
290   DEFINE_NON_INSTANTIABLE(OpenTypeFontFile);
291   static const hb_tag_t TrueTypeTag     = HB_TAG ( 0 , 1 , 0 , 0 );
292   static const hb_tag_t CFFTag          = HB_TAG ('O','T','T','O');
293   static const hb_tag_t TTCTag          = HB_TAG ('t','t','c','f');
294
295   /* Factory: ::get(font_data)
296    * This is how you get a handle to one of these
297    */
298   static inline const OpenTypeFontFile& get (const char *font_data) {
299     return (const OpenTypeFontFile&)*font_data;
300   }
301   static inline OpenTypeFontFile& get (char *font_data) {
302     return (OpenTypeFontFile&)*font_data;
303   }
304
305   /* This is how you get a table */
306   inline const char* get_table (const OpenTypeTable& table) const {
307     return ((const char*)this) + table.offset;
308   }
309   inline char* get_table (const OpenTypeTable& table) {
310     return ((char*)this) + table.offset;
311   }
312   inline const char* operator[] (const OpenTypeTable& table) const {
313     return ((const char*)this) + table.offset;
314   }
315   inline char* operator[] (const OpenTypeTable& table) {
316     return ((char*)this) + table.offset;
317   }
318
319   /* Array interface sans get_size() */
320   inline unsigned int get_len (void) const {
321     switch (tag) {
322     default: return 0;
323     case TrueTypeTag: case CFFTag: return 1;
324     case TTCTag: return ((const TTCHeader&)*this).get_len();
325     }
326   }
327   inline const OpenTypeFontFace& operator[] (unsigned int i) const {
328     assert (i < get_len ());
329     switch (tag) {
330     default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this;
331     case TTCTag: return ((const TTCHeader&)*this)[i];
332     }
333   }
334   inline OpenTypeFontFace& operator[] (unsigned int i) {
335     assert (i < get_len ());
336     switch (tag) {
337     default: case TrueTypeTag: case CFFTag: return (OffsetTable&)*this;
338     case TTCTag: return ((TTCHeader&)*this)[i];
339     }
340   }
341   inline const Tag& get_tag (void) const { return tag; }
342
343   private:
344   Tag           tag;            /* 4-byte identifier. */
345 };
346 ASSERT_SIZE (OpenTypeFontFile, 4);
347
348
349
350 /*
351  *
352  * OpenType Layout Common Table Formats
353  *
354  */
355
356 /*
357  * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
358  */
359
360 struct Script;
361 struct ScriptList;
362 struct LangSys;
363 struct Feature;
364 struct FeatureList;
365 struct Lookup;
366 struct LookupList;
367
368 typedef struct Record {
369   Tag           tag;            /* 4-byte Tag identifier */
370   Offset        offset;         /* Offset from beginning of object holding
371                                  * the Record */
372 } ScriptRecord, LangSysRecord, FeatureRecord;
373 ASSERT_SIZE (Record, 6);
374
375 struct ScriptList {
376   /* Scripts, in sorted alphabetical tag order */
377   DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
378
379   private:
380   USHORT        scriptCount;    /* Number of ScriptRecords */
381   ScriptRecord  scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
382                                  * by ScriptTag */
383 };
384 ASSERT_SIZE (ScriptList, 2);
385
386 struct Script {
387   /* LangSys', in sorted alphabetical tag order */
388   DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
389
390   /* Return NULL if none */
391   inline const LangSys* get_default_language_system (void) const {
392     if (!defaultLangSys)
393       return NULL;
394     return (const LangSys *)((const char*)this + defaultLangSys);
395   }
396   inline LangSys* get_default_language_system (void) {
397     if (!defaultLangSys)
398       return NULL;
399     return (LangSys *)((char*)this + defaultLangSys);
400   }
401
402   private:
403   Offset        defaultLangSys; /* Offset to DefaultLangSys table--from
404                                  * beginning of Script table--may be NULL */
405   USHORT        langSysCount;   /* Number of LangSysRecords for this script--
406                                  * excluding the DefaultLangSys */
407   LangSysRecord langSysRecord[];/* Array of LangSysRecords--listed
408                                  * alphabetically by LangSysTag */
409 };
410 ASSERT_SIZE (Script, 4);
411
412 struct LangSys {
413   /* Feature indices, in no particular order */
414   DEFINE_ARRAY_TYPE (USHORT, featureIndex, featureCount);
415   
416   /* Returns -1 if none */
417   inline int get_required_feature_index (void) const {
418     if (reqFeatureIndex == 0xffff)
419       return -1;
420     return reqFeatureIndex;;
421   }
422
423   private:
424   Offset        lookupOrder;    /* = NULL (reserved for an offset to a
425                                  * reordering table) */
426   USHORT        reqFeatureIndex;/* Index of a feature required for this
427                                  * language system--if no required features
428                                  * = 0xFFFF */
429   USHORT        featureCount;   /* Number of FeatureIndex values for this
430                                  * language system--excludes the required
431                                  * feature */
432   USHORT        featureIndex[]; /* Array of indices into the FeatureList--in
433                                  * arbitrary order. featureCount entires long */
434 };
435 ASSERT_SIZE (LangSys, 6);
436
437 struct FeatureList {
438   /* Feature indices, in sorted alphabetical tag order */
439   DEFINE_RECORD_ARRAY_TYPE (Feature, featureRecord, featureCount);
440
441   private:
442   USHORT        featureCount;   /* Number of FeatureRecords in this table */
443   FeatureRecord featureRecord[];/* Array of FeatureRecords--zero-based (first
444                                  * feature has FeatureIndex = 0)--listed
445                                  * alphabetically by FeatureTag */
446 };
447 ASSERT_SIZE (FeatureList, 2);
448
449 struct Feature {
450   /* LookupList indices, in no particular order */
451   DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
452
453   // TODO: implement get_feature_params()
454
455   private:
456   Offset        featureParams;  /* Offset to Feature Parameters table (if one
457                                  * has been defined for the feature), relative
458                                  * to the beginning of the Feature Table; = NULL
459                                  * if not required */
460   USHORT        lookupCount;    /* Number of LookupList indices for this
461                                  * feature */
462   USHORT        lookupIndex[];  /* Array of LookupList indices for this
463                                  * feature--zero-based (first lookup is
464                                  * LookupListIndex = 0) */
465 };
466 ASSERT_SIZE (Feature, 4);
467
468 struct LookupList {
469   /* Lookup indices, in sorted alphabetical tag order */
470   DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
471
472   private:
473   USHORT        lookupCount;    /* Number of lookups in this table */
474   Offset        lookupOffset[]; /* Array of offsets to Lookup tables--from
475                                  * beginning of LookupList--zero based (first
476                                  * lookup is Lookup index = 0) */
477 };
478 ASSERT_SIZE (LookupList, 2);
479
480 struct LookupFlag : USHORT {
481   static const uint16_t RightToLeft             = 0x0001u;
482   static const uint16_t IgnoreBaseGlyphs        = 0x0002u;
483   static const uint16_t IgnoreLigatures         = 0x0004u;
484   static const uint16_t IgnoreMarks             = 0x0008u;
485   static const uint16_t Reserved                = 0x00F0u;
486   static const uint16_t MarkAttachmentType      = 0xFF00u;
487 };
488 ASSERT_SIZE (LookupFlag, 2);
489
490 struct Lookup {
491   /* SubTables, in the desired order */
492   DEFINE_OFFSET_ARRAY_TYPE (char*, subTableOffset, subTableCount);
493
494   inline bool is_right_to_left  (void) const { return lookupFlag & LookupFlag::RightToLeft; }
495   inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
496   inline bool ignore_ligatures  (void) const { return lookupFlag & LookupFlag::IgnoreLigatures; }
497   inline bool ignore_marks      (void) const { return lookupFlag & LookupFlag::IgnoreMarks; }
498   inline bool get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; }
499
500   inline uint16_t get_type (void) const { return lookupType; }
501   inline uint16_t get_flag (void) const { return lookupFlag; }
502
503   private:
504   USHORT        lookupType;     /* Different enumerations for GSUB and GPOS */
505   USHORT        lookupFlag;     /* Lookup qualifiers */
506   USHORT        subTableCount;  /* Number of SubTables for this lookup */
507   Offset        subTableOffset[];/* Array of offsets to SubTables-from
508                                   * beginning of Lookup table */
509 };
510 ASSERT_SIZE (Lookup, 6);
511
512 /*
513  * Coverage Table
514  */
515
516 struct CoverageFormat1 {
517   /* GlyphIDs, in sorted numerical order */
518   DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);
519
520   inline int get_coverage (uint16_t glyph_id) const {
521     GlyphID gid;
522     gid = glyph_id;
523     // TODO: bsearch
524     for (int i = 0; i < glyphCount; i++)
525       if (gid == glyphArray[i])
526         return i;
527     return -1;
528   }
529
530   private:
531   USHORT        coverageFormat; /* Format identifier--format = 1 */
532   USHORT        glyphCount;     /* Number of glyphs in the GlyphArray */
533   GlyphID       glyphArray[];   /* Array of GlyphIDs--in numerical order */
534 };
535 ASSERT_SIZE (CoverageFormat1, 4);
536
537 struct CoverageRangeRecord {
538
539   inline int get_coverage (uint16_t glyph_id) const {
540     if (glyph_id >= start && glyph_id <= end)
541       return startCoverageIndex + (glyph_id - start);
542     return -1;
543   }
544
545   private:
546   GlyphID       start;                  /* First GlyphID in the range */
547   GlyphID       end;                    /* Last GlyphID in the range */
548   USHORT        startCoverageIndex;     /* Coverage Index of first GlyphID in
549                                          * range */
550 };
551 ASSERT_SIZE (CoverageRangeRecord, 6);
552
553 struct CoverageFormat2 {
554   /* CoverageRangeRecords, in sorted numerical start order */
555   DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
556
557   inline int get_coverage (uint16_t glyph_id) const {
558     // TODO: bsearch
559     for (int i = 0; i < rangeCount; i++) {
560       int coverage = rangeRecord[i].get_coverage (glyph_id);
561       if (coverage >= 0)
562         return coverage;
563     }
564     return -1;
565   }
566
567   private:
568   USHORT                coverageFormat; /* Format identifier--format = 2 */
569   USHORT                rangeCount;     /* Number of CoverageRangeRecords */
570   CoverageRangeRecord   rangeRecord[];  /* Array of glyph ranges--ordered by
571                                          * Start GlyphID. rangeCount entries
572                                          * long */
573 };
574 ASSERT_SIZE (CoverageFormat2, 4);
575
576 struct Coverage {
577   DEFINE_NON_INSTANTIABLE(Coverage);
578
579   inline unsigned int get_size (void) const {
580     switch (u.coverageFormat) {
581     case 1: return u.format1.get_size ();
582     case 2: return u.format2.get_size ();
583     default:return sizeof (u.coverageFormat);
584     }
585   }
586
587   /* Returns -1 if not covered. */
588   inline int get_coverage (uint16_t glyph_id) const {
589     switch (u.coverageFormat) {
590     case 1: return u.format1.get_coverage(glyph_id);
591     case 2: return u.format2.get_coverage(glyph_id);
592     default:return -1;
593     }
594   }
595
596   private:
597   union {
598   USHORT                coverageFormat; /* Format identifier */
599   CoverageFormat1       format1;
600   CoverageFormat2       format2;
601   } u;
602 };
603
604 /*
605  * Class Definition Table
606  */
607
608 struct ClassDefFormat1 {
609   /* GlyphIDs, in sorted numerical order */
610   DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount);
611
612   inline int get_class (uint16_t glyph_id) const {
613     if (glyph_id >= startGlyph && glyph_id < startGlyph + glyphCount)
614       return classValueArray[glyph_id - startGlyph];
615     return 0;
616   }
617
618   private:
619   USHORT        classFormat;            /* Format identifier--format = 1 */
620   GlyphID       startGlyph;             /* First GlyphID of the classValueArray */
621   USHORT        glyphCount;             /* Size of the classValueArray */
622   USHORT        classValueArray[];      /* Array of Class Values--one per GlyphID */
623 };
624 ASSERT_SIZE (ClassDefFormat1, 6);
625
626 struct ClassRangeRecord {
627
628   inline int get_class (uint16_t glyph_id) const {
629     if (glyph_id >= start && glyph_id <= end)
630       return classValue;
631     return 0;
632   }
633
634   private:
635   GlyphID       start;          /* First GlyphID in the range */
636   GlyphID       end;            /* Last GlyphID in the range */
637   USHORT        classValue;     /* Applied to all glyphs in the range */
638 };
639 ASSERT_SIZE (ClassRangeRecord, 6);
640
641 struct ClassDefFormat2 {
642   /* ClassRangeRecords, in sorted numerical start order */
643   DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount);
644
645   inline int get_class (uint16_t glyph_id) const {
646     // TODO: bsearch
647     for (int i = 0; i < rangeCount; i++) {
648       int classValue = rangeRecord[i].get_class (glyph_id);
649       if (classValue > 0)
650         return classValue;
651     }
652     return 0;
653   }
654
655   private:
656   USHORT                classFormat;    /* Format identifier--format = 2 */
657   USHORT                rangeCount;     /* Number of Number of ClassRangeRecords */
658   ClassRangeRecord      rangeRecord[];  /* Array of glyph ranges--ordered by
659                                          * Start GlyphID */
660 };
661 ASSERT_SIZE (ClassDefFormat2, 4);
662
663 struct ClassDef {
664   DEFINE_NON_INSTANTIABLE(ClassDef);
665
666   inline unsigned int get_size (void) const {
667     switch (u.classFormat) {
668     case 1: return u.format1.get_size ();
669     case 2: return u.format2.get_size ();
670     default:return sizeof (u.classFormat);
671     }
672   }
673
674   /* Returns 0 if not found. */
675   inline int get_class (uint16_t glyph_id) const {
676     switch (u.classFormat) {
677     case 1: u.format1.get_class(glyph_id);
678     case 2: u.format2.get_class(glyph_id);
679     default:return 0;
680     }
681   }
682
683   private:
684   union {
685   USHORT                classFormat;    /* Format identifier */
686   ClassDefFormat1       format1;
687   ClassDefFormat2       format2;
688   } u;
689 };
690
691 /*
692  * Device Tables
693  */
694
695 struct Device {
696
697   inline unsigned int get_size (void) const {
698     int count = endSize - startSize + 1;
699     if (count < 0) count = 0;
700     switch (deltaFormat) {
701     case 1: return sizeof (Device) + sizeof (USHORT) * ((count+7)/8);
702     case 2: return sizeof (Device) + sizeof (USHORT) * ((count+3)/4);
703     case 3: return sizeof (Device) + sizeof (USHORT) * ((count+1)/2);
704     default:return sizeof (Device);
705     }
706   }
707
708   inline int get_delta (int ppem_size) const {
709     if (ppem_size >= startSize && ppem_size <= endSize &&
710         deltaFormat >= 1 && deltaFormat <= 3) {
711       int s = ppem_size - startSize;
712       int f = deltaFormat;
713
714       uint16_t byte = deltaValue[s >> (4 - f)];
715       uint16_t bits = byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f));
716       uint16_t mask = 0xFFFF >> (16 - (1 << f));
717       
718       int delta = bits & mask;
719
720       if (delta >= ((mask + 1) >> 1))
721         delta -= mask + 1;
722
723       return delta;
724     }
725     return 0;
726   }
727
728   private:
729   USHORT        startSize;      /* Smallest size to correct--in ppem */
730   USHORT        endSize;        /* Largest size to correct--in ppem */
731   USHORT        deltaFormat;    /* Format of DeltaValue array data: 1, 2, or 3 */
732   USHORT        deltaValue[];   /* Array of compressed data */
733 };
734 ASSERT_SIZE (Device, 6);
735
736
737
738 #define DEFINE_LIST_ACCESSOR0(const, Type, name) \
739   inline const Type##List* get_##name##_list (void) const { \
740     assert (name##List); \
741     return (const Type##List *)((const char*)this + name##List); \
742   } \
743   inline const Type& name (unsigned int i) const { \
744     return (*get_##name##_list())[i]; \
745   }
746 #define DEFINE_LIST_ACCESSOR(Type, name) \
747         DEFINE_LIST_ACCESSOR0(const, Type, name) \
748         DEFINE_LIST_ACCESSOR0(     , Type, name)
749
750 struct GSUBGPOSHeader {
751
752 /*
753   inline unsigned int get_size (void) const {
754     return offsetof (GSUBGPOSHeader, padding);
755   }
756   */
757
758   DEFINE_LIST_ACCESSOR(Script, script);  /* get_script_list and script(i) */
759   DEFINE_LIST_ACCESSOR(Feature, feature);/* get_feature_list and feature(i) */
760   DEFINE_LIST_ACCESSOR(Lookup, lookup);  /* get_lookup_list and lookup(i) */
761
762   private:
763   Fixed_Version version;        /* Version of the GSUB/GPOS table--initially set
764                                  * to 0x00010000 */
765   Offset        scriptList;     /* Offset to ScriptList table--from beginning of
766                                  * GSUB/GPOS table */
767   Offset        featureList;    /* Offset to FeatureList table--from beginning of
768                                  * GSUB/GPOS table */
769   Offset        lookupList;     /* Offset to LookupList table--from beginning of
770                                  * GSUB/GPOS table */
771 };
772 ASSERT_SIZE (GSUBGPOSHeader, 10);
773
774 #endif /* HARFBUZZ_OPEN_PRIVATE_H */