| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2009 Red Hat, Inc. | 2 * Copyright © 2009 Red Hat, Inc. |
| 3 * Copyright © 2009 Keith Stribley | 3 * Copyright © 2009 Keith Stribley |
| 4 * | 4 * |
| 5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
| 6 * | 6 * |
| 7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
| 8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
| 9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
| 10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 /* TODO: | 44 /* TODO: |
| 45 * | 45 * |
| 46 * In general, this file does a fine job of what it's supposed to do. | 46 * In general, this file does a fine job of what it's supposed to do. |
| 47 * There are, however, things that need more work: | 47 * There are, however, things that need more work: |
| 48 * | 48 * |
| 49 * - We don't handle any load_flags. That definitely has API implications. :( | 49 * - We don't handle any load_flags. That definitely has API implications. :( |
| 50 * I believe hb_ft_font_create() should take load_flags input. | 50 * I believe hb_ft_font_create() should take load_flags input. |
| 51 * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be | 51 * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be |
| 52 * buggy. | 52 * buggy. |
| 53 * | 53 * |
| 54 * FreeType works in 26.6 mode. Clients can decide to use that mode, and ev
erything |
| 55 * would work fine. However, we also abuse this API for performing in font-
space, |
| 56 * but don't pass the correct flags to FreeType. We just abuse the no-hinti
ng mode |
| 57 * for that, such that no rounding etc happens. As such, we don't set ppem,
and |
| 58 * pass NO_HINTING around. This seems to work best, until we go ahead and a
dd a full |
| 59 * load_flags API. |
| 60 * |
| 54 * - We don't handle / allow for emboldening / obliqueing. | 61 * - We don't handle / allow for emboldening / obliqueing. |
| 55 * | 62 * |
| 56 * - In the future, we should add constructors to create fonts in font space? | 63 * - In the future, we should add constructors to create fonts in font space? |
| 57 * | 64 * |
| 58 * - FT_Load_Glyph() is exteremely costly. Do something about it? | 65 * - FT_Load_Glyph() is exteremely costly. Do something about it? |
| 59 */ | 66 */ |
| 60 | 67 |
| 61 | 68 |
| 62 static hb_bool_t | 69 static hb_bool_t |
| 63 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, | 70 hb_ft_get_glyph (hb_font_t *font HB_UNUSED, |
| 64 void *font_data, | 71 void *font_data, |
| 65 hb_codepoint_t unicode, | 72 hb_codepoint_t unicode, |
| 66 hb_codepoint_t variation_selector, | 73 hb_codepoint_t variation_selector, |
| 67 hb_codepoint_t *glyph, | 74 hb_codepoint_t *glyph, |
| 68 void *user_data HB_UNUSED) | 75 void *user_data HB_UNUSED) |
| 69 | 76 |
| 70 { | 77 { |
| 71 FT_Face ft_face = (FT_Face) font_data; | 78 FT_Face ft_face = (FT_Face) font_data; |
| 72 | 79 |
| 73 #ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX | |
| 74 if (unlikely (variation_selector)) { | 80 if (unlikely (variation_selector)) { |
| 75 *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); | 81 *glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); |
| 76 return *glyph != 0; | 82 return *glyph != 0; |
| 77 } | 83 } |
| 78 #endif | |
| 79 | 84 |
| 80 *glyph = FT_Get_Char_Index (ft_face, unicode); | 85 *glyph = FT_Get_Char_Index (ft_face, unicode); |
| 81 return *glyph != 0; | 86 return *glyph != 0; |
| 82 } | 87 } |
| 83 | 88 |
| 84 static hb_position_t | 89 static hb_position_t |
| 85 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, | 90 hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, |
| 86 void *font_data, | 91 void *font_data, |
| 87 hb_codepoint_t glyph, | 92 hb_codepoint_t glyph, |
| 88 void *user_data HB_UNUSED) | 93 void *user_data HB_UNUSED) |
| 89 { | 94 { |
| 90 FT_Face ft_face = (FT_Face) font_data; | 95 FT_Face ft_face = (FT_Face) font_data; |
| 91 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | 96 int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; |
| 92 FT_Fixed v; | 97 FT_Fixed v; |
| 93 | 98 |
| 94 if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) | 99 if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) |
| 95 return 0; | 100 return 0; |
| 96 | 101 |
| 102 if (font->x_scale < 0) |
| 103 v = -v; |
| 104 |
| 97 return (v + (1<<9)) >> 10; | 105 return (v + (1<<9)) >> 10; |
| 98 } | 106 } |
| 99 | 107 |
| 100 static hb_position_t | 108 static hb_position_t |
| 101 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, | 109 hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, |
| 102 void *font_data, | 110 void *font_data, |
| 103 hb_codepoint_t glyph, | 111 hb_codepoint_t glyph, |
| 104 void *user_data HB_UNUSED) | 112 void *user_data HB_UNUSED) |
| 105 { | 113 { |
| 106 FT_Face ft_face = (FT_Face) font_data; | 114 FT_Face ft_face = (FT_Face) font_data; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 hb_ft_face_create (FT_Face ft_face, | 341 hb_ft_face_create (FT_Face ft_face, |
| 334 hb_destroy_func_t destroy) | 342 hb_destroy_func_t destroy) |
| 335 { | 343 { |
| 336 hb_face_t *face; | 344 hb_face_t *face; |
| 337 | 345 |
| 338 if (ft_face->stream->read == NULL) { | 346 if (ft_face->stream->read == NULL) { |
| 339 hb_blob_t *blob; | 347 hb_blob_t *blob; |
| 340 | 348 |
| 341 blob = hb_blob_create ((const char *) ft_face->stream->base, | 349 blob = hb_blob_create ((const char *) ft_face->stream->base, |
| 342 (unsigned int) ft_face->stream->size, | 350 (unsigned int) ft_face->stream->size, |
| 343 » » » /* TODO: We assume that it's mmap()'ed, but FreeType
code | 351 » » » HB_MEMORY_MODE_READONLY, |
| 344 » » » * suggests that there are cases we reach here but fo
nt is | |
| 345 » » » * not mmapped. For example, when mmap() fails. No
idea | |
| 346 » » » * how to deal with it better here. */ | |
| 347 » » » HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, | |
| 348 ft_face, destroy); | 352 ft_face, destroy); |
| 349 face = hb_face_create (blob, ft_face->face_index); | 353 face = hb_face_create (blob, ft_face->face_index); |
| 350 hb_blob_destroy (blob); | 354 hb_blob_destroy (blob); |
| 351 } else { | 355 } else { |
| 352 face = hb_face_create_for_tables (reference_table, ft_face, destroy); | 356 face = hb_face_create_for_tables (reference_table, ft_face, destroy); |
| 353 } | 357 } |
| 354 | 358 |
| 355 hb_face_set_index (face, ft_face->face_index); | 359 hb_face_set_index (face, ft_face->face_index); |
| 356 hb_face_set_upem (face, ft_face->units_per_EM); | 360 hb_face_set_upem (face, ft_face->units_per_EM); |
| 357 | 361 |
| 358 return face; | 362 return face; |
| 359 } | 363 } |
| 360 | 364 |
| 365 /** |
| 366 * hb_ft_face_create_referenced: |
| 367 * @ft_face: |
| 368 * |
| 369 * |
| 370 * |
| 371 * Return value: (transfer full): |
| 372 * Since: 1.0 |
| 373 **/ |
| 374 hb_face_t * |
| 375 hb_ft_face_create_referenced (FT_Face ft_face) |
| 376 { |
| 377 FT_Reference_Face (ft_face); |
| 378 return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face); |
| 379 } |
| 380 |
| 361 static void | 381 static void |
| 362 hb_ft_face_finalize (FT_Face ft_face) | 382 hb_ft_face_finalize (FT_Face ft_face) |
| 363 { | 383 { |
| 364 hb_face_destroy ((hb_face_t *) ft_face->generic.data); | 384 hb_face_destroy ((hb_face_t *) ft_face->generic.data); |
| 365 } | 385 } |
| 366 | 386 |
| 367 /** | 387 /** |
| 368 * hb_ft_face_create_cached: | 388 * hb_ft_face_create_cached: |
| 369 * @ft_face: | 389 * @ft_face: |
| 370 * | 390 * |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 | 433 |
| 414 face = hb_ft_face_create (ft_face, destroy); | 434 face = hb_ft_face_create (ft_face, destroy); |
| 415 font = hb_font_create (face); | 435 font = hb_font_create (face); |
| 416 hb_face_destroy (face); | 436 hb_face_destroy (face); |
| 417 hb_font_set_funcs (font, | 437 hb_font_set_funcs (font, |
| 418 _hb_ft_get_font_funcs (), | 438 _hb_ft_get_font_funcs (), |
| 419 ft_face, (hb_destroy_func_t) _do_nothing); | 439 ft_face, (hb_destroy_func_t) _do_nothing); |
| 420 hb_font_set_scale (font, | 440 hb_font_set_scale (font, |
| 421 (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16), | 441 (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16), |
| 422 (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16)); | 442 (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64
_t) ft_face->units_per_EM + (1<<15)) >> 16)); |
| 443 #if 0 /* hb-ft works in no-hinting model */ |
| 423 hb_font_set_ppem (font, | 444 hb_font_set_ppem (font, |
| 424 ft_face->size->metrics.x_ppem, | 445 ft_face->size->metrics.x_ppem, |
| 425 ft_face->size->metrics.y_ppem); | 446 ft_face->size->metrics.y_ppem); |
| 447 #endif |
| 426 | 448 |
| 427 return font; | 449 return font; |
| 428 } | 450 } |
| 429 | 451 |
| 452 /** |
| 453 * hb_ft_font_create_referenced: |
| 454 * @ft_face: |
| 455 * |
| 456 * |
| 457 * |
| 458 * Return value: (transfer full): |
| 459 * Since: 1.0 |
| 460 **/ |
| 461 hb_font_t * |
| 462 hb_ft_font_create_referenced (FT_Face ft_face) |
| 463 { |
| 464 FT_Reference_Face (ft_face); |
| 465 return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face); |
| 466 } |
| 467 |
| 430 | 468 |
| 431 /* Thread-safe, lock-free, FT_Library */ | 469 /* Thread-safe, lock-free, FT_Library */ |
| 432 | 470 |
| 433 static FT_Library ft_library; | 471 static FT_Library ft_library; |
| 434 | 472 |
| 435 static inline | 473 #ifdef HB_USE_ATEXIT |
| 474 static |
| 436 void free_ft_library (void) | 475 void free_ft_library (void) |
| 437 { | 476 { |
| 438 FT_Done_FreeType (ft_library); | 477 FT_Done_FreeType (ft_library); |
| 439 } | 478 } |
| 479 #endif |
| 440 | 480 |
| 441 static FT_Library | 481 static FT_Library |
| 442 get_ft_library (void) | 482 get_ft_library (void) |
| 443 { | 483 { |
| 444 retry: | 484 retry: |
| 445 FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library); | 485 FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library); |
| 446 | 486 |
| 447 if (unlikely (!library)) | 487 if (unlikely (!library)) |
| 448 { | 488 { |
| 449 /* Not found; allocate one. */ | 489 /* Not found; allocate one. */ |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 &ft_face); | 526 &ft_face); |
| 487 | 527 |
| 488 if (unlikely (err)) { | 528 if (unlikely (err)) { |
| 489 hb_blob_destroy (blob); | 529 hb_blob_destroy (blob); |
| 490 DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed"); | 530 DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed"); |
| 491 return; | 531 return; |
| 492 } | 532 } |
| 493 | 533 |
| 494 FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); | 534 FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); |
| 495 | 535 |
| 496 assert (font->y_scale >= 0); | |
| 497 FT_Set_Char_Size (ft_face, | 536 FT_Set_Char_Size (ft_face, |
| 498 » » font->x_scale, font->y_scale, | 537 » » abs (font->x_scale), abs (font->y_scale), |
| 499 0, 0); | 538 0, 0); |
| 500 #if 0 | 539 #if 0 |
| 501 font->x_ppem * 72 * 64 / font->x_scale, | 540 font->x_ppem * 72 * 64 / font->x_scale, |
| 502 font->y_ppem * 72 * 64 / font->y_scale); | 541 font->y_ppem * 72 * 64 / font->y_scale); |
| 503 #endif | 542 #endif |
| 543 if (font->x_scale < 0 || font->y_scale < 0) |
| 544 { |
| 545 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, |
| 546 0, font->y_scale < 0 ? -1 : +1}; |
| 547 FT_Set_Transform (ft_face, &matrix, NULL); |
| 548 } |
| 504 | 549 |
| 505 ft_face->generic.data = blob; | 550 ft_face->generic.data = blob; |
| 506 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; | 551 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; |
| 507 | 552 |
| 508 hb_font_set_funcs (font, | 553 hb_font_set_funcs (font, |
| 509 _hb_ft_get_font_funcs (), | 554 _hb_ft_get_font_funcs (), |
| 510 ft_face, | 555 ft_face, |
| 511 (hb_destroy_func_t) FT_Done_Face); | 556 (hb_destroy_func_t) FT_Done_Face); |
| 512 } | 557 } |
| 513 | 558 |
| 514 FT_Face | 559 FT_Face |
| 515 hb_ft_font_get_face (hb_font_t *font) | 560 hb_ft_font_get_face (hb_font_t *font) |
| 516 { | 561 { |
| 517 if (font->destroy == (hb_destroy_func_t) FT_Done_Face || | 562 if (font->destroy == (hb_destroy_func_t) FT_Done_Face || |
| 518 font->destroy == (hb_destroy_func_t) _do_nothing) | 563 font->destroy == (hb_destroy_func_t) _do_nothing) |
| 519 return (FT_Face) font->user_data; | 564 return (FT_Face) font->user_data; |
| 520 | 565 |
| 521 return NULL; | 566 return NULL; |
| 522 } | 567 } |
| OLD | NEW |