hb-ot-layout-gdef-table.hh revision ae9877dea6a1aed3566d9b87a75ede84259deaca
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 42typedef ArrayOf<USHORT> AttachPoint; /* Array of contour point indices--in 43 * increasing numerical order */ 44 45struct 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 coverage.sanitize (c, this) 75 && 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 93struct CaretValueFormat1 94{ 95 friend struct CaretValue; 96 97 private: 98 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 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); 101 } 102 103 inline bool sanitize (hb_sanitize_context_t *c) { 104 TRACE_SANITIZE (); 105 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 115struct CaretValueFormat2 116{ 117 friend struct CaretValue; 118 119 private: 120 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 if (hb_font_get_glyph_contour_point_for_origin (font, glyph_id, caretValuePoint, direction, &x, &y)) 124 return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; 125 else 126 return 0; 127 } 128 129 inline bool sanitize (hb_sanitize_context_t *c) { 130 TRACE_SANITIZE (); 131 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 141struct CaretValueFormat3 142{ 143 friend struct CaretValue; 144 145 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 font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) : 149 font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font); 150 } 151 152 inline bool sanitize (hb_sanitize_context_t *c) { 153 TRACE_SANITIZE (); 154 return c->check_struct (this) 155 && 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 169struct CaretValue 170{ 171 inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const 172 { 173 switch (u.format) { 174 case 1: return u.format1.get_caret_value (font, direction, glyph_id); 175 case 2: return u.format2.get_caret_value (font, direction, glyph_id); 176 case 3: return u.format3.get_caret_value (font, direction, glyph_id); 177 default:return 0; 178 } 179 } 180 181 inline bool sanitize (hb_sanitize_context_t *c) { 182 TRACE_SANITIZE (); 183 if (!u.format.sanitize (c)) return false; 184 switch (u.format) { 185 case 1: return u.format1.sanitize (c); 186 case 2: return u.format2.sanitize (c); 187 case 3: return u.format3.sanitize (c); 188 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 203struct LigGlyph 204{ 205 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 if (caret_count) { 213 const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count); 214 unsigned int count = *caret_count; 215 for (unsigned int i = 0; i < count; i++) 216 caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id); 217 } 218 219 return carets.len; 220 } 221 222 inline bool sanitize (hb_sanitize_context_t *c) { 223 TRACE_SANITIZE (); 224 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 236struct LigCaretList 237{ 238 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 unsigned int index = (this+coverage) (glyph_id); 246 if (index == NOT_COVERED) 247 { 248 if (caret_count) 249 *caret_count = 0; 250 return 0; 251 } 252 const LigGlyph &lig_glyph = this+ligGlyph[index]; 253 return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); 254 } 255 256 inline bool sanitize (hb_sanitize_context_t *c) { 257 TRACE_SANITIZE (); 258 return coverage.sanitize (c, this) 259 && 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 274struct MarkGlyphSetsFormat1 275{ 276 inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 277 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } 278 279 inline bool sanitize (hb_sanitize_context_t *c) { 280 TRACE_SANITIZE (); 281 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 293struct MarkGlyphSets 294{ 295 inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 296 { 297 switch (u.format) { 298 case 1: return u.format1.covers (set_index, glyph_id); 299 default:return false; 300 } 301 } 302 303 inline bool sanitize (hb_sanitize_context_t *c) { 304 TRACE_SANITIZE (); 305 if (!u.format.sanitize (c)) return false; 306 switch (u.format) { 307 case 1: return u.format1.sanitize (c); 308 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 326struct 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 inline bool has_glyph_classes (void) const { return glyphClassDef != 0; } 339 inline unsigned int get_glyph_class (hb_codepoint_t glyph) const 340 { return (this+glyphClassDef).get_class (glyph); } 341 342 inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; } 343 inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const 344 { return (this+markAttachClassDef).get_class (glyph); } 345 346 inline bool has_attach_points (void) const { return attachList != 0; } 347 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 { 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 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 { 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 inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 364 { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } 365 366 inline bool sanitize (hb_sanitize_context_t *c) { 367 TRACE_SANITIZE (); 368 return version.sanitize (c) && likely (version.major == 1) 369 && glyphClassDef.sanitize (c, this) 370 && attachList.sanitize (c, this) 371 && ligCaretList.sanitize (c, this) 372 && markAttachClassDef.sanitize (c, this) 373 && (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 inline unsigned int get_glyph_props (hb_codepoint_t glyph) const 381 { 382 unsigned int klass = get_glyph_class (glyph); 383 384 switch (klass) { 385 default: 386 case UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; 387 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; 388 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; 389 case ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT; 390 case MarkGlyph: 391 klass = get_mark_attachment_type (glyph); 392 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 */ 428