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