[cairo-commit] src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h

Adrian Johnson ajohnson at kemper.freedesktop.org
Tue Sep 6 05:46:38 PDT 2011


 src/cairo-pdf-surface-private.h |    2 
 src/cairo-pdf-surface.c         |  143 ++++++++++++++++++----------------------
 2 files changed, 68 insertions(+), 77 deletions(-)

New commits:
commit c34d6adfccfe9dc7f76a0ab970914dd8f6e626b0
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Sep 6 21:36:54 2011 +0930

    pdf: use _emit_smask() instead of _emit_imagemask to emit stencil mask
    
    Now that _emit_smask() can generate A1 masks, the _emit_imagemask()
    code can be removed and emit_smask() used instead. An additional
    benefit is stencil masks can be generated from ARGB32 and A8 images as
    well as A1 providing that the analysis of the transparency shows that
    the image is opaque or has bilevel alpha.

diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 139c1c6..08620e6 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -70,7 +70,7 @@ typedef struct _cairo_pdf_source_surface_entry {
     unsigned char *unique_id;
     unsigned long unique_id_length;
     cairo_bool_t interpolate;
-    cairo_bool_t mask;
+    cairo_bool_t stencil_mask;
     cairo_pdf_resource_t surface_res;
     int width;
     int height;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 19d829a..6d45422 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1175,7 +1175,7 @@ static cairo_status_t
 _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
 				       cairo_surface_t		*source,
 				       cairo_filter_t		 filter,
-				       cairo_bool_t              mask,
+				       cairo_bool_t              stencil_mask,
 				       cairo_pdf_resource_t	*surface_res,
 				       int                      *width,
 				       int                      *height,
@@ -1225,7 +1225,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
 
     surface_entry->id = surface_key.id;
     surface_entry->interpolate = interpolate;
-    surface_entry->mask = mask;
+    surface_entry->stencil_mask = stencil_mask;
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_UNIQUE_ID,
 				 &unique_id, &unique_id_length);
     if (unique_id && unique_id_length > 0) {
@@ -1870,56 +1870,21 @@ _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
     return TRUE;
 }
 
-static cairo_status_t
-_cairo_pdf_surface_emit_imagemask (cairo_pdf_surface_t	 *surface,
-				   cairo_image_surface_t *image,
-				   cairo_pdf_resource_t	 *image_res)
-{
-    cairo_status_t status;
-    uint8_t *byte, output_byte;
-    int row, col, num_cols;
-
-
-    /* This is the only image format supported for stencil masking */
-    assert (image->format == CAIRO_FORMAT_A1);
-
-    status = _cairo_pdf_surface_open_stream (surface,
-					     image_res,
-					     TRUE,
-					     "   /Type /XObject\n"
-					     "   /Subtype /Image\n"
-					     "   /ImageMask true\n"
-					     "   /Width %d\n"
-					     "   /Height %d\n"
-					     "   /BitsPerComponent 1\n",
-					     image->width, image->height);
-    if (unlikely (status))
-	return status;
-
-    num_cols = (image->width + 7) / 8;
-    for (row = 0; row < image->height; row++) {
-	byte = image->data + row * image->stride;
-	for (col = 0; col < num_cols; col++) {
-	    output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
-	    output_byte = ~output_byte;
-	    _cairo_output_stream_write (surface->output, &output_byte, 1);
-	    byte++;
-	}
-    }
-
-    return _cairo_pdf_surface_close_stream (surface);
-}
-
 /* Emit alpha channel from the image into the given data, providing
  * an id that can be used to reference the resulting SMask object.
  *
  * In the case that the alpha channel happens to be all opaque, then
  * no SMask object will be emitted and *id_ret will be set to 0.
+ *
+ * When stencil_mask is TRUE, stream_res is an an input specifying the
+ * resource to use. When stencil_mask is FALSE, a new resource will be
+ * created and returned in stream_res.
  */
 static cairo_status_t
 _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 			       cairo_image_surface_t	*image,
-			       cairo_pdf_resource_t	*stream_ret)
+			       cairo_bool_t              stencil_mask,
+			       cairo_pdf_resource_t	*stream_res)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     char *alpha;
@@ -1934,10 +1899,14 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 	    image->format == CAIRO_FORMAT_A8 ||
 	    image->format == CAIRO_FORMAT_A1 );
 
-    stream_ret->id = 0;
     transparency = _cairo_image_analyze_transparency (image);
-    if (transparency == CAIRO_IMAGE_IS_OPAQUE)
-	return status;
+    if (stencil_mask) {
+	assert (transparency == CAIRO_IMAGE_IS_OPAQUE ||
+		transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA);
+    } else {
+	if (transparency == CAIRO_IMAGE_IS_OPAQUE)
+	    return status;
+    }
 
     if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA) {
 	alpha_size = (image->width + 7) / 8 * image->height;
@@ -1977,7 +1946,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 
 		if (transparency == CAIRO_IMAGE_HAS_ALPHA) {
 		    alpha[i++] = a;
-		} else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA */
+		} else { /* transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA or CAIRO_IMAGE_IS_OPAQUE */
 		    if (bit == 7)
 			alpha[i] = 0;
 		    if (a != 0)
@@ -1994,21 +1963,37 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 	}
     }
 
