hb-ot-layout-open-private.h 29.0 KB
Newer Older
B
Behdad Esfahbod 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright (C) 2007,2008  Red Hat, Inc.
 *
 *  This is part of HarfBuzz, an OpenType Layout engine library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Red Hat Author(s): Behdad Esfahbod
 */

27 28
#ifndef HB_OT_LAYOUT_OPEN_PRIVATE_H
#define HB_OT_LAYOUT_OPEN_PRIVATE_H
29

B
Behdad Esfahbod 已提交
30
#ifndef HB_OT_LAYOUT_CC
31
#error "This file should only be included from hb-ot-layout.cc"
B
Behdad Esfahbod 已提交
32 33
#endif

B
Behdad Esfahbod 已提交
34
#include "hb-ot-layout-private.h"
35

B
Behdad Esfahbod 已提交
36

37
#define NO_INDEX		((unsigned int) 0xFFFF)
B
Behdad Esfahbod 已提交
38
#define NO_CONTEXT		((unsigned int) -1)
39 40 41
#define NOT_COVERED		((unsigned int) -1)
#define MAX_NESTING_LEVEL	32

42

B
Behdad Esfahbod 已提交
43 44 45 46
/*
 * Int types
 */

B
Behdad Esfahbod 已提交
47
/* XXX define these as structs of chars on machines that do not allow
48
 * unaligned access (using templates?). */
49
#define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN) \
B
Behdad Esfahbod 已提交
50 51 52
  inline NAME& operator = (TYPE i) { v = BIG_ENDIAN(i); return *this; } \
  inline operator TYPE(void) const { return BIG_ENDIAN(v); } \
  inline bool operator== (NAME o) const { return v == o.v; } \
53
  private: TYPE v; \
54
  public:
55 56
#define DEFINE_INT_TYPE0(NAME, type) DEFINE_INT_TYPE1 (NAME, type, hb_be_##type)
#define DEFINE_INT_TYPE(NAME, u, w)  DEFINE_INT_TYPE0 (NAME, u##int##w##_t)
57 58 59
#define DEFINE_INT_TYPE_STRUCT(NAME, u, w) \
  struct NAME { \
    DEFINE_INT_TYPE(NAME, u, w) \
60 61
  }; \
  ASSERT_SIZE (NAME, w / 8)
B
Behdad Esfahbod 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74

/*
 * Array types
 */

/* get_len() is a method returning the number of items in an array-like object */
#define DEFINE_LEN(Type, array, num) \
  inline unsigned int get_len(void) const { return num; } \

/* An array type is one that contains a variable number of objects
 * as its last item.  An array object is extended with len() and size()
 * methods, as well as overloaded [] operator. */
#define DEFINE_ARRAY_TYPE(Type, array, num) \
75
  DEFINE_INDEX_OPERATOR(Type, array, num) \
B
Behdad Esfahbod 已提交
76
  DEFINE_LEN(Type, array, num)
77
#define DEFINE_INDEX_OPERATOR(Type, array, num) \
B
Behdad Esfahbod 已提交
78
  inline const Type& operator[] (unsigned int i) const { \
79
    if (HB_UNLIKELY (i >= num)) return Null(Type); \
B
Behdad Esfahbod 已提交
80 81 82 83 84 85 86
    return array[i]; \
  }

/* An offset array type is like an array type, but it contains a table
 * of offsets to the objects, relative to the beginning of the current
 * object. */
#define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
87
  DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
B
Behdad Esfahbod 已提交
88
  DEFINE_LEN(Offset, array, num)
89
#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
B
Behdad Esfahbod 已提交
90
  inline const Type& operator[] (unsigned int i) const { \
91 92
    if (HB_UNLIKELY (i >= num)) return Null(Type); \
    if (HB_UNLIKELY (!array[i])) return Null(Type); \
B
Behdad Esfahbod 已提交
93 94 95
    return *(const Type *)((const char*)this + array[i]); \
  }

B
Behdad Esfahbod 已提交
96 97 98
/* A record array type is like an array type, but it contains a table
 * of records to the objects.  Each record has a tag, and an offset
 * relative to the beginning of the current object. */
B
Behdad Esfahbod 已提交
99
#define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \
100
  DEFINE_RECORD_ACCESSOR(Type, array, num) \
B
Behdad Esfahbod 已提交
101
  DEFINE_LEN(Record, array, num)
102
#define DEFINE_RECORD_ACCESSOR(Type, array, num) \
B
Behdad Esfahbod 已提交
103
  inline const Type& operator[] (unsigned int i) const { \
104 105
    if (HB_UNLIKELY (i >= num)) return Null(Type); \
    if (HB_UNLIKELY (!array[i].offset)) return Null(Type); \
B
Behdad Esfahbod 已提交
106 107
    return *(const Type *)((const char*)this + array[i].offset); \
  } \
108
  inline const Tag& get_tag (unsigned int i) const { \
109
    if (HB_UNLIKELY (i >= num)) return Null(Tag); \
110 111
    return array[i].tag; \
  }
B
Behdad Esfahbod 已提交
112

B
Behdad Esfahbod 已提交
113 114 115 116 117 118 119 120 121 122

#define DEFINE_ARRAY_INTERFACE(Type, name) \
  inline const Type& get_##name (unsigned int i) const { \
    return (*this)[i]; \
  } \
  inline unsigned int get_##name##_count (void) const { \
    return this->get_len (); \
  }
#define DEFINE_INDEX_ARRAY_INTERFACE(name) \
  inline unsigned int get_##name##_index (unsigned int i) const { \
123
    if (HB_UNLIKELY (i >= get_len ())) return NO_INDEX; \
B
Behdad Esfahbod 已提交
124 125 126
    return (*this)[i]; \
  } \
  inline unsigned int get_##name##_count (void) const { \
127
    return get_len (); \
B
Behdad Esfahbod 已提交
128 129 130
  }


131 132 133
/*
 * List types
 */
