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 OT_LAYOUT_GDEF_GDEF_HH 30 #define OT_LAYOUT_GDEF_GDEF_HH 31 32 #include "../../../hb-ot-var-common.hh" 33 34 #include "../../../hb-font.hh" 35 #include "../../../hb-cache.hh" 36 37 38 namespace OT { 39 40 41 /* 42 * Attachment List Table 43 */ 44 45 /* Array of contour point indices--in increasing numerical order */ 46 struct AttachPoint : Array16Of<HBUINT16> 47 { subsetOT::AttachPoint48 bool subset (hb_subset_context_t *c) const 49 { 50 TRACE_SUBSET (this); 51 auto *out = c->serializer->start_embed (*this); 52 return_trace (out->serialize (c->serializer, + iter ())); 53 } 54 }; 55 56 struct AttachList 57 { get_attach_pointsOT::AttachList58 unsigned int get_attach_points (hb_codepoint_t glyph_id, 59 unsigned int start_offset, 60 unsigned int *point_count /* IN/OUT */, 61 unsigned int *point_array /* OUT */) const 62 { 63 unsigned int index = (this+coverage).get_coverage (glyph_id); 64 if (index == NOT_COVERED) 65 { 66 if (point_count) 67 *point_count = 0; 68 return 0; 69 } 70 71 const AttachPoint &points = this+attachPoint[index]; 72 73 if (point_count) 74 { 75 + points.as_array ().sub_array (start_offset, point_count) 76 | hb_sink (hb_array (point_array, *point_count)) 77 ; 78 } 79 80 return points.len; 81 } 82 subsetOT::AttachList83 bool subset (hb_subset_context_t *c) const 84 { 85 TRACE_SUBSET (this); 86 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 87 const hb_map_t &glyph_map = *c->plan->glyph_map; 88 89 auto *out = c->serializer->start_embed (*this); 90 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 91 92 hb_sorted_vector_t<hb_codepoint_t> new_coverage; 93 + hb_zip (this+coverage, attachPoint) 94 | hb_filter (glyphset, hb_first) 95 | hb_filter (subset_offset_array (c, out->attachPoint, this), hb_second) 96 | hb_map (hb_first) 97 | hb_map (glyph_map) 98 | hb_sink (new_coverage) 99 ; 100 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); 101 return_trace (bool (new_coverage)); 102 } 103 sanitizeOT::AttachList104 bool sanitize (hb_sanitize_context_t *c) const 105 { 106 TRACE_SANITIZE (this); 107 return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); 108 } 109 110 protected: 111 Offset16To<Coverage> 112 coverage; /* Offset to Coverage table -- from 113 * beginning of AttachList table */ 114 Array16OfOffset16To<AttachPoint> 115 attachPoint; /* Array of AttachPoint tables 116 * in Coverage Index order */ 117 public: 118 DEFINE_SIZE_ARRAY (4, attachPoint); 119 }; 120 121 /* 122 * Ligature Caret Table 123 */ 124 125 struct CaretValueFormat1 126 { 127 friend struct CaretValue; subsetOT::CaretValueFormat1128 bool subset (hb_subset_context_t *c) const 129 { 130 TRACE_SUBSET (this); 131 auto *out = c->serializer->embed (this); 132 if (unlikely (!out)) return_trace (false); 133 return_trace (true); 134 } 135 136 private: get_caret_valueOT::CaretValueFormat1137 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const 138 { 139 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); 140 } 141 sanitizeOT::CaretValueFormat1142 bool sanitize (hb_sanitize_context_t *c) const 143 { 144 TRACE_SANITIZE (this); 145 return_trace (c->check_struct (this)); 146 } 147 148 protected: 149 HBUINT16 caretValueFormat; /* Format identifier--format = 1 */ 150 FWORD coordinate; /* X or Y value, in design units */ 151 public: 152 DEFINE_SIZE_STATIC (4); 153 }; 154 155 struct CaretValueFormat2 156 { 157 friend struct CaretValue; subsetOT::CaretValueFormat2158 bool subset (hb_subset_context_t *c) const 159 { 160 TRACE_SUBSET (this); 161 auto *out = c->serializer->embed (this); 162 if (unlikely (!out)) return_trace (false); 163 return_trace (true); 164 } 165 166 private: get_caret_valueOT::CaretValueFormat2167 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const 168 { 169 hb_position_t x, y; 170 font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y); 171 return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; 172 } 173 sanitizeOT::CaretValueFormat2174 bool sanitize (hb_sanitize_context_t *c) const 175 { 176 TRACE_SANITIZE (this); 177 return_trace (c->check_struct (this)); 178 } 179 180 protected: 181 HBUINT16 caretValueFormat; /* Format identifier--format = 2 */ 182 HBUINT16 caretValuePoint; /* Contour point index on glyph */ 183 public: 184 DEFINE_SIZE_STATIC (4); 185 }; 186 187 struct CaretValueFormat3 188 { 189 friend struct CaretValue; 190 get_caret_valueOT::CaretValueFormat3191 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, 192 const ItemVariationStore &var_store) const 193 { 194 return HB_DIRECTION_IS_HORIZONTAL (direction) ? 195 font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : 196 font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store); 197 } 198 subsetOT::CaretValueFormat3199 bool subset (hb_subset_context_t *c) const 200 { 201 TRACE_SUBSET (this); 202 auto *out = c->serializer->start_embed (*this); 203 if (!c->serializer->embed (caretValueFormat)) return_trace (false); 204 if (!c->serializer->embed (coordinate)) return_trace (false); 205 206 unsigned varidx = (this+deviceTable).get_variation_index (); 207 hb_pair_t<unsigned, int> *new_varidx_delta; 208 if (!c->plan->layout_variation_idx_delta_map.has (varidx, &new_varidx_delta)) 209 return_trace (false); 210 211 uint32_t new_varidx = hb_first (*new_varidx_delta); 212 int delta = hb_second (*new_varidx_delta); 213 if (delta != 0) 214 { 215 if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) 216 return_trace (false); 217 } 218 219 if (new_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX) 220 return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); 221 222 if (!c->serializer->embed (deviceTable)) 223 return_trace (false); 224 225 return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out), 226 hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map)); 227 } 228 collect_variation_indicesOT::CaretValueFormat3229 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 230 { (this+deviceTable).collect_variation_indices (c); } 231 sanitizeOT::CaretValueFormat3232 bool sanitize (hb_sanitize_context_t *c) const 233 { 234 TRACE_SANITIZE (this); 235 return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); 236 } 237 238 protected: 239 HBUINT16 caretValueFormat; /* Format identifier--format = 3 */ 240 FWORD coordinate; /* X or Y value, in design units */ 241 Offset16To<Device> 242 deviceTable; /* Offset to Device table for X or Y 243 * value--from beginning of CaretValue 244 * table */ 245 public: 246 DEFINE_SIZE_STATIC (6); 247 }; 248 249 struct CaretValue 250 { get_caret_valueOT::CaretValue251 hb_position_t get_caret_value (hb_font_t *font, 252 hb_direction_t direction, 253 hb_codepoint_t glyph_id, 254 const ItemVariationStore &var_store) const 255 { 256 switch (u.format) { 257 case 1: return u.format1.get_caret_value (font, direction); 258 case 2: return u.format2.get_caret_value (font, direction, glyph_id); 259 case 3: return u.format3.get_caret_value (font, direction, var_store); 260 default:return 0; 261 } 262 } 263 264 template <typename context_t, typename ...Ts> dispatchOT::CaretValue265 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const 266 { 267 if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value (); 268 TRACE_DISPATCH (this, u.format); 269 switch (u.format) { 270 case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); 271 case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); 272 case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); 273 default:return_trace (c->default_return_value ()); 274 } 275 } 276 collect_variation_indicesOT::CaretValue277 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 278 { 279 switch (u.format) { 280 case 1: 281 case 2: 282 return; 283 case 3: 284 u.format3.collect_variation_indices (c); 285 return; 286 default: return; 287 } 288 } 289 sanitizeOT::CaretValue290 bool sanitize (hb_sanitize_context_t *c) const 291 { 292 TRACE_SANITIZE (this); 293 if (!u.format.sanitize (c)) return_trace (false); 294 hb_barrier (); 295 switch (u.format) { 296 case 1: return_trace (u.format1.sanitize (c)); 297 case 2: return_trace (u.format2.sanitize (c)); 298 case 3: return_trace (u.format3.sanitize (c)); 299 default:return_trace (true); 300 } 301 } 302 303 protected: 304 union { 305 HBUINT16 format; /* Format identifier */ 306 CaretValueFormat1 format1; 307 CaretValueFormat2 format2; 308 CaretValueFormat3 format3; 309 } u; 310 public: 311 DEFINE_SIZE_UNION (2, format); 312 }; 313 314 struct LigGlyph 315 { get_lig_caretsOT::LigGlyph316 unsigned get_lig_carets (hb_font_t *font, 317 hb_direction_t direction, 318 hb_codepoint_t glyph_id, 319 const ItemVariationStore &var_store, 320 unsigned start_offset, 321 unsigned *caret_count /* IN/OUT */, 322 hb_position_t *caret_array /* OUT */) const 323 { 324 if (caret_count) 325 { 326 + carets.as_array ().sub_array (start_offset, caret_count) 327 | hb_map (hb_add (this)) 328 | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); }) 329 | hb_sink (hb_array (caret_array, *caret_count)) 330 ; 331 } 332 333 return carets.len; 334 } 335 subsetOT::LigGlyph336 bool subset (hb_subset_context_t *c) const 337 { 338 TRACE_SUBSET (this); 339 auto *out = c->serializer->start_embed (*this); 340 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 341 342 + hb_iter (carets) 343 | hb_apply (subset_offset_array (c, out->carets, this)) 344 ; 345 346 return_trace (bool (out->carets)); 347 } 348 collect_variation_indicesOT::LigGlyph349 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 350 { 351 for (const Offset16To<CaretValue>& offset : carets.iter ()) 352 (this+offset).collect_variation_indices (c); 353 } 354 sanitizeOT::LigGlyph355 bool sanitize (hb_sanitize_context_t *c) const 356 { 357 TRACE_SANITIZE (this); 358 return_trace (carets.sanitize (c, this)); 359 } 360 361 protected: 362 Array16OfOffset16To<CaretValue> 363 carets; /* Offset array of CaretValue tables 364 * --from beginning of LigGlyph table 365 * --in increasing coordinate order */ 366 public: 367 DEFINE_SIZE_ARRAY (2, carets); 368 }; 369 370 struct LigCaretList 371 { get_lig_caretsOT::LigCaretList372 unsigned int get_lig_carets (hb_font_t *font, 373 hb_direction_t direction, 374 hb_codepoint_t glyph_id, 375 const ItemVariationStore &var_store, 376 unsigned int start_offset, 377 unsigned int *caret_count /* IN/OUT */, 378 hb_position_t *caret_array /* OUT */) const 379 { 380 unsigned int index = (this+coverage).get_coverage (glyph_id); 381 if (index == NOT_COVERED) 382 { 383 if (caret_count) 384 *caret_count = 0; 385 return 0; 386 } 387 const LigGlyph &lig_glyph = this+ligGlyph[index]; 388 return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); 389 } 390 subsetOT::LigCaretList391 bool subset (hb_subset_context_t *c) const 392 { 393 TRACE_SUBSET (this); 394 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 395 const hb_map_t &glyph_map = *c->plan->glyph_map; 396 397 auto *out = c->serializer->start_embed (*this); 398 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 399 400 hb_sorted_vector_t<hb_codepoint_t> new_coverage; 401 + hb_zip (this+coverage, ligGlyph) 402 | hb_filter (glyphset, hb_first) 403 | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second) 404 | hb_map (hb_first) 405 | hb_map (glyph_map) 406 | hb_sink (new_coverage) 407 ; 408 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); 409 return_trace (bool (new_coverage)); 410 } 411 collect_variation_indicesOT::LigCaretList412 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 413 { 414 + hb_zip (this+coverage, ligGlyph) 415 | hb_filter (c->glyph_set, hb_first) 416 | hb_map (hb_second) 417 | hb_map (hb_add (this)) 418 | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); }) 419 ; 420 } 421 sanitizeOT::LigCaretList422 bool sanitize (hb_sanitize_context_t *c) const 423 { 424 TRACE_SANITIZE (this); 425 return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); 426 } 427 428 protected: 429 Offset16To<Coverage> 430 coverage; /* Offset to Coverage table--from 431 * beginning of LigCaretList table */ 432 Array16OfOffset16To<LigGlyph> 433 ligGlyph; /* Array of LigGlyph tables 434 * in Coverage Index order */ 435 public: 436 DEFINE_SIZE_ARRAY (4, ligGlyph); 437 }; 438 439 440 struct MarkGlyphSetsFormat1 441 { coversOT::MarkGlyphSetsFormat1442 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 443 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } 444 collect_used_mark_setsOT::MarkGlyphSetsFormat1445 void collect_used_mark_sets (const hb_set_t& glyph_set, 446 hb_set_t& used_mark_sets /* OUT */) const 447 { 448 unsigned i = 0; 449 for (const auto &offset : coverage) 450 { 451 const auto &cov = this+offset; 452 if (cov.intersects (&glyph_set)) 453 used_mark_sets.add (i); 454 455 i++; 456 } 457 } 458 459 template <typename set_t> collect_coverageOT::MarkGlyphSetsFormat1460 void collect_coverage (hb_vector_t<set_t> &sets) const 461 { 462 for (const auto &offset : coverage) 463 { 464 const auto &cov = this+offset; 465 cov.collect_coverage (sets.push ()); 466 } 467 } 468 subsetOT::MarkGlyphSetsFormat1469 bool subset (hb_subset_context_t *c) const 470 { 471 TRACE_SUBSET (this); 472 auto *out = c->serializer->start_embed (*this); 473 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 474 out->format = format; 475 476 bool ret = true; 477 for (const Offset32To<Coverage>& offset : coverage.iter ()) 478 { 479 auto snap = c->serializer->snapshot (); 480 auto *o = out->coverage.serialize_append (c->serializer); 481 if (unlikely (!o)) 482 { 483 ret = false; 484 break; 485 } 486 487 //skip empty coverage 488 c->serializer->push (); 489 bool res = false; 490 if (offset) res = c->dispatch (this+offset); 491 if (!res) 492 { 493 c->serializer->pop_discard (); 494 c->serializer->revert (snap); 495 (out->coverage.len)--; 496 continue; 497 } 498 c->serializer->add_link (*o, c->serializer->pop_pack ()); 499 } 500 501 return_trace (ret && out->coverage.len); 502 } 503 sanitizeOT::MarkGlyphSetsFormat1504 bool sanitize (hb_sanitize_context_t *c) const 505 { 506 TRACE_SANITIZE (this); 507 return_trace (coverage.sanitize (c, this)); 508 } 509 510 protected: 511 HBUINT16 format; /* Format identifier--format = 1 */ 512 Array16Of<Offset32To<Coverage>> 513 coverage; /* Array of long offsets to mark set 514 * coverage tables */ 515 public: 516 DEFINE_SIZE_ARRAY (4, coverage); 517 }; 518 519 struct MarkGlyphSets 520 { coversOT::MarkGlyphSets521 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 522 { 523 switch (u.format) { 524 case 1: return u.format1.covers (set_index, glyph_id); 525 default:return false; 526 } 527 } 528 529 template <typename set_t> collect_coverageOT::MarkGlyphSets530 void collect_coverage (hb_vector_t<set_t> &sets) const 531 { 532 switch (u.format) { 533 case 1: u.format1.collect_coverage (sets); return; 534 default:return; 535 } 536 } 537 collect_used_mark_setsOT::MarkGlyphSets538 void collect_used_mark_sets (const hb_set_t& glyph_set, 539 hb_set_t& used_mark_sets /* OUT */) const 540 { 541 switch (u.format) { 542 case 1: u.format1.collect_used_mark_sets (glyph_set, used_mark_sets); return; 543 default:return; 544 } 545 } 546 subsetOT::MarkGlyphSets547 bool subset (hb_subset_context_t *c) const 548 { 549 TRACE_SUBSET (this); 550 switch (u.format) { 551 case 1: return_trace (u.format1.subset (c)); 552 default:return_trace (false); 553 } 554 } 555 sanitizeOT::MarkGlyphSets556 bool sanitize (hb_sanitize_context_t *c) const 557 { 558 TRACE_SANITIZE (this); 559 if (!u.format.sanitize (c)) return_trace (false); 560 hb_barrier (); 561 switch (u.format) { 562 case 1: return_trace (u.format1.sanitize (c)); 563 default:return_trace (true); 564 } 565 } 566 567 protected: 568 union { 569 HBUINT16 format; /* Format identifier */ 570 MarkGlyphSetsFormat1 format1; 571 } u; 572 public: 573 DEFINE_SIZE_UNION (2, format); 574 }; 575 576 577 /* 578 * GDEF -- Glyph Definition 579 * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef 580 */ 581 582 583 template <typename Types> 584 struct GDEFVersion1_2 585 { 586 friend struct GDEF; 587 588 protected: 589 FixedVersion<>version; /* Version of the GDEF table--currently 590 * 0x00010003u */ 591 typename Types::template OffsetTo<ClassDef> 592 glyphClassDef; /* Offset to class definition table 593 * for glyph type--from beginning of 594 * GDEF header (may be Null) */ 595 typename Types::template OffsetTo<AttachList> 596 attachList; /* Offset to list of glyphs with 597 * attachment points--from beginning 598 * of GDEF header (may be Null) */ 599 typename Types::template OffsetTo<LigCaretList> 600 ligCaretList; /* Offset to list of positioning points 601 * for ligature carets--from beginning 602 * of GDEF header (may be Null) */ 603 typename Types::template OffsetTo<ClassDef> 604 markAttachClassDef; /* Offset to class definition table for 605 * mark attachment type--from beginning 606 * of GDEF header (may be Null) */ 607 typename Types::template OffsetTo<MarkGlyphSets> 608 markGlyphSetsDef; /* Offset to the table of mark set 609 * definitions--from beginning of GDEF 610 * header (may be NULL). Introduced 611 * in version 0x00010002. */ 612 Offset32To<ItemVariationStore> 613 varStore; /* Offset to the table of Item Variation 614 * Store--from beginning of GDEF 615 * header (may be NULL). Introduced 616 * in version 0x00010003. */ 617 public: 618 DEFINE_SIZE_MIN (4 + 4 * Types::size); 619 get_sizeOT::GDEFVersion1_2620 unsigned int get_size () const 621 { 622 return min_size + 623 (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + 624 (version.to_int () >= 0x00010003u ? varStore.static_size : 0); 625 } 626 sanitizeOT::GDEFVersion1_2627 bool sanitize (hb_sanitize_context_t *c) const 628 { 629 TRACE_SANITIZE (this); 630 return_trace (version.sanitize (c) && 631 glyphClassDef.sanitize (c, this) && 632 attachList.sanitize (c, this) && 633 ligCaretList.sanitize (c, this) && 634 markAttachClassDef.sanitize (c, this) && 635 hb_barrier () && 636 ((version.to_int () < 0x00010002u && hb_barrier ()) || markGlyphSetsDef.sanitize (c, this)) && 637 ((version.to_int () < 0x00010003u && hb_barrier ()) || varStore.sanitize (c, this))); 638 } 639 remap_varidx_after_instantiationOT::GDEFVersion1_2640 static void remap_varidx_after_instantiation (const hb_map_t& varidx_map, 641 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>& layout_variation_idx_delta_map /* IN/OUT */) 642 { 643 /* varidx_map is empty which means varstore is empty after instantiation, 644 * no variations, map all varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX. 645 * varidx_map doesn't have original varidx, indicating delta row is all 646 * zeros, map varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */ 647 for (auto _ : layout_variation_idx_delta_map.iter_ref ()) 648 { 649 /* old_varidx->(varidx, delta) mapping generated for subsetting, then this 650 * varidx is used as key of varidx_map during instantiation */ 651 uint32_t varidx = _.second.first; 652 uint32_t *new_varidx; 653 if (varidx_map.has (varidx, &new_varidx)) 654 _.second.first = *new_varidx; 655 else 656 _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX; 657 } 658 } 659 subsetOT::GDEFVersion1_2660 bool subset (hb_subset_context_t *c) const 661 { 662 TRACE_SUBSET (this); 663 auto *out = c->serializer->start_embed (*this); 664 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 665 666 // Push var store first (if it's needed) so that it's last in the 667 // serialization order. Some font consumers assume that varstore runs to 668 // the end of the GDEF table. 669 // See: https://github.com/harfbuzz/harfbuzz/issues/4636 670 auto snapshot_version0 = c->serializer->snapshot (); 671 if (unlikely (version.to_int () >= 0x00010002u && hb_barrier () && !c->serializer->embed (markGlyphSetsDef))) 672 return_trace (false); 673 674 bool subset_varstore = false; 675 unsigned varstore_index = (unsigned) -1; 676 auto snapshot_version2 = c->serializer->snapshot (); 677 if (version.to_int () >= 0x00010003u && hb_barrier ()) 678 { 679 if (unlikely (!c->serializer->embed (varStore))) return_trace (false); 680 if (c->plan->all_axes_pinned) 681 out->varStore = 0; 682 else if (c->plan->normalized_coords) 683 { 684 if (varStore) 685 { 686 item_variations_t item_vars; 687 if (item_vars.instantiate (this+varStore, c->plan, true, true, 688 c->plan->gdef_varstore_inner_maps.as_array ())) { 689 subset_varstore = out->varStore.serialize_serialize (c->serializer, 690 item_vars.has_long_word (), 691 c->plan->axis_tags, 692 item_vars.get_region_list (), 693 item_vars.get_vardata_encodings ()); 694 varstore_index = c->serializer->last_added_child_index(); 695 } 696 remap_varidx_after_instantiation (item_vars.get_varidx_map (), 697 c->plan->layout_variation_idx_delta_map); 698 } 699 } 700 else 701 { 702 subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ()); 703 varstore_index = c->serializer->last_added_child_index(); 704 } 705 } 706 707 out->version.major = version.major; 708 out->version.minor = version.minor; 709 710 if (!subset_varstore && version.to_int () >= 0x00010002u) { 711 c->serializer->revert (snapshot_version2); 712 } 713 714 bool subset_markglyphsetsdef = false; 715 if (version.to_int () >= 0x00010002u && hb_barrier ()) 716 { 717 subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); 718 } 719 720 if (subset_varstore) 721 { 722 out->version.minor = 3; 723 c->plan->has_gdef_varstore = true; 724 } else if (subset_markglyphsetsdef) { 725 out->version.minor = 2; 726 } else { 727 out->version.minor = 0; 728 c->serializer->revert (snapshot_version0); 729 } 730 731 bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); 732 bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); 733 bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); 734 bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); 735 736 if (subset_varstore && varstore_index != (unsigned) -1) { 737 c->serializer->repack_last(varstore_index); 738 } 739 740 return_trace (subset_glyphclassdef || subset_attachlist || 741 subset_ligcaretlist || subset_markattachclassdef || 742 (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || 743 (out->version.to_int () >= 0x00010003u && subset_varstore)); 744 } 745 }; 746 747 struct GDEF 748 { 749 static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF; 750 751 enum GlyphClasses { 752 UnclassifiedGlyph = 0, 753 BaseGlyph = 1, 754 LigatureGlyph = 2, 755 MarkGlyph = 3, 756 ComponentGlyph = 4 757 }; 758 get_sizeOT::GDEF759 unsigned int get_size () const 760 { 761 switch (u.version.major) { 762 case 1: return u.version1.get_size (); 763 #ifndef HB_NO_BEYOND_64K 764 case 2: return u.version2.get_size (); 765 #endif 766 default: return u.version.static_size; 767 } 768 } 769 sanitizeOT::GDEF770 bool sanitize (hb_sanitize_context_t *c) const 771 { 772 TRACE_SANITIZE (this); 773 if (unlikely (!u.version.sanitize (c))) return_trace (false); 774 hb_barrier (); 775 switch (u.version.major) { 776 case 1: return_trace (u.version1.sanitize (c)); 777 #ifndef HB_NO_BEYOND_64K 778 case 2: return_trace (u.version2.sanitize (c)); 779 #endif 780 default: return_trace (true); 781 } 782 } 783 subsetOT::GDEF784 bool subset (hb_subset_context_t *c) const 785 { 786 switch (u.version.major) { 787 case 1: return u.version1.subset (c); 788 #ifndef HB_NO_BEYOND_64K 789 case 2: return u.version2.subset (c); 790 #endif 791 default: return false; 792 } 793 } 794 has_glyph_classesOT::GDEF795 bool has_glyph_classes () const 796 { 797 switch (u.version.major) { 798 case 1: return u.version1.glyphClassDef != 0; 799 #ifndef HB_NO_BEYOND_64K 800 case 2: return u.version2.glyphClassDef != 0; 801 #endif 802 default: return false; 803 } 804 } get_glyph_class_defOT::GDEF805 const ClassDef &get_glyph_class_def () const 806 { 807 switch (u.version.major) { 808 case 1: return this+u.version1.glyphClassDef; 809 #ifndef HB_NO_BEYOND_64K 810 case 2: return this+u.version2.glyphClassDef; 811 #endif 812 default: return Null(ClassDef); 813 } 814 } has_attach_listOT::GDEF815 bool has_attach_list () const 816 { 817 switch (u.version.major) { 818 case 1: return u.version1.attachList != 0; 819 #ifndef HB_NO_BEYOND_64K 820 case 2: return u.version2.attachList != 0; 821 #endif 822 default: return false; 823 } 824 } get_attach_listOT::GDEF825 const AttachList &get_attach_list () const 826 { 827 switch (u.version.major) { 828 case 1: return this+u.version1.attachList; 829 #ifndef HB_NO_BEYOND_64K 830 case 2: return this+u.version2.attachList; 831 #endif 832 default: return Null(AttachList); 833 } 834 } has_lig_caretsOT::GDEF835 bool has_lig_carets () const 836 { 837 switch (u.version.major) { 838 case 1: return u.version1.ligCaretList != 0; 839 #ifndef HB_NO_BEYOND_64K 840 case 2: return u.version2.ligCaretList != 0; 841 #endif 842 default: return false; 843 } 844 } get_lig_caret_listOT::GDEF845 const LigCaretList &get_lig_caret_list () const 846 { 847 switch (u.version.major) { 848 case 1: return this+u.version1.ligCaretList; 849 #ifndef HB_NO_BEYOND_64K 850 case 2: return this+u.version2.ligCaretList; 851 #endif 852 default: return Null(LigCaretList); 853 } 854 } has_mark_attachment_typesOT::GDEF855 bool has_mark_attachment_types () const 856 { 857 switch (u.version.major) { 858 case 1: return u.version1.markAttachClassDef != 0; 859 #ifndef HB_NO_BEYOND_64K 860 case 2: return u.version2.markAttachClassDef != 0; 861 #endif 862 default: return false; 863 } 864 } get_mark_attach_class_defOT::GDEF865 const ClassDef &get_mark_attach_class_def () const 866 { 867 switch (u.version.major) { 868 case 1: return this+u.version1.markAttachClassDef; 869 #ifndef HB_NO_BEYOND_64K 870 case 2: return this+u.version2.markAttachClassDef; 871 #endif 872 default: return Null(ClassDef); 873 } 874 } has_mark_glyph_setsOT::GDEF875 bool has_mark_glyph_sets () const 876 { 877 switch (u.version.major) { 878 case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () && u.version1.markGlyphSetsDef != 0; 879 #ifndef HB_NO_BEYOND_64K 880 case 2: return u.version2.markGlyphSetsDef != 0; 881 #endif 882 default: return false; 883 } 884 } get_mark_glyph_setsOT::GDEF885 const MarkGlyphSets &get_mark_glyph_sets () const 886 { 887 switch (u.version.major) { 888 case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets); 889 #ifndef HB_NO_BEYOND_64K 890 case 2: return this+u.version2.markGlyphSetsDef; 891 #endif 892 default: return Null(MarkGlyphSets); 893 } 894 } has_var_storeOT::GDEF895 bool has_var_store () const 896 { 897 switch (u.version.major) { 898 case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () && u.version1.varStore != 0; 899 #ifndef HB_NO_BEYOND_64K 900 case 2: return u.version2.varStore != 0; 901 #endif 902 default: return false; 903 } 904 } get_var_storeOT::GDEF905 const ItemVariationStore &get_var_store () const 906 { 907 switch (u.version.major) { 908 case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () ? this+u.version1.varStore : Null(ItemVariationStore); 909 #ifndef HB_NO_BEYOND_64K 910 case 2: return this+u.version2.varStore; 911 #endif 912 default: return Null(ItemVariationStore); 913 } 914 } 915 916 has_dataOT::GDEF917 bool has_data () const { return u.version.to_int (); } get_glyph_classOT::GDEF918 unsigned int get_glyph_class (hb_codepoint_t glyph) const 919 { return get_glyph_class_def ().get_class (glyph); } get_glyphs_in_classOT::GDEF920 void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const 921 { get_glyph_class_def ().collect_class (glyphs, klass); } 922 get_mark_attachment_typeOT::GDEF923 unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const 924 { return get_mark_attach_class_def ().get_class (glyph); } 925 get_attach_pointsOT::GDEF926 unsigned int get_attach_points (hb_codepoint_t glyph_id, 927 unsigned int start_offset, 928 unsigned int *point_count /* IN/OUT */, 929 unsigned int *point_array /* OUT */) const 930 { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); } 931 get_lig_caretsOT::GDEF932 unsigned int get_lig_carets (hb_font_t *font, 933 hb_direction_t direction, 934 hb_codepoint_t glyph_id, 935 unsigned int start_offset, 936 unsigned int *caret_count /* IN/OUT */, 937 hb_position_t *caret_array /* OUT */) const 938 { return get_lig_caret_list ().get_lig_carets (font, 939 direction, glyph_id, get_var_store(), 940 start_offset, caret_count, caret_array); } 941 mark_set_coversOT::GDEF942 bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 943 { return get_mark_glyph_sets ().covers (set_index, glyph_id); } 944 945 /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing 946 * glyph class and other bits, and high 8-bit the mark attachment type (if any). 947 * Not to be confused with lookup_props which is very similar. */ get_glyph_propsOT::GDEF948 unsigned int get_glyph_props (hb_codepoint_t glyph) const 949 { 950 unsigned int klass = get_glyph_class (glyph); 951 952 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), ""); 953 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), ""); 954 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), ""); 955 956 switch (klass) { 957 default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; 958 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; 959 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; 960 case MarkGlyph: 961 klass = get_mark_attachment_type (glyph); 962 return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8); 963 } 964 } 965 966 HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, 967 hb_face_t *face) const; 968 969 struct accelerator_t 970 { accelerator_tOT::GDEF::accelerator_t971 accelerator_t (hb_face_t *face) 972 { 973 table = hb_sanitize_context_t ().reference_table<GDEF> (face); 974 if (unlikely (table->is_blocklisted (table.get_blob (), face))) 975 { 976 hb_blob_destroy (table.get_blob ()); 977 table = hb_blob_get_empty (); 978 } 979 980 #ifndef HB_NO_GDEF_CACHE 981 table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests); 982 #endif 983 } ~accelerator_tOT::GDEF::accelerator_t984 ~accelerator_t () { table.destroy (); } 985 get_glyph_propsOT::GDEF::accelerator_t986 unsigned int get_glyph_props (hb_codepoint_t glyph) const 987 { 988 unsigned v; 989 990 #ifndef HB_NO_GDEF_CACHE 991 if (glyph_props_cache.get (glyph, &v)) 992 return v; 993 #endif 994 995 v = table->get_glyph_props (glyph); 996 997 #ifndef HB_NO_GDEF_CACHE 998 if (likely (table.get_blob ())) // Don't try setting if we are the null instance! 999 glyph_props_cache.set (glyph, v); 1000 #endif 1001 1002 return v; 1003 1004 } 1005 mark_set_coversOT::GDEF::accelerator_t1006 bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 1007 { 1008 return 1009 #ifndef HB_NO_GDEF_CACHE 1010 mark_glyph_set_digests[set_index].may_have (glyph_id) && 1011 #endif 1012 table->mark_set_covers (set_index, glyph_id); 1013 } 1014 1015 hb_blob_ptr_t<GDEF> table; 1016 #ifndef HB_NO_GDEF_CACHE 1017 hb_vector_t<hb_set_digest_t> mark_glyph_set_digests; 1018 mutable hb_cache_t<21, 3, 8> glyph_props_cache; 1019 #endif 1020 }; 1021 collect_variation_indicesOT::GDEF1022 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 1023 { get_lig_caret_list ().collect_variation_indices (c); } 1024 1025 protected: 1026 union { 1027 FixedVersion<> version; /* Version identifier */ 1028 GDEFVersion1_2<SmallTypes> version1; 1029 #ifndef HB_NO_BEYOND_64K 1030 GDEFVersion1_2<MediumTypes> version2; 1031 #endif 1032 } u; 1033 public: 1034 DEFINE_SIZE_MIN (4); 1035 }; 1036 1037 struct GDEF_accelerator_t : GDEF::accelerator_t { GDEF_accelerator_tOT::GDEF_accelerator_t1038 GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {} 1039 }; 1040 1041 } /* namespace OT */ 1042 1043 1044 #endif /* OT_LAYOUT_GDEF_GDEF_HH */ 1045