pdf: fix record-replay-extend test failures

This commit is contained in:
Adrian Johnson 2016-06-04 14:43:43 +09:30
parent e7b1cb0c53
commit 14fa88fd02
17 changed files with 81 additions and 50 deletions

View file

@ -146,6 +146,7 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
cairo_surface_t *source, *proxy;
cairo_matrix_t p2d, surface_transform;
cairo_status_t status, analysis_status;
cairo_bool_t surface_is_unbounded;
cairo_bool_t unused;
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
@ -175,8 +176,12 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
surface_transform = tmp->ctm;
status = cairo_matrix_invert (&surface_transform);
source = _cairo_surface_get_source (source, NULL);
surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT
|| pattern->extend == CAIRO_EXTEND_REFLECT);
status = _cairo_recording_surface_replay_and_create_regions (source,
&surface_transform, &tmp->base);
&surface_transform,
&tmp->base,
surface_is_unbounded);
if (!tmp->first_op)
_cairo_box_add_box (&surface->page_bbox, &tmp->page_bbox);

View file

@ -355,7 +355,7 @@ _paint_page (cairo_paginated_surface_t *surface)
surface->backend->set_paginated_mode (surface->target,
CAIRO_PAGINATED_MODE_ANALYZE);
status = _cairo_recording_surface_replay_and_create_regions (surface->recording_surface,
NULL, analysis);
NULL, analysis, FALSE);
if (status)
goto FAIL;

View file

