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