diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2011-12-06 20:45:14 +1030 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2011-12-06 20:45:14 +1030 |
commit | c7ce1b68d5370f6e804a6edbf5be4bca3a5b7c57 (patch) | |
tree | da93a10f587046d39effdf8cf210051d0c4d2c0b | |
parent | 346b8fe3984acd2127285f4a57516a3deda5df25 (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.c | 246 |
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; |