mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-21 04:00:11 +01:00
[quartz] Convert font handling from CGFont to CTFont.
This commit is contained in:
parent
cf351a8a0a
commit
c6dc5df612
5 changed files with 184 additions and 202 deletions
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
#include "cairo-error-private.h"
|
#include "cairo-error-private.h"
|
||||||
|
|
||||||
|
//#define DEBUG /* Uncomment this to get debug messages on the console. */
|
||||||
/**
|
/**
|
||||||
* SECTION:cairo-quartz-fonts
|
* SECTION:cairo-quartz-fonts
|
||||||
* @Title: Quartz (CGFont) Fonts
|
* @Title: Quartz (CGFont) Fonts
|
||||||
|
|
@ -66,11 +67,19 @@ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
|
||||||
static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL;
|
static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL;
|
||||||
|
|
||||||
static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
|
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 */
|
/* Defined in 10.11 */
|
||||||
#define CGGLYPH_MAX ((CGGlyph) 0xFFFE) /* kCGFontIndexMax */
|
#define CGGLYPH_MAX ((CGGlyph) 0xFFFE) /* kCGFontIndexMax */
|
||||||
#define CGGLYPH_INVALID ((CGGlyph) 0xFFFF) /* kCGFontIndexInvalid */
|
#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
|
static void
|
||||||
quartz_font_ensure_symbols(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 {
|
struct _cairo_quartz_scaled_font {
|
||||||
cairo_scaled_font_t base;
|
cairo_scaled_font_t base;
|
||||||
|
CTFontRef ctFont;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _cairo_quartz_font_face {
|
struct _cairo_quartz_font_face {
|
||||||
cairo_font_face_t base;
|
cairo_font_face_t base;
|
||||||
|
|
||||||
CGFontRef cgFont;
|
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;
|
const char *family;
|
||||||
char *full_name;
|
char *full_name;
|
||||||
CFStringRef FontName = NULL;
|
CFStringRef FontName = NULL;
|
||||||
CTFontRef ctFont = NULL;
|
CGFontRef cgFont = NULL;
|
||||||
int loop;
|
int loop;
|
||||||
|
|
||||||
family = toy_face->family;
|
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);
|
FontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII);
|
||||||
ctFont = CTFontCreateWithName (FontName, 1.0, NULL);
|
cgFont = CGFontCreateWithFontName (FontName);
|
||||||
CFRelease (FontName);
|
CFRelease (FontName);
|
||||||
|
|
||||||
if (ctFont)
|
if (cgFont)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctFont) {
|
if (!cgFont) {
|
||||||
/* Give up */
|
/* Give up */
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
*font_face = _cairo_quartz_font_face_create_for_ctfont (ctFont);
|
*font_face = cairo_quartz_font_face_create_for_cgfont (cgFont);
|
||||||
CFRelease (ctFont);
|
CFRelease (cgFont);
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
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;
|
cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
|
||||||
|
|
||||||
CGFontRelease (font_face->cgFont);
|
CGFontRelease (font_face->cgFont);
|
||||||
CFRelease (font_face->ctFont);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend;
|
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
|
static cairo_status_t
|
||||||
_cairo_quartz_font_face_scaled_font_create (void *abstract_face,
|
_cairo_quartz_font_face_scaled_font_create (void *abstract_face,
|
||||||
const cairo_matrix_t *font_matrix,
|
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_quartz_scaled_font_t *font = NULL;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
cairo_font_extents_t fs_metrics;
|
cairo_font_extents_t fs_metrics;
|
||||||
double ems;
|
CTFontRef ctFont;
|
||||||
CGRect bbox;
|
CGRect bbox;
|
||||||
|
|
||||||
font = _cairo_malloc (sizeof(cairo_quartz_scaled_font_t));
|
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)
|
if (status)
|
||||||
goto FINISH;
|
goto FINISH;
|
||||||
|
|
||||||
ems = CGFontGetUnitsPerEm (font_face->cgFont);
|
ctFont = CTFontCreateWithGraphicsFont (font_face->cgFont, font_scale, NULL, NULL);
|
||||||
|
|
||||||
/* initialize metrics */
|
/* initialize metrics */
|
||||||
fs_metrics.ascent = (CGFontGetAscent (font_face->cgFont) / ems);
|
fs_metrics.ascent = CTFontGetAscent (ctFont);
|
||||||
fs_metrics.descent = - (CGFontGetDescent (font_face->cgFont) / ems);
|
fs_metrics.descent = CTFontGetDescent (ctFont);
|
||||||
fs_metrics.height = fs_metrics.ascent + fs_metrics.descent +
|
fs_metrics.height = fs_metrics.ascent + fs_metrics.descent +
|
||||||
(CGFontGetLeading (font_face->cgFont) / ems);
|
CTFontGetLeading (ctFont);
|
||||||
|
|
||||||
bbox = CGFontGetFontBBox (font_face->cgFont);
|
bbox = CTFontGetBoundingBox (ctFont);
|
||||||
fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems;
|
fs_metrics.max_x_advance = CGRectGetMaxX(bbox);
|
||||||
fs_metrics.max_y_advance = 0.0;
|
fs_metrics.max_y_advance = 0.0;
|
||||||
|
font->ctFont = CFRetain (ctFont);
|
||||||
status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics);
|
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:
|
FINISH:
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
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_create_for_cgfont (CGFontRef font)
|
||||||
{
|
{
|
||||||
cairo_quartz_font_face_t* font_face = _cairo_quartz_font_face_create ();
|
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))
|
if (cairo_font_face_status (&font_face->base))
|
||||||
return &font_face->base;
|
return &font_face->base;
|
||||||
|
|
||||||
font_face->cgFont = CGFontRetain (font);
|
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;
|
return &font_face->base;
|
||||||
}
|
}
|
||||||
|
|
@ -315,6 +359,8 @@ _cairo_quartz_scaled_to_face (void *abstract_font)
|
||||||
static void
|
static void
|
||||||
_cairo_quartz_scaled_font_fini(void *abstract_font)
|
_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
|
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_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};
|
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
|
||||||
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
|
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
|
||||||
int advance;
|
CGSize advance;
|
||||||
CGRect bbox;
|
CGRect bbox;
|
||||||
double emscale = CGFontGetUnitsPerEm (font_face->cgFont);
|
|
||||||
double xmin, ymin, xmax, ymax;
|
double xmin, ymin, xmax, ymax;
|
||||||
|
|
||||||
if (unlikely (glyph == CGGLYPH_INVALID))
|
if (unlikely (glyph == CGGLYPH_INVALID))
|
||||||
goto FAIL;
|
goto FAIL;
|
||||||
|
|
||||||
if (!CGFontGetGlyphAdvances (font_face->cgFont, &glyph, 1, &advance) ||
|
CTFontGetAdvancesForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &advance, 1);
|
||||||
!CGFontGetGlyphBBoxes (font_face->cgFont, &glyph, 1, &bbox))
|
CTFontGetBoundingRectsForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &bbox, 1);
|
||||||
goto FAIL;
|
|
||||||
|
|
||||||
/* broken fonts like Al Bayan return incorrect bounds for some null characters,
|
/* broken fonts like Al Bayan return incorrect bounds for some null characters,
|
||||||
see https://bugzilla.mozilla.org/show_bug.cgi?id=534260 */
|
see https://bugzilla.mozilla.org/show_bug.cgi?id=534260 */
|
||||||
if (unlikely (bbox.origin.x == -32767 &&
|
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.size.width = bbox.size.height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bbox = CGRectMake (bbox.origin.x / emscale,
|
#ifdef DEBUG
|
||||||
bbox.origin.y / emscale,
|
fprintf (stderr, "[0x%04x] bbox: x %f y %f width %f height %f\n", glyph,
|
||||||
bbox.size.width / emscale,
|
bbox.origin.x, bbox.origin.y, bbox.size.width, bbox.size.height);
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xmin = CGRectGetMinX(bbox);
|
xmin = CGRectGetMinX(bbox);
|
||||||
|
|
@ -391,12 +411,12 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
|
||||||
extents.width = xmax - xmin;
|
extents.width = xmax - xmin;
|
||||||
extents.height = ymax - ymin;
|
extents.height = ymax - ymin;
|
||||||
|
|
||||||
extents.x_advance = (double) advance / emscale;
|
extents.x_advance = advance.width;
|
||||||
extents.y_advance = 0.0;
|
extents.y_advance = advance.height;
|
||||||
|
|
||||||
#if 0
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph,
|
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.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FAIL:
|
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[1].y),
|
||||||
_cairo_fixed_from_double(el->points[2].x),
|
_cairo_fixed_from_double(el->points[2].x),
|
||||||
_cairo_fixed_from_double(el->points[2].y));
|
_cairo_fixed_from_double(el->points[2].y));
|
||||||
assert(!status);
|
assert(!status);
|
||||||
break;
|
break;
|
||||||
case kCGPathElementCloseSubpath:
|
case kCGPathElementCloseSubpath:
|
||||||
status = _cairo_path_fixed_close_path (path);
|
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_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
|
||||||
cairo_scaled_glyph_t *scaled_glyph)
|
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);
|
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
|
||||||
CGAffineTransform textMatrix;
|
CGAffineTransform textMatrix;
|
||||||
CGPathRef glyphPath;
|
CGPathRef glyphPath;
|
||||||
|
|
@ -483,7 +502,7 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
|
||||||
-font->base.scale.yy,
|
-font->base.scale.yy,
|
||||||
0, 0);
|
0, 0);
|
||||||
|
|
||||||
glyphPath = CTFontCreatePathForGlyph (font_face->ctFont, glyph, &textMatrix);
|
glyphPath = CTFontCreatePathForGlyph (font->ctFont, glyph, &textMatrix);
|
||||||
|
|
||||||
if (!glyphPath)
|
if (!glyphPath)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
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_scaled_glyph_t *scaled_glyph)
|
||||||
{
|
{
|
||||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
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;
|
cairo_image_surface_t *surface = NULL;
|
||||||
|
|
||||||
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
|
CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
|
||||||
|
cairo_text_extents_t metrics = scaled_glyph->fs_metrics;
|
||||||
int advance;
|
CGRect bbox = CGRectMake (metrics.x_bearing, -(metrics.y_bearing + metrics.height),
|
||||||
CGRect bbox;
|
metrics.width, metrics.height);
|
||||||
double width, height;
|
double width, height;
|
||||||
double emscale = CGFontGetUnitsPerEm (font_face->cgFont);
|
|
||||||
|
|
||||||
CGContextRef cgContext = NULL;
|
|
||||||
CGAffineTransform textMatrix;
|
CGAffineTransform textMatrix;
|
||||||
CGRect glyphRect, glyphRectInt;
|
CGRect glyphRect, glyphRectInt;
|
||||||
CGPoint glyphOrigin;
|
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.
|
/* Create blank 2x2 image if we don't have this character.
|
||||||
* Maybe we should draw a better missing-glyph slug or something,
|
* Maybe we should draw a better missing-glyph slug or something,
|
||||||
* but this is ok for now.
|
* 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;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTFontGetBoundingRectsForGlyphs (font_face->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &bbox, 1);
|
|
||||||
|
|
||||||
/* scale(1,-1) * font->base.scale * scale(1,-1) */
|
/* scale(1,-1) * font->base.scale * scale(1,-1) */
|
||||||
textMatrix = CGAffineTransformMake (font->base.scale.xx,
|
textMatrix = CGAffineTransformMake (font->base.scale.xx,
|
||||||
-font->base.scale.yx,
|
-font->base.scale.yx,
|
||||||
-font->base.scale.xy,
|
-font->base.scale.xy,
|
||||||
font->base.scale.yy,
|
font->base.scale.yy,
|
||||||
0, -0);
|
0, 0);
|
||||||
glyphRect = CGRectMake (bbox.origin.x / emscale,
|
glyphRect = CGRectApplyAffineTransform (bbox, textMatrix);
|
||||||
bbox.origin.y / emscale,
|
|
||||||
bbox.size.width / emscale,
|
|
||||||
bbox.size.height / emscale);
|
|
||||||
|
|
||||||
glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix);
|
|
||||||
|
|
||||||
/* Round the rectangle outwards, so that we don't have to deal
|
/* Round the rectangle outwards, so that we don't have to deal
|
||||||
* with non-integer-pixel origins or dimensions.
|
* with non-integer-pixel origins or dimensions.
|
||||||
*/
|
*/
|
||||||
glyphRectInt = CGRectIntegral (glyphRect);
|
glyphRectInt = CGRectIntegral (glyphRect);
|
||||||
|
|
||||||
#if 0
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "glyphRect[o]: %f %f %f %f\n",
|
fprintf (stderr, "glyphRect[o]: %f %f %f %f\n",
|
||||||
glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
|
glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
|
||||||
fprintf (stderr, "glyphRectInt: %f %f %f %f\n",
|
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;
|
glyphOrigin = glyphRectInt.origin;
|
||||||
|
|
||||||
//textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));
|
|
||||||
|
|
||||||
width = glyphRectInt.size.width;
|
width = glyphRectInt.size.width;
|
||||||
height = glyphRectInt.size.height;
|
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);
|
surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
|
||||||
if (surface->base.status)
|
if (surface->base.status)
|
||||||
return surface->base.status;
|
return surface->base.status;
|
||||||
|
|
||||||
if (surface->width != 0 && surface->height != 0) {
|
if (surface->width != 0 && surface->height != 0) {
|
||||||
cgContext = CGBitmapContextCreate (surface->data,
|
CGContextRef cgContext = CGBitmapContextCreate (surface->data,
|
||||||
surface->width,
|
surface->width,
|
||||||
surface->height,
|
surface->height,
|
||||||
8,
|
8,
|
||||||
surface->stride,
|
surface->stride,
|
||||||
NULL,
|
NULL,
|
||||||
kCGImageAlphaOnly);
|
kCGImageAlphaOnly);
|
||||||
|
|
||||||
if (cgContext == NULL) {
|
if (cgContext == NULL) {
|
||||||
cairo_surface_destroy (&surface->base);
|
cairo_surface_destroy (&surface->base);
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextSetFont (cgContext, font_face->cgFont);
|
_cairo_quartz_set_antialiasing (cgContext, font->base.options.antialias);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGContextSetAlpha (cgContext, 1.0);
|
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);
|
CGContextRelease (cgContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -667,12 +648,11 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
|
||||||
uint32_t ucs4)
|
uint32_t ucs4)
|
||||||
{
|
{
|
||||||
cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font;
|
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];
|
CGGlyph glyph[2];
|
||||||
UniChar utf16[2];
|
UniChar utf16[2];
|
||||||
|
|
||||||
int len = _cairo_ucs4_to_utf16 (ucs4, utf16);
|
int len = _cairo_ucs4_to_utf16 (ucs4, utf16);
|
||||||
CTFontGetGlyphsForCharacters (ffont->ctFont, utf16, glyph, len);
|
CTFontGetGlyphsForCharacters (font->ctFont, utf16, glyph, len);
|
||||||
return glyph[0];
|
return glyph[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -683,8 +663,8 @@ _cairo_quartz_load_truetype_table (void *abstract_font,
|
||||||
unsigned char *buffer,
|
unsigned char *buffer,
|
||||||
unsigned long *length)
|
unsigned long *length)
|
||||||
{
|
{
|
||||||
cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face (abstract_font);
|
cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font;
|
||||||
CFDataRef data = CGFontCopyTableForTag (font_face->cgFont, tag);
|
CFDataRef data = CTFontCopyTable (font->ctFont, tag, kCTFontTableOptionNoOptions);
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
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;
|
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
|
* compat with old ATSUI backend
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ cairo_private CTFontRef
|
||||||
_cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *sfont);
|
_cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *sfont);
|
||||||
cairo_private cairo_font_face_t*
|
cairo_private cairo_font_face_t*
|
||||||
_cairo_quartz_font_face_create_for_ctfont (CTFontRef ctFont);
|
_cairo_quartz_font_face_create_for_ctfont (CTFontRef ctFont);
|
||||||
|
cairo_private void
|
||||||
|
_cairo_quartz_set_antialiasing (CGContextRef context, cairo_antialias_t antialias);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0)
|
#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
|
* SECTION:cairo-quartz
|
||||||
|
|
@ -1894,17 +1900,15 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor,
|
||||||
cairo_bool_t overlap)
|
cairo_bool_t overlap)
|
||||||
{
|
{
|
||||||
CGAffineTransform textTransform, invTextTransform;
|
CGAffineTransform textTransform, invTextTransform;
|
||||||
CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)];
|
CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGGlyph)];
|
||||||
CGSize cg_advances_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)];
|
CGPoint cg_positions_static[CAIRO_STACK_ARRAY_LENGTH (CGPoint)];
|
||||||
CGGlyph *cg_glyphs = &glyphs_static[0];
|
CGGlyph *cg_glyphs = &glyphs_static[0];
|
||||||
CGSize *cg_advances = &cg_advances_static[0];
|
CGPoint *cg_positions = &cg_positions_static[0];
|
||||||
COMPILE_TIME_ASSERT (sizeof (CGGlyph) <= sizeof (CGSize));
|
|
||||||
|
|
||||||
cairo_quartz_drawing_state_t state;
|
cairo_quartz_drawing_state_t state;
|
||||||
cairo_int_status_t rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
cairo_int_status_t rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||||
cairo_quartz_float_t xprev, yprev;
|
CGPoint origin;
|
||||||
int i;
|
CTFontRef ctFont = NULL;
|
||||||
CGFontRef cgfref = NULL;
|
|
||||||
|
|
||||||
cairo_bool_t didForceFontSmoothing = FALSE;
|
cairo_bool_t didForceFontSmoothing = FALSE;
|
||||||
|
|
||||||
|
|
@ -1923,45 +1927,17 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this doesn't addref */
|
/* this doesn't addref */
|
||||||
cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font);
|
ctFont = _cairo_quartz_scaled_font_get_ct_font (scaled_font);
|
||||||
CGContextSetFont (state.cgMaskContext, cgfref);
|
_cairo_quartz_set_antialiasing (state.cgMaskContext, scaled_font->options.antialias);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_glyphs > ARRAY_LENGTH (glyphs_static)) {
|
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)) {
|
if (unlikely (cg_glyphs == NULL)) {
|
||||||
rv = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
rv = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
goto BAIL;
|
goto BAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cg_advances = (CGSize*) (cg_glyphs + num_glyphs);
|
cg_positions = (CGPoint*) (cg_glyphs + num_glyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* scale(1,-1) * scaled_font->scale */
|
/* scale(1,-1) * scaled_font->scale */
|
||||||
|
|
@ -1978,36 +1954,23 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor,
|
||||||
-scaled_font->scale_inverse.yy,
|
-scaled_font->scale_inverse.yy,
|
||||||
0.0, 0.0);
|
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,
|
origin = CGPointMake (glyphs[0].x, glyphs[0].y);
|
||||||
* since the advance at index 0 is applied after glyph 0. */
|
for (int i = 0; i < num_glyphs; ++i)
|
||||||
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;
|
|
||||||
cg_glyphs[i] = glyphs[i].index;
|
cg_glyphs[i] = glyphs[i].index;
|
||||||
cg_advances[i - 1] = CGSizeApplyAffineTransform (CGSizeMake (xf - xprev, yf - yprev), invTextTransform);
|
cg_positions[i] = CGPointMake (glyphs[i].x - origin.x, glyphs[i].y - origin.y);
|
||||||
xprev = xf;
|
cg_positions[i] = CGPointApplyAffineTransform (cg_positions[i], invTextTransform);
|
||||||
yprev = yf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate to the first glyph's position before drawing */
|
/* 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);
|
CGContextConcatCTM (state.cgMaskContext, textTransform);
|
||||||
|
|
||||||
CGContextShowGlyphsWithAdvances (state.cgMaskContext,
|
CTFontDrawGlyphs (ctFont, cg_glyphs, cg_positions, num_glyphs, state.cgMaskContext);
|
||||||
cg_glyphs,
|
|
||||||
cg_advances,
|
|
||||||
num_glyphs);
|
|
||||||
|
|
||||||
CGContextConcatCTM (state.cgMaskContext, invTextTransform);
|
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)
|
if (state.action != DO_DIRECT)
|
||||||
_cairo_quartz_draw_source (&state, extents->op);
|
_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 |
Loading…
Add table
Reference in a new issue