OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2007,2008,2009 Red Hat, Inc. | |
3 * Copyright (C) 2010 Google, Inc. | |
4 * | |
5 * This is part of HarfBuzz, a text shaping library. | |
6 * | |
7 * Permission is hereby granted, without written agreement and without | |
8 * license or royalty fees, to use, copy, modify, and distribute this | |
9 * software and its documentation for any purpose, provided that the | |
10 * above copyright notice and the following two paragraphs appear in | |
11 * all copies of this software. | |
12 * | |
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | |
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | |
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | |
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | |
17 * DAMAGE. | |
18 * | |
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | |
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | |
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | |
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
24 * | |
25 * Red Hat Author(s): Behdad Esfahbod | |
26 * Google Author(s): Behdad Esfahbod | |
27 */ | |
28 | |
29 #ifndef HB_OT_LAYOUT_GDEF_PRIVATE_HH | |
30 #define HB_OT_LAYOUT_GDEF_PRIVATE_HH | |
31 | |
32 #include "hb-ot-layout-common-private.hh" | |
33 | |
34 #include "hb-font-private.h" | |
35 | |
36 HB_BEGIN_DECLS | |
37 | |
38 | |
39 /* | |
40 * Attachment List Table | |
41 */ | |
42 | |
43 typedef ArrayOf<USHORT> AttachPoint; /* Array of contour point indices--in | |
44 * increasing numerical order */ | |
45 | |
46 struct AttachList | |
47 { | |
48 inline unsigned int get_attach_points (hb_codepoint_t glyph_id, | |
49 unsigned int start_offset, | |
50 unsigned int *point_count /* IN/OUT */, | |
51 unsigned int *point_array /* OUT */) co
nst | |
52 { | |
53 unsigned int index = (this+coverage) (glyph_id); | |
54 if (index == NOT_COVERED) | |
55 { | |
56 if (point_count) | |
57 *point_count = 0; | |
58 return 0; | |
59 } | |
60 | |
61 const AttachPoint &points = this+attachPoint[index]; | |
62 | |
63 if (point_count) { | |
64 const USHORT *array = points.sub_array (start_offset, point_count); | |
65 unsigned int count = *point_count; | |
66 for (unsigned int i = 0; i < count; i++) | |
67 point_array[i] = array[i]; | |
68 } | |
69 | |
70 return points.len; | |
71 } | |
72 | |
73 inline bool sanitize (hb_sanitize_context_t *c) { | |
74 TRACE_SANITIZE (); | |
75 return coverage.sanitize (c, this) | |
76 && attachPoint.sanitize (c, this); | |
77 } | |
78 | |
79 private: | |
80 OffsetTo<Coverage> | |
81 coverage; /* Offset to Coverage table -- from | |
82 * beginning of AttachList table */ | |
83 OffsetArrayOf<AttachPoint> | |
84 attachPoint; /* Array of AttachPoint tables | |
85 * in Coverage Index order */ | |
86 public: | |
87 DEFINE_SIZE_ARRAY (4, attachPoint); | |
88 }; | |
89 | |
90 /* | |
91 * Ligature Caret Table | |
92 */ | |
93 | |
94 struct CaretValueFormat1 | |
95 { | |
96 friend struct CaretValue; | |
97 | |
98 private: | |
99 inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t directio
n, hb_codepoint_t glyph_id HB_UNUSED) const | |
100 { | |
101 return HB_DIRECTION_IS_HORIZONTAL (direction) ? c->scale_x (coordinate) : c-
>scale_y (coordinate); | |
102 } | |
103 | |
104 inline bool sanitize (hb_sanitize_context_t *c) { | |
105 TRACE_SANITIZE (); | |
106 return c->check_struct (this); | |
107 } | |
108 | |
109 private: | |
110 USHORT caretValueFormat; /* Format identifier--format = 1 */ | |
111 SHORT coordinate; /* X or Y value, in design units */ | |
112 public: | |
113 DEFINE_SIZE_STATIC (4); | |
114 }; | |
115 | |
116 struct CaretValueFormat2 | |
117 { | |
118 friend struct CaretValue; | |
119 | |
120 private: | |
121 inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t directio
n, hb_codepoint_t glyph_id) const | |
122 { | |
123 hb_position_t x, y; | |
124 if (hb_font_get_contour_point (c->font, c->face, caretValuePoint, glyph_id,
&x, &y)) | |
125 return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; | |
126 else | |
127 return 0; | |
128 } | |
129 | |
130 inline bool sanitize (hb_sanitize_context_t *c) { | |
131 TRACE_SANITIZE (); | |
132 return c->check_struct (this); | |
133 } | |
134 | |
135 private: | |
136 USHORT caretValueFormat; /* Format identifier--format = 2 */ | |
137 USHORT caretValuePoint; /* Contour point index on glyph */ | |
138 public: | |
139 DEFINE_SIZE_STATIC (4); | |
140 }; | |
141 | |
142 struct CaretValueFormat3 | |
143 { | |
144 friend struct CaretValue; | |
145 | |
146 inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t directio
n, hb_codepoint_t glyph_id) const | |
147 { | |
148 return HB_DIRECTION_IS_HORIZONTAL (direction) ? | |
149 c->scale_x (coordinate) + (this+deviceTable).get_x_delta (c) : | |
150 c->scale_y (coordinate) + (this+deviceTable).get_y_delta (c); | |
151 } | |
152 | |
153 inline bool sanitize (hb_sanitize_context_t *c) { | |
154 TRACE_SANITIZE (); | |
155 return c->check_struct (this) | |
156 && deviceTable.sanitize (c, this); | |
157 } | |
158 | |
159 private: | |
160 USHORT caretValueFormat; /* Format identifier--format = 3 */ | |
161 SHORT coordinate; /* X or Y value, in design units */ | |
162 OffsetTo<Device> | |
163 deviceTable; /* Offset to Device table for X or Y | |
164 * value--from beginning of CaretValue | |
165 * table */ | |
166 public: | |
167 DEFINE_SIZE_STATIC (6); | |
168 }; | |
169 | |
170 struct CaretValue | |
171 { | |
172 inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t directio
n, hb_codepoint_t glyph_id) const | |
173 { | |
174 switch (u.format) { | |
175 case 1: return u.format1.get_caret_value (c, direction, glyph_id); | |
176 case 2: return u.format2.get_caret_value (c, direction, glyph_id); | |
177 case 3: return u.format3.get_caret_value (c, direction, glyph_id); | |
178 default:return 0; | |
179 } | |
180 } | |
181 | |
182 inline bool sanitize (hb_sanitize_context_t *c) { | |
183 TRACE_SANITIZE (); | |
184 if (!u.format.sanitize (c)) return false; | |
185 switch (u.format) { | |
186 case 1: return u.format1.sanitize (c); | |
187 case 2: return u.format2.sanitize (c); | |
188 case 3: return u.format3.sanitize (c); | |
189 default:return true; | |
190 } | |
191 } | |
192 | |
193 private: | |
194 union { | |
195 USHORT format; /* Format identifier */ | |
196 CaretValueFormat1 format1; | |
197 CaretValueFormat2 format2; | |
198 CaretValueFormat3 format3; | |
199 } u; | |
200 public: | |
201 DEFINE_SIZE_UNION (2, format); | |
202 }; | |
203 | |
204 struct LigGlyph | |
205 { | |
206 inline unsigned int get_lig_carets (hb_ot_layout_context_t *c, | |
207 hb_direction_t direction, | |
208 hb_codepoint_t glyph_id, | |
209 unsigned int start_offset, | |
210 unsigned int *caret_count /* IN/OUT */, | |
211 int *caret_array /* OUT */) const | |
212 { | |
213 if (caret_count) { | |
214 const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_
count); | |
215 unsigned int count = *caret_count; | |
216 for (unsigned int i = 0; i < count; i++) | |
217 caret_array[i] = (this+array[i]).get_caret_value (c, direction, glyph_id
); | |
218 } | |
219 | |
220 return carets.len; | |
221 } | |
222 | |
223 inline bool sanitize (hb_sanitize_context_t *c) { | |
224 TRACE_SANITIZE (); | |
225 return carets.sanitize (c, this); | |
226 } | |
227 | |
228 private: | |
229 OffsetArrayOf<CaretValue> | |
230 carets; /* Offset array of CaretValue tables | |
231 * --from beginning of LigGlyph table | |
232 * --in increasing coordinate order */ | |
233 public: | |
234 DEFINE_SIZE_ARRAY (2, carets); | |
235 }; | |
236 | |
237 struct LigCaretList | |
238 { | |
239 inline unsigned int get_lig_carets (hb_ot_layout_context_t *c, | |
240 hb_direction_t direction, | |
241 hb_codepoint_t glyph_id, | |
242 unsigned int start_offset, | |
243 unsigned int *caret_count /* IN/OUT */, | |
244 int *caret_array /* OUT */) const | |
245 { | |
246 unsigned int index = (this+coverage) (glyph_id); | |
247 if (index == NOT_COVERED) | |
248 { | |
249 if (caret_count) | |
250 *caret_count = 0; | |
251 return 0; | |
252 } | |
253 const LigGlyph &lig_glyph = this+ligGlyph[index]; | |
254 return lig_glyph.get_lig_carets (c, direction, glyph_id, start_offset, caret
_count, caret_array); | |
255 } | |
256 | |
257 inline bool sanitize (hb_sanitize_context_t *c) { | |
258 TRACE_SANITIZE (); | |
259 return coverage.sanitize (c, this) | |
260 && ligGlyph.sanitize (c, this); | |
261 } | |
262 | |
263 private: | |
264 OffsetTo<Coverage> | |
265 coverage; /* Offset to Coverage table--from | |
266 * beginning of LigCaretList table */ | |
267 OffsetArrayOf<LigGlyph> | |
268 ligGlyph; /* Array of LigGlyph tables | |
269 * in Coverage Index order */ | |
270 public: | |
271 DEFINE_SIZE_ARRAY (4, ligGlyph); | |
272 }; | |
273 | |
274 | |
275 struct MarkGlyphSetsFormat1 | |
276 { | |
277 inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const | |
278 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } | |
279 | |
280 inline bool sanitize (hb_sanitize_context_t *c) { | |
281 TRACE_SANITIZE (); | |
282 return coverage.sanitize (c, this); | |
283 } | |
284 | |
285 private: | |
286 USHORT format; /* Format identifier--format = 1 */ | |
287 LongOffsetArrayOf<Coverage> | |
288 coverage; /* Array of long offsets to mark set | |
289 * coverage tables */ | |
290 public: | |
291 DEFINE_SIZE_ARRAY (4, coverage); | |
292 }; | |
293 | |
294 struct MarkGlyphSets | |
295 { | |
296 inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const | |
297 { | |
298 switch (u.format) { | |
299 case 1: return u.format1.covers (set_index, glyph_id); | |
300 default:return false; | |
301 } | |
302 } | |
303 | |
304 inline bool sanitize (hb_sanitize_context_t *c) { | |
305 TRACE_SANITIZE (); | |
306 if (!u.format.sanitize (c)) return false; | |
307 switch (u.format) { | |
308 case 1: return u.format1.sanitize (c); | |
309 default:return true; | |
310 } | |
311 } | |
312 | |
313 private: | |
314 union { | |
315 USHORT format; /* Format identifier */ | |
316 MarkGlyphSetsFormat1 format1; | |
317 } u; | |
318 public: | |
319 DEFINE_SIZE_UNION (2, format); | |
320 }; | |
321 | |
322 | |
323 /* | |
324 * GDEF | |
325 */ | |
326 | |
327 struct GDEF | |
328 { | |
329 static const hb_tag_t Tag = HB_OT_TAG_GDEF; | |
330 | |
331 enum { | |
332 UnclassifiedGlyph = 0, | |
333 BaseGlyph = 1, | |
334 LigatureGlyph = 2, | |
335 MarkGlyph = 3, | |
336 ComponentGlyph = 4 | |
337 }; | |
338 | |
339 inline bool has_glyph_classes (void) const { return glyphClassDef != 0; } | |
340 inline unsigned int get_glyph_class (hb_codepoint_t glyph) const | |
341 { return (this+glyphClassDef).get_class (glyph); } | |
342 | |
343 inline bool has_mark_attachment_types (void) const { return markAttachClassDef
!= 0; } | |
344 inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const | |
345 { return (this+markAttachClassDef).get_class (glyph); } | |
346 | |
347 inline bool has_attach_points (void) const { return attachList != 0; } | |
348 inline unsigned int get_attach_points (hb_codepoint_t glyph_id, | |
349 unsigned int start_offset, | |
350 unsigned int *point_count /* IN/OUT */, | |
351 unsigned int *point_array /* OUT */) co
nst | |
352 { return (this+attachList).get_attach_points (glyph_id, start_offset, point_co
unt, point_array); } | |
353 | |
354 inline bool has_lig_carets (void) const { return ligCaretList != 0; } | |
355 inline unsigned int get_lig_carets (hb_ot_layout_context_t *c, | |
356 hb_direction_t direction, | |
357 hb_codepoint_t glyph_id, | |
358 unsigned int start_offset, | |
359 unsigned int *caret_count /* IN/OUT */, | |
360 int *caret_array /* OUT */) const | |
361 { return (this+ligCaretList).get_lig_carets (c, direction, glyph_id, start_off
set, caret_count, caret_array); } | |
362 | |
363 inline bool has_mark_sets (void) const { return version >= 0x00010002 && markG
lyphSetsDef[0] != 0; } | |
364 inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id)
const | |
365 { return version >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index
, glyph_id); } | |
366 | |
367 inline bool sanitize (hb_sanitize_context_t *c) { | |
368 TRACE_SANITIZE (); | |
369 return version.sanitize (c) && likely (version.major == 1) | |
370 && glyphClassDef.sanitize (c, this) | |
371 && attachList.sanitize (c, this) | |
372 && ligCaretList.sanitize (c, this) | |
373 && markAttachClassDef.sanitize (c, this) | |
374 && (version < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this)); | |
375 } | |
376 | |
377 | |
378 /* glyph_props is a 16-bit integer where the lower 8-bit have bits representin
g | |
379 * glyph class and other bits, and high 8-bit gthe mark attachment type (if an
y). | |
380 * Not to be confused with lookup_props which is very similar. */ | |
381 inline unsigned int get_glyph_props (hb_codepoint_t glyph) const | |
382 { | |
383 unsigned int klass = get_glyph_class (glyph); | |
384 | |
385 switch (klass) { | |
386 default: | |
387 case UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; | |
388 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; | |
389 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; | |
390 case ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT; | |
391 case MarkGlyph: | |
392 klass = get_mark_attachment_type (glyph); | |
393 return HB_OT_LAYOUT_GLYPH_CLASS_MARK | (klass << 8); | |
394 } | |
395 } | |
396 | |
397 | |
398 private: | |
399 FixedVersion version; /* Version of the GDEF table--currently | |
400 * 0x00010002 */ | |
401 OffsetTo<ClassDef> | |
402 glyphClassDef; /* Offset to class definition table | |
403 * for glyph type--from beginning of | |
404 * GDEF header (may be Null) */ | |
405 OffsetTo<AttachList> | |
406 attachList; /* Offset to list of glyphs with | |
407 * attachment points--from beginning | |
408 * of GDEF header (may be Null) */ | |
409 OffsetTo<LigCaretList> | |
410 ligCaretList; /* Offset to list of positioning points | |
411 * for ligature carets--from beginning | |
412 * of GDEF header (may be Null) */ | |
413 OffsetTo<ClassDef> | |
414 markAttachClassDef; /* Offset to class definition table for | |
415 * mark attachment type--from beginning | |
416 * of GDEF header (may be Null) */ | |
417 OffsetTo<MarkGlyphSets> | |
418 markGlyphSetsDef[VAR]; /* Offset to the table of mark set | |
419 * definitions--from beginning of GDEF | |
420 * header (may be NULL). Introduced | |
421 * in version 00010002. */ | |
422 public: | |
423 DEFINE_SIZE_ARRAY (12, markGlyphSetsDef); | |
424 }; | |
425 | |
426 | |
427 HB_END_DECLS | |
428 | |
429 #endif /* HB_OT_LAYOUT_GDEF_PRIVATE_HH */ | |
OLD | NEW |