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