B
Behdad Esfahbod 已提交
134

135
#define DEFINE_LIST_ARRAY(Type, name) \
136
  inline const Type##List& get_##name##_list (void) const { \
137
    if (HB_UNLIKELY (!name##List)) return Null(Type##List); \
138
    return *(const Type##List *)((const char*)this + name##List); \
139 140 141
  }

#define DEFINE_LIST_INTERFACE(Type, name) \
142
  inline const Type& get_##name (unsigned int i) const { \
143 144 145 146 147 148 149 150 151 152 153 154
    return get_##name##_list ()[i]; \
  } \
  inline unsigned int get_##name##_count (void) const { \
    return get_##name##_list ().get_len (); \
  }

/*
 * Tag types
 */

#define DEFINE_TAG_ARRAY_INTERFACE(Type, name) \
  DEFINE_ARRAY_INTERFACE (Type, name); \
155
  inline const Tag& get_##name##_tag (unsigned int i) const { \
156 157 158 159 160 161 162 163 164
    return (*this)[i].tag; \
  }
#define DEFINE_TAG_LIST_INTERFACE(Type, name) \
  DEFINE_LIST_INTERFACE (Type, name); \
  inline const Tag& get_##name##_tag (unsigned int i) const { \
    return get_##name##_list ().get_tag (i); \
  }

#define DEFINE_TAG_FIND_INTERFACE(Type, name) \
165 166 167 168 169 170 171 172 173 174
  inline bool find_##name##_index (hb_tag_t tag, unsigned int *name##_index) const { \
    const Tag t = tag; \
    for (unsigned int i = 0; i < get_##name##_count (); i++) { \
      if (t == get_##name##_tag (i)) { \
        if (name##_index) *name##_index = i; \
        return true; \
      } \
    } \
    if (name##_index) *name##_index = NO_INDEX; \
    return false; \
175 176
  } \
  inline const Type& get_##name##_by_tag (hb_tag_t tag) const { \
177 178 179
    unsigned int i; \
    if (find_##name##_index (tag, &i)) \
      return get_##name (i); \
180
    else \
181
      return Null(Type); \
182
  }
183 184 185 186 187

/*
 * Class features
 */

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

/* Null objects */

/* Global nul-content Null pool.  Enlarge as necessary. */
static const char NullPool[16] = "";

/* Generic template for nul-content sizeof-sized Null objects. */
template <typename Type>
struct NullSize {
  char bytes[sizeof (Type)];
};
template <typename Type>
struct Null {
  ASSERT_STATIC (sizeof (NullSize<Type>) <= sizeof (NullPool));
  static inline const Type &get () { return (const Type&) *(const Type*) NullPool; }
};

/* Specializaiton for nul-content arbitrary-sized Null objects. */
206
#define DEFINE_NULL(Type, size) \
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
template <> \
struct NullSize <Type> { \
  char bytes[size]; \
}

/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
#define DEFINE_NULL_DATA(Type, size, data) \
template <> \
struct Null <Type> { \
  static inline const Type &get () { static const char bytes[size] = data; return (const Type&) *(const Type*) bytes; } \
}

/* Accessor macro. */
#define Null(Type) (Null<Type>::get())


#define ASSERT_SIZE_DATA(Type, size, data) \
224 225 226
  ASSERT_SIZE (Type, size); \
  DEFINE_NULL_DATA (Type, size, data)

227 228
/* get_for_data() is a static class method returning a reference to an
 * instance of Type located at the input data location.  It's just a
B
Behdad Esfahbod 已提交
229
 * fancy, NULL-safe, cast! */
B
Behdad Esfahbod 已提交
230
#define STATIC_DEFINE_GET_FOR_DATA(Type) \
231
  static inline const Type& get_for_data (const char *data) { \
232
    if (HB_UNLIKELY (data == NULL)) return Null(Type); \
233
    return *(const Type*)data; \
B
Behdad Esfahbod 已提交
234 235 236
  } \
  static inline Type& get_for_data (char *data) { \
    return *(Type*)data; \
237 238 239
  }


B
Behdad Esfahbod 已提交
240 241
#define DEFINE_GET_ACCESSOR(Type, name, Name) \
  inline const Type& get_##name (void) const { \
242
    if (HB_UNLIKELY (!Name)) return Null(Type); \
243 244
    return *(const Type*)((const char*)this + Name); \
  }
B
Behdad Esfahbod 已提交
245 246 247 248 249
#define DEFINE_GET_HAS_ACCESSOR(Type, name, Name) \
  DEFINE_GET_ACCESSOR (Type, name, Name); \
  inline bool has_##name (void) const { \
    return Name != 0; \
  }
250 251


252

B
Behdad Esfahbod 已提交
253

B
Behdad Esfahbod 已提交
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
/*
 *
 * The OpenType Font File
 *
 */



/*
 * Data Types
 */


/* "The following data types are used in the OpenType font file.
 *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */


B
Behdad Esfahbod 已提交
271 272 273
DEFINE_INT_TYPE_STRUCT (BYTE,	 u,  8);	/*  8-bit unsigned integer. */
DEFINE_INT_TYPE_STRUCT (CHAR,	  ,  8);	/*  8-bit signed integer. */
DEFINE_INT_TYPE_STRUCT (USHORT,  u, 16);	/* 16-bit unsigned integer. */
274 275 276
DEFINE_INT_TYPE_STRUCT (SHORT,	  , 16);	/* 16-bit signed integer. */
DEFINE_INT_TYPE_STRUCT (ULONG,	 u, 32);	/* 32-bit unsigned integer. */
DEFINE_INT_TYPE_STRUCT (LONG,	  , 32);	/* 32-bit signed integer. */
277 278 279

/* Date represented in number of seconds since 12:00 midnight, January 1,
 * 1904. The value is represented as a signed 64-bit integer. */
280
DEFINE_INT_TYPE_STRUCT (LONGDATETIME, , 64);
281 282

