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

Andrea Canciani ranma42 at kemper.freedesktop.org
Fri Jan 15 02:22:43 PST 2010


 src/cairo-quartz-surface.c |  148 +++++++++++++++++++++++----------------------
 1 file changed, 76 insertions(+), 72 deletions(-)

New commits:
commit a39075c88f9b2e12e19348ea11c9b3f739818265
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Jan 6 18:53:54 2010 +0100

    [quartz] Fix generic masking
    
    Masking with unbounded operators was broken because an incorrect
    transformation was applied to inverted mask used for the fixup.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index f1e09fb..81a6aad 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -651,6 +651,7 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
     CGContextRef cgc;
     CGImageRef maskImage;
 
+    /* TODO: handle failure */
     if (!CGContextClipToMaskPtr)
 	return;
 
@@ -675,7 +676,7 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
     CGContextSetAlpha (cgc, 1.0f);
     CGContextFillRect (cgc, CGRectMake (0, 0, clipBoxRound.size.width, clipBoxRound.size.height));
 
-    CGContextSetAlpha (cgc, 0.0f);
+    CGContextSetCompositeOperation (cgc, kPrivateCGCompositeClear);
     CGContextSetShouldAntialias (cgc, (antialias != CAIRO_ANTIALIAS_NONE));
 
     CGContextTranslateCTM (cgc, -clipBoxRound.origin.x, -clipBoxRound.origin.y);
@@ -710,27 +711,26 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
 					 op->u.show_glyphs.nglyphs);
 
 	if (op->u.show_glyphs.isClipping) {
-	    CGContextFillRect (cgc, CGRectMake (0.0, 0.0, clipBoxRound.size.width, clipBoxRound.size.height));
+	    CGContextClearRect (cgc, clipBoxRound);
 	    CGContextRestoreGState (cgc);
 	}
     } else if (op->op == UNBOUNDED_MASK) {
+	CGAffineTransform ctm = CGContextGetCTM (cgc);
 	CGContextSaveGState (cgc);
 	CGContextConcatCTM (cgc, op->u.mask.maskTransform);
 	CGContextClipToMask (cgc, CGRectMake (0.0f, 0.0f,
 					      CGImageGetWidth(op->u.mask.mask), CGImageGetHeight(op->u.mask.mask)),
 			     op->u.mask.mask);
-	CGContextFillRect (cgc, CGRectMake (0.0, 0.0, clipBoxRound.size.width, clipBoxRound.size.height));
+	CGContextSetCTM (cgc, ctm);
+	CGContextClearRect (cgc, clipBoxRound);
 	CGContextRestoreGState (cgc);
     }
 
     /* Also mask out the portion of the clipbox that we rounded out, if any */
     if (!CGRectEqualToRect (clipBox, clipBoxRound)) {
 	CGContextBeginPath (cgc);
-	CGContextAddRect (cgc, CGRectMake (0.0, 0.0, clipBoxRound.size.width, clipBoxRound.size.height));
-	CGContextAddRect (cgc, CGRectMake (clipBoxRound.origin.x - clipBox.origin.x,
-					   clipBoxRound.origin.y - clipBox.origin.y,
-					   clipBox.size.width,
-					   clipBox.size.height));
+	CGContextAddRect (cgc, clipBoxRound);
+	CGContextAddRect (cgc, clipBox);
 	CGContextEOFillPath (cgc);
     }
 
@@ -2369,18 +2369,14 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
     CGAffineTransform ctm, mask_matrix;
     cairo_bool_t is_bounded;
 
-    is_bounded = _cairo_surface_get_extents (pat_surf, &mask_extents);
-    assert (is_bounded);
-
-    // everything would be masked out, so do nothing
-    if (mask_extents.width == 0 || mask_extents.height == 0)
-	return CAIRO_STATUS_SUCCESS;
-
     status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
     if (status)
 	return status;
-    if (img == NULL)
+    if (img == NULL) {
+	if (!_cairo_operator_bounded_by_mask (op))
+	    CGContextClearRect (surface->cgContext, CGContextGetClipBoundingBox (surface->cgContext));
 	return CAIRO_STATUS_SUCCESS;
+    }
 
     rect = CGRectMake (0.0f, 0.0f, mask_extents.width, mask_extents.height);
 
@@ -2391,10 +2387,11 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
     ctm = CGContextGetCTM (surface->cgContext);
 
     _cairo_quartz_cairo_matrix_to_quartz (&mask->base.matrix, &mask_matrix);
