[cairo-commit] 3 commits - src/cairo-image-surface.c src/cairoint.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-types-private.h

Adrian Johnson ajohnson at kemper.freedesktop.org
Mon Mar 10 00:17:14 PDT 2008


 src/cairo-image-surface.c |   38 +++++++++++++++++++++++++++++++++++++
 src/cairo-pdf-surface.c   |   38 ++++++++++++++++++++++++++++++++++++-
 src/cairo-ps-surface.c    |   47 ++++------------------------------------------
 src/cairo-types-private.h |    7 ++++++
 src/cairoint.h            |    4 +++
 5 files changed, 91 insertions(+), 43 deletions(-)

New commits:
commit f534fe434db38c2c24605bdfc251e0186dc7cafc
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Mar 10 17:18:07 2008 +1030

    PDF: Use cairo_image_analyse_transparency during analysis
    
    OPERATOR_SOURCE is only supported for opaque images. Check if and ARGB
    image really contains transparency before returing unsupported.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d5a86df..6a59af4 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -4021,6 +4021,35 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_int_status_t
+_cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t      *surface,
+							 cairo_surface_pattern_t *pattern)
+{
+    cairo_image_surface_t  *image;
+    void		   *image_extra;
+    cairo_int_status_t      status;
+    cairo_image_transparency_t transparency;
+
+    status = _cairo_surface_acquire_source_image (pattern->surface,
+						  &image,
+						  &image_extra);
+    if (status)
+	return status;
+
+    if (image->base.status)
+	return image->base.status;
+
+    transparency = _cairo_image_analyze_transparency (image);
+    if (transparency == CAIRO_IMAGE_IS_OPAQUE)
+	status = CAIRO_STATUS_SUCCESS;
+    else
+	status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
+
+    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
+
+    return status;
+}
+
 static cairo_bool_t
 _surface_pattern_supported (cairo_surface_pattern_t *pattern)
 {
@@ -4129,9 +4158,16 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t  *surface,
     if (op == CAIRO_OPERATOR_OVER)
 	return CAIRO_STATUS_SUCCESS;
 
-    /* The SOURCE operator supported if the pattern is opaque or if
+    /* The SOURCE operator is supported if the pattern is opaque or if
      * there is nothing painted underneath. */
     if (op == CAIRO_OPERATOR_SOURCE) {
+	if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+
+	    return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
+									    surface_pattern);
+	}
+
 	if (_cairo_pattern_is_opaque (pattern))
 	    return CAIRO_STATUS_SUCCESS;
 	else
commit 61d45c9d1f2322c7c2ee7a58e7b3d5ccfac92db2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Feb 16 22:34:39 2008 +1030

    Remember the results of _cairo_image_analyze_transparency
    
    As _cairo_image_analyze_transparency() is only used on images in the
    meta surface, we can store the results of the image analysis and
    return the saved value on second and subsequent calls to analyze the
    same image.
    
    Previously each image was analyzed twice - once during
    CAIRO_PAGINATED_MODE_ANALYZE and once during
    CAIRO_PAGINATED_MODE_RENDER.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 9ea274c..57dbdb8 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -131,6 +131,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
     surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
     surface->owns_data = FALSE;
     surface->has_clip = FALSE;
+    surface->transparency = CAIRO_IMAGE_UNKNOWN;
 
     surface->width = pixman_image_get_width (pixman_image);
     surface->height = pixman_image_get_height (pixman_image);