/* 32-bit signed fixed-point number (16.16) */
B
Behdad Esfahbod 已提交
283 284 285 286 287
struct Fixed {
  inline Fixed& operator = (int32_t v) { i = (int16_t) (v >> 16); f = (uint16_t) v; return *this; } \
  inline operator int32_t(void) const { return (((int32_t) i) << 16) + (uint16_t) f; } \
  inline bool operator== (Fixed o) const { return i == o.i && f == o.f; } \

B
Behdad Esfahbod 已提交
288
  inline operator double(void) const { return (uint32_t) this / 65536.; }
B
Behdad Esfahbod 已提交
289 290 291 292 293 294
  inline int16_t int_part (void) const { return i; }
  inline uint16_t frac_part (void) const { return f; }

  private:
  SHORT i;
  USHORT f;
295
};
296
ASSERT_SIZE (Fixed, 4);
297 298

/* Smallest measurable distance in the em space. */
B
Behdad Esfahbod 已提交
299
struct FUNIT;
300 301

/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
B
Behdad Esfahbod 已提交
302
struct FWORD : SHORT {
303
};
304
ASSERT_SIZE (FWORD, 2);
305 306

/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
B
Behdad Esfahbod 已提交
307
struct UFWORD : USHORT {
308
};
309
ASSERT_SIZE (UFWORD, 2);
310 311

/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
B
Behdad Esfahbod 已提交
312
struct F2DOT14 : SHORT {
B
Behdad Esfahbod 已提交
313
  inline operator double() const { return (uint32_t) this / 16384.; }
314
};
315
ASSERT_SIZE (F2DOT14, 2);
316 317 318

/* Array of four uint8s (length = 32 bits) used to identify a script, language
 * system, feature, or baseline */
B
Behdad Esfahbod 已提交
319 320
struct Tag {
  inline Tag (void) { v[0] = v[1] = v[2] = v[3] = 0; }
B
LangSys  
Behdad Esfahbod 已提交
321
  inline Tag (uint32_t v) { (ULONG&)(*this) = v; }
B
Behdad Esfahbod 已提交
322
  inline Tag (const char *c) { v[0] = c[0]; v[1] = c[1]; v[2] = c[2]; v[3] = c[3]; }
B
LangSys  
Behdad Esfahbod 已提交
323
  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]; }
B
Behdad Esfahbod 已提交
324
  inline bool operator== (const char *c) const { return v[0]==c[0]&&v[1]==c[1]&&v[2]==c[2]&&v[3]==c[3]; }
B
Behdad Esfahbod 已提交
325
  inline bool operator== (uint32_t i) const { return i == (uint32_t) *this; }
B
LangSys  
Behdad Esfahbod 已提交
326 327
  inline operator uint32_t(void) const { return (v[0]<<24)+(v[1]<<16) +(v[2]<<8)+v[3]; }
  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
B
Behdad Esfahbod 已提交
328 329 330
  inline operator const char* (void) const { return (const char *)this; }
  inline operator char* (void) { return (char *)this; }

B
Behdad Esfahbod 已提交
331 332
  private:
  char v[4];
333
};
B
Behdad Esfahbod 已提交
334
ASSERT_SIZE (Tag, 4);
335
DEFINE_NULL_DATA (Tag, 5, "    ");
336 337

/* Glyph index number, same as uint16 (length = 16 bits) */
338
DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16);
339

340
/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
341
DEFINE_INT_TYPE_STRUCT (Offset, u, 16);
342

343 344

/* CheckSum */
B
Behdad Esfahbod 已提交
345 346
struct CheckSum : ULONG {
  static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) {
347
    uint32_t Sum = 0L;
B
Behdad Esfahbod 已提交
348
    ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
349 350 351 352 353 354

    while (Table < EndPtr)
      Sum += *Table++;
    return Sum;
  }
};
355
ASSERT_SIZE (CheckSum, 4);
356 357 358 359 360 361


/*
 * Version Numbers
 */

B
Behdad Esfahbod 已提交
362
struct USHORT_Version : USHORT {
363
};
364
ASSERT_SIZE (USHORT_Version, 2);
365

B
Behdad Esfahbod 已提交
366
struct Fixed_Version : Fixed {
B
Behdad Esfahbod 已提交
367 368
  inline int16_t major (void) const { return this->int_part(); }
  inline int16_t minor (void) const { return this->frac_part(); }
369
};
370
ASSERT_SIZE (Fixed_Version, 4);
371 372 373 374 375 376


/*
 * Organization of an OpenType Font
 */

377
struct OpenTypeFontFile;
B
Behdad Esfahbod 已提交
378 379 380
struct OffsetTable;
struct TTCHeader;

B
Behdad Esfahbod 已提交
381
typedef struct TableDirectory {
B
Behdad Esfahbod 已提交
382

B
Behdad Esfahbod 已提交
383
  friend struct OpenTypeFontFile;
B
Behdad Esfahbod 已提交
384
  friend struct OffsetTable;
B
Behdad Esfahbod 已提交
385

B
Behdad Esfahbod 已提交
386
  inline bool is_null (void) const { return length == 0; }
387
  inline const Tag& get_tag (void) const { return tag; }
B
Behdad Esfahbod 已提交
388 389 390 391 392
  inline unsigned long get_checksum (void) const { return checkSum; }
  inline unsigned long get_offset (void) const { return offset; }
  inline unsigned long get_length (void) const { return length; }

  private:
B
Behdad Esfahbod 已提交
393 394 395
  Tag		tag;		/* 4-byte identifier. */
  CheckSum	checkSum;	/* CheckSum for this table. */
  ULONG		offset;		/* Offset from beginning of TrueType font
396
				 * file. */
B
Behdad Esfahbod 已提交
397
  ULONG		length;		/* Length of this table. */
B
Behdad Esfahbod 已提交
398
} OpenTypeTable;
399
ASSERT_SIZE (TableDirectory, 16);
400

