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