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