B
Behdad Esfahbod 已提交
401
typedef struct OffsetTable {
B
Minor  
Behdad Esfahbod 已提交
402 403 404 405

  friend struct OpenTypeFontFile;
  friend struct TTCHeader;

406
  DEFINE_TAG_ARRAY_INTERFACE (OpenTypeTable, table);	/* get_table_count(), get_table(i), get_table_tag(i) */
407
  DEFINE_TAG_FIND_INTERFACE  (OpenTypeTable, table);	/* find_table_index(tag), get_table_by_tag(tag) */
B
Behdad Esfahbod 已提交
408 409

  private:
B
LangSys  
Behdad Esfahbod 已提交
410
  /* OpenTypeTables, in no particular order */
B
Behdad Esfahbod 已提交
411 412
  DEFINE_ARRAY_TYPE (TableDirectory, tableDir, numTables);

B
Behdad Esfahbod 已提交
413
  private:
B
Behdad Esfahbod 已提交
414 415 416 417 418 419
  Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
  USHORT	numTables;	/* Number of tables. */
  USHORT	searchRange;	/* (Maximum power of 2 <= numTables) x 16 */
  USHORT	entrySelector;	/* Log2(maximum power of 2 <= numTables). */
  USHORT	rangeShift;	/* NumTables x 16-searchRange. */
  TableDirectory tableDir[];	/* TableDirectory entries. numTables items */
420
} OpenTypeFontFace;
421
ASSERT_SIZE (OffsetTable, 12);
422 423 424 425 426

/*
 * TrueType Collections
 */

B
Behdad Esfahbod 已提交
427
struct TTCHeader {
B
Minor  
Behdad Esfahbod 已提交
428 429 430 431

  friend struct OpenTypeFontFile;

  private:
432
  /* OpenTypeFontFaces, in no particular order */
B
Behdad Esfahbod 已提交
433
  DEFINE_OFFSET_ARRAY_TYPE (OffsetTable, offsetTable, numFonts);
B
Behdad Esfahbod 已提交
434
  /* XXX check version here? */
B
Behdad Esfahbod 已提交
435

B
Behdad Esfahbod 已提交
436
  private:
B
Behdad Esfahbod 已提交
437
  Tag	ttcTag;		/* TrueType Collection ID string: 'ttcf' */
B
Behdad Esfahbod 已提交
438
  ULONG	version;	/* Version of the TTC Header (1.0 or 2.0),
439
			 * 0x00010000 or 0x00020000 */
B
Behdad Esfahbod 已提交
440
  ULONG	numFonts;	/* Number of fonts in TTC */
B
Behdad Esfahbod 已提交
441
  ULONG	offsetTable[];	/* Array of offsets to the OffsetTable for each font
B
Behdad Esfahbod 已提交
442
			 * from the beginning of the file */
443
};
444
ASSERT_SIZE (TTCHeader, 12);
445 446


B
Behdad Esfahbod 已提交
447 448 449 450
/*
 * OpenType Font File
 */

451
struct OpenTypeFontFile {
452

B
Behdad Esfahbod 已提交
453 454 455
  static const hb_tag_t TrueTypeTag	= HB_TAG ( 0 , 1 , 0 , 0 );
  static const hb_tag_t CFFTag		= HB_TAG ('O','T','T','O');
  static const hb_tag_t TTCTag		= HB_TAG ('t','t','c','f');
B
Behdad Esfahbod 已提交
456

457
  STATIC_DEFINE_GET_FOR_DATA (OpenTypeFontFile);
B
Behdad Esfahbod 已提交
458

459
  DEFINE_ARRAY_INTERFACE (OpenTypeFontFace, face);	/* get_face_count(), get_face(i) */
B
Behdad Esfahbod 已提交
460

461
  inline const Tag& get_tag (void) const { return tag; }
B
Behdad Esfahbod 已提交
462

B
Behdad Esfahbod 已提交
463
  /* This is how you get a table */
B
Behdad Esfahbod 已提交
464 465
  inline const char* get_table_data (const OpenTypeTable& table) const {
    return (*this)[table];
B
Behdad Esfahbod 已提交
466
  }
B
Behdad Esfahbod 已提交
467 468
  inline char* get_table_data (const OpenTypeTable& table) {
    return (*this)[table];
B
Behdad Esfahbod 已提交
469
  }
B
Behdad Esfahbod 已提交
470 471

  private:
B
Behdad Esfahbod 已提交
472
  inline const char* operator[] (const OpenTypeTable& table) const {
B
Behdad Esfahbod 已提交
473
    if (G_UNLIKELY (table.offset == 0)) return NULL;
B
Behdad Esfahbod 已提交
474 475 476
    return ((const char*)this) + table.offset;
  }
  inline char* operator[] (const OpenTypeTable& table) {
B
Behdad Esfahbod 已提交
477
    if (G_UNLIKELY (table.offset == 0)) return NULL;
B
Behdad Esfahbod 已提交
478 479 480
    return ((char*)this) + table.offset;
  }

B
Minor  
Behdad Esfahbod 已提交
481
  unsigned int get_len (void) const {
B
Behdad Esfahbod 已提交
482
    switch (tag) {
B
Behdad Esfahbod 已提交
483
    default: return 0;
B
Behdad Esfahbod 已提交
484 485
    case TrueTypeTag: case CFFTag: return 1;
    case TTCTag: return ((const TTCHeader&)*this).get_len();
B
Behdad Esfahbod 已提交
486 487
    }
  }
B
Minor  
Behdad Esfahbod 已提交
488
  const OpenTypeFontFace& operator[] (unsigned int i) const {
489
    if (HB_UNLIKELY (i >= get_len ())) return Null(OpenTypeFontFace);
B
Behdad Esfahbod 已提交
490
    switch (tag) {
B
Behdad Esfahbod 已提交
491 492
    default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this;
    case TTCTag: return ((const TTCHeader&)*this)[i];
B
Behdad Esfahbod 已提交
493 494 495
    }
  }

B
Behdad Esfahbod 已提交
496
  private:
B
Behdad Esfahbod 已提交
497
  Tag		tag;		/* 4-byte identifier. */
B
Behdad Esfahbod 已提交
498
};
499
ASSERT_SIZE (OpenTypeFontFile, 4);
500 501 502 503 504 505 506 507 508



/*
 *
 * OpenType Layout Common Table Formats
 *
 */

509
/*
510
 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
511 512
 */

B
Behdad Esfahbod 已提交
513 514 515 516 517
typedef struct Record {
  Tag		tag;		/* 4-byte Tag identifier */
  Offset	offset;		/* Offset from beginning of object holding
				 * the Record */
} ScriptRecord, LangSysRecord, FeatureRecord;
518
ASSERT_SIZE (Record, 6);
519

B
Behdad Esfahbod 已提交
520
struct LangSys {
B
Behdad Esfahbod 已提交
521 522 523

  DEFINE_INDEX_ARRAY_INTERFACE (feature);

524 525 526 527
  inline const bool has_required_feature (void) const {
    return reqFeatureIndex != 0xffff;
  }
  /* Returns NO_INDEX if none */
B
LangSys  
Behdad Esfahbod 已提交
528 529
  inline int get_required_feature_index (void) const {
    if (reqFeatureIndex == 0xffff)
530
      return NO_INDEX;
B
LangSys  
Behdad Esfahbod 已提交
531 532
    return reqFeatureIndex;;
  }
533

B
Behdad Esfahbod 已提交
534 535 536
  private:
  /* Feature indices, in no particular order */
  DEFINE_ARRAY_TYPE (USHORT, featureIndex, featureCount);
B
Behdad Esfahbod 已提交
537

B
Behdad Esfahbod 已提交
538
  private:
539
  Offset	lookupOrder;	/* = Null (reserved for an offset to a
B
LangSys  
Behdad Esfahbod 已提交
540 541 542 543 544 545 546 547
				 * reordering table) */
  USHORT	reqFeatureIndex;/* Index of a feature required for this
				 * language system--if no required features
				 * = 0xFFFF */
  USHORT	featureCount;	/* Number of FeatureIndex values for this
				 * language system--excludes the required
				 * feature */
  USHORT	featureIndex[];	/* Array of indices into the FeatureList--in
B
Behdad Esfahbod 已提交
548
				 * arbitrary order. featureCount entires long */
B
Behdad Esfahbod 已提交
549
};
550
ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
B
Behdad Esfahbod 已提交
551

552 553
struct Script {

554 555 556 557 558 559 560 561 562
  /* DEFINE_ARRAY_INTERFACE (LangSys, lang_sys) but handling defaultLangSys */

  inline const LangSys& get_lang_sys (unsigned int i) const {
    if (i == NO_INDEX) return get_default_lang_sys ();
    return (*this)[i];
  }
  inline unsigned int get_lang_sys_count (void) const {
    return this->get_len ();
  }
563 564 565 566 567

  inline const Tag& get_lang_sys_tag (unsigned int i) const {
    return get_tag (i);
  }

568
  // LONGTERMTODO bsearch
569
  DEFINE_TAG_FIND_INTERFACE (LangSys, lang_sys);	/* find_lang_sys_index (), get_lang_sys_by_tag (tag) */
570 571

  inline const bool has_default_lang_sys (void) const {
572 573
    return defaultLangSys != 0;
  }
574
  inline const LangSys& get_default_lang_sys (void) const {
575
    if (HB_UNLIKELY (!defaultLangSys))
576
      return Null(LangSys);
577 578 579
    return *(LangSys*)((const char*)this + defaultLangSys);
  }

580 581 582
  private:
  /* LangSys', in sorted alphabetical tag order */
  DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
B
Behdad Esfahbod 已提交
583

B
Behdad Esfahbod 已提交
584
  private:
585 586 587 588 589 590
  Offset	defaultLangSys;	/* Offset to DefaultLangSys table--from
				 * beginning of Script table--may be Null */
  USHORT	langSysCount;	/* Number of LangSysRecords for this script--
				 * excluding the DefaultLangSys */
  LangSysRecord	langSysRecord[];/* Array of LangSysRecords--listed
				 * alphabetically by LangSysTag */
B
Behdad Esfahbod 已提交
591
};
592
ASSERT_SIZE (Script, 4);
593 594

struct ScriptList {
595 596 597 598

  friend struct GSUBGPOS;

private:
599 600 601 602 603 604 605 606
  /* Scripts, in sorted alphabetical tag order */
  DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);

private:
  USHORT	scriptCount;	/* Number of ScriptRecords */
  ScriptRecord	scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
				 * by ScriptTag */
};
607
ASSERT_SIZE (ScriptList, 2);
B
Behdad Esfahbod 已提交
608 609

struct Feature {
B
Behdad Esfahbod 已提交
610

B
Behdad Esfahbod 已提交
611
  DEFINE_INDEX_ARRAY_INTERFACE (lookup);	/* get_lookup_count(), get_lookup_index(i) */
B
Behdad Esfahbod 已提交
612 613

  private:
B
Behdad Esfahbod 已提交
614 615 616
  /* LookupList indices, in no particular order */
  DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);

B
Behdad Esfahbod 已提交
617 618 619
  /* TODO: implement get_feature_parameters() */
  /* TODO: implement FeatureSize and other special features? */

B
Behdad Esfahbod 已提交
620
  private:
B
Behdad Esfahbod 已提交
621 622
  Offset	featureParams;	/* Offset to Feature Parameters table (if one
				 * has been defined for the feature), relative
B
Behdad Esfahbod 已提交
623
				 * to the beginning of the Feature Table; = Null
B
Behdad Esfahbod 已提交
624 625 626 627 628
				 * if not required */
  USHORT	lookupCount;	/* Number of LookupList indices for this
				 * feature */
  USHORT	lookupIndex[];	/* Array of LookupList indices for this
				 * feature--zero-based (first lookup is
B
Behdad Esfahbod 已提交
629
				 * LookupListIndex = 0) */
