mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-27 02:00:28 +01:00
PS: Implement EXTEND_PAD for image patterns
Images with EXTEND_PAD are painted into a new image the size of the operation extents. The new image is then embedded in the PS file with the pattern matrix adjusted to ensure the image origin is in the correct location.
This commit is contained in:
parent
e639b53671
commit
19ee13ca2b
2 changed files with 83 additions and 17 deletions
|
|
@ -68,6 +68,7 @@ typedef struct cairo_ps_surface {
|
|||
int bbox_x1, bbox_y1, bbox_x2, bbox_y2;
|
||||
cairo_matrix_t cairo_to_ps;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_image_surface_t *acquired_image;
|
||||
void *image_extra;
|
||||
cairo_bool_t use_string_datasource;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@
|
|||
static const cairo_surface_backend_t cairo_ps_surface_backend;
|
||||
static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
|
||||
|
||||
static void
|
||||
_cairo_ps_surface_release_surface (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern);
|
||||
|
||||
static const cairo_ps_level_t _cairo_ps_levels[] =
|
||||
{
|
||||
CAIRO_PS_LEVEL_2,
|
||||
|
|
@ -2224,11 +2228,16 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
|
|||
static cairo_status_t
|
||||
_cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents,
|
||||
int *width,
|
||||
int *height,
|
||||
cairo_operator_t op)
|
||||
int *origin_x,
|
||||
int *origin_y)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *pad_image;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
cairo_surface_t *meta_surface = pattern->surface;
|
||||
|
|
@ -2242,16 +2251,62 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
|||
*height = pattern_extents.height;
|
||||
} else {
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||
&surface->image,
|
||||
&surface->acquired_image,
|
||||
&surface->image_extra);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
pad_image = &surface->acquired_image->base;
|
||||
if (cairo_pattern_get_extend (&pattern->base) == 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, 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, &surface->acquired_image->base);
|
||||
cairo_matrix_init_translate (&pad_pattern.base.matrix, -x, -y);
|
||||
pad_pattern.base.extend = CAIRO_EXTEND_PAD;
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
|
||||
&pad_pattern.base,
|
||||
NULL,
|
||||
pad_image,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
rect.width,
|
||||
rect.height);
|
||||
_cairo_pattern_fini (&pad_pattern.base);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
}
|
||||
|
||||
surface->image = (cairo_image_surface_t *) pad_image;
|
||||
*width = surface->image->width;
|
||||
*height = surface->image->height;
|
||||
*origin_x = x;
|
||||
*origin_y = y;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
BAIL:
|
||||
_cairo_ps_surface_release_surface (surface, pattern);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -2279,24 +2334,28 @@ _cairo_ps_surface_release_surface (cairo_ps_surface_t *surface,
|
|||
cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
if (!_cairo_surface_is_meta (pattern->surface))
|
||||
_cairo_surface_release_source_image (pattern->surface, surface->image,
|
||||
_cairo_surface_release_source_image (pattern->surface,
|
||||
surface->acquired_image,
|
||||
surface->image_extra);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents,
|
||||
cairo_operator_t op)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int width, height;
|
||||
cairo_matrix_t cairo_p2d, ps_p2d;
|
||||
int origin_x = 0;
|
||||
int origin_y = 0;
|
||||
|
||||
status = _cairo_ps_surface_acquire_surface (surface,
|
||||
pattern,
|
||||
&width,
|
||||
&height,
|
||||
op);
|
||||
extents,
|
||||
&width, &height,
|
||||
&origin_x, &origin_y);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
|
@ -2329,6 +2388,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
|
|||
|
||||
ps_p2d = surface->cairo_to_ps;
|
||||
cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
|
||||
cairo_matrix_translate (&ps_p2d, -origin_x, -origin_y);
|
||||
cairo_matrix_translate (&ps_p2d, 0.0, height);
|
||||
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
|
||||
|
||||
|
|
@ -2349,6 +2409,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
|
|||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents,
|
||||
cairo_operator_t op)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
|
@ -2358,6 +2419,8 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
cairo_matrix_t cairo_p2d, ps_p2d;
|
||||
cairo_rectangle_int_t surface_extents;
|
||||
cairo_bool_t old_use_string_datasource;
|
||||
int origin_x = 0;
|
||||
int origin_y = 0;
|
||||
|
||||
cairo_p2d = pattern->base.matrix;
|
||||
status = cairo_matrix_invert (&cairo_p2d);
|
||||
|
|
@ -2366,19 +2429,19 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
|
||||
ps_p2d = surface->cairo_to_ps;
|
||||
cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
|
||||
cairo_matrix_translate (&ps_p2d, -origin_x, -origin_y);
|
||||
cairo_matrix_translate (&ps_p2d, 0.0, pattern_height);
|
||||
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
|
||||
|
||||
status = _cairo_ps_surface_acquire_surface (surface,
|
||||
pattern,
|
||||
&pattern_width,
|
||||
&pattern_height,
|
||||
op);
|
||||
extents,
|
||||
&pattern_width, &pattern_height,
|
||||
&origin_x, &origin_y);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
switch (pattern->base.extend) {
|
||||
/* We implement EXTEND_PAD like EXTEND_NONE for now */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
case CAIRO_EXTEND_NONE:
|
||||
{
|
||||
|
|
@ -2914,7 +2977,8 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
|
|||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_operator_t op)
|
||||
cairo_rectangle_int_t *extents,
|
||||
cairo_operator_t op)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -2951,6 +3015,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
|||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
status = _cairo_ps_surface_emit_surface_pattern (surface,
|
||||
(cairo_surface_pattern_t *) pattern,
|
||||
extents,
|
||||
op);
|
||||
if (status)
|
||||
return status;
|
||||
|
|
@ -3079,13 +3144,13 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
|
||||
status = _cairo_ps_surface_paint_surface (surface,
|
||||
(cairo_surface_pattern_t *) source,
|
||||
op);
|
||||
paint_extents, op);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "Q\n");
|
||||
} else {
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, paint_extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -3125,7 +3190,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
"%% _cairo_ps_surface_stroke\n");
|
||||
#endif
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -3177,14 +3242,14 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
|
||||
status = _cairo_ps_surface_paint_surface (surface,
|
||||
(cairo_surface_pattern_t *) source,
|
||||
op);
|
||||
extents, op);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream, "Q\n");
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
} else {
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -3225,7 +3290,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue