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 |