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