diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2017-10-13 22:53:19 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2017-10-13 22:53:19 +0000 |
commit | 1031c01a2674825fe7037630e3f37f05fd1e739c (patch) | |
tree | ebfef9c9c109565c30c9b2bc8b601a703aafa487 /Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc | |
parent | eb1d91e185ce0b605a76da41e16cf0eb736edc06 (diff) |
harfbuzz-1.6.0
git-svn-id: svn://tug.org/texlive/trunk@45535 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc | 157 |
1 files changed, 92 insertions, 65 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc index ba96d3994ee..22661407dea 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-coretext.cc @@ -30,12 +30,27 @@ #include "hb-shaper-impl-private.hh" #include "hb-coretext.h" +#include <math.h> #ifndef HB_DEBUG_CORETEXT #define HB_DEBUG_CORETEXT (HB_DEBUG+0) #endif +/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ +#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f + +static CGFloat +coretext_font_size (float ptem) +{ + /* CoreText points are CSS pixels (96 per inch), + * NOT typographic points (72 per inch). + * + * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html + */ + ptem *= 96.f / 72.f; + return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem; +} static void release_table_data (void *user_data) @@ -62,16 +77,22 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) release_table_data); } +static void +_hb_cg_font_release (void *data) +{ + CGFontRelease ((CGFontRef) data); +} + hb_face_t * hb_coretext_face_create (CGFontRef cg_font) { - return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease); + return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release); } - HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) -HB_SHAPER_DATA_ENSURE_DEFINE(coretext, font) - +HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, + fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size (font->ptem)) <= .5 +) /* * shaper face data @@ -113,7 +134,7 @@ static CGFontRef create_cg_font (hb_face_t *face) { CGFontRef cg_font = NULL; - if (face->destroy == (hb_destroy_func_t) CGFontRelease) + if (face->destroy == _hb_cg_font_release) { cg_font = CGFontRetain ((CGFontRef) face->user_data); } @@ -140,7 +161,33 @@ create_cg_font (hb_face_t *face) static CTFontRef create_ct_font (CGFontRef cg_font, CGFloat font_size) { - CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL); + CTFontRef ct_font = NULL; + + /* CoreText does not enable trak table usage / tracking when creating a CTFont + * using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems + * to be through the CTFontCreateUIFontForLanguage call. */ + CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font); + if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) || + CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay"))) + { + CTFontUIFontType font_type = kCTFontUIFontSystem; + if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold"))) + font_type = kCTFontUIFontEmphasizedSystem; + + ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, NULL); + CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font); + if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo) + { + CFRelease(ct_font); + ct_font = NULL; + } + CFRelease (ct_result_name); + } + CFRelease (cg_postscript_name); + + if (!ct_font) + ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL); + if (unlikely (!ct_font)) { DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); return NULL; @@ -202,51 +249,24 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) return ct_font; } -struct hb_coretext_shaper_face_data_t { - CGFontRef cg_font; - CTFontRef ct_font; -}; - hb_coretext_shaper_face_data_t * _hb_coretext_shaper_face_data_create (hb_face_t *face) { - hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t)); - if (unlikely (!data)) - return NULL; + CGFontRef cg_font = create_cg_font (face); - data->cg_font = create_cg_font (face); - if (unlikely (!data->cg_font)) + if (unlikely (!cg_font)) { DEBUG_MSG (CORETEXT, face, "CGFont creation failed.."); - free (data); - return NULL; - } - - /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table, - * which can make the font too tight at large sizes. 36pt should be a good semi-neutral - * size. - * - * Since we always create CTFont at a fixed size, our CTFont lives in face_data - * instead of font_data. Which is good, because when people change scale on - * hb_font_t, we won't need to update our CTFont. */ - data->ct_font = create_ct_font (data->cg_font, 36.); - if (unlikely (!data->ct_font)) - { - DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); - CFRelease (data->cg_font); - free (data); return NULL; } - return data; + return (hb_coretext_shaper_face_data_t *) cg_font; } void _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) { - CFRelease (data->ct_font); - CFRelease (data->cg_font); - free (data); + CFRelease ((CGFontRef) data); } /* @@ -256,8 +276,7 @@ CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face) { if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->cg_font; + return (CGFontRef) HB_SHAPER_DATA_GET (face); } @@ -265,17 +284,28 @@ hb_coretext_face_get_cg_font (hb_face_t *face) * shaper font data */ -struct hb_coretext_shaper_font_data_t {}; - hb_coretext_shaper_font_data_t * -_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED) +_hb_coretext_shaper_font_data_create (hb_font_t *font) { - return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + hb_face_t *face = font->face; + if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; + CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); + + CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size (font->ptem)); + + if (unlikely (!ct_font)) + { + DEBUG_MSG (CORETEXT, font, "CGFont creation failed.."); + return NULL; + } + + return (hb_coretext_shaper_font_data_t *) ct_font; } void _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) { + CFRelease ((CTFontRef) data); } @@ -303,10 +333,8 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_ CTFontRef hb_coretext_font_get_ct_font (hb_font_t *font) { - hb_face_t *face = font->face; - if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->ct_font; + if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; + return (CTFontRef)HB_SHAPER_DATA_GET (font); } @@ -538,9 +566,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, unsigned int num_features) { hb_face_t *face = font->face; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); + CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font); - CGFloat ct_font_size = CTFontGetSize (face_data->ct_font); + CGFloat ct_font_size = CTFontGetSize (ct_font); CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size; @@ -675,7 +704,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); CFRelease (attributes); - range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc); + range->font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, font_desc); CFRelease (font_desc); } else @@ -829,7 +858,7 @@ resize_and_retry: CFRelease (lang); } CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), - kCTFontAttributeName, face_data->ct_font); + kCTFontAttributeName, ct_font); if (num_features && range_records.len) { @@ -947,7 +976,7 @@ resize_and_retry: */ CFDictionaryRef attributes = CTRunGetAttributes (run); CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName)); - if (!CFEqual (run_ct_font, face_data->ct_font)) + if (!CFEqual (run_ct_font, ct_font)) { /* The run doesn't use our main font instance. We have to figure out * whether font fallback happened, or this is just CoreText giving us @@ -985,13 +1014,13 @@ resize_and_retry: CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); if (run_cg_font) { - matched = CFEqual (run_cg_font, face_data->cg_font); + matched = CFEqual (run_cg_font, cg_font); CFRelease (run_cg_font); } } if (!matched) { - CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFontPostScriptNameKey); + CFStringRef font_ps_name = CTFontCopyName (ct_font, kCTFontPostScriptNameKey); CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey); CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0); CFRelease (run_ps_name); @@ -1263,22 +1292,20 @@ struct hb_coretext_aat_shaper_face_data_t {}; hb_coretext_aat_shaper_face_data_t * _hb_coretext_aat_shaper_face_data_create (hb_face_t *face) { - hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT); - /* Umm, we just reference the table to check whether it exists. - * Maybe add better API for this? */ - if (!hb_blob_get_length (mort_blob)) + static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX}; + + for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++) { - hb_blob_destroy (mort_blob); - mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX); - if (!hb_blob_get_length (mort_blob)) + hb_blob_t *blob = face->reference_table (tags[i]); + if (hb_blob_get_length (blob)) { - hb_blob_destroy (mort_blob); - return NULL; + hb_blob_destroy (blob); + return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; } + hb_blob_destroy (blob); } - hb_blob_destroy (mort_blob); - return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; + return NULL; } void |