mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-28 05:10:12 +01:00
pdf: don't use patterns with padded images
and avoid padding if the padding is not required to fill the extents.
This commit is contained in:
parent
346b8fe398
commit
c7ce1b68d5
1 changed files with 131 additions and 115 deletions
|
|
@ -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.
|
||||
*
|
||||
|
|
@ -2317,100 +2404,6 @@ BAIL:
|
|||
return status;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue