[cairo-commit] 10 commits - NEWS src/cairo-atsui-font.c src/cairo-quartz-private.h src/cairo-quartz-surface.c

Brian Ewins brianewins at kemper.freedesktop.org
Thu Jun 7 17:57:02 PDT 2007


 NEWS                       |    3 
 src/cairo-atsui-font.c     |   19 +-
 src/cairo-quartz-private.h |    5 
 src/cairo-quartz-surface.c |  293 ++++++++++++++++++++++++++++++++-------------
 4 files changed, 224 insertions(+), 96 deletions(-)

New commits:
diff-tree 8223c976d54319b58906de03fcb8fb1967105e53 (from 00063a65f758265f3ad5c0caa374d9c7d5e89932)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Fri Jun 8 01:56:10 2007 +0100

    [NEWS] add note about quartz fixes
    
    We've got 11 less failures in the quartz tests this time around,
    worth a mention.

diff --git a/NEWS b/NEWS
index a2badde..a805bc9 100644
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,9 @@ Remove Xsun from the buggy_repeat blackl
 
 ATSUI: Fix glyph measurement: faster and more correct (Brian Ewins)
 
+Quartz: fixed 'extend' behaviour for patterns, improved pattern performance,
+and a few smaller correctness fixes. (Brian Ewins, Vladimir Vukicevic)
+
 Release 1.4.6 (2007-05-01 Carl Worth <cworth at cworth.org>)
 =========================================================
 This is the third update in cairo's stable 1.4 series. It comes a
diff-tree 00063a65f758265f3ad5c0caa374d9c7d5e89932 (from 39e6a0090faa4e73a658c1ca0ead3040309b84a2)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Fri Jun 8 01:17:09 2007 +0100

    [quartz] fix DO_IMAGE
    
    The implementation of DO_IMAGE leaks memory via a referenced surface,
    and wasn't applied for strokes and glyphs. This patch corrects those
    issues.

diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index 23d7d4b..cd1b15c 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -56,8 +56,11 @@ typedef struct cairo_quartz_surface {
     /* These are stored while drawing operations are in place, set up
      * by quartz_setup_source() and quartz_finish_source()
      */
-    CGAffineTransform imageTransform;
     CGImageRef sourceImage;
+    cairo_surface_t *sourceImageSurface;
+    CGAffineTransform sourceImageTransform;
+    CGRect sourceImageRect;
+
     CGShadingRef sourceShading;
     CGPatternRef sourcePattern;
 } cairo_quartz_surface_t;
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index dea8c26..dc831c1 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -472,28 +472,28 @@ _cairo_quartz_cairo_gradient_pattern_to_
 
 /* generic cairo surface -> cairo_quartz_surface_t function */
 static cairo_quartz_surface_t *
-_cairo_quartz_surface_to_quartz (cairo_surface_t *pat_surf)
+_cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_surf)
 {
     cairo_quartz_surface_t *quartz_surf = NULL;
 
     if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
-	/* This sucks; we should really store a dummy quartz surface
-	 * for passing in here
-	 * XXXtodo store a dummy quartz surface somewhere for handing off to clone_similar
-	 * XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
+	/* XXXtodo/perf don't use clone if the source surface is an image surface!  Instead,
 	 * just create the CGImage directly!
 	 */
 
-	cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+	cairo_surface_t *ref_type = target;
+	if (ref_type == NULL)
+	    ref_type = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
 	cairo_surface_t *new_surf = NULL;
 	cairo_rectangle_int16_t rect;
 
 	_cairo_surface_get_extents (pat_surf, &rect);
 
-	_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
+	_cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
 				      rect.width, rect.height, &new_surf);
 