-    CGContextConcatCTM (surface->cgContext, CGAffineTransformInvert(mask_matrix));
-    CGContextTranslateCTM (surface->cgContext, 0.0f, rect.size.height);
-    CGContextScaleCTM (surface->cgContext, 1.0f, -1.0f);
+    mask_matrix = CGAffineTransformInvert(mask_matrix);
+    mask_matrix = CGAffineTransformTranslate (mask_matrix, 0.0, CGImageGetHeight (img));
+    mask_matrix = CGAffineTransformScale (mask_matrix, 1.0, -1.0);
 
+    CGContextConcatCTM (surface->cgContext, mask_matrix);
     CGContextClipToMaskPtr (surface->cgContext, rect, img);
 
     CGContextSetCTM (surface->cgContext, ctm);
@@ -2407,7 +2404,7 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
 	unbounded_op_data_t ub;
 	ub.op = UNBOUNDED_MASK;
 	ub.u.mask.mask = img;
-	ub.u.mask.maskTransform = CGAffineTransformInvert(mask_matrix);
+	ub.u.mask.maskTransform = mask_matrix;
 	_cairo_quartz_fixup_unbounded_operation (surface, &ub, CAIRO_ANTIALIAS_NONE);
     }
 
@@ -2427,33 +2424,19 @@ _cairo_quartz_surface_mask_with_generic (cairo_quartz_surface_t *surface,
 					 const cairo_pattern_t *mask,
 					 cairo_clip_t *clip)
 {
-    int width = surface->extents.width - surface->extents.x;
-    int height = surface->extents.height - surface->extents.y;
+    int width = surface->extents.width;
+    int height = surface->extents.height;
 
     cairo_surface_t *gradient_surf = NULL;
-    cairo_t *gradient_surf_cr = NULL;
-
     cairo_surface_pattern_t surface_pattern;
-    cairo_pattern_t *mask_copy;
     cairo_int_status_t status;
 
     /* Render the gradient to a surface */
-    gradient_surf = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32,
+    gradient_surf = cairo_quartz_surface_create (CAIRO_FORMAT_A8,
 						 width,
 						 height);
-    gradient_surf_cr = cairo_create(gradient_surf);
-
-    /* make a copy of the pattern because because cairo_set_source doesn't take
-     * a 'const cairo_pattern_t *' */
-    _cairo_pattern_create_copy (&mask_copy, mask);
-    cairo_set_source (gradient_surf_cr, mask_copy);
-    cairo_pattern_destroy (mask_copy);
-
-    cairo_set_operator (gradient_surf_cr, CAIRO_OPERATOR_SOURCE);
-    cairo_paint (gradient_surf_cr);
-    status = cairo_status (gradient_surf_cr);
-    cairo_destroy (gradient_surf_cr);
 
+    status = _cairo_quartz_surface_paint (gradient_surf, CAIRO_OPERATOR_SOURCE, mask, NULL);
     if (status)
 	goto BAIL;
 
commit 27701ed8447d4c21b7bf9709a2fc21690b3cdc96
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Tue Jan 5 19:42:23 2010 +0100

    [quartz] Approximate dense dashing patterns
    
    Quartz doesn't try to approximate dash pattern even if they are well
    beyond suface sampling frequency. Approximating dash patterns when their
    density is too high avoids looping indefinitely in these degenerate cases.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 8df96f2..f1e09fb 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -2052,20 +2052,30 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
 #define STATIC_DASH 32
 	float sdash[STATIC_DASH];
 	float *fdash = sdash;
+	double offset = style->dash_offset;
 	unsigned int max_dashes = style->num_dashes;
 	unsigned int k;
 
-	if (style->num_dashes%2)
-	    max_dashes *= 2;
-	if (max_dashes > STATIC_DASH)
-	    fdash = _cairo_malloc_ab (max_dashes, sizeof (float));
-	if (fdash == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	for (k = 0; k < max_dashes; k++)
-	    fdash[k] = (float) style->dash[k % style->num_dashes];
-
-	CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, max_dashes);
+	if (_cairo_stroke_style_dash_can_approximate (style, ctm, tolerance)) {
+	    double approximate_dashes[2];
+	    _cairo_stroke_style_dash_approximate (style, ctm, tolerance,
+						  &offset,
+						  approximate_dashes,
+						  &max_dashes);
+	    sdash[0] = approximate_dashes[0];
+	    sdash[1] = approximate_dashes[1];
+	} else {
+	    if (style->num_dashes%2)
+		max_dashes *= 2;
+	    if (max_dashes > STATIC_DASH)
+		fdash = _cairo_malloc_ab (max_dashes, sizeof (float));
+	    if (fdash == NULL)
+		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	    for (k = 0; k < max_dashes; k++)
+		fdash[k] = (float) style->dash[k % style->num_dashes];
+	}
+	CGContextSetLineDash (surface->cgContext, offset, fdash, max_dashes);
 	if (fdash != sdash)
 	    free (fdash);
     } else
