Index: third_party/harfbuzz-ng/src/hb-coretext.cc |
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.cc b/third_party/harfbuzz-ng/src/hb-coretext.cc |
index 04cf0570f042807d411f0c28395dc7a446bca6d2..90c6653d00fe9fc90283963b9a43aea21a1a43f3 100644 |
--- a/third_party/harfbuzz-ng/src/hb-coretext.cc |
+++ b/third_party/harfbuzz-ng/src/hb-coretext.cc |
@@ -27,7 +27,6 @@ |
*/ |
#define HB_SHAPER coretext |
-#define hb_coretext_shaper_face_data_t CGFont |
#include "hb-shaper-impl-private.hh" |
#include "hb-coretext.h" |
@@ -78,6 +77,29 @@ HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) |
* shaper face data |
*/ |
+static CTFontDescriptorRef |
+get_last_resort_font_desc (void) |
+{ |
+ // TODO Handle allocation failures? |
+ CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0); |
+ CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault, |
+ (const void **) &last_resort, |
+ 1, |
+ &kCFTypeArrayCallBacks); |
+ CFRelease (last_resort); |
+ CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, |
+ (const void **) &kCTFontCascadeListAttribute, |
+ (const void **) &cascade_list, |
+ 1, |
+ &kCFTypeDictionaryKeyCallBacks, |
+ &kCFTypeDictionaryValueCallBacks); |
+ CFRelease (cascade_list); |
+ |
+ CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); |
+ CFRelease (attributes); |
+ return font_desc; |
+} |
+ |
static void |
release_data (void *info, const void *data, size_t size) |
{ |
@@ -87,14 +109,13 @@ release_data (void *info, const void *data, size_t size) |
hb_blob_destroy ((hb_blob_t *) info); |
} |
-hb_coretext_shaper_face_data_t * |
-_hb_coretext_shaper_face_data_create (hb_face_t *face) |
+static CGFontRef |
+create_cg_font (hb_face_t *face) |
{ |
- hb_coretext_shaper_face_data_t *data = NULL; |
- |
+ CGFontRef cg_font = NULL; |
if (face->destroy == (hb_destroy_func_t) CGFontRelease) |
{ |
- data = CGFontRetain ((CGFontRef) face->user_data); |
+ cg_font = CGFontRetain ((CGFontRef) face->user_data); |
} |
else |
{ |
@@ -107,13 +128,76 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) |
CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); |
if (likely (provider)) |
{ |
- data = CGFontCreateWithDataProvider (provider); |
+ cg_font = CGFontCreateWithDataProvider (provider); |
+ if (unlikely (!cg_font)) |
+ DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); |
CGDataProviderRelease (provider); |
} |
} |
+ return cg_font; |
+} |
- if (unlikely (!data)) { |
- DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); |
+static CTFontRef |
+create_ct_font (CGFontRef cg_font, CGFloat font_size) |
+{ |
+ CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL); |
+ if (unlikely (!ct_font)) { |
+ DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); |
+ return NULL; |
+ } |
+ |
+ /* Create font copy with cascade list that has LastResort first; this speeds up CoreText |
+ * font fallback which we don't need anyway. */ |
+ { |
+ CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc (); |
+ CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, last_resort_font_desc); |
+ CFRelease (last_resort_font_desc); |
+ if (new_ct_font) |
+ { |
+ CFRelease (ct_font); |
+ ct_font = new_ct_font; |
+ } |
+ else |
+ DEBUG_MSG (CORETEXT, ct_font, "Font copy with empty cascade list failed"); |
+ } |
+ |
+ 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; |
+ |
+ data->cg_font = create_cg_font (face); |
+ if (unlikely (!data->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; |
@@ -122,7 +206,9 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face) |
void |
_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) |
{ |
- CFRelease (data); |
+ CFRelease (data->ct_font); |
+ CFRelease (data->cg_font); |
+ free (data); |
} |
/* |
@@ -133,7 +219,7 @@ 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; |
+ return face_data->cg_font; |
} |
@@ -141,86 +227,17 @@ hb_coretext_face_get_cg_font (hb_face_t *face) |
* shaper font data |
*/ |
-struct hb_coretext_shaper_font_data_t { |
- CTFontRef ct_font; |
- CGFloat x_mult, y_mult; /* From CT space to HB space. */ |
-}; |
+struct hb_coretext_shaper_font_data_t {}; |
hb_coretext_shaper_font_data_t * |
-_hb_coretext_shaper_font_data_create (hb_font_t *font) |
+_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED) |
{ |
- if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; |
- |
- hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) calloc (1, sizeof (hb_coretext_shaper_font_data_t)); |
- if (unlikely (!data)) |
- return NULL; |
- |
- hb_face_t *face = font->face; |
- hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); |
- |
- /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */ |
- /* TODO: use upem instead of 36? */ |
- CGFloat font_size = 36.; /* Default... */ |
- /* No idea if the following is even a good idea. */ |
- if (font->y_ppem) |
- font_size = font->y_ppem; |
- |
- if (font_size < 0) |
- font_size = -font_size; |
- data->x_mult = (CGFloat) font->x_scale / font_size; |
- data->y_mult = (CGFloat) font->y_scale / font_size; |
- data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL); |
- if (unlikely (!data->ct_font)) { |
- DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); |
- free (data); |
- return NULL; |
- } |
- |
- /* Create font copy with cascade list that has LastResort first; this speeds up CoreText |
- * font fallback which we don't need anyway. */ |
- { |
- // TODO Handle allocation failures? |
- CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0); |
- CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault, |
- (const void **) &last_resort, |
- 1, |
- &kCFTypeArrayCallBacks); |
- CFRelease (last_resort); |
- CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, |
- (const void **) &kCTFontCascadeListAttribute, |
- (const void **) &cascade_list, |
- 1, |
- &kCFTypeDictionaryKeyCallBacks, |
- &kCFTypeDictionaryValueCallBacks); |
- CFRelease (cascade_list); |
- |
- CTFontDescriptorRef new_font_desc = CTFontDescriptorCreateWithAttributes (attributes); |
- CFRelease (attributes); |
- |
- CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (data->ct_font, 0.0, NULL, new_font_desc); |
- if (new_ct_font) |
- { |
- CFRelease (data->ct_font); |
- data->ct_font = new_ct_font; |
- } |
- else |
- DEBUG_MSG (CORETEXT, font, "Font copy with empty cascade list failed"); |
- } |
- |
- if (unlikely (!data->ct_font)) { |
- DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); |
- free (data); |
- return NULL; |
- } |
- |
- return data; |
+ return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; |
} |
void |
_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) |
{ |
- CFRelease (data->ct_font); |
- free (data); |
} |
@@ -246,9 +263,10 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_ |
CTFontRef |
hb_coretext_font_get_ct_font (hb_font_t *font) |
{ |
- if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; |
- hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); |
- return font_data->ct_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; |
} |
@@ -481,7 +499,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, |
{ |
hb_face_t *face = font->face; |
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); |
- hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); |
+ |
+ CGFloat ct_font_size = CTFontGetSize (face_data->ct_font); |
+ CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; |
+ CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size; |
/* Attach marks to their bases, to match the 'ot' shaper. |
* Adapted from hb-ot-shape:hb_form_clusters(). |
@@ -490,6 +511,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, |
* B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will |
* continue pointing to B2 even though B2 was merged into B1's |
* cluster... */ |
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) |
{ |
hb_unicode_funcs_t *unicode = buffer->unicode; |
unsigned int count = buffer->len; |
@@ -612,7 +634,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, |
CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); |
CFRelease (attributes); |
- range->font = CTFontCreateCopyWithAttributes (font_data->ct_font, 0.0, NULL, font_desc); |
+ range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc); |
CFRelease (font_desc); |
} |
else |
@@ -769,7 +791,7 @@ resize_and_retry: |
CFRelease (lang); |
} |
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), |
- kCTFontAttributeName, font_data->ct_font); |
+ kCTFontAttributeName, face_data->ct_font); |
if (num_features) |
{ |
@@ -862,7 +884,7 @@ resize_and_retry: |
*/ |
CFDictionaryRef attributes = CTRunGetAttributes (run); |
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName)); |
- if (!CFEqual (run_ct_font, font_data->ct_font)) |
+ if (!CFEqual (run_ct_font, face_data->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 |
@@ -902,13 +924,13 @@ resize_and_retry: |
CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); |
if (run_cg_font) |
{ |
- matched = CFEqual (run_cg_font, face_data); |
+ matched = CFEqual (run_cg_font, face_data->cg_font); |
CFRelease (run_cg_font); |
} |
} |
if (!matched) |
{ |
- CFStringRef font_ps_name = CTFontCopyName (font_data->ct_font, kCTFontPostScriptNameKey); |
+ CFStringRef font_ps_name = CTFontCopyName (face_data->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); |
@@ -1028,7 +1050,6 @@ resize_and_retry: |
positions = position_buf; |
} |
hb_glyph_info_t *info = run_info; |
- CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult; |
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) |
{ |
hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; |