Behdad Esfahbod | 64aef3a | 2008-01-23 16:14:38 -0500 | [diff] [blame] | 1 | /* |
| 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 Esfahbod | 8dd1c8b | 2008-01-23 05:00:30 -0500 | [diff] [blame] | 27 | #ifndef HB_OT_LAYOUT_OPEN_PRIVATE_H |
| 28 | #define HB_OT_LAYOUT_OPEN_PRIVATE_H |
Behdad Esfahbod | 12c4568 | 2006-12-28 06:10:59 -0500 | [diff] [blame] | 29 | |
Behdad Esfahbod | 54e5aac | 2008-01-27 21:19:51 -0500 | [diff] [blame] | 30 | #ifndef HB_OT_LAYOUT_CC |
| 31 | #error "This file should only be included from hb-ot-layout.c" |
| 32 | #endif |
| 33 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 34 | #include "hb-ot-layout-private.h" |
Behdad Esfahbod | 12c4568 | 2006-12-28 06:10:59 -0500 | [diff] [blame] | 35 | |
Behdad Esfahbod | a16ecbf | 2008-01-23 17:01:55 -0500 | [diff] [blame] | 36 | |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 37 | #define NO_INDEX ((unsigned int) 0xFFFF) |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 38 | #define NO_CONTEXT ((unsigned int) -1) |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 39 | #define NOT_COVERED ((unsigned int) -1) |
| 40 | #define MAX_NESTING_LEVEL 32 |
| 41 | |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 42 | |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 43 | /* |
| 44 | * Int types |
| 45 | */ |
| 46 | |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 47 | /* XXX define these as structs of chars on machines that do not allow |
| 48 | * unaligned access */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 49 | #define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 50 | 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 Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 54 | public: |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 55 | #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 Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 57 | #define DEFINE_INT_TYPE_STRUCT(NAME, u, w) \ |
| 58 | struct NAME { \ |
| 59 | DEFINE_INT_TYPE(NAME, u, w) \ |
| 60 | } |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 61 | |
| 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 Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 82 | DEFINE_INDEX_OPERATOR(Type, array, num) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 83 | DEFINE_LEN_AND_SIZE(Type, array, num) |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 84 | #define DEFINE_INDEX_OPERATOR(Type, array, num) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 85 | inline const Type& operator[] (unsigned int i) const { \ |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 86 | if (HB_UNLIKELY (i >= num)) return Null##Type; \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 87 | 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 Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 94 | DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 95 | DEFINE_LEN_AND_SIZE(Offset, array, num) |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 96 | #define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 97 | inline const Type& operator[] (unsigned int i) const { \ |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 98 | if (HB_UNLIKELY (i >= num)) return Null##Type; \ |
| 99 | if (HB_UNLIKELY (!array[i])) return Null##Type; \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 100 | return *(const Type *)((const char*)this + array[i]); \ |
| 101 | } |
| 102 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 103 | /* 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 Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 106 | #define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 107 | DEFINE_RECORD_ACCESSOR(Type, array, num) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 108 | DEFINE_LEN_AND_SIZE(Record, array, num) |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 109 | #define DEFINE_RECORD_ACCESSOR(Type, array, num) \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 110 | inline const Type& operator[] (unsigned int i) const { \ |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 111 | if (HB_UNLIKELY (i >= num)) return Null##Type; \ |
| 112 | if (HB_UNLIKELY (!array[i].offset)) return Null##Type; \ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 113 | return *(const Type *)((const char*)this + array[i].offset); \ |
| 114 | } \ |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 115 | inline const Tag& get_tag (unsigned int i) const { \ |
| 116 | if (HB_UNLIKELY (i >= num)) return NullTag; \ |
| 117 | return array[i].tag; \ |
| 118 | } |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 119 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 120 | |
| 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 Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 130 | if (HB_UNLIKELY (i >= get_len ())) return NO_INDEX; \ |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 131 | return (*this)[i]; \ |
| 132 | } \ |
| 133 | inline unsigned int get_##name##_count (void) const { \ |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 134 | return get_len (); \ |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 135 | } |
| 136 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 137 | |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 138 | /* |
| 139 | * List types |
| 140 | */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 141 | |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 142 | #define DEFINE_LIST_ARRAY(Type, name) \ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 143 | inline const Type##List& get_##name##_list (void) const { \ |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 144 | if (HB_UNLIKELY (!name##List)) return Null##Type##List; \ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 145 | return *(const Type##List *)((const char*)this + name##List); \ |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 146 | } |
| 147 | |
| 148 | #define DEFINE_LIST_INTERFACE(Type, name) \ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 149 | inline const Type& get_##name (unsigned int i) const { \ |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 150 | 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 Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 162 | inline const Tag& get_##name##_tag (unsigned int i) const { \ |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 163 | 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 Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 172 | 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 Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 182 | } \ |
| 183 | inline const Type& get_##name##_by_tag (hb_tag_t tag) const { \ |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 184 | unsigned int i; \ |
| 185 | if (find_##name##_index (tag, &i)) \ |
| 186 | return get_##name (i); \ |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 187 | else \ |
| 188 | return Null##Type; \ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 189 | } |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 190 | |
| 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 Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 198 | protected: inline Type() {} /* cannot be instantiated */ \ |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 199 | public: |
| 200 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 201 | // TODO use a global nul-array for most Null's |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 202 | /* 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 Esfahbod | 54e5aac | 2008-01-27 21:19:51 -0500 | [diff] [blame] | 214 | /* XXX static */ const NewType &Null##NewType = *(NewType *)Null##OldType##Data |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 215 | |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 216 | /* 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 Esfahbod | 54e5aac | 2008-01-27 21:19:51 -0500 | [diff] [blame] | 218 | * fancy, NULL-safe, cast! */ |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 219 | #define STATIC_DEFINE_GET_FOR_DATA(Type) \ |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 220 | 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 Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 228 | |
| 229 | |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 230 | #define DEFINE_GET_ACCESSOR(Type, name, Name) \ |
| 231 | inline const Type& get_##name (void) const { \ |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 232 | if (HB_UNLIKELY (!Name)) return Null##Type; \ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 233 | return *(const Type*)((const char*)this + Name); \ |
| 234 | } |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 235 | #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 Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 240 | |
| 241 | |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 242 | |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 243 | |
Behdad Esfahbod | f78e70c | 2006-12-21 22:30:38 -0500 | [diff] [blame] | 244 | /* |
| 245 | * |
| 246 | * The OpenType Font File |
| 247 | * |
| 248 | */ |
| 249 | |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 250 | |
| 251 | |
Behdad Esfahbod | f78e70c | 2006-12-21 22:30:38 -0500 | [diff] [blame] | 252 | /* |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 253 | * Data Types |
Behdad Esfahbod | f78e70c | 2006-12-21 22:30:38 -0500 | [diff] [blame] | 254 | */ |
| 255 | |
| 256 | |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 257 | /* "The following data types are used in the OpenType font file. |
| 258 | * All OpenType fonts use Motorola-style byte ordering (Big Endian):" */ |
Behdad Esfahbod | f78e70c | 2006-12-21 22:30:38 -0500 | [diff] [blame] | 259 | |
| 260 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 261 | DEFINE_INT_TYPE_STRUCT (BYTE, u, 8); /* 8-bit unsigned integer. */ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 262 | DEFINE_NULL_ASSERT_SIZE (BYTE, 1); |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 263 | DEFINE_INT_TYPE_STRUCT (CHAR, , 8); /* 8-bit signed integer. */ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 264 | DEFINE_NULL_ASSERT_SIZE (CHAR, 1); |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 265 | DEFINE_INT_TYPE_STRUCT (USHORT, u, 16); /* 16-bit unsigned integer. */ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 266 | DEFINE_NULL_ASSERT_SIZE (USHORT, 2); |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 267 | DEFINE_INT_TYPE_STRUCT (SHORT, , 16); /* 16-bit signed integer. */ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 268 | DEFINE_NULL_ASSERT_SIZE (SHORT, 2); |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 269 | DEFINE_INT_TYPE_STRUCT (ULONG, u, 32); /* 32-bit unsigned integer. */ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 270 | DEFINE_NULL_ASSERT_SIZE (ULONG, 4); |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 271 | DEFINE_INT_TYPE_STRUCT (LONG, , 32); /* 32-bit signed integer. */ |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 272 | DEFINE_NULL_ASSERT_SIZE (LONG, 4); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 273 | |
| 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 Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 276 | DEFINE_INT_TYPE_STRUCT (LONGDATETIME, , 64); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 277 | |
| 278 | /* 32-bit signed fixed-point number (16.16) */ |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 279 | struct 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 Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 284 | inline operator double(void) const { return (uint32_t) this / 65536.; } |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 285 | 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 Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 291 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 292 | DEFINE_NULL_ASSERT_SIZE (Fixed, 4); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 293 | |
| 294 | /* Smallest measurable distance in the em space. */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 295 | struct FUNIT; |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 296 | |
| 297 | /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 298 | struct FWORD : SHORT { |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 299 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 300 | DEFINE_NULL_ASSERT_SIZE (FWORD, 2); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 301 | |
| 302 | /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 303 | struct UFWORD : USHORT { |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 304 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 305 | DEFINE_NULL_ASSERT_SIZE (UFWORD, 2); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 306 | |
| 307 | /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 308 | struct F2DOT14 : SHORT { |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 309 | inline operator double() const { return (uint32_t) this / 16384.; } |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 310 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 311 | DEFINE_NULL_ASSERT_SIZE (F2DOT14, 2); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 312 | |
| 313 | /* Array of four uint8s (length = 32 bits) used to identify a script, language |
| 314 | * system, feature, or baseline */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 315 | struct Tag { |
| 316 | inline Tag (void) { v[0] = v[1] = v[2] = v[3] = 0; } |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 317 | inline Tag (uint32_t v) { (ULONG&)(*this) = v; } |
Behdad Esfahbod | b739c05 | 2006-12-25 05:39:20 -0500 | [diff] [blame] | 318 | inline Tag (const char *c) { v[0] = c[0]; v[1] = c[1]; v[2] = c[2]; v[3] = c[3]; } |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 319 | 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 Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 320 | 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 Esfahbod | b9d7688 | 2008-01-23 01:38:10 -0500 | [diff] [blame] | 321 | inline bool operator== (uint32_t i) const { return i == (uint32_t) *this; } |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 322 | 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 Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 324 | inline operator const char* (void) const { return (const char *)this; } |
| 325 | inline operator char* (void) { return (char *)this; } |
| 326 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 327 | private: |
| 328 | char v[4]; |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 329 | }; |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 330 | ASSERT_SIZE (Tag, 4); |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 331 | DEFINE_NULL_DATA (Tag, 5, " "); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 332 | |
| 333 | /* Glyph index number, same as uint16 (length = 16 bits) */ |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 334 | DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16); |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 335 | DEFINE_NULL_ASSERT_SIZE (GlyphID, 2); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 336 | |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 337 | /* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */ |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 338 | DEFINE_INT_TYPE_STRUCT (Offset, u, 16); |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 339 | DEFINE_NULL_ASSERT_SIZE (Offset, 2); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 340 | |
| 341 | /* CheckSum */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 342 | struct CheckSum : ULONG { |
| 343 | static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) { |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 344 | uint32_t Sum = 0L; |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 345 | ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 346 | |
| 347 | while (Table < EndPtr) |
| 348 | Sum += *Table++; |
| 349 | return Sum; |
| 350 | } |
| 351 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 352 | DEFINE_NULL_ASSERT_SIZE (CheckSum, 4); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 353 | |
| 354 | |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 355 | /* |
| 356 | * Version Numbers |
| 357 | */ |
| 358 | |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 359 | struct USHORT_Version : USHORT { |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 360 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 361 | DEFINE_NULL_ASSERT_SIZE (USHORT_Version, 2); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 362 | |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 363 | struct Fixed_Version : Fixed { |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 364 | inline int16_t major (void) const { return this->int_part(); } |
| 365 | inline int16_t minor (void) const { return this->frac_part(); } |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 366 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 367 | DEFINE_NULL_ASSERT_SIZE (Fixed_Version, 4); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 368 | |
| 369 | |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 370 | /* |
| 371 | * Organization of an OpenType Font |
| 372 | */ |
| 373 | |
Behdad Esfahbod | 3158d84 | 2006-12-27 20:08:07 -0500 | [diff] [blame] | 374 | struct OpenTypeFontFile; |
Behdad Esfahbod | b739c05 | 2006-12-25 05:39:20 -0500 | [diff] [blame] | 375 | struct OffsetTable; |
| 376 | struct TTCHeader; |
| 377 | |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 378 | typedef struct TableDirectory { |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 379 | |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 380 | friend struct OpenTypeFontFile; |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 381 | friend struct OffsetTable; |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 382 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 383 | inline bool is_null (void) const { return length == 0; } |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 384 | inline const Tag& get_tag (void) const { return tag; } |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 385 | 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 Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 390 | Tag tag; /* 4-byte identifier. */ |
| 391 | CheckSum checkSum; /* CheckSum for this table. */ |
| 392 | ULONG offset; /* Offset from beginning of TrueType font |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 393 | * file. */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 394 | ULONG length; /* Length of this table. */ |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 395 | } OpenTypeTable; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 396 | DEFINE_NULL_ASSERT_SIZE (TableDirectory, 16); |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 397 | DEFINE_NULL_ALIAS (OpenTypeTable, TableDirectory); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 398 | |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 399 | typedef struct OffsetTable { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 400 | |
| 401 | friend struct OpenTypeFontFile; |
| 402 | friend struct TTCHeader; |
| 403 | |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 404 | DEFINE_TAG_ARRAY_INTERFACE (OpenTypeTable, table); /* get_table_count(), get_table(i), get_table_tag(i) */ |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 405 | DEFINE_TAG_FIND_INTERFACE (OpenTypeTable, table); /* find_table_index(tag), get_table_by_tag(tag) */ |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 406 | |
| 407 | private: |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 408 | /* OpenTypeTables, in no particular order */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 409 | DEFINE_ARRAY_TYPE (TableDirectory, tableDir, numTables); |
| 410 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 411 | private: |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 412 | 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 Esfahbod | 1334661 | 2006-12-27 19:58:32 -0500 | [diff] [blame] | 418 | } OpenTypeFontFace; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 419 | DEFINE_NULL_ASSERT_SIZE (OffsetTable, 12); |
| 420 | DEFINE_NULL_ALIAS (OpenTypeFontFace, OffsetTable); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 421 | |
| 422 | /* |
| 423 | * TrueType Collections |
| 424 | */ |
| 425 | |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 426 | struct TTCHeader { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 427 | |
| 428 | friend struct OpenTypeFontFile; |
| 429 | |
| 430 | private: |
Behdad Esfahbod | 1334661 | 2006-12-27 19:58:32 -0500 | [diff] [blame] | 431 | /* OpenTypeFontFaces, in no particular order */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 432 | DEFINE_OFFSET_ARRAY_TYPE (OffsetTable, offsetTable, numFonts); |
Behdad Esfahbod | aefaafe | 2008-01-23 17:25:29 -0500 | [diff] [blame] | 433 | /* XXX check version here? */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 434 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 435 | private: |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 436 | Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 437 | ULONG version; /* Version of the TTC Header (1.0 or 2.0), |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 438 | * 0x00010000 or 0x00020000 */ |
Behdad Esfahbod | 01e4fcb | 2006-12-21 22:31:31 -0500 | [diff] [blame] | 439 | ULONG numFonts; /* Number of fonts in TTC */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 440 | ULONG offsetTable[]; /* Array of offsets to the OffsetTable for each font |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 441 | * from the beginning of the file */ |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 442 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 443 | DEFINE_NULL_ASSERT_SIZE (TTCHeader, 12); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 444 | |
| 445 | |
Behdad Esfahbod | b739c05 | 2006-12-25 05:39:20 -0500 | [diff] [blame] | 446 | /* |
| 447 | * OpenType Font File |
| 448 | */ |
| 449 | |
Behdad Esfahbod | 3158d84 | 2006-12-27 20:08:07 -0500 | [diff] [blame] | 450 | struct OpenTypeFontFile { |
| 451 | DEFINE_NON_INSTANTIABLE(OpenTypeFontFile); |
Behdad Esfahbod | c81efca | 2006-12-25 06:22:08 -0500 | [diff] [blame] | 452 | 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 Esfahbod | b739c05 | 2006-12-25 05:39:20 -0500 | [diff] [blame] | 455 | |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 456 | STATIC_DEFINE_GET_FOR_DATA (OpenTypeFontFile); |
Behdad Esfahbod | b739c05 | 2006-12-25 05:39:20 -0500 | [diff] [blame] | 457 | |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 458 | DEFINE_ARRAY_INTERFACE (OpenTypeFontFace, face); /* get_face_count(), get_face(i) */ |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 459 | |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 460 | inline const Tag& get_tag (void) const { return tag; } |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 461 | |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 462 | /* This is how you get a table */ |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 463 | inline const char* get_table_data (const OpenTypeTable& table) const { |
| 464 | return (*this)[table]; |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 465 | } |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 466 | inline char* get_table_data (const OpenTypeTable& table) { |
| 467 | return (*this)[table]; |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 468 | } |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 469 | |
| 470 | private: |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 471 | inline const char* operator[] (const OpenTypeTable& table) const { |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 472 | if (G_UNLIKELY (table.offset == 0)) return NULL; |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 473 | return ((const char*)this) + table.offset; |
| 474 | } |
| 475 | inline char* operator[] (const OpenTypeTable& table) { |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 476 | if (G_UNLIKELY (table.offset == 0)) return NULL; |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 477 | return ((char*)this) + table.offset; |
| 478 | } |
| 479 | |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 480 | /* Array interface sans get_size() */ |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 481 | unsigned int get_len (void) const { |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 482 | switch (tag) { |
| 483 | default: return 0; |
Behdad Esfahbod | c81efca | 2006-12-25 06:22:08 -0500 | [diff] [blame] | 484 | case TrueTypeTag: case CFFTag: return 1; |
| 485 | case TTCTag: return ((const TTCHeader&)*this).get_len(); |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 486 | } |
| 487 | } |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 488 | const OpenTypeFontFace& operator[] (unsigned int i) const { |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 489 | if (HB_UNLIKELY (i >= get_len ())) return NullOpenTypeFontFace; |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 490 | switch (tag) { |
Behdad Esfahbod | c81efca | 2006-12-25 06:22:08 -0500 | [diff] [blame] | 491 | default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this; |
| 492 | case TTCTag: return ((const TTCHeader&)*this)[i]; |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 493 | } |
| 494 | } |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 495 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 496 | private: |
Behdad Esfahbod | 808dbe2 | 2006-12-25 06:18:52 -0500 | [diff] [blame] | 497 | Tag tag; /* 4-byte identifier. */ |
Behdad Esfahbod | b739c05 | 2006-12-25 05:39:20 -0500 | [diff] [blame] | 498 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 499 | DEFINE_NULL_ASSERT_SIZE (OpenTypeFontFile, 4); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 500 | |
| 501 | |
| 502 | |
| 503 | /* |
| 504 | * |
| 505 | * OpenType Layout Common Table Formats |
| 506 | * |
| 507 | */ |
| 508 | |
Behdad Esfahbod | 53502c6 | 2006-12-26 19:29:08 -0500 | [diff] [blame] | 509 | /* |
Behdad Esfahbod | 1334661 | 2006-12-27 19:58:32 -0500 | [diff] [blame] | 510 | * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList |
Behdad Esfahbod | 53502c6 | 2006-12-26 19:29:08 -0500 | [diff] [blame] | 511 | */ |
| 512 | |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 513 | typedef 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 Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 518 | DEFINE_NULL_ASSERT_SIZE (Record, 6); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 519 | |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 520 | struct LangSys { |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 521 | |
| 522 | DEFINE_INDEX_ARRAY_INTERFACE (feature); |
| 523 | |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 524 | inline const bool has_required_feature (void) const { |
| 525 | return reqFeatureIndex != 0xffff; |
| 526 | } |
| 527 | /* Returns NO_INDEX if none */ |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 528 | inline int get_required_feature_index (void) const { |
| 529 | if (reqFeatureIndex == 0xffff) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 530 | return NO_INDEX; |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 531 | return reqFeatureIndex;; |
| 532 | } |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 533 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 534 | private: |
| 535 | /* Feature indices, in no particular order */ |
| 536 | DEFINE_ARRAY_TYPE (USHORT, featureIndex, featureCount); |
Behdad Esfahbod | b9d7688 | 2008-01-23 01:38:10 -0500 | [diff] [blame] | 537 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 538 | private: |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 539 | Offset lookupOrder; /* = Null (reserved for an offset to a |
Behdad Esfahbod | befc022 | 2006-12-25 09:14:52 -0500 | [diff] [blame] | 540 | * 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 Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 548 | * arbitrary order. featureCount entires long */ |
Behdad Esfahbod | b6e62bc | 2006-12-22 02:21:55 -0500 | [diff] [blame] | 549 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 550 | DEFINE_NULL_ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF"); |
| 551 | |
| 552 | struct Script { |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 553 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 554 | /* 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 Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 563 | |
| 564 | inline const Tag& get_lang_sys_tag (unsigned int i) const { |
| 565 | return get_tag (i); |
| 566 | } |
| 567 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 568 | // LONGTERMTODO bsearch |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 569 | DEFINE_TAG_FIND_INTERFACE (LangSys, lang_sys); /* find_lang_sys_index (), get_lang_sys_by_tag (tag) */ |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 570 | |
| 571 | inline const bool has_default_lang_sys (void) const { |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 572 | return defaultLangSys != 0; |
| 573 | } |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 574 | inline const LangSys& get_default_lang_sys (void) const { |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 575 | if (HB_UNLIKELY (!defaultLangSys)) |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 576 | return NullLangSys; |
| 577 | return *(LangSys*)((const char*)this + defaultLangSys); |
| 578 | } |
| 579 | |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 580 | private: |
| 581 | /* LangSys', in sorted alphabetical tag order */ |
| 582 | DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount); |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 583 | |
| 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 | }; |
| 592 | DEFINE_NULL_ASSERT_SIZE (Script, 4); |
| 593 | |
| 594 | struct ScriptList { |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 595 | |
| 596 | friend struct GSUBGPOS; |
| 597 | |
| 598 | private: |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 599 | /* Scripts, in sorted alphabetical tag order */ |
| 600 | DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount); |
| 601 | |
| 602 | private: |
| 603 | USHORT scriptCount; /* Number of ScriptRecords */ |
| 604 | ScriptRecord scriptRecord[]; /* Array of ScriptRecords--listed alphabetically |
| 605 | * by ScriptTag */ |
| 606 | }; |
| 607 | DEFINE_NULL_ASSERT_SIZE (ScriptList, 2); |
| 608 | |
| 609 | struct Feature { |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 610 | |
Behdad Esfahbod | 5722567 | 2008-02-18 20:58:39 -0500 | [diff] [blame] | 611 | DEFINE_INDEX_ARRAY_INTERFACE (lookup); /* get_lookup_count(), get_lookup_index(i) */ |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 612 | |
| 613 | private: |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 614 | /* LookupList indices, in no particular order */ |
| 615 | DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount); |
| 616 | |
Behdad Esfahbod | 5722567 | 2008-02-18 20:58:39 -0500 | [diff] [blame] | 617 | /* TODO: implement get_feature_parameters() */ |
| 618 | /* TODO: implement FeatureSize and other special features? */ |
| 619 | |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 620 | private: |
| 621 | Offset featureParams; /* Offset to Feature Parameters table (if one |
| 622 | * has been defined for the feature), relative |
Behdad Esfahbod | ce48f03 | 2009-11-02 14:35:51 -0500 | [diff] [blame] | 623 | * to the beginning of the Feature Table; = Null |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 624 | * 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 | }; |
| 631 | DEFINE_NULL_ASSERT_SIZE (Feature, 4); |
Behdad Esfahbod | 6b4ce01 | 2006-12-21 22:31:10 -0500 | [diff] [blame] | 632 | |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 633 | struct FeatureList { |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 634 | |
| 635 | friend struct GSUBGPOS; |
| 636 | |
| 637 | private: |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 638 | /* Feature indices, in sorted alphabetical tag order */ |
| 639 | DEFINE_RECORD_ARRAY_TYPE (Feature, featureRecord, featureCount); |
| 640 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 641 | private: |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 642 | USHORT featureCount; /* Number of FeatureRecords in this table */ |
| 643 | FeatureRecord featureRecord[];/* Array of FeatureRecords--zero-based (first |
| 644 | * feature has FeatureIndex = 0)--listed |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 645 | * alphabetically by FeatureTag */ |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 646 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 647 | DEFINE_NULL_ASSERT_SIZE (FeatureList, 2); |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 648 | |
| 649 | struct LookupFlag : USHORT { |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 650 | 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 Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 656 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 657 | DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2); |
| 658 | |
| 659 | struct LookupSubTable { |
| 660 | DEFINE_NON_INSTANTIABLE(LookupSubTable); |
| 661 | |
| 662 | private: |
| 663 | USHORT format; /* Subtable format. Different for GSUB and GPOS */ |
| 664 | }; |
| 665 | DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2); |
| 666 | |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 667 | |
| 668 | struct Lookup { |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 669 | DEFINE_NON_INSTANTIABLE(Lookup); |
| 670 | |
| 671 | DEFINE_ARRAY_INTERFACE (LookupSubTable, subtable); /* get_subtable_count(), get_subtable(i) */ |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 672 | |
| 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 Esfahbod | 30bd763 | 2009-04-15 22:56:15 -0400 | [diff] [blame] | 677 | inline unsigned int get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; } |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 678 | |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 679 | inline unsigned int get_type (void) const { return lookupType; } |
| 680 | inline unsigned int get_flag (void) const { return lookupFlag; } |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 681 | |
| 682 | private: |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 683 | /* SubTables, in the desired order */ |
| 684 | DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount); |
| 685 | |
| 686 | protected: |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 687 | 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 Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 691 | * beginning of Lookup table */ |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 692 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 693 | DEFINE_NULL_ASSERT_SIZE (Lookup, 6); |
| 694 | |
| 695 | struct LookupList { |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 696 | |
| 697 | friend struct GSUBGPOS; |
| 698 | |
| 699 | private: |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 700 | /* 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 | }; |
| 709 | DEFINE_NULL_ASSERT_SIZE (LookupList, 2); |
Behdad Esfahbod | f8ba99f | 2006-12-25 09:58:02 -0500 | [diff] [blame] | 710 | |
Behdad Esfahbod | 53502c6 | 2006-12-26 19:29:08 -0500 | [diff] [blame] | 711 | /* |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 712 | * Coverage Table |
Behdad Esfahbod | 53502c6 | 2006-12-26 19:29:08 -0500 | [diff] [blame] | 713 | */ |
| 714 | |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 715 | struct CoverageFormat1 { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 716 | |
| 717 | friend struct Coverage; |
| 718 | |
| 719 | private: |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 720 | /* GlyphIDs, in sorted numerical order */ |
| 721 | DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount); |
| 722 | |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 723 | inline unsigned int get_coverage (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | c46196d | 2006-12-27 20:05:16 -0500 | [diff] [blame] | 724 | GlyphID gid; |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 725 | if (HB_UNLIKELY (glyph_id > 65535)) |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 726 | return NOT_COVERED; |
Behdad Esfahbod | c46196d | 2006-12-27 20:05:16 -0500 | [diff] [blame] | 727 | gid = glyph_id; |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 728 | // TODO: bsearch |
Behdad Esfahbod | 12360f7 | 2008-01-23 15:50:38 -0500 | [diff] [blame] | 729 | for (unsigned int i = 0; i < glyphCount; i++) |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 730 | if (gid == glyphArray[i]) |
| 731 | return i; |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 732 | return NOT_COVERED; |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 733 | } |
| 734 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 735 | private: |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 736 | 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 Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 739 | }; |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 740 | ASSERT_SIZE (CoverageFormat1, 4); |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 741 | |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 742 | struct CoverageRangeRecord { |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 743 | |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 744 | friend struct CoverageFormat2; |
| 745 | |
| 746 | private: |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 747 | inline unsigned int get_coverage (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 748 | if (glyph_id >= start && glyph_id <= end) |
| 749 | return startCoverageIndex + (glyph_id - start); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 750 | return NOT_COVERED; |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 751 | } |
| 752 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 753 | private: |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 754 | 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 Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 759 | DEFINE_NULL_ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\001"); |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 760 | |
| 761 | struct CoverageFormat2 { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 762 | |
| 763 | friend struct Coverage; |
| 764 | |
| 765 | private: |
Behdad Esfahbod | 0d6db2a | 2006-12-26 18:53:55 -0500 | [diff] [blame] | 766 | /* CoverageRangeRecords, in sorted numerical start order */ |
| 767 | DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount); |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 768 | |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 769 | inline unsigned int get_coverage (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 770 | // TODO: bsearch |
Behdad Esfahbod | eed05b0 | 2009-05-06 00:25:59 -0400 | [diff] [blame] | 771 | unsigned int count = rangeCount; |
| 772 | for (unsigned int i = 0; i < count; i++) { |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 773 | int coverage = rangeRecord[i].get_coverage (glyph_id); |
| 774 | if (coverage >= 0) |
| 775 | return coverage; |
| 776 | } |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 777 | return NOT_COVERED; |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 778 | } |
| 779 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 780 | private: |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 781 | USHORT coverageFormat; /* Format identifier--format = 2 */ |
| 782 | USHORT rangeCount; /* Number of CoverageRangeRecords */ |
| 783 | CoverageRangeRecord rangeRecord[]; /* Array of glyph ranges--ordered by |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 784 | * Start GlyphID. rangeCount entries |
| 785 | * long */ |
| 786 | }; |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 787 | ASSERT_SIZE (CoverageFormat2, 4); |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 788 | |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 789 | struct Coverage { |
Behdad Esfahbod | 53502c6 | 2006-12-26 19:29:08 -0500 | [diff] [blame] | 790 | DEFINE_NON_INSTANTIABLE(Coverage); |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 791 | |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 792 | unsigned int get_size (void) const { |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 793 | 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 Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 797 | } |
| 798 | } |
| 799 | |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 800 | unsigned int get_coverage (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 801 | switch (u.coverageFormat) { |
| 802 | case 1: return u.format1.get_coverage(glyph_id); |
| 803 | case 2: return u.format2.get_coverage(glyph_id); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 804 | default:return NOT_COVERED; |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 805 | } |
| 806 | } |
| 807 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 808 | private: |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 809 | union { |
Behdad Esfahbod | c46196d | 2006-12-27 20:05:16 -0500 | [diff] [blame] | 810 | USHORT coverageFormat; /* Format identifier */ |
| 811 | CoverageFormat1 format1; |
| 812 | CoverageFormat2 format2; |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 813 | } u; |
Behdad Esfahbod | 0c0d553 | 2006-12-26 15:29:38 -0500 | [diff] [blame] | 814 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 815 | DEFINE_NULL (Coverage, 2); |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 816 | |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 817 | /* |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 818 | * Class Definition Table |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 819 | */ |
| 820 | |
| 821 | struct ClassDefFormat1 { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 822 | |
| 823 | friend struct ClassDef; |
| 824 | |
| 825 | private: |
Behdad Esfahbod | 52886ca | 2009-04-16 14:19:42 -0400 | [diff] [blame] | 826 | /* Class Values, in sorted numerical order */ |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 827 | DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount); |
| 828 | |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 829 | inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 830 | if (glyph_id >= startGlyph && glyph_id - startGlyph < glyphCount) |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 831 | return classValueArray[glyph_id - startGlyph]; |
| 832 | return 0; |
| 833 | } |
| 834 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 835 | private: |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 836 | 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 Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 841 | ASSERT_SIZE (ClassDefFormat1, 6); |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 842 | |
| 843 | struct ClassRangeRecord { |
| 844 | |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 845 | friend struct ClassDefFormat2; |
| 846 | |
| 847 | private: |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 848 | inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 849 | if (glyph_id >= start && glyph_id <= end) |
| 850 | return classValue; |
| 851 | return 0; |
| 852 | } |
| 853 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 854 | private: |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 855 | GlyphID start; /* First GlyphID in the range */ |
| 856 | GlyphID end; /* Last GlyphID in the range */ |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 857 | USHORT classValue; /* Applied to all glyphs in the range */ |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 858 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 859 | DEFINE_NULL_ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\001"); |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 860 | |
| 861 | struct ClassDefFormat2 { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 862 | |
| 863 | friend struct ClassDef; |
| 864 | |
| 865 | private: |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 866 | /* ClassRangeRecords, in sorted numerical start order */ |
| 867 | DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount); |
| 868 | |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 869 | inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 870 | // TODO: bsearch |
Behdad Esfahbod | eed05b0 | 2009-05-06 00:25:59 -0400 | [diff] [blame] | 871 | unsigned int count = rangeCount; |
| 872 | for (unsigned int i = 0; i < count; i++) { |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 873 | int classValue = rangeRecord[i].get_class (glyph_id); |
| 874 | if (classValue > 0) |
| 875 | return classValue; |
| 876 | } |
| 877 | return 0; |
| 878 | } |
| 879 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 880 | private: |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 881 | 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 Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 886 | ASSERT_SIZE (ClassDefFormat2, 4); |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 887 | |
| 888 | struct ClassDef { |
| 889 | DEFINE_NON_INSTANTIABLE(ClassDef); |
| 890 | |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 891 | unsigned int get_size (void) const { |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 892 | 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 Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 896 | } |
| 897 | } |
| 898 | |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 899 | hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const { |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 900 | switch (u.classFormat) { |
Behdad Esfahbod | b9d7688 | 2008-01-23 01:38:10 -0500 | [diff] [blame] | 901 | case 1: return u.format1.get_class(glyph_id); |
| 902 | case 2: return u.format2.get_class(glyph_id); |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 903 | default:return 0; |
| 904 | } |
| 905 | } |
| 906 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 907 | private: |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 908 | union { |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 909 | USHORT classFormat; /* Format identifier */ |
Behdad Esfahbod | bf0f9dd | 2006-12-27 20:06:42 -0500 | [diff] [blame] | 910 | ClassDefFormat1 format1; |
| 911 | ClassDefFormat2 format2; |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 912 | } u; |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 913 | }; |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 914 | DEFINE_NULL (ClassDef, 2); |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 915 | |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 916 | /* |
| 917 | * Device Tables |
| 918 | */ |
Behdad Esfahbod | eb32e37 | 2006-12-26 20:00:33 -0500 | [diff] [blame] | 919 | |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 920 | struct Device { |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 921 | DEFINE_NON_INSTANTIABLE(Device); |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 922 | |
Behdad Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 923 | unsigned int get_size (void) const { |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 924 | 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 Esfahbod | 7586089 | 2008-01-23 18:02:28 -0500 | [diff] [blame] | 934 | int get_delta (int ppem_size) const { |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 935 | 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 Esfahbod | ce48f03 | 2009-11-02 14:35:51 -0500 | [diff] [blame] | 943 | |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 944 | 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 Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 954 | private: |
Behdad Esfahbod | 2b73745 | 2006-12-26 20:55:37 -0500 | [diff] [blame] | 955 | 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 Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 960 | DEFINE_NULL_ASSERT_SIZE (Device, 6); |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 961 | |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 962 | /* |
Behdad Esfahbod | aefaafe | 2008-01-23 17:25:29 -0500 | [diff] [blame] | 963 | * GSUB/GPOS Common |
Behdad Esfahbod | 1f437e6 | 2008-01-23 04:36:40 -0500 | [diff] [blame] | 964 | */ |
Behdad Esfahbod | 25ad92c | 2006-12-25 09:35:06 -0500 | [diff] [blame] | 965 | |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 966 | struct GSUBGPOS { |
Behdad Esfahbod | 600e5eb | 2008-01-23 02:01:37 -0500 | [diff] [blame] | 967 | 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 Esfahbod | aefaafe | 2008-01-23 17:25:29 -0500 | [diff] [blame] | 970 | STATIC_DEFINE_GET_FOR_DATA (GSUBGPOS); |
| 971 | /* XXX check version here? */ |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 972 | |
Behdad Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 973 | 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 Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 977 | // LONGTERMTODO bsearch |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 978 | 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 Esfahbod | 40a8131 | 2008-01-28 02:30:48 -0500 | [diff] [blame] | 980 | |
| 981 | private: |
| 982 | DEFINE_LIST_ARRAY(Script, script); |
| 983 | DEFINE_LIST_ARRAY(Feature, feature); |
| 984 | DEFINE_LIST_ARRAY(Lookup, lookup); |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 985 | |
Behdad Esfahbod | 303fe62 | 2008-01-23 00:20:48 -0500 | [diff] [blame] | 986 | private: |
Behdad Esfahbod | 5b2e947 | 2007-07-06 02:03:26 -0400 | [diff] [blame] | 987 | 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 Esfahbod | aefaafe | 2008-01-23 17:25:29 -0500 | [diff] [blame] | 995 | }; |
| 996 | DEFINE_NULL_ASSERT_SIZE (GSUBGPOS, 10); |
Behdad Esfahbod | 71d62ba | 2006-12-27 01:29:24 -0500 | [diff] [blame] | 997 | |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 998 | /* XXX */ |
| 999 | #include "harfbuzz-impl.h" |
| 1000 | HB_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 Esfahbod | 8dd1c8b | 2008-01-23 05:00:30 -0500 | [diff] [blame] | 1008 | #endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */ |