[quartz] Convert font handling from CGFont to CTFont.

This commit is contained in:
John Ralls 2022-04-21 17:19:15 -07:00
parent cf351a8a0a
commit c6dc5df612
5 changed files with 184 additions and 202 deletions

View file

@ -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
*/

View file

@ -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

View file

@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB