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 { 49 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 74 inline bool sanitize (hb_sanitize_context_t *c) { 75 TRACE_SANITIZE (this); 76 return TRACE_RETURN (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); 77 } 78 79 protected: 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 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const 100 { 101 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); 102 } 103 104 inline bool sanitize (hb_sanitize_context_t *c) { 105 TRACE_SANITIZE (this); 106 return TRACE_RETURN (c->check_struct (this)); 107 } 108 109 protected: 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 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const 122 { 123 hb_position_t x, y; 124 if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &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 (this); 132 return TRACE_RETURN (c->check_struct (this)); 133 } 134 135 protected: 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 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const 147 { 148 return HB_DIRECTION_IS_HORIZONTAL (direction) ? 149 font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) : 150 font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font); 151 } 152 153 inline bool sanitize (hb_sanitize_context_t *c) { 154 TRACE_SANITIZE (this); 155 return TRACE_RETURN (c->check_struct (this) && deviceTable.sanitize (c, this)); 156 } 157 158 protected: 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 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 (this); 183 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 184 switch (u.format) { 185 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 186 case 2: return TRACE_RETURN (u.format2.sanitize (c)); 187 case 3: return TRACE_RETURN (u.format3.sanitize (c)); 188 default:return TRACE_RETURN (true); 189 } 190 } 191 192 protected: 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 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 (this); 224 return TRACE_RETURN (carets.sanitize (c, this)); 225 } 226 227 protected: 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 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).get_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 (this); 258 return TRACE_RETURN (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); 259 } 260 261 protected: 262 OffsetTo<Coverage> 263 coverage; /* Offset to Coverage table--from 264 * beginning of LigCaretList table */ 265 OffsetArrayOf<LigGlyph> 266 ligGlyph; /* Array of LigGlyph tables 267 * in Coverage Index order */ 268 public: 269 DEFINE_SIZE_ARRAY (4, ligGlyph); 270 }; 271 272 273 struct MarkGlyphSetsFormat1 274 { 275 inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 276 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } 277 278 inline bool sanitize (hb_sanitize_context_t *c) { 279 TRACE_SANITIZE (this); 280 return TRACE_RETURN (coverage.sanitize (c, this)); 281 } 282 283 protected: 284 USHORT format; /* Format identifier--format = 1 */ 285 LongOffsetArrayOf<Coverage> 286 coverage; /* Array of long offsets to mark set 287 * coverage tables */ 288 public: 289 DEFINE_SIZE_ARRAY (4, coverage); 290 }; 291 292 struct MarkGlyphSets 293 { 294 inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 295 { 296 switch (u.format) { 297 case 1: return u.format1.covers (set_index, glyph_id); 298 default:return false; 299 } 300 } 301 302 inline bool sanitize (hb_sanitize_context_t *c) { 303 TRACE_SANITIZE (this); 304 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 305 switch (u.format) { 306 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 307 default:return TRACE_RETURN (true); 308 } 309 } 310 311 protected: 312 union { 313 USHORT format; /* Format identifier */ 314 MarkGlyphSetsFormat1 format1; 315 } u; 316 public: 317 DEFINE_SIZE_UNION (2, format); 318 }; 319 320 321 /* 322 * GDEF -- The Glyph Definition Table 323 */ 324 325 struct GDEF 326 { 327 static const hb_tag_t Tag = HB_OT_TAG_GDEF; 328 329 enum GlyphClasses { 330 UnclassifiedGlyph = 0, 331 BaseGlyph = 1, 332 LigatureGlyph = 2, 333 MarkGlyph = 3, 334 ComponentGlyph = 4 335 }; 336 337 inline bool has_glyph_classes (void) const { return glyphClassDef != 0; } 338 inline unsigned int get_glyph_class (hb_codepoint_t glyph) const 339 { return (this+glyphClassDef).get_class (glyph); } 340 inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const 341 { (this+glyphClassDef).add_class (glyphs, klass); } 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 */) const 352 { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); } 353 354 inline bool has_lig_carets (void) const { return ligCaretList != 0; } 355 inline unsigned int get_lig_carets (hb_font_t *font, 356 hb_direction_t direction, 357 hb_codepoint_t glyph_id, 358 unsigned int start_offset, 359 unsigned int *caret_count /* IN/OUT */, 360 hb_position_t *caret_array /* OUT */) const 361 { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); } 362 363 inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002 && markGlyphSetsDef[0] != 0; } 364 inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 365 { return version.to_int () >= 0x00010002 && (this+markGlyphSetsDef[0]).covers (set_index, glyph_id); } 366 367 inline bool sanitize (hb_sanitize_context_t *c) { 368 TRACE_SANITIZE (this); 369 return TRACE_RETURN (version.sanitize (c) && 370 likely (version.major == 1) && 371 glyphClassDef.sanitize (c, this) && 372 attachList.sanitize (c, this) && 373 ligCaretList.sanitize (c, this) && 374 markAttachClassDef.sanitize (c, this) && 375 (version.to_int () < 0x00010002 || markGlyphSetsDef[0].sanitize (c, this))); 376 } 377 378 379 /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing 380 * glyph class and other bits, and high 8-bit gthe mark attachment type (if any). 381 * Not to be confused with lookup_props which is very similar. */ 382 inline unsigned int get_glyph_props (hb_codepoint_t glyph) const 383 { 384 unsigned int klass = get_glyph_class (glyph); 385 386 switch (klass) { 387 default: 388 case UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_UNCLASSIFIED; 389 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; 390 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; 391 case ComponentGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_COMPONENT; 392 case MarkGlyph: 393 klass = get_mark_attachment_type (glyph); 394 return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8); 395 } 396 } 397 398 399 protected: 400 FixedVersion version; /* Version of the GDEF table--currently 401 * 0x00010002 */ 402 OffsetTo<ClassDef> 403 glyphClassDef; /* Offset to class definition table 404 * for glyph type--from beginning of 405 * GDEF header (may be Null) */ 406 OffsetTo<AttachList> 407 attachList; /* Offset to list of glyphs with 408 * attachment points--from beginning 409 * of GDEF header (may be Null) */ 410 OffsetTo<LigCaretList> 411 ligCaretList; /* Offset to list of positioning points 412 * for ligature carets--from beginning 413 * of GDEF header (may be Null) */ 414 OffsetTo<ClassDef> 415 markAttachClassDef; /* Offset to class definition table for 416 * mark attachment type--from beginning 417 * of GDEF header (may be Null) */ 418 OffsetTo<MarkGlyphSets> 419 markGlyphSetsDef[VAR]; /* Offset to the table of mark set 420 * definitions--from beginning of GDEF 421 * header (may be NULL). Introduced 422 * in version 00010002. */ 423 public: 424 DEFINE_SIZE_ARRAY (12, markGlyphSetsDef); 425 }; 426 427 428 } /* namespace OT */ 429 430 431 #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */ 432