OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2012,2013 Mozilla Foundation. | 2 * Copyright © 2012,2013 Mozilla Foundation. |
3 * Copyright © 2012,2013 Google, Inc. | 3 * Copyright © 2012,2013 Google, Inc. |
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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 return face_data; | 133 return face_data; |
134 } | 134 } |
135 | 135 |
136 | 136 |
137 /* | 137 /* |
138 * shaper font data | 138 * shaper font data |
139 */ | 139 */ |
140 | 140 |
141 struct hb_coretext_shaper_font_data_t { | 141 struct hb_coretext_shaper_font_data_t { |
142 CTFontRef ct_font; | 142 CTFontRef ct_font; |
| 143 CGFloat x_mult, y_mult; /* From CT space to HB space. */ |
143 }; | 144 }; |
144 | 145 |
145 hb_coretext_shaper_font_data_t * | 146 hb_coretext_shaper_font_data_t * |
146 _hb_coretext_shaper_font_data_create (hb_font_t *font) | 147 _hb_coretext_shaper_font_data_create (hb_font_t *font) |
147 { | 148 { |
148 if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; | 149 if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; |
149 | 150 |
150 hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) call
oc (1, sizeof (hb_coretext_shaper_font_data_t)); | 151 hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) call
oc (1, sizeof (hb_coretext_shaper_font_data_t)); |
151 if (unlikely (!data)) | 152 if (unlikely (!data)) |
152 return NULL; | 153 return NULL; |
153 | 154 |
154 hb_face_t *face = font->face; | 155 hb_face_t *face = font->face; |
155 hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); | 156 hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); |
156 | 157 |
157 data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL,
NULL); | 158 /* Choose a CoreText font size and calculate multipliers to convert to HarfBuz
z space. */ |
| 159 CGFloat font_size = 36.; /* Default... */ |
| 160 /* No idea if the following is even a good idea. */ |
| 161 if (font->y_ppem) |
| 162 font_size = font->y_ppem; |
| 163 |
| 164 if (font_size < 0) |
| 165 font_size = -font_size; |
| 166 data->x_mult = (CGFloat) font->x_scale / font_size; |
| 167 data->y_mult = (CGFloat) font->y_scale / font_size; |
| 168 data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL
); |
158 if (unlikely (!data->ct_font)) { | 169 if (unlikely (!data->ct_font)) { |
159 DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); | 170 DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); |
160 free (data); | 171 free (data); |
161 return NULL; | 172 return NULL; |
162 } | 173 } |
163 | 174 |
164 return data; | 175 return data; |
165 } | 176 } |
166 | 177 |
167 void | 178 void |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 if (unlikely (!line)) | 780 if (unlikely (!line)) |
770 FAIL ("CTTypesetterCreateLine failed"); | 781 FAIL ("CTTypesetterCreateLine failed"); |
771 } | 782 } |
772 | 783 |
773 CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); | 784 CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); |
774 unsigned int num_runs = CFArrayGetCount (glyph_runs); | 785 unsigned int num_runs = CFArrayGetCount (glyph_runs); |
775 DEBUG_MSG (CORETEXT, NULL, "Num runs: %d", num_runs); | 786 DEBUG_MSG (CORETEXT, NULL, "Num runs: %d", num_runs); |
776 | 787 |
777 buffer->len = 0; | 788 buffer->len = 0; |
778 uint32_t status_and = ~0, status_or = 0; | 789 uint32_t status_and = ~0, status_or = 0; |
| 790 double advances_so_far = 0; |
779 | 791 |
780 const CFRange range_all = CFRangeMake (0, 0); | 792 const CFRange range_all = CFRangeMake (0, 0); |
781 | 793 |
782 for (unsigned int i = 0; i < num_runs; i++) | 794 for (unsigned int i = 0; i < num_runs; i++) |
783 { | 795 { |
784 CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i
)); | 796 CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i
)); |
785 CTRunStatus run_status = CTRunGetStatus (run); | 797 CTRunStatus run_status = CTRunGetStatus (run); |
786 status_or |= run_status; | 798 status_or |= run_status; |
787 status_and &= run_status; | 799 status_and &= run_status; |
788 DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); | 800 DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); |
| 801 double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL
, NULL); |
| 802 if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) |
| 803 run_advance = -run_advance; |
| 804 DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); |
789 | 805 |
790 /* CoreText does automatic font fallback (AKA "cascading") for characters | 806 /* CoreText does automatic font fallback (AKA "cascading") for characters |
791 * not supported by the requested font, and provides no way to turn it off
, | 807 * not supported by the requested font, and provides no way to turn it off
, |
792 * so we must detect if the returned run uses a font other than the reques
ted | 808 * so we must detect if the returned run uses a font other than the reques
ted |
793 * one and fill in the buffer with .notdef glyphs instead of random glyph | 809 * one and fill in the buffer with .notdef glyphs instead of random glyph |
794 * indices from a different font. | 810 * indices from a different font. |
795 */ | 811 */ |
796 CFDictionaryRef attributes = CTRunGetAttributes (run); | 812 CFDictionaryRef attributes = CTRunGetAttributes (run); |
797 CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attri
butes, kCTFontAttributeName)); | 813 CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attri
butes, kCTFontAttributeName)); |
798 if (!CFEqual (run_ct_font, font_data->ct_font)) | 814 if (!CFEqual (run_ct_font, font_data->ct_font)) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 } | 869 } |
854 if (!matched) | 870 if (!matched) |
855 { | 871 { |
856 CFRange range = CTRunGetStringRange (run); | 872 CFRange range = CTRunGetStringRange (run); |
857 DEBUG_MSG (CORETEXT, run, "Run used fallback font: %ld..%ld", | 873 DEBUG_MSG (CORETEXT, run, "Run used fallback font: %ld..%ld", |
858 range.location, range.location + range.length); | 874 range.location, range.location + range.length); |
859 if (!buffer->ensure_inplace (buffer->len + range.length)) | 875 if (!buffer->ensure_inplace (buffer->len + range.length)) |
860 goto resize_and_retry; | 876 goto resize_and_retry; |
861 hb_glyph_info_t *info = buffer->info + buffer->len; | 877 hb_glyph_info_t *info = buffer->info + buffer->len; |
862 | 878 |
863 » CGGlyph notdef = 0; | 879 » hb_codepoint_t notdef = 0; |
864 » double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFo
ntHorizontalOrientation, ¬def, NULL, 1); | 880 » hb_direction_t dir = buffer->props.direction; |
| 881 » hb_position_t x_advance, y_advance, x_offset, y_offset; |
| 882 » hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance
, &y_advance); |
| 883 » hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset,
&y_offset); |
| 884 » hb_position_t advance = x_advance + y_advance; |
| 885 » x_offset = -x_offset; |
| 886 » y_offset = -y_offset; |
865 | 887 |
866 unsigned int old_len = buffer->len; | 888 unsigned int old_len = buffer->len; |
867 for (CFIndex j = range.location; j < range.location + range.length; j+
+) | 889 for (CFIndex j = range.location; j < range.location + range.length; j+
+) |
868 { | 890 { |
869 UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); | 891 UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); |
870 if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location
< j) | 892 if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location
< j) |
871 { | 893 { |
872 ch = CFStringGetCharacterAtIndex (string_ref, j - 1); | 894 ch = CFStringGetCharacterAtIndex (string_ref, j - 1); |
873 if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu)) | 895 if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu)) |
874 /* This is the second of a surrogate pair. Don't need .notdef | 896 /* This is the second of a surrogate pair. Don't need .notdef |
875 * for this one. */ | 897 * for this one. */ |
876 continue; | 898 continue; |
877 } | 899 } |
| 900 if (buffer->unicode->is_default_ignorable (ch)) |
| 901 continue; |
878 | 902 |
879 info->codepoint = notdef; | 903 info->codepoint = notdef; |
880 info->cluster = log_clusters[j]; | 904 info->cluster = log_clusters[j]; |
881 | 905 |
882 info->mask = advance; | 906 info->mask = advance; |
883 » info->var1.u32 = 0; | 907 » info->var1.u32 = x_offset; |
884 » info->var2.u32 = 0; | 908 » info->var2.u32 = y_offset; |
885 | 909 |
886 info++; | 910 info++; |
887 buffer->len++; | 911 buffer->len++; |
888 } | 912 } |
889 if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) | 913 if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) |
890 buffer->reverse_range (old_len, buffer->len); | 914 buffer->reverse_range (old_len, buffer->len); |
| 915 advances_so_far += run_advance; |
891 continue; | 916 continue; |
892 } | 917 } |
893 } | 918 } |
894 | 919 |
895 unsigned int num_glyphs = CTRunGetGlyphCount (run); | 920 unsigned int num_glyphs = CTRunGetGlyphCount (run); |
896 if (num_glyphs == 0) | 921 if (num_glyphs == 0) |
897 continue; | 922 continue; |
898 | 923 |
899 if (!buffer->ensure_inplace (buffer->len + num_glyphs)) | 924 if (!buffer->ensure_inplace (buffer->len + num_glyphs)) |
900 goto resize_and_retry; | 925 goto resize_and_retry; |
901 | 926 |
902 hb_glyph_info_t *run_info = buffer->info + buffer->len; | 927 hb_glyph_info_t *run_info = buffer->info + buffer->len; |
903 | 928 |
904 /* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always | 929 /* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always |
905 * succeed, and so copying data to our own buffer will be rare. Reports | 930 * succeed, and so copying data to our own buffer will be rare. Reports |
906 * have it that this changed in OS X 10.10 Yosemite, and NULL is returned | 931 * have it that this changed in OS X 10.10 Yosemite, and NULL is returned |
907 * frequently. At any rate, we can test that codepath by setting USE_PTR | 932 * frequently. At any rate, we can test that codepath by setting USE_PTR |
908 * to false. */ | 933 * to false. */ |
909 | 934 |
910 #define USE_PTR true | 935 #define USE_PTR true |
911 | 936 |
912 #define SCRATCH_SAVE() \ | 937 #define SCRATCH_SAVE() \ |
913 unsigned int scratch_size_saved = scratch_size; \ | 938 unsigned int scratch_size_saved = scratch_size; \ |
914 hb_buffer_t::scratch_buffer_t *scratch_saved = scratch | 939 hb_buffer_t::scratch_buffer_t *scratch_saved = scratch |
915 | 940 |
916 #define SCRATCH_RESTORE() \ | 941 #define SCRATCH_RESTORE() \ |
917 scratch_size = scratch_size_saved; \ | 942 scratch_size = scratch_size_saved; \ |
918 scratch = scratch_saved; | 943 scratch = scratch_saved; |
919 | 944 |
920 { | 945 { /* Setup glyphs */ |
921 SCRATCH_SAVE(); | 946 SCRATCH_SAVE(); |
922 const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; | 947 const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; |
923 if (!glyphs) { | 948 if (!glyphs) { |
924 ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry)
; | 949 ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry)
; |
925 CTRunGetGlyphs (run, range_all, glyph_buf); | 950 CTRunGetGlyphs (run, range_all, glyph_buf); |
926 glyphs = glyph_buf; | 951 glyphs = glyph_buf; |
927 } | 952 } |
928 const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run)
: NULL; | 953 const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run)
: NULL; |
929 if (!string_indices) { | 954 if (!string_indices) { |
930 ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry)
; | 955 ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry)
; |
931 CTRunGetStringIndices (run, range_all, index_buf); | 956 CTRunGetStringIndices (run, range_all, index_buf); |
932 string_indices = index_buf; | 957 string_indices = index_buf; |
933 } | 958 } |
934 hb_glyph_info_t *info = run_info; | 959 hb_glyph_info_t *info = run_info; |
935 for (unsigned int j = 0; j < num_glyphs; j++) | 960 for (unsigned int j = 0; j < num_glyphs; j++) |
936 { | 961 { |
937 info->codepoint = glyphs[j]; | 962 info->codepoint = glyphs[j]; |
938 info->cluster = log_clusters[string_indices[j]]; | 963 info->cluster = log_clusters[string_indices[j]]; |
939 info++; | 964 info++; |
940 } | 965 } |
941 SCRATCH_RESTORE(); | 966 SCRATCH_RESTORE(); |
942 } | 967 } |
943 { | 968 { |
| 969 /* Setup positions. |
| 970 * Note that CoreText does not return advances for glyphs. As such, |
| 971 * for all but last glyph, we use the delta position to next glyph as |
| 972 * advance (in the advance direction only), and for last glyph we set |
| 973 * whatever is needed to make the whole run's advance add up. */ |
944 SCRATCH_SAVE(); | 974 SCRATCH_SAVE(); |
945 const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; | 975 const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; |
946 if (!positions) { | 976 if (!positions) { |
947 ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_ret
ry); | 977 ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_ret
ry); |
948 CTRunGetPositions (run, range_all, position_buf); | 978 CTRunGetPositions (run, range_all, position_buf); |
949 positions = position_buf; | 979 positions = position_buf; |
950 } | 980 } |
951 double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NU
LL, NULL); | |
952 DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); | |
953 hb_glyph_info_t *info = run_info; | 981 hb_glyph_info_t *info = run_info; |
| 982 CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult; |
954 if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) | 983 if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) |
955 { | 984 { |
| 985 hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; |
956 for (unsigned int j = 0; j < num_glyphs; j++) | 986 for (unsigned int j = 0; j < num_glyphs; j++) |
957 { | 987 { |
958 » double advance = (j + 1 < num_glyphs ? positions[j + 1].x : position
s[0].x + run_advance) - positions[j].x; | 988 » double advance; |
959 » info->mask = advance; | 989 » if (likely (j + 1 < num_glyphs)) |
960 » info->var1.u32 = positions[0].x; /* Yes, zero. */ | 990 » advance = positions[j + 1].x - positions[j].x; |
961 » info->var2.u32 = positions[j].y; | 991 » else /* last glyph */ |
| 992 » advance = run_advance - (positions[j].x - positions[0].x); |
| 993 » info->mask = advance * x_mult; |
| 994 » info->var1.u32 = x_offset; |
| 995 » info->var2.u32 = positions[j].y * y_mult; |
962 info++; | 996 info++; |
963 } | 997 } |
964 } | 998 } |
965 else | 999 else |
966 { | 1000 { |
967 » run_advance = -run_advance; | 1001 » hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult; |
968 for (unsigned int j = 0; j < num_glyphs; j++) | 1002 for (unsigned int j = 0; j < num_glyphs; j++) |
969 { | 1003 { |
970 » double advance = (j + 1 < num_glyphs ? positions[j + 1].y : position
s[0].y + run_advance) - positions[j].y; | 1004 » double advance; |
971 » info->mask = advance; | 1005 » if (likely (j + 1 < num_glyphs)) |
972 » info->var1.u32 = positions[j].x; | 1006 » advance = positions[j + 1].y - positions[j].y; |
973 » info->var2.u32 = positions[0].y; /* Yes, zero. */ | 1007 » else /* last glyph */ |
| 1008 » advance = run_advance - (positions[j].y - positions[0].y); |
| 1009 » info->mask = advance * y_mult; |
| 1010 » info->var1.u32 = positions[j].x * x_mult; |
| 1011 » info->var2.u32 = y_offset; |
974 info++; | 1012 info++; |
975 } | 1013 } |
976 } | 1014 } |
977 SCRATCH_RESTORE(); | 1015 SCRATCH_RESTORE(); |
| 1016 advances_so_far += run_advance; |
978 } | 1017 } |
979 #undef SCRATCH_RESTORE | 1018 #undef SCRATCH_RESTORE |
980 #undef SCRATCH_SAVE | 1019 #undef SCRATCH_SAVE |
981 #undef USE_PTR | 1020 #undef USE_PTR |
982 #undef ALLOCATE_ARRAY | 1021 #undef ALLOCATE_ARRAY |
983 | 1022 |
984 buffer->len += num_glyphs; | 1023 buffer->len += num_glyphs; |
985 } | 1024 } |
986 | 1025 |
987 /* Make sure all runs had the expected direction. */ | 1026 /* Make sure all runs had the expected direction. */ |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 | 1185 |
1147 hb_bool_t | 1186 hb_bool_t |
1148 _hb_coretext_aat_shape (hb_shape_plan_t *shape_plan, | 1187 _hb_coretext_aat_shape (hb_shape_plan_t *shape_plan, |
1149 hb_font_t *font, | 1188 hb_font_t *font, |
1150 hb_buffer_t *buffer, | 1189 hb_buffer_t *buffer, |
1151 const hb_feature_t *features, | 1190 const hb_feature_t *features, |
1152 unsigned int num_features) | 1191 unsigned int num_features) |
1153 { | 1192 { |
1154 return _hb_coretext_shape (shape_plan, font, buffer, features, num_features); | 1193 return _hb_coretext_shape (shape_plan, font, buffer, features, num_features); |
1155 } | 1194 } |
OLD | NEW |