hb-font.cc revision 2f87cebe1062c7007021ebd05c1664e60da80825
1/* 2 * Copyright © 2009 Red Hat, Inc. 3 * Copyright © 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#include "hb-private.hh" 30 31#include "hb-ot-layout-private.hh" 32 33#include "hb-font-private.hh" 34#include "hb-blob.h" 35#include "hb-open-file-private.hh" 36#include "hb-ot-head-table.hh" 37 38#include "hb-cache-private.hh" 39 40#include <string.h> 41 42 43 44/* 45 * hb_font_funcs_t 46 */ 47 48static hb_bool_t 49hb_font_get_glyph_nil (hb_font_t *font, 50 void *font_data HB_UNUSED, 51 hb_codepoint_t unicode, 52 hb_codepoint_t variation_selector, 53 hb_codepoint_t *glyph, 54 void *user_data HB_UNUSED) 55{ 56 if (font->parent) 57 return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph); 58 59 *glyph = 0; 60 return false; 61} 62 63static hb_position_t 64hb_font_get_glyph_h_advance_nil (hb_font_t *font, 65 void *font_data HB_UNUSED, 66 hb_codepoint_t glyph, 67 void *user_data HB_UNUSED) 68{ 69 if (font->parent) 70 return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph)); 71 72 return font->x_scale; 73} 74 75static hb_position_t 76hb_font_get_glyph_v_advance_nil (hb_font_t *font, 77 void *font_data HB_UNUSED, 78 hb_codepoint_t glyph, 79 void *user_data HB_UNUSED) 80{ 81 if (font->parent) 82 return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph)); 83 84 return font->y_scale; 85} 86 87static hb_bool_t 88hb_font_get_glyph_h_origin_nil (hb_font_t *font, 89 void *font_data HB_UNUSED, 90 hb_codepoint_t glyph, 91 hb_position_t *x, 92 hb_position_t *y, 93 void *user_data HB_UNUSED) 94{ 95 if (font->parent) { 96 hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent, glyph, x, y); 97 if (ret) 98 font->parent_scale_position (x, y); 99 return ret; 100 } 101 102 *x = *y = 0; 103 return false; 104} 105 106static hb_bool_t 107hb_font_get_glyph_v_origin_nil (hb_font_t *font, 108 void *font_data HB_UNUSED, 109 hb_codepoint_t glyph, 110 hb_position_t *x, 111 hb_position_t *y, 112 void *user_data HB_UNUSED) 113{ 114 if (font->parent) { 115 hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent, glyph, x, y); 116 if (ret) 117 font->parent_scale_position (x, y); 118 return ret; 119 } 120 121 *x = *y = 0; 122 return false; 123} 124 125static hb_position_t 126hb_font_get_glyph_h_kerning_nil (hb_font_t *font, 127 void *font_data HB_UNUSED, 128 hb_codepoint_t left_glyph, 129 hb_codepoint_t right_glyph, 130 void *user_data HB_UNUSED) 131{ 132 if (font->parent) 133 return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph)); 134 135 return 0; 136} 137 138static hb_position_t 139hb_font_get_glyph_v_kerning_nil (hb_font_t *font, 140 void *font_data HB_UNUSED, 141 hb_codepoint_t top_glyph, 142 hb_codepoint_t bottom_glyph, 143 void *user_data HB_UNUSED) 144{ 145 if (font->parent) 146 return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph)); 147 148 return 0; 149} 150 151static hb_bool_t 152hb_font_get_glyph_extents_nil (hb_font_t *font, 153 void *font_data HB_UNUSED, 154 hb_codepoint_t glyph, 155 hb_glyph_extents_t *extents, 156 void *user_data HB_UNUSED) 157{ 158 if (font->parent) { 159 hb_bool_t ret = hb_font_get_glyph_extents (font->parent, 160 glyph, 161 extents); 162 if (ret) { 163 font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); 164 font->parent_scale_distance (&extents->width, &extents->height); 165 } 166 return ret; 167 } 168 169 memset (extents, 0, sizeof (*extents)); 170 return false; 171} 172 173static hb_bool_t 174hb_font_get_glyph_contour_point_nil (hb_font_t *font, 175 void *font_data HB_UNUSED, 176 hb_codepoint_t glyph, 177 unsigned int point_index, 178 hb_position_t *x, 179 hb_position_t *y, 180 void *user_data HB_UNUSED) 181{ 182 if (font->parent) { 183 hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent, glyph, point_index, x, y); 184 if (ret) 185 font->parent_scale_position (x, y); 186 return ret; 187 } 188 189 *x = *y = 0; 190 return false; 191} 192 193static hb_bool_t 194hb_font_get_glyph_name_nil (hb_font_t *font, 195 void *font_data HB_UNUSED, 196 hb_codepoint_t glyph, 197 char *name, unsigned int size, 198 void *user_data HB_UNUSED) 199{ 200 if (font->parent) 201 return hb_font_get_glyph_name (font->parent, glyph, name, size); 202 203 snprintf (name, size, "gid%u", glyph); 204 return false; 205} 206 207static hb_bool_t 208hb_font_get_glyph_from_name_nil (hb_font_t *font, 209 void *font_data HB_UNUSED, 210 const char *name, int len, /* -1 means nul-terminated */ 211 hb_codepoint_t *glyph, 212 void *user_data HB_UNUSED) 213{ 214 if (font->parent) 215 return hb_font_get_glyph_from_name (font->parent, name, len, glyph); 216 217 *glyph = 0; 218 return false; 219} 220 221 222static const hb_font_funcs_t _hb_font_funcs_nil = { 223 HB_OBJECT_HEADER_STATIC, 224 225 true, /* immutable */ 226 227 { 228#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil, 229 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 230#undef HB_FONT_FUNC_IMPLEMENT 231 } 232}; 233 234 235hb_font_funcs_t * 236hb_font_funcs_create (void) 237{ 238 hb_font_funcs_t *ffuncs; 239 240 if (!(ffuncs = hb_object_create<hb_font_funcs_t> ())) 241 return hb_font_funcs_get_empty (); 242 243 ffuncs->get = _hb_font_funcs_nil.get; 244 245 return ffuncs; 246} 247 248hb_font_funcs_t * 249hb_font_funcs_get_empty (void) 250{ 251 return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil); 252} 253 254hb_font_funcs_t * 255hb_font_funcs_reference (hb_font_funcs_t *ffuncs) 256{ 257 return hb_object_reference (ffuncs); 258} 259 260void 261hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) 262{ 263 if (!hb_object_destroy (ffuncs)) return; 264 265#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \ 266 ffuncs->destroy.name (ffuncs->user_data.name); 267 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 268#undef HB_FONT_FUNC_IMPLEMENT 269 270 free (ffuncs); 271} 272 273hb_bool_t 274hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, 275 hb_user_data_key_t *key, 276 void * data, 277 hb_destroy_func_t destroy, 278 hb_bool_t replace) 279{ 280 return hb_object_set_user_data (ffuncs, key, data, destroy, replace); 281} 282 283void * 284hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, 285 hb_user_data_key_t *key) 286{ 287 return hb_object_get_user_data (ffuncs, key); 288} 289 290 291void 292hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) 293{ 294 if (hb_object_is_inert (ffuncs)) 295 return; 296 297 ffuncs->immutable = true; 298} 299 300hb_bool_t 301hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) 302{ 303 return ffuncs->immutable; 304} 305 306 307#define HB_FONT_FUNC_IMPLEMENT(name) \ 308 \ 309void \ 310hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ 311 hb_font_get_##name##_func_t func, \ 312 void *user_data, \ 313 hb_destroy_func_t destroy) \ 314{ \ 315 if (ffuncs->immutable) { \ 316 if (destroy) \ 317 destroy (user_data); \ 318 return; \ 319 } \ 320 \ 321 if (ffuncs->destroy.name) \ 322 ffuncs->destroy.name (ffuncs->user_data.name); \ 323 \ 324 if (func) { \ 325 ffuncs->get.name = func; \ 326 ffuncs->user_data.name = user_data; \ 327 ffuncs->destroy.name = destroy; \ 328 } else { \ 329 ffuncs->get.name = hb_font_get_##name##_nil; \ 330 ffuncs->user_data.name = NULL; \ 331 ffuncs->destroy.name = NULL; \ 332 } \ 333} 334 335HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 336#undef HB_FONT_FUNC_IMPLEMENT 337 338 339hb_bool_t 340hb_font_get_glyph (hb_font_t *font, 341 hb_codepoint_t unicode, hb_codepoint_t variation_selector, 342 hb_codepoint_t *glyph) 343{ 344 *glyph = 0; 345 return font->klass->get.glyph (font, font->user_data, 346 unicode, variation_selector, glyph, 347 font->klass->user_data.glyph); 348} 349 350hb_position_t 351hb_font_get_glyph_h_advance (hb_font_t *font, 352 hb_codepoint_t glyph) 353{ 354 return font->klass->get.glyph_h_advance (font, font->user_data, 355 glyph, 356 font->klass->user_data.glyph_h_advance); 357} 358 359hb_position_t 360hb_font_get_glyph_v_advance (hb_font_t *font, 361 hb_codepoint_t glyph) 362{ 363 return font->klass->get.glyph_v_advance (font, font->user_data, 364 glyph, 365 font->klass->user_data.glyph_v_advance); 366} 367 368hb_bool_t 369hb_font_get_glyph_h_origin (hb_font_t *font, 370 hb_codepoint_t glyph, 371 hb_position_t *x, hb_position_t *y) 372{ 373 *x = *y = 0; 374 return font->klass->get.glyph_h_origin (font, font->user_data, 375 glyph, x, y, 376 font->klass->user_data.glyph_h_origin); 377} 378 379hb_bool_t 380hb_font_get_glyph_v_origin (hb_font_t *font, 381 hb_codepoint_t glyph, 382 hb_position_t *x, hb_position_t *y) 383{ 384 *x = *y = 0; 385 return font->klass->get.glyph_v_origin (font, font->user_data, 386 glyph, x, y, 387 font->klass->user_data.glyph_v_origin); 388} 389 390hb_position_t 391hb_font_get_glyph_h_kerning (hb_font_t *font, 392 hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 393{ 394 return font->klass->get.glyph_h_kerning (font, font->user_data, 395 left_glyph, right_glyph, 396 font->klass->user_data.glyph_h_kerning); 397} 398 399hb_position_t 400hb_font_get_glyph_v_kerning (hb_font_t *font, 401 hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 402{ 403 return font->klass->get.glyph_v_kerning (font, font->user_data, 404 left_glyph, right_glyph, 405 font->klass->user_data.glyph_v_kerning); 406} 407 408hb_bool_t 409hb_font_get_glyph_extents (hb_font_t *font, 410 hb_codepoint_t glyph, 411 hb_glyph_extents_t *extents) 412{ 413 memset (extents, 0, sizeof (*extents)); 414 return font->klass->get.glyph_extents (font, font->user_data, 415 glyph, 416 extents, 417 font->klass->user_data.glyph_extents); 418} 419 420hb_bool_t 421hb_font_get_glyph_contour_point (hb_font_t *font, 422 hb_codepoint_t glyph, unsigned int point_index, 423 hb_position_t *x, hb_position_t *y) 424{ 425 *x = *y = 0; 426 return font->klass->get.glyph_contour_point (font, font->user_data, 427 glyph, point_index, 428 x, y, 429 font->klass->user_data.glyph_contour_point); 430} 431 432hb_bool_t 433hb_font_get_glyph_name (hb_font_t *font, 434 hb_codepoint_t glyph, 435 char *name, unsigned int size) 436{ 437 return font->klass->get.glyph_name (font, font->user_data, 438 glyph, 439 name, size, 440 font->klass->user_data.glyph_name); 441} 442 443hb_bool_t 444hb_font_get_glyph_from_name (hb_font_t *font, 445 const char *name, int len, /* -1 means nul-terminated */ 446 hb_codepoint_t *glyph) 447{ 448 return font->klass->get.glyph_from_name (font, font->user_data, 449 name, len, 450 glyph, 451 font->klass->user_data.glyph_from_name); 452} 453 454 455/* A bit higher-level, and with fallback */ 456 457void 458hb_font_get_glyph_advance_for_direction (hb_font_t *font, 459 hb_codepoint_t glyph, 460 hb_direction_t direction, 461 hb_position_t *x, hb_position_t *y) 462{ 463 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 464 *x = hb_font_get_glyph_h_advance (font, glyph); 465 *y = 0; 466 } else { 467 *x = 0; 468 *y = hb_font_get_glyph_v_advance (font, glyph); 469 } 470} 471 472static void 473guess_v_origin_minus_h_origin (hb_font_t *font, 474 hb_codepoint_t glyph, 475 hb_position_t *x, hb_position_t *y) 476{ 477 *x = hb_font_get_glyph_h_advance (font, glyph) / 2; 478 479 /* TODO use font_metics.ascent */ 480 *y = font->y_scale; 481} 482 483 484void 485hb_font_get_glyph_origin_for_direction (hb_font_t *font, 486 hb_codepoint_t glyph, 487 hb_direction_t direction, 488 hb_position_t *x, hb_position_t *y) 489{ 490 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 491 hb_bool_t ret = hb_font_get_glyph_h_origin (font, glyph, x, y); 492 if (!ret && (ret = hb_font_get_glyph_v_origin (font, glyph, x, y))) { 493 hb_position_t dx, dy; 494 guess_v_origin_minus_h_origin (font, glyph, &dx, &dy); 495 *x -= dx; *y -= dy; 496 } 497 } else { 498 hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y); 499 if (!ret && (ret = hb_font_get_glyph_h_origin (font, glyph, x, y))) { 500 hb_position_t dx, dy; 501 guess_v_origin_minus_h_origin (font, glyph, &dx, &dy); 502 *x += dx; *y += dy; 503 } 504 } 505} 506 507void 508hb_font_add_glyph_origin_for_direction (hb_font_t *font, 509 hb_codepoint_t glyph, 510 hb_direction_t direction, 511 hb_position_t *x, hb_position_t *y) 512{ 513 hb_position_t origin_x, origin_y; 514 515 hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y); 516 517 *x += origin_x; 518 *y += origin_y; 519} 520 521void 522hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, 523 hb_codepoint_t glyph, 524 hb_direction_t direction, 525 hb_position_t *x, hb_position_t *y) 526{ 527 hb_position_t origin_x, origin_y; 528 529 hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y); 530 531 *x -= origin_x; 532 *y -= origin_y; 533} 534 535void 536hb_font_get_glyph_kerning_for_direction (hb_font_t *font, 537 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 538 hb_direction_t direction, 539 hb_position_t *x, hb_position_t *y) 540{ 541 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 542 *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph); 543 *y = 0; 544 } else { 545 *x = 0; 546 *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph); 547 } 548} 549 550hb_bool_t 551hb_font_get_glyph_extents_for_origin (hb_font_t *font, 552 hb_codepoint_t glyph, 553 hb_direction_t direction, 554 hb_glyph_extents_t *extents) 555{ 556 hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents); 557 558 if (ret) 559 hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, &extents->x_bearing, &extents->y_bearing); 560 561 return ret; 562} 563 564hb_bool_t 565hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, 566 hb_codepoint_t glyph, unsigned int point_index, 567 hb_direction_t direction, 568 hb_position_t *x, hb_position_t *y) 569{ 570 hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y); 571 572 if (ret) 573 hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, x, y); 574 575 return ret; 576} 577 578 579/* 580 * hb_face_t 581 */ 582 583static const hb_face_t _hb_face_nil = { 584 HB_OBJECT_HEADER_STATIC, 585 586 true, /* immutable */ 587 588 NULL, /* reference_table */ 589 NULL, /* user_data */ 590 NULL, /* destroy */ 591 592 0, /* index */ 593 1000, /* upem */ 594 595 { 596#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, 597#include "hb-shaper-list.hh" 598#undef HB_SHAPER_IMPLEMENT 599 }, 600 601 NULL, /* shape_plans */ 602}; 603 604 605hb_face_t * 606hb_face_create_for_tables (hb_reference_table_func_t reference_table, 607 void *user_data, 608 hb_destroy_func_t destroy) 609{ 610 hb_face_t *face; 611 612 if (!reference_table || !(face = hb_object_create<hb_face_t> ())) { 613 if (destroy) 614 destroy (user_data); 615 return hb_face_get_empty (); 616 } 617 618 face->reference_table = reference_table; 619 face->user_data = user_data; 620 face->destroy = destroy; 621 622 face->upem = 0; 623 624 return face; 625} 626 627 628typedef struct hb_face_for_data_closure_t { 629 hb_blob_t *blob; 630 unsigned int index; 631} hb_face_for_data_closure_t; 632 633static hb_face_for_data_closure_t * 634_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) 635{ 636 hb_face_for_data_closure_t *closure; 637 638 closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t)); 639 if (unlikely (!closure)) 640 return NULL; 641 642 closure->blob = blob; 643 closure->index = index; 644 645 return closure; 646} 647 648static void 649_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure) 650{ 651 hb_blob_destroy (closure->blob); 652 free (closure); 653} 654 655static hb_blob_t * 656_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) 657{ 658 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; 659 660 if (tag == HB_TAG_NONE) 661 return hb_blob_reference (data->blob); 662 663 const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob); 664 const OpenTypeFontFace &ot_face = ot_file.get_face (data->index); 665 666 const OpenTypeTable &table = ot_face.get_table_by_tag (tag); 667 668 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length); 669 670 return blob; 671} 672 673hb_face_t * 674hb_face_create (hb_blob_t *blob, 675 unsigned int index) 676{ 677 hb_face_t *face; 678 679 if (unlikely (!blob || !hb_blob_get_length (blob))) 680 return hb_face_get_empty (); 681 682 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); 683 684 if (unlikely (!closure)) 685 return hb_face_get_empty (); 686 687 face = hb_face_create_for_tables (_hb_face_for_data_reference_table, 688 closure, 689 (hb_destroy_func_t) _hb_face_for_data_closure_destroy); 690 691 hb_face_set_index (face, index); 692 693 return face; 694} 695 696hb_face_t * 697hb_face_get_empty (void) 698{ 699 return const_cast<hb_face_t *> (&_hb_face_nil); 700} 701 702 703hb_face_t * 704hb_face_reference (hb_face_t *face) 705{ 706 return hb_object_reference (face); 707} 708 709void 710hb_face_destroy (hb_face_t *face) 711{ 712 if (!hb_object_destroy (face)) return; 713 714 /* The cached shape_plans think they have a reference on us, and 715 * try to release it. Make sure that doesn't mess up. */ 716 face->header.ref_count.ref_count = HB_REFERENCE_COUNT_INVALID_VALUE; 717 for (hb_face_t::plan_node_t *node = face->shape_plans; node; ) 718 { 719 hb_face_t::plan_node_t *next = node->next; 720 hb_shape_plan_destroy (node->shape_plan); 721 free (node); 722 node = next; 723 } 724 725#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face); 726#include "hb-shaper-list.hh" 727#undef HB_SHAPER_IMPLEMENT 728 729 if (face->destroy) 730 face->destroy (face->user_data); 731 732 free (face); 733} 734 735hb_bool_t 736hb_face_set_user_data (hb_face_t *face, 737 hb_user_data_key_t *key, 738 void * data, 739 hb_destroy_func_t destroy, 740 hb_bool_t replace) 741{ 742 return hb_object_set_user_data (face, key, data, destroy, replace); 743} 744 745void * 746hb_face_get_user_data (hb_face_t *face, 747 hb_user_data_key_t *key) 748{ 749 return hb_object_get_user_data (face, key); 750} 751 752void 753hb_face_make_immutable (hb_face_t *face) 754{ 755 if (hb_object_is_inert (face)) 756 return; 757 758 face->immutable = true; 759} 760 761hb_bool_t 762hb_face_is_immutable (hb_face_t *face) 763{ 764 return face->immutable; 765} 766 767 768hb_blob_t * 769hb_face_reference_table (hb_face_t *face, 770 hb_tag_t tag) 771{ 772 hb_blob_t *blob; 773 774 if (unlikely (!face || !face->reference_table)) 775 return hb_blob_get_empty (); 776 777 blob = face->reference_table (face, tag, face->user_data); 778 if (unlikely (!blob)) 779 return hb_blob_get_empty (); 780 781 return blob; 782} 783 784hb_blob_t * 785hb_face_reference_blob (hb_face_t *face) 786{ 787 return hb_face_reference_table (face, HB_TAG_NONE); 788} 789 790void 791hb_face_set_index (hb_face_t *face, 792 unsigned int index) 793{ 794 if (hb_object_is_inert (face)) 795 return; 796 797 face->index = index; 798} 799 800unsigned int 801hb_face_get_index (hb_face_t *face) 802{ 803 return face->index; 804} 805 806void 807hb_face_set_upem (hb_face_t *face, 808 unsigned int upem) 809{ 810 if (hb_object_is_inert (face)) 811 return; 812 813 face->upem = upem; 814} 815 816unsigned int 817hb_face_get_upem (hb_face_t *face) 818{ 819 if (unlikely (!face->upem)) { 820 hb_blob_t *head_blob = Sanitizer<head>::sanitize (hb_face_reference_table (face, HB_OT_TAG_head)); 821 const head *head_table = Sanitizer<head>::lock_instance (head_blob); 822 face->upem = head_table->get_upem (); 823 hb_blob_destroy (head_blob); 824 } 825 return face->upem; 826} 827 828 829/* 830 * hb_font_t 831 */ 832 833hb_font_t * 834hb_font_create (hb_face_t *face) 835{ 836 hb_font_t *font; 837 838 if (unlikely (!face)) 839 face = hb_face_get_empty (); 840 if (unlikely (hb_object_is_inert (face))) 841 return hb_font_get_empty (); 842 if (!(font = hb_object_create<hb_font_t> ())) 843 return hb_font_get_empty (); 844 845 hb_face_make_immutable (face); 846 font->face = hb_face_reference (face); 847 font->klass = hb_font_funcs_get_empty (); 848 849 return font; 850} 851 852hb_font_t * 853hb_font_create_sub_font (hb_font_t *parent) 854{ 855 if (unlikely (!parent)) 856 return hb_font_get_empty (); 857 858 hb_font_t *font = hb_font_create (parent->face); 859 860 if (unlikely (hb_object_is_inert (font))) 861 return font; 862 863 hb_font_make_immutable (parent); 864 font->parent = hb_font_reference (parent); 865 866 font->x_scale = parent->x_scale; 867 font->y_scale = parent->y_scale; 868 font->x_ppem = parent->x_ppem; 869 font->y_ppem = parent->y_ppem; 870 871 return font; 872} 873 874hb_font_t * 875hb_font_get_empty (void) 876{ 877 static const hb_font_t _hb_font_nil = { 878 HB_OBJECT_HEADER_STATIC, 879 880 true, /* immutable */ 881 882 NULL, /* parent */ 883 const_cast<hb_face_t *> (&_hb_face_nil), 884 885 0, /* x_scale */ 886 0, /* y_scale */ 887 888 0, /* x_ppem */ 889 0, /* y_ppem */ 890 891 const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */ 892 NULL, /* user_data */ 893 NULL, /* destroy */ 894 895 { 896#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, 897#include "hb-shaper-list.hh" 898#undef HB_SHAPER_IMPLEMENT 899 } 900 }; 901 902 return const_cast<hb_font_t *> (&_hb_font_nil); 903} 904 905hb_font_t * 906hb_font_reference (hb_font_t *font) 907{ 908 return hb_object_reference (font); 909} 910 911void 912hb_font_destroy (hb_font_t *font) 913{ 914 if (!hb_object_destroy (font)) return; 915 916#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font); 917#include "hb-shaper-list.hh" 918#undef HB_SHAPER_IMPLEMENT 919 920 if (font->destroy) 921 font->destroy (font->user_data); 922 923 hb_font_destroy (font->parent); 924 hb_face_destroy (font->face); 925 hb_font_funcs_destroy (font->klass); 926 927 free (font); 928} 929 930hb_bool_t 931hb_font_set_user_data (hb_font_t *font, 932 hb_user_data_key_t *key, 933 void * data, 934 hb_destroy_func_t destroy, 935 hb_bool_t replace) 936{ 937 return hb_object_set_user_data (font, key, data, destroy, replace); 938} 939 940void * 941hb_font_get_user_data (hb_font_t *font, 942 hb_user_data_key_t *key) 943{ 944 return hb_object_get_user_data (font, key); 945} 946 947void 948hb_font_make_immutable (hb_font_t *font) 949{ 950 if (hb_object_is_inert (font)) 951 return; 952 953 font->immutable = true; 954} 955 956hb_bool_t 957hb_font_is_immutable (hb_font_t *font) 958{ 959 return font->immutable; 960} 961 962hb_font_t * 963hb_font_get_parent (hb_font_t *font) 964{ 965 return font->parent; 966} 967 968hb_face_t * 969hb_font_get_face (hb_font_t *font) 970{ 971 return font->face; 972} 973 974 975void 976hb_font_set_funcs (hb_font_t *font, 977 hb_font_funcs_t *klass, 978 void *user_data, 979 hb_destroy_func_t destroy) 980{ 981 if (font->immutable) { 982 if (destroy) 983 destroy (user_data); 984 return; 985 } 986 987 if (font->destroy) 988 font->destroy (font->user_data); 989 990 if (!klass) 991 klass = hb_font_funcs_get_empty (); 992 993 hb_font_funcs_reference (klass); 994 hb_font_funcs_destroy (font->klass); 995 font->klass = klass; 996 font->user_data = user_data; 997 font->destroy = destroy; 998} 999 1000void 1001hb_font_set_funcs_data (hb_font_t *font, 1002 void *user_data, 1003 hb_destroy_func_t destroy) 1004{ 1005 /* Destroy user_data? */ 1006 if (font->immutable) { 1007 if (destroy) 1008 destroy (user_data); 1009 return; 1010 } 1011 1012 if (font->destroy) 1013 font->destroy (font->user_data); 1014 1015 font->user_data = user_data; 1016 font->destroy = destroy; 1017} 1018 1019 1020void 1021hb_font_set_scale (hb_font_t *font, 1022 int x_scale, 1023 int y_scale) 1024{ 1025 if (font->immutable) 1026 return; 1027 1028 font->x_scale = x_scale; 1029 font->y_scale = y_scale; 1030} 1031 1032void 1033hb_font_get_scale (hb_font_t *font, 1034 int *x_scale, 1035 int *y_scale) 1036{ 1037 if (x_scale) *x_scale = font->x_scale; 1038 if (y_scale) *y_scale = font->y_scale; 1039} 1040 1041void 1042hb_font_set_ppem (hb_font_t *font, 1043 unsigned int x_ppem, 1044 unsigned int y_ppem) 1045{ 1046 if (font->immutable) 1047 return; 1048 1049 font->x_ppem = x_ppem; 1050 font->y_ppem = y_ppem; 1051} 1052 1053void 1054hb_font_get_ppem (hb_font_t *font, 1055 unsigned int *x_ppem, 1056 unsigned int *y_ppem) 1057{ 1058 if (x_ppem) *x_ppem = font->x_ppem; 1059 if (y_ppem) *y_ppem = font->y_ppem; 1060} 1061 1062 1063