[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