@@ -1321,6 +1322,7 @@ _cairo_image_surface_clone (cairo_image_surface_t	*surface,
 
     cairo_surface_get_device_offset (&surface->base, &x, &y);
     cairo_surface_set_device_offset (&clone->base, x, y);
+    clone->transparency = CAIRO_IMAGE_UNKNOWN;
 
     /* XXX Use _cairo_surface_composite directly */
     cr = cairo_create (&clone->base);
@@ -1342,27 +1344,34 @@ cairo_image_transparency_t
 _cairo_image_analyze_transparency (cairo_image_surface_t      *image)
 {
     int x, y;
-    cairo_image_transparency_t transparency;
 
-    if (image->format == CAIRO_FORMAT_RGB24)
+    if (image->transparency != CAIRO_IMAGE_UNKNOWN)
+	return image->transparency;
+
+    if (image->format == CAIRO_FORMAT_RGB24) {
+	image->transparency = CAIRO_IMAGE_IS_OPAQUE;
 	return CAIRO_IMAGE_IS_OPAQUE;
+    }
 
-    if (image->format != CAIRO_FORMAT_ARGB32)
+    if (image->format != CAIRO_FORMAT_ARGB32) {
+	image->transparency = CAIRO_IMAGE_HAS_ALPHA;
 	return CAIRO_IMAGE_HAS_ALPHA;
+    }
 
-    transparency = CAIRO_IMAGE_IS_OPAQUE;
+    image->transparency = CAIRO_IMAGE_IS_OPAQUE;
     for (y = 0; y < image->height; y++) {
 	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
 
 	for (x = 0; x < image->width; x++, pixel++) {
 	    int a = (*pixel & 0xff000000) >> 24;
 	    if (a > 0 && a < 255) {
+		image->transparency = CAIRO_IMAGE_HAS_ALPHA;
 		return CAIRO_IMAGE_HAS_ALPHA;
 	    } else if (a == 0) {
-		transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
+		image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
 	    }
 	}
     }
 
-    return transparency;
+    return image->transparency;
 }
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index ec8a8b2..cbaaead 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1379,6 +1379,9 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
     case CAIRO_IMAGE_HAS_ALPHA:
 	status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
 	break;
+
+    case CAIRO_IMAGE_UNKNOWN:
+	ASSERT_NOT_REACHED;
     }
 
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 5e15b64..30f7476 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -316,7 +316,8 @@ typedef enum {
 typedef enum _cairo_image_transparency {
     CAIRO_IMAGE_IS_OPAQUE,
     CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
-    CAIRO_IMAGE_HAS_ALPHA
+    CAIRO_IMAGE_HAS_ALPHA,
+    CAIRO_IMAGE_UNKNOWN
 } cairo_image_transparency_t;
 
 #endif /* CAIRO_TYPES_PRIVATE_H */
diff --git a/src/cairoint.h b/src/cairoint.h
index 966742b..a1f384c 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -708,6 +708,7 @@ struct _cairo_image_surface {
     unsigned char *data;
     cairo_bool_t owns_data;
     cairo_bool_t has_clip;
+    cairo_image_transparency_t transparency;
 
     int width;
     int height;
commit 7eb8f497d8ac8ee76809f958170f1e5370744ba8
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Feb 16 22:13:43 2008 +1030

    Move analyze_image_transparency in to cairo-image-surface.c

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 28e3ce2..9ea274c 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1337,3 +1337,32 @@ _cairo_image_surface_clone (cairo_image_surface_t	*surface,
 
     return clone;
 }
+
+cairo_image_transparency_t
+_cairo_image_analyze_transparency (cairo_image_surface_t      *image)
+{
+    int x, y;
+    cairo_image_transparency_t transparency;
+
+    if (image->format == CAIRO_FORMAT_RGB24)
+	return CAIRO_IMAGE_IS_OPAQUE;
+
+    if (image->format != CAIRO_FORMAT_ARGB32)
+	return CAIRO_IMAGE_HAS_ALPHA;
+
+    transparency = CAIRO_IMAGE_IS_OPAQUE;
+    for (y = 0; y < image->height; y++) {
+	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
+
+	for (x = 0; x < image->width; x++, pixel++) {
+	    int a = (*pixel & 0xff000000) >> 24;
+	    if (a > 0 && a < 255) {
+		return CAIRO_IMAGE_HAS_ALPHA;
+	    } else if (a == 0) {
+		transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
+	    }
+	}
+    }
+
+    return transparency;
+}
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6ab1c0a..ec8a8b2 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -61,12 +61,6 @@
 #define ctime_r(T, BUF) ctime (T)
 #endif
 
-typedef enum _cairo_image_transparency {
-    CAIRO_IMAGE_IS_OPAQUE,
-    CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
-    CAIRO_IMAGE_HAS_ALPHA
-} cairo_image_transparency_t;
-
 static const cairo_surface_backend_t cairo_ps_surface_backend;
 static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
 
@@ -1349,40 +1343,6 @@ color_is_gray (double red, double green, double blue)
 	    fabs (red - blue) < epsilon);
 }
 
-static cairo_image_transparency_t
-_analyze_image_transparency (cairo_image_surface_t      *image)
-{
-    int x, y;
-    cairo_image_transparency_t transparency;
-
-    if (image->format == CAIRO_FORMAT_RGB24)
-	return CAIRO_IMAGE_IS_OPAQUE;
-
-    if (image->format != CAIRO_FORMAT_ARGB32) {
-	/* If the PS surface does not support the image format, assume
-	 * that it does have alpha. The image will be converted to
-	 * rgb24 when the PS surface blends the image into the page
-	 * color to remove the transparency. */
-	return CAIRO_IMAGE_HAS_ALPHA;
-    }
-
-    transparency = CAIRO_IMAGE_IS_OPAQUE;
-    for (y = 0; y < image->height; y++) {
-	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
-
-	for (x = 0; x < image->width; x++, pixel++) {
-	    int a = (*pixel & 0xff000000) >> 24;
-	    if (a > 0 && a < 255) {
-		return CAIRO_IMAGE_HAS_ALPHA;
-	    } else if (a == 0) {
-		transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
-	    }
-	}
-    }
-
-    return transparency;
-}
-
 static cairo_int_status_t
 _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t      *surface,
 						       cairo_surface_pattern_t *pattern)
@@ -1401,7 +1361,7 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
     if (image->base.status)
 	return image->base.status;
 
-    transparency = _analyze_image_transparency (image);
+    transparency = _cairo_image_analyze_transparency (image);
     switch (transparency) {
     case CAIRO_IMAGE_IS_OPAQUE:
 	status = CAIRO_STATUS_SUCCESS;
@@ -1847,7 +1807,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t    *surface,
     if (image->base.status)
 	return image->base.status;
 
-    transparency = _analyze_image_transparency (image);
+    transparency = _cairo_image_analyze_transparency (image);
 
     /* PostScript can not represent the alpha channel, so we blend the
        current image over a white (or black for CONTENT_COLOR
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 2c98f0e..5e15b64 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -313,4 +313,10 @@ typedef enum {
     CAIRO_STOCK_TRANSPARENT
 } cairo_stock_t;
 
+typedef enum _cairo_image_transparency {
+    CAIRO_IMAGE_IS_OPAQUE,
+    CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
+    CAIRO_IMAGE_HAS_ALPHA
+} cairo_image_transparency_t;
+
 #endif /* CAIRO_TYPES_PRIVATE_H */
diff --git a/src/cairoint.h b/src/cairoint.h
index 022033c..966742b 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1903,6 +1903,9 @@ cairo_private cairo_image_surface_t *
 _cairo_image_surface_clone (cairo_image_surface_t	*surface,
 			    cairo_format_t		 format);
 
+cairo_image_transparency_t
+_cairo_image_analyze_transparency (cairo_image_surface_t      *image);
+
 cairo_private cairo_bool_t
 _cairo_surface_is_image (const cairo_surface_t *surface);
 


More information about the cairo-commit mailing list