1 diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
2 index a9bbbdc..48eb071 100644
3 --- a/src/cairo-quartz-font.c
4 +++ b/src/cairo-quartz-font.c
5 @@ -95,6 +95,10 @@ static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL;
6 static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL;
7 static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL;
9 +/* CTFontCreateWithGraphicsFont is not public until 10.5. */
10 +typedef const struct __CTFontDescriptor *CTFontDescriptorRef;
11 +static CTFontRef (*CTFontCreateWithGraphicsFontPtr) (CGFontRef, CGFloat, const CGAffineTransform *, CTFontDescriptorRef) = NULL;
13 /* Not public anymore in 64-bits nor in 10.7 */
14 static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL;
16 @@ -137,6 +141,8 @@ quartz_font_ensure_symbols(void)
17 CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
18 CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
20 + CTFontCreateWithGraphicsFontPtr = dlsym(RTLD_DEFAULT, "CTFontCreateWithGraphicsFont");
22 FMGetATSFontRefFromFontPtr = dlsym(RTLD_DEFAULT, "FMGetATSFontRefFromFont");
24 if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) &&
25 @@ -162,6 +168,7 @@ struct _cairo_quartz_font_face {
26 cairo_font_face_t base;
33 @@ -246,6 +253,10 @@ _cairo_quartz_font_face_destroy (void *abstract_face)
35 cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
37 + if (font_face->ctFont) {
38 + CFRelease (font_face->ctFont);
41 CGFontRelease (font_face->cgFont);
44 @@ -370,6 +381,12 @@ cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
46 font_face->cgFont = CGFontRetain (font);
48 + if (CTFontCreateWithGraphicsFontPtr) {
49 + font_face->ctFont = CTFontCreateWithGraphicsFontPtr (font, 1.0, NULL, NULL);
51 + font_face->ctFont = NULL;
54 _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
56 return &font_face->base;
57 @@ -812,6 +829,14 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
62 +_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *abstract_font)
64 + cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
66 + return ffont->ctFont;
70 * compat with old ATSUI backend
72 diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
73 index f841a49..3c1e5aa 100644
74 --- a/src/cairo-quartz-private.h
75 +++ b/src/cairo-quartz-private.h
76 @@ -57,6 +57,9 @@ typedef enum {
78 } cairo_quartz_action_t;
80 +/* define CTFontRef for pre-10.5 SDKs */
81 +typedef const struct __CTFont *CTFontRef;
83 typedef struct cairo_quartz_surface {
86 @@ -97,6 +100,9 @@ CairoQuartzCreateCGImage (cairo_format_t format,
87 cairo_private CGFontRef
88 _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
91 +_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *sfont);
95 # error Cairo was not compiled with support for the quartz backend
96 diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
97 index 1e2bbec..417255c 100644
98 --- a/src/cairo-quartz-surface.c
99 +++ b/src/cairo-quartz-surface.c
100 @@ -123,6 +123,9 @@ static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL;
101 static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL;
102 static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
104 +/* CTFontDrawGlyphs is not available until 10.7 */
105 +static void (*CTFontDrawGlyphsPtr) (CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef) = NULL;
107 static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE;
110 @@ -155,6 +158,8 @@ static void quartz_ensure_symbols (void)
111 CGContextGetAllowsFontSmoothingPtr = dlsym (RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
112 CGContextSetAllowsFontSmoothingPtr = dlsym (RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
114 + CTFontDrawGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
116 _cairo_quartz_symbol_lookup_done = TRUE;
119 @@ -2026,30 +2031,50 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor,
120 CGContextSetTextPosition (state.cgMaskContext, 0.0, 0.0);
121 CGContextSetTextMatrix (state.cgMaskContext, CGAffineTransformIdentity);
123 - /* Convert our glyph positions to glyph advances. We need n-1 advances,
124 - * since the advance at index 0 is applied after glyph 0. */
125 - xprev = glyphs[0].x;
126 - yprev = glyphs[0].y;
128 - cg_glyphs[0] = glyphs[0].index;
130 - for (i = 1; i < num_glyphs; i++) {
131 - cairo_quartz_float_t xf = glyphs[i].x;
132 - cairo_quartz_float_t yf = glyphs[i].y;
133 - cg_glyphs[i] = glyphs[i].index;
134 - cg_advances[i - 1] = CGSizeApplyAffineTransform (CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
139 /* Translate to the first glyph's position before drawing */
140 CGContextTranslateCTM (state.cgMaskContext, glyphs[0].x, glyphs[0].y);
141 CGContextConcatCTM (state.cgMaskContext, textTransform);
143 - CGContextShowGlyphsWithAdvances (state.cgMaskContext,
147 + if (CTFontDrawGlyphsPtr) {
148 + /* If CTFontDrawGlyphs is available (i.e. OS X 10.7 or later), we want to use
149 + * that in preference to CGContextShowGlyphsWithAdvances so that colored-bitmap
150 + * fonts like Apple Color Emoji will render properly.
151 + * For this, we need to convert our glyph positions to Core Graphics's CGPoint.
152 + * We borrow the cg_advances array, as CGPoint and CGSize are the same size. */
154 + CGPoint *cg_positions = (CGPoint*) cg_advances;
155 + cairo_quartz_float_t origin_x = glyphs[0].x;
156 + cairo_quartz_float_t origin_y = glyphs[0].y;
158 + for (i = 0; i < num_glyphs; i++) {
159 + CGPoint pt = CGPointMake (glyphs[i].x - origin_x, glyphs[i].y - origin_y);
160 + cg_positions[i] = CGPointApplyAffineTransform (pt, invTextTransform);
161 + cg_glyphs[i] = glyphs[i].index;
164 + CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (scaled_font),
165 + cg_glyphs, cg_positions, num_glyphs, state.cgMaskContext);
167 + /* Convert our glyph positions to glyph advances. We need n-1 advances,
168 + * since the advance at index 0 is applied after glyph 0. */
169 + xprev = glyphs[0].x;
170 + yprev = glyphs[0].y;
172 + cg_glyphs[0] = glyphs[0].index;
174 + for (i = 1; i < num_glyphs; i++) {
175 + cairo_quartz_float_t xf = glyphs[i].x;
176 + cairo_quartz_float_t yf = glyphs[i].y;
177 + cg_glyphs[i] = glyphs[i].index;
178 + cg_advances[i - 1] = CGSizeApplyAffineTransform (CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
182 + CGContextShowGlyphsWithAdvances (state.cgMaskContext,
188 CGContextConcatCTM (state.cgMaskContext, invTextTransform);
189 CGContextTranslateCTM (state.cgMaskContext, -glyphs[0].x, -glyphs[0].y);