ps: support RASTER_SOURCE patterns

This commit is contained in:
Adrian Johnson 2012-01-31 22:29:01 +10:30
parent 0f40cdea1b
commit 46ca65895f
3 changed files with 389 additions and 217 deletions

View file

@ -70,11 +70,6 @@ typedef struct cairo_ps_surface {
int bbox_x1, bbox_y1, bbox_x2, bbox_y2;
cairo_matrix_t cairo_to_ps;
/* XXX These 3 are used as temporary storage whilst emitting patterns */
cairo_image_surface_t *image;
cairo_image_surface_t *acquired_image;
void *image_extra;
cairo_bool_t use_string_datasource;
cairo_bool_t current_pattern_is_solid_color;

View file

@ -126,10 +126,6 @@ static cairo_bool_t
_cairo_ps_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle);
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,
@ -1670,21 +1666,229 @@ color_is_gray (double red, double green, double blue)
fabs (red - blue) < epsilon);
}
static cairo_int_status_t
_cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern)
/**
* _cairo_ps_surface_acquire_source_surface_from_pattern:
* @surface: the ps surface
* @pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source
* @extents: extents of the operation that is using this source
* @width: returns width of surface
* @height: returns height of surface
* @x_offset: returns x offset of surface
* @y_offset: returns y offset of surface
* @surface: returns surface of type image surface or recording surface
* @image_extra: returns image extra for image type surface
*
* Acquire source surface surface or raster source pattern.
*/
static cairo_status_t
_cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t *surface,
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents,
int *width,
int *height,
double *x_offset,
double *y_offset,
cairo_surface_t **source_surface,
void **image_extra)
{
cairo_status_t status;
cairo_image_surface_t *image;
void *image_extra;
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SURFACE: {
cairo_surface_t *surf = ((cairo_surface_pattern_t *) pattern)->surface;
if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) {
if (surf->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) surf;
*width = sub->extents.width;
*height = sub->extents.height;
} else {
cairo_recording_surface_t *recording_surface;
cairo_box_t bbox;
cairo_rectangle_int_t extents;
recording_surface = (cairo_recording_surface_t *) surf;
if (_cairo_surface_is_snapshot (&recording_surface->base))
recording_surface = (cairo_recording_surface_t *)
_cairo_surface_snapshot_get_target (&recording_surface->base);
status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
if (unlikely (status))
return status;
_cairo_box_round_to_rectangle (&bbox, &extents);
*width = extents.width;
*height = extents.height;
}
cairo_surface_get_device_offset (surf, x_offset, y_offset);
*source_surface = surf;
return CAIRO_STATUS_SUCCESS;
} else {
status = _cairo_surface_acquire_source_image (surf, &image, image_extra);
if (unlikely (status))
return status;
}
} break;
case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
cairo_surface_t *surf;
cairo_box_t box;
cairo_rectangle_int_t rect;
/* get the operation extents in pattern space */
_cairo_box_from_rectangle (&box, extents);
_cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL);
_cairo_box_round_to_rectangle (&box, &rect);
surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, &rect);
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;
}
*width = image->width;
*height = image->height;
cairo_surface_get_device_offset (&image->base, x_offset, y_offset);
*source_surface = &image->base;
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t *surface,
const cairo_pattern_t *pattern,
cairo_surface_t *source,
void *image_extra)
{
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SURFACE: {
cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern;
if (surf_pat->surface->type != CAIRO_SURFACE_TYPE_RECORDING) {
cairo_image_surface_t *image = (cairo_image_surface_t *) source;
_cairo_surface_release_source_image (surf_pat->surface, image, image_extra);
}
} break;
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
_cairo_raster_source_pattern_release (pattern, source);
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;
}
}
/**
* _cairo_ps_surface_create_padded_image_from_image
* @surface: the ps surface
* @source: The source image
* @extents: extents of the operation that is using this source
* @width: returns width of padded image
* @height: returns height of padded image
* @x_offset: returns x offset of padded image
* @y_offset: returns y offset of padded image
* @image: returns the padded image
*/
static cairo_status_t
_cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t *surface,
cairo_image_surface_t *source,
const cairo_matrix_t *source_matrix,
const cairo_rectangle_int_t *extents,
int *width,
int *height,
double *x_offset,
double *y_offset,
cairo_image_surface_t **image)
{
cairo_box_t box;
cairo_rectangle_int_t rect;
cairo_surface_t *pad_image;
cairo_surface_pattern_t pad_pattern;
int w, h;
cairo_int_status_t status;
/* get the operation extents in pattern space */
_cairo_box_from_rectangle (&box, extents);
_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. */
w = source->width;
h = source->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)
{
pad_image =
_cairo_image_surface_create_with_pixman_format (NULL,
source->pixman_format,
rect.width, rect.height,
0);
if (pad_image->status)
return pad_image->status;
_cairo_pattern_init_for_surface (&pad_pattern, &source->base);
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,
NULL);
_cairo_pattern_fini (&pad_pattern.base);
}
*image = (cairo_image_surface_t *) pad_image;
*width = rect.width;
*height = rect.height;
*x_offset = rect.x;
*y_offset = rect.y;
return status;
}
static cairo_int_status_t
_cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t *surface,
const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents)
{
int width, height;
double x_offset, y_offset;
cairo_surface_t *source;
cairo_image_surface_t *image;
void *image_extra;
cairo_int_status_t status;
cairo_image_transparency_t transparency;
status = _cairo_surface_acquire_source_image (pattern->surface,
&image,
&image_extra);
status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface,
pattern,
extents,
&width,
&height,
&x_offset,
&y_offset,
&source,
&image_extra);
if (unlikely (status))
return status;
image = (cairo_image_surface_t *) source;
if (image->base.status)
return image->base.status;
@ -1711,7 +1915,7 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
ASSERT_NOT_REACHED;
}
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
_cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra);
return status;
}
@ -1771,8 +1975,9 @@ pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern)
case CAIRO_PATTERN_TYPE_SURFACE:
return surface_pattern_supported ((cairo_surface_pattern_t *) pattern);
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return FALSE;
return TRUE;
default:
ASSERT_NOT_REACHED;
@ -1781,7 +1986,9 @@ pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern)
}
static cairo_bool_t
mask_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *mask)
mask_supported (cairo_ps_surface_t *surface,
const cairo_pattern_t *mask,
const cairo_rectangle_int_t *extents)
{
if (surface->ps_level == CAIRO_PS_LEVEL_2)
return FALSE;
@ -1790,7 +1997,7 @@ mask_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *mask)
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE) {
/* check if mask if opaque or bilevel alpha */
if (_cairo_ps_surface_analyze_surface_pattern_transparency (surface, surface_pattern) == CAIRO_INT_STATUS_SUCCESS) {
if (_cairo_ps_surface_analyze_surface_pattern_transparency (surface, mask, extents) == CAIRO_INT_STATUS_SUCCESS) {
surface->ps_level_used = CAIRO_PS_LEVEL_3;
return TRUE;
}
@ -1822,7 +2029,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Mask is only supported when the mask is an image with opaque or bilevel alpha. */
if (mask && !mask_supported (surface, mask))
if (mask && !mask_supported (surface, mask, extents))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
@ -1852,12 +2059,8 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
* render stage and we blend the transparency into the white
* background to convert the pattern to opaque.
*/
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
surface_pattern);
}
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE || pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
return _cairo_ps_surface_analyze_surface_pattern_transparency (surface, pattern, extents);
/* Patterns whose drawn part is opaque are directly supported;
those whose drawn part is partially transparent can be
@ -2825,121 +3028,10 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
red, green, blue);
}
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,
int *origin_x,
int *origin_y)
{
cairo_status_t status;
cairo_surface_t *pad_image;
int x = 0;
int y = 0;
int w, h;
surface->acquired_image = NULL;
surface->image = NULL;
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
if (pattern->surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) pattern->surface;
*width = sub->extents.width;
*height = sub->extents.height;
} else {
cairo_recording_surface_t *recording_surface;
cairo_box_t bbox;
cairo_rectangle_int_t extents;
recording_surface = (cairo_recording_surface_t *) pattern->surface;
if (_cairo_surface_is_snapshot (&recording_surface->base))
recording_surface = (cairo_recording_surface_t *)
_cairo_surface_snapshot_get_target (&recording_surface->base);
status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
if (unlikely (status))
return status;
_cairo_box_round_to_rectangle (&bbox, &extents);
*width = extents.width;
*height = extents.height;
}
return CAIRO_STATUS_SUCCESS;
} else {
status = _cairo_surface_acquire_source_image (pattern->surface,
&surface->acquired_image,
&surface->image_extra);
if (unlikely (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);
/* Check if image needs padding to fill extents. */
w = surface->acquired_image->width;
h = surface->acquired_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_pixman_format (NULL,
surface->acquired_image->pixman_format,
rect.width, rect.height,
0);
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_paint (pad_image,
CAIRO_OPERATOR_SOURCE,
&pad_pattern.base,
NULL);
_cairo_pattern_fini (&pad_pattern.base);
if (unlikely (status)) {
if (pad_image != &surface->acquired_image->base)
cairo_surface_destroy (pad_image);
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
_cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern,
cairo_pattern_t *source_pattern,
cairo_surface_t *source_surface,
cairo_operator_t op,
int width,
int height,
@ -2947,46 +3039,29 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
{
cairo_int_status_t status;
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
cairo_surface_t *source = pattern->surface;
if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
if (source_surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
if (source_surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source_surface;
status = _cairo_ps_surface_emit_recording_subsurface (surface, sub->target, &sub->extents);
} else {
status = _cairo_ps_surface_emit_recording_surface (surface, source);
status = _cairo_ps_surface_emit_recording_surface (surface, source_surface);
}
} else {
if (pattern->base.extend != CAIRO_EXTEND_PAD) {
status = _cairo_ps_surface_emit_jpeg_image (surface, pattern->surface,
cairo_image_surface_t *image = (cairo_image_surface_t *) source_surface;
if (source_pattern->extend != CAIRO_EXTEND_PAD) {
status = _cairo_ps_surface_emit_jpeg_image (surface, source_surface,
width, height);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
status = _cairo_ps_surface_emit_image (surface, surface->image,
op, pattern->base.filter, stencil_mask);
status = _cairo_ps_surface_emit_image (surface, image,
op, source_pattern->filter, stencil_mask);
}
return status;
}
static void
_cairo_ps_surface_release_surface (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern)
{
if (surface->image != surface->acquired_image)
cairo_surface_destroy (&surface->image->base);
if (pattern->surface->type != CAIRO_SURFACE_TYPE_RECORDING) {
_cairo_surface_release_source_image (pattern->surface,
surface->acquired_image,
surface->image_extra);
}
surface->acquired_image = NULL;
surface->image = NULL;
}
static void
_path_fixed_init_rectangle (cairo_path_fixed_t *path,
@ -3018,40 +3093,60 @@ _path_fixed_init_rectangle (cairo_path_fixed_t *path,
}
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_bool_t stencil_mask)
_cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
cairo_pattern_t *pattern,
cairo_rectangle_int_t *extents,
cairo_operator_t op,
cairo_bool_t stencil_mask)
{
cairo_status_t status;
int width, height;
cairo_matrix_t cairo_p2d, ps_p2d;
cairo_path_fixed_t path;
int origin_x = 0;
int origin_y = 0;
double x_offset, y_offset;
cairo_surface_t *source;
cairo_image_surface_t *image = NULL;
void *image_extra;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
return status;
status = _cairo_ps_surface_acquire_surface (surface,
pattern,
extents,
&width, &height,
&origin_x, &origin_y);
status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface,
pattern,
extents,
&width, &height,
&x_offset, &y_offset,
&source,
&image_extra);
if (unlikely (status))
return status;
if (pattern->extend == CAIRO_EXTEND_PAD) {
cairo_image_surface_t *img;
assert (source->type == CAIRO_SURFACE_TYPE_IMAGE);
img = (cairo_image_surface_t *) source;
status = _cairo_ps_surface_create_padded_image_from_image (surface,
img,
&pattern->matrix,
extents,
&width, &height,
&x_offset, &y_offset,
&image);
if (unlikely (status))
goto release_source;
}
_path_fixed_init_rectangle (&path, extents);
status = _cairo_pdf_operators_clip (&surface->pdf_operators,
&path,
CAIRO_FILL_RULE_WINDING);
_cairo_path_fixed_fini (&path);
if (unlikely (status))
return status;
goto release_source;
cairo_p2d = pattern->base.matrix;
cairo_p2d = pattern->matrix;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
double x_scale = cairo_p2d.xx;
@ -3092,7 +3187,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, x_offset, y_offset);
cairo_matrix_translate (&ps_p2d, 0.0, height);
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
@ -3104,15 +3199,74 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
ps_p2d.x0, ps_p2d.y0);
}
status = _cairo_ps_surface_emit_surface (surface, pattern, op, width, height, stencil_mask);
_cairo_ps_surface_release_surface (surface, pattern);
status = _cairo_ps_surface_emit_surface (surface,
pattern,
image ? &image->base : source,
op,
width, height,
stencil_mask);
release_source:
if (image)
cairo_surface_destroy (&image->base);
_cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra);
return status;
}
static cairo_status_t
_cairo_ps_surface_paint_pattern (cairo_ps_surface_t *surface,
const cairo_pattern_t *source,
cairo_rectangle_int_t *extents,
cairo_operator_t op,
cairo_bool_t stencil_mask)
{
switch (source->type) {
case CAIRO_PATTERN_TYPE_SURFACE:
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return _cairo_ps_surface_paint_surface (surface,
(cairo_pattern_t *)source,
extents,
op,
stencil_mask);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
case CAIRO_PATTERN_TYPE_MESH:
case CAIRO_PATTERN_TYPE_SOLID:
default:
ASSERT_NOT_REACHED;
return CAIRO_STATUS_SUCCESS;
}
}
static cairo_bool_t
_can_paint_pattern (const cairo_pattern_t *pattern)
{
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
return FALSE;
case CAIRO_PATTERN_TYPE_SURFACE:
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return (pattern->extend == CAIRO_EXTEND_NONE ||
pattern->extend == CAIRO_EXTEND_PAD);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
case CAIRO_PATTERN_TYPE_MESH:
return FALSE;
default:
ASSERT_NOT_REACHED;
return FALSE;
}
}
static cairo_status_t
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern,
cairo_pattern_t *pattern,
cairo_rectangle_int_t *extents,
cairo_operator_t op)
{
@ -3122,23 +3276,45 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
double xstep, ystep;
cairo_matrix_t cairo_p2d, ps_p2d;
cairo_bool_t old_use_string_datasource;
int origin_x = 0;
int origin_y = 0;
double x_offset, y_offset;
cairo_surface_t *source;
cairo_image_surface_t *image = NULL;
void *image_extra;
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);
status = _cairo_ps_surface_acquire_surface (surface,
pattern,
extents,
&pattern_width, &pattern_height,
&origin_x, &origin_y);
status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface,
pattern,
extents,
&pattern_width, &pattern_height,
&x_offset, &y_offset,
&source,
&image_extra);
if (unlikely (status))
return status;
switch (pattern->base.extend) {
if (pattern->extend == CAIRO_EXTEND_PAD) {
cairo_image_surface_t *img;
assert (source->type == CAIRO_SURFACE_TYPE_IMAGE);
img = (cairo_image_surface_t *) source;
status = _cairo_ps_surface_create_padded_image_from_image (surface,
img,
&pattern->matrix,
extents,
&pattern_width, &pattern_height,
&x_offset, &y_offset,
&image);
if (unlikely (status))
goto release_source;
}
if (unlikely (status))
goto release_source;
switch (pattern->extend) {
case CAIRO_EXTEND_PAD:
case CAIRO_EXTEND_NONE:
{
@ -3156,7 +3332,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_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);
@ -3195,10 +3371,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
surface->content == CAIRO_CONTENT_COLOR ? 0 : 1,
xstep, ystep);
}
status = _cairo_ps_surface_emit_surface (surface, pattern, op,
status = _cairo_ps_surface_emit_surface (surface,
pattern,
image ? &image->base : source,
op,
pattern_width, pattern_height, FALSE);
if (unlikely (status))
return status;
goto release_source;
surface->use_string_datasource = old_use_string_datasource;
_cairo_output_stream_printf (surface->stream,
@ -3212,7 +3391,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
" /XStep %f /YStep %f\n",
xstep, ystep);
if (pattern->base.extend == CAIRO_EXTEND_REFLECT) {
if (pattern->extend == CAIRO_EXTEND_REFLECT) {
_cairo_output_stream_printf (surface->stream,
" /BBox [0 0 %d %d]\n"
" /PaintProc {\n"
@ -3243,7 +3422,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->stream,
">>\n");
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);
@ -3263,7 +3442,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->stream,
"makepattern setpattern\n");
return CAIRO_STATUS_SUCCESS;
release_source:
if (image)
cairo_surface_destroy (&image->base);
_cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra);
return status;
}
typedef struct _cairo_ps_color_stop {
@ -3735,8 +3920,9 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
break;
case CAIRO_PATTERN_TYPE_SURFACE:
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
status = _cairo_ps_surface_emit_surface_pattern (surface,
(cairo_surface_pattern_t *) pattern,
(cairo_pattern_t *)pattern,
extents,
op);
if (unlikely (status))
@ -3757,9 +3943,6 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
if (unlikely (status))
return status;
break;
case CAIRO_PATTERN_TYPE_RASTER_SOURCE: /* XXX */
break;
}
return CAIRO_STATUS_SUCCESS;
@ -3847,17 +4030,14 @@ _cairo_ps_surface_paint (void *abstract_surface,
if (unlikely (status))
goto cleanup_composite;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
(source->extend == CAIRO_EXTEND_NONE ||
source->extend == CAIRO_EXTEND_PAD))
{
if (_can_paint_pattern (source)) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (unlikely (status))
goto cleanup_composite;
_cairo_output_stream_printf (stream, "q\n");
status = _cairo_ps_surface_paint_surface (surface,
(cairo_surface_pattern_t *) source,
status = _cairo_ps_surface_paint_pattern (surface,
source,
&extents.bounded, op, FALSE);
if (unlikely (status))
goto cleanup_composite;
@ -3916,8 +4096,8 @@ _cairo_ps_surface_mask (void *abstract_surface,
goto cleanup_composite;
_cairo_output_stream_printf (stream, "q\n");
status = _cairo_ps_surface_paint_surface (surface,
(cairo_surface_pattern_t *) mask,
status = _cairo_ps_surface_paint_pattern (surface,
mask,
&extents.bounded, op, TRUE);
if (unlikely (status))
goto cleanup_composite;
@ -4059,10 +4239,7 @@ _cairo_ps_surface_fill (void *abstract_surface,
if (unlikely (status))
goto cleanup_composite;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
(source->extend == CAIRO_EXTEND_NONE ||
source->extend == CAIRO_EXTEND_PAD))
{
if (_can_paint_pattern (source)) {
_cairo_output_stream_printf (surface->stream, "q\n");
status = _cairo_pdf_operators_clip (&surface->pdf_operators,
@ -4071,8 +4248,8 @@ _cairo_ps_surface_fill (void *abstract_surface,
if (unlikely (status))
goto cleanup_composite;
status = _cairo_ps_surface_paint_surface (surface,
(cairo_surface_pattern_t *) source,
status = _cairo_ps_surface_paint_pattern (surface,
source,
&extents.bounded, op, FALSE);
if (unlikely (status))
goto cleanup_composite;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB