blob: d2e1839ce4e3f9e36b2aaae0cd1d36ca1222acd5 [file] [log] [blame]
Behdad Esfahbod64aef3a2008-01-23 16:14:38 -05001/*
2 * Copyright (C) 2007,2008 Red Hat, Inc.
3 *
4 * This is part of HarfBuzz, an OpenType Layout engine library.
5 *
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.
11 *
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
16 * DAMAGE.
17 *
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.
23 *
24 * Red Hat Author(s): Behdad Esfahbod
25 */
26
Behdad Esfahbod8dd1c8b2008-01-23 05:00:30 -050027#ifndef HB_OT_LAYOUT_OPEN_PRIVATE_H
28#define HB_OT_LAYOUT_OPEN_PRIVATE_H
Behdad Esfahbod12c45682006-12-28 06:10:59 -050029
Behdad Esfahbod54e5aac2008-01-27 21:19:51 -050030#ifndef HB_OT_LAYOUT_CC
31#error "This file should only be included from hb-ot-layout.c"
32#endif
33
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -050034#include "hb-ot-layout-private.h"
Behdad Esfahbod12c45682006-12-28 06:10:59 -050035
Behdad Esfahboda16ecbf2008-01-23 17:01:55 -050036
Behdad Esfahbod706ab252008-01-28 05:58:50 -050037#define NO_INDEX ((unsigned int) 0xFFFF)
Behdad Esfahbod2d15e722009-04-15 19:50:16 -040038#define NO_CONTEXT ((unsigned int) -1)
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -040039#define NOT_COVERED ((unsigned int) -1)
40#define MAX_NESTING_LEVEL 32
41
Behdad Esfahbod706ab252008-01-28 05:58:50 -050042
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050043/*
44 * Int types
45 */
46
Behdad Esfahbodead428d2008-01-24 03:54:09 -050047/* XXX define these as structs of chars on machines that do not allow
48 * unaligned access */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050049#define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050050 inline NAME& operator = (TYPE i) { v = BIG_ENDIAN(i); return *this; } \
51 inline operator TYPE(void) const { return BIG_ENDIAN(v); } \
52 inline bool operator== (NAME o) const { return v == o.v; } \
53 private: TYPE v; \
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -050054 public:
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050055#define DEFINE_INT_TYPE0(NAME, type) DEFINE_INT_TYPE1 (NAME, type, hb_be_##type)
56#define DEFINE_INT_TYPE(NAME, u, w) DEFINE_INT_TYPE0 (NAME, u##int##w##_t)
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -050057#define DEFINE_INT_TYPE_STRUCT(NAME, u, w) \
58 struct NAME { \
59 DEFINE_INT_TYPE(NAME, u, w) \
60 }
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050061
62/*
63 * Array types
64 */
65
66/* get_len() is a method returning the number of items in an array-like object */
67#define DEFINE_LEN(Type, array, num) \
68 inline unsigned int get_len(void) const { return num; } \
69
70/* get_size() is a method returning the size in bytes of an array-like object */
71#define DEFINE_SIZE(Type, array, num) \
72 inline unsigned int get_size(void) const { return sizeof (*this) + sizeof (Type) * num; }
73
74#define DEFINE_LEN_AND_SIZE(Type, array, num) \
75 DEFINE_LEN(Type, array, num) \
76 DEFINE_SIZE(Type, array, num)
77
78/* An array type is one that contains a variable number of objects
79 * as its last item. An array object is extended with len() and size()
80 * methods, as well as overloaded [] operator. */
81#define DEFINE_ARRAY_TYPE(Type, array, num) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -050082 DEFINE_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050083 DEFINE_LEN_AND_SIZE(Type, array, num)
Behdad Esfahbod1f437e62008-01-23 04:36:40 -050084#define DEFINE_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050085 inline const Type& operator[] (unsigned int i) const { \
Behdad Esfahbod12360f72008-01-23 15:50:38 -050086 if (HB_UNLIKELY (i >= num)) return Null##Type; \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050087 return array[i]; \
88 }
89
90/* An offset array type is like an array type, but it contains a table
91 * of offsets to the objects, relative to the beginning of the current
92 * object. */
93#define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -050094 DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050095 DEFINE_LEN_AND_SIZE(Offset, array, num)
Behdad Esfahbod1f437e62008-01-23 04:36:40 -050096#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -050097 inline const Type& operator[] (unsigned int i) const { \
Behdad Esfahbod12360f72008-01-23 15:50:38 -050098 if (HB_UNLIKELY (i >= num)) return Null##Type; \
99 if (HB_UNLIKELY (!array[i])) return Null##Type; \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500100 return *(const Type *)((const char*)this + array[i]); \
101 }
102
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500103/* A record array type is like an array type, but it contains a table
104 * of records to the objects. Each record has a tag, and an offset
105 * relative to the beginning of the current object. */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500106#define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500107 DEFINE_RECORD_ACCESSOR(Type, array, num) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500108 DEFINE_LEN_AND_SIZE(Record, array, num)
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500109#define DEFINE_RECORD_ACCESSOR(Type, array, num) \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500110 inline const Type& operator[] (unsigned int i) const { \
Behdad Esfahbod12360f72008-01-23 15:50:38 -0500111 if (HB_UNLIKELY (i >= num)) return Null##Type; \
112 if (HB_UNLIKELY (!array[i].offset)) return Null##Type; \
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500113 return *(const Type *)((const char*)this + array[i].offset); \
114 } \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500115 inline const Tag& get_tag (unsigned int i) const { \
116 if (HB_UNLIKELY (i >= num)) return NullTag; \
117 return array[i].tag; \
118 }
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500119
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500120
121#define DEFINE_ARRAY_INTERFACE(Type, name) \
122 inline const Type& get_##name (unsigned int i) const { \
123 return (*this)[i]; \
124 } \
125 inline unsigned int get_##name##_count (void) const { \
126 return this->get_len (); \
127 }
128#define DEFINE_INDEX_ARRAY_INTERFACE(name) \
129 inline unsigned int get_##name##_index (unsigned int i) const { \
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500130 if (HB_UNLIKELY (i >= get_len ())) return NO_INDEX; \
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500131 return (*this)[i]; \
132 } \
133 inline unsigned int get_##name##_count (void) const { \
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500134 return get_len (); \
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500135 }
136
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500137
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500138/*
139 * List types
140 */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500141
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500142#define DEFINE_LIST_ARRAY(Type, name) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500143 inline const Type##List& get_##name##_list (void) const { \
Behdad Esfahbod12360f72008-01-23 15:50:38 -0500144 if (HB_UNLIKELY (!name##List)) return Null##Type##List; \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500145 return *(const Type##List *)((const char*)this + name##List); \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500146 }
147
148#define DEFINE_LIST_INTERFACE(Type, name) \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500149 inline const Type& get_##name (unsigned int i) const { \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500150 return get_##name##_list ()[i]; \
151 } \
152 inline unsigned int get_##name##_count (void) const { \
153 return get_##name##_list ().get_len (); \
154 }
155
156/*
157 * Tag types
158 */
159
160#define DEFINE_TAG_ARRAY_INTERFACE(Type, name) \
161 DEFINE_ARRAY_INTERFACE (Type, name); \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500162 inline const Tag& get_##name##_tag (unsigned int i) const { \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500163 return (*this)[i].tag; \
164 }
165#define DEFINE_TAG_LIST_INTERFACE(Type, name) \
166 DEFINE_LIST_INTERFACE (Type, name); \
167 inline const Tag& get_##name##_tag (unsigned int i) const { \
168 return get_##name##_list ().get_tag (i); \
169 }
170
171#define DEFINE_TAG_FIND_INTERFACE(Type, name) \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500172 inline bool find_##name##_index (hb_tag_t tag, unsigned int *name##_index) const { \
173 const Tag t = tag; \
174 for (unsigned int i = 0; i < get_##name##_count (); i++) { \
175 if (t == get_##name##_tag (i)) { \
176 if (name##_index) *name##_index = i; \
177 return true; \
178 } \
179 } \
180 if (name##_index) *name##_index = NO_INDEX; \
181 return false; \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500182 } \
183 inline const Type& get_##name##_by_tag (hb_tag_t tag) const { \
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500184 unsigned int i; \
185 if (find_##name##_index (tag, &i)) \
186 return get_##name (i); \
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500187 else \
188 return Null##Type; \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500189 }
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500190
191/*
192 * Class features
193 */
194
195/* makes class uninstantiable. should be used for union classes that don't
196 * contain any complete type */
197#define DEFINE_NON_INSTANTIABLE(Type) \
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400198 protected: inline Type() {} /* cannot be instantiated */ \
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500199 public:
200
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500201// TODO use a global nul-array for most Null's
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500202/* defines Null##Type as a safe nil instance of Type */
203#define DEFINE_NULL_DATA(Type, size, data) \
204 static const unsigned char Null##Type##Data[size] = data; \
205 DEFINE_NULL_ALIAS (Type, Type)
206#define DEFINE_NULL(Type, size) \
207 DEFINE_NULL_DATA(Type, size, "")
208#define DEFINE_NULL_ASSERT_SIZE(Type, size) \
209 DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, "")
210#define DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, data) \
211 ASSERT_SIZE (Type, size); \
212 DEFINE_NULL_DATA (Type, size, data)
213#define DEFINE_NULL_ALIAS(NewType, OldType) \
Behdad Esfahbod54e5aac2008-01-27 21:19:51 -0500214 /* XXX static */ const NewType &Null##NewType = *(NewType *)Null##OldType##Data
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500215
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500216/* get_for_data() is a static class method returning a reference to an
217 * instance of Type located at the input data location. It's just a
Behdad Esfahbod54e5aac2008-01-27 21:19:51 -0500218 * fancy, NULL-safe, cast! */
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500219#define STATIC_DEFINE_GET_FOR_DATA(Type) \
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500220 static inline const Type& get_for_data (const char *data) { \
221 extern const Type &Null##Type; \
222 if (HB_UNLIKELY (data == NULL)) return Null##Type; \
223 return *(const Type*)data; \
224 } \
225 static inline Type& get_for_data (char *data) { \
226 return *(Type*)data; \
227 }
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500228
229
Behdad Esfahbod590d55c2008-01-24 19:13:50 -0500230#define DEFINE_GET_ACCESSOR(Type, name, Name) \
231 inline const Type& get_##name (void) const { \
Behdad Esfahbod12360f72008-01-23 15:50:38 -0500232 if (HB_UNLIKELY (!Name)) return Null##Type; \
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500233 return *(const Type*)((const char*)this + Name); \
234 }
Behdad Esfahbod590d55c2008-01-24 19:13:50 -0500235#define DEFINE_GET_HAS_ACCESSOR(Type, name, Name) \
236 DEFINE_GET_ACCESSOR (Type, name, Name); \
237 inline bool has_##name (void) const { \
238 return Name != 0; \
239 }
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500240
241
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500242
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400243
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500244/*
245 *
246 * The OpenType Font File
247 *
248 */
249
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500250
251
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500252/*
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500253 * Data Types
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500254 */
255
256
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500257/* "The following data types are used in the OpenType font file.
258 * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
Behdad Esfahbodf78e70c2006-12-21 22:30:38 -0500259
260
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500261DEFINE_INT_TYPE_STRUCT (BYTE, u, 8); /* 8-bit unsigned integer. */
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500262DEFINE_NULL_ASSERT_SIZE (BYTE, 1);
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500263DEFINE_INT_TYPE_STRUCT (CHAR, , 8); /* 8-bit signed integer. */
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500264DEFINE_NULL_ASSERT_SIZE (CHAR, 1);
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500265DEFINE_INT_TYPE_STRUCT (USHORT, u, 16); /* 16-bit unsigned integer. */
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500266DEFINE_NULL_ASSERT_SIZE (USHORT, 2);
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500267DEFINE_INT_TYPE_STRUCT (SHORT, , 16); /* 16-bit signed integer. */
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500268DEFINE_NULL_ASSERT_SIZE (SHORT, 2);
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500269DEFINE_INT_TYPE_STRUCT (ULONG, u, 32); /* 32-bit unsigned integer. */
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500270DEFINE_NULL_ASSERT_SIZE (ULONG, 4);
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500271DEFINE_INT_TYPE_STRUCT (LONG, , 32); /* 32-bit signed integer. */
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500272DEFINE_NULL_ASSERT_SIZE (LONG, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500273
274/* Date represented in number of seconds since 12:00 midnight, January 1,
275 * 1904. The value is represented as a signed 64-bit integer. */
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500276DEFINE_INT_TYPE_STRUCT (LONGDATETIME, , 64);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500277
278/* 32-bit signed fixed-point number (16.16) */
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500279struct Fixed {
280 inline Fixed& operator = (int32_t v) { i = (int16_t) (v >> 16); f = (uint16_t) v; return *this; } \
281 inline operator int32_t(void) const { return (((int32_t) i) << 16) + (uint16_t) f; } \
282 inline bool operator== (Fixed o) const { return i == o.i && f == o.f; } \
283
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500284 inline operator double(void) const { return (uint32_t) this / 65536.; }
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500285 inline int16_t int_part (void) const { return i; }
286 inline uint16_t frac_part (void) const { return f; }
287
288 private:
289 SHORT i;
290 USHORT f;
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500291};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500292DEFINE_NULL_ASSERT_SIZE (Fixed, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500293
294/* Smallest measurable distance in the em space. */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500295struct FUNIT;
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500296
297/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500298struct FWORD : SHORT {
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500299};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500300DEFINE_NULL_ASSERT_SIZE (FWORD, 2);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500301
302/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500303struct UFWORD : USHORT {
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500304};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500305DEFINE_NULL_ASSERT_SIZE (UFWORD, 2);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500306
307/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500308struct F2DOT14 : SHORT {
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500309 inline operator double() const { return (uint32_t) this / 16384.; }
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500310};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500311DEFINE_NULL_ASSERT_SIZE (F2DOT14, 2);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500312
313/* Array of four uint8s (length = 32 bits) used to identify a script, language
314 * system, feature, or baseline */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500315struct Tag {
316 inline Tag (void) { v[0] = v[1] = v[2] = v[3] = 0; }
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500317 inline Tag (uint32_t v) { (ULONG&)(*this) = v; }
Behdad Esfahbodb739c052006-12-25 05:39:20 -0500318 inline Tag (const char *c) { v[0] = c[0]; v[1] = c[1]; v[2] = c[2]; v[3] = c[3]; }
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500319 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]; }
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500320 inline bool operator== (const char *c) const { return v[0]==c[0]&&v[1]==c[1]&&v[2]==c[2]&&v[3]==c[3]; }
Behdad Esfahbodb9d76882008-01-23 01:38:10 -0500321 inline bool operator== (uint32_t i) const { return i == (uint32_t) *this; }
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500322 inline operator uint32_t(void) const { return (v[0]<<24)+(v[1]<<16) +(v[2]<<8)+v[3]; }
323 /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500324 inline operator const char* (void) const { return (const char *)this; }
325 inline operator char* (void) { return (char *)this; }
326
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500327 private:
328 char v[4];
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500329};
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500330ASSERT_SIZE (Tag, 4);
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500331DEFINE_NULL_DATA (Tag, 5, " ");
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500332
333/* Glyph index number, same as uint16 (length = 16 bits) */
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500334DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16);
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500335DEFINE_NULL_ASSERT_SIZE (GlyphID, 2);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500336
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500337/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500338DEFINE_INT_TYPE_STRUCT (Offset, u, 16);
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500339DEFINE_NULL_ASSERT_SIZE (Offset, 2);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500340
341/* CheckSum */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500342struct CheckSum : ULONG {
343 static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) {
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500344 uint32_t Sum = 0L;
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500345 ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500346
347 while (Table < EndPtr)
348 Sum += *Table++;
349 return Sum;
350 }
351};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500352DEFINE_NULL_ASSERT_SIZE (CheckSum, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500353
354
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500355/*
356 * Version Numbers
357 */
358
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500359struct USHORT_Version : USHORT {
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500360};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500361DEFINE_NULL_ASSERT_SIZE (USHORT_Version, 2);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500362
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500363struct Fixed_Version : Fixed {
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500364 inline int16_t major (void) const { return this->int_part(); }
365 inline int16_t minor (void) const { return this->frac_part(); }
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500366};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500367DEFINE_NULL_ASSERT_SIZE (Fixed_Version, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500368
369
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500370/*
371 * Organization of an OpenType Font
372 */
373
Behdad Esfahbod3158d842006-12-27 20:08:07 -0500374struct OpenTypeFontFile;
Behdad Esfahbodb739c052006-12-25 05:39:20 -0500375struct OffsetTable;
376struct TTCHeader;
377
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500378typedef struct TableDirectory {
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500379
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500380 friend struct OpenTypeFontFile;
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500381 friend struct OffsetTable;
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500382
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500383 inline bool is_null (void) const { return length == 0; }
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500384 inline const Tag& get_tag (void) const { return tag; }
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500385 inline unsigned long get_checksum (void) const { return checkSum; }
386 inline unsigned long get_offset (void) const { return offset; }
387 inline unsigned long get_length (void) const { return length; }
388
389 private:
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500390 Tag tag; /* 4-byte identifier. */
391 CheckSum checkSum; /* CheckSum for this table. */
392 ULONG offset; /* Offset from beginning of TrueType font
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500393 * file. */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500394 ULONG length; /* Length of this table. */
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500395} OpenTypeTable;
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500396DEFINE_NULL_ASSERT_SIZE (TableDirectory, 16);
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500397DEFINE_NULL_ALIAS (OpenTypeTable, TableDirectory);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500398
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500399typedef struct OffsetTable {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500400
401 friend struct OpenTypeFontFile;
402 friend struct TTCHeader;
403
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500404 DEFINE_TAG_ARRAY_INTERFACE (OpenTypeTable, table); /* get_table_count(), get_table(i), get_table_tag(i) */
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500405 DEFINE_TAG_FIND_INTERFACE (OpenTypeTable, table); /* find_table_index(tag), get_table_by_tag(tag) */
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500406
407 private:
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500408 /* OpenTypeTables, in no particular order */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500409 DEFINE_ARRAY_TYPE (TableDirectory, tableDir, numTables);
410
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500411 private:
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500412 Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
413 USHORT numTables; /* Number of tables. */
414 USHORT searchRange; /* (Maximum power of 2 <= numTables) x 16 */
415 USHORT entrySelector; /* Log2(maximum power of 2 <= numTables). */
416 USHORT rangeShift; /* NumTables x 16-searchRange. */
417 TableDirectory tableDir[]; /* TableDirectory entries. numTables items */
Behdad Esfahbod13346612006-12-27 19:58:32 -0500418} OpenTypeFontFace;
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500419DEFINE_NULL_ASSERT_SIZE (OffsetTable, 12);
420DEFINE_NULL_ALIAS (OpenTypeFontFace, OffsetTable);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500421
422/*
423 * TrueType Collections
424 */
425
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500426struct TTCHeader {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500427
428 friend struct OpenTypeFontFile;
429
430 private:
Behdad Esfahbod13346612006-12-27 19:58:32 -0500431 /* OpenTypeFontFaces, in no particular order */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500432 DEFINE_OFFSET_ARRAY_TYPE (OffsetTable, offsetTable, numFonts);
Behdad Esfahbodaefaafe2008-01-23 17:25:29 -0500433 /* XXX check version here? */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500434
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500435 private:
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500436 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500437 ULONG version; /* Version of the TTC Header (1.0 or 2.0),
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400438 * 0x00010000 or 0x00020000 */
Behdad Esfahbod01e4fcb2006-12-21 22:31:31 -0500439 ULONG numFonts; /* Number of fonts in TTC */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500440 ULONG offsetTable[]; /* Array of offsets to the OffsetTable for each font
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500441 * from the beginning of the file */
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500442};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500443DEFINE_NULL_ASSERT_SIZE (TTCHeader, 12);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500444
445
Behdad Esfahbodb739c052006-12-25 05:39:20 -0500446/*
447 * OpenType Font File
448 */
449
Behdad Esfahbod3158d842006-12-27 20:08:07 -0500450struct OpenTypeFontFile {
451 DEFINE_NON_INSTANTIABLE(OpenTypeFontFile);
Behdad Esfahbodc81efca2006-12-25 06:22:08 -0500452 static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 );
453 static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O');
454 static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f');
Behdad Esfahbodb739c052006-12-25 05:39:20 -0500455
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500456 STATIC_DEFINE_GET_FOR_DATA (OpenTypeFontFile);
Behdad Esfahbodb739c052006-12-25 05:39:20 -0500457
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500458 DEFINE_ARRAY_INTERFACE (OpenTypeFontFace, face); /* get_face_count(), get_face(i) */
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500459
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500460 inline const Tag& get_tag (void) const { return tag; }
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500461
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500462 /* This is how you get a table */
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500463 inline const char* get_table_data (const OpenTypeTable& table) const {
464 return (*this)[table];
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500465 }
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500466 inline char* get_table_data (const OpenTypeTable& table) {
467 return (*this)[table];
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500468 }
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500469
470 private:
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500471 inline const char* operator[] (const OpenTypeTable& table) const {
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500472 if (G_UNLIKELY (table.offset == 0)) return NULL;
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500473 return ((const char*)this) + table.offset;
474 }
475 inline char* operator[] (const OpenTypeTable& table) {
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500476 if (G_UNLIKELY (table.offset == 0)) return NULL;
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500477 return ((char*)this) + table.offset;
478 }
479
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500480 /* Array interface sans get_size() */
Behdad Esfahbod75860892008-01-23 18:02:28 -0500481 unsigned int get_len (void) const {
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500482 switch (tag) {
483 default: return 0;
Behdad Esfahbodc81efca2006-12-25 06:22:08 -0500484 case TrueTypeTag: case CFFTag: return 1;
485 case TTCTag: return ((const TTCHeader&)*this).get_len();
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500486 }
487 }
Behdad Esfahbod75860892008-01-23 18:02:28 -0500488 const OpenTypeFontFace& operator[] (unsigned int i) const {
Behdad Esfahbod12360f72008-01-23 15:50:38 -0500489 if (HB_UNLIKELY (i >= get_len ())) return NullOpenTypeFontFace;
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500490 switch (tag) {
Behdad Esfahbodc81efca2006-12-25 06:22:08 -0500491 default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this;
492 case TTCTag: return ((const TTCHeader&)*this)[i];
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500493 }
494 }
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500495
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500496 private:
Behdad Esfahbod808dbe22006-12-25 06:18:52 -0500497 Tag tag; /* 4-byte identifier. */
Behdad Esfahbodb739c052006-12-25 05:39:20 -0500498};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500499DEFINE_NULL_ASSERT_SIZE (OpenTypeFontFile, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500500
501
502
503/*
504 *
505 * OpenType Layout Common Table Formats
506 *
507 */
508
Behdad Esfahbod53502c62006-12-26 19:29:08 -0500509/*
Behdad Esfahbod13346612006-12-27 19:58:32 -0500510 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
Behdad Esfahbod53502c62006-12-26 19:29:08 -0500511 */
512
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500513typedef struct Record {
514 Tag tag; /* 4-byte Tag identifier */
515 Offset offset; /* Offset from beginning of object holding
516 * the Record */
517} ScriptRecord, LangSysRecord, FeatureRecord;
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500518DEFINE_NULL_ASSERT_SIZE (Record, 6);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500519
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500520struct LangSys {
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500521
522 DEFINE_INDEX_ARRAY_INTERFACE (feature);
523
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500524 inline const bool has_required_feature (void) const {
525 return reqFeatureIndex != 0xffff;
526 }
527 /* Returns NO_INDEX if none */
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500528 inline int get_required_feature_index (void) const {
529 if (reqFeatureIndex == 0xffff)
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500530 return NO_INDEX;
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500531 return reqFeatureIndex;;
532 }
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500533
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500534 private:
535 /* Feature indices, in no particular order */
536 DEFINE_ARRAY_TYPE (USHORT, featureIndex, featureCount);
Behdad Esfahbodb9d76882008-01-23 01:38:10 -0500537
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500538 private:
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500539 Offset lookupOrder; /* = Null (reserved for an offset to a
Behdad Esfahbodbefc0222006-12-25 09:14:52 -0500540 * reordering table) */
541 USHORT reqFeatureIndex;/* Index of a feature required for this
542 * language system--if no required features
543 * = 0xFFFF */
544 USHORT featureCount; /* Number of FeatureIndex values for this
545 * language system--excludes the required
546 * feature */
547 USHORT featureIndex[]; /* Array of indices into the FeatureList--in
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500548 * arbitrary order. featureCount entires long */
Behdad Esfahbodb6e62bc2006-12-22 02:21:55 -0500549};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500550DEFINE_NULL_ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
551
552struct Script {
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500553
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500554 /* DEFINE_ARRAY_INTERFACE (LangSys, lang_sys) but handling defaultLangSys */
555
556 inline const LangSys& get_lang_sys (unsigned int i) const {
557 if (i == NO_INDEX) return get_default_lang_sys ();
558 return (*this)[i];
559 }
560 inline unsigned int get_lang_sys_count (void) const {
561 return this->get_len ();
562 }
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500563
564 inline const Tag& get_lang_sys_tag (unsigned int i) const {
565 return get_tag (i);
566 }
567
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500568 // LONGTERMTODO bsearch
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500569 DEFINE_TAG_FIND_INTERFACE (LangSys, lang_sys); /* find_lang_sys_index (), get_lang_sys_by_tag (tag) */
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500570
571 inline const bool has_default_lang_sys (void) const {
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500572 return defaultLangSys != 0;
573 }
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500574 inline const LangSys& get_default_lang_sys (void) const {
Behdad Esfahbod12360f72008-01-23 15:50:38 -0500575 if (HB_UNLIKELY (!defaultLangSys))
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500576 return NullLangSys;
577 return *(LangSys*)((const char*)this + defaultLangSys);
578 }
579
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500580 private:
581 /* LangSys', in sorted alphabetical tag order */
582 DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500583
584 private:
585 Offset defaultLangSys; /* Offset to DefaultLangSys table--from
586 * beginning of Script table--may be Null */
587 USHORT langSysCount; /* Number of LangSysRecords for this script--
588 * excluding the DefaultLangSys */
589 LangSysRecord langSysRecord[];/* Array of LangSysRecords--listed
590 * alphabetically by LangSysTag */
591};
592DEFINE_NULL_ASSERT_SIZE (Script, 4);
593
594struct ScriptList {
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500595
596 friend struct GSUBGPOS;
597
598private:
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500599 /* Scripts, in sorted alphabetical tag order */
600 DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
601
602private:
603 USHORT scriptCount; /* Number of ScriptRecords */
604 ScriptRecord scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
605 * by ScriptTag */
606};
607DEFINE_NULL_ASSERT_SIZE (ScriptList, 2);
608
609struct Feature {
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500610
Behdad Esfahbod57225672008-02-18 20:58:39 -0500611 DEFINE_INDEX_ARRAY_INTERFACE (lookup); /* get_lookup_count(), get_lookup_index(i) */
Behdad Esfahbodfd92a3d2008-01-24 03:11:09 -0500612
613 private:
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500614 /* LookupList indices, in no particular order */
615 DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
616
Behdad Esfahbod57225672008-02-18 20:58:39 -0500617 /* TODO: implement get_feature_parameters() */
618 /* TODO: implement FeatureSize and other special features? */
619
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500620 private:
621 Offset featureParams; /* Offset to Feature Parameters table (if one
622 * has been defined for the feature), relative
Behdad Esfahbodce48f032009-11-02 14:35:51 -0500623 * to the beginning of the Feature Table; = Null
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500624 * if not required */
625 USHORT lookupCount; /* Number of LookupList indices for this
626 * feature */
627 USHORT lookupIndex[]; /* Array of LookupList indices for this
628 * feature--zero-based (first lookup is
629 * LookupListIndex = 0) */
630};
631DEFINE_NULL_ASSERT_SIZE (Feature, 4);
Behdad Esfahbod6b4ce012006-12-21 22:31:10 -0500632
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500633struct FeatureList {
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500634
635 friend struct GSUBGPOS;
636
637 private:
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500638 /* Feature indices, in sorted alphabetical tag order */
639 DEFINE_RECORD_ARRAY_TYPE (Feature, featureRecord, featureCount);
640
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500641 private:
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500642 USHORT featureCount; /* Number of FeatureRecords in this table */
643 FeatureRecord featureRecord[];/* Array of FeatureRecords--zero-based (first
644 * feature has FeatureIndex = 0)--listed
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500645 * alphabetically by FeatureTag */
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500646};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500647DEFINE_NULL_ASSERT_SIZE (FeatureList, 2);
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500648
649struct LookupFlag : USHORT {
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400650 static const unsigned int RightToLeft = 0x0001u;
651 static const unsigned int IgnoreBaseGlyphs = 0x0002u;
652 static const unsigned int IgnoreLigatures = 0x0004u;
653 static const unsigned int IgnoreMarks = 0x0008u;
654 static const unsigned int Reserved = 0x00F0u;
655 static const unsigned int MarkAttachmentType = 0xFF00u;
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500656};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500657DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2);
658
659struct LookupSubTable {
660 DEFINE_NON_INSTANTIABLE(LookupSubTable);
661
662 private:
663 USHORT format; /* Subtable format. Different for GSUB and GPOS */
664};
665DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2);
666
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500667
668struct Lookup {
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400669 DEFINE_NON_INSTANTIABLE(Lookup);
670
671 DEFINE_ARRAY_INTERFACE (LookupSubTable, subtable); /* get_subtable_count(), get_subtable(i) */
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500672
673 inline bool is_right_to_left (void) const { return lookupFlag & LookupFlag::RightToLeft; }
674 inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
675 inline bool ignore_ligatures (void) const { return lookupFlag & LookupFlag::IgnoreLigatures; }
676 inline bool ignore_marks (void) const { return lookupFlag & LookupFlag::IgnoreMarks; }
Behdad Esfahbod30bd7632009-04-15 22:56:15 -0400677 inline unsigned int get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; }
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500678
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400679 inline unsigned int get_type (void) const { return lookupType; }
680 inline unsigned int get_flag (void) const { return lookupFlag; }
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500681
682 private:
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400683 /* SubTables, in the desired order */
684 DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);
685
686 protected:
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500687 USHORT lookupType; /* Different enumerations for GSUB and GPOS */
688 USHORT lookupFlag; /* Lookup qualifiers */
689 USHORT subTableCount; /* Number of SubTables for this lookup */
690 Offset subTableOffset[];/* Array of offsets to SubTables-from
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500691 * beginning of Lookup table */
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500692};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500693DEFINE_NULL_ASSERT_SIZE (Lookup, 6);
694
695struct LookupList {
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500696
697 friend struct GSUBGPOS;
698
699 private:
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500700 /* Lookup indices, in sorted alphabetical tag order */
701 DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
702
703 private:
704 USHORT lookupCount; /* Number of lookups in this table */
705 Offset lookupOffset[]; /* Array of offsets to Lookup tables--from
706 * beginning of LookupList--zero based (first
707 * lookup is Lookup index = 0) */
708};
709DEFINE_NULL_ASSERT_SIZE (LookupList, 2);
Behdad Esfahbodf8ba99f2006-12-25 09:58:02 -0500710
Behdad Esfahbod53502c62006-12-26 19:29:08 -0500711/*
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500712 * Coverage Table
Behdad Esfahbod53502c62006-12-26 19:29:08 -0500713 */
714
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500715struct CoverageFormat1 {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500716
717 friend struct Coverage;
718
719 private:
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500720 /* GlyphIDs, in sorted numerical order */
721 DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);
722
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400723 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
Behdad Esfahbodc46196d2006-12-27 20:05:16 -0500724 GlyphID gid;
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400725 if (HB_UNLIKELY (glyph_id > 65535))
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400726 return NOT_COVERED;
Behdad Esfahbodc46196d2006-12-27 20:05:16 -0500727 gid = glyph_id;
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500728 // TODO: bsearch
Behdad Esfahbod12360f72008-01-23 15:50:38 -0500729 for (unsigned int i = 0; i < glyphCount; i++)
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500730 if (gid == glyphArray[i])
731 return i;
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400732 return NOT_COVERED;
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500733 }
734
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500735 private:
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500736 USHORT coverageFormat; /* Format identifier--format = 1 */
737 USHORT glyphCount; /* Number of glyphs in the GlyphArray */
738 GlyphID glyphArray[]; /* Array of GlyphIDs--in numerical order */
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500739};
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500740ASSERT_SIZE (CoverageFormat1, 4);
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500741
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500742struct CoverageRangeRecord {
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500743
Behdad Esfahbod75860892008-01-23 18:02:28 -0500744 friend struct CoverageFormat2;
745
746 private:
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400747 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500748 if (glyph_id >= start && glyph_id <= end)
749 return startCoverageIndex + (glyph_id - start);
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400750 return NOT_COVERED;
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500751 }
752
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500753 private:
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500754 GlyphID start; /* First GlyphID in the range */
755 GlyphID end; /* Last GlyphID in the range */
756 USHORT startCoverageIndex; /* Coverage Index of first GlyphID in
757 * range */
758};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500759DEFINE_NULL_ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\001");
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500760
761struct CoverageFormat2 {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500762
763 friend struct Coverage;
764
765 private:
Behdad Esfahbod0d6db2a2006-12-26 18:53:55 -0500766 /* CoverageRangeRecords, in sorted numerical start order */
767 DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500768
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400769 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const {
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500770 // TODO: bsearch
Behdad Esfahbodeed05b02009-05-06 00:25:59 -0400771 unsigned int count = rangeCount;
772 for (unsigned int i = 0; i < count; i++) {
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500773 int coverage = rangeRecord[i].get_coverage (glyph_id);
774 if (coverage >= 0)
775 return coverage;
776 }
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400777 return NOT_COVERED;
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500778 }
779
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500780 private:
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500781 USHORT coverageFormat; /* Format identifier--format = 2 */
782 USHORT rangeCount; /* Number of CoverageRangeRecords */
783 CoverageRangeRecord rangeRecord[]; /* Array of glyph ranges--ordered by
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500784 * Start GlyphID. rangeCount entries
785 * long */
786};
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500787ASSERT_SIZE (CoverageFormat2, 4);
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500788
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400789struct Coverage {
Behdad Esfahbod53502c62006-12-26 19:29:08 -0500790 DEFINE_NON_INSTANTIABLE(Coverage);
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500791
Behdad Esfahbod75860892008-01-23 18:02:28 -0500792 unsigned int get_size (void) const {
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400793 switch (u.coverageFormat) {
794 case 1: return u.format1.get_size ();
795 case 2: return u.format2.get_size ();
796 default:return sizeof (u.coverageFormat);
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500797 }
798 }
799
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400800 unsigned int get_coverage (hb_codepoint_t glyph_id) const {
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400801 switch (u.coverageFormat) {
802 case 1: return u.format1.get_coverage(glyph_id);
803 case 2: return u.format2.get_coverage(glyph_id);
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400804 default:return NOT_COVERED;
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500805 }
806 }
807
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500808 private:
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400809 union {
Behdad Esfahbodc46196d2006-12-27 20:05:16 -0500810 USHORT coverageFormat; /* Format identifier */
811 CoverageFormat1 format1;
812 CoverageFormat2 format2;
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400813 } u;
Behdad Esfahbod0c0d5532006-12-26 15:29:38 -0500814};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500815DEFINE_NULL (Coverage, 2);
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500816
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500817/*
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500818 * Class Definition Table
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500819 */
820
821struct ClassDefFormat1 {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500822
823 friend struct ClassDef;
824
825 private:
Behdad Esfahbod52886ca2009-04-16 14:19:42 -0400826 /* Class Values, in sorted numerical order */
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500827 DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount);
828
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400829 inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
Behdad Esfahbodead428d2008-01-24 03:54:09 -0500830 if (glyph_id >= startGlyph && glyph_id - startGlyph < glyphCount)
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500831 return classValueArray[glyph_id - startGlyph];
832 return 0;
833 }
834
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500835 private:
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500836 USHORT classFormat; /* Format identifier--format = 1 */
837 GlyphID startGlyph; /* First GlyphID of the classValueArray */
838 USHORT glyphCount; /* Size of the classValueArray */
839 USHORT classValueArray[]; /* Array of Class Values--one per GlyphID */
840};
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500841ASSERT_SIZE (ClassDefFormat1, 6);
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500842
843struct ClassRangeRecord {
844
Behdad Esfahbod75860892008-01-23 18:02:28 -0500845 friend struct ClassDefFormat2;
846
847 private:
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400848 inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500849 if (glyph_id >= start && glyph_id <= end)
850 return classValue;
851 return 0;
852 }
853
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500854 private:
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500855 GlyphID start; /* First GlyphID in the range */
856 GlyphID end; /* Last GlyphID in the range */
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500857 USHORT classValue; /* Applied to all glyphs in the range */
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500858};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500859DEFINE_NULL_ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\001");
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500860
861struct ClassDefFormat2 {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500862
863 friend struct ClassDef;
864
865 private:
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500866 /* ClassRangeRecords, in sorted numerical start order */
867 DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount);
868
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400869 inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500870 // TODO: bsearch
Behdad Esfahbodeed05b02009-05-06 00:25:59 -0400871 unsigned int count = rangeCount;
872 for (unsigned int i = 0; i < count; i++) {
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500873 int classValue = rangeRecord[i].get_class (glyph_id);
874 if (classValue > 0)
875 return classValue;
876 }
877 return 0;
878 }
879
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500880 private:
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500881 USHORT classFormat; /* Format identifier--format = 2 */
882 USHORT rangeCount; /* Number of Number of ClassRangeRecords */
883 ClassRangeRecord rangeRecord[]; /* Array of glyph ranges--ordered by
884 * Start GlyphID */
885};
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500886ASSERT_SIZE (ClassDefFormat2, 4);
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500887
888struct ClassDef {
889 DEFINE_NON_INSTANTIABLE(ClassDef);
890
Behdad Esfahbod75860892008-01-23 18:02:28 -0500891 unsigned int get_size (void) const {
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400892 switch (u.classFormat) {
893 case 1: return u.format1.get_size ();
894 case 2: return u.format2.get_size ();
895 default:return sizeof (u.classFormat);
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500896 }
897 }
898
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400899 hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400900 switch (u.classFormat) {
Behdad Esfahbodb9d76882008-01-23 01:38:10 -0500901 case 1: return u.format1.get_class(glyph_id);
902 case 2: return u.format2.get_class(glyph_id);
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500903 default:return 0;
904 }
905 }
906
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500907 private:
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400908 union {
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500909 USHORT classFormat; /* Format identifier */
Behdad Esfahbodbf0f9dd2006-12-27 20:06:42 -0500910 ClassDefFormat1 format1;
911 ClassDefFormat2 format2;
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400912 } u;
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500913};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500914DEFINE_NULL (ClassDef, 2);
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500915
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500916/*
917 * Device Tables
918 */
Behdad Esfahbodeb32e372006-12-26 20:00:33 -0500919
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500920struct Device {
Behdad Esfahbod75860892008-01-23 18:02:28 -0500921 DEFINE_NON_INSTANTIABLE(Device);
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500922
Behdad Esfahbod75860892008-01-23 18:02:28 -0500923 unsigned int get_size (void) const {
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500924 int count = endSize - startSize + 1;
925 if (count < 0) count = 0;
926 switch (deltaFormat) {
927 case 1: return sizeof (Device) + sizeof (USHORT) * ((count+7)/8);
928 case 2: return sizeof (Device) + sizeof (USHORT) * ((count+3)/4);
929 case 3: return sizeof (Device) + sizeof (USHORT) * ((count+1)/2);
930 default:return sizeof (Device);
931 }
932 }
933
Behdad Esfahbod75860892008-01-23 18:02:28 -0500934 int get_delta (int ppem_size) const {
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500935 if (ppem_size >= startSize && ppem_size <= endSize &&
936 deltaFormat >= 1 && deltaFormat <= 3) {
937 int s = ppem_size - startSize;
938 int f = deltaFormat;
939
940 uint16_t byte = deltaValue[s >> (4 - f)];
941 uint16_t bits = byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f));
942 uint16_t mask = 0xFFFF >> (16 - (1 << f));
Behdad Esfahbodce48f032009-11-02 14:35:51 -0500943
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500944 int delta = bits & mask;
945
946 if (delta >= ((mask + 1) >> 1))
947 delta -= mask + 1;
948
949 return delta;
950 }
951 return 0;
952 }
953
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500954 private:
Behdad Esfahbod2b737452006-12-26 20:55:37 -0500955 USHORT startSize; /* Smallest size to correct--in ppem */
956 USHORT endSize; /* Largest size to correct--in ppem */
957 USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3 */
958 USHORT deltaValue[]; /* Array of compressed data */
959};
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500960DEFINE_NULL_ASSERT_SIZE (Device, 6);
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500961
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500962/*
Behdad Esfahbodaefaafe2008-01-23 17:25:29 -0500963 * GSUB/GPOS Common
Behdad Esfahbod1f437e62008-01-23 04:36:40 -0500964 */
Behdad Esfahbod25ad92c2006-12-25 09:35:06 -0500965
Behdad Esfahbod2d15e722009-04-15 19:50:16 -0400966struct GSUBGPOS {
Behdad Esfahbod600e5eb2008-01-23 02:01:37 -0500967 static const hb_tag_t GSUBTag = HB_TAG ('G','S','U','B');
968 static const hb_tag_t GPOSTag = HB_TAG ('G','P','O','S');
969
Behdad Esfahbodaefaafe2008-01-23 17:25:29 -0500970 STATIC_DEFINE_GET_FOR_DATA (GSUBGPOS);
971 /* XXX check version here? */
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500972
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500973 DEFINE_TAG_LIST_INTERFACE (Script, script ); /* get_script_count (), get_script (i), get_script_tag (i) */
974 DEFINE_TAG_LIST_INTERFACE (Feature, feature); /* get_feature_count(), get_feature(i), get_feature_tag(i) */
975 DEFINE_LIST_INTERFACE (Lookup, lookup ); /* get_lookup_count (), get_lookup (i) */
976
Behdad Esfahbod4a26ea42008-01-28 07:40:10 -0500977 // LONGTERMTODO bsearch
Behdad Esfahbod706ab252008-01-28 05:58:50 -0500978 DEFINE_TAG_FIND_INTERFACE (Script, script ); /* find_script_index (), get_script_by_tag (tag) */
979 DEFINE_TAG_FIND_INTERFACE (Feature, feature); /* find_feature_index(), get_feature_by_tag(tag) */
Behdad Esfahbod40a81312008-01-28 02:30:48 -0500980
981 private:
982 DEFINE_LIST_ARRAY(Script, script);
983 DEFINE_LIST_ARRAY(Feature, feature);
984 DEFINE_LIST_ARRAY(Lookup, lookup);
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500985
Behdad Esfahbod303fe622008-01-23 00:20:48 -0500986 private:
Behdad Esfahbod5b2e9472007-07-06 02:03:26 -0400987 Fixed_Version version; /* Version of the GSUB/GPOS table--initially set
988 * to 0x00010000 */
989 Offset scriptList; /* Offset to ScriptList table--from beginning of
990 * GSUB/GPOS table */
991 Offset featureList; /* Offset to FeatureList table--from beginning of
992 * GSUB/GPOS table */
993 Offset lookupList; /* Offset to LookupList table--from beginning of
994 * GSUB/GPOS table */
Behdad Esfahbodaefaafe2008-01-23 17:25:29 -0500995};
996DEFINE_NULL_ASSERT_SIZE (GSUBGPOS, 10);
Behdad Esfahbod71d62ba2006-12-27 01:29:24 -0500997
Behdad Esfahbod5a0b7912009-04-16 04:45:30 -0400998/* XXX */
999#include "harfbuzz-impl.h"
1000HB_INTERNAL HB_Error
1001_hb_buffer_add_output_glyph_ids( HB_Buffer buffer,
1002 HB_UShort num_in,
1003 HB_UShort num_out,
1004 const GlyphID *glyph_data,
1005 HB_UShort component,
1006 HB_UShort ligID );
1007
Behdad Esfahbod8dd1c8b2008-01-23 05:00:30 -05001008#endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */