[cairo-commit] src/cairo-quartz-surface.c

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Fri Mar 7 00:00:38 PST 2008


 src/cairo-quartz-surface.c |   65 ++++++++++++++++++++++++---------------------
 1 file changed, 36 insertions(+), 29 deletions(-)

New commits:
commit b52f127c12fd7ee2b4f532954cb1e9e4eb8561b4
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Thu Mar 6 16:52:54 2008 -0800

    [quartz] fix text rendering with gradient or image source
    
    A quirk in how CGContextShowGlyphsWithAdvances works was causing all
    non-solid glyphs to be rendered on top of eachother.  This fixes the problem.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index f26cc51..a9f6580 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1473,8 +1473,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 				    int num_glyphs,
 				    cairo_scaled_font_t *scaled_font)
 {
-    CGAffineTransform cairoTextTransform, textTransform, ctm;
-    // XXXtodo/perf: stack storage for glyphs/sizes
+    CGAffineTransform textTransform, ctm;
 #define STATIC_BUF_SIZE 64
     CGGlyph glyphs_static[STATIC_BUF_SIZE];
     CGSize cg_advances_static[STATIC_BUF_SIZE];
@@ -1488,6 +1487,8 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
     int i;
     CGFontRef cgfref;
 
+    cairo_bool_t isClipping = FALSE;
+
     if (IS_EMPTY(surface))
 	return CAIRO_STATUS_SUCCESS;
 
@@ -1507,6 +1508,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
     } else if (action == DO_IMAGE || action == DO_TILED_IMAGE || action == DO_SHADING) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
+	isClipping = TRUE;
     } else {
 	if (action != DO_NOTHING)
 	    rv = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1518,31 +1520,6 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
     /* this doesn't addref */
     cgfref = _cairo_atsui_scaled_font_get_cg_font_ref (scaled_font);
     CGContextSetFont (surface->cgContext, cgfref);
-
-    /* So this should include the size; I don't know if I need to extract the
-     * size from this and call CGContextSetFontSize.. will I get crappy hinting
-     * with this 1.0 size business?  Or will CG just multiply that size into the
-     * text matrix?
-     */
-    //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
-    cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
-						scaled_font->font_matrix.yx,
-						scaled_font->font_matrix.xy,
-						scaled_font->font_matrix.yy,
-						0., 0.);
-
-    textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
-    textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
-    textTransform = CGAffineTransformConcat (cairoTextTransform, textTransform);
-
-    ctm = CGAffineTransformMake (scaled_font->ctm.xx,
-				 -scaled_font->ctm.yx,
-				 -scaled_font->ctm.xy,
-				 scaled_font->ctm.yy,
-				 0., 0.);
-    textTransform = CGAffineTransformConcat (ctm, textTransform);
-
-    CGContextSetTextMatrix (surface->cgContext, textTransform);
     CGContextSetFontSize (surface->cgContext, 1.0);
 
     if (num_glyphs > STATIC_BUF_SIZE) {
@@ -1559,12 +1536,27 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 	}
     }
 
+    textTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
+					   scaled_font->font_matrix.yx,
+					   scaled_font->font_matrix.xy,
+					   scaled_font->font_matrix.yy,
+					   0., 0.);
+    textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
+    textTransform = CGAffineTransformConcat (CGAffineTransformMake(scaled_font->ctm.xx,
+								   -scaled_font->ctm.yx,
+								   -scaled_font->ctm.xy,
+								   scaled_font->ctm.yy,
+								   0., 0.),
+					     textTransform);
+
+    CGContextSetTextMatrix (surface->cgContext, textTransform);
+
+    /* 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;
-    cg_advances[0].width = 0;
-    cg_advances[0].height = 0;
 
     for (i = 1; i < num_glyphs; i++) {
 	float xf = glyphs[i].x;
@@ -1576,17 +1568,31 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 	yprev = yf;
     }
 
+    if (isClipping) {
+	/* If we're clipping, we get multiplied by the inverse of our text matrix; no,
+	 * I don't understand why this is any different.  So pre-apply our textTransform.
+	 * Note that the new CGContextShowGlyphsAtPositions has a similar problem. */
+	for (i = 0; i < num_glyphs - 1; i++)
+	    cg_advances[i] = CGSizeApplyAffineTransform(cg_advances[i], textTransform);
+    }
+
 #if 0
     for (i = 0; i < num_glyphs; i++) {
 	ND((stderr, "[%d: %d %f,%f]\n", i, cg_glyphs[i], cg_advances[i].width, cg_advances[i].height));
     }
 #endif
 
+    /* Translate to the first glyph's position before drawing */
+    ctm = CGContextGetCTM (surface->cgContext);
+    CGContextTranslateCTM (surface->cgContext, glyphs[0].x, glyphs[0].y);
+
     CGContextShowGlyphsWithAdvances (surface->cgContext,
 				     cg_glyphs,
 				     cg_advances,
 				     num_glyphs);
 
+    CGContextSetCTM (surface->cgContext, ctm);
+
     if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
 	CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
 	CGContextTranslateCTM (surface->cgContext, 0, surface->sourceImageRect.size.height);
@@ -2123,6 +2129,7 @@ void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest)
 	DisposeHandle(dataRef);
     }
 }
+
 #endif
 
 void


More information about the cairo-commit mailing list