hb-font.cc revision abcfe9b59b4475eb02dd679aac4bc59616713b28
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 35#include <string.h> 36 37HB_BEGIN_DECLS 38 39 40/* 41 * hb_font_funcs_t 42 */ 43 44static hb_bool_t 45hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED, 46 const void *font_data HB_UNUSED, 47 unsigned int point_index HB_UNUSED, 48 hb_codepoint_t glyph HB_UNUSED, 49 hb_position_t *x HB_UNUSED, 50 hb_position_t *y HB_UNUSED, 51 const void *user_data HB_UNUSED) 52{ 53 if (font->parent) 54 return hb_font_get_contour_point (font->parent, 55 point_index, glyph, 56 x, y); 57 58 *x = *y = 0; 59 60 return false; 61} 62 63static void 64hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED, 65 const void *font_data HB_UNUSED, 66 hb_codepoint_t glyph HB_UNUSED, 67 hb_position_t *x_advance HB_UNUSED, 68 hb_position_t *y_advance HB_UNUSED, 69 const void *user_data HB_UNUSED) 70{ 71 if (font->parent) { 72 hb_font_get_glyph_advance (font->parent, glyph, x_advance, y_advance); 73 return; 74 } 75 76 *x_advance = *y_advance = 0; 77} 78 79static void 80hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, 81 const void *font_data HB_UNUSED, 82 hb_codepoint_t glyph HB_UNUSED, 83 hb_glyph_extents_t *extents HB_UNUSED, 84 const void *user_data HB_UNUSED) 85{ 86 if (font->parent) { 87 hb_font_get_glyph_extents (font->parent, glyph, extents); 88 return; 89 } 90 91 extents->x_bearing = extents->y_bearing = 0; 92 extents->width = extents->height = 0; 93} 94 95static hb_codepoint_t 96hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED, 97 const void *font_data HB_UNUSED, 98 hb_codepoint_t unicode HB_UNUSED, 99 hb_codepoint_t variation_selector HB_UNUSED, 100 const void *user_data HB_UNUSED) 101{ 102 if (font->parent) 103 return hb_font_get_glyph (font->parent, unicode, variation_selector); 104 105 return 0; 106} 107 108static hb_position_t 109hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED, 110 const void *font_data HB_UNUSED, 111 hb_codepoint_t first_glyph HB_UNUSED, 112 hb_codepoint_t second_glyph HB_UNUSED, 113 const void *user_data HB_UNUSED) 114{ 115 if (font->parent) 116 return hb_font_get_kerning (font->parent, first_glyph, second_glyph); 117 118 return 0; 119} 120 121 122static hb_font_funcs_t _hb_font_funcs_nil = { 123 HB_OBJECT_HEADER_STATIC, 124 125 TRUE, /* immutable */ 126 127 { 128 hb_font_get_contour_point_nil, 129 hb_font_get_glyph_advance_nil, 130 hb_font_get_glyph_extents_nil, 131 hb_font_get_glyph_nil, 132 hb_font_get_kerning_nil 133 } 134}; 135 136 137hb_font_funcs_t * 138hb_font_funcs_create (void) 139{ 140 hb_font_funcs_t *ffuncs; 141 142 if (!(ffuncs = hb_object_create<hb_font_funcs_t> ())) 143 return &_hb_font_funcs_nil; 144 145 ffuncs->get = _hb_font_funcs_nil.get; 146 147 return ffuncs; 148} 149 150hb_font_funcs_t * 151hb_font_funcs_reference (hb_font_funcs_t *ffuncs) 152{ 153 return hb_object_reference (ffuncs); 154} 155 156void 157hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) 158{ 159 if (!hb_object_destroy (ffuncs)) return; 160 161#define DESTROY(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name) 162 DESTROY (contour_point); 163 DESTROY (glyph_advance); 164 DESTROY (glyph_extents); 165 DESTROY (glyph); 166 DESTROY (kerning); 167#undef DESTROY 168 169 free (ffuncs); 170} 171 172hb_bool_t 173hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, 174 hb_user_data_key_t *key, 175 void * data, 176 hb_destroy_func_t destroy) 177{ 178 return hb_object_set_user_data (ffuncs, key, data, destroy); 179} 180 181void * 182hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, 183 hb_user_data_key_t *key) 184{ 185 return hb_object_get_user_data (ffuncs, key); 186} 187 188 189void 190hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) 191{ 192 if (hb_object_is_inert (ffuncs)) 193 return; 194 195 ffuncs->immutable = TRUE; 196} 197 198hb_bool_t 199hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) 200{ 201 return ffuncs->immutable; 202} 203 204 205#define IMPLEMENT(name) \ 206 \ 207void \ 208hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ 209 hb_font_get_##name##_func_t func, \ 210 void *user_data, \ 211 hb_destroy_func_t destroy) \ 212{ \ 213 if (ffuncs->immutable) \ 214 return; \ 215 \ 216 if (ffuncs->destroy.name) \ 217 ffuncs->destroy.name (ffuncs->user_data.name); \ 218 \ 219 if (func) { \ 220 ffuncs->get.name = func; \ 221 ffuncs->user_data.name = user_data; \ 222 ffuncs->destroy.name = destroy; \ 223 } else { \ 224 ffuncs->get.name = hb_font_get_##name##_nil; \ 225 ffuncs->user_data.name = NULL; \ 226 ffuncs->destroy.name = NULL; \ 227 } \ 228} 229 230IMPLEMENT (contour_point); 231IMPLEMENT (glyph_advance); 232IMPLEMENT (glyph_extents); 233IMPLEMENT (glyph); 234IMPLEMENT (kerning); 235 236#undef IMPLEMENT 237 238 239hb_bool_t 240hb_font_get_contour_point (hb_font_t *font, 241 unsigned int point_index, 242 hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) 243{ 244 *x = 0; *y = 0; 245 return font->klass->get.contour_point (font, font->user_data, 246 point_index, 247 glyph, x, y, 248 font->klass->user_data.contour_point); 249} 250 251void 252hb_font_get_glyph_advance (hb_font_t *font, 253 hb_codepoint_t glyph, 254 hb_position_t *x_advance, hb_position_t *y_advance) 255{ 256 *x_advance = *y_advance = 0; 257 return font->klass->get.glyph_advance (font, font->user_data, 258 glyph, x_advance, y_advance, 259 font->klass->user_data.glyph_advance); 260} 261 262void 263hb_font_get_glyph_extents (hb_font_t *font, 264 hb_codepoint_t glyph, hb_glyph_extents_t *extents) 265{ 266 memset (extents, 0, sizeof (*extents)); 267 return font->klass->get.glyph_extents (font, font->user_data, 268 glyph, extents, 269 font->klass->user_data.glyph_extents); 270} 271 272hb_codepoint_t 273hb_font_get_glyph (hb_font_t *font, 274 hb_codepoint_t unicode, hb_codepoint_t variation_selector) 275{ 276 return font->klass->get.glyph (font, font->user_data, 277 unicode, variation_selector, 278 font->klass->user_data.glyph); 279} 280 281hb_position_t 282hb_font_get_kerning (hb_font_t *font, 283 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph) 284{ 285 return font->klass->get.kerning (font, font->user_data, 286 first_glyph, second_glyph, 287 font->klass->user_data.kerning); 288} 289 290 291/* 292 * hb_face_t 293 */ 294 295static hb_face_t _hb_face_nil = { 296 HB_OBJECT_HEADER_STATIC, 297 298 NULL, /* get_table */ 299 NULL, /* user_data */ 300 NULL, /* destroy */ 301 302 NULL, /* ot_layout */ 303 304 1000 305}; 306 307 308hb_face_t * 309hb_face_create_for_tables (hb_get_table_func_t get_table, 310 void *user_data, 311 hb_destroy_func_t destroy) 312{ 313 hb_face_t *face; 314 315 if (!get_table || !(face = hb_object_create<hb_face_t> ())) { 316 if (destroy) 317 destroy (user_data); 318 return &_hb_face_nil; 319 } 320 321 face->get_table = get_table; 322 face->user_data = user_data; 323 face->destroy = destroy; 324 325 face->ot_layout = _hb_ot_layout_create (face); 326 327 face->upem = _hb_ot_layout_get_upem (face); 328 329 return face; 330} 331 332 333typedef struct _hb_face_for_data_closure_t { 334 hb_blob_t *blob; 335 unsigned int index; 336} hb_face_for_data_closure_t; 337 338static hb_face_for_data_closure_t * 339_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) 340{ 341 hb_face_for_data_closure_t *closure; 342 343 closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t)); 344 if (unlikely (!closure)) 345 return NULL; 346 347 closure->blob = blob; 348 closure->index = index; 349 350 return closure; 351} 352 353static void 354_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure) 355{ 356 hb_blob_destroy (closure->blob); 357 free (closure); 358} 359 360static hb_blob_t * 361_hb_face_for_data_get_table (hb_tag_t tag, void *user_data) 362{ 363 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; 364 365 const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob); 366 const OpenTypeFontFace &ot_face = ot_file.get_face (data->index); 367 368 const OpenTypeTable &table = ot_face.get_table_by_tag (tag); 369 370 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length); 371 372 return blob; 373} 374 375hb_face_t * 376hb_face_create_for_data (hb_blob_t *blob, 377 unsigned int index) 378{ 379 if (unlikely (!blob || !hb_blob_get_length (blob))) 380 return &_hb_face_nil; 381 382 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); 383 384 if (unlikely (!closure)) 385 return &_hb_face_nil; 386 387 return hb_face_create_for_tables (_hb_face_for_data_get_table, 388 closure, 389 (hb_destroy_func_t) _hb_face_for_data_closure_destroy); 390} 391 392 393hb_face_t * 394hb_face_reference (hb_face_t *face) 395{ 396 return hb_object_reference (face); 397} 398 399void 400hb_face_destroy (hb_face_t *face) 401{ 402 if (!hb_object_destroy (face)) return; 403 404 _hb_ot_layout_destroy (face->ot_layout); 405 406 if (face->destroy) 407 face->destroy (face->user_data); 408 409 free (face); 410} 411 412hb_bool_t 413hb_face_set_user_data (hb_face_t *face, 414 hb_user_data_key_t *key, 415 void * data, 416 hb_destroy_func_t destroy) 417{ 418 return hb_object_set_user_data (face, key, data, destroy); 419} 420 421void * 422hb_face_get_user_data (hb_face_t *face, 423 hb_user_data_key_t *key) 424{ 425 return hb_object_get_user_data (face, key); 426} 427 428 429hb_blob_t * 430hb_face_reference_table (hb_face_t *face, 431 hb_tag_t tag) 432{ 433 hb_blob_t *blob; 434 435 if (unlikely (!face || !face->get_table)) 436 return hb_blob_get_empty (); 437 438 blob = face->get_table (tag, face->user_data); 439 if (unlikely (!blob)) 440 return hb_blob_get_empty (); 441 442 return blob; 443} 444 445unsigned int 446hb_face_get_upem (hb_face_t *face) 447{ 448 return _hb_ot_layout_get_upem (face); 449} 450 451 452/* 453 * hb_font_t 454 */ 455 456static hb_font_t _hb_font_nil = { 457 HB_OBJECT_HEADER_STATIC, 458 459 TRUE, /* immutable */ 460 461 NULL, /* parent */ 462 &_hb_face_nil, 463 464 0, /* x_scale */ 465 0, /* y_scale */ 466 467 0, /* x_ppem */ 468 0, /* y_ppem */ 469 470 &_hb_font_funcs_nil, /* klass */ 471 NULL, /* user_data */ 472 NULL /* destroy */ 473}; 474 475hb_font_t * 476hb_font_create (hb_face_t *face) 477{ 478 hb_font_t *font; 479 480 if (unlikely (!face)) 481 face = &_hb_face_nil; 482 if (unlikely (hb_object_is_inert (face))) 483 return &_hb_font_nil; 484 if (!(font = hb_object_create<hb_font_t> ())) 485 return &_hb_font_nil; 486 487 font->face = hb_face_reference (face); 488 font->klass = &_hb_font_funcs_nil; 489 490 return font; 491} 492 493hb_font_t * 494hb_font_create_sub_font (hb_font_t *parent) 495{ 496 if (unlikely (!parent)) 497 return &_hb_font_nil; 498 499 hb_font_t *font = hb_font_create (parent->face); 500 501 if (unlikely (hb_object_is_inert (font))) 502 return font; 503 504 hb_font_make_immutable (parent); 505 font->parent = hb_font_reference (parent); 506 507 font->x_scale = parent->x_scale; 508 font->y_scale = parent->y_scale; 509 font->x_ppem = parent->x_ppem; 510 font->y_ppem = parent->y_ppem; 511 512 /* We can safely copy user_data from parent since we hold a reference 513 * onto it and it's immutable. We should not copy the destroy notifiers 514 * though. */ 515 font->klass = hb_font_funcs_reference (parent->klass); 516 font->user_data = parent->user_data; 517 518 return font; 519} 520 521hb_font_t * 522hb_font_reference (hb_font_t *font) 523{ 524 return hb_object_reference (font); 525} 526 527void 528hb_font_destroy (hb_font_t *font) 529{ 530 if (!hb_object_destroy (font)) return; 531 532 hb_font_destroy (font->parent); 533 hb_face_destroy (font->face); 534 hb_font_funcs_destroy (font->klass); 535 if (font->destroy) 536 font->destroy (font->user_data); 537 538 free (font); 539} 540 541hb_bool_t 542hb_font_set_user_data (hb_font_t *font, 543 hb_user_data_key_t *key, 544 void * data, 545 hb_destroy_func_t destroy) 546{ 547 return hb_object_set_user_data (font, key, data, destroy); 548} 549 550void * 551hb_font_get_user_data (hb_font_t *font, 552 hb_user_data_key_t *key) 553{ 554 return hb_object_get_user_data (font, key); 555} 556 557void 558hb_font_make_immutable (hb_font_t *font) 559{ 560 if (hb_object_is_inert (font)) 561 return; 562 563 font->immutable = true; 564} 565 566hb_bool_t 567hb_font_is_immutable (hb_font_t *font) 568{ 569 return font->immutable; 570} 571 572hb_font_t * 573hb_font_get_parent (hb_font_t *font) 574{ 575 return font->parent; 576} 577 578hb_face_t * 579hb_font_get_face (hb_font_t *font) 580{ 581 return font->face; 582} 583 584 585void 586hb_font_set_funcs (hb_font_t *font, 587 hb_font_funcs_t *klass, 588 void *user_data, 589 hb_destroy_func_t destroy) 590{ 591 if (font->immutable) 592 return; 593 594 if (font->destroy) 595 font->destroy (font->user_data); 596 597 if (!klass) 598 klass = &_hb_font_funcs_nil; 599 600 hb_font_funcs_reference (klass); 601 hb_font_funcs_destroy (font->klass); 602 font->klass = klass; 603 font->user_data = user_data; 604 font->destroy = destroy; 605} 606 607 608void 609hb_font_set_scale (hb_font_t *font, 610 int x_scale, 611 int y_scale) 612{ 613 if (font->immutable) 614 return; 615 616 font->x_scale = x_scale; 617 font->y_scale = y_scale; 618} 619 620void 621hb_font_get_scale (hb_font_t *font, 622 int *x_scale, 623 int *y_scale) 624{ 625 if (x_scale) *x_scale = font->x_scale; 626 if (y_scale) *y_scale = font->y_scale; 627} 628 629void 630hb_font_set_ppem (hb_font_t *font, 631 unsigned int x_ppem, 632 unsigned int y_ppem) 633{ 634 if (font->immutable) 635 return; 636 637 font->x_ppem = x_ppem; 638 font->y_ppem = y_ppem; 639} 640 641void 642hb_font_get_ppem (hb_font_t *font, 643 unsigned int *x_ppem, 644 unsigned int *y_ppem) 645{ 646 if (x_ppem) *x_ppem = font->x_ppem; 647 if (y_ppem) *y_ppem = font->y_ppem; 648} 649 650 651HB_END_DECLS 652