1 : /*
2 : * Copyright © 2007,2008,2009 Red Hat, Inc.
3 : * Copyright © 2010,2011 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_TABLE_HH
30 : #define HB_OT_LAYOUT_GDEF_TABLE_HH
31 :
32 : #include "hb-ot-layout-common-private.hh"
33 :
34 : #include "hb-font-private.hh"
35 :
36 :
37 :
38 : /*
39 : * Attachment List Table
40 : */
41 :
42 : typedef ArrayOf<USHORT> AttachPoint; /* Array of contour point indices--in
43 : * increasing numerical order */
44 :
45 : struct AttachList
46 : {
47 0 : inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
48 : unsigned int start_offset,
49 : unsigned int *point_count /* IN/OUT */,
50 : unsigned int *point_array /* OUT */) const
51 : {
52 0 : unsigned int index = (this+coverage) (glyph_id);
53 0 : if (index == NOT_COVERED)
54 : {
55 0 : if (point_count)
56 0 : *point_count = 0;
57 0 : return 0;
58 : }
59 :
60 0 : const AttachPoint &points = this+attachPoint[index];
61 :
62 0 : if (point_count) {
63 0 : const USHORT *array = points.sub_array (start_offset, point_count);
64 0 : unsigned int count = *point_count;
65 0 : for (unsigned int i = 0; i < count; i++)
66 0 : point_array[i] = array[i];
67 : }
68 :
69 0 : return points.len;
70 : }
71 :
72 0 : inline bool sanitize (hb_sanitize_context_t *c) {
73 0 : TRACE_SANITIZE ();
74 0 : return coverage.sanitize (c, this)
75 0 : && attachPoint.sanitize (c, this);
76 : }
77 :
78 : private:
79 : OffsetTo<Coverage>
80 : coverage; /* Offset to Coverage table -- from
81 : * beginning of AttachList table */
82 : OffsetArrayOf<AttachPoint>
83 : attachPoint; /* Array of AttachPoint tables
84 : * in Coverage Index order */
85 : public:
86 : DEFINE_SIZE_ARRAY (4, attachPoint);
87 : };
88 :
89 : /*
90 : * Ligature Caret Table
91 : */
92 :
93 : struct CaretValueFormat1
94 : {
95 : friend struct CaretValue;
96 :
97 : private:
98 0 : inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
99 : {
100 0 : return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
101 : }
102 :
103 0 : inline bool sanitize (hb_sanitize_context_t *c) {
104 0 : TRACE_SANITIZE ();
105 0 : return c->check_struct (this);
106 : }
107 :
108 : private:
109 : USHORT caretValueFormat; /* Format identifier--format = 1 */
110 : SHORT coordinate; /* X or Y value, in design units */
111 : public:
112 : DEFINE_SIZE_STATIC (4);
113 : };
114 :
115 : struct CaretValueFormat2
116 : {
117 : friend struct CaretValue;
118 :
119 : private:
120 0 : inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
121 : {
122 : hb_position_t x, y;
123 0 : if (hb_font_get_glyph_contour_point_for_origin (font, glyph_id, caretValuePoint, direction, &x, &y))
124 0 : return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
125 : else
126 0 : return 0;
127 : }
128 :
129 0 : inline bool sanitize (hb_sanitize_context_t *c) {
130 0 : TRACE_SANITIZE ();
131 0 : return c->check_struct (this);
132 : }
133 :
134 : private:
135 : USHORT caretValueFormat; /* Format identifier--format = 2 */
136 : USHORT caretValuePoint; /* Contour point index on glyph */
137 : public:
138 : DEFINE_SIZE_STATIC (4);
139 : };
140 :
141 : struct CaretValueFormat3
142 : {
143 : friend struct CaretValue;
144 :
145 0 : inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
146 : {
147 : return HB_DIRECTION_IS_HORIZONTAL (direction) ?
148 0 : font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
149 0 : font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
150 : }
151 :
152 0 : inline bool sanitize (hb_sanitize_context_t *c) {
153 0 : TRACE_SANITIZE ();
154 0 : return c->check_struct (this)
155 0 : && deviceTable.sanitize (c, this);
156 : }
157 :
158 : private:
159 : USHORT caretValueFormat; /* Format identifier--format = 3 */
160 : SHORT coordinate; /* X or Y value, in design units */
161 : OffsetTo<Device>
162 : deviceTable; /* Offset to Device table for X or Y
163 : * value--from beginning of CaretValue
164 : * table */
165 : public:
166 : DEFINE_SIZE_STATIC (6);
167 : };
168 :
169 : struct CaretValue
170 : {
171 0 : inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
172 : {
173 0 : switch (u.format) {
174 0 : case 1: return u.format1.get_caret_value (font, direction, glyph_id);
175 0 : case 2: return u.format2.get_caret_value (font, direction, glyph_id);
176 0 : case 3: return u.format3.get_caret_value (font, direction, glyph_id);
177 0 : default:return 0;
178 : }
179 : }
180 :
181 0 : inline bool sanitize (hb_sanitize_context_t *c) {
182 0 : TRACE_SANITIZE ();
183 0 : if (!u.format.sanitize (c)) return false;
184 0 : switch (u.format) {
185 0 : case 1: return u.format1.sanitize (c);
186 0 : case 2: return u.format2.sanitize (c);
187 0 : case 3: return u.format3.sanitize (c);
188 0 : default:return true;
189 : }
190 : }
191 :
192 : private:
193 : union {
194 : USHORT format; /* Format identifier */
195 : CaretValueFormat1 format1;
196 : CaretValueFormat2 format2;
197 : CaretValueFormat3 format3;
198 : } u;
199 : public:
200 : DEFINE_SIZE_UNION (2, format);
201 : };
202 :
203 : struct LigGlyph
204 : {
205 0 : inline unsigned int get_lig_carets (hb_font_t *font,
206 : hb_direction_t direction,
207 : hb_codepoint_t glyph_id,
208 : unsigned int start_offset,
209 : unsigned int *caret_count /* IN/OUT */,
210 : hb_position_t *caret_array /* OUT */) const
211 : {
212 0 : if (caret_count) {
213 0 : const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
214 0 : unsigned int count = *caret_count;
215 0 : for (unsigned int i = 0; i < count; i++)
216 0 : caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
217 : }
218 :
219 0 : return carets.len;
220 : }
221 :
222 0 : inline bool sanitize (hb_sanitize_context_t *c) {
223 0 : TRACE_SANITIZE ();
224 0 : return carets.sanitize (c, this);
225 : }
226 :
227 : private:
228 : OffsetArrayOf<CaretValue>
229 : carets; /* Offset array of CaretValue tables
230 : * --from beginning of LigGlyph table
231 : * --in increasing coordinate order */
232 : public:
233 : DEFINE_SIZE_ARRAY (2, carets);
234 : };
235 :
236 : struct LigCaretList
237 : {
238 0 : inline unsigned int get_lig_carets (hb_font_t *font,
239 : hb_direction_t direction,
240 : hb_codepoint_t glyph_id,
241 : unsigned int start_offset,
242 : unsigned int *caret_count /* IN/OUT */,
243 : hb_position_t *caret_array /* OUT */) const
244 : {
245 0 : unsigned int index = (this+coverage) (glyph_id);
246 0 : if (index == NOT_COVERED)
247 : {
248 0 : if (caret_count)
249 0 : *caret_count = 0;
250 0 : return 0;
251 : }
252 0 : const LigGlyph &lig_glyph = this+ligGlyph[index];
253 0 : return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
254 : }
255 :
256 0 : inline bool sanitize (hb_sanitize_context_t *c) {
257 0 : TRACE_SANITIZE ();
258 0 : return coverage.sanitize (c, this)
259 0 : && ligGlyph.sanitize (c, this);
260 : }
261 :
262 : private:
263 : OffsetTo<Coverage>
264 : coverage; /* Offset to Coverage table--from
265 : * beginning of LigCaretList table */
266 : OffsetArrayOf<LigGlyph>
267 : ligGlyph; /* Array of LigGlyph tables
268 : * in Coverage Index order */
269 : public:
270 : DEFINE_SIZE_ARRAY (4, ligGlyph);
271 : };
272 :
273 :
274 : struct MarkGlyphSetsFormat1
275 : {
276 0 : inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
277 0 : { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
278 :
279 0 : inline bool sanitize (hb_sanitize_context_t *c) {
280 0 : TRACE_SANITIZE ();
281 0 : return coverage.sanitize (c, this);
282 : }
283 :
284 : private:
285 : USHORT format; /* Format identifier--format = 1 */
286 : LongOffsetArrayOf<Coverage>
287 : coverage; /* Array of long offsets to mark set
288 : * coverage tables */
289 : public:
290 : DEFINE_SIZE_ARRAY (4, coverage);
291 : };
292 :
293 : struct MarkGlyphSets
294 : {
295 0 : inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
296 : {
297 0 : switch (u.format) {
298 0 : case 1: return u.format1.covers (set_index, glyph_id);
299 0 : default:return false;
300 : }
301 : }
302 :
303 0 : inline bool sanitize (hb_sanitize_context_t *c) {
304 0 : TRACE_SANITIZE ();
305 0 : if (!u.format.sanitize (c)) return false;
306 0 : switch (u.format) {
307 0 : case 1: return u.format1.sanitize (c);
308 0 : default:return true;
309 : }
310 : }
311 :
312 : private:
313 : union {
314 : USHORT format; /* Format identifier */
315 : MarkGlyphSetsFormat1 format1;
316 : } u;
317 : public:
318 : DEFINE_SIZE_UNION (2, format);
319 : };
320 :
321 :
322 : /*
323 : * GDEF -- The Glyph Definition Table
324 : */
325 :
326 : struct GDEF
327 : {
328 : static const hb_tag_t Tag = HB_OT_TAG_GDEF;
329 :
330 : enum {
331 : UnclassifiedGlyph = 0,
332 : BaseGlyph = 1,
333 : LigatureGlyph = 2,
334 : MarkGlyph = 3,
335 : ComponentGlyph = 4
336 : };
337 :
338 0 : inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
339 0 : inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
340 0 : { return (this+glyphClassDef).get_class (glyph); }
341 :
342 : inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
343 0 : inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
344 0 : { return (this+markAttachClassDef).get_class (glyph); }
345 :
346 : inline bool has_attach_points (void) const { return attachList != 0; }
347 0 : inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
348 : unsigned int start_offset,
349 : unsigned int *point_count /* IN/OUT */,
350 : unsigned int *point_array /* OUT */) const
351 0 : { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
352 :
353 : inline bool has_lig_carets (void) const { return ligCaretList != 0; }
354 0 : inline unsigned int get_lig_carets (hb_font_t *font,
355 : hb_direction_t direction,
356 : hb_codepoint_t glyph_id,
357 : unsigned int start_offset,
358 : unsigned int *caret_count /* IN/OUT */,
359 : hb_position_t *caret_array /* OUT */) const
360 0 : { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
361 :
362 : inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002 && markGlyphSetsDef[0] != 0; }
363 0 : inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
364 0 : { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); }
365 :
366 0 : inline bool sanitize (hb_sanitize_context_t *c) {
367 0 : TRACE_SANITIZE ();
368 0 : return version.sanitize (c) && likely (version.major == 1)
369 0 : && glyphClassDef.sanitize (c, this)
370 0 : && attachList.sanitize (c, this)
371 0 : && ligCaretList.sanitize (c, this)
372 0 : && markAttachClassDef.sanitize (c, this)
373 0 : && (version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this));
374 : }
375 :
376 :
377 : /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
378 : * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
379 : * Not to be confused with lookup_props which is very similar. */
380 0 : inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
381 : {
382 0 : unsigned int klass = get_glyph_class (glyph);
383 :
384 0 : switch (klass) {
385 : default:
386 0 : case UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
387 0 : case BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
388 0 : case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
389 0 : case ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT;
390 : case MarkGlyph:
391 0 : klass = get_mark_attachment_type (glyph);
392 0 : return HB_OT_LAYOUT_GLYPH_CLASS_MARK | (klass << 8);
393 : }
394 : }
395 :
396 :
397 : private:
398 : FixedVersion version; /* Version of the GDEF table--currently
399 : * 0x00010002 */
400 : OffsetTo<ClassDef>
401 : glyphClassDef; /* Offset to class definition table
402 : * for glyph type--from beginning of
403 : * GDEF header (may be Null) */
404 : OffsetTo<AttachList>
405 : attachList; /* Offset to list of glyphs with
406 : * attachment points--from beginning
407 : * of GDEF header (may be Null) */
408 : OffsetTo<LigCaretList>
409 : ligCaretList; /* Offset to list of positioning points
410 : * for ligature carets--from beginning
411 : * of GDEF header (may be Null) */
412 : OffsetTo<ClassDef>
413 : markAttachClassDef; /* Offset to class definition table for
414 : * mark attachment type--from beginning
415 : * of GDEF header (may be Null) */
416 : OffsetTo<MarkGlyphSets>
417 : markGlyphSetsDef[VAR]; /* Offset to the table of mark set
418 : * definitions--from beginning of GDEF
419 : * header (may be NULL). Introduced
420 : * in version 00010002. */
421 : public:
422 : DEFINE_SIZE_ARRAY (12, markGlyphSetsDef);
423 : };
424 :
425 :
426 :
427 : #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */
|