summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2011-12-06 20:45:14 +1030
committerAdrian Johnson <ajohnson@redneon.com>2011-12-06 20:45:14 +1030
commitc7ce1b68d5370f6e804a6edbf5be4bca3a5b7c57 (patch)
treeda93a10f587046d39effdf8cf210051d0c4d2c0b
parent346b8fe3984acd2127285f4a57516a3deda5df25 (diff)
pdf: don't use patterns with padded images
and avoid padding if the padding is not required to fill the extents.
-rw-r--r--src/cairo-pdf-surface.c246
1 files changed, 131 insertions, 115 deletions
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index f45846cd..5a54530b 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1875,6 +1875,93 @@ _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
return TRUE;
}
+static cairo_status_t
+_cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface,
+ cairo_surface_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)
+{
+ 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);
+ if (unlikely (status))
+ return status;
+
+ pad_image = &image->base;
+
+ /* 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_box_round_to_rectangle (&box, &rect);
+
+ /* Check if image needs padding to fill extents */
+ w = image->width;
+ h = image->height;
+ if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
+ _cairo_fixed_integer_ceil(box.p1.y) < 0 ||
+ _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,
+ rect.width,
+ rect.height);
+ if (pad_image->status) {
+ status = pad_image->status;
+ goto BAIL;
+ }
+
+ _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
+ cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
+ pad_pattern.base.extend = CAIRO_EXTEND_PAD;
+ status = _cairo_surface_paint (pad_image,
+ CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
+ NULL);
+ _cairo_pattern_fini (&pad_pattern.base);
+ if (unlikely (status))
+ goto BAIL;
+ }
+
+ status = _cairo_pdf_surface_add_source_surface (surface,
+ pad_image,
+ source->base.filter,
+ FALSE,
+ surface_res,
+ &w,
+ &h,
+ &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);
+
+ return status;
+}
+
/* Emit alpha channel from the image into the given data, providing
* an id that can be used to reference the resulting SMask object.
*
@@ -2318,100 +2405,6 @@ BAIL:
}
static cairo_status_t
-_cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
- cairo_pdf_pattern_t *pdf_pattern,
- cairo_pdf_resource_t *resource,
- int *width,
- int *height,
- int *origin_x,
- int *origin_y)
-{
- cairo_image_surface_t *image;
- cairo_surface_t *pad_image;
- void *image_extra;
- cairo_int_status_t status;
- cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) pdf_pattern->pattern;
- int x = 0;
- int y = 0;
- cairo_bool_t interpolate;
-
- status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
- if (unlikely (status))
- return status;
-
- pad_image = &image->base;
- if (pattern->base.extend == CAIRO_EXTEND_PAD) {
- cairo_box_t box;
- cairo_rectangle_int_t rect;
- cairo_surface_pattern_t pad_pattern;
-
- /* get the operation extents in pattern space */
- _cairo_box_from_rectangle (&box, &pdf_pattern->extents);
- _cairo_matrix_transform_bounding_box_fixed (&pattern->base.matrix, &box, NULL);
- _cairo_box_round_to_rectangle (&box, &rect);
- x = -rect.x;
- y = -rect.y;
-
- pad_image = _cairo_image_surface_create_with_content (pattern->surface->content,
- rect.width,
- rect.height);
- if (pad_image->status) {
- status = pad_image->status;
- goto BAIL;
- }
-
- _cairo_pattern_init_for_surface (&pad_pattern, &image->base);
- cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
- pad_pattern.base.extend = CAIRO_EXTEND_PAD;
- status = _cairo_surface_paint (pad_image,
- CAIRO_OPERATOR_SOURCE, &pad_pattern.base,
- NULL);
- _cairo_pattern_fini (&pad_pattern.base);
- if (unlikely (status))
- goto BAIL;
- }
-
- switch (pdf_pattern->pattern->filter) {
- default:
- case CAIRO_FILTER_GOOD:
- case CAIRO_FILTER_BEST:
- case CAIRO_FILTER_BILINEAR:
- interpolate = TRUE;
- break;
- case CAIRO_FILTER_FAST:
- case CAIRO_FILTER_NEAREST:
- case CAIRO_FILTER_GAUSSIAN:
- interpolate = FALSE;
- break;
- }
-
- *resource = _cairo_pdf_surface_new_object (surface);
- if (resource->id == 0) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto BAIL;
- }
-
- status = _cairo_pdf_surface_emit_image (surface, (cairo_image_surface_t *)pad_image,
- resource, interpolate, FALSE);
- 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 (pattern->surface, image, image_extra);
-
- return status;
-}
-
-
-static cairo_status_t
_cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t *pdf_source)
{
@@ -2590,13 +2583,14 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
if (pattern->base.extend == CAIRO_EXTEND_PAD &&
pattern->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
{
- status = _cairo_pdf_surface_emit_padded_image_surface (surface,
- pdf_pattern,
- &pattern_resource,
- &pattern_width,
- &pattern_height,
- &origin_x,
- &origin_y);
+ status = _cairo_pdf_surface_add_padded_image_surface (surface,
+ pattern,
+ &pdf_pattern->extents,
+ &pattern_resource,
+ &pattern_width,
+ &pattern_height,
+ &origin_x,
+ &origin_y);
pattern_extents.x = 0;
pattern_extents.y = 0;
pattern_extents.width = pattern_width;
@@ -3653,25 +3647,41 @@ _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 stencil_mask)
+_cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
+ cairo_surface_pattern_t *source,
+ const cairo_rectangle_int_t *extents,
+ cairo_bool_t stencil_mask)
{
cairo_pdf_resource_t surface_res;
int width, height;
cairo_matrix_t cairo_p2d, pdf_p2d;
cairo_status_t status;
int alpha;
- cairo_rectangle_int_t extents;
+ cairo_rectangle_int_t extents2;
+ int origin_x = 0;
+ int origin_y = 0;
- status = _cairo_pdf_surface_add_source_surface (surface,
- source->surface,
- source->base.filter,
- stencil_mask,
- &surface_res,
- &width,
- &height,
- &extents);
+ if (source->base.extend == CAIRO_EXTEND_PAD &&
+ source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
+ {
+ status = _cairo_pdf_surface_add_padded_image_surface (surface,
+ source,
+ extents,
+ &surface_res,
+ &width,
+ &height,
+ &origin_x,
+ &origin_y);
+ } else {
+ status = _cairo_pdf_surface_add_source_surface (surface,
+ source->surface,
+ source->base.filter,
+ stencil_mask,
+ &surface_res,
+ &width,
+ &height,
+ &extents2);
+ }
if (unlikely (status))
return status;
@@ -3682,6 +3692,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
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, 0.0, height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
if (source->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
@@ -5943,6 +5954,7 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_surface_paint_surface_pattern (surface,
(cairo_surface_pattern_t *) surface_pattern,
+ NULL,
TRUE);
if (unlikely (status))
return status;
@@ -6018,11 +6030,13 @@ _cairo_pdf_surface_paint (void *abstract_surface,
goto cleanup;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
- source->extend == CAIRO_EXTEND_NONE)
+ (source->extend == CAIRO_EXTEND_NONE ||
+ source->extend == CAIRO_EXTEND_PAD))
{
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_surface_paint_surface_pattern (surface,
(cairo_surface_pattern_t *) source,
+ &extents.bounded,
FALSE);
if (unlikely (status))
goto cleanup;
@@ -6433,7 +6447,8 @@ _cairo_pdf_surface_fill (void *abstract_surface,
goto cleanup;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
- source->extend == CAIRO_EXTEND_NONE)
+ (source->extend == CAIRO_EXTEND_NONE ||
+ source->extend == CAIRO_EXTEND_PAD))
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
@@ -6448,6 +6463,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
status = _cairo_pdf_surface_paint_surface_pattern (surface,
(cairo_surface_pattern_t *) source,
+ &extents.bounded,
FALSE);
if (unlikely (status))
goto cleanup;