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