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