B
Behdad Esfahbod 已提交
630
};
631
ASSERT_SIZE (Feature, 4);
B
Behdad Esfahbod 已提交
632

633
struct FeatureList {
634 635 636 637

  friend struct GSUBGPOS;

  private:
638 639
  /* Feature indices, in sorted alphabetical tag order */
  DEFINE_RECORD_ARRAY_TYPE (Feature, featureRecord, featureCount);
B
Behdad Esfahbod 已提交
640

B
Behdad Esfahbod 已提交
641
  private:
642 643 644 645
  USHORT	featureCount;	/* Number of FeatureRecords in this table */
  FeatureRecord	featureRecord[];/* Array of FeatureRecords--zero-based (first
				 * feature has FeatureIndex = 0)--listed
				 * alphabetically by FeatureTag */
B
Behdad Esfahbod 已提交
646
};
647
ASSERT_SIZE (FeatureList, 2);
B
Behdad Esfahbod 已提交
648 649

struct LookupFlag : USHORT {
B
Behdad Esfahbod 已提交
650 651 652 653 654 655
  static const unsigned int RightToLeft		= 0x0001u;
  static const unsigned int IgnoreBaseGlyphs	= 0x0002u;
  static const unsigned int IgnoreLigatures	= 0x0004u;
  static const unsigned int IgnoreMarks		= 0x0008u;
  static const unsigned int Reserved		= 0x00F0u;
  static const unsigned int MarkAttachmentType	= 0xFF00u;
B
Behdad Esfahbod 已提交
656
};
657
ASSERT_SIZE (LookupFlag, 2);
658 659 660 661 662

struct LookupSubTable {
  private:
  USHORT	format;		/* Subtable format.  Different for GSUB and GPOS */
};
663
ASSERT_SIZE (LookupSubTable, 2);
664

B
Behdad Esfahbod 已提交
665 666

struct Lookup {
B
Behdad Esfahbod 已提交
667
  DEFINE_ARRAY_INTERFACE (LookupSubTable, subtable);	/* get_subtable_count(), get_subtable(i) */
B
Behdad Esfahbod 已提交
668 669 670 671 672

  inline bool is_right_to_left	(void) const { return lookupFlag & LookupFlag::RightToLeft; }
  inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
  inline bool ignore_ligatures	(void) const { return lookupFlag & LookupFlag::IgnoreLigatures; }
  inline bool ignore_marks	(void) const { return lookupFlag & LookupFlag::IgnoreMarks; }
B
Behdad Esfahbod 已提交
673
  inline unsigned int get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; }
B
Behdad Esfahbod 已提交
674

B
Behdad Esfahbod 已提交
675 676
  inline unsigned int get_type (void) const { return lookupType; }
  inline unsigned int get_flag (void) const { return lookupFlag; }
B
Behdad Esfahbod 已提交
677 678

  private:
B
Behdad Esfahbod 已提交
679 680 681 682
  /* SubTables, in the desired order */
  DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);

  protected:
B
Behdad Esfahbod 已提交
683 684 685 686
  USHORT	lookupType;	/* Different enumerations for GSUB and GPOS */
  USHORT	lookupFlag;	/* Lookup qualifiers */
  USHORT	subTableCount;	/* Number of SubTables for this lookup */
  Offset	subTableOffset[];/* Array of offsets to SubTables-from
B
Behdad Esfahbod 已提交
687
				  * beginning of Lookup table */
B
Behdad Esfahbod 已提交
688
};
689
ASSERT_SIZE (Lookup, 6);
690 691

struct LookupList {
692 693 694 695

  friend struct GSUBGPOS;

  private:
696 697 698 699 700 701 702 703 704
  /* Lookup indices, in sorted alphabetical tag order */
  DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);

  private:
  USHORT	lookupCount;	/* Number of lookups in this table */
  Offset	lookupOffset[];	/* Array of offsets to Lookup tables--from
				 * beginning of LookupList--zero based (first
				 * lookup is Lookup index = 0) */
};
705
ASSERT_SIZE (LookupList, 2);
B
Behdad Esfahbod 已提交
706

707
/*
B
Behdad Esfahbod 已提交
708
 * Coverage Table
709 710
 */

B
Behdad Esfahbod 已提交
711
struct CoverageFormat1 {
B
Minor  
Behdad Esfahbod 已提交
712 713 714 715

  friend struct Coverage;

  private:
B
Behdad Esfahbod 已提交
716 717 718
  /* GlyphIDs, in sorted numerical order */
  DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);

719
  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
B
Behdad Esfahbod 已提交
720
    GlyphID gid;
B
Behdad Esfahbod 已提交
721
    if (HB_UNLIKELY (glyph_id > 65535))
722
      return NOT_COVERED;
B
Behdad Esfahbod 已提交
723
    gid = glyph_id;
B
Behdad Esfahbod 已提交
724
    // TODO: bsearch
725
    for (unsigned int i = 0; i < glyphCount; i++)
B
Behdad Esfahbod 已提交
726 727
      if (gid == glyphArray[i])
        return i;
728
    return NOT_COVERED;
B
Behdad Esfahbod 已提交
729 730
  }

B
Behdad Esfahbod 已提交
731
  private:
B
Behdad Esfahbod 已提交
732 733 734
  USHORT	coverageFormat;	/* Format identifier--format = 1 */
  USHORT	glyphCount;	/* Number of glyphs in the GlyphArray */
  GlyphID	glyphArray[];	/* Array of GlyphIDs--in numerical order */
B
Behdad Esfahbod 已提交
735
};
B
Behdad Esfahbod 已提交
736
ASSERT_SIZE (CoverageFormat1, 4);
B
Behdad Esfahbod 已提交
737

