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 * Copyright © 2016 Ebrahim Byagowi |
4 * | 5 * |
5 * This is part of HarfBuzz, a text shaping library. | 6 * This is part of HarfBuzz, a text shaping library. |
6 * | 7 * |
7 * Permission is hereby granted, without written agreement and without | 8 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 9 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 10 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 11 * above copyright notice and the following two paragraphs appear in |
11 * all copies of this software. | 12 * all copies of this software. |
12 * | 13 * |
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
(...skipping 26 matching lines...) Expand all Loading... |
40 static void | 41 static void |
41 release_table_data (void *user_data) | 42 release_table_data (void *user_data) |
42 { | 43 { |
43 CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data); | 44 CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data); |
44 CFRelease(cf_data); | 45 CFRelease(cf_data); |
45 } | 46 } |
46 | 47 |
47 static hb_blob_t * | 48 static hb_blob_t * |
48 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) | 49 reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) |
49 { | 50 { |
50 CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data); | 51 CTFontRef ct_font = reinterpret_cast<CTFontRef> (user_data); |
51 CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag); | 52 CFDataRef cf_data = CTFontCopyTable (ct_font, tag, kCTFontTableOptionNoOptions
); |
52 if (unlikely (!cf_data)) | 53 if (unlikely (!cf_data)) |
53 return NULL; | 54 return NULL; |
54 | 55 |
55 const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data)); | 56 const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data)); |
56 const size_t length = CFDataGetLength (cf_data); | 57 const size_t length = CFDataGetLength (cf_data); |
57 if (!data || !length) | 58 if (!data || !length) |
58 return NULL; | 59 return NULL; |
59 | 60 |
60 return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, | 61 return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, |
61 reinterpret_cast<void *> (const_cast<__CFData *> (cf_da
ta)), | 62 reinterpret_cast<void *> (const_cast<__CFData *> (cf_da
ta)), |
62 release_table_data); | 63 release_table_data); |
63 } | 64 } |
64 | 65 |
| 66 static void |
| 67 hb_face_ct_font_destroyer (void *user_data) |
| 68 { |
| 69 CTFontRef ct_font = reinterpret_cast<CTFontRef> (user_data); |
| 70 CFRelease (ct_font); |
| 71 } |
| 72 |
| 73 /* |
| 74 * Since: 0.9.2 |
| 75 */ |
65 hb_face_t * | 76 hb_face_t * |
66 hb_coretext_face_create (CGFontRef cg_font) | 77 hb_coretext_face_create (CGFontRef cg_font) |
67 { | 78 { |
68 return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb
_destroy_func_t) CGFontRelease); | 79 return hb_face_create_for_tables (reference_table, |
| 80 (void*) CTFontCreateWithGraphicsFont (cg_fon
t, 36., 0, 0), |
| 81 hb_face_ct_font_destroyer); |
| 82 |
| 83 } |
| 84 |
| 85 /* |
| 86 * Since: 1.3.4 |
| 87 */ |
| 88 hb_face_t * |
| 89 hb_coretext_face_create_from_ct_font (CTFontRef ct_font) |
| 90 { |
| 91 return hb_face_create_for_tables (reference_table, |
| 92 (void*) CFRetain (ct_font), |
| 93 hb_face_ct_font_destroyer); |
69 } | 94 } |
70 | 95 |
71 | 96 |
72 HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) | 97 HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) |
73 HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) | 98 HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) |
74 | 99 |
75 | 100 |
76 /* | 101 /* |
77 * shaper face data | 102 * shaper face data |
78 */ | 103 */ |
(...skipping 14 matching lines...) Expand all Loading... |
93 1, | 118 1, |
94 &kCFTypeDictionaryKeyCallBack
s, | 119 &kCFTypeDictionaryKeyCallBack
s, |
95 &kCFTypeDictionaryValueCallBa
cks); | 120 &kCFTypeDictionaryValueCallBa
cks); |
96 CFRelease (cascade_list); | 121 CFRelease (cascade_list); |
97 | 122 |
98 CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attribut
es); | 123 CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attribut
es); |
99 CFRelease (attributes); | 124 CFRelease (attributes); |
100 return font_desc; | 125 return font_desc; |
101 } | 126 } |
102 | 127 |
103 static void | 128 static CTFontRef |
104 release_data (void *info, const void *data, size_t size) | 129 create_ct_font (CTFontDescriptorRef ct_font_descriptor, CGFloat font_size) |
105 { | 130 { |
106 assert (hb_blob_get_length ((hb_blob_t *) info) == size && | 131 CTFontRef ct_font = CTFontCreateWithFontDescriptor (ct_font_descriptor, font_s
ize, NULL); |
107 hb_blob_get_data ((hb_blob_t *) info, NULL) == data); | |
108 | |
109 hb_blob_destroy ((hb_blob_t *) info); | |
110 } | |
111 | |
112 static CGFontRef | |
113 create_cg_font (hb_face_t *face) | |
114 { | |
115 CGFontRef cg_font = NULL; | |
116 if (face->destroy == (hb_destroy_func_t) CGFontRelease) | |
117 { | |
118 cg_font = CGFontRetain ((CGFontRef) face->user_data); | |
119 } | |
120 else | |
121 { | |
122 hb_blob_t *blob = hb_face_reference_blob (face); | |
123 unsigned int blob_length; | |
124 const char *blob_data = hb_blob_get_data (blob, &blob_length); | |
125 if (unlikely (!blob_length)) | |
126 DEBUG_MSG (CORETEXT, face, "Face has empty blob"); | |
127 | |
128 CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data,
blob_length, &release_data); | |
129 if (likely (provider)) | |
130 { | |
131 cg_font = CGFontCreateWithDataProvider (provider); | |
132 if (unlikely (!cg_font)) | |
133 » DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed")
; | |
134 CGDataProviderRelease (provider); | |
135 } | |
136 } | |
137 return cg_font; | |
138 } | |
139 | |
140 static CTFontRef | |
141 create_ct_font (CGFontRef cg_font, CGFloat font_size) | |
142 { | |
143 CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NU
LL); | |
144 if (unlikely (!ct_font)) { | 132 if (unlikely (!ct_font)) { |
145 DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); | 133 DEBUG_MSG (CORETEXT, ct_font_descriptor, "Font CTFontCreateWithFontDescripto
r() failed"); |
146 return NULL; | 134 return NULL; |
147 } | 135 } |
148 | 136 |
149 /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter | 137 /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter |
150 * bug indicate that the cascade list reconfiguration occasionally causes | 138 * bug indicate that the cascade list reconfiguration occasionally causes |
151 * crashes in CoreText on OS X 10.9, thus let's skip this step on older | 139 * crashes in CoreText on OS X 10.9, thus let's skip this step on older |
152 * operating system versions. Except for the emoji font, where _not_ | 140 * operating system versions. Except for the emoji font, where _not_ |
153 * reconfiguring the cascade list causes CoreText crashes. For details, see | 141 * reconfiguring the cascade list causes CoreText crashes. For details, see |
154 * crbug.com/549610 */ | 142 * crbug.com/549610 */ |
155 if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < kCTVersionNumber
10_10) { | 143 // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h |
| 144 if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < 0x00070000) { |
156 CFStringRef fontName = CTFontCopyPostScriptName (ct_font); | 145 CFStringRef fontName = CTFontCopyPostScriptName (ct_font); |
157 bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) =
= kCFCompareEqualTo; | 146 bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) =
= kCFCompareEqualTo; |
158 CFRelease (fontName); | 147 CFRelease (fontName); |
159 if (!isEmojiFont) | 148 if (!isEmojiFont) |
160 return ct_font; | 149 return ct_font; |
161 } | 150 } |
162 | 151 |
163 CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttri
bute); | 152 CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttri
bute); |
164 | 153 |
165 /* Create font copy with cascade list that has LastResort first; this speeds u
p CoreText | 154 /* Create font copy with cascade list that has LastResort first; this speeds u
p CoreText |
(...skipping 29 matching lines...) Expand all Loading... |
195 else | 184 else |
196 DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed"); | 185 DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed"); |
197 } | 186 } |
198 | 187 |
199 if (original_url) | 188 if (original_url) |
200 CFRelease (original_url); | 189 CFRelease (original_url); |
201 return ct_font; | 190 return ct_font; |
202 } | 191 } |
203 | 192 |
204 struct hb_coretext_shaper_face_data_t { | 193 struct hb_coretext_shaper_face_data_t { |
205 CGFontRef cg_font; | |
206 CTFontRef ct_font; | 194 CTFontRef ct_font; |
| 195 hb_blob_t *blob; |
207 }; | 196 }; |
208 | 197 |
209 hb_coretext_shaper_face_data_t * | 198 hb_coretext_shaper_face_data_t * |
210 _hb_coretext_shaper_face_data_create (hb_face_t *face) | 199 _hb_coretext_shaper_face_data_create (hb_face_t *face) |
211 { | 200 { |
212 hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) call
oc (1, sizeof (hb_coretext_shaper_face_data_t)); | 201 hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) call
oc (1, sizeof (hb_coretext_shaper_face_data_t)); |
213 if (unlikely (!data)) | 202 if (unlikely (!data)) |
214 return NULL; | 203 return NULL; |
215 | 204 |
216 data->cg_font = create_cg_font (face); | 205 if (face->destroy == hb_face_ct_font_destroyer) |
217 if (unlikely (!data->cg_font)) | |
218 { | 206 { |
219 DEBUG_MSG (CORETEXT, face, "CGFont creation failed.."); | 207 data->ct_font = reinterpret_cast<CTFontRef> (CFRetain (face->user_data)); |
| 208 return data; |
| 209 } |
| 210 |
| 211 data->blob = hb_face_reference_blob (face); |
| 212 unsigned int blob_length; |
| 213 const char *blob_data = hb_blob_get_data (data->blob, &blob_length); |
| 214 if (unlikely (!blob_length)) |
| 215 { |
| 216 DEBUG_MSG (CORETEXT, face, "Face has empty blob"); |
220 free (data); | 217 free (data); |
221 return NULL; | 218 return NULL; |
222 } | 219 } |
| 220 |
| 221 CFDataRef cf_data = CFDataCreateWithBytesNoCopy (kCFAllocatorDefault, |
| 222 reinterpret_cast<const UInt8*
> (blob_data), |
| 223 blob_length, |
| 224 kCFAllocatorNull); |
| 225 if (unlikely (!cf_data)) |
| 226 { |
| 227 DEBUG_MSG (CORETEXT, face, "CFDataRef creation failed."); |
| 228 free (data); |
| 229 return NULL; |
| 230 } |
| 231 |
| 232 CTFontDescriptorRef ct_font_descriptor = CTFontManagerCreateFontDescriptorFrom
Data (cf_data); |
| 233 if (unlikely (!ct_font_descriptor)) |
| 234 { |
| 235 DEBUG_MSG (CORETEXT, face, "CTFontDescriptorRef creation failed."); |
| 236 CFRelease (cf_data); |
| 237 free (data); |
| 238 return NULL; |
| 239 } |
223 | 240 |
224 /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' ta
ble, | 241 /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' ta
ble, |
225 * which can make the font too tight at large sizes. 36pt should be a good se
mi-neutral | 242 * which can make the font too tight at large sizes. 36pt should be a good se
mi-neutral |
226 * size. | 243 * size. |
227 * | 244 * |
228 * Since we always create CTFont at a fixed size, our CTFont lives in face_dat
a | 245 * Since we always create CTFont at a fixed size, our CTFont lives in face_dat
a |
229 * instead of font_data. Which is good, because when people change scale on | 246 * instead of font_data. Which is good, because when people change scale on |
230 * hb_font_t, we won't need to update our CTFont. */ | 247 * hb_font_t, we won't need to update our CTFont. */ |
231 data->ct_font = create_ct_font (data->cg_font, 36.); | 248 data->ct_font = create_ct_font (ct_font_descriptor, 36.); |
232 if (unlikely (!data->ct_font)) | 249 if (unlikely (!data->ct_font)) |
233 { | 250 { |
234 DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); | 251 DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); |
235 CFRelease (data->cg_font); | 252 CFRelease (ct_font_descriptor); |
| 253 CFRelease (cf_data); |
| 254 hb_blob_destroy (data->blob); |
236 free (data); | 255 free (data); |
237 return NULL; | 256 return NULL; |
238 } | 257 } |
239 | 258 |
| 259 CFRelease (ct_font_descriptor); |
| 260 CFRelease (cf_data); |
| 261 |
240 return data; | 262 return data; |
241 } | 263 } |
242 | 264 |
243 void | 265 void |
244 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) | 266 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) |
245 { | 267 { |
246 CFRelease (data->ct_font); | 268 if (data->ct_font) |
247 CFRelease (data->cg_font); | 269 CFRelease (data->ct_font); |
| 270 if (data->blob) |
| 271 hb_blob_destroy (data->blob); |
248 free (data); | 272 free (data); |
249 } | 273 } |
250 | 274 |
251 /* | 275 /* |
252 * Since: 0.9.10 | 276 * Since: 0.9.10 |
253 */ | 277 */ |
254 CGFontRef | 278 CGFontRef |
255 hb_coretext_face_get_cg_font (hb_face_t *face) | 279 hb_coretext_face_get_cg_font (hb_face_t *face) |
256 { | 280 { |
257 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; | 281 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; |
258 hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); | 282 hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); |
259 return face_data->cg_font; | 283 return CTFontCopyGraphicsFont (face_data->ct_font, NULL); |
260 } | 284 } |
261 | 285 |
262 | 286 |
263 /* | 287 /* |
264 * shaper font data | 288 * shaper font data |
265 */ | 289 */ |
266 | 290 |
267 struct hb_coretext_shaper_font_data_t {}; | 291 struct hb_coretext_shaper_font_data_t {}; |
268 | 292 |
269 hb_coretext_shaper_font_data_t * | 293 hb_coretext_shaper_font_data_t * |
(...skipping 20 matching lines...) Expand all Loading... |
290 unsigned int num_user_featur
es HB_UNUSED) | 314 unsigned int num_user_featur
es HB_UNUSED) |
291 { | 315 { |
292 return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; | 316 return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; |
293 } | 317 } |
294 | 318 |
295 void | 319 void |
296 _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_
t *data HB_UNUSED) | 320 _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_
t *data HB_UNUSED) |
297 { | 321 { |
298 } | 322 } |
299 | 323 |
| 324 /* |
| 325 * Since: 0.9.2 |
| 326 */ |
300 CTFontRef | 327 CTFontRef |
301 hb_coretext_font_get_ct_font (hb_font_t *font) | 328 hb_coretext_font_get_ct_font (hb_font_t *font) |
302 { | 329 { |
303 hb_face_t *face = font->face; | 330 hb_face_t *face = font->face; |
304 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; | 331 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; |
305 hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); | 332 hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); |
306 return face_data->ct_font; | 333 return face_data->ct_font; |
307 } | 334 } |
308 | 335 |
309 | 336 |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 | 810 |
784 /* Adjust scratch, pchars, and log_cluster arrays. This is ugly, but really
the | 811 /* Adjust scratch, pchars, and log_cluster arrays. This is ugly, but really
the |
785 * cleanest way to do without completely restructuring the rest of this shap
er. */ | 812 * cleanest way to do without completely restructuring the rest of this shap
er. */ |
786 scratch = buffer->get_scratch_buffer (&scratch_size); | 813 scratch = buffer->get_scratch_buffer (&scratch_size); |
787 pchars = reinterpret_cast<UniChar *> (((char *) scratch + ((char *) pchars -
(char *) old_scratch))); | 814 pchars = reinterpret_cast<UniChar *> (((char *) scratch + ((char *) pchars -
(char *) old_scratch))); |
788 log_clusters = reinterpret_cast<unsigned int *> (((char *) scratch + ((char
*) log_clusters - (char *) old_scratch))); | 815 log_clusters = reinterpret_cast<unsigned int *> (((char *) scratch + ((char
*) log_clusters - (char *) old_scratch))); |
789 scratch += old_scratch_used; | 816 scratch += old_scratch_used; |
790 scratch_size -= old_scratch_used; | 817 scratch_size -= old_scratch_used; |
791 } | 818 } |
792 { | 819 { |
793 string_ref = CFStringCreateWithCharactersNoCopy (NULL, | 820 string_ref = CFStringCreateWithCharactersNoCopy (kCFAllocatorDefault, |
794 pchars, chars_len, | 821 pchars, chars_len, |
795 kCFAllocatorNull); | 822 kCFAllocatorNull); |
796 if (unlikely (!string_ref)) | 823 if (unlikely (!string_ref)) |
797 FAIL ("CFStringCreateWithCharactersNoCopy failed"); | 824 FAIL ("CFStringCreateWithCharactersNoCopy failed"); |
798 | 825 |
799 /* Create an attributed string, populate it, and create a line from it, then
release attributed string. */ | 826 /* Create an attributed string, populate it, and create a line from it, then
release attributed string. */ |
800 { | 827 { |
801 CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable
(kCFAllocatorDefault, | 828 CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable
(kCFAllocatorDefault, |
802
chars_len); | 829
chars_len); |
803 if (unlikely (!attr_string)) | 830 if (unlikely (!attr_string)) |
(...skipping 11 matching lines...) Expand all Loading... |
815 * The symbols was introduced in iOS 7.0. | 842 * The symbols was introduced in iOS 7.0. |
816 * At any rate, our fallback is safe and works fine. */ | 843 * At any rate, our fallback is safe and works fine. */ |
817 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 | 844 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 |
818 # define kCTLanguageAttributeName CFSTR ("NSLanguage") | 845 # define kCTLanguageAttributeName CFSTR ("NSLanguage") |
819 #endif | 846 #endif |
820 CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault, | 847 CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault, |
821 hb_language_to_strin
g (buffer->props.language), | 848 hb_language_to_strin
g (buffer->props.language), |
822 kCFStringEncodingUTF
8, | 849 kCFStringEncodingUTF
8, |
823 kCFAllocatorNull); | 850 kCFAllocatorNull); |
824 if (unlikely (!lang)) | 851 if (unlikely (!lang)) |
| 852 { |
| 853 CFRelease (attr_string); |
825 FAIL ("CFStringCreateWithCStringNoCopy failed"); | 854 FAIL ("CFStringCreateWithCStringNoCopy failed"); |
| 855 } |
826 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), | 856 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
827 kCTLanguageAttributeName, lang); | 857 kCTLanguageAttributeName, lang); |
828 CFRelease (lang); | 858 CFRelease (lang); |
829 } | 859 } |
830 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), | 860 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
831 kCTFontAttributeName, face_data->ct_font); | 861 kCTFontAttributeName, face_data->ct_font); |
832 | 862 |
833 if (num_features) | 863 if (num_features) |
834 { | 864 { |
835 unsigned int start = 0; | 865 unsigned int start = 0; |
(...skipping 23 matching lines...) Expand all Loading... |
859 | 889 |
860 int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; | 890 int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; |
861 CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberI
ntType, &level); | 891 CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberI
ntType, &level); |
862 CFDictionaryRef options = CFDictionaryCreate (kCFAllocatorDefault, | 892 CFDictionaryRef options = CFDictionaryCreate (kCFAllocatorDefault, |
863 (const void **) &kCTTypesett
erOptionForcedEmbeddingLevel, | 893 (const void **) &kCTTypesett
erOptionForcedEmbeddingLevel, |
864 (const void **) &level_numbe
r, | 894 (const void **) &level_numbe
r, |
865 1, | 895 1, |
866 &kCFTypeDictionaryKeyCallBac
ks, | 896 &kCFTypeDictionaryKeyCallBac
ks, |
867 &kCFTypeDictionaryValueCallB
acks); | 897 &kCFTypeDictionaryValueCallB
acks); |
868 if (unlikely (!options)) | 898 if (unlikely (!options)) |
| 899 { |
| 900 CFRelease (attr_string); |
869 FAIL ("CFDictionaryCreate failed"); | 901 FAIL ("CFDictionaryCreate failed"); |
| 902 } |
870 | 903 |
871 CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOpti
ons (attr_string, options); | 904 CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOpti
ons (attr_string, options); |
872 CFRelease (options); | 905 CFRelease (options); |
873 CFRelease (attr_string); | 906 CFRelease (attr_string); |
874 if (unlikely (!typesetter)) | 907 if (unlikely (!typesetter)) |
875 FAIL ("CTTypesetterCreateWithAttributedStringAndOptions failed"); | 908 FAIL ("CTTypesetterCreateWithAttributedStringAndOptions failed"); |
876 | 909 |
877 line = CTTypesetterCreateLine (typesetter, CFRangeMake(0, 0)); | 910 line = CTTypesetterCreateLine (typesetter, CFRangeMake(0, 0)); |
878 CFRelease (typesetter); | 911 CFRelease (typesetter); |
879 if (unlikely (!line)) | 912 if (unlikely (!line)) |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 */ | 982 */ |
950 bool matched = false; | 983 bool matched = false; |
951 for (unsigned int i = 0; i < range_records.len; i++) | 984 for (unsigned int i = 0; i < range_records.len; i++) |
952 if (range_records[i].font && CFEqual (run_ct_font, range_records[i].fo
nt)) | 985 if (range_records[i].font && CFEqual (run_ct_font, range_records[i].fo
nt)) |
953 { | 986 { |
954 matched = true; | 987 matched = true; |
955 break; | 988 break; |
956 } | 989 } |
957 if (!matched) | 990 if (!matched) |
958 { | 991 { |
959 » CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); | 992 » matched = CFEqual (run_ct_font, face_data->ct_font); |
960 » if (run_cg_font) | |
961 » { | |
962 » matched = CFEqual (run_cg_font, face_data->cg_font); | |
963 » CFRelease (run_cg_font); | |
964 » } | |
965 } | 993 } |
966 if (!matched) | 994 if (!matched) |
967 { | 995 { |
968 CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFont
PostScriptNameKey); | 996 CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFont
PostScriptNameKey); |
969 CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScri
ptNameKey); | 997 CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScri
ptNameKey); |
970 CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name
, 0); | 998 CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name
, 0); |
971 CFRelease (run_ps_name); | 999 CFRelease (run_ps_name); |
972 CFRelease (font_ps_name); | 1000 CFRelease (font_ps_name); |
973 if (result == kCFCompareEqualTo) | 1001 if (result == kCFCompareEqualTo) |
974 matched = true; | 1002 matched = true; |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 | 1324 |
1297 hb_bool_t | 1325 hb_bool_t |
1298 _hb_coretext_aat_shape (hb_shape_plan_t *shape_plan, | 1326 _hb_coretext_aat_shape (hb_shape_plan_t *shape_plan, |
1299 hb_font_t *font, | 1327 hb_font_t *font, |
1300 hb_buffer_t *buffer, | 1328 hb_buffer_t *buffer, |
1301 const hb_feature_t *features, | 1329 const hb_feature_t *features, |
1302 unsigned int num_features) | 1330 unsigned int num_features) |
1303 { | 1331 { |
1304 return _hb_coretext_shape (shape_plan, font, buffer, features, num_features); | 1332 return _hb_coretext_shape (shape_plan, font, buffer, features, num_features); |
1305 } | 1333 } |
OLD | NEW |