hb-ot-font.cc (30620B)
1 /* 2 * Copyright © 2011,2014 Google, Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Google Author(s): Behdad Esfahbod, Roozbeh Pournader 25 */ 26 27 #include "hb.hh" 28 29 #ifndef HB_NO_OT_FONT 30 31 #include "hb-ot.h" 32 33 #include "hb-cache.hh" 34 #include "hb-font.hh" 35 #include "hb-machinery.hh" 36 #include "hb-ot-face.hh" 37 38 #include "hb-ot-cmap-table.hh" 39 #include "hb-ot-glyf-table.hh" 40 #include "hb-ot-var-gvar-table.hh" 41 #include "hb-ot-cff2-table.hh" 42 #include "hb-ot-cff1-table.hh" 43 #include "hb-ot-hmtx-table.hh" 44 #include "hb-ot-post-table.hh" 45 #include "hb-ot-stat-table.hh" 46 #include "hb-ot-var-varc-table.hh" 47 #include "hb-ot-vorg-table.hh" 48 #include "OT/Color/CBDT/CBDT.hh" 49 #include "OT/Color/COLR/COLR.hh" 50 #include "OT/Color/sbix/sbix.hh" 51 #include "OT/Color/svg/svg.hh" 52 53 54 /** 55 * SECTION:hb-ot-font 56 * @title: hb-ot-font 57 * @short_description: OpenType font implementation 58 * @include: hb-ot.h 59 * 60 * Functions for using OpenType fonts with hb_shape(). Note that fonts returned 61 * by hb_font_create() default to using these functions, so most clients would 62 * never need to call these functions directly. 63 **/ 64 65 using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>; 66 static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, ""); 67 68 using hb_ot_font_origin_cache_t = hb_cache_t<20, 20>; 69 static_assert (sizeof (hb_ot_font_origin_cache_t) == 1024, ""); 70 71 struct hb_ot_font_t 72 { 73 const hb_ot_face_t *ot_face; 74 75 mutable hb_atomic_t<int> cached_serial; 76 mutable hb_atomic_t<int> cached_coords_serial; 77 78 struct direction_cache_t 79 { 80 mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache; 81 mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache; 82 83 ~direction_cache_t () 84 { 85 clear (); 86 } 87 88 hb_ot_font_advance_cache_t *acquire_advance_cache () const 89 { 90 retry: 91 auto *cache = advance_cache.get_acquire (); 92 if (!cache) 93 { 94 cache = (hb_ot_font_advance_cache_t *) hb_malloc (sizeof (hb_ot_font_advance_cache_t)); 95 if (!cache) 96 return nullptr; 97 new (cache) hb_ot_font_advance_cache_t; 98 return cache; 99 } 100 if (advance_cache.cmpexch (cache, nullptr)) 101 return cache; 102 else 103 goto retry; 104 } 105 void release_advance_cache (hb_ot_font_advance_cache_t *cache) const 106 { 107 if (!cache) 108 return; 109 if (!advance_cache.cmpexch (nullptr, cache)) 110 hb_free (cache); 111 } 112 void clear_advance_cache () const 113 { 114 retry: 115 auto *cache = advance_cache.get_acquire (); 116 if (!cache) 117 return; 118 if (advance_cache.cmpexch (cache, nullptr)) 119 hb_free (cache); 120 else 121 goto retry; 122 } 123 124 OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const 125 { 126 retry: 127 auto *cache = varStore_cache.get_acquire (); 128 if (!cache) 129 return varStore.create_cache (); 130 if (varStore_cache.cmpexch (cache, nullptr)) 131 return cache; 132 else 133 goto retry; 134 } 135 void release_varStore_cache (OT::hb_scalar_cache_t *cache) const 136 { 137 if (!cache) 138 return; 139 if (!varStore_cache.cmpexch (nullptr, cache)) 140 OT::ItemVariationStore::destroy_cache (cache); 141 } 142 void clear_varStore_cache () const 143 { 144 retry: 145 auto *cache = varStore_cache.get_acquire (); 146 if (!cache) 147 return; 148 if (varStore_cache.cmpexch (cache, nullptr)) 149 OT::ItemVariationStore::destroy_cache (cache); 150 else 151 goto retry; 152 } 153 154 void clear () const 155 { 156 clear_advance_cache (); 157 clear_varStore_cache (); 158 } 159 160 } h, v; 161 162 struct origin_cache_t 163 { 164 mutable hb_atomic_t<hb_ot_font_origin_cache_t *> origin_cache; 165 mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache; 166 167 ~origin_cache_t () 168 { 169 clear (); 170 } 171 172 hb_ot_font_origin_cache_t *acquire_origin_cache () const 173 { 174 retry: 175 auto *cache = origin_cache.get_acquire (); 176 if (!cache) 177 { 178 cache = (hb_ot_font_origin_cache_t *) hb_malloc (sizeof (hb_ot_font_origin_cache_t)); 179 if (!cache) 180 return nullptr; 181 new (cache) hb_ot_font_origin_cache_t; 182 return cache; 183 } 184 if (origin_cache.cmpexch (cache, nullptr)) 185 return cache; 186 else 187 goto retry; 188 } 189 void release_origin_cache (hb_ot_font_origin_cache_t *cache) const 190 { 191 if (!cache) 192 return; 193 if (!origin_cache.cmpexch (nullptr, cache)) 194 hb_free (cache); 195 } 196 void clear_origin_cache () const 197 { 198 retry: 199 auto *cache = origin_cache.get_acquire (); 200 if (!cache) 201 return; 202 if (origin_cache.cmpexch (cache, nullptr)) 203 hb_free (cache); 204 else 205 goto retry; 206 } 207 208 OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const 209 { 210 retry: 211 auto *cache = varStore_cache.get_acquire (); 212 if (!cache) 213 return varStore.create_cache (); 214 if (varStore_cache.cmpexch (cache, nullptr)) 215 return cache; 216 else 217 goto retry; 218 } 219 void release_varStore_cache (OT::hb_scalar_cache_t *cache) const 220 { 221 if (!cache) 222 return; 223 if (!varStore_cache.cmpexch (nullptr, cache)) 224 OT::ItemVariationStore::destroy_cache (cache); 225 } 226 void clear_varStore_cache () const 227 { 228 retry: 229 auto *cache = varStore_cache.get_acquire (); 230 if (!cache) 231 return; 232 if (varStore_cache.cmpexch (cache, nullptr)) 233 OT::ItemVariationStore::destroy_cache (cache); 234 else 235 goto retry; 236 } 237 238 void clear () const 239 { 240 clear_origin_cache (); 241 clear_varStore_cache (); 242 } 243 } v_origin; 244 245 struct draw_cache_t 246 { 247 mutable hb_atomic_t<OT::hb_scalar_cache_t *> gvar_cache; 248 249 ~draw_cache_t () 250 { 251 clear (); 252 } 253 254 OT::hb_scalar_cache_t *acquire_gvar_cache (const OT::gvar_accelerator_t &gvar) const 255 { 256 retry: 257 auto *cache = gvar_cache.get_acquire (); 258 if (!cache) 259 return gvar.create_cache (); 260 if (gvar_cache.cmpexch (cache, nullptr)) 261 return cache; 262 else 263 goto retry; 264 } 265 void release_gvar_cache (OT::hb_scalar_cache_t *cache) const 266 { 267 if (!cache) 268 return; 269 if (!gvar_cache.cmpexch (nullptr, cache)) 270 OT::gvar_accelerator_t::destroy_cache (cache); 271 } 272 void clear_gvar_cache () const 273 { 274 retry: 275 auto *cache = gvar_cache.get_acquire (); 276 if (!cache) 277 return; 278 if (gvar_cache.cmpexch (cache, nullptr)) 279 OT::gvar_accelerator_t::destroy_cache (cache); 280 else 281 goto retry; 282 } 283 284 void clear () const 285 { 286 clear_gvar_cache (); 287 } 288 } draw; 289 290 void check_serial (hb_font_t *font) const 291 { 292 int font_serial = font->serial_coords.get_acquire (); 293 if (cached_serial.get_acquire () != font_serial) 294 { 295 /* These caches are dependent on scale and synthetic settings. 296 * Any change to the font invalidates them. */ 297 v_origin.clear (); 298 299 cached_serial.set_release (font_serial); 300 } 301 302 int font_serial_coords = font->serial_coords.get_acquire (); 303 if (cached_coords_serial.get_acquire () != font_serial_coords) 304 { 305 /* These caches are independent of scale or synthetic settings. 306 * Just variation changes will invalidate them. */ 307 h.clear (); 308 v.clear (); 309 draw.clear (); 310 311 cached_coords_serial.set_release (font_serial_coords); 312 } 313 } 314 }; 315 316 static hb_ot_font_t * 317 _hb_ot_font_create (hb_font_t *font) 318 { 319 hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t)); 320 if (unlikely (!ot_font)) 321 return nullptr; 322 323 ot_font->ot_face = &font->face->table; 324 325 return ot_font; 326 } 327 328 static void 329 _hb_ot_font_destroy (void *font_data) 330 { 331 hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data; 332 333 ot_font->~hb_ot_font_t (); 334 335 hb_free (ot_font); 336 } 337 338 static hb_bool_t 339 hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, 340 void *font_data, 341 hb_codepoint_t unicode, 342 hb_codepoint_t *glyph, 343 void *user_data HB_UNUSED) 344 { 345 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 346 const hb_ot_face_t *ot_face = ot_font->ot_face; 347 return ot_face->cmap->get_nominal_glyph (unicode, glyph); 348 } 349 350 static unsigned int 351 hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED, 352 void *font_data, 353 unsigned int count, 354 const hb_codepoint_t *first_unicode, 355 unsigned int unicode_stride, 356 hb_codepoint_t *first_glyph, 357 unsigned int glyph_stride, 358 void *user_data HB_UNUSED) 359 { 360 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 361 const hb_ot_face_t *ot_face = ot_font->ot_face; 362 return ot_face->cmap->get_nominal_glyphs (count, 363 first_unicode, unicode_stride, 364 first_glyph, glyph_stride); 365 } 366 367 static hb_bool_t 368 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, 369 void *font_data, 370 hb_codepoint_t unicode, 371 hb_codepoint_t variation_selector, 372 hb_codepoint_t *glyph, 373 void *user_data HB_UNUSED) 374 { 375 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 376 const hb_ot_face_t *ot_face = ot_font->ot_face; 377 return ot_face->cmap->get_variation_glyph (unicode, 378 variation_selector, glyph); 379 } 380 381 static void 382 hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, 383 unsigned count, 384 const hb_codepoint_t *first_glyph, 385 unsigned glyph_stride, 386 hb_position_t *first_advance, 387 unsigned advance_stride, 388 void *user_data HB_UNUSED) 389 { 390 // Duplicated in v_advances. Ugly. Keep in sync'ish. 391 392 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 393 const hb_ot_face_t *ot_face = ot_font->ot_face; 394 const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx; 395 396 if (unlikely (!hmtx.has_data ())) 397 { 398 hb_position_t advance = font->face->get_upem () / 2; 399 advance = font->em_scale_x (advance); 400 for (unsigned int i = 0; i < count; i++) 401 { 402 *first_advance = advance; 403 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 404 } 405 return; 406 } 407 408 #ifndef HB_NO_VAR 409 if (!font->has_nonzero_coords) 410 { 411 fallback: 412 #else 413 { 414 #endif 415 // Just plain htmx data. No need to cache. 416 for (unsigned int i = 0; i < count; i++) 417 { 418 *first_advance = font->em_scale_x (hmtx.get_advance_without_var_unscaled (*first_glyph)); 419 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 420 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 421 } 422 return; 423 } 424 425 #ifndef HB_NO_VAR 426 /* has_nonzero_coords. */ 427 428 ot_font->check_serial (font); 429 hb_ot_font_advance_cache_t *advance_cache = ot_font->h.acquire_advance_cache (); 430 if (!advance_cache) 431 { 432 // malloc failure. Just use the fallback non-variable path. 433 goto fallback; 434 } 435 436 /* If HVAR is present, use it.*/ 437 const OT::HVAR &HVAR = *hmtx.var_table; 438 if (HVAR.has_data ()) 439 { 440 const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore; 441 OT::hb_scalar_cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore); 442 443 for (unsigned int i = 0; i < count; i++) 444 { 445 hb_position_t v; 446 unsigned cv; 447 if (advance_cache->get (*first_glyph, &cv)) 448 v = cv; 449 else 450 { 451 v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache); 452 advance_cache->set (*first_glyph, v); 453 } 454 *first_advance = font->em_scale_x (v); 455 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 456 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 457 } 458 459 ot_font->h.release_varStore_cache (varStore_cache); 460 ot_font->h.release_advance_cache (advance_cache); 461 return; 462 } 463 464 const auto &gvar = *ot_face->gvar; 465 if (gvar.has_data ()) 466 { 467 const auto &glyf = *ot_face->glyf; 468 auto *scratch = glyf.acquire_scratch (); 469 if (unlikely (!scratch)) 470 { 471 ot_font->h.release_advance_cache (advance_cache); 472 goto fallback; 473 } 474 OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar); 475 476 for (unsigned int i = 0; i < count; i++) 477 { 478 hb_position_t v; 479 unsigned cv; 480 if (advance_cache->get (*first_glyph, &cv)) 481 v = cv; 482 else 483 { 484 v = glyf.get_advance_with_var_unscaled (*first_glyph, font, false, *scratch, gvar_cache); 485 advance_cache->set (*first_glyph, v); 486 } 487 *first_advance = font->em_scale_x (v); 488 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 489 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 490 } 491 492 ot_font->draw.release_gvar_cache (gvar_cache); 493 glyf.release_scratch (scratch); 494 ot_font->h.release_advance_cache (advance_cache); 495 return; 496 } 497 498 ot_font->h.release_advance_cache (advance_cache); 499 // No HVAR or GVAR. Just use the fallback non-variable path. 500 goto fallback; 501 #endif 502 } 503 504 #ifndef HB_NO_VERTICAL 505 static void 506 hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, 507 unsigned count, 508 const hb_codepoint_t *first_glyph, 509 unsigned glyph_stride, 510 hb_position_t *first_advance, 511 unsigned advance_stride, 512 void *user_data HB_UNUSED) 513 { 514 // Duplicated from h_advances. Ugly. Keep in sync'ish. 515 516 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 517 const hb_ot_face_t *ot_face = ot_font->ot_face; 518 const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx; 519 520 if (unlikely (!vmtx.has_data ())) 521 { 522 hb_font_extents_t font_extents; 523 font->get_h_extents_with_fallback (&font_extents); 524 hb_position_t advance = font_extents.descender - font_extents.ascender; 525 for (unsigned int i = 0; i < count; i++) 526 { 527 *first_advance = advance; 528 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 529 } 530 return; 531 } 532 533 #ifndef HB_NO_VAR 534 if (!font->has_nonzero_coords) 535 { 536 fallback: 537 #else 538 { 539 #endif 540 // Just plain vtmx data. No need to cache. 541 for (unsigned int i = 0; i < count; i++) 542 { 543 *first_advance = font->em_scale_y (- (int) vmtx.get_advance_without_var_unscaled (*first_glyph)); 544 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 545 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 546 } 547 return; 548 } 549 550 #ifndef HB_NO_VAR 551 /* has_nonzero_coords. */ 552 553 ot_font->check_serial (font); 554 hb_ot_font_advance_cache_t *advance_cache = ot_font->v.acquire_advance_cache (); 555 if (!advance_cache) 556 { 557 // malloc failure. Just use the fallback non-variable path. 558 goto fallback; 559 } 560 561 /* If VVAR is present, use it.*/ 562 const OT::VVAR &VVAR = *vmtx.var_table; 563 if (VVAR.has_data ()) 564 { 565 const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore; 566 OT::hb_scalar_cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore); 567 568 for (unsigned int i = 0; i < count; i++) 569 { 570 hb_position_t v; 571 unsigned cv; 572 if (advance_cache->get (*first_glyph, &cv)) 573 v = cv; 574 else 575 { 576 v = vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache); 577 advance_cache->set (*first_glyph, v); 578 } 579 *first_advance = font->em_scale_y (- (int) v); 580 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 581 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 582 } 583 584 ot_font->v.release_varStore_cache (varStore_cache); 585 ot_font->v.release_advance_cache (advance_cache); 586 return; 587 } 588 589 const auto &gvar = *ot_face->gvar; 590 if (gvar.has_data ()) 591 { 592 const auto &glyf = *ot_face->glyf; 593 auto *scratch = glyf.acquire_scratch (); 594 if (unlikely (!scratch)) 595 { 596 ot_font->v.release_advance_cache (advance_cache); 597 goto fallback; 598 } 599 OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar); 600 601 for (unsigned int i = 0; i < count; i++) 602 { 603 hb_position_t v; 604 unsigned cv; 605 if (advance_cache->get (*first_glyph, &cv)) 606 v = cv; 607 else 608 { 609 v = glyf.get_advance_with_var_unscaled (*first_glyph, font, true, *scratch, gvar_cache); 610 advance_cache->set (*first_glyph, v); 611 } 612 *first_advance = font->em_scale_y (- (int) v); 613 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 614 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 615 } 616 617 ot_font->draw.release_gvar_cache (gvar_cache); 618 glyf.release_scratch (scratch); 619 ot_font->v.release_advance_cache (advance_cache); 620 return; 621 } 622 623 ot_font->v.release_advance_cache (advance_cache); 624 // No VVAR or GVAR. Just use the fallback non-variable path. 625 goto fallback; 626 #endif 627 } 628 #endif 629 630 #ifndef HB_NO_VERTICAL 631 HB_HOT 632 static hb_bool_t 633 hb_ot_get_glyph_v_origins (hb_font_t *font, 634 void *font_data, 635 unsigned int count, 636 const hb_codepoint_t *first_glyph, 637 unsigned glyph_stride, 638 hb_position_t *first_x, 639 unsigned x_stride, 640 hb_position_t *first_y, 641 unsigned y_stride, 642 void *user_data HB_UNUSED) 643 { 644 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 645 const hb_ot_face_t *ot_face = ot_font->ot_face; 646 647 /* First, set all the x values to half the advance width. */ 648 font->get_glyph_h_advances (count, 649 first_glyph, glyph_stride, 650 first_x, x_stride); 651 for (unsigned i = 0; i < count; i++) 652 { 653 *first_x /= 2; 654 first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride); 655 } 656 657 /* The vertical origin business is messy... 658 * 659 * We allocate the cache, then have various code paths that use the cache. 660 * Each one is responsible to free it before returning. 661 */ 662 hb_ot_font_origin_cache_t *origin_cache = ot_font->v_origin.acquire_origin_cache (); 663 664 /* If there is VORG, always use it. It uses VVAR for variations if necessary. */ 665 const OT::VORG &VORG = *ot_face->VORG; 666 if (origin_cache && VORG.has_data ()) 667 { 668 #ifndef HB_NO_VAR 669 if (!font->has_nonzero_coords) 670 #endif 671 { 672 for (unsigned i = 0; i < count; i++) 673 { 674 hb_position_t origin; 675 unsigned cv; 676 if (origin_cache->get (*first_glyph, &cv)) 677 origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); 678 else 679 { 680 origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph)); 681 origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin); 682 } 683 684 *first_y = origin; 685 686 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 687 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride); 688 } 689 } 690 #ifndef HB_NO_VAR 691 else 692 { 693 const OT::VVAR &VVAR = *ot_face->vmtx->var_table; 694 const auto &varStore = &VVAR + VVAR.varStore; 695 auto *varStore_cache = ot_font->v_origin.acquire_varStore_cache (varStore); 696 for (unsigned i = 0; i < count; i++) 697 { 698 hb_position_t origin; 699 unsigned cv; 700 if (origin_cache->get (*first_glyph, &cv)) 701 origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); 702 else 703 { 704 origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) + 705 VVAR.get_vorg_delta_unscaled (*first_glyph, 706 font->coords, font->num_coords, 707 varStore_cache)); 708 origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin); 709 } 710 711 *first_y = origin; 712 713 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 714 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride); 715 } 716 ot_font->v_origin.release_varStore_cache (varStore_cache); 717 } 718 #endif 719 ot_font->v_origin.release_origin_cache (origin_cache); 720 return true; 721 } 722 723 /* If and only if `vmtx` is present and it's a `glyf` font, 724 * we use the top phantom point, deduced from vmtx,glyf[,gvar]. */ 725 const auto &vmtx = *ot_face->vmtx; 726 const auto &glyf = *ot_face->glyf; 727 if (origin_cache && vmtx.has_data() && glyf.has_data ()) 728 { 729 auto *scratch = glyf.acquire_scratch (); 730 if (unlikely (!scratch)) 731 { 732 ot_font->v_origin.release_origin_cache (origin_cache); 733 return false; 734 } 735 OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ? 736 ot_font->draw.acquire_gvar_cache (*ot_face->gvar) : 737 nullptr; 738 739 for (unsigned i = 0; i < count; i++) 740 { 741 hb_position_t origin; 742 unsigned cv; 743 if (origin_cache->get (*first_glyph, &cv)) 744 origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); 745 else 746 { 747 origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache)); 748 origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin); 749 } 750 751 *first_y = origin; 752 753 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 754 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride); 755 } 756 757 if (gvar_cache) 758 ot_font->draw.release_gvar_cache (gvar_cache); 759 glyf.release_scratch (scratch); 760 ot_font->v_origin.release_origin_cache (origin_cache); 761 return true; 762 } 763 764 /* Otherwise, use glyph extents to center the glyph vertically. 765 * If getting glyph extents failed, just use the font ascender. */ 766 if (origin_cache && font->has_glyph_extents_func ()) 767 { 768 hb_font_extents_t font_extents; 769 font->get_h_extents_with_fallback (&font_extents); 770 hb_position_t font_advance = font_extents.ascender - font_extents.descender; 771 772 for (unsigned i = 0; i < count; i++) 773 { 774 hb_position_t origin; 775 unsigned cv; 776 777 if (origin_cache->get (*first_glyph, &cv)) 778 origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); 779 else 780 { 781 hb_glyph_extents_t extents = {0}; 782 if (likely (font->get_glyph_extents (*first_glyph, &extents))) 783 origin = extents.y_bearing + ((font_advance - -extents.height) >> 1); 784 else 785 origin = font_extents.ascender; 786 787 origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin); 788 } 789 790 *first_y = origin; 791 792 first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride); 793 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride); 794 } 795 } 796 797 ot_font->v_origin.release_origin_cache (origin_cache); 798 return true; 799 } 800 #endif 801 802 static hb_bool_t 803 hb_ot_get_glyph_extents (hb_font_t *font, 804 void *font_data, 805 hb_codepoint_t glyph, 806 hb_glyph_extents_t *extents, 807 void *user_data HB_UNUSED) 808 { 809 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 810 const hb_ot_face_t *ot_face = ot_font->ot_face; 811 812 #if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR) 813 if (ot_face->sbix->get_extents (font, glyph, extents)) return true; 814 if (ot_face->CBDT->get_extents (font, glyph, extents)) return true; 815 #endif 816 #if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT) 817 if (ot_face->COLR->get_extents (font, glyph, extents)) return true; 818 #endif 819 #ifndef HB_NO_VAR_COMPOSITES 820 if (ot_face->VARC->get_extents (font, glyph, extents)) return true; 821 #endif 822 if (ot_face->glyf->get_extents (font, glyph, extents)) return true; 823 #ifndef HB_NO_OT_FONT_CFF 824 if (ot_face->cff2->get_extents (font, glyph, extents)) return true; 825 if (ot_face->cff1->get_extents (font, glyph, extents)) return true; 826 #endif 827 828 return false; 829 } 830 831 #ifndef HB_NO_OT_FONT_GLYPH_NAMES 832 static hb_bool_t 833 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, 834 void *font_data, 835 hb_codepoint_t glyph, 836 char *name, unsigned int size, 837 void *user_data HB_UNUSED) 838 { 839 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 840 const hb_ot_face_t *ot_face = ot_font->ot_face; 841 842 if (ot_face->post->get_glyph_name (glyph, name, size)) return true; 843 #ifndef HB_NO_OT_FONT_CFF 844 if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true; 845 #endif 846 return false; 847 } 848 static hb_bool_t 849 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, 850 void *font_data, 851 const char *name, int len, 852 hb_codepoint_t *glyph, 853 void *user_data HB_UNUSED) 854 { 855 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 856 const hb_ot_face_t *ot_face = ot_font->ot_face; 857 858 if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true; 859 #ifndef HB_NO_OT_FONT_CFF 860 if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true; 861 #endif 862 return false; 863 } 864 #endif 865 866 static hb_bool_t 867 hb_ot_get_font_h_extents (hb_font_t *font, 868 void *font_data HB_UNUSED, 869 hb_font_extents_t *metrics, 870 void *user_data HB_UNUSED) 871 { 872 return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) && 873 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) && 874 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap); 875 } 876 877 #ifndef HB_NO_VERTICAL 878 static hb_bool_t 879 hb_ot_get_font_v_extents (hb_font_t *font, 880 void *font_data HB_UNUSED, 881 hb_font_extents_t *metrics, 882 void *user_data HB_UNUSED) 883 { 884 return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_ASCENDER, &metrics->ascender) && 885 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_DESCENDER, &metrics->descender) && 886 _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap); 887 } 888 #endif 889 890 #ifndef HB_NO_DRAW 891 static hb_bool_t 892 hb_ot_draw_glyph_or_fail (hb_font_t *font, 893 void *font_data HB_UNUSED, 894 hb_codepoint_t glyph, 895 hb_draw_funcs_t *draw_funcs, void *draw_data, 896 void *user_data) 897 { 898 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 899 hb_draw_session_t draw_session {draw_funcs, draw_data}; 900 bool ret = false; 901 902 OT::hb_scalar_cache_t *gvar_cache = nullptr; 903 if (font->num_coords) 904 { 905 ot_font->check_serial (font); 906 gvar_cache = ot_font->draw.acquire_gvar_cache (*ot_font->ot_face->gvar); 907 } 908 909 #ifndef HB_NO_VAR_COMPOSITES 910 if (font->face->table.VARC->get_path (font, glyph, draw_session)) { ret = true; goto done; } 911 #endif 912 // Keep the following in synch with VARC::get_path_at() 913 if (font->face->table.glyf->get_path (font, glyph, draw_session, gvar_cache)) { ret = true; goto done; } 914 915 #ifndef HB_NO_CFF 916 if (font->face->table.cff2->get_path (font, glyph, draw_session)) { ret = true; goto done; } 917 if (font->face->table.cff1->get_path (font, glyph, draw_session)) { ret = true; goto done; } 918 #endif 919 920 done: 921 922 ot_font->draw.release_gvar_cache (gvar_cache); 923 924 return ret; 925 } 926 #endif 927 928 #ifndef HB_NO_PAINT 929 static hb_bool_t 930 hb_ot_paint_glyph_or_fail (hb_font_t *font, 931 void *font_data, 932 hb_codepoint_t glyph, 933 hb_paint_funcs_t *paint_funcs, void *paint_data, 934 unsigned int palette, 935 hb_color_t foreground, 936 void *user_data) 937 { 938 #ifndef HB_NO_COLOR 939 if (font->face->table.COLR->paint_glyph (font, glyph, paint_funcs, paint_data, palette, foreground)) return true; 940 if (font->face->table.SVG->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; 941 #ifndef HB_NO_OT_FONT_BITMAP 942 if (font->face->table.CBDT->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; 943 if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return true; 944 #endif 945 #endif 946 return false; 947 } 948 #endif 949 950 static inline void free_static_ot_funcs (); 951 952 static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t> 953 { 954 static hb_font_funcs_t *create () 955 { 956 hb_font_funcs_t *funcs = hb_font_funcs_create (); 957 958 hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); 959 hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr); 960 hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); 961 962 hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); 963 hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr); 964 965 #ifndef HB_NO_VERTICAL 966 hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); 967 hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); 968 hb_font_funcs_set_glyph_v_origins_func (funcs, hb_ot_get_glyph_v_origins, nullptr, nullptr); 969 #endif 970 971 #ifndef HB_NO_DRAW 972 hb_font_funcs_set_draw_glyph_or_fail_func (funcs, hb_ot_draw_glyph_or_fail, nullptr, nullptr); 973 #endif 974 975 #ifndef HB_NO_PAINT 976 hb_font_funcs_set_paint_glyph_or_fail_func (funcs, hb_ot_paint_glyph_or_fail, nullptr, nullptr); 977 #endif 978 979 hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); 980 //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); 981 982 #ifndef HB_NO_OT_FONT_GLYPH_NAMES 983 hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); 984 hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr); 985 #endif 986 987 hb_font_funcs_make_immutable (funcs); 988 989 hb_atexit (free_static_ot_funcs); 990 991 return funcs; 992 } 993 } static_ot_funcs; 994 995 static inline 996 void free_static_ot_funcs () 997 { 998 static_ot_funcs.free_instance (); 999 } 1000 1001 static hb_font_funcs_t * 1002 _hb_ot_get_font_funcs () 1003 { 1004 return static_ot_funcs.get_unconst (); 1005 } 1006 1007 1008 /** 1009 * hb_ot_font_set_funcs: 1010 * @font: #hb_font_t to work upon 1011 * 1012 * Sets the font functions to use when working with @font to 1013 * the HarfBuzz's native implementation. This is the default 1014 * for fonts newly created. 1015 * 1016 * Since: 0.9.28 1017 **/ 1018 void 1019 hb_ot_font_set_funcs (hb_font_t *font) 1020 { 1021 hb_ot_font_t *ot_font = _hb_ot_font_create (font); 1022 if (unlikely (!ot_font)) 1023 return; 1024 1025 hb_font_set_funcs (font, 1026 _hb_ot_get_font_funcs (), 1027 ot_font, 1028 _hb_ot_font_destroy); 1029 } 1030 1031 #endif