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