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 VariationStore &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 VariationStore &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 switch (u.format) { 295 case 1: return_trace (u.format1.sanitize (c)); 296 case 2: return_trace (u.format2.sanitize (c)); 297 case 3: return_trace (u.format3.sanitize (c)); 298 default:return_trace (true); 299 } 300 } 301 302 protected: 303 union { 304 HBUINT16 format; /* Format identifier */ 305 CaretValueFormat1 format1; 306 CaretValueFormat2 format2; 307 CaretValueFormat3 format3; 308 } u; 309 public: 310 DEFINE_SIZE_UNION (2, format); 311 }; 312 313 struct LigGlyph 314 { get_lig_caretsOT::LigGlyph315 unsigned get_lig_carets (hb_font_t *font, 316 hb_direction_t direction, 317 hb_codepoint_t glyph_id, 318 const VariationStore &var_store, 319 unsigned start_offset, 320 unsigned *caret_count /* IN/OUT */, 321 hb_position_t *caret_array /* OUT */) const 322 { 323 if (caret_count) 324 { 325 + carets.as_array ().sub_array (start_offset, caret_count) 326 | hb_map (hb_add (this)) 327 | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); }) 328 | hb_sink (hb_array (caret_array, *caret_count)) 329 ; 330 } 331 332 return carets.len; 333 } 334 subsetOT::LigGlyph335 bool subset (hb_subset_context_t *c) const 336 { 337 TRACE_SUBSET (this); 338 auto *out = c->serializer->start_embed (*this); 339 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 340 341 + hb_iter (carets) 342 | hb_apply (subset_offset_array (c, out->carets, this)) 343 ; 344 345 return_trace (bool (out->carets)); 346 } 347 collect_variation_indicesOT::LigGlyph348 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 349 { 350 for (const Offset16To<CaretValue>& offset : carets.iter ()) 351 (this+offset).collect_variation_indices (c); 352 } 353 sanitizeOT::LigGlyph354 bool sanitize (hb_sanitize_context_t *c) const 355 { 356 TRACE_SANITIZE (this); 357 return_trace (carets.sanitize (c, this)); 358 } 359 360 protected: 361 Array16OfOffset16To<CaretValue> 362 carets; /* Offset array of CaretValue tables 363 * --from beginning of LigGlyph table 364 * --in increasing coordinate order */ 365 public: 366 DEFINE_SIZE_ARRAY (2, carets); 367 }; 368 369 struct LigCaretList 370 { get_lig_caretsOT::LigCaretList371 unsigned int get_lig_carets (hb_font_t *font, 372 hb_direction_t direction, 373 hb_codepoint_t glyph_id, 374 const VariationStore &var_store, 375 unsigned int start_offset, 376 unsigned int *caret_count /* IN/OUT */, 377 hb_position_t *caret_array /* OUT */) const 378 { 379 unsigned int index = (this+coverage).get_coverage (glyph_id); 380 if (index == NOT_COVERED) 381 { 382 if (caret_count) 383 *caret_count = 0; 384 return 0; 385 } 386 const LigGlyph &lig_glyph = this+ligGlyph[index]; 387 return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); 388 } 389 subsetOT::LigCaretList390 bool subset (hb_subset_context_t *c) const 391 { 392 TRACE_SUBSET (this); 393 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); 394 const hb_map_t &glyph_map = *c->plan->glyph_map; 395 396 auto *out = c->serializer->start_embed (*this); 397 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 398 399 hb_sorted_vector_t<hb_codepoint_t> new_coverage; 400 + hb_zip (this+coverage, ligGlyph) 401 | hb_filter (glyphset, hb_first) 402 | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second) 403 | hb_map (hb_first) 404 | hb_map (glyph_map) 405 | hb_sink (new_coverage) 406 ; 407 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); 408 return_trace (bool (new_coverage)); 409 } 410 collect_variation_indicesOT::LigCaretList411 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 412 { 413 + hb_zip (this+coverage, ligGlyph) 414 | hb_filter (c->glyph_set, hb_first) 415 | hb_map (hb_second) 416 | hb_map (hb_add (this)) 417 | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); }) 418 ; 419 } 420 sanitizeOT::LigCaretList421 bool sanitize (hb_sanitize_context_t *c) const 422 { 423 TRACE_SANITIZE (this); 424 return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); 425 } 426 427 protected: 428 Offset16To<Coverage> 429 coverage; /* Offset to Coverage table--from 430 * beginning of LigCaretList table */ 431 Array16OfOffset16To<LigGlyph> 432 ligGlyph; /* Array of LigGlyph tables 433 * in Coverage Index order */ 434 public: 435 DEFINE_SIZE_ARRAY (4, ligGlyph); 436 }; 437 438 439 struct MarkGlyphSetsFormat1 440 { coversOT::MarkGlyphSetsFormat1441 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 442 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } 443 444 template <typename set_t> collect_coverageOT::MarkGlyphSetsFormat1445 void collect_coverage (hb_vector_t<set_t> &sets) const 446 { 447 for (const auto &offset : coverage) 448 { 449 const auto &cov = this+offset; 450 cov.collect_coverage (sets.push ()); 451 } 452 } 453 subsetOT::MarkGlyphSetsFormat1454 bool subset (hb_subset_context_t *c) const 455 { 456 TRACE_SUBSET (this); 457 auto *out = c->serializer->start_embed (*this); 458 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); 459 out->format = format; 460 461 bool ret = true; 462 for (const Offset32To<Coverage>& offset : coverage.iter ()) 463 { 464 auto *o = out->coverage.serialize_append (c->serializer); 465 if (unlikely (!o)) 466 { 467 ret = false; 468 break; 469 } 470 471 //not using o->serialize_subset (c, offset, this, out) here because 472 //OTS doesn't allow null offset. 473 //See issue: https://github.com/khaledhosny/ots/issues/172 474 c->serializer->push (); 475 c->dispatch (this+offset); 476 c->serializer->add_link (*o, c->serializer->pop_pack ()); 477 } 478 479 return_trace (ret && out->coverage.len); 480 } 481 sanitizeOT::MarkGlyphSetsFormat1482 bool sanitize (hb_sanitize_context_t *c) const 483 { 484 TRACE_SANITIZE (this); 485 return_trace (coverage.sanitize (c, this)); 486 } 487 488 protected: 489 HBUINT16 format; /* Format identifier--format = 1 */ 490 Array16Of<Offset32To<Coverage>> 491 coverage; /* Array of long offsets to mark set 492 * coverage tables */ 493 public: 494 DEFINE_SIZE_ARRAY (4, coverage); 495 }; 496 497 struct MarkGlyphSets 498 { coversOT::MarkGlyphSets499 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const 500 { 501 switch (u.format) { 502 case 1: return u.format1.covers (set_index, glyph_id); 503 default:return false; 504 } 505 } 506 507 template <typename set_t> collect_coverageOT::MarkGlyphSets508 void collect_coverage (hb_vector_t<set_t> &sets) const 509 { 510 switch (u.format) { 511 case 1: u.format1.collect_coverage (sets); return; 512 default:return; 513 } 514 } 515 subsetOT::MarkGlyphSets516 bool subset (hb_subset_context_t *c) const 517 { 518 TRACE_SUBSET (this); 519 switch (u.format) { 520 case 1: return_trace (u.format1.subset (c)); 521 default:return_trace (false); 522 } 523 } 524 sanitizeOT::MarkGlyphSets525 bool sanitize (hb_sanitize_context_t *c) const 526 { 527 TRACE_SANITIZE (this); 528 if (!u.format.sanitize (c)) return_trace (false); 529 switch (u.format) { 530 case 1: return_trace (u.format1.sanitize (c)); 531 default:return_trace (true); 532 } 533 } 534 535 protected: 536 union { 537 HBUINT16 format; /* Format identifier */ 538 MarkGlyphSetsFormat1 format1; 539 } u; 540 public: 541 DEFINE_SIZE_UNION (2, format); 542 }; 543 544 545 /* 546 * GDEF -- Glyph Definition 547 * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef 548 */ 549 550 551 template <typename Types> 552 struct GDEFVersion1_2 553 { 554 friend struct GDEF; 555 556 protected: 557 FixedVersion<>version; /* Version of the GDEF table--currently 558 * 0x00010003u */ 559 typename Types::template OffsetTo<ClassDef> 560 glyphClassDef; /* Offset to class definition table 561 * for glyph type--from beginning of 562 * GDEF header (may be Null) */ 563 typename Types::template OffsetTo<AttachList> 564 attachList; /* Offset to list of glyphs with 565 * attachment points--from beginning 566 * of GDEF header (may be Null) */ 567 typename Types::template OffsetTo<LigCaretList> 568 ligCaretList; /* Offset to list of positioning points 569 * for ligature carets--from beginning 570 * of GDEF header (may be Null) */ 571 typename Types::template OffsetTo<ClassDef> 572 markAttachClassDef; /* Offset to class definition table for 573 * mark attachment type--from beginning 574 * of GDEF header (may be Null) */ 575 typename Types::template OffsetTo<MarkGlyphSets> 576 markGlyphSetsDef; /* Offset to the table of mark set 577 * definitions--from beginning of GDEF 578 * header (may be NULL). Introduced 579 * in version 0x00010002. */ 580 Offset32To<VariationStore> 581 varStore; /* Offset to the table of Item Variation 582 * Store--from beginning of GDEF 583 * header (may be NULL). Introduced 584 * in version 0x00010003. */ 585 public: 586 DEFINE_SIZE_MIN (4 + 4 * Types::size); 587 get_sizeOT::GDEFVersion1_2588 unsigned int get_size () const 589 { 590 return min_size + 591 (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + 592 (version.to_int () >= 0x00010003u ? varStore.static_size : 0); 593 } 594 sanitizeOT::GDEFVersion1_2595 bool sanitize (hb_sanitize_context_t *c) const 596 { 597 TRACE_SANITIZE (this); 598 return_trace (version.sanitize (c) && 599 glyphClassDef.sanitize (c, this) && 600 attachList.sanitize (c, this) && 601 ligCaretList.sanitize (c, this) && 602 markAttachClassDef.sanitize (c, this) && 603 (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && 604 (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); 605 } 606 remap_varidx_after_instantiationOT::GDEFVersion1_2607 static void remap_varidx_after_instantiation (const hb_map_t& varidx_map, 608 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>>& layout_variation_idx_delta_map /* IN/OUT */) 609 { 610 /* varidx_map is empty which means varstore is empty after instantiation, 611 * no variations, map all varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX. 612 * varidx_map doesn't have original varidx, indicating delta row is all 613 * zeros, map varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */ 614 for (auto _ : layout_variation_idx_delta_map.iter_ref ()) 615 { 616 /* old_varidx->(varidx, delta) mapping generated for subsetting, then this 617 * varidx is used as key of varidx_map during instantiation */ 618 uint32_t varidx = _.second.first; 619 uint32_t *new_varidx; 620 if (varidx_map.has (varidx, &new_varidx)) 621 _.second.first = *new_varidx; 622 else 623 _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX; 624 } 625 } 626 subsetOT::GDEFVersion1_2627 bool subset (hb_subset_context_t *c) const 628 { 629 TRACE_SUBSET (this); 630 auto *out = c->serializer->embed (*this); 631 if (unlikely (!out)) return_trace (false); 632 633 bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); 634 bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); 635 bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); 636 bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); 637 638 bool subset_markglyphsetsdef = false; 639 if (version.to_int () >= 0x00010002u) 640 { 641 subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); 642 } 643 644 bool subset_varstore = false; 645 if (version.to_int () >= 0x00010003u) 646 { 647 if (c->plan->all_axes_pinned) 648 out->varStore = 0; 649 else if (c->plan->normalized_coords) 650 { 651 if (varStore) 652 { 653 item_variations_t item_vars; 654 if (item_vars.instantiate (this+varStore, c->plan, true, true, 655 c->plan->gdef_varstore_inner_maps.as_array ())) 656 subset_varstore = out->varStore.serialize_serialize (c->serializer, 657 item_vars.has_long_word (), 658 c->plan->axis_tags, 659 item_vars.get_region_list (), 660 item_vars.get_vardata_encodings ()); 661 remap_varidx_after_instantiation (item_vars.get_varidx_map (), 662 c->plan->layout_variation_idx_delta_map); 663 } 664 } 665 else 666 subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ()); 667 } 668 669 if (subset_varstore) 670 { 671 out->version.minor = 3; 672 } else if (subset_markglyphsetsdef) { 673 out->version.minor = 2; 674 } else { 675 out->version.minor = 0; 676 } 677 678 return_trace (subset_glyphclassdef || subset_attachlist || 679 subset_ligcaretlist || subset_markattachclassdef || 680 (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || 681 (out->version.to_int () >= 0x00010003u && subset_varstore)); 682 } 683 }; 684 685 struct GDEF 686 { 687 static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF; 688 689 enum GlyphClasses { 690 UnclassifiedGlyph = 0, 691 BaseGlyph = 1, 692 LigatureGlyph = 2, 693 MarkGlyph = 3, 694 ComponentGlyph = 4 695 }; 696 get_sizeOT::GDEF697 unsigned int get_size () const 698 { 699 switch (u.version.major) { 700 case 1: return u.version1.get_size (); 701 #ifndef HB_NO_BEYOND_64K 702 case 2: return u.version2.get_size (); 703 #endif 704 default: return u.version.static_size; 705 } 706 } 707 sanitizeOT::GDEF708 bool sanitize (hb_sanitize_context_t *c) const 709 { 710 TRACE_SANITIZE (this); 711 if (unlikely (!u.version.sanitize (c))) return_trace (false); 712 switch (u.version.major) { 713 case 1: return_trace (u.version1.sanitize (c)); 714 #ifndef HB_NO_BEYOND_64K 715 case 2: return_trace (u.version2.sanitize (c)); 716 #endif 717 default: return_trace (true); 718 } 719 } 720 subsetOT::GDEF721 bool subset (hb_subset_context_t *c) const 722 { 723 switch (u.version.major) { 724 case 1: return u.version1.subset (c); 725 #ifndef HB_NO_BEYOND_64K 726 case 2: return u.version2.subset (c); 727 #endif 728 default: return false; 729 } 730 } 731 has_glyph_classesOT::GDEF732 bool has_glyph_classes () const 733 { 734 switch (u.version.major) { 735 case 1: return u.version1.glyphClassDef != 0; 736 #ifndef HB_NO_BEYOND_64K 737 case 2: return u.version2.glyphClassDef != 0; 738 #endif 739 default: return false; 740 } 741 } get_glyph_class_defOT::GDEF742 const ClassDef &get_glyph_class_def () const 743 { 744 switch (u.version.major) { 745 case 1: return this+u.version1.glyphClassDef; 746 #ifndef HB_NO_BEYOND_64K 747 case 2: return this+u.version2.glyphClassDef; 748 #endif 749 default: return Null(ClassDef); 750 } 751 } has_attach_listOT::GDEF752 bool has_attach_list () const 753 { 754 switch (u.version.major) { 755 case 1: return u.version1.attachList != 0; 756 #ifndef HB_NO_BEYOND_64K 757 case 2: return u.version2.attachList != 0; 758 #endif 759 default: return false; 760 } 761 } get_attach_listOT::GDEF762 const AttachList &get_attach_list () const 763 { 764 switch (u.version.major) { 765 case 1: return this+u.version1.attachList; 766 #ifndef HB_NO_BEYOND_64K 767 case 2: return this+u.version2.attachList; 768 #endif 769 default: return Null(AttachList); 770 } 771 } has_lig_caretsOT::GDEF772 bool has_lig_carets () const 773 { 774 switch (u.version.major) { 775 case 1: return u.version1.ligCaretList != 0; 776 #ifndef HB_NO_BEYOND_64K 777 case 2: return u.version2.ligCaretList != 0; 778 #endif 779 default: return false; 780 } 781 } get_lig_caret_listOT::GDEF782 const LigCaretList &get_lig_caret_list () const 783 { 784 switch (u.version.major) { 785 case 1: return this+u.version1.ligCaretList; 786 #ifndef HB_NO_BEYOND_64K 787 case 2: return this+u.version2.ligCaretList; 788 #endif 789 default: return Null(LigCaretList); 790 } 791 } has_mark_attachment_typesOT::GDEF792 bool has_mark_attachment_types () const 793 { 794 switch (u.version.major) { 795 case 1: return u.version1.markAttachClassDef != 0; 796 #ifndef HB_NO_BEYOND_64K 797 case 2: return u.version2.markAttachClassDef != 0; 798 #endif 799 default: return false; 800 } 801 } get_mark_attach_class_defOT::GDEF802 const ClassDef &get_mark_attach_class_def () const 803 { 804 switch (u.version.major) { 805 case 1: return this+u.version1.markAttachClassDef; 806 #ifndef HB_NO_BEYOND_64K 807 case 2: return this+u.version2.markAttachClassDef; 808 #endif 809 default: return Null(ClassDef); 810 } 811 } has_mark_glyph_setsOT::GDEF812 bool has_mark_glyph_sets () const 813 { 814 switch (u.version.major) { 815 case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0; 816 #ifndef HB_NO_BEYOND_64K 817 case 2: return u.version2.markGlyphSetsDef != 0; 818 #endif 819 default: return false; 820 } 821 } get_mark_glyph_setsOT::GDEF822 const MarkGlyphSets &get_mark_glyph_sets () const 823 { 824 switch (u.version.major) { 825 case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets); 826 #ifndef HB_NO_BEYOND_64K 827 case 2: return this+u.version2.markGlyphSetsDef; 828 #endif 829 default: return Null(MarkGlyphSets); 830 } 831 } has_var_storeOT::GDEF832 bool has_var_store () const 833 { 834 switch (u.version.major) { 835 case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0; 836 #ifndef HB_NO_BEYOND_64K 837 case 2: return u.version2.varStore != 0; 838 #endif 839 default: return false; 840 } 841 } get_var_storeOT::GDEF842 const VariationStore &get_var_store () const 843 { 844 switch (u.version.major) { 845 case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore); 846 #ifndef HB_NO_BEYOND_64K 847 case 2: return this+u.version2.varStore; 848 #endif 849 default: return Null(VariationStore); 850 } 851 } 852 853 has_dataOT::GDEF854 bool has_data () const { return u.version.to_int (); } get_glyph_classOT::GDEF855 unsigned int get_glyph_class (hb_codepoint_t glyph) const 856 { return get_glyph_class_def ().get_class (glyph); } get_glyphs_in_classOT::GDEF857 void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const 858 { get_glyph_class_def ().collect_class (glyphs, klass); } 859 get_mark_attachment_typeOT::GDEF860 unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const 861 { return get_mark_attach_class_def ().get_class (glyph); } 862 get_attach_pointsOT::GDEF863 unsigned int get_attach_points (hb_codepoint_t glyph_id, 864 unsigned int start_offset, 865 unsigned int *point_count /* IN/OUT */, 866 unsigned int *point_array /* OUT */) const 867 { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); } 868 get_lig_caretsOT::GDEF869 unsigned int get_lig_carets (hb_font_t *font, 870 hb_direction_t direction, 871 hb_codepoint_t glyph_id, 872 unsigned int start_offset, 873 unsigned int *caret_count /* IN/OUT */, 874 hb_position_t *caret_array /* OUT */) const 875 { return get_lig_caret_list ().get_lig_carets (font, 876 direction, glyph_id, get_var_store(), 877 start_offset, caret_count, caret_array); } 878 mark_set_coversOT::GDEF879 bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 880 { return get_mark_glyph_sets ().covers (set_index, glyph_id); } 881 882 /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing 883 * glyph class and other bits, and high 8-bit the mark attachment type (if any). 884 * Not to be confused with lookup_props which is very similar. */ get_glyph_propsOT::GDEF885 unsigned int get_glyph_props (hb_codepoint_t glyph) const 886 { 887 unsigned int klass = get_glyph_class (glyph); 888 889 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), ""); 890 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), ""); 891 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), ""); 892 893 switch (klass) { 894 default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; 895 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; 896 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; 897 case MarkGlyph: 898 klass = get_mark_attachment_type (glyph); 899 return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8); 900 } 901 } 902 903 HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, 904 hb_face_t *face) const; 905 906 struct accelerator_t 907 { accelerator_tOT::GDEF::accelerator_t908 accelerator_t (hb_face_t *face) 909 { 910 table = hb_sanitize_context_t ().reference_table<GDEF> (face); 911 if (unlikely (table->is_blocklisted (table.get_blob (), face))) 912 { 913 hb_blob_destroy (table.get_blob ()); 914 table = hb_blob_get_empty (); 915 } 916 917 #ifndef HB_NO_GDEF_CACHE 918 table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests); 919 #endif 920 } ~accelerator_tOT::GDEF::accelerator_t921 ~accelerator_t () { table.destroy (); } 922 get_glyph_propsOT::GDEF::accelerator_t923 unsigned int get_glyph_props (hb_codepoint_t glyph) const 924 { 925 unsigned v; 926 927 #ifndef HB_NO_GDEF_CACHE 928 if (glyph_props_cache.get (glyph, &v)) 929 return v; 930 #endif 931 932 v = table->get_glyph_props (glyph); 933 934 #ifndef HB_NO_GDEF_CACHE 935 if (likely (table.get_blob ())) // Don't try setting if we are the null instance! 936 glyph_props_cache.set (glyph, v); 937 #endif 938 939 return v; 940 941 } 942 mark_set_coversOT::GDEF::accelerator_t943 bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const 944 { 945 return 946 #ifndef HB_NO_GDEF_CACHE 947 mark_glyph_set_digests[set_index].may_have (glyph_id) && 948 #endif 949 table->mark_set_covers (set_index, glyph_id); 950 } 951 952 hb_blob_ptr_t<GDEF> table; 953 #ifndef HB_NO_GDEF_CACHE 954 hb_vector_t<hb_set_digest_t> mark_glyph_set_digests; 955 mutable hb_cache_t<21, 3, 8> glyph_props_cache; 956 #endif 957 }; 958 collect_variation_indicesOT::GDEF959 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const 960 { get_lig_caret_list ().collect_variation_indices (c); } 961 remap_layout_variation_indicesOT::GDEF962 void remap_layout_variation_indices (const hb_set_t *layout_variation_indices, 963 const hb_vector_t<int>& normalized_coords, 964 bool calculate_delta, /* not pinned at default */ 965 bool no_variations, /* all axes pinned */ 966 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const 967 { 968 if (!has_var_store ()) return; 969 const VariationStore &var_store = get_var_store (); 970 float *store_cache = var_store.create_cache (); 971 972 unsigned new_major = 0, new_minor = 0; 973 unsigned last_major = (layout_variation_indices->get_min ()) >> 16; 974 for (unsigned idx : layout_variation_indices->iter ()) 975 { 976 int delta = 0; 977 if (calculate_delta) 978 delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ, 979 normalized_coords.length, store_cache)); 980 981 if (no_variations) 982 { 983 layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta)); 984 continue; 985 } 986 987 uint16_t major = idx >> 16; 988 if (major >= var_store.get_sub_table_count ()) break; 989 if (major != last_major) 990 { 991 new_minor = 0; 992 ++new_major; 993 } 994 995 unsigned new_idx = (new_major << 16) + new_minor; 996 layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta)); 997 ++new_minor; 998 last_major = major; 999 } 1000 var_store.destroy_cache (store_cache); 1001 } 1002 1003 protected: 1004 union { 1005 FixedVersion<> version; /* Version identifier */ 1006 GDEFVersion1_2<SmallTypes> version1; 1007 #ifndef HB_NO_BEYOND_64K 1008 GDEFVersion1_2<MediumTypes> version2; 1009 #endif 1010 } u; 1011 public: 1012 DEFINE_SIZE_MIN (4); 1013 }; 1014 1015 struct GDEF_accelerator_t : GDEF::accelerator_t { GDEF_accelerator_tOT::GDEF_accelerator_t1016 GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {} 1017 }; 1018 1019 } /* namespace OT */ 1020 1021 1022 #endif /* OT_LAYOUT_GDEF_GDEF_HH */ 1023