hb-font.hh (33559B)
1 /* 2 * Copyright © 2009 Red Hat, Inc. 3 * Copyright © 2011 Google, Inc. 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Red Hat Author(s): Behdad Esfahbod 26 * Google Author(s): Behdad Esfahbod 27 */ 28 29 #ifndef HB_FONT_HH 30 #define HB_FONT_HH 31 32 #include "hb.hh" 33 34 #include "hb-face.hh" 35 #include "hb-atomic.hh" 36 #include "hb-draw.hh" 37 #include "hb-paint-extents.hh" 38 #include "hb-shaper.hh" 39 #include "hb-outline.hh" 40 41 42 /* 43 * hb_font_funcs_t 44 */ 45 46 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 47 HB_FONT_FUNC_IMPLEMENT (get_,font_h_extents) \ 48 HB_FONT_FUNC_IMPLEMENT (get_,font_v_extents) \ 49 HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyph) \ 50 HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyphs) \ 51 HB_FONT_FUNC_IMPLEMENT (get_,variation_glyph) \ 52 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advance) \ 53 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advance) \ 54 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advances) \ 55 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \ 56 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \ 57 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \ 58 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origins) \ 59 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origins) \ 60 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \ 61 HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \ 62 HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \ 63 HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \ 64 HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \ 65 HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \ 66 HB_FONT_FUNC_IMPLEMENT (,draw_glyph_or_fail) \ 67 HB_FONT_FUNC_IMPLEMENT (,paint_glyph_or_fail) \ 68 /* ^--- Add new callbacks here */ 69 70 struct hb_font_funcs_t 71 { 72 hb_object_header_t header; 73 74 struct { 75 #define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name; 76 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 77 #undef HB_FONT_FUNC_IMPLEMENT 78 } *user_data; 79 80 struct { 81 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name; 82 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 83 #undef HB_FONT_FUNC_IMPLEMENT 84 } *destroy; 85 86 /* Don't access these directly. Call font->get_*() instead. */ 87 union get_t { 88 struct get_funcs_t { 89 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name; 90 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 91 #undef HB_FONT_FUNC_IMPLEMENT 92 } f; 93 void (*array[0 94 #define HB_FONT_FUNC_IMPLEMENT(get_,name) +1 95 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 96 #undef HB_FONT_FUNC_IMPLEMENT 97 ]) (); 98 } get; 99 }; 100 DECLARE_NULL_INSTANCE (hb_font_funcs_t); 101 102 103 /* 104 * hb_font_t 105 */ 106 107 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font); 108 #include "hb-shaper-list.hh" 109 #undef HB_SHAPER_IMPLEMENT 110 111 struct hb_font_t 112 { 113 hb_object_header_t header; 114 hb_atomic_t<unsigned> serial; 115 hb_atomic_t<unsigned> serial_coords; 116 117 hb_font_t *parent; 118 hb_face_t *face; 119 120 int32_t x_scale; 121 int32_t y_scale; 122 123 bool is_synthetic; 124 125 float x_embolden; 126 float y_embolden; 127 bool embolden_in_place; 128 int32_t x_strength; /* x_embolden, in scaled units. */ 129 int32_t y_strength; /* y_embolden, in scaled units. */ 130 131 float slant; 132 float slant_xy; 133 134 float x_multf; 135 float y_multf; 136 int64_t x_mult; 137 int64_t y_mult; 138 139 unsigned int x_ppem; 140 unsigned int y_ppem; 141 142 float ptem; 143 144 /* Font variation coordinates. */ 145 unsigned int instance_index; 146 bool has_nonzero_coords; 147 unsigned int num_coords; 148 int *coords; 149 float *design_coords; 150 151 hb_font_funcs_t *klass; 152 void *user_data; 153 hb_destroy_func_t destroy; 154 155 hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */ 156 157 158 /* Convert from font-space to user-space */ 159 int64_t dir_mult (hb_direction_t direction) 160 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; } 161 hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); } 162 hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); } 163 hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); } 164 hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); } 165 float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); } 166 float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); } 167 float em_fscalef_x (float v) { return em_fmultf (v, x_multf); } 168 float em_fscalef_y (float v) { return em_fmultf (v, y_multf); } 169 hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) 170 { return em_mult (v, dir_mult (direction)); } 171 172 /* Convert from parent-font user-space to our user-space */ 173 hb_position_t parent_scale_x_distance (hb_position_t v) 174 { 175 if (unlikely (parent && parent->x_scale != x_scale)) 176 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 177 return v; 178 } 179 hb_position_t parent_scale_y_distance (hb_position_t v) 180 { 181 if (unlikely (parent && parent->y_scale != y_scale)) 182 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); 183 return v; 184 } 185 hb_position_t parent_scale_x_position (hb_position_t v) 186 { return parent_scale_x_distance (v); } 187 hb_position_t parent_scale_y_position (hb_position_t v) 188 { return parent_scale_y_distance (v); } 189 190 void parent_scale_distance (hb_position_t *x, hb_position_t *y) 191 { 192 *x = parent_scale_x_distance (*x); 193 *y = parent_scale_y_distance (*y); 194 } 195 void parent_scale_position (hb_position_t *x, hb_position_t *y) 196 { 197 *x = parent_scale_x_position (*x); 198 *y = parent_scale_y_position (*y); 199 } 200 201 void scale_glyph_extents (hb_glyph_extents_t *extents) 202 { 203 float x1 = em_scale_x (extents->x_bearing); 204 float y1 = em_scale_y (extents->y_bearing); 205 float x2 = em_scale_x (extents->x_bearing + extents->width); 206 float y2 = em_scale_y (extents->y_bearing + extents->height); 207 208 extents->x_bearing = roundf (x1); 209 extents->y_bearing = roundf (y1); 210 extents->width = roundf (x2) - extents->x_bearing; 211 extents->height = roundf (y2) - extents->y_bearing; 212 } 213 214 void synthetic_glyph_extents (hb_glyph_extents_t *extents) 215 { 216 /* Slant. */ 217 if (slant_xy) 218 { 219 hb_position_t x1 = extents->x_bearing; 220 hb_position_t y1 = extents->y_bearing; 221 hb_position_t x2 = extents->x_bearing + extents->width; 222 hb_position_t y2 = extents->y_bearing + extents->height; 223 224 x1 += floorf (hb_min (y1 * slant_xy, y2 * slant_xy)); 225 x2 += ceilf (hb_max (y1 * slant_xy, y2 * slant_xy)); 226 227 extents->x_bearing = x1; 228 extents->width = x2 - extents->x_bearing; 229 } 230 231 /* Embolden. */ 232 if (x_strength || y_strength) 233 { 234 /* Y */ 235 int y_shift = y_strength; 236 if (y_scale < 0) y_shift = -y_shift; 237 extents->y_bearing += y_shift; 238 extents->height -= y_shift; 239 240 /* X */ 241 int x_shift = x_strength; 242 if (x_scale < 0) x_shift = -x_shift; 243 if (embolden_in_place) 244 extents->x_bearing -= x_shift / 2; 245 extents->width += x_shift; 246 } 247 } 248 249 250 /* Public getters */ 251 252 HB_INTERNAL bool has_func (unsigned int i); 253 HB_INTERNAL bool has_func_set (unsigned int i); 254 255 /* has_* ... */ 256 #define HB_FONT_FUNC_IMPLEMENT(get_,name) \ 257 bool \ 258 has_##name##_func () \ 259 { \ 260 hb_font_funcs_t *funcs = this->klass; \ 261 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 262 return has_func (i); \ 263 } \ 264 bool \ 265 has_##name##_func_set () \ 266 { \ 267 hb_font_funcs_t *funcs = this->klass; \ 268 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 269 return has_func_set (i); \ 270 } 271 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 272 #undef HB_FONT_FUNC_IMPLEMENT 273 274 hb_bool_t get_font_h_extents (hb_font_extents_t *extents, 275 bool synthetic = true) 276 { 277 hb_memset (extents, 0, sizeof (*extents)); 278 bool ret = klass->get.f.font_h_extents (this, user_data, 279 extents, 280 !klass->user_data ? nullptr : klass->user_data->font_h_extents); 281 282 if (synthetic && ret) 283 { 284 /* Embolden */ 285 int y_shift = y_scale < 0 ? -y_strength : y_strength; 286 extents->ascender += y_shift; 287 } 288 289 return ret; 290 } 291 hb_bool_t get_font_v_extents (hb_font_extents_t *extents, 292 bool synthetic = true) 293 { 294 hb_memset (extents, 0, sizeof (*extents)); 295 bool ret = klass->get.f.font_v_extents (this, user_data, 296 extents, 297 !klass->user_data ? nullptr : klass->user_data->font_v_extents); 298 299 if (synthetic && ret) 300 { 301 /* Embolden */ 302 int x_shift = x_scale < 0 ? -x_strength : x_strength; 303 if (embolden_in_place) 304 { 305 extents->ascender += x_shift / 2; 306 extents->descender -= x_shift - x_shift / 2; 307 } 308 else 309 extents->ascender += x_shift; 310 } 311 312 return ret; 313 } 314 315 bool has_glyph (hb_codepoint_t unicode) 316 { 317 hb_codepoint_t glyph; 318 return get_nominal_glyph (unicode, &glyph); 319 } 320 321 hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, 322 hb_codepoint_t *glyph, 323 hb_codepoint_t not_found = 0) 324 { 325 *glyph = not_found; 326 return klass->get.f.nominal_glyph (this, user_data, 327 unicode, glyph, 328 !klass->user_data ? nullptr : klass->user_data->nominal_glyph); 329 } 330 unsigned int get_nominal_glyphs (unsigned int count, 331 const hb_codepoint_t *first_unicode, 332 unsigned int unicode_stride, 333 hb_codepoint_t *first_glyph, 334 unsigned int glyph_stride) 335 { 336 return klass->get.f.nominal_glyphs (this, user_data, 337 count, 338 first_unicode, unicode_stride, 339 first_glyph, glyph_stride, 340 !klass->user_data ? nullptr : klass->user_data->nominal_glyphs); 341 } 342 343 hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 344 hb_codepoint_t *glyph, 345 hb_codepoint_t not_found = 0) 346 { 347 *glyph = not_found; 348 return klass->get.f.variation_glyph (this, user_data, 349 unicode, variation_selector, glyph, 350 !klass->user_data ? nullptr : klass->user_data->variation_glyph); 351 } 352 353 hb_position_t get_glyph_h_advance (hb_codepoint_t glyph, 354 bool synthetic = true) 355 { 356 hb_position_t advance = klass->get.f.glyph_h_advance (this, user_data, 357 glyph, 358 !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); 359 360 if (synthetic && x_strength && !embolden_in_place) 361 { 362 /* Embolden */ 363 hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; 364 advance += advance ? strength : 0; 365 } 366 367 return advance; 368 } 369 370 hb_position_t get_glyph_v_advance (hb_codepoint_t glyph, 371 bool synthetic = true) 372 { 373 hb_position_t advance = klass->get.f.glyph_v_advance (this, user_data, 374 glyph, 375 !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); 376 377 if (synthetic && y_strength && !embolden_in_place) 378 { 379 /* Embolden */ 380 hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; 381 advance += advance ? strength : 0; 382 } 383 384 return advance; 385 } 386 387 void get_glyph_h_advances (unsigned int count, 388 const hb_codepoint_t *first_glyph, 389 unsigned int glyph_stride, 390 hb_position_t *first_advance, 391 unsigned int advance_stride, 392 bool synthetic = true) 393 { 394 klass->get.f.glyph_h_advances (this, user_data, 395 count, 396 first_glyph, glyph_stride, 397 first_advance, advance_stride, 398 !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); 399 400 if (synthetic && x_strength && !embolden_in_place) 401 { 402 /* Embolden */ 403 hb_position_t strength = x_scale >= 0 ? x_strength : -x_strength; 404 for (unsigned int i = 0; i < count; i++) 405 { 406 *first_advance += *first_advance ? strength : 0; 407 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 408 } 409 } 410 } 411 412 void get_glyph_v_advances (unsigned int count, 413 const hb_codepoint_t *first_glyph, 414 unsigned int glyph_stride, 415 hb_position_t *first_advance, 416 unsigned int advance_stride, 417 bool synthetic = true) 418 { 419 klass->get.f.glyph_v_advances (this, user_data, 420 count, 421 first_glyph, glyph_stride, 422 first_advance, advance_stride, 423 !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); 424 425 if (synthetic && y_strength && !embolden_in_place) 426 { 427 /* Embolden */ 428 hb_position_t strength = y_scale >= 0 ? y_strength : -y_strength; 429 for (unsigned int i = 0; i < count; i++) 430 { 431 *first_advance += *first_advance ? strength : 0; 432 first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride); 433 } 434 } 435 } 436 437 hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 438 hb_position_t *x, hb_position_t *y, 439 bool synthetic = true) 440 { 441 *x = *y = 0; 442 bool ret = klass->get.f.glyph_h_origin (this, user_data, 443 glyph, x, y, 444 !klass->user_data ? nullptr : klass->user_data->glyph_h_origin); 445 446 if (synthetic && ret) 447 { 448 /* Slant is ignored as it does not affect glyph origin */ 449 450 /* Embolden */ 451 if (!embolden_in_place) 452 { 453 *x += x_scale < 0 ? -x_strength : x_strength; 454 *y += y_scale < 0 ? -y_strength : y_strength; 455 } 456 } 457 458 return ret; 459 } 460 461 hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 462 hb_position_t *x, hb_position_t *y, 463 bool synthetic = true) 464 { 465 *x = *y = 0; 466 bool ret = klass->get.f.glyph_v_origin (this, user_data, 467 glyph, x, y, 468 !klass->user_data ? nullptr : klass->user_data->glyph_v_origin); 469 470 if (synthetic && ret) 471 { 472 /* Slant is ignored as it does not affect glyph origin */ 473 474 /* Embolden */ 475 if (!embolden_in_place) 476 { 477 *x += x_scale < 0 ? -x_strength : x_strength; 478 *y += y_scale < 0 ? -y_strength : y_strength; 479 } 480 } 481 482 return ret; 483 } 484 485 hb_bool_t get_glyph_h_origins (unsigned int count, 486 const hb_codepoint_t *first_glyph, 487 unsigned int glyph_stride, 488 hb_position_t *first_x, 489 unsigned int x_stride, 490 hb_position_t *first_y, 491 unsigned int y_stride, 492 bool synthetic = true) 493 494 { 495 bool ret = klass->get.f.glyph_h_origins (this, user_data, 496 count, 497 first_glyph, glyph_stride, 498 first_x, x_stride, first_y, y_stride, 499 !klass->user_data ? nullptr : klass->user_data->glyph_h_origins); 500 501 if (synthetic && ret) 502 { 503 hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength; 504 hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength; 505 for (unsigned i = 0; i < count; i++) 506 { 507 /* Slant is ignored as it does not affect glyph origin */ 508 509 /* Embolden */ 510 if (!embolden_in_place) 511 { 512 *first_x += x_shift; 513 *first_y += y_shift; 514 } 515 first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride); 516 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride); 517 } 518 } 519 520 return ret; 521 } 522 523 hb_bool_t get_glyph_v_origins (unsigned int count, 524 const hb_codepoint_t *first_glyph, 525 unsigned int glyph_stride, 526 hb_position_t *first_x, 527 unsigned int x_stride, 528 hb_position_t *first_y, 529 unsigned int y_stride, 530 bool synthetic = true) 531 532 { 533 bool ret = klass->get.f.glyph_v_origins (this, user_data, 534 count, 535 first_glyph, glyph_stride, 536 first_x, x_stride, first_y, y_stride, 537 !klass->user_data ? nullptr : klass->user_data->glyph_v_origins); 538 539 if (synthetic && is_synthetic && ret) 540 { 541 hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength; 542 hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength; 543 for (unsigned i = 0; i < count; i++) 544 { 545 /* Slant is ignored as it does not affect glyph origin */ 546 547 /* Embolden */ 548 if (!embolden_in_place) 549 { 550 *first_x += x_shift; 551 *first_y += y_shift; 552 } 553 first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride); 554 first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride); 555 } 556 } 557 558 return ret; 559 } 560 561 hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, 562 hb_codepoint_t right_glyph) 563 { 564 #ifdef HB_DISABLE_DEPRECATED 565 return 0; 566 #else 567 return klass->get.f.glyph_h_kerning (this, user_data, 568 left_glyph, right_glyph, 569 !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning); 570 #endif 571 } 572 573 hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, 574 hb_codepoint_t bottom_glyph) 575 { 576 #ifdef HB_DISABLE_DEPRECATED 577 return 0; 578 #else 579 return klass->get.f.glyph_v_kerning (this, user_data, 580 top_glyph, bottom_glyph, 581 !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning); 582 #endif 583 } 584 585 hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 586 hb_glyph_extents_t *extents, 587 bool synthetic = true) 588 { 589 hb_memset (extents, 0, sizeof (*extents)); 590 591 /* This is rather messy, but necessary. */ 592 593 if (!synthetic) 594 { 595 return klass->get.f.glyph_extents (this, user_data, 596 glyph, 597 extents, 598 !klass->user_data ? nullptr : klass->user_data->glyph_extents); 599 } 600 if (!is_synthetic && 601 klass->get.f.glyph_extents (this, user_data, 602 glyph, 603 extents, 604 !klass->user_data ? nullptr : klass->user_data->glyph_extents)) 605 return true; 606 607 /* Try getting extents from paint(), then draw(), *then* get_extents() 608 * and apply synthetic settings in the last case. */ 609 610 #ifndef HB_NO_PAINT 611 hb_paint_extents_context_t paint_extents; 612 if (paint_glyph_or_fail (glyph, 613 hb_paint_extents_get_funcs (), &paint_extents, 614 0, 0)) 615 { 616 *extents = paint_extents.get_extents ().to_glyph_extents (); 617 return true; 618 } 619 #endif 620 621 #ifndef HB_NO_DRAW 622 hb_extents_t<> draw_extents; 623 if (draw_glyph_or_fail (glyph, 624 hb_draw_extents_get_funcs (), &draw_extents)) 625 { 626 *extents = draw_extents.to_glyph_extents (); 627 return true; 628 } 629 #endif 630 631 bool ret = klass->get.f.glyph_extents (this, user_data, 632 glyph, 633 extents, 634 !klass->user_data ? nullptr : klass->user_data->glyph_extents); 635 if (ret) 636 synthetic_glyph_extents (extents); 637 638 return ret; 639 } 640 641 hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 642 hb_position_t *x, hb_position_t *y, 643 bool synthetic = true) 644 { 645 *x = *y = 0; 646 bool ret = klass->get.f.glyph_contour_point (this, user_data, 647 glyph, point_index, 648 x, y, 649 !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); 650 651 if (synthetic && ret) 652 { 653 /* Slant */ 654 if (slant_xy) 655 *x += roundf (*y * slant_xy); 656 657 /* Embolden */ 658 if (!embolden_in_place) 659 { 660 int x_shift = x_scale < 0 ? -x_strength : x_strength; 661 *x += x_shift; 662 } 663 } 664 665 return ret; 666 } 667 668 hb_bool_t get_glyph_name (hb_codepoint_t glyph, 669 char *name, unsigned int size) 670 { 671 if (size) *name = '\0'; 672 return klass->get.f.glyph_name (this, user_data, 673 glyph, 674 name, size, 675 !klass->user_data ? nullptr : klass->user_data->glyph_name); 676 } 677 678 hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 679 hb_codepoint_t *glyph) 680 { 681 *glyph = 0; 682 if (len == -1) len = strlen (name); 683 return klass->get.f.glyph_from_name (this, user_data, 684 name, len, 685 glyph, 686 !klass->user_data ? nullptr : klass->user_data->glyph_from_name); 687 } 688 689 bool draw_glyph_or_fail (hb_codepoint_t glyph, 690 hb_draw_funcs_t *draw_funcs, void *draw_data, 691 bool synthetic = true) 692 { 693 #ifndef HB_NO_DRAW 694 #ifndef HB_NO_OUTLINE 695 bool embolden = x_strength || y_strength; 696 bool slanted = slant_xy; 697 synthetic = synthetic && (embolden || slanted); 698 #else 699 synthetic = false; 700 #endif 701 702 if (!synthetic) 703 { 704 return klass->get.f.draw_glyph_or_fail (this, user_data, 705 glyph, 706 draw_funcs, draw_data, 707 !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail); 708 } 709 710 #ifndef HB_NO_OUTLINE 711 712 hb_outline_t outline; 713 if (!klass->get.f.draw_glyph_or_fail (this, user_data, 714 glyph, 715 hb_outline_recording_pen_get_funcs (), &outline, 716 !klass->user_data ? nullptr : klass->user_data->draw_glyph_or_fail)) 717 return false; 718 719 // Slant before embolden; produces nicer results. 720 721 if (slanted) 722 { 723 hb_position_t xo = 0, yo = 0; 724 get_glyph_h_origin (glyph, &xo, &yo, false); 725 outline.translate (-xo, -yo); 726 outline.slant (slant_xy); 727 outline.translate (xo, yo); 728 } 729 730 if (embolden) 731 { 732 float x_shift = embolden_in_place ? 0 : (float) x_strength / 2; 733 float y_shift = (float) y_strength / 2; 734 if (x_scale < 0) x_shift = -x_shift; 735 if (y_scale < 0) y_shift = -y_shift; 736 outline.embolden (x_strength, y_strength, x_shift, y_shift); 737 } 738 739 outline.replay (draw_funcs, draw_data); 740 741 return true; 742 #endif 743 #endif 744 return false; 745 } 746 747 bool paint_glyph_or_fail (hb_codepoint_t glyph, 748 hb_paint_funcs_t *paint_funcs, void *paint_data, 749 unsigned int palette, 750 hb_color_t foreground, 751 bool synthetic = true) 752 { 753 #ifndef HB_NO_PAINT 754 /* Slant */ 755 if (synthetic && slant_xy) 756 hb_paint_push_transform (paint_funcs, paint_data, 757 1.f, 0.f, 758 slant_xy, 1.f, 759 0.f, 0.f); 760 761 bool ret = klass->get.f.paint_glyph_or_fail (this, user_data, 762 glyph, 763 paint_funcs, paint_data, 764 palette, foreground, 765 !klass->user_data ? nullptr : klass->user_data->paint_glyph_or_fail); 766 767 if (synthetic && slant_xy) 768 hb_paint_pop_transform (paint_funcs, paint_data); 769 770 return ret; 771 #endif 772 return false; 773 } 774 775 /* A bit higher-level, and with fallback */ 776 777 HB_INTERNAL 778 void paint_glyph (hb_codepoint_t glyph, 779 hb_paint_funcs_t *paint_funcs, void *paint_data, 780 unsigned int palette, 781 hb_color_t foreground); 782 783 void get_h_extents_with_fallback (hb_font_extents_t *extents) 784 { 785 if (!get_font_h_extents (extents)) 786 { 787 extents->ascender = y_scale * .8; 788 extents->descender = extents->ascender - y_scale; 789 extents->line_gap = 0; 790 } 791 } 792 void get_v_extents_with_fallback (hb_font_extents_t *extents) 793 { 794 if (!get_font_v_extents (extents)) 795 { 796 extents->ascender = x_scale / 2; 797 extents->descender = extents->ascender - x_scale; 798 extents->line_gap = 0; 799 } 800 } 801 802 void get_extents_for_direction (hb_direction_t direction, 803 hb_font_extents_t *extents) 804 { 805 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 806 get_h_extents_with_fallback (extents); 807 else 808 get_v_extents_with_fallback (extents); 809 } 810 811 void get_glyph_advance_for_direction (hb_codepoint_t glyph, 812 hb_direction_t direction, 813 hb_position_t *x, hb_position_t *y) 814 { 815 *x = *y = 0; 816 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 817 *x = get_glyph_h_advance (glyph); 818 else 819 *y = get_glyph_v_advance (glyph); 820 } 821 void get_glyph_advances_for_direction (hb_direction_t direction, 822 unsigned int count, 823 const hb_codepoint_t *first_glyph, 824 unsigned glyph_stride, 825 hb_position_t *first_advance, 826 unsigned advance_stride) 827 { 828 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 829 get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 830 else 831 get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 832 } 833 834 void apply_offset (hb_position_t *x, hb_position_t *y, 835 hb_position_t dx, hb_position_t dy, 836 signed mult) 837 { 838 assert (mult == -1 || mult == +1); 839 840 *x += dx * mult; 841 *y += dy * mult; 842 } 843 void add_offset (hb_position_t *x, hb_position_t *y, 844 hb_position_t dx, hb_position_t dy) 845 { 846 *x += dx; 847 *y += dy; 848 } 849 void subtract_offset (hb_position_t *x, hb_position_t *y, 850 hb_position_t dx, hb_position_t dy) 851 { 852 *x -= dx; 853 *y -= dy; 854 } 855 856 void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 857 hb_position_t *x, hb_position_t *y) 858 { 859 *x = get_glyph_h_advance (glyph) / 2; 860 861 hb_font_extents_t extents; 862 get_h_extents_with_fallback (&extents); 863 *y = extents.ascender; 864 } 865 866 void apply_glyph_h_origins_with_fallback (hb_buffer_t *buf, int mult) 867 { 868 bool has_ascender = false; 869 hb_position_t ascender = 0; 870 871 struct { hb_position_t x, y; } origins[32]; 872 873 unsigned int offset = 0; 874 unsigned int count = buf->len; 875 while (offset < count) 876 { 877 unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins)); 878 if (!get_glyph_h_origins (n, 879 &buf->info[offset].codepoint, sizeof (hb_glyph_info_t), 880 &origins[0].x, sizeof (origins[0]), 881 &origins[0].y, sizeof (origins[0]))) 882 { 883 if (get_glyph_v_origins (n, 884 &buf->info[offset].codepoint, sizeof (hb_glyph_info_t), 885 &origins[0].x, sizeof (origins[0]), 886 &origins[0].y, sizeof (origins[0]))) 887 { 888 if (!has_ascender) 889 { 890 hb_font_extents_t extents; 891 get_h_extents_with_fallback (&extents); 892 ascender = extents.ascender; 893 has_ascender = true; 894 } 895 896 /* We got the v_origins, adjust them to h_origins. */ 897 for (unsigned j = 0; j < n; j++) 898 { 899 hb_codepoint_t glyph = buf->info[offset + j].codepoint; 900 origins[j].x -= get_glyph_h_advance (glyph) / 2; 901 origins[j].y -= ascender; 902 } 903 } 904 else 905 { 906 for (unsigned j = 0; j < n; j++) 907 { 908 origins[j].x = 0; 909 origins[j].y = 0; 910 } 911 } 912 } 913 914 assert (mult == -1 || mult == +1); 915 if (mult == +1) 916 for (unsigned j = 0; j < n; j++) 917 { 918 hb_glyph_position_t *pos = &buf->pos[offset + j]; 919 add_offset (&pos->x_offset, &pos->y_offset, 920 origins[j].x, origins[j].y); 921 } 922 else /* mult == -1 */ 923 for (unsigned j = 0; j < n; j++) 924 { 925 hb_glyph_position_t *pos = &buf->pos[offset + j]; 926 subtract_offset (&pos->x_offset, &pos->y_offset, 927 origins[j].x, origins[j].y); 928 } 929 930 offset += n; 931 } 932 } 933 void apply_glyph_v_origins_with_fallback (hb_buffer_t *buf, int mult) 934 { 935 bool has_ascender = false; 936 hb_position_t ascender = 0; 937 938 struct { hb_position_t x, y; } origins[32]; 939 940 unsigned int offset = 0; 941 unsigned int count = buf->len; 942 while (offset < count) 943 { 944 unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins)); 945 if (!get_glyph_v_origins (n, 946 &buf->info[offset].codepoint, sizeof (hb_glyph_info_t), 947 &origins[0].x, sizeof (origins[0]), 948 &origins[0].y, sizeof (origins[0]))) 949 { 950 if (get_glyph_h_origins (n, 951 &buf->info[offset].codepoint, sizeof (hb_glyph_info_t), 952 &origins[0].x, sizeof (origins[0]), 953 &origins[0].y, sizeof (origins[0]))) 954 { 955 if (!has_ascender) 956 { 957 hb_font_extents_t extents; 958 get_h_extents_with_fallback (&extents); 959 ascender = extents.ascender; 960 has_ascender = true; 961 } 962 963 /* We got the h_origins, adjust them to v_origins. */ 964 for (unsigned j = 0; j < n; j++) 965 { 966 hb_codepoint_t glyph = buf->info[offset + j].codepoint; 967 origins[j].x += get_glyph_h_advance (glyph) / 2; 968 origins[j].y += ascender; 969 } 970 } 971 else 972 { 973 for (unsigned j = 0; j < n; j++) 974 { 975 origins[j].x = 0; 976 origins[j].y = 0; 977 } 978 } 979 } 980 981 assert (mult == -1 || mult == +1); 982 if (mult == +1) 983 for (unsigned j = 0; j < n; j++) 984 { 985 hb_glyph_position_t *pos = &buf->pos[offset + j]; 986 add_offset (&pos->x_offset, &pos->y_offset, 987 origins[j].x, origins[j].y); 988 } 989 else /* mult == -1 */ 990 for (unsigned j = 0; j < n; j++) 991 { 992 hb_glyph_position_t *pos = &buf->pos[offset + j]; 993 subtract_offset (&pos->x_offset, &pos->y_offset, 994 origins[j].x, origins[j].y); 995 } 996 997 offset += n; 998 } 999 } 1000 1001 void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, 1002 hb_position_t *x, hb_position_t *y) 1003 { 1004 if (!get_glyph_h_origin (glyph, x, y) && 1005 get_glyph_v_origin (glyph, x, y)) 1006 { 1007 hb_position_t dx, dy; 1008 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 1009 subtract_offset (x, y, dx, dy); 1010 } 1011 } 1012 void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, 1013 hb_position_t *x, hb_position_t *y) 1014 { 1015 if (!get_glyph_v_origin (glyph, x, y) && 1016 get_glyph_h_origin (glyph, x, y)) 1017 { 1018 hb_position_t dx, dy; 1019 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 1020 add_offset (x, y, dx, dy); 1021 } 1022 } 1023 1024 void get_glyph_origin_for_direction (hb_codepoint_t glyph, 1025 hb_direction_t direction, 1026 hb_position_t *x, hb_position_t *y) 1027 { 1028 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 1029 get_glyph_h_origin_with_fallback (glyph, x, y); 1030 else 1031 get_glyph_v_origin_with_fallback (glyph, x, y); 1032 } 1033 1034 void add_glyph_h_origins (hb_buffer_t *buf) 1035 { 1036 apply_glyph_h_origins_with_fallback (buf, +1); 1037 } 1038 void add_glyph_v_origins (hb_buffer_t *buf) 1039 { 1040 apply_glyph_v_origins_with_fallback (buf, +1); 1041 } 1042 void add_glyph_origin_for_direction (hb_codepoint_t glyph, 1043 hb_direction_t direction, 1044 hb_position_t *x, hb_position_t *y) 1045 { 1046 hb_position_t origin_x, origin_y; 1047 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 1048 add_offset (x, y, origin_x, origin_y); 1049 } 1050 1051 void subtract_glyph_h_origins (hb_buffer_t *buf) 1052 { 1053 apply_glyph_h_origins_with_fallback (buf, -1); 1054 } 1055 void subtract_glyph_v_origins (hb_buffer_t *buf) 1056 { 1057 apply_glyph_v_origins_with_fallback (buf, -1); 1058 } 1059 void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 1060 hb_direction_t direction, 1061 hb_position_t *x, hb_position_t *y) 1062 { 1063 hb_position_t origin_x, origin_y; 1064 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 1065 subtract_offset (x, y, origin_x, origin_y); 1066 } 1067 1068 void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 1069 hb_direction_t direction, 1070 hb_position_t *x, hb_position_t *y) 1071 { 1072 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 1073 *y = 0; 1074 *x = get_glyph_h_kerning (first_glyph, second_glyph); 1075 } else { 1076 *x = 0; 1077 *y = get_glyph_v_kerning (first_glyph, second_glyph); 1078 } 1079 } 1080 1081 hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 1082 hb_direction_t direction, 1083 hb_glyph_extents_t *extents) 1084 { 1085 hb_bool_t ret = get_glyph_extents (glyph, extents); 1086 1087 if (ret) 1088 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 1089 1090 return ret; 1091 } 1092 1093 hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 1094 hb_direction_t direction, 1095 hb_position_t *x, hb_position_t *y) 1096 { 1097 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 1098 1099 if (ret) 1100 subtract_glyph_origin_for_direction (glyph, direction, x, y); 1101 1102 return ret; 1103 } 1104 1105 /* Generates gidDDD if glyph has no name. */ 1106 void 1107 glyph_to_string (hb_codepoint_t glyph, 1108 char *s, unsigned int size) 1109 { 1110 if (get_glyph_name (glyph, s, size)) return; 1111 1112 if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0) 1113 *s = '\0'; 1114 } 1115 1116 /* Parses gidDDD and uniUUUU strings automatically. */ 1117 hb_bool_t 1118 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 1119 hb_codepoint_t *glyph) 1120 { 1121 if (get_glyph_from_name (s, len, glyph)) return true; 1122 1123 if (len == -1) len = strlen (s); 1124 1125 /* Straight glyph index. */ 1126 if (hb_codepoint_parse (s, len, 10, glyph)) 1127 return true; 1128 1129 if (len > 3) 1130 { 1131 /* gidDDD syntax for glyph indices. */ 1132 if (0 == strncmp (s, "gid", 3) && 1133 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 1134 return true; 1135 1136 /* uniUUUU and other Unicode character indices. */ 1137 hb_codepoint_t unichar; 1138 if (0 == strncmp (s, "uni", 3) && 1139 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 1140 get_nominal_glyph (unichar, glyph)) 1141 return true; 1142 } 1143 1144 return false; 1145 } 1146 1147 void changed () 1148 { 1149 float upem = face->get_upem (); 1150 1151 x_multf = x_scale / upem; 1152 y_multf = y_scale / upem; 1153 bool x_neg = x_scale < 0; 1154 x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem; 1155 bool y_neg = y_scale < 0; 1156 y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem; 1157 1158 is_synthetic = x_embolden || y_embolden || slant; 1159 1160 x_strength = roundf (abs (x_scale) * x_embolden); 1161 y_strength = roundf (abs (y_scale) * y_embolden); 1162 1163 slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; 1164 1165 data.fini (); 1166 1167 serial++; 1168 } 1169 1170 hb_position_t em_mult (int16_t v, int64_t mult) 1171 { return (hb_position_t) ((v * mult + 32768) >> 16); } 1172 hb_position_t em_multf (float v, float mult) 1173 { return (hb_position_t) roundf (em_fmultf (v, mult)); } 1174 float em_fmultf (float v, float mult) 1175 { return v * mult; } 1176 float em_fmult (int16_t v, float mult) 1177 { return (float) v * mult; } 1178 }; 1179 DECLARE_NULL_INSTANCE (hb_font_t); 1180 1181 1182 #endif /* HB_FONT_HH */