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 * Copyright © 2015 Google, Inc. | 4 * Copyright © 2015 Google, Inc. |
5 * | 5 * |
6 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
7 * | 7 * |
8 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
9 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
10 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 * - 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? |
64 * | 64 * |
65 * - FT_Load_Glyph() is exteremely costly. Do something about it? | 65 * - FT_Load_Glyph() is exteremely costly. Do something about it? |
66 */ | 66 */ |
67 | 67 |
68 | 68 |
69 struct hb_ft_font_t | 69 struct hb_ft_font_t |
70 { | 70 { |
71 FT_Face ft_face; | 71 FT_Face ft_face; |
72 int load_flags; | 72 int load_flags; |
| 73 bool symbol; /* Whether selected cmap is symbol cmap. */ |
73 bool unref; /* Whether to destroy ft_face when done. */ | 74 bool unref; /* Whether to destroy ft_face when done. */ |
74 }; | 75 }; |
75 | 76 |
76 static hb_ft_font_t * | 77 static hb_ft_font_t * |
77 _hb_ft_font_create (FT_Face ft_face, bool unref) | 78 _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) |
78 { | 79 { |
79 hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); | 80 hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); |
80 | 81 |
81 if (unlikely (!ft_font)) | 82 if (unlikely (!ft_font)) |
82 return NULL; | 83 return NULL; |
83 | 84 |
84 ft_font->ft_face = ft_face; | 85 ft_font->ft_face = ft_face; |
| 86 ft_font->symbol = symbol; |
85 ft_font->unref = unref; | 87 ft_font->unref = unref; |
86 | 88 |
87 ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; | 89 ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; |
88 | 90 |
89 return ft_font; | 91 return ft_font; |
90 } | 92 } |
91 | 93 |
92 static void | 94 static void |
| 95 _hb_ft_face_destroy (FT_Face ft_face) |
| 96 { |
| 97 FT_Done_Face (ft_face); |
| 98 } |
| 99 |
| 100 static void |
93 _hb_ft_font_destroy (hb_ft_font_t *ft_font) | 101 _hb_ft_font_destroy (hb_ft_font_t *ft_font) |
94 { | 102 { |
95 if (ft_font->unref) | 103 if (ft_font->unref) |
96 FT_Done_Face (ft_font->ft_face); | 104 _hb_ft_face_destroy (ft_font->ft_face); |
97 | 105 |
98 free (ft_font); | 106 free (ft_font); |
99 } | 107 } |
100 | 108 |
101 /** | 109 /** |
102 * hb_ft_font_set_load_flags: | 110 * hb_ft_font_set_load_flags: |
103 * @font: | 111 * @font: |
104 * @load_flags: | 112 * @load_flags: |
105 * | 113 * |
106 * | 114 * |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, | 166 hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, |
159 void *font_data, | 167 void *font_data, |
160 hb_codepoint_t unicode, | 168 hb_codepoint_t unicode, |
161 hb_codepoint_t *glyph, | 169 hb_codepoint_t *glyph, |
162 void *user_data HB_UNUSED) | 170 void *user_data HB_UNUSED) |
163 { | 171 { |
164 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; | 172 const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; |
165 unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); | 173 unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); |
166 | 174 |
167 if (unlikely (!g)) | 175 if (unlikely (!g)) |
168 return false; | 176 { |
| 177 if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) |
| 178 { |
| 179 /* For symbol-encoded OpenType fonts, we duplicate the |
| 180 * U+F000..F0FF range at U+0000..U+00FF. That's what |
| 181 * Windows seems to do, and that's hinted about at: |
| 182 * http://www.microsoft.com/typography/otspec/recom.htm |
| 183 * under "Non-Standard (Symbol) Fonts". */ |
| 184 g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); |
| 185 if (!g) |
| 186 » return false; |
| 187 } |
| 188 else |
| 189 return false; |
| 190 } |
169 | 191 |
170 *glyph = g; | 192 *glyph = g; |
171 return true; | 193 return true; |
172 } | 194 } |
173 | 195 |
174 static hb_bool_t | 196 static hb_bool_t |
175 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, | 197 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED, |
176 void *font_data, | 198 void *font_data, |
177 hb_codepoint_t unicode, | 199 hb_codepoint_t unicode, |
178 hb_codepoint_t variation_selector, | 200 hb_codepoint_t variation_selector, |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { | 459 if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { |
438 hb_font_funcs_destroy (funcs); | 460 hb_font_funcs_destroy (funcs); |
439 goto retry; | 461 goto retry; |
440 } | 462 } |
441 | 463 |
442 #ifdef HB_USE_ATEXIT | 464 #ifdef HB_USE_ATEXIT |
443 atexit (free_static_ft_funcs); /* First person registers atexit() callback.
*/ | 465 atexit (free_static_ft_funcs); /* First person registers atexit() callback.
*/ |
444 #endif | 466 #endif |
445 }; | 467 }; |
446 | 468 |
| 469 bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS
_SYMBOL; |
| 470 |
447 hb_font_set_funcs (font, | 471 hb_font_set_funcs (font, |
448 funcs, | 472 funcs, |
449 » » _hb_ft_font_create (ft_face, unref), | 473 » » _hb_ft_font_create (ft_face, symbol, unref), |
450 (hb_destroy_func_t) _hb_ft_font_destroy); | 474 (hb_destroy_func_t) _hb_ft_font_destroy); |
451 } | 475 } |
452 | 476 |
453 | 477 |
454 static hb_blob_t * | 478 static hb_blob_t * |
455 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) | 479 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) |
456 { | 480 { |
457 FT_Face ft_face = (FT_Face) user_data; | 481 FT_Face ft_face = (FT_Face) user_data; |
458 FT_Byte *buffer; | 482 FT_Byte *buffer; |
459 FT_ULong length = 0; | 483 FT_ULong length = 0; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 * | 543 * |
520 * | 544 * |
521 * | 545 * |
522 * Return value: (transfer full): | 546 * Return value: (transfer full): |
523 * Since: 0.9.38 | 547 * Since: 0.9.38 |
524 **/ | 548 **/ |
525 hb_face_t * | 549 hb_face_t * |
526 hb_ft_face_create_referenced (FT_Face ft_face) | 550 hb_ft_face_create_referenced (FT_Face ft_face) |
527 { | 551 { |
528 FT_Reference_Face (ft_face); | 552 FT_Reference_Face (ft_face); |
529 return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face); | 553 return hb_ft_face_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); |
530 } | 554 } |
531 | 555 |
532 static void | 556 static void |
533 hb_ft_face_finalize (FT_Face ft_face) | 557 hb_ft_face_finalize (FT_Face ft_face) |
534 { | 558 { |
535 hb_face_destroy ((hb_face_t *) ft_face->generic.data); | 559 hb_face_destroy ((hb_face_t *) ft_face->generic.data); |
536 } | 560 } |
537 | 561 |
538 /** | 562 /** |
539 * hb_ft_face_create_cached: | 563 * hb_ft_face_create_cached: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 * | 623 * |
600 * | 624 * |
601 * | 625 * |
602 * Return value: (transfer full): | 626 * Return value: (transfer full): |
603 * Since: 0.9.38 | 627 * Since: 0.9.38 |
604 **/ | 628 **/ |
605 hb_font_t * | 629 hb_font_t * |
606 hb_ft_font_create_referenced (FT_Face ft_face) | 630 hb_ft_font_create_referenced (FT_Face ft_face) |
607 { | 631 { |
608 FT_Reference_Face (ft_face); | 632 FT_Reference_Face (ft_face); |
609 return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face); | 633 return hb_ft_font_create (ft_face, (hb_destroy_func_t) _hb_ft_face_destroy); |
610 } | 634 } |
611 | 635 |
612 | 636 |
613 /* Thread-safe, lock-free, FT_Library */ | 637 /* Thread-safe, lock-free, FT_Library */ |
614 | 638 |
615 static FT_Library ft_library; | 639 static FT_Library ft_library; |
616 | 640 |
617 #ifdef HB_USE_ATEXIT | 641 #ifdef HB_USE_ATEXIT |
618 static | 642 static |
619 void free_ft_library (void) | 643 void free_ft_library (void) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 blob_length, | 692 blob_length, |
669 hb_face_get_index (font->face), | 693 hb_face_get_index (font->face), |
670 &ft_face); | 694 &ft_face); |
671 | 695 |
672 if (unlikely (err)) { | 696 if (unlikely (err)) { |
673 hb_blob_destroy (blob); | 697 hb_blob_destroy (blob); |
674 DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed"); | 698 DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed"); |
675 return; | 699 return; |
676 } | 700 } |
677 | 701 |
678 FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); | 702 if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE)) |
| 703 FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL); |
679 | 704 |
680 FT_Set_Char_Size (ft_face, | 705 FT_Set_Char_Size (ft_face, |
681 abs (font->x_scale), abs (font->y_scale), | 706 abs (font->x_scale), abs (font->y_scale), |
682 0, 0); | 707 0, 0); |
683 #if 0 | 708 #if 0 |
684 font->x_ppem * 72 * 64 / font->x_scale, | 709 font->x_ppem * 72 * 64 / font->x_scale, |
685 font->y_ppem * 72 * 64 / font->y_scale); | 710 font->y_ppem * 72 * 64 / font->y_scale); |
686 #endif | 711 #endif |
687 if (font->x_scale < 0 || font->y_scale < 0) | 712 if (font->x_scale < 0 || font->y_scale < 0) |
688 { | 713 { |
689 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, | 714 FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0, |
690 0, font->y_scale < 0 ? -1 : +1}; | 715 0, font->y_scale < 0 ? -1 : +1}; |
691 FT_Set_Transform (ft_face, &matrix, NULL); | 716 FT_Set_Transform (ft_face, &matrix, NULL); |
692 } | 717 } |
693 | 718 |
694 ft_face->generic.data = blob; | 719 ft_face->generic.data = blob; |
695 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; | 720 ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; |
696 | 721 |
697 _hb_ft_font_set_funcs (font, ft_face, true); | 722 _hb_ft_font_set_funcs (font, ft_face, true); |
698 hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); | 723 hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); |
699 } | 724 } |
OLD | NEW |