738
struct CoverageRangeRecord {
B
Behdad Esfahbod 已提交
739

B
Minor  
Behdad Esfahbod 已提交
740 741 742
  friend struct CoverageFormat2;

  private:
743
  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
B
Behdad Esfahbod 已提交
744 745
    if (glyph_id >= start && glyph_id <= end)
      return startCoverageIndex + (glyph_id - start);
746
    return NOT_COVERED;
B
Behdad Esfahbod 已提交
747 748
  }

B
Behdad Esfahbod 已提交
749
  private:
B
Behdad Esfahbod 已提交
750 751 752 753 754
  GlyphID	start;			/* First GlyphID in the range */
  GlyphID	end;			/* Last GlyphID in the range */
  USHORT	startCoverageIndex;	/* Coverage Index of first GlyphID in
					 * range */
};
755
ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\001");
B
Behdad Esfahbod 已提交
756 757

struct CoverageFormat2 {
B
Minor  
Behdad Esfahbod 已提交
758 759 760 761

  friend struct Coverage;

  private:
762 763
  /* CoverageRangeRecords, in sorted numerical start order */
  DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
B
Behdad Esfahbod 已提交
764

765
  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
B
Behdad Esfahbod 已提交
766
    // TODO: bsearch
B
Behdad Esfahbod 已提交
767 768
    unsigned int count = rangeCount;
    for (unsigned int i = 0; i < count; i++) {
B
Behdad Esfahbod 已提交
769 770 771 772
      int coverage = rangeRecord[i].get_coverage (glyph_id);
      if (coverage >= 0)
        return coverage;
    }
773
    return NOT_COVERED;
B
Behdad Esfahbod 已提交
774 775
  }

B
Behdad Esfahbod 已提交
776
  private:
B
Behdad Esfahbod 已提交
777 778 779
  USHORT		coverageFormat;	/* Format identifier--format = 2 */
  USHORT		rangeCount;	/* Number of CoverageRangeRecords */
  CoverageRangeRecord	rangeRecord[];	/* Array of glyph ranges--ordered by
B
Behdad Esfahbod 已提交
780 781 782
					 * Start GlyphID. rangeCount entries
					 * long */
};
B
Behdad Esfahbod 已提交
783
ASSERT_SIZE (CoverageFormat2, 4);
B
Behdad Esfahbod 已提交
784

785
struct Coverage {
786
  unsigned int get_coverage (hb_codepoint_t glyph_id) const {
787 788 789
    switch (u.coverageFormat) {
    case 1: return u.format1.get_coverage(glyph_id);
    case 2: return u.format2.get_coverage(glyph_id);
790
    default:return NOT_COVERED;
B
Behdad Esfahbod 已提交
791 792 793
    }
  }

B
Behdad Esfahbod 已提交
794
  private:
795
  union {
B
Behdad Esfahbod 已提交
796 797 798
  USHORT		coverageFormat;	/* Format identifier */
  CoverageFormat1	format1;
  CoverageFormat2	format2;
799
  } u;
B
Behdad Esfahbod 已提交
800
};
801
DEFINE_NULL (Coverage, 2);
B
Behdad Esfahbod 已提交
802

B
Behdad Esfahbod 已提交
803
/*
B
Behdad Esfahbod 已提交
804
 * Class Definition Table
B
Behdad Esfahbod 已提交
805 806 807
 */

struct ClassDefFormat1 {
B
Minor  
Behdad Esfahbod 已提交
808 809 810 811

  friend struct ClassDef;

  private:
812
  /* Class Values, in sorted numerical order */
B
Behdad Esfahbod 已提交
813 814
  DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount);

B
Behdad Esfahbod 已提交
815
  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
B
Behdad Esfahbod 已提交
816
    if (glyph_id >= startGlyph && glyph_id - startGlyph < glyphCount)
B
Behdad Esfahbod 已提交
817 818 819 820
      return classValueArray[glyph_id - startGlyph];
    return 0;
  }

B
Behdad Esfahbod 已提交
821
  private:
B
Behdad Esfahbod 已提交
822 823 824 825 826
  USHORT	classFormat;		/* Format identifier--format = 1 */
  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
  USHORT	glyphCount;		/* Size of the classValueArray */
  USHORT	classValueArray[];	/* Array of Class Values--one per GlyphID */
};
B
Behdad Esfahbod 已提交
827
ASSERT_SIZE (ClassDefFormat1, 6);
B
Behdad Esfahbod 已提交
828 829 830

struct ClassRangeRecord {

B
Minor  
Behdad Esfahbod 已提交
831 832 833
  friend struct ClassDefFormat2;

  private:
B
Behdad Esfahbod 已提交
834
  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
B
Behdad Esfahbod 已提交
835 836 837 838 839
    if (glyph_id >= start && glyph_id <= end)
      return classValue;
    return 0;
  }

B
Behdad Esfahbod 已提交
840
  private:
B
Behdad Esfahbod 已提交
841 842
  GlyphID	start;		/* First GlyphID in the range */
  GlyphID	end;		/* Last GlyphID in the range */
B
Behdad Esfahbod 已提交
843
  USHORT	classValue;	/* Applied to all glyphs in the range */
B
Behdad Esfahbod 已提交
844
};
845
ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\001");
B
Behdad Esfahbod 已提交
846 847

struct ClassDefFormat2 {
B
Minor  
Behdad Esfahbod 已提交
848 849 850 851

  friend struct ClassDef;

  private:
B
Behdad Esfahbod 已提交
852 853 854
  /* ClassRangeRecords, in sorted numerical start order */
  DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount);

B
Behdad Esfahbod 已提交
855
  inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
B
Behdad Esfahbod 已提交
856
    // TODO: bsearch
B
Behdad Esfahbod 已提交
857 858
    unsigned int count = rangeCount;
    for (unsigned int i = 0; i < count; i++) {
B
Behdad Esfahbod 已提交
859 860 861 862 863 864 865
      int classValue = rangeRecord[i].get_class (glyph_id);
      if (classValue > 0)
        return classValue;
    }
    return 0;
  }