-    status = _cairo_pdf_surface_open_stream (surface,
-					     NULL,
-					     TRUE,
-					     "   /Type /XObject\n"
-					     "   /Subtype /Image\n"
-					     "   /Width %d\n"
-					     "   /Height %d\n"
-					     "   /ColorSpace /DeviceGray\n"
-					     "   /BitsPerComponent %d\n",
-					     image->width, image->height,
-					     transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
+    if (stencil_mask) {
+	status = _cairo_pdf_surface_open_stream (surface,
+						 stream_res,
+						 TRUE,
+						 "   /Type /XObject\n"
+						 "   /Subtype /Image\n"
+						 "   /ImageMask true\n"
+						 "   /Width %d\n"
+						 "   /Height %d\n"
+						 "   /BitsPerComponent 1\n",
+						 image->width, image->height);
+    } else {
+	stream_res->id = 0;
+	status = _cairo_pdf_surface_open_stream (surface,
+						 NULL,
+						 TRUE,
+						 "   /Type /XObject\n"
+						 "   /Subtype /Image\n"
+						 "   /Width %d\n"
+						 "   /Height %d\n"
+						 "   /ColorSpace /DeviceGray\n"
+						 "   /BitsPerComponent %d\n",
+						 image->width, image->height,
+						 transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
+    }
     if (unlikely (status))
 	goto CLEANUP_ALPHA;
 
-    *stream_ret = surface->pdf_stream.self;
+    if (!stencil_mask)
+	*stream_res = surface->pdf_stream.self;
+
     _cairo_output_stream_write (surface->output, alpha, alpha_size);
     status = _cairo_pdf_surface_close_stream (surface);
 
@@ -2025,7 +2010,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t     *surface,
                                cairo_image_surface_t   *image,
                                cairo_pdf_resource_t    *image_res,
 			       cairo_filter_t           filter,
-			       cairo_bool_t             mask)
+			       cairo_bool_t             stencil_mask)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     char *data;
@@ -2047,8 +2032,8 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t     *surface,
 	    image->format == CAIRO_FORMAT_A8 ||
 	    image->format == CAIRO_FORMAT_A1);
 
-    if (mask)
-	return _cairo_pdf_surface_emit_imagemask (surface, image, image_res);
+    if (stencil_mask)
+	return _cairo_pdf_surface_emit_smask (surface, image, stencil_mask, image_res);
 
     color = _cairo_image_analyze_color (image);
     switch (color) {
@@ -2136,7 +2121,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t     *surface,
     if (image->format == CAIRO_FORMAT_ARGB32 ||
 	image->format == CAIRO_FORMAT_A8 ||
 	image->format == CAIRO_FORMAT_A1) {
-	status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
+	status = _cairo_pdf_surface_emit_smask (surface, image, FALSE, &smask);
 	if (unlikely (status))
 	    goto CLEANUP_RGB;
 
@@ -2292,26 +2277,28 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
 				       cairo_surface_t         *source,
 				       cairo_pdf_resource_t     resource,
 				       cairo_bool_t		interpolate,
-				       cairo_bool_t             mask)
+				       cairo_bool_t             stencil_mask)
 {
     cairo_image_surface_t *image;
     void *image_extra;
     cairo_int_status_t status;
 
-    status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	return status;
+    if (!stencil_mask) {
+	status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
 
-    status = _cairo_pdf_surface_emit_jpeg_image (surface, source, resource);
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	return status;
+	status = _cairo_pdf_surface_emit_jpeg_image (surface, source, resource);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+    }
 
     status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
     if (unlikely (status))
 	return status;
 
     status = _cairo_pdf_surface_emit_image (surface, image,
-					    &resource, interpolate, mask);
+					    &resource, interpolate, stencil_mask);
     if (unlikely (status))
 	goto BAIL;
 
@@ -2576,7 +2563,7 @@ _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t        *surface,
 						      src_surface->surface,
 						      src_surface->hash_entry->surface_res,
 						      src_surface->hash_entry->interpolate,
-						      src_surface->hash_entry->mask);
+						      src_surface->hash_entry->stencil_mask);
     }
 }
 
@@ -3665,7 +3652,7 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
 static cairo_status_t
 _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
 					  cairo_surface_pattern_t *source,
-					  cairo_bool_t             mask)
+					  cairo_bool_t             stencil_mask)
 {
     cairo_pdf_resource_t surface_res;
     int width, height;
@@ -3677,7 +3664,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
     status = _cairo_pdf_surface_add_source_surface (surface,
 						    source->surface,
 						    source->base.filter,
-						    mask,
+						    stencil_mask,
 						    &surface_res,
 						    &width,
 						    &height,
@@ -3713,7 +3700,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t     *surface,
     if (unlikely (status))
 	return status;
 
-    if (mask) {
+    if (stencil_mask) {
 	_cairo_output_stream_printf (surface->output,
 				     "/x%d Do\n",
 				     surface_res.id);
@@ -5841,6 +5828,7 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t   *surface,
     cairo_surface_pattern_t *surface_pattern;
     cairo_image_surface_t  *image;
     void		   *image_extra;
+    cairo_image_transparency_t transparency;
     cairo_pdf_resource_t pattern_res = {0};
 
     if (! (source->type == CAIRO_PATTERN_TYPE_SOLID &&
@@ -5860,7 +5848,10 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t   *surface,
     if (image->base.status)
 	return image->base.status;
 
-    if (image->format != CAIRO_FORMAT_A1) {
+    transparency = _cairo_image_analyze_transparency (image);
+    if (transparency != CAIRO_IMAGE_IS_OPAQUE &&
+	transparency != CAIRO_IMAGE_HAS_BILEVEL_ALPHA)
+    {
 	status = CAIRO_INT_STATUS_UNSUPPORTED;
 	goto cleanup;
     }


More information about the cairo-commit mailing list