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.hh" 33 34 #include "hb-font.hh" 35 36 37 namespace OT { 38 39 40 /* 41 * Attachment List Table 42 */ 43 44 /* Array of contour point indices--in increasing numerical order */ 45 struct AttachPoint : Array16Of<HBUINT16> 46 { subsetOT::AttachPoint47 bool subset (hb_subset_context_t *c) const 48 { 49 TRACE_SUBSET (this); 50 auto *out = c->serializer->start_embed (*this); 51 if (unlikely (!out)) return_trace (false); 52 53 return_trace (out->serialize (c->serializer, + iter ())); 54 } 55 }; 56 57 struct AttachList 58 { get_attach_pointsOT::AttachList59 unsigned int get_attach_points (hb_codepoint_t glyph_id, 60 unsigned int start_offset, 61 unsigned int *point_count /* IN/OUT */, 62 unsigned int *point_array /* OUT */) const 63 { 64 unsigned int index = (this+coverage).get_coverage (glyph_id); 65 if (index == NOT_COVERED) 66 { 67 if (point_count) 68 *point_count = 0; 69 return 0; 70 } 71 72 const AttachPoint &points = this+attachPoint[index]; 73 74 if (point_count) 75 { 76 + points.sub_array (start_offset, point_count) 77 | hb_sink (hb_array (point_array, *point_count)) 78 ; 79 } 80 81 return points.len; 82 } 83 subsetOT::AttachList84 bool subset (hb_subset_context_t *c) const 85 { 86 TRACE_SUBSET (this); 87 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 88 const hb_map_t &glyph_map = *c->plan->glyph_map; 89 90 auto *out = c->serializer->start_embed (*this); 91 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 92 93 hb_sorted_vector_t<hb_codepoint_t> new_coverage; 94 + hb_zip (this+coverage, attachPoint) 95 | hb_filter (glyphset, hb_first) 96 | hb_filter (subset_offset_array (c, out->attachPoint, this), hb_second) 97 | hb_map (hb_first) 98 | hb_map (glyph_map) 99 | hb_sink (new_coverage) 100 ; 101 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); 102 return_trace (bool (new_coverage)); 103 } 104 sanitizeOT::AttachList105 bool sanitize (hb_sanitize_context_t *c) const 106 { 107 TRACE_SANITIZE (this); 108 return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); 109 } 110 111 protected: 112 Offset16To<Coverage> 113 coverage; /* Offset to Coverage table -- from 114 * beginning of AttachList table */ 115 Array16OfOffset16To<AttachPoint> 116 attachPoint; /* Array of AttachPoint tables 117 * in Coverage Index order */ 118 public: 119 DEFINE_SIZE_ARRAY (4, attachPoint); 120 }; 121 122 /* 123 * Ligature Caret Table 124 */ 125 126 struct CaretValueFormat1 127 { 128 friend struct CaretValue; subsetOT::CaretValueFormat1129 bool subset (hb_subset_context_t *c) const 130 { 131 TRACE_SUBSET (this); 132 auto *out = c->serializer->embed (this); 133 if (unlikely (!out)) return_trace (false); 134 return_trace (true); 135 } 136 137 private: get_caret_valueOT::CaretValueFormat1138 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const 139 { 140 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); 141 } 142 sanitizeOT::CaretValueFormat1143 bool sanitize (hb_sanitize_context_t *c) const 144 { 145 TRACE_SANITIZE (this); 146 return_trace (c->check_struct (this)); 147 } 148 149 protected: 150 HBUINT16 caretValueFormat; /* Format identifier--format = 1 */ 151 FWORD coordinate; /* X or Y value, in design units */ 152 public: 153 DEFINE_SIZE_STATIC (4); 154 }; 155 156 struct CaretValueFormat2 157 { 158 friend struct CaretValue; subsetOT::CaretValueFormat2159 bool subset (hb_subset_context_t *c) const 160 { 161 TRACE_SUBSET (this); 162 auto *out = c->serializer->embed (this); 163 if (unlikely (!out)) return_trace (false); 164 return_trace (true); 165 } 166 167 private: get_caret_valueOT::CaretValueFormat2168 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const 169 { 170 hb_position_t x, y; 171 font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y); 172 return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; 173 } 174 sanitizeOT::CaretValueFormat2175 bool sanitize (hb_sanitize_context_t *c) const 176 { 177 TRACE_SANITIZE (this); 178 return_trace (c->check_struct (this)); 179 } 180 181 protected: 182 HBUINT16 caretValueFormat; /* Format identifier--format = 2 */ 183 HBUINT16 caretValuePoint; /* Contour point index on glyph */ 184 public: 185 DEFINE_SIZE_STATIC (4); 186 }; 187 188 struct CaretValueFormat3 189 { 190 friend struct CaretValue; 191 get_caret_valueOT::CaretValueFormat3192 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, 193 const VariationStore &var_store) const 194 { 195 return HB_DIRECTION_IS_HORIZONTAL (direction) ? 196 font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : 197 font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store); 198 } 199 subsetOT::CaretValueFormat3200 bool subset (hb_subset_context_t *c) const 201 { 202 TRACE_SUBSET (this); 203 auto *out = c->serializer->embed (this); 204 if (unlikely (!out)) return_trace (false); 205 206 return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out), 207 hb_serialize_context_t::Head, c->plan->layout_variation_idx_map)); 208 } 209 collect_variation_indicesOT::CaretValueFormat3210 void collect_variation_indices (hb_set_t *layout_variation_indices) const 211 { (this+deviceTable).collect_variation_indices (layout_variation_indices); } 212 sanitizeOT::CaretValueFormat3213 bool sanitize (hb_sanitize_context_t *c) const 214 { 215 TRACE_SANITIZE (this); 216 return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); 217 } 218 219 protected: 220 HBUINT16 caretValueFormat; /* Format identifier--format = 3 */ 221 FWORD coordinate; /* X or Y value, in design units */ 222 Offset16To<Device> 223 deviceTable; /* Offset to Device table for X or Y 224 * value--from beginning of CaretValue 225 * table */ 226 public: 227 DEFINE_SIZE_STATIC (6); 228 }; 229 230 struct CaretValue 231 { get_caret_valueOT::CaretValue232 hb_position_t get_caret_value (hb_font_t *font, 233 hb_direction_t direction, 234 hb_codepoint_t glyph_id, 235 const VariationStore &var_store) const 236 { 237 switch (u.format) { 238 case 1: return u.format1.get_caret_value (font, direction); 239 case 2: return u.format2.get_caret_value (font, direction, glyph_id); 240 case 3: return u.format3.get_caret_value (font, direction, var_store); 241 default:return 0; 242 } 243 } 244 245 template <typename context_t, typename ...Ts> dispatchOT::CaretValue246 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const 247 { 248 TRACE_DISPATCH (this, u.format); 249 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); 250 switch (u.format) { 251 case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); 252 case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); 253 case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); 254 default:return_trace (c->default_return_value ()); 255 } 256 } 257 collect_variation_indicesOT::CaretValue258 void collect_variation_indices (hb_set_t *layout_variation_indices) const 259 { 260 switch (u.format) { 261 case 1: 262 case 2: 263 return; 264 case 3: 265 u.format3.collect_variation_indices (layout_variation_indices); 266 return; 267 default: return; 268 } 269 } 270 sanitizeOT::CaretValue271 bool sanitize (hb_sanitize_context_t *c) const 272 { 273 TRACE_SANITIZE (this); 274 if (!u.format.sanitize (c)) return_trace (false); 275 switch (u.format) { 276 case 1: return_trace (u.format1.sanitize (c)); 277 case 2: return_trace (u.format2.sanitize (c)); 278 case 3: return_trace (u.format3.sanitize (c)); 279 default:return_trace (true); 280 } 281 } 282 283 protected: 284 union { 285 HBUINT16 format; /* Format identifier */ 286 CaretValueFormat1 format1; 287 CaretValueFormat2 format2; 288 CaretValueFormat3 format3; 289 } u; 290 public: 291 DEFINE_SIZE_UNION (2, format); 292 }; 293 294 struct LigGlyph 295 { get_lig_caretsOT::LigGlyph296 unsigned get_lig_carets (hb_font_t *font, 297 hb_direction_t direction, 298 hb_codepoint_t glyph_id, 299 const VariationStore &var_store, 300 unsigned start_offset, 301 unsigned *caret_count /* IN/OUT */, 302 hb_position_t *caret_array /* OUT */) const 303 { 304 if (caret_count) 305 { 306 + carets.sub_array (start_offset, caret_count) 307 | hb_map (hb_add (this)) 308 | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); }) 309 | hb_sink (hb_array (caret_array, *caret_count)) 310 ; 311 } 312 313 return carets.len; 314 } 315 subsetOT::LigGlyph316 bool subset (hb_subset_context_t *c) const 317 { 318 TRACE_SUBSET (this); 319 auto *out = c->serializer->start_embed (*this); 320 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 321 322 + hb_iter (carets) 323 | hb_apply (subset_offset_array (c, out->carets, this)) 324 ; 325 326 return_trace (bool (out->carets)); 327 } 328 collect_variation_indicesOT::LigGlyph329 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 330 { 331 for (const Offset16To<CaretValue>& offset : carets.iter ()) 332 (this+offset).collect_variation_indices (c->layout_variation_indices); 333 } 334 sanitizeOT::LigGlyph335 bool sanitize (hb_sanitize_context_t *c) const 336 { 337 TRACE_SANITIZE (this); 338 return_trace (carets.sanitize (c, this)); 339 } 340 341 protected: 342 Array16OfOffset16To<CaretValue> 343 carets; /* Offset array of CaretValue tables 344 * --from beginning of LigGlyph table 345 * --in increasing coordinate order */ 346 public: 347 DEFINE_SIZE_ARRAY (2, carets); 348 }; 349 350 struct LigCaretList 351 { get_lig_caretsOT::LigCaretList352 unsigned int get_lig_carets (hb_font_t *font, 353 hb_direction_t direction, 354 hb_codepoint_t glyph_id, 355 const VariationStore &var_store, 356 unsigned int start_offset, 357 unsigned int *caret_count /* IN/OUT */, 358 hb_position_t *caret_array /* OUT */) const 359 { 360 unsigned int index = (this+coverage).get_coverage (glyph_id); 361 if (index == NOT_COVERED) 362 { 363 if (caret_count) 364 *caret_count = 0; 365 return 0; 366 } 367 const LigGlyph &lig_glyph = this+ligGlyph[index]; 368 return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); 369 } 370 subsetOT::LigCaretList371 bool subset (hb_subset_context_t *c) const 372 { 373 TRACE_SUBSET (this); 374 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 375 const hb_map_t &glyph_map = *c->plan->glyph_map; 376 377 auto *out = c->serializer->start_embed (*this); 378 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 379 380 hb_sorted_vector_t<hb_codepoint_t> new_coverage; 381 + hb_zip (this+coverage, ligGlyph) 382 | hb_filter (glyphset, hb_first) 383 | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second) 384 | hb_map (hb_first) 385 | hb_map (glyph_map) 386 | hb_sink (new_coverage) 387 ; 388 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); 389 return_trace (bool (new_coverage)); 390 } 391 collect_variation_indicesOT::LigCaretList392 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 393 { 394 + hb_zip (this+coverage, ligGlyph) 395 | hb_filter (c->glyph_set, hb_first) 396 | hb_map (hb_second) 397 | hb_map (hb_add (this)) 398 | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); }) 399 ; 400 } 401 sanitizeOT::LigCaretList402 bool sanitize (hb_sanitize_context_t *c) const 403 { 404 TRACE_SANITIZE (this); 405 return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); 406 } 407 408 protected: 409 Offset16To<Coverage> 410 coverage; /* Offset to Coverage table--from 411 * beginning of LigCaretList table */ 412 Array16OfOffset16To<LigGlyph> 413 ligGlyph; /* Array of LigGlyph tables 414 * in Coverage Index order */ 415 public: 416 DEFINE_SIZE_ARRAY (4, ligGlyph); 417 }; 418 419 420 struct MarkGlyphSetsFormat1 421 { coversOT::MarkGlyphSetsFormat1422 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 423 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } 424 subsetOT::MarkGlyphSetsFormat1425 bool subset (hb_subset_context_t *c) const 426 { 427 TRACE_SUBSET (this); 428 auto *out = c->serializer->start_embed (*this); 429 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 430 out->format = format; 431 432 bool ret = true; 433 for (const Offset32To<Coverage>& offset : coverage.iter ()) 434 { 435 auto *o = out->coverage.serialize_append (c->serializer); 436 if (unlikely (!o)) 437 { 438 ret = false; 439 break; 440 } 441 442 //not using o->serialize_subset (c, offset, this, out) here because 443 //OTS doesn't allow null offset. 444 //See issue: https://github.com/khaledhosny/ots/issues/172 445 c->serializer->push (); 446 c->dispatch (this+offset); 447 c->serializer->add_link (*o, c->serializer->pop_pack ()); 448 } 449 450 return_trace (ret && out->coverage.len); 451 } 452 sanitizeOT::MarkGlyphSetsFormat1453 bool sanitize (hb_sanitize_context_t *c) const 454 { 455 TRACE_SANITIZE (this); 456 return_trace (coverage.sanitize (c, this)); 457 } 458 459 protected: 460 HBUINT16 format; /* Format identifier--format = 1 */ 461 Array16Of<Offset32To<Coverage>> 462 coverage; /* Array of long offsets to mark set 463 * coverage tables */ 464 public: 465 DEFINE_SIZE_ARRAY (4, coverage); 466 }; 467 468 struct MarkGlyphSets 469 { coversOT::MarkGlyphSets470 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 471 { 472 switch (u.format) { 473 case 1: return u.format1.covers (set_index, glyph_id); 474 default:return false; 475 } 476 } 477 subsetOT::MarkGlyphSets478 bool subset (hb_subset_context_t *c) const 479 { 480 TRACE_SUBSET (this); 481 switch (u.format) { 482 case 1: return_trace (u.format1.subset (c)); 483 default:return_trace (false); 484 } 485 } 486 sanitizeOT::MarkGlyphSets487 bool sanitize (hb_sanitize_context_t *c) const 488 { 489 TRACE_SANITIZE (this); 490 if (!u.format.sanitize (c)) return_trace (false); 491 switch (u.format) { 492 case 1: return_trace (u.format1.sanitize (c)); 493 default:return_trace (true); 494 } 495 } 496 497 protected: 498 union { 499 HBUINT16 format; /* Format identifier */ 500 MarkGlyphSetsFormat1 format1; 501 } u; 502 public: 503 DEFINE_SIZE_UNION (2, format); 504 }; 505 506 507 /* 508 * GDEF -- Glyph Definition 509 * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef 510 */ 511 512 513 struct GDEF 514 { 515 static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF; 516 517 enum GlyphClasses { 518 UnclassifiedGlyph = 0, 519 BaseGlyph = 1, 520 LigatureGlyph = 2, 521 MarkGlyph = 3, 522 ComponentGlyph = 4 523 }; 524 has_dataOT::GDEF525 bool has_data () const { return version.to_int (); } has_glyph_classesOT::GDEF526 bool has_glyph_classes () const { return glyphClassDef != 0; } get_glyph_classOT::GDEF527 unsigned int get_glyph_class (hb_codepoint_t glyph) const 528 { return (this+glyphClassDef).get_class (glyph); } get_glyphs_in_classOT::GDEF529 void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const 530 { (this+glyphClassDef).collect_class (glyphs, klass); } 531 has_mark_attachment_typesOT::GDEF532 bool has_mark_attachment_types () const { return markAttachClassDef != 0; } get_mark_attachment_typeOT::GDEF533 unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const 534 { return (this+markAttachClassDef).get_class (glyph); } 535 has_attach_pointsOT::GDEF536 bool has_attach_points () const { return attachList != 0; } get_attach_pointsOT::GDEF537 unsigned int get_attach_points (hb_codepoint_t glyph_id, 538 unsigned int start_offset, 539 unsigned int *point_count /* IN/OUT */, 540 unsigned int *point_array /* OUT */) const 541 { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); } 542 has_lig_caretsOT::GDEF543 bool has_lig_carets () const { return ligCaretList != 0; } get_lig_caretsOT::GDEF544 unsigned int get_lig_carets (hb_font_t *font, 545 hb_direction_t direction, 546 hb_codepoint_t glyph_id, 547 unsigned int start_offset, 548 unsigned int *caret_count /* IN/OUT */, 549 hb_position_t *caret_array /* OUT */) const 550 { return (this+ligCaretList).get_lig_carets (font, 551 direction, glyph_id, get_var_store(), 552 start_offset, caret_count, caret_array); } 553 has_mark_setsOT::GDEF554 bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; } mark_set_coversOT::GDEF555 bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 556 { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); } 557 has_var_storeOT::GDEF558 bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; } get_var_storeOT::GDEF559 const VariationStore &get_var_store () const 560 { return version.to_int () >= 0x00010003u ? this+varStore : Null (VariationStore); } 561 562 /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing 563 * glyph class and other bits, and high 8-bit the mark attachment type (if any). 564 * Not to be confused with lookup_props which is very similar. */ get_glyph_propsOT::GDEF565 unsigned int get_glyph_props (hb_codepoint_t glyph) const 566 { 567 unsigned int klass = get_glyph_class (glyph); 568 569 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), ""); 570 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), ""); 571 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), ""); 572 573 switch (klass) { 574 default: return 0; 575 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; 576 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; 577 case MarkGlyph: 578 klass = get_mark_attachment_type (glyph); 579 return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8); 580 } 581 } 582 583 HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, 584 hb_face_t *face) const; 585 586 struct accelerator_t 587 { accelerator_tOT::GDEF::accelerator_t588 accelerator_t (hb_face_t *face) 589 { 590 table = hb_sanitize_context_t ().reference_table<GDEF> (face); 591 if (unlikely (table->is_blocklisted (table.get_blob (), face))) 592 { 593 hb_blob_destroy (table.get_blob ()); 594 table = hb_blob_get_empty (); 595 } 596 } ~accelerator_tOT::GDEF::accelerator_t597 ~accelerator_t () { table.destroy (); } 598 599 hb_blob_ptr_t<GDEF> table; 600 }; 601 get_sizeOT::GDEF602 unsigned int get_size () const 603 { 604 return min_size + 605 (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + 606 (version.to_int () >= 0x00010003u ? varStore.static_size : 0); 607 } 608 collect_variation_indicesOT::GDEF609 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 610 { (this+ligCaretList).collect_variation_indices (c); } 611 remap_layout_variation_indicesOT::GDEF612 void remap_layout_variation_indices (const hb_set_t *layout_variation_indices, 613 hb_map_t *layout_variation_idx_map /* OUT */) const 614 { 615 if (version.to_int () < 0x00010003u || !varStore) return; 616 if (layout_variation_indices->is_empty ()) return; 617 618 unsigned new_major = 0, new_minor = 0; 619 unsigned last_major = (layout_variation_indices->get_min ()) >> 16; 620 for (unsigned idx : layout_variation_indices->iter ()) 621 { 622 uint16_t major = idx >> 16; 623 if (major >= (this+varStore).get_sub_table_count ()) break; 624 if (major != last_major) 625 { 626 new_minor = 0; 627 ++new_major; 628 } 629 630 unsigned new_idx = (new_major << 16) + new_minor; 631 layout_variation_idx_map->set (idx, new_idx); 632 ++new_minor; 633 last_major = major; 634 } 635 } 636 subsetOT::GDEF637 bool subset (hb_subset_context_t *c) const 638 { 639 TRACE_SUBSET (this); 640 auto *out = c->serializer->embed (*this); 641 if (unlikely (!out)) return_trace (false); 642 643 bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); 644 bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); 645 bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); 646 bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); 647 648 bool subset_markglyphsetsdef = true; 649 if (version.to_int () >= 0x00010002u) 650 { 651 subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); 652 if (!subset_markglyphsetsdef && 653 version.to_int () == 0x00010002u) 654 out->version.minor = 0; 655 } 656 657 bool subset_varstore = true; 658 if (version.to_int () >= 0x00010003u) 659 { 660 subset_varstore = out->varStore.serialize_subset (c, varStore, this); 661 if (!subset_varstore && version.to_int () == 0x00010003u) 662 out->version.minor = 2; 663 } 664 665 return_trace (subset_glyphclassdef || subset_attachlist || 666 subset_ligcaretlist || subset_markattachclassdef || 667 (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || 668 (out->version.to_int () >= 0x00010003u && subset_varstore)); 669 } 670 sanitizeOT::GDEF671 bool sanitize (hb_sanitize_context_t *c) const 672 { 673 TRACE_SANITIZE (this); 674 return_trace (version.sanitize (c) && 675 likely (version.major == 1) && 676 glyphClassDef.sanitize (c, this) && 677 attachList.sanitize (c, this) && 678 ligCaretList.sanitize (c, this) && 679 markAttachClassDef.sanitize (c, this) && 680 (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && 681 (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); 682 } 683 684 protected: 685 FixedVersion<>version; /* Version of the GDEF table--currently 686 * 0x00010003u */ 687 Offset16To<ClassDef> 688 glyphClassDef; /* Offset to class definition table 689 * for glyph type--from beginning of 690 * GDEF header (may be Null) */ 691 Offset16To<AttachList> 692 attachList; /* Offset to list of glyphs with 693 * attachment points--from beginning 694 * of GDEF header (may be Null) */ 695 Offset16To<LigCaretList> 696 ligCaretList; /* Offset to list of positioning points 697 * for ligature carets--from beginning 698 * of GDEF header (may be Null) */ 699 Offset16To<ClassDef> 700 markAttachClassDef; /* Offset to class definition table for 701 * mark attachment type--from beginning 702 * of GDEF header (may be Null) */ 703 Offset16To<MarkGlyphSets> 704 markGlyphSetsDef; /* Offset to the table of mark set 705 * definitions--from beginning of GDEF 706 * header (may be NULL). Introduced 707 * in version 0x00010002. */ 708 Offset32To<VariationStore> 709 varStore; /* Offset to the table of Item Variation 710 * Store--from beginning of GDEF 711 * header (may be NULL). Introduced 712 * in version 0x00010003. */ 713 public: 714 DEFINE_SIZE_MIN (12); 715 }; 716 717 struct GDEF_accelerator_t : GDEF::accelerator_t { GDEF_accelerator_tOT::GDEF_accelerator_t718 GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {} 719 }; 720 721 } /* namespace OT */ 722 723 724 #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */ 725