B
Behdad Esfahbod 已提交
866
  private:
B
Behdad Esfahbod 已提交
867
  USHORT		classFormat;	/* Format identifier--format = 2 */
B
Behdad Esfahbod 已提交
868
  USHORT		rangeCount;	/* Number of ClassRangeRecords */
B
Behdad Esfahbod 已提交
869 870 871
  ClassRangeRecord	rangeRecord[];	/* Array of glyph ranges--ordered by
					 * Start GlyphID */
};
B
Behdad Esfahbod 已提交
872
ASSERT_SIZE (ClassDefFormat2, 4);
B
Behdad Esfahbod 已提交
873 874

struct ClassDef {
B
Behdad Esfahbod 已提交
875
  hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
876
    switch (u.classFormat) {
B
Behdad Esfahbod 已提交
877 878
    case 1: return u.format1.get_class(glyph_id);
    case 2: return u.format2.get_class(glyph_id);
B
Behdad Esfahbod 已提交
879 880 881 882
    default:return 0;
    }
  }

B
Behdad Esfahbod 已提交
883
  private:
884
  union {
B
Behdad Esfahbod 已提交
885
  USHORT		classFormat;	/* Format identifier */
B
Behdad Esfahbod 已提交
886 887
  ClassDefFormat1	format1;
  ClassDefFormat2	format2;
888
  } u;
B
Behdad Esfahbod 已提交
889
};
890
DEFINE_NULL (ClassDef, 2);
B
Behdad Esfahbod 已提交
891

B
Behdad Esfahbod 已提交
892 893 894 895 896
/*
 * Device Tables
 */

struct Device {
B
Minor  
Behdad Esfahbod 已提交
897
  int get_delta (int ppem_size) const {
B
Behdad Esfahbod 已提交
898 899 900 901
    if (ppem_size >= startSize && ppem_size <= endSize &&
        deltaFormat >= 1 && deltaFormat <= 3) {
      int s = ppem_size - startSize;
      int f = deltaFormat;
B
Behdad Esfahbod 已提交
902

B
Behdad Esfahbod 已提交
903 904 905
      uint16_t byte = deltaValue[s >> (4 - f)];
      uint16_t bits = byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f));
      uint16_t mask = 0xFFFF >> (16 - (1 << f));
B
Behdad Esfahbod 已提交
906

B
Behdad Esfahbod 已提交
907 908 909 910 911 912 913 914 915 916
      int delta = bits & mask;

      if (delta >= ((mask + 1) >> 1))
        delta -= mask + 1;

      return delta;
    }
    return 0;
  }

B
Behdad Esfahbod 已提交
917
  private:
B
Behdad Esfahbod 已提交
918 919 920 921 922
  USHORT	startSize;	/* Smallest size to correct--in ppem */
  USHORT	endSize;	/* Largest size to correct--in ppem */
  USHORT	deltaFormat;	/* Format of DeltaValue array data: 1, 2, or 3 */
  USHORT	deltaValue[];	/* Array of compressed data */
};
923
ASSERT_SIZE (Device, 6);
B
Behdad Esfahbod 已提交
924

925
/*
B
Behdad Esfahbod 已提交
926
 * GSUB/GPOS Common
927
 */
B
Behdad Esfahbod 已提交
928

B
Behdad Esfahbod 已提交
929
struct GSUBGPOS {
930 931 932
  static const hb_tag_t GSUBTag		= HB_TAG ('G','S','U','B');
  static const hb_tag_t GPOSTag		= HB_TAG ('G','P','O','S');

B
Behdad Esfahbod 已提交
933 934
  STATIC_DEFINE_GET_FOR_DATA (GSUBGPOS);
  /* XXX check version here? */
B
Behdad Esfahbod 已提交
935

936 937 938 939
  DEFINE_TAG_LIST_INTERFACE (Script,  script );	/* get_script_count (), get_script (i), get_script_tag (i) */
  DEFINE_TAG_LIST_INTERFACE (Feature, feature);	/* get_feature_count(), get_feature(i), get_feature_tag(i) */
  DEFINE_LIST_INTERFACE     (Lookup,  lookup );	/* get_lookup_count (), get_lookup (i) */

940
  // LONGTERMTODO bsearch
941 942
  DEFINE_TAG_FIND_INTERFACE (Script,  script );	/* find_script_index (), get_script_by_tag (tag) */
  DEFINE_TAG_FIND_INTERFACE (Feature, feature);	/* find_feature_index(), get_feature_by_tag(tag) */
943 944 945 946 947

  private:
  DEFINE_LIST_ARRAY(Script,  script);
  DEFINE_LIST_ARRAY(Feature, feature);
  DEFINE_LIST_ARRAY(Lookup,  lookup);
B
Behdad Esfahbod 已提交
948 949

  private:
950 951 952 953 954 955 956 957
  Fixed_Version	version;	/* Version of the GSUB/GPOS table--initially set
				 * to 0x00010000 */
  Offset	scriptList;  	/* Offset to ScriptList table--from beginning of
				 * GSUB/GPOS table */
  Offset	featureList; 	/* Offset to FeatureList table--from beginning of
				 * GSUB/GPOS table */
  Offset	lookupList; 	/* Offset to LookupList table--from beginning of
				 * GSUB/GPOS table */
B
Behdad Esfahbod 已提交
958
};
959
ASSERT_SIZE (GSUBGPOS, 10);
B
Behdad Esfahbod 已提交
960

961 962 963 964 965 966 967 968 969 970
/* XXX */
#include "harfbuzz-impl.h"
HB_INTERNAL HB_Error
_hb_buffer_add_output_glyph_ids( HB_Buffer  buffer,
			      HB_UShort  num_in,
			      HB_UShort  num_out,
			      const GlyphID *glyph_data,
			      HB_UShort  component,
			      HB_UShort  ligID );

971
#endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */