| 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 |