diff options
author | John Ralls <jralls@ceridwen.us> | 2022-04-21 17:19:15 -0700 |
---|---|---|
committer | John Ralls <jralls@ceridwen.us> | 2022-04-24 13:08:48 -0700 |
commit | c6dc5df61264be1bec2e622355b97c6c45d236fc (patch) | |
tree | a1813c4b01a33a4a944fe57ece09ac48526e8365 | |
parent | cf351a8a0a5c0be291061f58db9853a95b9044d3 (diff) |
[quartz] Convert font handling from CGFont to CTFont.
-rw-r--r-- | src/cairo-quartz-font.c | 301 | ||||
-rw-r--r-- | src/cairo-quartz-private.h | 2 | ||||
-rw-r--r-- | src/cairo-quartz-surface.c | 83 | ||||
-rw-r--r-- | test/reference/overlapping-glyphs.quartz.argb32.ref.png | bin | 2766 -> 2687 bytes | |||
-rw-r--r-- | test/reference/overlapping-glyphs.quartz.rgb24.ref.png | bin | 1667 -> 1630 bytes |
5 files changed, 184 insertions, 202 deletions
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c index 3a702ca0e..9e667e0d6 100644 --- a/src/cairo-quartz-font.c +++ b/src/cairo-quartz-font.c @@ -44,6 +44,7 @@ #include "cairo-error-private.h" +//#define DEBUG /* Uncomment this to get debug messages on the console. */ /** * SECTION:cairo-quartz-fonts * @Title: Quartz (CGFont) Fonts @@ -66,11 +67,19 @@ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL; static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE; +/* Cairo's transformations assume a unit-scaled font. */ +static const CGFloat font_scale = 1.0; /* Defined in 10.11 */ #define CGGLYPH_MAX ((CGGlyph) 0xFFFE) /* kCGFontIndexMax */ #define CGGLYPH_INVALID ((CGGlyph) 0xFFFF) /* kCGFontIndexInvalid */ +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 +#define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation +#else +#define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal +#endif + static void quartz_font_ensure_symbols(void) { @@ -90,14 +99,13 @@ typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t; struct _cairo_quartz_scaled_font { cairo_scaled_font_t base; + CTFontRef ctFont; }; struct _cairo_quartz_font_face { cairo_font_face_t base; CGFontRef cgFont; - CTFontRef ctFont; - double ctFont_scale; }; /* @@ -111,7 +119,7 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, const char *family; char *full_name; CFStringRef FontName = NULL; - CTFontRef ctFont = NULL; + CGFontRef cgFont = NULL; int loop; family = toy_face->family; @@ -151,20 +159,20 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, } FontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII); - ctFont = CTFontCreateWithName (FontName, 1.0, NULL); + cgFont = CGFontCreateWithFontName (FontName); CFRelease (FontName); - if (ctFont) + if (cgFont) break; } - if (!ctFont) { + if (!cgFont) { /* Give up */ return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - *font_face = _cairo_quartz_font_face_create_for_ctfont (ctFont); - CFRelease (ctFont); + *font_face = cairo_quartz_font_face_create_for_cgfont (cgFont); + CFRelease (cgFont); return CAIRO_STATUS_SUCCESS; } @@ -175,12 +183,56 @@ _cairo_quartz_font_face_destroy (void *abstract_face) cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face; CGFontRelease (font_face->cgFont); - CFRelease (font_face->ctFont); return TRUE; } static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend; +#ifdef DEBUG +static void +_cairo_quartz_debug_font_characteristics (cairo_quartz_scaled_font_t *font) +{ + CGRect ct_bbox = CTFontGetBoundingBox (font->ctFont); + CGFloat ct_ascent = CTFontGetAscent (font->ctFont); + CGFloat ct_descent = CTFontGetDescent (font->ctFont); + CGFloat ct_leading = CTFontGetLeading (font->ctFont); + CGFloat ct_capheight = CTFontGetCapHeight (font->ctFont); + CGFloat ct_xheight = CTFontGetXHeight (font->ctFont); + char chars[] = "ymMW"; + CGGlyph glyphs[4]; + UniChar *utf16 = NULL; + CGSize ct_advances[4]; + CGRect ct_gbbox[4], ct_gobox[4], ct_rbbox, ct_robox; + double ct_radvance; + int converted; + cairo_status_t rv; + + rv = _cairo_utf8_to_utf16 (chars, 4, &utf16, &converted); + if (rv) return; + CTFontGetGlyphsForCharacters (font->ctFont, utf16, glyphs, 4); + free (utf16); + ct_rbbox = CTFontGetBoundingRectsForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, glyphs, ct_gbbox, 4); + ct_robox = CTFontGetOpticalBoundsForGlyphs (font->ctFont, glyphs, ct_gobox, 4, 0); + ct_radvance = CTFontGetAdvancesForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, glyphs, ct_advances, 4); + + fprintf (stderr, "\nCTFont Bounding Box: %f %f %f %f\nAscent %f Descent %f Leading %f Cap Height %f X-Height %f\n", + ct_bbox.origin.x, ct_bbox.origin.y, ct_bbox.size.width, ct_bbox.size.height, ct_ascent, ct_descent, + ct_leading, ct_capheight, ct_xheight); + fprintf (stderr, "CTFont string\n\t bounding box %f %f %f %f advance %f\n\toptical box %f %f %f %f\n\n", + ct_rbbox.origin.x, ct_rbbox.origin.y, ct_rbbox.size.width, ct_rbbox.size.height, ct_radvance, + ct_robox.origin.x, ct_robox.origin.y, ct_robox.size.width, ct_robox.size.height); + for (int i = 0; i < 4; ++i) + { + fprintf (stderr, "Character %c\n", chars[i]); + fprintf (stderr, "\tbox %f %f %f %f\n\toptical %f %f %f %f advance %f %f\n", + ct_gbbox[i].origin.x, ct_gbbox[i].origin.y, ct_gbbox[i].size.width, ct_gbbox[i].size.height, + ct_advances[i].width, ct_advances[i].height, + ct_gobox[i].origin.x, ct_gobox[i].origin.y, ct_gobox[i].size.width, ct_gobox[i].size.height); + } + fprintf (stderr, "\n"); +} +#endif + static cairo_status_t _cairo_quartz_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, @@ -192,7 +244,7 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face, cairo_quartz_scaled_font_t *font = NULL; cairo_status_t status; cairo_font_extents_t fs_metrics; - double ems; + CTFontRef ctFont; CGRect bbox; font = _cairo_malloc (sizeof(cairo_quartz_scaled_font_t)); @@ -207,19 +259,29 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face, if (status) goto FINISH; - ems = CGFontGetUnitsPerEm (font_face->cgFont); - + ctFont = CTFontCreateWithGraphicsFont (font_face->cgFont, font_scale, NULL, NULL); /* initialize metrics */ - fs_metrics.ascent = (CGFontGetAscent (font_face->cgFont) / ems); - fs_metrics.descent = - (CGFontGetDescent (font_face->cgFont) / ems); + fs_metrics.ascent = CTFontGetAscent (ctFont); + fs_metrics.descent = CTFontGetDescent (ctFont); fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + - (CGFontGetLeading (font_face->cgFont) / ems); + CTFontGetLeading (ctFont); - bbox = CGFontGetFontBBox (font_face->cgFont); - fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; + bbox = CTFontGetBoundingBox (ctFont); + fs_metrics.max_x_advance = CGRectGetMaxX(bbox); fs_metrics.max_y_advance = 0.0; - + font->ctFont = CFRetain (ctFont); status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics); +#ifdef DEBUG + { + CFStringRef fontFullName = CTFontCopyFullName (ctFont); + const char* font_full_name = CFStringGetCStringPtr(fontFullName, kCFStringEncodingUTF8); + + fprintf (stderr, "Create scaled font %s with scale %f ascent %f, descent %f, height %f, x-advance %f\n", + font_full_name, fs_metrics.ascent, fs_metrics.descent, fs_metrics.height, + fs_metrics.max_x_advance); + _cairo_quartz_debug_font_characteristics (font); + } +#endif FINISH: if (status != CAIRO_STATUS_SUCCESS) { @@ -272,29 +334,11 @@ cairo_font_face_t * cairo_quartz_font_face_create_for_cgfont (CGFontRef font) { cairo_quartz_font_face_t* font_face = _cairo_quartz_font_face_create (); - double font_scale = 1.0; /* 1.0 produces glyphs of the right size to pass tests. */ if (cairo_font_face_status (&font_face->base)) return &font_face->base; font_face->cgFont = CGFontRetain (font); - font_face->ctFont = CTFontCreateWithGraphicsFont (font, font_scale, NULL, NULL); - font_face->ctFont_scale = CTFontGetUnitsPerEm(font_face->ctFont); - - return &font_face->base; -} - -cairo_font_face_t * -_cairo_quartz_font_face_create_for_ctfont (CTFontRef font) -{ - cairo_quartz_font_face_t* font_face = _cairo_quartz_font_face_create (); - - if (cairo_font_face_status (&font_face->base)) - return &font_face->base; - - font_face->ctFont = CFRetain (font); - font_face->cgFont = CTFontCopyGraphicsFont (font, NULL); - font_face->ctFont_scale = CTFontGetUnitsPerEm(font_face->ctFont); return &font_face->base; } @@ -315,6 +359,8 @@ _cairo_quartz_scaled_to_face (void *abstract_font) static void _cairo_quartz_scaled_font_fini(void *abstract_font) { + cairo_quartz_scaled_font_t* font = (cairo_quartz_scaled_font_t*)abstract_font; + CFRelease (font->ctFont); } static inline CGGlyph @@ -329,21 +375,17 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0}; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - int advance; + CGSize advance; CGRect bbox; - double emscale = CGFontGetUnitsPerEm (font_face->cgFont); double xmin, ymin, xmax, ymax; if (unlikely (glyph == CGGLYPH_INVALID)) goto FAIL; - if (!CGFontGetGlyphAdvances (font_face->cgFont, &glyph, 1, &advance) || - !CGFontGetGlyphBBoxes (font_face->cgFont, &glyph, 1, &bbox)) - goto FAIL; - + CTFontGetAdvancesForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &advance, 1); + CTFontGetBoundingRectsForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &bbox, 1); /* broken fonts like Al Bayan return incorrect bounds for some null characters, see https://bugzilla.mozilla.org/show_bug.cgi?id=534260 */ if (unlikely (bbox.origin.x == -32767 && @@ -354,31 +396,9 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, bbox.size.width = bbox.size.height = 0; } - bbox = CGRectMake (bbox.origin.x / emscale, - bbox.origin.y / emscale, - bbox.size.width / emscale, - bbox.size.height / emscale); - - /* Should we want to always integer-align glyph extents, we can do so in this way */ -#if 0 - { - CGAffineTransform textMatrix; - textMatrix = CGAffineTransformMake (font->base.scale.xx, - -font->base.scale.yx, - -font->base.scale.xy, - font->base.scale.yy, - 0.0f, 0.0f); - - bbox = CGRectApplyAffineTransform (bbox, textMatrix); - bbox = CGRectIntegral (bbox); - bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix)); - } -#endif - -#if 0 - fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph, - bbox.origin.x / emscale, bbox.origin.y / emscale, - bbox.size.width / emscale, bbox.size.height / emscale); +#ifdef DEBUG + fprintf (stderr, "[0x%04x] bbox: x %f y %f width %f height %f\n", glyph, + bbox.origin.x, bbox.origin.y, bbox.size.width, bbox.size.height); #endif xmin = CGRectGetMinX(bbox); @@ -391,12 +411,12 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, extents.width = xmax - xmin; extents.height = ymax - ymin; - extents.x_advance = (double) advance / emscale; - extents.y_advance = 0.0; + extents.x_advance = advance.width; + extents.y_advance = advance.height; -#if 0 - fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph, - extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance); +#ifdef DEBUG + fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f %f\n\n", glyph, + extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance); #endif FAIL: @@ -452,7 +472,7 @@ _cairo_quartz_path_apply_func (void *info, const CGPathElement *el) _cairo_fixed_from_double(el->points[1].y), _cairo_fixed_from_double(el->points[2].x), _cairo_fixed_from_double(el->points[2].y)); - assert(!status); + assert(!status); break; case kCGPathElementCloseSubpath: status = _cairo_path_fixed_close_path (path); @@ -465,7 +485,6 @@ static cairo_int_status_t _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); CGAffineTransform textMatrix; CGPathRef glyphPath; @@ -483,7 +502,7 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, -font->base.scale.yy, 0, 0); - glyphPath = CTFontCreatePathForGlyph (font_face->ctFont, glyph, &textMatrix); + glyphPath = CTFontCreatePathForGlyph (font->ctFont, glyph, &textMatrix); if (!glyphPath) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -508,25 +527,25 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); - cairo_image_surface_t *surface = NULL; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - - int advance; - CGRect bbox; + cairo_text_extents_t metrics = scaled_glyph->fs_metrics; + CGRect bbox = CGRectMake (metrics.x_bearing, -(metrics.y_bearing + metrics.height), + metrics.width, metrics.height); double width, height; - double emscale = CGFontGetUnitsPerEm (font_face->cgFont); - CGContextRef cgContext = NULL; CGAffineTransform textMatrix; CGRect glyphRect, glyphRectInt; CGPoint glyphOrigin; - //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface); - +#ifdef DEBUG + fprintf (stderr, "[0x%04x] bearing: %f %f width %f height %f advances %f %f\n", + glyph, metrics.x_bearing, metrics.y_bearing, metrics.width, metrics.height, + metrics.x_advance, metrics.y_advance); + fprintf (stderr, "[0x%04x] bounds: origin %f %f, size %f %f\n", glyph, bbox.origin.x, + bbox.origin.y, bbox.size.width, bbox.size.height); +#endif /* Create blank 2x2 image if we don't have this character. * Maybe we should draw a better missing-glyph slug or something, * but this is ok for now. @@ -543,27 +562,20 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, return CAIRO_STATUS_SUCCESS; } - CTFontGetBoundingRectsForGlyphs (font_face->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &bbox, 1); - /* scale(1,-1) * font->base.scale * scale(1,-1) */ textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, - 0, -0); - glyphRect = CGRectMake (bbox.origin.x / emscale, - bbox.origin.y / emscale, - bbox.size.width / emscale, - bbox.size.height / emscale); - - glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix); + 0, 0); + glyphRect = CGRectApplyAffineTransform (bbox, textMatrix); /* Round the rectangle outwards, so that we don't have to deal * with non-integer-pixel origins or dimensions. */ glyphRectInt = CGRectIntegral (glyphRect); -#if 0 +#ifdef DEBUG fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); fprintf (stderr, "glyphRectInt: %f %f %f %f\n", @@ -572,63 +584,32 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, glyphOrigin = glyphRectInt.origin; - //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm)); - width = glyphRectInt.size.width; height = glyphRectInt.size.height; - //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); - surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); if (surface->base.status) return surface->base.status; if (surface->width != 0 && surface->height != 0) { - cgContext = CGBitmapContextCreate (surface->data, - surface->width, - surface->height, - 8, - surface->stride, - NULL, - kCGImageAlphaOnly); + CGContextRef cgContext = CGBitmapContextCreate (surface->data, + surface->width, + surface->height, + 8, + surface->stride, + NULL, + kCGImageAlphaOnly); if (cgContext == NULL) { cairo_surface_destroy (&surface->base); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - CGContextSetFont (cgContext, font_face->cgFont); - CGContextSetFontSize (cgContext, 1.0); - CGContextSetTextMatrix (cgContext, textMatrix); - - switch (font->base.options.antialias) { - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_BEST: - CGContextSetShouldAntialias (cgContext, TRUE); - CGContextSetShouldSmoothFonts (cgContext, TRUE); - quartz_font_ensure_symbols (); - if (CGContextGetAllowsFontSmoothingPtr && - !CGContextGetAllowsFontSmoothingPtr (cgContext)) - CGContextSetAllowsFontSmoothing (cgContext, TRUE); - break; - case CAIRO_ANTIALIAS_NONE: - CGContextSetShouldAntialias (cgContext, FALSE); - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_GOOD: - case CAIRO_ANTIALIAS_FAST: - CGContextSetShouldAntialias (cgContext, TRUE); - CGContextSetShouldSmoothFonts (cgContext, FALSE); - break; - case CAIRO_ANTIALIAS_DEFAULT: - default: - /* Don't do anything */ - break; - } - + _cairo_quartz_set_antialiasing (cgContext, font->base.options.antialias); CGContextSetAlpha (cgContext, 1.0); - CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1); - + CGContextTranslateCTM (cgContext, -glyphOrigin.x, -glyphOrigin.y); + CGContextConcatCTM (cgContext, textMatrix); + CTFontDrawGlyphs (font->ctFont, &glyph, &CGPointZero, 1, cgContext); CGContextRelease (cgContext); } @@ -667,12 +648,11 @@ _cairo_quartz_ucs4_to_index (void *abstract_font, uint32_t ucs4) { cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; - cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font); CGGlyph glyph[2]; UniChar utf16[2]; int len = _cairo_ucs4_to_utf16 (ucs4, utf16); - CTFontGetGlyphsForCharacters (ffont->ctFont, utf16, glyph, len); + CTFontGetGlyphsForCharacters (font->ctFont, utf16, glyph, len); return glyph[0]; } @@ -683,8 +663,8 @@ _cairo_quartz_load_truetype_table (void *abstract_font, unsigned char *buffer, unsigned long *length) { - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face (abstract_font); - CFDataRef data = CGFontCopyTableForTag (font_face->cgFont, tag); + cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; + CFDataRef data = CTFontCopyTable (font->ctFont, tag, kCTFontTableOptionNoOptions); if (!data) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -728,6 +708,43 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font) return ffont->cgFont; } +CTFontRef +_cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *abstract_font) +{ + cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; + + return font->ctFont; +} + + void + _cairo_quartz_set_antialiasing (CGContextRef cgContext, cairo_antialias_t antialias) +{ + switch (antialias) { + case CAIRO_ANTIALIAS_SUBPIXEL: + case CAIRO_ANTIALIAS_BEST: + CGContextSetShouldAntialias (cgContext, TRUE); + CGContextSetShouldSmoothFonts (cgContext, TRUE); + quartz_font_ensure_symbols (); + if (CGContextGetAllowsFontSmoothingPtr && + !CGContextGetAllowsFontSmoothingPtr (cgContext)) + CGContextSetAllowsFontSmoothing (cgContext, TRUE); + break; + case CAIRO_ANTIALIAS_NONE: + CGContextSetShouldAntialias (cgContext, FALSE); + break; + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_GOOD: + case CAIRO_ANTIALIAS_FAST: + CGContextSetShouldAntialias (cgContext, TRUE); + CGContextSetShouldSmoothFonts (cgContext, FALSE); + break; + case CAIRO_ANTIALIAS_DEFAULT: + default: + /* Don't do anything */ + break; + } + +} /* * compat with old ATSUI backend */ diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h index e3600d5fc..f142f8471 100644 --- a/src/cairo-quartz-private.h +++ b/src/cairo-quartz-private.h @@ -109,6 +109,8 @@ cairo_private CTFontRef _cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *sfont); cairo_private cairo_font_face_t* _cairo_quartz_font_face_create_for_ctfont (CTFontRef ctFont); +cairo_private void +_cairo_quartz_set_antialiasing (CGContextRef context, cairo_antialias_t antialias); #else diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index bc6968c06..ae6546029 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -65,6 +65,12 @@ #endif #define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0) +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 +#define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation +#else +#define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal +#endif + /** * SECTION:cairo-quartz @@ -1894,17 +1900,15 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, cairo_bool_t overlap) { CGAffineTransform textTransform, invTextTransform; - CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)]; - CGSize cg_advances_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)]; + CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGGlyph)]; + CGPoint cg_positions_static[CAIRO_STACK_ARRAY_LENGTH (CGPoint)]; CGGlyph *cg_glyphs = &glyphs_static[0]; - CGSize *cg_advances = &cg_advances_static[0]; - COMPILE_TIME_ASSERT (sizeof (CGGlyph) <= sizeof (CGSize)); + CGPoint *cg_positions = &cg_positions_static[0]; cairo_quartz_drawing_state_t state; cairo_int_status_t rv = CAIRO_INT_STATUS_UNSUPPORTED; - cairo_quartz_float_t xprev, yprev; - int i; - CGFontRef cgfref = NULL; + CGPoint origin; + CTFontRef ctFont = NULL; cairo_bool_t didForceFontSmoothing = FALSE; @@ -1923,45 +1927,17 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, } /* this doesn't addref */ - cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font); - CGContextSetFont (state.cgMaskContext, cgfref); - CGContextSetFontSize (state.cgMaskContext, 1.0); - - switch (scaled_font->options.antialias) { - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_BEST: - CGContextSetShouldAntialias (state.cgMaskContext, TRUE); - CGContextSetShouldSmoothFonts (state.cgMaskContext, TRUE); - quartz_ensure_symbols(); - if (CGContextGetAllowsFontSmoothingPtr && - !CGContextGetAllowsFontSmoothingPtr (state.cgMaskContext)) - { - didForceFontSmoothing = TRUE; - CGContextSetAllowsFontSmoothing (state.cgMaskContext, TRUE); - } - break; - case CAIRO_ANTIALIAS_NONE: - CGContextSetShouldAntialias (state.cgMaskContext, FALSE); - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_GOOD: - case CAIRO_ANTIALIAS_FAST: - CGContextSetShouldAntialias (state.cgMaskContext, TRUE); - CGContextSetShouldSmoothFonts (state.cgMaskContext, FALSE); - break; - case CAIRO_ANTIALIAS_DEFAULT: - /* Don't do anything */ - break; - } + ctFont = _cairo_quartz_scaled_font_get_ct_font (scaled_font); + _cairo_quartz_set_antialiasing (state.cgMaskContext, scaled_font->options.antialias); if (num_glyphs > ARRAY_LENGTH (glyphs_static)) { - cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof (CGGlyph) + sizeof (CGSize)); + cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof (CGGlyph) + sizeof (CGPoint)); if (unlikely (cg_glyphs == NULL)) { rv = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL; } - cg_advances = (CGSize*) (cg_glyphs + num_glyphs); + cg_positions = (CGPoint*) (cg_glyphs + num_glyphs); } /* scale(1,-1) * scaled_font->scale */ @@ -1978,36 +1954,23 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, -scaled_font->scale_inverse.yy, 0.0, 0.0); - CGContextSetTextPosition (state.cgMaskContext, 0.0, 0.0); - CGContextSetTextMatrix (state.cgMaskContext, CGAffineTransformIdentity); - /* Convert our glyph positions to glyph advances. We need n-1 advances, - * since the advance at index 0 is applied after glyph 0. */ - xprev = glyphs[0].x; - yprev = glyphs[0].y; - - cg_glyphs[0] = glyphs[0].index; - - for (i = 1; i < num_glyphs; i++) { - cairo_quartz_float_t xf = glyphs[i].x; - cairo_quartz_float_t yf = glyphs[i].y; + origin = CGPointMake (glyphs[0].x, glyphs[0].y); + for (int i = 0; i < num_glyphs; ++i) + { cg_glyphs[i] = glyphs[i].index; - cg_advances[i - 1] = CGSizeApplyAffineTransform (CGSizeMake (xf - xprev, yf - yprev), invTextTransform); - xprev = xf; - yprev = yf; + cg_positions[i] = CGPointMake (glyphs[i].x - origin.x, glyphs[i].y - origin.y); + cg_positions[i] = CGPointApplyAffineTransform (cg_positions[i], invTextTransform); } /* Translate to the first glyph's position before drawing */ - CGContextTranslateCTM (state.cgMaskContext, glyphs[0].x, glyphs[0].y); + CGContextTranslateCTM (state.cgMaskContext, origin.x, origin.y); CGContextConcatCTM (state.cgMaskContext, textTransform); - CGContextShowGlyphsWithAdvances (state.cgMaskContext, - cg_glyphs, - cg_advances, - num_glyphs); + CTFontDrawGlyphs (ctFont, cg_glyphs, cg_positions, num_glyphs, state.cgMaskContext); CGContextConcatCTM (state.cgMaskContext, invTextTransform); - CGContextTranslateCTM (state.cgMaskContext, -glyphs[0].x, -glyphs[0].y); + CGContextTranslateCTM (state.cgMaskContext, -origin.x, -origin.y); if (state.action != DO_DIRECT) _cairo_quartz_draw_source (&state, extents->op); diff --git a/test/reference/overlapping-glyphs.quartz.argb32.ref.png b/test/reference/overlapping-glyphs.quartz.argb32.ref.png Binary files differindex 2bbbb3944..44200d59e 100644 --- a/test/reference/overlapping-glyphs.quartz.argb32.ref.png +++ b/test/reference/overlapping-glyphs.quartz.argb32.ref.png diff --git a/test/reference/overlapping-glyphs.quartz.rgb24.ref.png b/test/reference/overlapping-glyphs.quartz.rgb24.ref.png Binary files differindex a3961f8bf..d236e19a5 100644 --- a/test/reference/overlapping-glyphs.quartz.rgb24.ref.png +++ b/test/reference/overlapping-glyphs.quartz.rgb24.ref.png |