-	cairo_surface_destroy(dummy);
+	if (target == NULL)
+	    cairo_surface_destroy(ref_type);
 
 	quartz_surf = (cairo_quartz_surface_t *) new_surf;
     } else {
@@ -515,7 +515,7 @@ SurfacePatternDrawFunc (void *info, CGCo
     cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
     cairo_surface_t *pat_surf = spat->surface;
 
-    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (pat_surf);
+    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
     CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
 
     if (!img) {
@@ -685,7 +685,7 @@ typedef enum {
 
 static cairo_quartz_action_t
 _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
-			     cairo_pattern_t *source)
+			    cairo_pattern_t *source)
 {
     assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
 
@@ -714,13 +714,15 @@ _cairo_quartz_setup_source (cairo_quartz
 	surface->sourceShading = shading;
 
 	return DO_SHADING;
-    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE
-	&& source->extend == CAIRO_EXTEND_NONE) {
+    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	       source->extend == CAIRO_EXTEND_NONE)
+    {
 	    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
 	    cairo_surface_t *pat_surf = spat->surface;
-	    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (pat_surf);
+	    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (surface, pat_surf);
 	    CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
 	    cairo_matrix_t m = spat->base.matrix;
+	    cairo_rectangle_int16_t extents;
 
 	    if (!img)
 		return DO_UNSUPPORTED;
@@ -728,7 +730,13 @@ _cairo_quartz_setup_source (cairo_quartz
 	    surface->sourceImage = img;
 
 	    cairo_matrix_invert(&m);
-	    _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->imageTransform);
+	    _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform);
+
+	    _cairo_surface_get_extents (pat_surf, &extents);
+	    surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
+
+	    surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
+
 	    return DO_IMAGE;
     } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	CGPatternRef pattern = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
@@ -773,6 +781,9 @@ _cairo_quartz_teardown_source (cairo_qua
     if (surface->sourceImage) {
 	CGImageRelease(surface->sourceImage);
 	surface->sourceImage = NULL;
+
+	cairo_surface_destroy(surface->sourceImageSurface);
+	surface->sourceImageSurface = NULL;
     }
 
     if (surface->sourceShading) {
@@ -1156,18 +1167,13 @@ _cairo_quartz_surface_paint (void *abstr
 	    (cairo_surface_pattern_t *) source;
 	cairo_surface_t *pat_surf = surface_pattern->surface;
 	CGContextSaveGState (surface->cgContext);
-	CGContextConcatCTM (surface->cgContext, surface->imageTransform);
+	CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
 	if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
 	    CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
 	    CGContextScaleCTM (surface->cgContext, 1, -1);
 	}
 
-	CGRect imageBounds;
-	imageBounds.size = CGSizeMake (CGImageGetWidth(surface->sourceImage), CGImageGetHeight(surface->sourceImage));
-	imageBounds.origin.x = 0;
-	imageBounds.origin.y = 0;
-
-	CGContextDrawImage (surface->cgContext, imageBounds, surface->sourceImage);
+	CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
 	CGContextRestoreGState (surface->cgContext);
     } else {
 	rv = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1238,18 +1244,13 @@ _cairo_quartz_surface_fill (void *abstra
 	    CGContextClip (surface->cgContext);
 	else
 	    CGContextEOClip (surface->cgContext);
-	CGContextConcatCTM (surface->cgContext, surface->imageTransform);
+	CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
 	if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
 	    CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
 	    CGContextScaleCTM (surface->cgContext, 1, -1);
 	}
 
-	CGRect imageBounds;
-	imageBounds.size = CGSizeMake (CGImageGetWidth(surface->sourceImage), CGImageGetHeight(surface->sourceImage));
-	imageBounds.origin.x = 0;
-	imageBounds.origin.y = 0;
-
-	CGContextDrawImage (surface->cgContext, imageBounds, surface->sourceImage);
+	CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
     } else {
 	rv = CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -1329,9 +1330,18 @@ _cairo_quartz_surface_stroke (void *abst
 
     if (action == DO_SOLID || action == DO_PATTERN) {
 	CGContextStrokePath (surface->cgContext);
+    } else if (action == DO_IMAGE) {
+	CGContextReplacePathWithStrokedPath (surface->cgContext);
+	CGContextClip (surface->cgContext);
+
+	CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
+	if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
+	    CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
+	    CGContextScaleCTM (surface->cgContext, 1, -1);
+	}
+
+	CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
     } else if (action == DO_SHADING) {
-	// we have to clip and then paint the shading; first we have to convert
-	// the stroke to a path that we can fill
 	CGContextReplacePathWithStrokedPath (surface->cgContext);
 	CGContextClip (surface->cgContext);
 
@@ -1376,7 +1386,7 @@ _cairo_quartz_surface_show_glyphs (void 
     action = _cairo_quartz_setup_source (surface, source);
     if (action == DO_SOLID || action == DO_PATTERN) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
-    } else if (action == DO_SHADING) {
+    } else if (action == DO_IMAGE || action == DO_SHADING) {
 	CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
     } else {
 	/* Unsupported */
@@ -1465,8 +1475,17 @@ _cairo_quartz_surface_show_glyphs (void 
 	free (cg_advances);
     }
 
-    if (action == DO_SHADING)
+    if (action == DO_IMAGE) {
+	CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
+	if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
+	    CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
+	    CGContextScaleCTM (surface->cgContext, 1, -1);
+	}
+
+	CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
+    } else if (action == DO_SHADING) {
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    }
 
     _cairo_quartz_teardown_source (surface, source);
 
diff-tree 39e6a0090faa4e73a658c1ca0ead3040309b84a2 (from 7c1afdcd597331c14f256f406a3e95743f7fdad6)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Fri Jun 8 01:12:24 2007 +0100

    [quartz] fall back on extended gradients
    
    A temporary fix for mozilla bug 379321, use an image fallback for
    gradients that use EXTEND_REPEAT or EXTEND_REFLECT.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index c2376fe..dea8c26 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -393,6 +393,13 @@ _cairo_quartz_cairo_gradient_pattern_to_
 	abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
 	return NULL;
 
+    /* bandaid for mozilla bug 379321, also visible in the
+     * linear-gradient-reflect test. 
+     */
+    if (abspat->extend == CAIRO_EXTEND_REFLECT ||
+	abspat->extend == CAIRO_EXTEND_REPEAT)
+	return NULL;
+	
     /* We can only do this if we have an identity pattern matrix;
      * otherwise fall back through to the generic pattern case.
      * XXXperf we could optimize this by creating a pattern with the shading;
diff-tree 7c1afdcd597331c14f256f406a3e95743f7fdad6 (from 55f1dbd0fbcbc587823ef8fa291a0af08441c775)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Mon Mar 26 00:06:23 2007 +0100

    [quartz] fixes the offsets in the font-matrix test
    
    Apply the font matrix offset to text on the quartz surface, if necessary.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index e7bc519..c2376fe 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1393,7 +1393,11 @@ _cairo_quartz_surface_show_glyphs (void 
      */
     //ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
     CGAffineTransform cairoTextTransform, textTransform, ctm;
-    _cairo_quartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
+    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);
diff-tree 55f1dbd0fbcbc587823ef8fa291a0af08441c775 (from 5a9de1b5c9f6cc445f9f6230937c2254ee49e7cb)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Apr 1 00:04:24 2007 +0100

    [quartz] ensure that line widths are scaled.
    
    cairo-gstate applies the ctm to the coordinates used in paths,
    but not to the line width. In quartz this ends up drawing unscaled
    lines. This is a minimal fix - it undoes the scaling applied to the
    points and then draws the path scaled correctly.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 9da1bba..e7bc519 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -101,6 +101,11 @@ static void quartz_image_to_png (CGImage
  * Cairo path -> Quartz path conversion helpers
  */
 
+typedef struct _quartz_stroke {
+    CGContextRef cgContext;
+    cairo_matrix_t *ctm_inverse;
+} quartz_stroke_t;
+
 /* cairo path -> mutable path */
 static cairo_status_t
 _cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
@@ -140,8 +145,14 @@ static cairo_status_t
 _cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
 {
     //ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
-    CGContextMoveToPoint ((CGContextRef) closure,
-			  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+
+    if (stroke->ctm_inverse)
+	cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
+
+    CGContextMoveToPoint (stroke->cgContext, x, y);
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -149,12 +160,17 @@ static cairo_status_t
 _cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
 {
     //ND((stderr, "lineto: %f %f\n",  _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
-    if (CGContextIsPathEmpty ((CGContextRef) closure))
-	CGContextMoveToPoint ((CGContextRef) closure,
-			      _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+    quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
+    double x = _cairo_fixed_to_double (point->x);
+    double y = _cairo_fixed_to_double (point->y);
+    
+    if (stroke->ctm_inverse)
+	cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
+
+    if (CGContextIsPathEmpty (stroke->cgContext))
+	CGContextMoveToPoint (stroke->cgContext, x, y);
     else
-	CGContextAddLineToPoint ((CGContextRef) closure,
-				 _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
+	CGContextAddLineToPoint (stroke->cgContext, x, y);
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -165,11 +181,22 @@ _cairo_path_to_quartz_context_curve_to (
     //		   _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
     //		   _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
     //		   _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
+    quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
+    double x0 = _cairo_fixed_to_double (p0->x);
+    double y0 = _cairo_fixed_to_double (p0->y);
+    double x1 = _cairo_fixed_to_double (p1->x);
+    double y1 = _cairo_fixed_to_double (p1->y);
+    double x2 = _cairo_fixed_to_double (p2->x);
+    double y2 = _cairo_fixed_to_double (p2->y);
+
+    if (stroke->ctm_inverse) {
+	cairo_matrix_transform_point (stroke->ctm_inverse, &x0, &y0);
+	cairo_matrix_transform_point (stroke->ctm_inverse, &x1, &y1);
+	cairo_matrix_transform_point (stroke->ctm_inverse, &x2, &y2);
+    }
 
-    CGContextAddCurveToPoint ((CGContextRef) closure,
-			      _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
-			      _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
-			      _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
+    CGContextAddCurveToPoint (stroke->cgContext,
+			      x0, y0, x1, y1, x2, y2);
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -177,7 +204,8 @@ static cairo_status_t
 _cairo_path_to_quartz_context_close_path (void *closure)
 {
     //ND((stderr, "closepath\n"));
-    CGContextClosePath ((CGContextRef) closure);
+    quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
+    CGContextClosePath (stroke->cgContext);
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1156,6 +1184,7 @@ _cairo_quartz_surface_fill (void *abstra
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
     cairo_quartz_action_t action;
+    quartz_stroke_t stroke;
 
     ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type));
 
@@ -1174,7 +1203,10 @@ _cairo_quartz_surface_fill (void *abstra
     }
 
     CGContextBeginPath (surface->cgContext);
-    _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
+
+    stroke.cgContext = surface->cgContext;
+    stroke.ctm_inverse = NULL;
+    _cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
 
     if (action == DO_SOLID || action == DO_PATTERN) {
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
@@ -1237,6 +1269,8 @@ _cairo_quartz_surface_stroke (void *abst
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
     cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
     cairo_quartz_action_t action;
+    quartz_stroke_t stroke;
+    CGAffineTransform strokeTransform;
 
     ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
 
@@ -1252,6 +1286,8 @@ _cairo_quartz_surface_stroke (void *abst
     CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
     CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
     CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
+    _cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
+    CGContextConcatCTM (surface->cgContext, strokeTransform);
 
     if (style->dash && style->num_dashes) {
 #define STATIC_DASH 32
@@ -1279,7 +1315,10 @@ _cairo_quartz_surface_stroke (void *abst
     }
 
     CGContextBeginPath (surface->cgContext);
-    _cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
+
+    stroke.cgContext = surface->cgContext;
+    stroke.ctm_inverse = ctm_inverse;
+    _cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
 
     if (action == DO_SOLID || action == DO_PATTERN) {
 	CGContextStrokePath (surface->cgContext);
@@ -1472,6 +1511,7 @@ _cairo_quartz_surface_intersect_clip_pat
 					    cairo_antialias_t antialias)
 {
     cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
+    quartz_stroke_t stroke;
 
     ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path));
 
@@ -1487,7 +1527,9 @@ _cairo_quartz_surface_intersect_clip_pat
 	CGContextSaveGState (surface->cgContext);
     } else {
 	CGContextBeginPath (surface->cgContext);
-	_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
+	stroke.cgContext = surface->cgContext;
+	stroke.ctm_inverse = NULL;
+	_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
 	if (fill_rule == CAIRO_FILL_RULE_WINDING)
 	    CGContextClip (surface->cgContext);
 	else
diff-tree 5a9de1b5c9f6cc445f9f6230937c2254ee49e7cb (from 807c5ab613e7df60be452d6683c4f9f045ef62a0)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Thu Jun 7 23:22:30 2007 +0100

    [atsui] remove unused code
    
    Remove CGAffineTransformMakeWithCairoFontScale.

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 599d525..34560d2 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -147,14 +147,6 @@ cairo_atsui_font_face_create_for_atsu_fo
     return &font_face->base;
 }
 
-static CGAffineTransform
-CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
-{
-    return CGAffineTransformMake(scale->xx, scale->yx,
-                                 scale->xy, scale->yy,
-                                 0, 0);
-}
-
 static ATSUStyle
 CreateSizedCopyOfStyle(ATSUStyle inStyle, 
 		       const Fixed *theSize, 
diff-tree 807c5ab613e7df60be452d6683c4f9f045ef62a0 (from b210b09e2de2f048debad6e8881f0226b6b17060)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Thu Jun 7 23:22:29 2007 +0100

    [atsui] clean up warnings
    
    Refactor code to get rid of compiler warnings.

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 5b39902..599d525 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -593,6 +593,7 @@ _cairo_atsui_scaled_font_init_glyph_surf
     CGContextRef drawingContext;
     cairo_image_surface_t *surface;
     cairo_format_t format;
+    cairo_status_t status;
 
     ATSFontRef atsFont;
     CGFontRef cgFont;
@@ -609,8 +610,9 @@ _cairo_atsui_scaled_font_init_glyph_surf
 
     if (theGlyph == kATSDeletedGlyphcode) {
 	surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
-	if (cairo_surface_status (surface))
-	    return cairo_surface_status (surface);
+	status = cairo_surface_status ((cairo_surface_t *)surface);
+	if (status)
+	    return status;
 
 	_cairo_scaled_glyph_set_surface (scaled_glyph,
 					 &base,
@@ -676,8 +678,9 @@ _cairo_atsui_scaled_font_init_glyph_surf
 
     /* create the glyph mask surface */
     surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
-    if (cairo_surface_status (surface))
-	return cairo_surface_status (surface);
+    status = cairo_surface_status ((cairo_surface_t *)surface);
+    if (status)
+	return status;
 
     /* Create a CGBitmapContext for the dest surface for drawing into */
     {
diff-tree b210b09e2de2f048debad6e8881f0226b6b17060 (from fa5dd548b0dd2dfe523501bd40cafe7916240be1)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Thu Jun 7 23:22:27 2007 +0100

    [quartz] implement CAIRO_EXTEND_REFLECT
    
    Implement extend-reflect by tiling a larger 2x2 grid of reflected
    images.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 748db62..9da1bba 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -506,6 +506,18 @@ SurfacePatternDrawFunc (void *info, CGCo
     imageBounds.origin.y = 0;
 
     CGContextDrawImage (context, imageBounds, img);
+    if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
+	/* draw 3 more copies of the image, flipped. */
+	CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
+	CGContextScaleCTM (context, 1, -1);
+	CGContextDrawImage (context, imageBounds, img);
+	CGContextTranslateCTM (context, 2 * imageBounds.size.width, 0);
+	CGContextScaleCTM (context, -1, 1);
+	CGContextDrawImage (context, imageBounds, img);
+	CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
+	CGContextScaleCTM (context, 1, -1);
+	CGContextDrawImage (context, imageBounds, img);
+    }
 
     CGImageRelease (img);
 
@@ -569,8 +581,24 @@ _cairo_quartz_cairo_repeating_surface_pa
     _cairo_surface_get_extents (pat_surf, &extents);
     pbounds.origin.x = 0;
     pbounds.origin.y = 0;
-    pbounds.size.width = extents.width;
-    pbounds.size.height = extents.height;
+
+    // kjs seems to indicate this should work (setting to 0,0 to avoid
+    // tiling); however, the pattern CTM scaling ends up being NaN in
+    // the pattern draw function if either rw or rh are 0.
+    // XXXtodo get pattern drawing working with extend options
+    // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
+    if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
+	/* XXX broken; need to emulate by reflecting the image into 4 quadrants
+	 * and then tiling that
+	 */
+	pbounds.size.width = 2 * extents.width;
+	pbounds.size.height = 2 * extents.height;
+    } else {
+	pbounds.size.width = extents.width;
+	pbounds.size.height = extents.height;
+    }
+    rw = pbounds.size.width;
+    rh = pbounds.size.height;
 
     m = spat->base.matrix;
     cairo_matrix_invert(&m);
@@ -590,38 +618,6 @@ _cairo_quartz_cairo_repeating_surface_pa
     ND((stderr, "  context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
 #endif
 
-    // kjs seems to indicate this should work (setting to 0,0 to avoid
-    // tiling); however, the pattern CTM scaling ends up being NaN in
-    // the pattern draw function if either rw or rh are 0.
-    // XXXtodo get pattern drawing working with extend options
-    // XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
-#if 0
-    if (spat->base.extend == CAIRO_EXTEND_NONE) {
-	/* XXX wasteful; this will keep drawing the pattern in the
-	 * original location.  We need to set up the clip region
-	 * instead to do this right.
-	 */
-	rw = 0;
-	rh = 0;
-    } else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
-	rw = extents.width;
-	rh = extents.height;
-    } else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
-	/* XXX broken; need to emulate by reflecting the image into 4 quadrants
-	 * and then tiling that
-	 */
-	rw = extents.width;
-	rh = extents.height;
-    } else {
-	/* CAIRO_EXTEND_PAD */
-	/* XXX broken. */
-	rw = 0;
-	rh = 0;
-    }
-#else
-    rw = extents.width;
-    rh = extents.height;
-#endif
 
     /* XXX fixme: only do snapshots if the context is for printing, or get rid of the
        other block if it doesn't fafect performance */
diff-tree fa5dd548b0dd2dfe523501bd40cafe7916240be1 (from 147288864c8c512f3ae17c8117d3c36dbbc6d5f8)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Tue May 29 23:11:49 2007 +0100

    [quartz] implement CAIRO_EXTEND_NONE
    
    Implement extend-none for surface patterns, by using a single
    DrawImage where possible. There is some code duplication in this
    patch, to make it easier to edit this patch series without conflicts.
    A patch to remove duplicate code will be required later..

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 64a871d..748db62 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -648,6 +648,7 @@ typedef enum {
     DO_SOLID,
     DO_SHADING,
     DO_PATTERN,
+    DO_IMAGE,
     DO_UNSUPPORTED
 } cairo_quartz_action_t;
 
@@ -682,6 +683,22 @@ _cairo_quartz_setup_source (cairo_quartz
 	surface->sourceShading = shading;
 
 	return DO_SHADING;
+    } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE
+	&& source->extend == CAIRO_EXTEND_NONE) {
+	    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
+	    cairo_surface_t *pat_surf = spat->surface;
+	    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (pat_surf);
+	    CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+	    cairo_matrix_t m = spat->base.matrix;
+
+	    if (!img)
+		return DO_UNSUPPORTED;
+
+	    surface->sourceImage = img;
+
+	    cairo_matrix_invert(&m);
+	    _cairo_quartz_cairo_matrix_to_quartz (&m, &surface->imageTransform);
+	    return DO_IMAGE;
     } else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	CGPatternRef pattern = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
 	if (!pattern)
@@ -694,7 +711,8 @@ _cairo_quartz_setup_source (cairo_quartz
 	// pattern (which may be stack allocated)
 	CGContextSaveGState(surface->cgContext);
 
-	CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+	CGColorSpaceRef patternSpace;
+	patternSpace = CGColorSpaceCreatePattern(NULL);
 	CGContextSetFillColorSpace (surface->cgContext, patternSpace);
 	CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
 	CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
@@ -722,7 +740,8 @@ _cairo_quartz_teardown_source (cairo_qua
 				cairo_pattern_t *source)
 {
     if (surface->sourceImage) {
-	// nothing to do; we don't use sourceImage yet
+	CGImageRelease(surface->sourceImage);
+	surface->sourceImage = NULL;
     }
 
     if (surface->sourceShading) {
@@ -1101,6 +1120,24 @@ _cairo_quartz_surface_paint (void *abstr
 							  surface->extents.height));
     } else if (action == DO_SHADING) {
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    } else if (action == DO_IMAGE) {
+	cairo_surface_pattern_t *surface_pattern =
+	    (cairo_surface_pattern_t *) source;
+	cairo_surface_t *pat_surf = surface_pattern->surface;
+	CGContextSaveGState (surface->cgContext);
+	CGContextConcatCTM (surface->cgContext, surface->imageTransform);
+	if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
+	    CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
+	    CGContextScaleCTM (surface->cgContext, 1, -1);
+	}
+
+	CGRect imageBounds;
+	imageBounds.size = CGSizeMake (CGImageGetWidth(surface->sourceImage), CGImageGetHeight(surface->sourceImage));
+	imageBounds.origin.x = 0;
+	imageBounds.origin.y = 0;
+
+	CGContextDrawImage (surface->cgContext, imageBounds, surface->sourceImage);
+	CGContextRestoreGState (surface->cgContext);
     } else {
 	rv = CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -1158,6 +1195,26 @@ _cairo_quartz_surface_fill (void *abstra
 	    CGContextEOClip (surface->cgContext);
 
 	CGContextDrawShading (surface->cgContext, surface->sourceShading);
+    } else if (action == DO_IMAGE) {
+	cairo_surface_pattern_t *surface_pattern =
+	    (cairo_surface_pattern_t *) source;
+	cairo_surface_t *pat_surf = surface_pattern->surface;
+	if (fill_rule == CAIRO_FILL_RULE_WINDING)
+	    CGContextClip (surface->cgContext);
+	else
+	    CGContextEOClip (surface->cgContext);
+	CGContextConcatCTM (surface->cgContext, surface->imageTransform);
+	if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
+	    CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
+	    CGContextScaleCTM (surface->cgContext, 1, -1);
+	}
+
+	CGRect imageBounds;
+	imageBounds.size = CGSizeMake (CGImageGetWidth(surface->sourceImage), CGImageGetHeight(surface->sourceImage));
+	imageBounds.origin.x = 0;
+	imageBounds.origin.y = 0;
+
+	CGContextDrawImage (surface->cgContext, imageBounds, surface->sourceImage);
     } else {
 	rv = CAIRO_INT_STATUS_UNSUPPORTED;
     }
diff-tree 147288864c8c512f3ae17c8117d3c36dbbc6d5f8 (from a5ee983e1cb97aff63b0c9c3a57125b37d0e3f74)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Thu Jun 7 23:22:05 2007 +0100

    [quartz] Refactor code to create a CGImageRef from a pattern
    
    In order to implement CAIRO_EXTEND_NONE we will need to create
    a CGImageRef without also creating a CGPattern. Separate the two
    pieces of code.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 3a80908..64a871d 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -435,20 +435,12 @@ _cairo_quartz_cairo_gradient_pattern_to_
     return NULL;
 }
 
-
-/* Generic cairo_pattern -> CGPattern function */
-static void
-SurfacePatternDrawFunc (void *info, CGContextRef context)
+/* generic cairo surface -> cairo_quartz_surface_t function */
+static cairo_quartz_surface_t *
+_cairo_quartz_surface_to_quartz (cairo_surface_t *pat_surf)
 {
-    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
-    cairo_surface_t *pat_surf = spat->surface;
-
     cairo_quartz_surface_t *quartz_surf = NULL;
 
-    cairo_bool_t flip = FALSE;
-
-    CGImageRef img;
-
     if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
 	/* This sucks; we should really store a dummy quartz surface
 	 * for passing in here
@@ -476,15 +468,20 @@ SurfacePatternDrawFunc (void *info, CGCo
 	cairo_surface_reference (pat_surf);
 	quartz_surf = (cairo_quartz_surface_t*) pat_surf;
 
-	/* XXXtodo WHY does this need to be flipped?  Writing this stuff
-	 * to disk shows that in both this path and the path above the source image
-	 * has an identical orientation, and the destination context at all times has a Y
-	 * flip.  So why do we need to flip in this case?
-	 */
-	flip = TRUE;
     }
 
-    img = CGBitmapContextCreateImage (quartz_surf->cgContext);
+    return quartz_surf;
+}
+
+/* Generic cairo_pattern -> CGPattern function */
+static void
+SurfacePatternDrawFunc (void *info, CGContextRef context)
+{
+    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
+    cairo_surface_t *pat_surf = spat->surface;
+
+    cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (pat_surf);
+    CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
 
     if (!img) {
 	// ... give up.
@@ -493,7 +490,12 @@ SurfacePatternDrawFunc (void *info, CGCo
 	return;
     }
 
-    if (flip) {
+    /* XXXtodo WHY does this need to be flipped?  Writing this stuff
+     * to disk shows that in both this path and the path above the source image
+     * has an identical orientation, and the destination context at all times has a Y
+     * flip.  So why do we need to flip in this case?
+     */
+    if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
 	CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
 	CGContextScaleCTM (context, 1, -1);
     }


More information about the cairo-commit mailing list