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