37 |
37 |
38 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ |
38 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ |
39 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f |
39 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f |
40 |
40 |
41 static CGFloat |
41 static CGFloat |
42 coretext_font_size (float ptem) |
42 coretext_font_size_from_ptem (float ptem) |
43 { |
43 { |
44 /* CoreText points are CSS pixels (96 per inch), |
44 /* CoreText points are CSS pixels (96 per inch), |
45 * NOT typographic points (72 per inch). |
45 * NOT typographic points (72 per inch). |
46 * |
46 * |
47 * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html |
47 * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html |
48 */ |
48 */ |
49 ptem *= 96.f / 72.f; |
49 ptem *= 96.f / 72.f; |
50 return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem; |
50 return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem; |
51 } |
51 } |
|
52 static float |
|
53 coretext_font_size_to_ptem (CGFloat size) |
|
54 { |
|
55 size *= 72.f / 96.f; |
|
56 return size <= 0.f ? 0 : size; |
|
57 } |
52 |
58 |
53 static void |
59 static void |
54 release_table_data (void *user_data) |
60 release_table_data (void *user_data) |
55 { |
61 { |
56 CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data); |
62 CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data); |
66 return nullptr; |
72 return nullptr; |
67 |
73 |
68 const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data)); |
74 const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data)); |
69 const size_t length = CFDataGetLength (cf_data); |
75 const size_t length = CFDataGetLength (cf_data); |
70 if (!data || !length) |
76 if (!data || !length) |
|
77 { |
|
78 CFRelease (cf_data); |
71 return nullptr; |
79 return nullptr; |
|
80 } |
72 |
81 |
73 return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, |
82 return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, |
74 reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)), |
83 reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)), |
75 release_table_data); |
84 release_table_data); |
76 } |
85 } |
79 _hb_cg_font_release (void *data) |
88 _hb_cg_font_release (void *data) |
80 { |
89 { |
81 CGFontRelease ((CGFontRef) data); |
90 CGFontRelease ((CGFontRef) data); |
82 } |
91 } |
83 |
92 |
84 hb_face_t * |
|
85 hb_coretext_face_create (CGFontRef cg_font) |
|
86 { |
|
87 return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release); |
|
88 } |
|
89 |
93 |
90 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) |
94 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) |
91 HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, |
95 HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, |
92 fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size (font->ptem)) <= .5 |
96 fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5 |
93 ) |
97 ) |
94 |
|
95 /* |
|
96 * shaper face data |
|
97 */ |
|
98 |
98 |
99 static CTFontDescriptorRef |
99 static CTFontDescriptorRef |
100 get_last_resort_font_desc (void) |
100 get_last_resort_font_desc (void) |
101 { |
101 { |
102 // TODO Handle allocation failures? |
102 // TODO Handle allocation failures? |
276 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; |
282 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; |
277 return (CGFontRef) HB_SHAPER_DATA_GET (face); |
283 return (CGFontRef) HB_SHAPER_DATA_GET (face); |
278 } |
284 } |
279 |
285 |
280 |
286 |
281 /* |
|
282 * shaper font data |
|
283 */ |
|
284 |
|
285 hb_coretext_shaper_font_data_t * |
287 hb_coretext_shaper_font_data_t * |
286 _hb_coretext_shaper_font_data_create (hb_font_t *font) |
288 _hb_coretext_shaper_font_data_create (hb_font_t *font) |
287 { |
289 { |
288 hb_face_t *face = font->face; |
290 hb_face_t *face = font->face; |
289 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; |
291 if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; |
290 CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); |
292 CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); |
291 |
293 |
292 CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size (font->ptem)); |
294 CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem)); |
293 |
295 |
294 if (unlikely (!ct_font)) |
296 if (unlikely (!ct_font)) |
295 { |
297 { |
296 DEBUG_MSG (CORETEXT, font, "CGFont creation failed.."); |
298 DEBUG_MSG (CORETEXT, font, "CGFont creation failed.."); |
297 return nullptr; |
299 return nullptr; |
303 void |
305 void |
304 _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) |
306 _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) |
305 { |
307 { |
306 CFRelease ((CTFontRef) data); |
308 CFRelease ((CTFontRef) data); |
307 } |
309 } |
|
310 |
|
311 /* |
|
312 * Since: 1.7.2 |
|
313 */ |
|
314 hb_font_t * |
|
315 hb_coretext_font_create (CTFontRef ct_font) |
|
316 { |
|
317 CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr); |
|
318 hb_face_t *face = hb_coretext_face_create (cg_font); |
|
319 CFRelease (cg_font); |
|
320 hb_font_t *font = hb_font_create (face); |
|
321 hb_face_destroy (face); |
|
322 |
|
323 if (unlikely (hb_object_is_inert (font))) |
|
324 return font; |
|
325 |
|
326 hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font))); |
|
327 |
|
328 /* Let there be dragons here... */ |
|
329 HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font); |
|
330 |
|
331 return font; |
|
332 } |
|
333 |
|
334 CTFontRef |
|
335 hb_coretext_font_get_ct_font (hb_font_t *font) |
|
336 { |
|
337 if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr; |
|
338 return (CTFontRef) HB_SHAPER_DATA_GET (font); |
|
339 } |
|
340 |
308 |
341 |
309 |
342 |
310 /* |
343 /* |
311 * shaper shape_plan data |
344 * shaper shape_plan data |
312 */ |
345 */ |
852 CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault, |
878 CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault, |
853 hb_language_to_string (buffer->props.language), |
879 hb_language_to_string (buffer->props.language), |
854 kCFStringEncodingUTF8, |
880 kCFStringEncodingUTF8, |
855 kCFAllocatorNull); |
881 kCFAllocatorNull); |
856 if (unlikely (!lang)) |
882 if (unlikely (!lang)) |
|
883 { |
|
884 CFRelease (attr_string); |
857 FAIL ("CFStringCreateWithCStringNoCopy failed"); |
885 FAIL ("CFStringCreateWithCStringNoCopy failed"); |
|
886 } |
858 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
887 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
859 kCTLanguageAttributeName, lang); |
888 kCTLanguageAttributeName, lang); |
860 CFRelease (lang); |
889 CFRelease (lang); |
861 } |
890 } |
862 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
891 CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
921 1, |
950 1, |
922 &kCFTypeDictionaryKeyCallBacks, |
951 &kCFTypeDictionaryKeyCallBacks, |
923 &kCFTypeDictionaryValueCallBacks); |
952 &kCFTypeDictionaryValueCallBacks); |
924 CFRelease (level_number); |
953 CFRelease (level_number); |
925 if (unlikely (!options)) |
954 if (unlikely (!options)) |
|
955 { |
|
956 CFRelease (attr_string); |
926 FAIL ("CFDictionaryCreate failed"); |
957 FAIL ("CFDictionaryCreate failed"); |
|
958 } |
927 |
959 |
928 CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options); |
960 CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options); |
929 CFRelease (options); |
961 CFRelease (options); |
930 CFRelease (attr_string); |
962 CFRelease (attr_string); |
931 if (unlikely (!typesetter)) |
963 if (unlikely (!typesetter)) |
998 * backend. |
1030 * backend. |
999 * |
1031 * |
1000 * However, even that wouldn't work if we were passed in the CGFont to |
1032 * However, even that wouldn't work if we were passed in the CGFont to |
1001 * construct a hb_face to begin with. |
1033 * construct a hb_face to begin with. |
1002 * |
1034 * |
1003 * See: http://github.com/behdad/harfbuzz/pull/36 |
1035 * See: http://github.com/harfbuzz/harfbuzz/pull/36 |
1004 * |
1036 * |
1005 * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098 |
1037 * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098 |
1006 */ |
1038 */ |
1007 bool matched = false; |
1039 bool matched = false; |
1008 for (unsigned int i = 0; i < range_records.len; i++) |
1040 for (unsigned int i = 0; i < range_records.len; i++) |
1184 |
1216 |
1185 buffer->len += num_glyphs; |
1217 buffer->len += num_glyphs; |
1186 } |
1218 } |
1187 |
1219 |
1188 /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel, |
1220 /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel, |
1189 * or if it does, it doesn't resepct it. So we get runs with wrong |
1221 * or if it does, it doesn't respect it. So we get runs with wrong |
1190 * directions. As such, disable the assert... It wouldn't crash, but |
1222 * directions. As such, disable the assert... It wouldn't crash, but |
1191 * cursoring will be off... |
1223 * cursoring will be off... |
1192 * |
1224 * |
1193 * http://crbug.com/419769 |
1225 * http://crbug.com/419769 |
1194 */ |
1226 */ |
1210 { |
1242 { |
1211 pos->x_advance = info->mask; |
1243 pos->x_advance = info->mask; |
1212 pos->x_offset = info->var1.i32; |
1244 pos->x_offset = info->var1.i32; |
1213 pos->y_offset = info->var2.i32; |
1245 pos->y_offset = info->var2.i32; |
1214 |
1246 |
1215 info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; |
|
1216 |
|
1217 info++, pos++; |
1247 info++, pos++; |
1218 } |
1248 } |
1219 else |
1249 else |
1220 for (unsigned int i = 0; i < count; i++) |
1250 for (unsigned int i = 0; i < count; i++) |
1221 { |
1251 { |
1222 pos->y_advance = info->mask; |
1252 pos->y_advance = info->mask; |
1223 pos->x_offset = info->var1.i32; |
1253 pos->x_offset = info->var1.i32; |
1224 pos->y_offset = info->var2.i32; |
1254 pos->y_offset = info->var2.i32; |
1225 |
|
1226 info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; |
|
1227 |
1255 |
1228 info++, pos++; |
1256 info++, pos++; |
1229 } |
1257 } |
1230 |
1258 |
1231 /* Fix up clusters so that we never return out-of-order indices; |
1259 /* Fix up clusters so that we never return out-of-order indices; |