commit ad7ab00c10fc1adcf2ef4574fdd00b25dfcdafdd
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Sat Jan 2 13:23:53 2010 +0100

    [quartz] Improve A8 and A1 support
    
    Use A8 images as alpha-only masks intread of greyscale images.
    Add support to A1 images (they were ignored before).

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 44b25a3..8df96f2 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -200,16 +200,16 @@ _cairo_quartz_create_cgimage (cairo_format_t format,
 	    bitsPerPixel = 32;
 	    break;
 
-	/* XXX -- should use CGImageMaskCreate! */
 	case CAIRO_FORMAT_A8:
-	    if (colorSpace == NULL)
-		colorSpace = CGColorSpaceCreateDeviceGray();
-	    bitinfo = kCGImageAlphaNone;
 	    bitsPerComponent = 8;
 	    bitsPerPixel = 8;
 	    break;
 
 	case CAIRO_FORMAT_A1:
+	    bitsPerComponent = 1;
+	    bitsPerPixel = 1;
+	    break;
+
 	default:
 	    return NULL;
     }
@@ -226,16 +226,26 @@ _cairo_quartz_create_cgimage (cairo_format_t format,
 	goto FINISH;
     }
 
-    image = CGImageCreate (width, height,
-			   bitsPerComponent,
-			   bitsPerPixel,
-			   stride,
-			   colorSpace,
-			   bitinfo,
-			   dataProvider,
-			   NULL,
-			   interpolate,
-			   kCGRenderingIntentDefault);
+    if (format == CAIRO_FORMAT_A8 || format == CAIRO_FORMAT_A1) {
+	float decode[] = {1.0, 0.0};
+	image = CGImageMaskCreate (width, height,
+				   bitsPerComponent,
+				   bitsPerPixel,
+				   stride,
+				   dataProvider,
+				   decode,
+				   interpolate);
+    } else
+	image = CGImageCreate (width, height,
+			       bitsPerComponent,
+			       bitsPerPixel,
+			       stride,
+			       colorSpace,
+			       bitinfo,
+			       dataProvider,
+			       NULL,
+			       interpolate,
+			       kCGRenderingIntentDefault);
 
 FINISH:
 
@@ -976,12 +986,14 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
 					      isurf_snap);
 
 	*image_out = image;
+	if (image == NULL)
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
     if (&isurf->base != source)
 	_cairo_surface_release_source_image (source, isurf, image_extra);
 
-    return CAIRO_STATUS_SUCCESS;
+    return status;
 }
 
 /* Generic #cairo_pattern_t -> CGPattern function */
@@ -1067,9 +1079,8 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     assert (is_bounded);
 
     status = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf, &image);
-    if (status != CAIRO_STATUS_SUCCESS)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
+    if (status)
+	return status;
     if (image == NULL)
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
@@ -1201,10 +1212,10 @@ _cairo_quartz_setup_fallback_source (cairo_quartz_surface_t *surface,
 #endif
 
     status = _cairo_surface_to_cgimage (&surface->base, fallback, &img);
-    if (status == CAIRO_STATUS_SUCCESS && img == NULL)
-	return DO_NOTHING;
     if (status)
 	return DO_UNSUPPORTED;
+    if (img == NULL)
+	return DO_NOTHING;
 
     surface->sourceImageRect = CGRectMake (0.0, 0.0, w, h);
     surface->sourceImage = img;
@@ -1371,10 +1382,10 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
 	cairo_bool_t is_bounded;
 
 	status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
-	if (status == CAIRO_STATUS_SUCCESS && img == NULL)
-	    return DO_NOTHING;
 	if (status)
 	    return DO_UNSUPPORTED;
+	if (img == NULL)
+	    return DO_NOTHING;
 
 	CGContextSetRGBFillColor (surface->cgContext, 0, 0, 0, 1);
 
@@ -2356,10 +2367,10 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
 	return CAIRO_STATUS_SUCCESS;
 
     status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
-    if (status == CAIRO_STATUS_SUCCESS && img == NULL)
-	return CAIRO_STATUS_SUCCESS;
     if (status)
 	return status;
+    if (img == NULL)
+	return CAIRO_STATUS_SUCCESS;
 
     rect = CGRectMake (0.0f, 0.0f, mask_extents.width, mask_extents.height);
 


More information about the cairo-commit mailing list