[cairo-commit] src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h
Adrian Johnson
ajohnson at kemper.freedesktop.org
Wed Jan 11 04:41:21 PST 2012
src/cairo-pdf-surface-private.h | 4
src/cairo-pdf-surface.c | 473 ++++++++++++++++++++++++++--------------
2 files changed, 323 insertions(+), 154 deletions(-)
New commits:
commit 0a10982f8c4f08018f50ec73663761ccf7b9c839
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Jan 10 00:11:41 2012 +1030
pdf: support RASTER_SOURCE patterns
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 1e174fe..a58fbbf 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -75,11 +75,15 @@ typedef struct _cairo_pdf_source_surface_entry {
cairo_pdf_resource_t surface_res;
int width;
int height;
+ double x_offset;
+ double y_offset;
cairo_rectangle_int_t extents;
} cairo_pdf_source_surface_entry_t;
typedef struct _cairo_pdf_source_surface {
+ cairo_pattern_type_t type;
cairo_surface_t *surface;
+ cairo_pattern_t *raster_pattern;
cairo_pdf_source_surface_entry_t *hash_entry;
} cairo_pdf_source_surface_t;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d7108d1..148e6ff 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1104,6 +1104,67 @@ _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
}
static cairo_int_status_t
+_cairo_pdf_surface_acquire_source_image_from_pattern (cairo_pdf_surface_t *surface,
+ const cairo_pattern_t *pattern,
+ const cairo_rectangle_int_t *extents,
+ cairo_image_surface_t **image,
+ void **image_extra)
+{
+ switch (pattern->type) {
+ case CAIRO_PATTERN_TYPE_SURFACE: {
+ cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
+ return _cairo_surface_acquire_source_image (surf_pat->surface, image, image_extra);
+ } break;
+
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
+ cairo_surface_t *surf;
+ surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, extents);
+ if (!surf)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (cairo_surface_get_type (surf) == CAIRO_SURFACE_TYPE_IMAGE);
+ *image = (cairo_image_surface_t *) surf;
+ } break;
+
+ case CAIRO_PATTERN_TYPE_SOLID:
+ case CAIRO_PATTERN_TYPE_LINEAR:
+ case CAIRO_PATTERN_TYPE_RADIAL:
+ case CAIRO_PATTERN_TYPE_MESH:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t *surface,
+ const cairo_pattern_t *pattern,
+ cairo_image_surface_t *image,
+ void *image_extra)
+{
+ switch (pattern->type) {
+ case CAIRO_PATTERN_TYPE_SURFACE: {
+ cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
+ _cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
+ } break;
+
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ _cairo_raster_source_pattern_release (pattern, &image->base);
+ break;
+
+ case CAIRO_PATTERN_TYPE_SOLID:
+ case CAIRO_PATTERN_TYPE_LINEAR:
+ case CAIRO_PATTERN_TYPE_RADIAL:
+ case CAIRO_PATTERN_TYPE_MESH:
+ default:
+
+ ASSERT_NOT_REACHED;
+ break;
+ }
+}
+
+static cairo_int_status_t
_get_jpx_image_info (cairo_surface_t *source,
cairo_image_info_t *info,
const unsigned char **mime_data,
@@ -1202,23 +1263,56 @@ _get_source_surface_size (cairo_surface_t *source,
return CAIRO_STATUS_SUCCESS;
}
+/**
+ * _cairo_pdf_surface_add_source_surface:
+ * @surface: the pdf surface
+ * @source_surface: A #cairo_surface_t to use as the source surface
+ * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
+ * @filter: filter type of the source pattern
+ * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask
+ * @extents: extents of the operation that is using this source
+ * @surface_res: return PDF resource number of the surface
+ * @width: returns width of surface
+ * @height: returns height of surface
+ * @x_offset: x offset of surface
+ * @t_offset: y offset of surface
+ * @source_extents: returns extents of source (either ink extents or extents needed to cover @extents)
+ *
+ * Add surface or raster_source pattern to list of surfaces to be
+ * written to the PDF file when the current page is finished. Returns
+ * a PDF resource to reference the image. A hash table of all images
+ * in the PDF files (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or surface
+ * unique_id) to ensure surfaces with the same id are only written
+ * once to the PDF file.
+ *
+ * Only one of @source_pattern or @source_surface is to be
+ * specified. Set the other to NULL.
+ */
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 stencil_mask,
- cairo_pdf_resource_t *surface_res,
- int *width,
- int *height,
- cairo_rectangle_int_t *extents)
+_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
+ cairo_surface_t *source_surface,
+ const cairo_pattern_t *source_pattern,
+ cairo_filter_t filter,
+ cairo_bool_t stencil_mask,
+ const cairo_rectangle_int_t *extents,
+ cairo_pdf_resource_t *surface_res,
+ int *width,
+ int *height,
+ double *x_offset,
+ double *y_offset,
+ cairo_rectangle_int_t *source_extents)
{
cairo_pdf_source_surface_t src_surface;
cairo_pdf_source_surface_entry_t surface_key;
cairo_pdf_source_surface_entry_t *surface_entry;
cairo_status_t status;
cairo_bool_t interpolate;
- const unsigned char *unique_id;
- unsigned long unique_id_length;
+ unsigned char *unique_id;
+ unsigned long unique_id_length = 0;
+ cairo_box_t box;
+ cairo_rectangle_int_t rect;
+ cairo_image_surface_t *image;
+ void *image_extra;
switch (filter) {
default:
@@ -1234,9 +1328,32 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
break;
}
- surface_key.id = source->unique_id;
+ *x_offset = 0;
+ *y_offset = 0;
+ if (source_pattern) {
+ if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
+ /* get the operation extents in pattern space */
+ _cairo_box_from_rectangle (&box, extents);
+ _cairo_matrix_transform_bounding_box_fixed (&source_pattern->matrix, &box, NULL);
+ _cairo_box_round_to_rectangle (&box, &rect);
+ status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern,
+ &rect, &image,
+ &image_extra);
+ if (unlikely (status))
+ return status;
+ source_surface = &image->base;
+ cairo_surface_get_device_offset (source_surface, x_offset, y_offset);
+ } else {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern;
+ source_surface = surface_pattern->surface;
+ }
+ } else {
+ cairo_surface_get_device_offset (source_surface, x_offset, y_offset);
+ }
+
+ surface_key.id = source_surface->unique_id;
surface_key.interpolate = interpolate;
- cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_UNIQUE_ID,
+ cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID,
(const unsigned char **) &surface_key.unique_id,
&surface_key.unique_id_length);
_cairo_pdf_source_surface_init_key (&surface_key);
@@ -1245,64 +1362,100 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
*surface_res = surface_entry->surface_res;
*width = surface_entry->width;
*height = surface_entry->height;
- *extents = surface_entry->extents;
+ *source_extents = surface_entry->extents;
+ status = CAIRO_STATUS_SUCCESS;
+ } else {
+ status = _get_source_surface_size (source_surface,
+ width,
+ height,
+ source_extents);
+ if (unlikely(status))
+ goto release_source;
+
+ if (surface_key.unique_id && surface_key.unique_id_length > 0) {
+ unique_id = malloc (unique_id_length);
+ if (unique_id == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto release_source;
+ }
- return CAIRO_STATUS_SUCCESS;
+ unique_id_length = surface_key.unique_id_length;
+ memcpy (unique_id, surface_key.unique_id, unique_id_length);
+ } else {
+ unique_id = NULL;
+ unique_id_length = 0;
+ }
}
+release_source:
+ if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
+ _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra);
+
+ if (status || surface_entry)
+ return status;
+
surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t));
- if (surface_entry == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (surface_entry == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto fail1;
+ }
surface_entry->id = surface_key.id;
surface_entry->interpolate = interpolate;
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) {
- surface_entry->unique_id = malloc (unique_id_length);
- if (surface_entry->unique_id == NULL) {
- cairo_surface_destroy (source);
- free (surface_entry);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
+ surface_entry->unique_id_length = unique_id_length;
+ surface_entry->unique_id = unique_id;
+ surface_entry->width = *width;
+ surface_entry->height = *height;
+ surface_entry->x_offset = *x_offset;
+ surface_entry->y_offset = *y_offset;
+ surface_entry->extents = *source_extents;
+ _cairo_pdf_source_surface_init_key (surface_entry);
+
+ src_surface.hash_entry = surface_entry;
+ if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
+ src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE;
+ src_surface.surface = NULL;
+ status = _cairo_pattern_create_copy (&src_surface.raster_pattern, source_pattern);
+ if (unlikely (status))
+ goto fail2;
- surface_entry->unique_id_length = unique_id_length;
- memcpy (surface_entry->unique_id, unique_id, unique_id_length);
} else {
- surface_entry->unique_id = NULL;
- surface_entry->unique_id_length = 0;
+ src_surface.type = CAIRO_PATTERN_TYPE_SURFACE;
+ src_surface.surface = cairo_surface_reference (source_surface);
+ src_surface.raster_pattern = NULL;
}
- _cairo_pdf_source_surface_init_key (surface_entry);
- src_surface.hash_entry = surface_entry;
- src_surface.surface = cairo_surface_reference (source);
surface_entry->surface_res = _cairo_pdf_surface_new_object (surface);
if (surface_entry->surface_res.id == 0) {
- cairo_surface_destroy (source);
- free (surface_entry);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto fail3;
}
- status = _get_source_surface_size (source,
- &surface_entry->width,
- &surface_entry->height,
- &surface_entry->extents);
-
status = _cairo_array_append (&surface->page_surfaces, &src_surface);
- if (unlikely (status)) {
- cairo_surface_destroy (source);
- free (surface_entry);
- return status;
- }
+ if (unlikely (status))
+ goto fail3;
status = _cairo_hash_table_insert (surface->all_surfaces,
&surface_entry->base);
+ if (unlikely(status))
+ goto fail3;
*surface_res = surface_entry->surface_res;
- *width = surface_entry->width;
- *height = surface_entry->height;
- *extents = surface_entry->extents;
+
+ return status;
+
+fail3:
+ if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
+ cairo_pattern_destroy (src_surface.raster_pattern);
+ else
+ cairo_surface_destroy (src_surface.surface);
+
+fail2:
+ free (surface_entry);
+
+fail1:
+ free (unique_id);
return status;
}
@@ -1936,27 +2089,26 @@ _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
static cairo_status_t
_cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
- cairo_surface_pattern_t *source,
+ const cairo_pattern_t *source,
const cairo_rectangle_int_t *extents,
cairo_pdf_resource_t *surface_res,
int *width,
int *height,
- int *origin_x,
- int *origin_y)
+ double *x_offset,
+ double *y_offset)
{
cairo_image_surface_t *image;
cairo_surface_t *pad_image;
void *image_extra;
cairo_int_status_t status;
- int x = 0;
- int y = 0;
int w, h;
cairo_rectangle_int_t extents2;
cairo_box_t box;
cairo_rectangle_int_t rect;
cairo_surface_pattern_t pad_pattern;
- status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
+ status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source, extents,
+ &image, &image_extra);
if (unlikely (status))
return status;
@@ -1964,7 +2116,7 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
/* get the operation extents in pattern space */
_cairo_box_from_rectangle (&box, extents);
- _cairo_matrix_transform_bounding_box_fixed (&source->base.matrix, &box, NULL);
+ _cairo_matrix_transform_bounding_box_fixed (&source->matrix, &box, NULL);
_cairo_box_round_to_rectangle (&box, &rect);
/* Check if image needs padding to fill extents */
@@ -1975,9 +2127,7 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
_cairo_fixed_integer_floor(box.p2.y) > w ||
_cairo_fixed_integer_floor(box.p2.y) > h)
{
- x = -rect.x;
- y = -rect.y;
- pad_image = _cairo_image_surface_create_with_content (source->surface->content,
+ pad_image = _cairo_image_surface_create_with_content (cairo_surface_get_content (&image->base),
rect.width,
rect.height);
if (pad_image->status) {
@@ -1986,7 +2136,7 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
}
_cairo_pattern_init_for_surface (&pad_pattern, &image->base);
- cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
+ cairo_matrix_init_translate (&pad_pattern.base.matrix, rect.x, rect.y);
pad_pattern.base.extend = CAIRO_EXTEND_PAD;
status = _cairo_surface_paint (pad_image,
CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
@@ -1994,29 +2144,30 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
_cairo_pattern_fini (&pad_pattern.base);
if (unlikely (status))
goto BAIL;
+
+ cairo_surface_set_device_offset (pad_image, rect.x, rect.y);
}
status = _cairo_pdf_surface_add_source_surface (surface,
pad_image,
- source->base.filter,
+ NULL,
+ source->filter,
FALSE,
+ extents,
surface_res,
- &w,
- &h,
+ width,
+ height,
+ x_offset,
+ y_offset,
&extents2);
if (unlikely (status))
goto BAIL;
- *width = ((cairo_image_surface_t *)pad_image)->width;
- *height = ((cairo_image_surface_t *)pad_image)->height;
- *origin_x = x;
- *origin_y = y;
-
BAIL:
if (pad_image != &image->base)
cairo_surface_destroy (pad_image);
- _cairo_surface_release_source_image (source->surface, image, image_extra);
+ _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
return status;
}
@@ -2440,37 +2591,44 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
}
static cairo_status_t
-_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 stencil_mask)
+_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
+ cairo_pdf_source_surface_t *source)
{
cairo_image_surface_t *image;
void *image_extra;
cairo_int_status_t status;
- if (!stencil_mask) {
- status = _cairo_pdf_surface_emit_jpx_image (surface, source, resource);
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra);
+ } else {
+ status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source->raster_pattern,
+ &source->hash_entry->extents,
+ &image, &image_extra);
+ }
+ if (unlikely (status))
+ return status;
+
+ if (!source->hash_entry->stencil_mask) {
+ status = _cairo_pdf_surface_emit_jpx_image (surface, &image->base, source->hash_entry->surface_res);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto release_source;
- status = _cairo_pdf_surface_emit_jpeg_image (surface, source, resource);
+ status = _cairo_pdf_surface_emit_jpeg_image (surface, &image->base, source->hash_entry->surface_res);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
+ goto release_source;
}
- 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, stencil_mask);
- if (unlikely (status))
- goto BAIL;
+ &source->hash_entry->surface_res,
+ source->hash_entry->interpolate,
+ source->hash_entry->stencil_mask);
-BAIL:
- _cairo_surface_release_source_image (source, image, image_extra);
+release_source:
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
+ _cairo_surface_release_source_image (source->surface, image, image_extra);
+ else
+ _cairo_pdf_surface_release_source_image_from_pattern (surface, source->raster_pattern,
+ image, image_extra);
return status;
}
@@ -2485,8 +2643,10 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
cairo_box_double_t bbox;
cairo_int_status_t status;
int alpha = 0;
- cairo_surface_t *source = pdf_source->surface;
+ cairo_surface_t *source;
+ assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE);
+ source = pdf_source->surface;
if (_cairo_surface_is_snapshot (source))
source = _cairo_surface_snapshot_get_target (source);
@@ -2613,69 +2773,66 @@ static cairo_status_t
_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t *src_surface)
{
- if (src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
- if (src_surface->surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
- cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) src_surface->surface;
- return _cairo_pdf_surface_emit_recording_subsurface (surface,
- sub->target,
- &sub->extents,
- src_surface->hash_entry->surface_res);
- } else {
- return _cairo_pdf_surface_emit_recording_surface (surface,
- src_surface);
+ if (src_surface->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ if (src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
+ if (src_surface->surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
+ cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) src_surface->surface;
+ return _cairo_pdf_surface_emit_recording_subsurface (surface,
+ sub->target,
+ &sub->extents,
+ src_surface->hash_entry->surface_res);
+ } else {
+ return _cairo_pdf_surface_emit_recording_surface (surface,
+ src_surface);
+ }
}
- } else {
- return _cairo_pdf_surface_emit_image_surface (surface,
- src_surface->surface,
- src_surface->hash_entry->surface_res,
- src_surface->hash_entry->interpolate,
- src_surface->hash_entry->stencil_mask);
}
+ return _cairo_pdf_surface_emit_image_surface (surface, src_surface);
}
static cairo_status_t
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern)
{
- cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
+ cairo_pattern_t *pattern = pdf_pattern->pattern;
cairo_status_t status;
cairo_pdf_resource_t pattern_resource = {0};
cairo_matrix_t cairo_p2d, pdf_p2d;
- cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
+ cairo_extend_t extend = cairo_pattern_get_extend (pattern);
double xstep, ystep;
cairo_rectangle_int_t pattern_extents;
int pattern_width = 0; /* squelch bogus compiler warning */
int pattern_height = 0; /* squelch bogus compiler warning */
- int origin_x = 0; /* squelch bogus compiler warning */
- int origin_y = 0; /* squelch bogus compiler warning */
+ double x_offset;
+ double y_offset;
char draw_surface[200];
cairo_box_double_t bbox;
- if (pattern->base.extend == CAIRO_EXTEND_PAD &&
- pattern->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
- {
+ if (pattern->extend == CAIRO_EXTEND_PAD) {
status = _cairo_pdf_surface_add_padded_image_surface (surface,
pattern,
&pdf_pattern->extents,
&pattern_resource,
&pattern_width,
&pattern_height,
- &origin_x,
- &origin_y);
+ &x_offset,
+ &y_offset);
pattern_extents.x = 0;
pattern_extents.y = 0;
pattern_extents.width = pattern_width;
pattern_extents.height = pattern_height;
- }
- else
- {
+ } else {
status = _cairo_pdf_surface_add_source_surface (surface,
- pattern->surface,
- pdf_pattern->pattern->filter,
+ NULL,
+ pattern,
+ pattern->filter,
FALSE,
+ &pdf_pattern->extents,
&pattern_resource,
&pattern_width,
&pattern_height,
+ &x_offset,
+ &y_offset,
&pattern_extents);
}
if (unlikely (status))
@@ -2699,7 +2856,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
*/
double x1 = 0.0, y1 = 0.0;
double x2 = surface->width, y2 = surface->height;
- _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
+ _cairo_matrix_transform_bounding_box (&pattern->matrix,
&x1, &y1, &x2, &y2,
NULL);
@@ -2758,13 +2915,13 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
* have to scale it up by the image width and height to fill our
* pattern cell.
*/
- cairo_p2d = pattern->base.matrix;
+ cairo_p2d = pattern->matrix;
status = cairo_matrix_invert (&cairo_p2d);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf);
- cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
+ cairo_matrix_translate (&pdf_p2d, -x_offset, -y_offset);
cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
@@ -2791,7 +2948,8 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
if (unlikely (status))
return status;
- if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
+ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ ((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
snprintf(draw_surface,
sizeof (draw_surface),
"/x%d Do\n",
@@ -3712,12 +3870,12 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
switch (pdf_pattern->pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
- case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
ASSERT_NOT_REACHED;
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
break;
case CAIRO_PATTERN_TYPE_SURFACE:
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
status = _cairo_pdf_surface_emit_surface_pattern (surface, pdf_pattern);
break;
@@ -3745,7 +3903,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,
+ const cairo_pattern_t *source,
const cairo_rectangle_int_t *extents,
cairo_bool_t stencil_mask)
{
@@ -3755,11 +3913,12 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
cairo_status_t status;
int alpha;
cairo_rectangle_int_t extents2;
- int origin_x = 0;
- int origin_y = 0;
+ double x_offset;
+ double y_offset;
- if (source->base.extend == CAIRO_EXTEND_PAD &&
- source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
+ if (source->extend == CAIRO_EXTEND_PAD &&
+ !(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
{
status = _cairo_pdf_surface_add_padded_image_surface (surface,
source,
@@ -3767,33 +3926,40 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
&surface_res,
&width,
&height,
- &origin_x,
- &origin_y);
+ &x_offset,
+ &y_offset);
} else {
status = _cairo_pdf_surface_add_source_surface (surface,
- source->surface,
- source->base.filter,
+ NULL,
+ source,
+ source->filter,
stencil_mask,
+ extents,
&surface_res,
&width,
&height,
+ &x_offset,
+ &y_offset,
&extents2);
}
if (unlikely (status))
return status;
- cairo_p2d = source->base.matrix;
+ cairo_p2d = source->matrix;
status = cairo_matrix_invert (&cairo_p2d);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
pdf_p2d = surface->cairo_to_pdf;
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
- cairo_matrix_translate (&pdf_p2d, -origin_x, -origin_y);
+ cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
cairo_matrix_translate (&pdf_p2d, 0.0, height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
- if (source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
+ if (!(source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING))
+ {
cairo_matrix_scale (&pdf_p2d, width, height);
+ }
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
@@ -3896,8 +4062,9 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
{
switch (source->type) {
case CAIRO_PATTERN_TYPE_SURFACE:
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return _cairo_pdf_surface_paint_surface_pattern (surface,
- (cairo_surface_pattern_t *)source,
+ source,
extents,
mask);
case CAIRO_PATTERN_TYPE_LINEAR:
@@ -3922,6 +4089,7 @@ _can_paint_pattern (const cairo_pattern_t *pattern)
return FALSE;
case CAIRO_PATTERN_TYPE_SURFACE:
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return (pattern->extend == CAIRO_EXTEND_NONE ||
pattern->extend == CAIRO_EXTEND_PAD);
@@ -5965,6 +6133,7 @@ _pattern_supported (const cairo_pattern_t *pattern)
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
case CAIRO_PATTERN_TYPE_MESH:
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return TRUE;
case CAIRO_PATTERN_TYPE_SURFACE:
@@ -5972,7 +6141,6 @@ _pattern_supported (const cairo_pattern_t *pattern)
default:
ASSERT_NOT_REACHED;
- case CAIRO_PATTERN_TYPE_RASTER_SOURCE: /* XXX */
return FALSE;
}
}
@@ -6116,28 +6284,29 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
/* A PDF stencil mask is an A1 mask used with the current color */
static cairo_int_status_t
-_cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask)
+_cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *extents)
{
cairo_status_t status;
- 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 &&
- mask->type == CAIRO_PATTERN_TYPE_SURFACE))
+ (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
return CAIRO_INT_STATUS_UNSUPPORTED;
- surface_pattern = (cairo_surface_pattern_t *) mask;
- if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
+ if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
+ {
return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
- status = _cairo_surface_acquire_source_image (surface_pattern->surface,
- &image,
- &image_extra);
+ status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask, extents,
+ &image, &image_extra);
if (unlikely (status))
return status;
@@ -6162,20 +6331,16 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
return status;
_cairo_output_stream_printf (surface->output, "q\n");
- status = _cairo_pdf_surface_paint_surface_pattern (surface,
- (cairo_surface_pattern_t *) surface_pattern,
- NULL,
- TRUE);
+ status = _cairo_pdf_surface_paint_surface_pattern (surface, mask, NULL, TRUE);
if (unlikely (status))
return status;
_cairo_output_stream_printf (surface->output, "Q\n");
- _cairo_surface_release_source_image (surface_pattern->surface, image, image_extra);
status = _cairo_output_stream_get_status (surface->output);
cleanup:
- _cairo_surface_release_source_image (surface_pattern->surface, image, image_extra);
+ _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
return status;
}
@@ -6396,7 +6561,7 @@ _cairo_pdf_surface_mask (void *abstract_surface,
goto cleanup;
/* Check if we can use a stencil mask */
- status = _cairo_pdf_surface_emit_stencil_mask (surface, source, mask);
+ status = _cairo_pdf_surface_emit_stencil_mask (surface, source, mask, &extents.bounded);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto cleanup;
More information about the cairo-commit
mailing list