@ -166,6 +166,7 @@ struct _cairo_pdf_surface {
double width;
double height;
cairo_rectangle_int_t surface_extents;
cairo_bool_t surface_bounded;
cairo_matrix_t cairo_to_pdf;
cairo_bool_t in_xobject;

View file

@ -380,6 +380,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
surface->surface_extents.y = 0;
surface->surface_extents.width = ceil (surface->width);
surface->surface_extents.height = ceil (surface->height);
surface->surface_bounded = TRUE;
_cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t));
_cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t));
@ -3028,6 +3029,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
{
double old_width, old_height;
cairo_rectangle_int_t old_surface_extents;
cairo_bool_t old_surface_bounded;
cairo_paginated_mode_t old_paginated_mode;
cairo_surface_clipper_t old_clipper;
cairo_bool_t old_in_xobject;
@ -3069,16 +3071,17 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
old_height = surface->height;
old_in_xobject = surface->in_xobject;
old_surface_extents = surface->surface_extents;
old_surface_bounded = surface->surface_bounded;
old_paginated_mode = surface->paginated_mode;
old_clipper = surface->clipper;
surface->surface_extents = *extents;
_cairo_surface_clipper_init (&surface->clipper,
_cairo_pdf_surface_clipper_intersect_clip_path);
_cairo_pdf_surface_set_size_internal (surface, width, height);
_cairo_pdf_operators_reset (&surface->pdf_operators);
surface->in_xobject = TRUE;
surface->surface_extents = *extents;
surface->surface_bounded = FALSE;
/* Patterns are emitted after fallback images. The paginated mode
* needs to be set to _RENDER while the recording surface is replayed
@ -3131,13 +3134,11 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
_cairo_surface_clipper_reset (&surface->clipper);
surface->clipper = old_clipper;
_cairo_pdf_surface_set_size_internal (surface,
old_width,
old_height);
_cairo_pdf_operators_reset (&surface->pdf_operators);
surface->in_xobject = old_in_xobject;
surface->paginated_mode = old_paginated_mode;
surface->surface_extents = old_surface_extents;
surface->surface_bounded = old_surface_bounded;
err:
cairo_surface_destroy (free_me);
@ -3165,16 +3166,16 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_extend_t extend = cairo_pattern_get_extend (pattern);
double xstep, ystep;
cairo_rectangle_int_t pattern_extents;
int pattern_width = 0; /* squelch bogus compiler warning */
int pattern_height = 0; /* squelch bogus compiler warning */
double x_offset;
double y_offset;
char draw_surface[200];
char draw_surface[50];
char draw_surface2[200];
cairo_box_double_t bbox;
cairo_matrix_t mat;
cairo_pdf_source_surface_entry_t *pdf_source;
cairo_rectangle_int_t op_extents;
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
if (pattern->extend == CAIRO_EXTEND_PAD) {
status = _cairo_pdf_surface_add_padded_image_surface (surface,
pattern,
@ -3202,8 +3203,6 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
return status;
pattern_extents = pdf_source->extents;
pattern_width = pdf_source->extents.width;
pattern_height = pdf_source->extents.height;
if (!pdf_source->bounded)
{
extend = CAIRO_EXTEND_NONE;
@ -3238,13 +3237,12 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
* required an answer that's large enough, we don't really
* care if it's not as tight as possible.*/
xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
pattern_width + pattern_height);
pattern_extents.width + pattern_extents.height);
}
break;
case CAIRO_EXTEND_REPEAT:
xstep = pattern_width;
ystep = pattern_height;
xstep = pattern_extents.width;
ystep = pattern_extents.height;
break;
case CAIRO_EXTEND_REFLECT:
@ -3303,11 +3301,11 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_matrix_translate (&pdf_p2d, x_offset, y_offset);
if (((cairo_surface_pattern_t *)pattern)->surface->type != CAIRO_SURFACE_TYPE_RECORDING)
{
cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
cairo_matrix_translate (&pdf_p2d, 0.0, pdf_source->extents.height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
}
_get_bbox_from_extents (pattern_height, &pattern_extents, &bbox);
_get_bbox_from_extents (pattern_extents.height, &pattern_extents, &bbox);
_cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
status = _cairo_pdf_surface_open_stream (surface,
&pdf_pattern->pattern_res,
@ -3330,35 +3328,54 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
if (unlikely (status))
return status;
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
if (((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
snprintf(draw_surface,
sizeof (draw_surface),
"/x%d Do\n",
"/x%d Do",
pdf_source->surface_res.id);
} else {
snprintf(draw_surface,
sizeof (draw_surface),
"q %d 0 0 %d 0 0 cm /x%d Do Q",
pattern_width,
pattern_height,
pdf_source->extents.width,
pdf_source->extents.height,
pdf_source->surface_res.id);
}
if (extend == CAIRO_EXTEND_REFLECT) {
_cairo_output_stream_printf (surface->output,
"q 0 0 %d %d re W n %s Q\n"
"q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n"
"q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n"
"q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n",
pattern_width, pattern_height,
draw_surface,
pattern_width*2, pattern_width, pattern_height,
draw_surface,
pattern_height*2, pattern_width, pattern_height,
draw_surface,
pattern_width*2, pattern_height*2, pattern_width, pattern_height,
draw_surface);
cairo_rectangle_int_t p_extents = pdf_source->extents;
snprintf(draw_surface2,
sizeof (draw_surface2),
"%d %d %d %d re W n %s",
p_extents.x, p_extents.y,
p_extents.width, p_extents.height,
draw_surface);
_cairo_output_stream_printf (surface->output, "q %s Q\n", draw_surface2);
cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
cairo_matrix_scale (&mat, -1, 1);
cairo_matrix_translate (&mat, -2*p_extents.width, 0);
cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
_cairo_output_stream_printf (surface->output, "q ");
_cairo_output_stream_print_matrix (surface->output, &mat);
_cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
cairo_matrix_scale (&mat, 1, -1);
cairo_matrix_translate (&mat, 0, -2*p_extents.height);
cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
_cairo_output_stream_printf (surface->output, "q ");
_cairo_output_stream_print_matrix (surface->output, &mat);
_cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y);
cairo_matrix_scale (&mat, -1, -1);
cairo_matrix_translate (&mat, -2*p_extents.width, -2*p_extents.height);
cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y);
_cairo_output_stream_printf (surface->output, "q ");
_cairo_output_stream_print_matrix (surface->output, &mat);
_cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2);
} else {
_cairo_output_stream_printf (surface->output,
" %s \n",
@ -4681,9 +4698,10 @@ _cairo_pdf_surface_get_extents (void *abstract_surface,
{
cairo_pdf_surface_t *surface = abstract_surface;
*rectangle = surface->surface_extents;
if (surface->surface_bounded)
*rectangle = surface->surface_extents;
return TRUE;
return surface->surface_bounded;
}
static void
@ -6280,9 +6298,11 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
cairo_bool_t old_in_xobject;
cairo_int_status_t status;
cairo_box_double_t bbox;
cairo_rectangle_int_t old_surface_extents;
old_width = surface->width;
old_height = surface->height;
old_surface_extents = surface->surface_extents;
old_in_xobject = surface->in_xobject;
surface->in_xobject = TRUE;
_cairo_pdf_surface_set_size_internal (surface,
@ -6352,6 +6372,7 @@ RESTORE_SIZE:
_cairo_pdf_surface_set_size_internal (surface,
old_width,
old_height);
surface->surface_extents = old_surface_extents;
_cairo_pdf_operators_reset (&surface->pdf_operators);
return status;

View file

@ -170,7 +170,8 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface,
cairo_private cairo_status_t
_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
const cairo_matrix_t *surface_transform,
cairo_surface_t *target);
cairo_surface_t *target,
cairo_bool_t surface_is_unbounded);
cairo_private cairo_status_t
_cairo_recording_surface_replay_region (cairo_surface_t *surface,
const cairo_rectangle_int_t *surface_extents,

View file

@ -725,10 +725,6 @@ _cairo_recording_surface_paint (void *abstract_surface,
(surface->base.is_clear || _cairo_pattern_is_opaque_solid (source)))))
{
_cairo_recording_surface_reset (surface);
if (is_identity_recording_pattern (source)) {
cairo_surface_t *src = ((cairo_surface_pattern_t *)source)->surface;
return _cairo_recording_surface_replay (src, &surface->base);
}
}
status = _cairo_composite_rectangles_init_for_paint (&composite,
@ -1676,6 +1672,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
const cairo_matrix_t *surface_transform,
cairo_surface_t *target,
const cairo_clip_t *target_clip,
cairo_bool_t surface_is_unbounded,
cairo_recording_replay_type_t type,
cairo_recording_region_type_t region)
{
@ -1708,7 +1705,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
if (surface_extents)
_cairo_surface_wrapper_intersect_extents (&wrapper, surface_extents);
r = &_cairo_unbounded_rectangle;
if (! surface->unbounded) {
if (! surface->unbounded && !surface_is_unbounded) {
_cairo_surface_wrapper_intersect_extents (&wrapper, &surface->extents);
r = &surface->extents;
}
@ -1716,7 +1713,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
_cairo_surface_wrapper_set_clip (&wrapper, target_clip);
/* Compute the extents of the target clip in recorded device space */
if (! _cairo_surface_wrapper_get_target_extents (&wrapper, &extents))
if (! _cairo_surface_wrapper_get_target_extents (&wrapper, surface_is_unbounded, &extents))
goto done;
surface->has_bilevel_alpha = TRUE;
@ -2001,7 +1998,7 @@ _cairo_recording_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
{
return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL,
target, NULL,
target, NULL, FALSE,
CAIRO_RECORDING_REPLAY,
CAIRO_RECORDING_REGION_ALL);
}
@ -2013,7 +2010,7 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface,
const cairo_clip_t *target_clip)
{
return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform,
target, target_clip,
target, target_clip, FALSE,
CAIRO_RECORDING_REPLAY,
CAIRO_RECORDING_REGION_ALL);
}
@ -2027,10 +2024,12 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface,
cairo_status_t
_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
const cairo_matrix_t *surface_transform,
cairo_surface_t *target)
cairo_surface_t *target,
cairo_bool_t surface_is_unbounded)
{
return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform,
target, NULL,
surface_is_unbounded,
CAIRO_RECORDING_CREATE_REGIONS,
CAIRO_RECORDING_REGION_ALL);
}
@ -2043,7 +2042,7 @@ _cairo_recording_surface_replay_region (cairo_surface_t *surface,
{
return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface,
surface_extents, NULL,
target, NULL,
target, NULL, FALSE,
CAIRO_RECORDING_REPLAY,
region);
}

View file

@ -186,6 +186,7 @@ _cairo_surface_wrapper_is_active (cairo_surface_wrapper_t *wrapper)
cairo_private cairo_bool_t
_cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper,
cairo_bool_t surface_is_unbounded,
cairo_rectangle_int_t *extents);
CAIRO_END_DECLS

View file

@ -625,12 +625,15 @@ _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper)
cairo_bool_t
_cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper,
cairo_bool_t surface_is_unbounded,
cairo_rectangle_int_t *extents)
{
cairo_rectangle_int_t clip;
cairo_bool_t has_clip;
cairo_bool_t has_clip = FALSE;
if (!surface_is_unbounded)
has_clip = _cairo_surface_get_extents (wrapper->target, &clip);
has_clip = _cairo_surface_get_extents (wrapper->target, &clip);
if (wrapper->clip) {
if (has_clip) {
if (! _cairo_rectangle_intersect (&clip,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB