diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2016-06-04 14:43:43 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2016-06-05 20:43:36 +0930 |
commit | 1c5ec6e3806587eff1fbb640c63838ef2768c2cb (patch) | |
tree | 4c980b5835f88fb8c2dc160ae087a780c6caa7a5 | |
parent | a14d319e4385033d726861dcd448154d393ffc53 (diff) |
Fix PS record-neg-extents test failure
-rw-r--r-- | src/cairo-analysis-surface.c | 111 | ||||
-rw-r--r-- | src/cairo-debug.c | 8 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 40 | ||||
-rw-r--r-- | src/cairo-ps-surface-private.h | 5 | ||||
-rw-r--r-- | src/cairo-ps-surface.c | 538 | ||||
-rw-r--r-- | src/cairo-recording-surface.c | 5 | ||||
-rw-r--r-- | src/cairoint.h | 3 |
7 files changed, 409 insertions, 301 deletions
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index 9a922ec5c..80f92d76e 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -139,12 +139,13 @@ detach_proxy (cairo_surface_t *proxy) static cairo_int_status_t _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, - const cairo_pattern_t *pattern) + const cairo_pattern_t *pattern, + cairo_rectangle_int_t *extents) { const cairo_surface_pattern_t *surface_pattern; cairo_analysis_surface_t *tmp; cairo_surface_t *source, *proxy; - cairo_matrix_t p2d, surface_transform; + cairo_matrix_t p2d; cairo_status_t status, analysis_status; cairo_bool_t surface_is_unbounded; cairo_bool_t unused; @@ -169,23 +170,15 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, p2d = pattern->matrix; status = cairo_matrix_invert (&p2d); assert (status == CAIRO_STATUS_SUCCESS); + _cairo_analysis_surface_set_ctm (&tmp->base, &p2d); - cairo_matrix_multiply (&tmp->ctm, &p2d, &surface->ctm); - tmp->has_ctm = ! _cairo_matrix_is_identity (&tmp->ctm); - - 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, + &pattern->matrix, &tmp->base, surface_is_unbounded); - - if (!tmp->first_op) - _cairo_box_add_box (&surface->page_bbox, &tmp->page_bbox); - if (tmp->has_supported) { surface->has_supported = TRUE; unused = cairo_region_union (&surface->supported_region, &tmp->supported_region); @@ -198,6 +191,18 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS; + if (pattern->extend != CAIRO_EXTEND_NONE) { + _cairo_unbounded_rectangle_init (extents); + } else if (source->content & CAIRO_CONTENT_ALPHA) { + status = cairo_matrix_invert (&tmp->ctm); + _cairo_matrix_transform_bounding_box_fixed (&tmp->ctm, + &tmp->page_bbox, NULL); + _cairo_box_round_to_rectangle (&tmp->page_bbox, extents); + } else { + /* black background fills entire extents */ + _cairo_surface_get_extents (source, extents); + } + detach_proxy (proxy); cairo_surface_destroy (&tmp->base); @@ -378,7 +383,7 @@ static cairo_int_status_t _cairo_analysis_surface_paint (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -394,12 +399,14 @@ _cairo_analysis_surface_paint (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } return _add_operation (surface, &extents, backend_status); } @@ -409,7 +416,7 @@ _cairo_analysis_surface_mask (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -425,18 +432,24 @@ _cairo_analysis_surface_mask (void *abstract_surface, return backend_status; } + _cairo_analysis_surface_operation_extents (surface, + op, source, clip, + &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS; cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS; + cairo_rectangle_int_t rec_extents; if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t *src_surface = ((cairo_surface_pattern_t *)source)->surface; src_surface = _cairo_surface_get_source (src_surface, NULL); if (_cairo_surface_is_recording (src_surface)) { backend_source_status = - _analyze_recording_surface_pattern (surface, source); + _analyze_recording_surface_pattern (surface, source, &rec_extents); if (_cairo_int_status_is_error (backend_source_status)) return backend_source_status; + + _cairo_rectangle_intersect (&extents, &rec_extents); } } @@ -445,9 +458,11 @@ _cairo_analysis_surface_mask (void *abstract_surface, mask_surface = _cairo_surface_get_source (mask_surface, NULL); if (_cairo_surface_is_recording (mask_surface)) { backend_mask_status = - _analyze_recording_surface_pattern (surface, mask); + _analyze_recording_surface_pattern (surface, mask, &rec_extents); if (_cairo_int_status_is_error (backend_mask_status)) return backend_mask_status; + + _cairo_rectangle_intersect (&extents, &rec_extents); } } @@ -456,10 +471,6 @@ _cairo_analysis_surface_mask (void *abstract_surface, backend_mask_status); } - _cairo_analysis_surface_operation_extents (surface, - op, source, clip, - &extents); - if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; @@ -471,16 +482,16 @@ _cairo_analysis_surface_mask (void *abstract_surface, } static cairo_int_status_t -_cairo_analysis_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) +_cairo_analysis_surface_stroke (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -499,12 +510,14 @@ _cairo_analysis_surface_stroke (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; @@ -531,7 +544,7 @@ _cairo_analysis_surface_fill (void *abstract_surface, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -549,12 +562,14 @@ _cairo_analysis_surface_fill (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; @@ -611,12 +626,14 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_scaled_font_glyph_device_extents (scaled_font, @@ -687,12 +704,14 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_scaled_font_glyph_device_extents (scaled_font, diff --git a/src/cairo-debug.c b/src/cairo-debug.c index dbc9e2f2c..1f32b19b3 100644 --- a/src/cairo-debug.c +++ b/src/cairo-debug.c @@ -311,3 +311,11 @@ _cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix) matrix->xy, matrix->yy, matrix->x0, matrix->y0); } + +void +_cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect) +{ + fprintf (file, "x: %d y: %d width: %d height: %d\n", + rect->x, rect->y, + rect->width, rect->height); +} diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 1dd3c551a..6ac4f87e8 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -417,7 +417,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, } surface->pdf_version = CAIRO_PDF_VERSION_1_5; - surface->compress_content = TRUE; + surface->compress_content = 0; surface->pdf_stream.active = FALSE; surface->pdf_stream.old_output = NULL; surface->group_stream.active = FALSE; @@ -1320,20 +1320,20 @@ _get_source_surface_extents (cairo_surface_t *source, /** * _cairo_pdf_surface_add_source_surface: - * @surface: the pdf surface - * @source_surface: A #cairo_surface_t to use as the source surface - * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source - * @op: the operator used to composite this source - * @filter: filter type of the source pattern - * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask - * @smask: if true, only the alpha channel will be written (images only) - * @smask_res: if not NULL, the image written will specify this resource as the smask for - the image (images only) - * @extents: extents of the operation that is using this source - * @pdf_source: return pdf_source_surface entry in hash table - * @x_offset: if not NULL return x offset of surface - * @y_offset: if not NULL return y offset of surface - * @source_extents: if not NULL return operation extents in source space + * @surface: [in] the pdf surface + * @source_surface: [in] A #cairo_surface_t to use as the source surface + * @source_pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source + * @op: [in] the operator used to composite this source + * @filter: [in] filter type of the source pattern + * @stencil_mask: [in] if true, the surface will be written to the PDF as an /ImageMask + * @smask: [in] if true, only the alpha channel will be written (images only) + * @extents: [in] extents of the operation that is using this source + * @smask_res: [out] if not NULL, the image written will specify this resource as the smask for + * the image (images only) + * @pdf_source: [out] return pdf_source_surface entry in hash table + * @x_offset: [out] if not NULL return x offset of surface + * @y_offset: [out] if not NULL return y offset of surface + * @source_extents: [out] if not NULL return operation extents in source space * * Add surface or raster_source pattern to list of surfaces to be * written to the PDF file when the current page is finished. Returns @@ -1353,8 +1353,8 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, cairo_filter_t filter, cairo_bool_t stencil_mask, cairo_bool_t smask, - cairo_pdf_resource_t *smask_res, const cairo_rectangle_int_t *extents, + cairo_pdf_resource_t *smask_res, cairo_pdf_source_surface_entry_t **pdf_source, double *x_offset, double *y_offset, @@ -2291,8 +2291,8 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa source->filter, FALSE, /* stencil mask */ FALSE, /* smask */ - NULL, /* smask_res */ extents, + NULL, /* smask_res */ pdf_source, x_offset, y_offset, @@ -3192,8 +3192,8 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, pattern->filter, FALSE, /* stencil mask */ FALSE, /* smask */ - NULL, /* smask_res */ &pdf_pattern->extents, + NULL, /* smask_res */ &pdf_source, &x_offset, &y_offset, @@ -4362,8 +4362,8 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, source->filter, stencil_mask, FALSE, /* smask */ - smask_res, extents, + smask_res, &pdf_source, &x_offset, &y_offset, @@ -6904,8 +6904,8 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, source->filter, FALSE, /* stencil mask */ TRUE, /* smask */ - NULL, /* smask_res */ extents, + NULL, /* smask_res */ &pdf_source, NULL, NULL, diff --git a/src/cairo-ps-surface-private.h b/src/cairo-ps-surface-private.h index 1d5d27d49..7cd275d73 100644 --- a/src/cairo-ps-surface-private.h +++ b/src/cairo-ps-surface-private.h @@ -66,8 +66,9 @@ typedef struct cairo_ps_surface { cairo_content_t content; double width; double height; - cairo_rectangle_int_t page_bbox; - int bbox_x1, bbox_y1, bbox_x2, bbox_y2; + cairo_point_int_t document_bbox_p1, document_bbox_p2; /* in PS coordinates */ + cairo_rectangle_int_t surface_extents; + cairo_bool_t surface_bounded; cairo_matrix_t cairo_to_ps; cairo_bool_t use_string_datasource; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index df5f3555c..7a098f602 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -84,7 +84,7 @@ #include <zlib.h> #include <errno.h> -#define DEBUG_PS 0 +/* #define DEBUG_PS 1 */ #if DEBUG_PS #define DEBUG_FALLBACK(s) \ @@ -259,10 +259,10 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) if (!has_bbox) { _cairo_output_stream_printf (surface->final_stream, "%%%%BoundingBox: %d %d %d %d\n", - surface->bbox_x1, - surface->bbox_y1, - surface->bbox_x2, - surface->bbox_y2); + surface->document_bbox_p1.x, + surface->document_bbox_p1.y, + surface->document_bbox_p2.x, + surface->document_bbox_p2.y); } _cairo_output_stream_printf (surface->final_stream, @@ -879,11 +879,11 @@ _path_covers_bbox (cairo_ps_surface_t *surface, _cairo_box_round_to_rectangle (&box, &rect); /* skip trivial whole-page clips */ - if (_cairo_rectangle_intersect (&rect, &surface->page_bbox)) { - if (rect.x == surface->page_bbox.x && - rect.width == surface->page_bbox.width && - rect.y == surface->page_bbox.y && - rect.height == surface->page_bbox.height) + if (_cairo_rectangle_intersect (&rect, &surface->surface_extents)) { + if (rect.x == surface->surface_extents.x && + rect.width == surface->surface_extents.width && + rect.y == surface->surface_extents.y && + rect.height == surface->surface_extents.height) { return TRUE; } @@ -1054,16 +1054,20 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->width = width; surface->height = height; cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, 1, 0, 0); + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); + surface->surface_bounded = TRUE; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; surface->force_fallbacks = FALSE; surface->content = CAIRO_CONTENT_COLOR_ALPHA; surface->use_string_datasource = FALSE; surface->current_pattern_is_solid_color = FALSE; - - surface->page_bbox.x = 0; - surface->page_bbox.y = 0; - surface->page_bbox.width = width; - surface->page_bbox.height = height; + surface->document_bbox_p1.x = 0; + surface->document_bbox_p1.y = 0; + surface->document_bbox_p2.x = 0; + surface->document_bbox_p2.y = 0; _cairo_surface_clipper_init (&surface->clipper, _cairo_ps_surface_clipper_intersect_clip_path); @@ -1402,6 +1406,10 @@ cairo_ps_surface_set_size (cairo_surface_t *surface, ps_surface->width = width_in_points; ps_surface->height = height_in_points; cairo_matrix_init (&ps_surface->cairo_to_ps, 1, 0, 0, 1, 0, 0); + ps_surface->surface_extents.x = 0; + ps_surface->surface_extents.y = 0; + ps_surface->surface_extents.width = ceil (ps_surface->width); + ps_surface->surface_extents.height = ceil (ps_surface->height); _cairo_pdf_operators_set_cairo_to_pdf_matrix (&ps_surface->pdf_operators, &ps_surface->cairo_to_ps); status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface, @@ -1713,15 +1721,16 @@ color_is_gray (double red, double green, double blue) /** * _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 + * @surface: [in] the ps surface + * @pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source + * @extents: [in] extents of the operation that is using this source + * @src_surface_extents: [out] return source surface extents + * @src_surface_bounded: [out] return TRUE if source surface is bounded + * @src_op_extents: [out] return operation extents in source space + * @source_surface: [out] returns surface of type image surface or recording surface + * @x_offset: [out] return x offset of surface + * @y_offset: [out] return y offset of surface + * @image_extra: [out] returns image extra for image type surface * * Acquire source surface or raster source pattern. **/ @@ -1729,20 +1738,24 @@ 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, + cairo_rectangle_int_t *src_surface_extents, + cairo_bool_t *src_surface_bounded, + cairo_rectangle_int_t *src_op_extents, + cairo_surface_t **source_surface, double *x_offset, double *y_offset, - cairo_surface_t **source_surface, void **image_extra) { cairo_status_t status; cairo_image_surface_t *image; - *x_offset = *y_offset = 0; + *x_offset = 0; + *y_offset = 0; *image_extra = NULL; switch (pattern->type) { case CAIRO_PATTERN_TYPE_SURFACE: { + cairo_box_t bbox; + //cairo_rectangle_int_t rect; cairo_surface_t *surf = ((cairo_surface_pattern_t *) pattern)->surface; if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) { @@ -1753,27 +1766,48 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t 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; + *src_surface_extents = sub->extents; + *src_surface_bounded = TRUE; + *x_offset = -sub->extents.x; + *y_offset = -sub->extents.y; } else { - cairo_recording_surface_t *recording_surface; - cairo_box_t bbox; - cairo_rectangle_int_t extents; + //cairo_recording_surface_t *recording_surface; - recording_surface = (cairo_recording_surface_t *) surf; + *src_surface_bounded = _cairo_surface_get_extents (surf, src_surface_extents); +/* recording_surface = (cairo_recording_surface_t *) surf; status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL); if (unlikely (status)) { cairo_surface_destroy (*image_extra); return status; } - _cairo_box_round_to_rectangle (&bbox, &extents); - *width = extents.width; - *height = extents.height; + _cairo_box_round_to_rectangle (&bbox, src_extents); + *x_offset = src_extents->x; + *y_offset = src_extents->y; */ } *source_surface = surf; +//* if (pattern->extend == CAIRO_EXTEND_NONE || pattern->extend == CAIRO_EXTEND_PAD) { + /* Clip the source extents to the operation extents (transformed to pattern space) */ +/* cairo_rectangle_int_t old_src_extents = *src_extents; + + _cairo_box_from_rectangle (&bbox, extents); + _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &bbox, NULL); + _cairo_box_round_to_rectangle (&bbox, &rect); + if (surf->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { + rect.x += src_extents->x; + rect.y += src_extents->y; + } + _cairo_rectangle_intersect (src_extents, &rect); + *x_offset += (src_extents->x - old_src_extents.x); + *y_offset += (src_extents->y - old_src_extents.y); + }*/ + + _cairo_box_from_rectangle (&bbox, extents); + _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &bbox, NULL); + _cairo_box_round_to_rectangle (&bbox, src_op_extents); + return CAIRO_STATUS_SUCCESS; } else { status = _cairo_surface_acquire_source_image (surf, &image, image_extra); @@ -1781,7 +1815,7 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t cairo_surface_destroy (*image_extra); return status; } - } + } } break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: { @@ -1810,8 +1844,11 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t break; } - *width = image->width; - *height = image->height; + src_surface_extents->x = 0; + src_surface_extents->y = 0; + src_surface_extents->width = image->width; + src_surface_extents->height = image->height; + *src_surface_bounded = TRUE; *source_surface = &image->base; return CAIRO_STATUS_SUCCESS; } @@ -1819,7 +1856,7 @@ _cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t static void _cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern, - cairo_surface_t *source, + cairo_surface_t *source_surface, void *image_extra) { switch (pattern->type) { @@ -1828,13 +1865,13 @@ _cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t if (surf_pat->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { cairo_surface_destroy (image_extra); } else { - cairo_image_surface_t *image = (cairo_image_surface_t *) source; + cairo_image_surface_t *image = (cairo_image_surface_t *) source_surface; _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); + _cairo_raster_source_pattern_release (pattern, source_surface); break; case CAIRO_PATTERN_TYPE_SOLID: @@ -1853,11 +1890,8 @@ _cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t * @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 or NULL if padding not required to fill @extents + * @image_extents: returns extents of padded image. These extents in are in source image space. * * Creates a padded image if the source image does not fill the extents. **/ @@ -1866,11 +1900,8 @@ _cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t * 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_image_surface_t **image, + cairo_rectangle_int_t *image_extents) { cairo_box_t box; cairo_rectangle_int_t rect; @@ -1909,10 +1940,10 @@ _cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t * 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; + image_extents->x = rect.x; + image_extents->y = rect.y; + image_extents->width = rect.width; + image_extents->height = rect.height; } else { *image = NULL; status = CAIRO_STATUS_SUCCESS; @@ -1926,27 +1957,31 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t const cairo_pattern_t *pattern, const cairo_rectangle_int_t *extents) { - int width, height; + cairo_rectangle_int_t src_surface_extents; + cairo_bool_t src_surface_bounded; + cairo_rectangle_int_t src_op_extents; + cairo_surface_t *source_surface; double x_offset, y_offset; - cairo_surface_t *source; - cairo_image_surface_t *image; void *image_extra; - cairo_int_status_t status; + cairo_image_surface_t *image; + cairo_int_status_t status; cairo_image_transparency_t transparency; status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, - &width, - &height, + &src_surface_extents, + &src_surface_bounded, + &src_op_extents, + &source_surface, &x_offset, &y_offset, - &source, &image_extra); if (unlikely (status)) return status; - image = (cairo_image_surface_t *) source; + assert (_cairo_surface_is_image (source_surface)); + image = (cairo_image_surface_t *) source_surface; if (image->base.status) return image->base.status; @@ -1973,7 +2008,7 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t ASSERT_NOT_REACHED; } - _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra); + _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source_surface, image_extra); return status; } @@ -2923,61 +2958,39 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, static cairo_status_t _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, cairo_surface_t *recording_surface, - cairo_bool_t subsurface, - const cairo_rectangle_int_t *extents) + const cairo_rectangle_int_t *recording_extents, + cairo_bool_t subsurface) { double old_width, old_height; + cairo_rectangle_int_t old_surface_extents; + cairo_bool_t old_surface_bounded; cairo_matrix_t old_cairo_to_ps; cairo_content_t old_content; - cairo_rectangle_int_t old_page_bbox; cairo_surface_clipper_t old_clipper; - cairo_box_t bbox; cairo_int_status_t status; old_content = surface->content; old_width = surface->width; old_height = surface->height; - old_page_bbox = surface->page_bbox; + old_surface_extents = surface->surface_extents; + old_surface_bounded = surface->surface_bounded; old_cairo_to_ps = surface->cairo_to_ps; old_clipper = surface->clipper; _cairo_surface_clipper_init (&surface->clipper, _cairo_ps_surface_clipper_intersect_clip_path); - if (subsurface) { - surface->page_bbox.x = surface->page_bbox.y = 0; - surface->page_bbox.width = surface->width = extents->width; - surface->page_bbox.height = surface->height = extents->height; - -#if DEBUG_PS - _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_emit_recording_subsurface" - " (%d, %d), (%d, %d)\n", - extents->x, extents->y, - extents->width, extents->height); -#endif - - } else { - status = - _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, - &bbox, - NULL); - if (unlikely (status)) - return status; - - surface->width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x); - surface->height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y); - _cairo_box_round_to_rectangle (&bbox, &surface->page_bbox); - #if DEBUG_PS _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_emit_recording_surface (%f, %f), (%f, %f)\n", - _cairo_fixed_to_double (bbox.p1.x), - _cairo_fixed_to_double (bbox.p1.y), - _cairo_fixed_to_double (bbox.p2.x), - _cairo_fixed_to_double (bbox.p2.y)); + "%% _cairo_ps_surface_emit_recording_surface" + " x: %d, y: %d, w: %d, h: %d subsurface: %d\n", + recording_extents->x, recording_extents->y, + recording_extents->width, recording_extents->height, + subsurface); #endif - } + surface->width = recording_extents->width; + surface->height = recording_extents->height; + surface->surface_extents = *recording_extents; surface->current_pattern_is_solid_color = FALSE; _cairo_pdf_operators_reset (&surface->pdf_operators); cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, 1, 0, 0); @@ -2989,14 +3002,14 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, surface->content = CAIRO_CONTENT_COLOR; _cairo_output_stream_printf (surface->stream, " 0 g %d %d %d %d rectfill\n", - surface->page_bbox.x, - surface->page_bbox.y, - surface->page_bbox.width, - surface->page_bbox.height); + recording_extents->x, + recording_extents->y, + recording_extents->width, + recording_extents->height); } status = _cairo_recording_surface_replay_region (recording_surface, - subsurface ? extents : NULL, + subsurface ? recording_extents : NULL, &surface->base, CAIRO_RECORDING_REGION_NATIVE); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); @@ -3014,7 +3027,8 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, surface->content = old_content; surface->width = old_width; surface->height = old_height; - surface->page_bbox = old_page_bbox; + surface->surface_extents = old_surface_extents; + surface->surface_bounded = old_surface_bounded; surface->current_pattern_is_solid_color = FALSE; _cairo_pdf_operators_reset (&surface->pdf_operators); surface->cairo_to_ps = old_cairo_to_ps; @@ -3068,22 +3082,23 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface, } static cairo_status_t -_cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, - cairo_pattern_t *source_pattern, - cairo_surface_t *source_surface, - cairo_operator_t op, - int width, - int height, - cairo_bool_t stencil_mask) +_cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, + const cairo_pattern_t *source_pattern, + cairo_surface_t *source_surface, + cairo_operator_t op, + const cairo_rectangle_int_t *src_surface_extents, + cairo_bool_t src_surface_bounded, + const cairo_rectangle_int_t *src_op_extents, + cairo_bool_t stencil_mask) { cairo_int_status_t status; if (source_pattern->type == CAIRO_PATTERN_TYPE_SURFACE && - source_pattern->extend != CAIRO_EXTEND_PAD) + source_pattern->extend != CAIRO_EXTEND_PAD && src_surface_bounded) { cairo_surface_t *surf = ((cairo_surface_pattern_t *) source_pattern)->surface; - status = _cairo_ps_surface_emit_jpeg_image (surface, surf, width, height); + status = _cairo_ps_surface_emit_jpeg_image (surface, surf, src_surface_extents->width, src_surface_extents->height); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; } @@ -3091,9 +3106,9 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, 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_surface (surface, sub->target, TRUE, &sub->extents); + status = _cairo_ps_surface_emit_recording_surface (surface, sub->target, &sub->extents, TRUE); } else { - status = _cairo_ps_surface_emit_recording_surface (surface, source_surface, FALSE, NULL); + status = _cairo_ps_surface_emit_recording_surface (surface, source_surface, src_op_extents, FALSE); } } else { cairo_image_surface_t *image = (cairo_image_surface_t *) source_surface; @@ -3137,19 +3152,21 @@ _path_fixed_init_rectangle (cairo_path_fixed_t *path, static cairo_status_t _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, - cairo_pattern_t *pattern, + const cairo_pattern_t *pattern, cairo_rectangle_int_t *extents, cairo_operator_t op, cairo_bool_t stencil_mask) { + cairo_rectangle_int_t src_surface_extents; + cairo_bool_t src_surface_bounded; + cairo_rectangle_int_t src_op_extents; + cairo_surface_t *source_surface; + double x_offset, y_offset; + void *image_extra; cairo_status_t status; - int width, height; cairo_matrix_t cairo_p2d, ps_p2d; cairo_path_fixed_t path; - 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)) @@ -3158,9 +3175,12 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, - &width, &height, - &x_offset, &y_offset, - &source, + &src_surface_extents, + &src_surface_bounded, + &src_op_extents, + &source_surface, + &x_offset, + &y_offset, &image_extra); if (unlikely (status)) return status; @@ -3170,16 +3190,18 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, ((cairo_surface_pattern_t *)pattern)->surface->type == CAIRO_SURFACE_TYPE_IMAGE) { cairo_image_surface_t *img; - img = (cairo_image_surface_t *) source; + img = (cairo_image_surface_t *) source_surface; status = _cairo_ps_surface_create_padded_image_from_image (surface, img, &pattern->matrix, extents, - &width, &height, - &x_offset, &y_offset, - &image); + &image, + &src_surface_extents); if (unlikely (status)) goto release_source; + + x_offset = src_surface_extents.x; + y_offset = src_surface_extents.y; } _path_fixed_init_rectangle (&path, extents); @@ -3200,8 +3222,8 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, "%% Fallback Image: x=%f y=%f w=%d h=%d ", -cairo_p2d.x0/x_scale, -cairo_p2d.y0/y_scale, - (int)(width/x_scale), - (int)(height/y_scale)); + (int)(src_surface_extents.width/x_scale), + (int)(src_surface_extents.height/y_scale)); if (x_scale == y_scale) { _cairo_output_stream_printf (surface->stream, "res=%fppi ", @@ -3214,14 +3236,16 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, "size=%ld\n", - (long)width*height*3); + (long)src_surface_extents.width * src_surface_extents.height * 3); } else { if (op == CAIRO_OPERATOR_SOURCE) { _cairo_output_stream_printf (surface->stream, - "%d g 0 0 %f %f rectfill\n", + "%d g %d %d %d %d rectfill\n", surface->content == CAIRO_CONTENT_COLOR ? 0 : 1, - surface->width, - surface->height); + surface->surface_extents.x, + surface->surface_extents.y, + surface->surface_extents.width, + surface->surface_extents.height); } } @@ -3235,7 +3259,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, if (!(pattern->type == CAIRO_PATTERN_TYPE_SURFACE && ((cairo_surface_pattern_t *)pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)) { - cairo_matrix_translate (&ps_p2d, 0.0, height); + cairo_matrix_translate (&ps_p2d, 0.0, src_surface_extents.height); cairo_matrix_scale (&ps_p2d, 1.0, -1.0); } @@ -3247,16 +3271,18 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, status = _cairo_ps_surface_emit_surface (surface, pattern, - image ? &image->base : source, + image ? &image->base : source_surface, op, - width, height, + &src_surface_extents, + image ? TRUE : src_surface_bounded, + &src_op_extents, stencil_mask); release_source: if (image) cairo_surface_destroy (&image->base); - _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra); + _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source_surface, image_extra); return status; } @@ -3268,15 +3294,17 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, cairo_operator_t op) { cairo_status_t status; - int pattern_width = 0; /* squelch bogus compiler warning */ - int pattern_height = 0; /* squelch bogus compiler warning */ double xstep, ystep; + cairo_rectangle_int_t pattern_extents; + cairo_bool_t bounded; cairo_matrix_t cairo_p2d, ps_p2d; cairo_bool_t old_use_string_datasource; double x_offset, y_offset; - cairo_surface_t *source; + cairo_surface_t *source_surface; cairo_image_surface_t *image = NULL; void *image_extra; + cairo_rectangle_int_t src_op_extents; + cairo_extend_t extend = cairo_pattern_get_extend (pattern); cairo_p2d = pattern->matrix; status = cairo_matrix_invert (&cairo_p2d); @@ -3286,32 +3314,39 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, - &pattern_width, &pattern_height, + &pattern_extents, + &bounded, + &src_op_extents, + &source_surface, &x_offset, &y_offset, - &source, &image_extra); if (unlikely (status)) return status; - if (pattern->extend == CAIRO_EXTEND_PAD) { + if (extend == CAIRO_EXTEND_PAD) { cairo_image_surface_t *img; - assert (source->type == CAIRO_SURFACE_TYPE_IMAGE); - img = (cairo_image_surface_t *) source; + assert (source_surface->type == CAIRO_SURFACE_TYPE_IMAGE); + img = (cairo_image_surface_t *) source_surface; status = _cairo_ps_surface_create_padded_image_from_image (surface, img, &pattern->matrix, extents, - &pattern_width, &pattern_height, - &x_offset, &y_offset, - &image); + &image, + &pattern_extents); if (unlikely (status)) goto release_source; } if (unlikely (status)) goto release_source; - switch (pattern->extend) { + if (!bounded) + { + extend = CAIRO_EXTEND_NONE; + _cairo_rectangle_intersect (&pattern_extents, &src_op_extents); + } + + switch (extend) { case CAIRO_EXTEND_PAD: case CAIRO_EXTEND_NONE: { @@ -3328,7 +3363,8 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, * repeat visibly. */ double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; + double x2 = surface->surface_extents.width; + double y2 = surface->surface_extents.height; _cairo_matrix_transform_bounding_box (&pattern->matrix, &x1, &y1, &x2, &y2, NULL); @@ -3338,16 +3374,16 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_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: - xstep = pattern_width*2; - ystep = pattern_height*2; + xstep = pattern_extents.width*2; + ystep = pattern_extents.height*2; break; /* All the rest (if any) should have been analyzed away, so these * cases should be unreachable. */ @@ -3358,27 +3394,38 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, - "/CairoPattern {\n"); + "/CairoPattern {\n" + "q %d %d %d %d rectclip\n", + pattern_extents.x, pattern_extents.y, + pattern_extents.width, pattern_extents.height); old_use_string_datasource = surface->use_string_datasource; surface->use_string_datasource = TRUE; if (op == CAIRO_OPERATOR_SOURCE) { _cairo_output_stream_printf (surface->stream, - "%d g 0 0 %f %f rectfill\n", + "%d g %d %d %f %f rectfill\n", surface->content == CAIRO_CONTENT_COLOR ? 0 : 1, + pattern_extents.x, pattern_extents.y, xstep, ystep); } + + if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) + src_op_extents = pattern_extents; + status = _cairo_ps_surface_emit_surface (surface, pattern, - image ? &image->base : source, + image ? &image->base : source_surface, op, - pattern_width, pattern_height, FALSE); + &pattern_extents, + bounded, + &src_op_extents, + FALSE); if (unlikely (status)) goto release_source; surface->use_string_datasource = old_use_string_datasource; _cairo_output_stream_printf (surface->stream, - "} bind def\n"); + " Q } bind def\n"); _cairo_output_stream_printf (surface->stream, "<< /PatternType 1\n" @@ -3388,20 +3435,43 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, " /XStep %f /YStep %f\n", xstep, ystep); - if (pattern->extend == CAIRO_EXTEND_REFLECT) { + if (extend == CAIRO_EXTEND_REFLECT) { + cairo_matrix_t mat; + _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %d %d]\n" + " /BBox [%d %d %d %d]\n" " /PaintProc {\n" - " pop CairoPattern\n" - " [-1 0 0 1 %d 0] concat CairoPattern\n" - " [ 1 0 0 -1 0 %d] concat CairoPattern\n" - " [-1 0 0 1 %d 0] concat CairoPattern\n" - " CairoPattern\n" - " } bind\n", - pattern_width*2, pattern_height*2, - pattern_width*2, - pattern_height*2, - pattern_width*2); + " pop CairoPattern\n", + pattern_extents.x, + pattern_extents.y, + pattern_extents.x + pattern_extents.width*2, + pattern_extents.y + pattern_extents.height*2); + + cairo_matrix_init_translate (&mat, pattern_extents.x, pattern_extents.y); + cairo_matrix_scale (&mat, -1, 1); + cairo_matrix_translate (&mat, -2*pattern_extents.width, 0); + cairo_matrix_translate (&mat, -pattern_extents.x, -pattern_extents.y); + _cairo_output_stream_printf (surface->stream, " q ["); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, "] concat CairoPattern Q\n"); + + cairo_matrix_init_translate (&mat, pattern_extents.x, pattern_extents.y); + cairo_matrix_scale (&mat, 1, -1); + cairo_matrix_translate (&mat, 0, -2*pattern_extents.height); + cairo_matrix_translate (&mat, -pattern_extents.x, -pattern_extents.y); + _cairo_output_stream_printf (surface->stream, " q ["); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, "] concat CairoPattern Q\n"); + + cairo_matrix_init_translate (&mat, pattern_extents.x, pattern_extents.y); + cairo_matrix_scale (&mat, -1, -1); + cairo_matrix_translate (&mat, -2*pattern_extents.width, -2*pattern_extents.height); + cairo_matrix_translate (&mat, -pattern_extents.x, -pattern_extents.y); + _cairo_output_stream_printf (surface->stream, " q ["); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, "] concat CairoPattern Q\n"); + + _cairo_output_stream_printf (surface->stream, " } bind\n"); } else { if (op == CAIRO_OPERATOR_SOURCE) { _cairo_output_stream_printf (surface->stream, @@ -3409,8 +3479,11 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, xstep, ystep); } else { _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %d %d]\n", - pattern_width, pattern_height); + " /BBox [%d %d %d %d]\n", + pattern_extents.x, + pattern_extents.y, + pattern_extents.x + pattern_extents.width, + pattern_extents.y + pattern_extents.height); } _cairo_output_stream_printf (surface->stream, " /PaintProc { pop CairoPattern }\n"); @@ -3426,10 +3499,10 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, cairo_matrix_init_identity (&ps_p2d); cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d); - + cairo_matrix_translate (&ps_p2d, x_offset, y_offset); if (((cairo_surface_pattern_t *)pattern)->surface->type != CAIRO_SURFACE_TYPE_RECORDING) { - cairo_matrix_translate (&ps_p2d, 0.0, pattern_height); + cairo_matrix_translate (&ps_p2d, 0.0, pattern_extents.height); cairo_matrix_scale (&ps_p2d, 1.0, -1.0); } @@ -3443,7 +3516,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, if (image) cairo_surface_destroy (&image->base); - _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra); + _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source_surface, image_extra); return status; } @@ -4026,7 +4099,7 @@ _cairo_ps_surface_paint_pattern (cairo_ps_surface_t *surface, case CAIRO_PATTERN_TYPE_SURFACE: case CAIRO_PATTERN_TYPE_RASTER_SOURCE: return _cairo_ps_surface_paint_surface (surface, - (cairo_pattern_t *)source, + source, extents, op, stencil_mask); @@ -4035,8 +4108,8 @@ _cairo_ps_surface_paint_pattern (cairo_ps_surface_t *surface, case CAIRO_PATTERN_TYPE_RADIAL: case CAIRO_PATTERN_TYPE_MESH: return _cairo_ps_surface_paint_gradient (surface, - source, - extents); + source, + extents); case CAIRO_PATTERN_TYPE_SOLID: default: @@ -4074,17 +4147,10 @@ _cairo_ps_surface_get_extents (void *abstract_surface, { cairo_ps_surface_t *surface = abstract_surface; - rectangle->x = 0; - rectangle->y = 0; - - /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the aribitray limitation of width to a short(!). We - * may need to come up with a better interface for get_extents. - */ - rectangle->width = ceil (surface->width); - rectangle->height = ceil (surface->height); + if (surface->surface_bounded) + *rectangle = surface->surface_extents; - return TRUE; + return surface->surface_bounded; } static void @@ -4168,8 +4234,11 @@ _cairo_ps_surface_paint (void *abstract_surface, if (unlikely (status)) goto cleanup_composite; - _cairo_output_stream_printf (stream, "0 0 %f %f rectfill\n", - surface->width, surface->height); + _cairo_output_stream_printf (stream, "%d %d %d %d rectfill\n", + surface->surface_extents.x, + surface->surface_extents.y, + surface->surface_extents.width, + surface->surface_extents.height); } cleanup_composite: @@ -4473,34 +4542,55 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface, surface->paginated_mode = paginated_mode; - if (surface->clipper.clip != NULL) { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); + if (paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); - _cairo_output_stream_printf (surface->stream, "Q q\n"); - _cairo_surface_clipper_reset (&surface->clipper); + if (surface->clipper.clip != NULL) + { + status = _cairo_pdf_operators_flush (&surface->pdf_operators); + + _cairo_output_stream_printf (surface->stream, "Q q\n"); + _cairo_surface_clipper_reset (&surface->clipper); + } } } static cairo_int_status_t _cairo_ps_surface_set_bounding_box (void *abstract_surface, - cairo_box_t *bbox) + cairo_box_t *analysis_bbox) { cairo_ps_surface_t *surface = abstract_surface; int i, num_comments; char **comments; - int x1, y1, x2, y2; cairo_bool_t has_page_media, has_page_bbox; const char *page_media; + cairo_rectangle_int_t page_bbox; + cairo_point_int_t bbox_p1, bbox_p2; /* in PS coordinates */ - x1 = floor (_cairo_fixed_to_double (bbox->p1.x)); - y1 = floor (surface->height - _cairo_fixed_to_double (bbox->p2.y)); - x2 = ceil (_cairo_fixed_to_double (bbox->p2.x)); - y2 = ceil (surface->height - _cairo_fixed_to_double (bbox->p1.y)); + _cairo_box_round_to_rectangle (analysis_bbox, &page_bbox); - surface->page_bbox.x = x1; - surface->page_bbox.y = y1; - surface->page_bbox.width = x2 - x1; - surface->page_bbox.height = y2 - y1; + /* convert to PS coordinates */ + bbox_p1.x = page_bbox.x; + bbox_p1.y = ceil(surface->height) - (page_bbox.y + page_bbox.height); + bbox_p2.x = page_bbox.x + page_bbox.width; + bbox_p2.y = ceil(surface->height) - page_bbox.y; + + if (surface->num_pages == 1) { + surface->document_bbox_p1 = bbox_p1; + surface->document_bbox_p2 = bbox_p2; + } else { + if (bbox_p1.x < surface->document_bbox_p1.x) + surface->document_bbox_p1.x = bbox_p1.x; + if (bbox_p1.y < surface->document_bbox_p1.y) + surface->document_bbox_p1.y = bbox_p1.y; + if (bbox_p2.x < surface->document_bbox_p2.x) + surface->document_bbox_p2.x = bbox_p2.x; + if (bbox_p2.y < surface->document_bbox_p2.y) + surface->document_bbox_p2.y = bbox_p2.y; + } _cairo_output_stream_printf (surface->stream, "%%%%Page: %d %d\n", @@ -4541,7 +4631,10 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface, if (!has_page_bbox) { _cairo_output_stream_printf (surface->stream, "%%%%PageBoundingBox: %d %d %d %d\n", - x1, y1, x2, y2); + bbox_p1.x, + bbox_p1.y, + bbox_p2.x, + bbox_p2.y); } if (!surface->eps) { @@ -4555,27 +4648,12 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface, "%%%%EndPageSetup\n" "q %d %d %d %d rectclip\n" "1 0 0 -1 0 %f cm q\n", - surface->page_bbox.x, - surface->page_bbox.y, - surface->page_bbox.width, - surface->page_bbox.height, - surface->height); + bbox_p1.x, + bbox_p1.y, + bbox_p2.x - bbox_p1.x, + bbox_p2.y - bbox_p1.y, + ceil(surface->height)); - if (surface->num_pages == 1) { - surface->bbox_x1 = x1; - surface->bbox_y1 = y1; - surface->bbox_x2 = x2; - surface->bbox_y2 = y2; - } else { - if (x1 < surface->bbox_x1) - surface->bbox_x1 = x1; - if (y1 < surface->bbox_y1) - surface->bbox_y1 = y1; - if (x2 > surface->bbox_x2) - surface->bbox_x2 = x2; - if (y2 > surface->bbox_y2) - surface->bbox_y2 = y2; - } surface->current_pattern_is_solid_color = FALSE; _cairo_pdf_operators_reset (&surface->pdf_operators); diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index d35512eaa..218a8e323 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -1679,8 +1679,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, cairo_surface_wrapper_t wrapper; cairo_command_t **elements; cairo_bool_t replay_all = - type == CAIRO_RECORDING_REPLAY && - region == CAIRO_RECORDING_REGION_ALL; + type == CAIRO_RECORDING_CREATE_REGIONS || region == CAIRO_RECORDING_REGION_ALL; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_rectangle_int_t extents; cairo_bool_t use_indices = FALSE; @@ -1871,7 +1870,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, ASSERT_NOT_REACHED; } - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (type == CAIRO_RECORDING_CREATE_REGIONS && command->header.region != CAIRO_RECORDING_REGION_NATIVE) { if (status == CAIRO_INT_STATUS_SUCCESS) { command->header.region = CAIRO_RECORDING_REGION_NATIVE; } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { diff --git a/src/cairoint.h b/src/cairoint.h index 88b1bf739..efc9ad1fc 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1784,6 +1784,9 @@ _cairo_matrix_to_pixman_matrix_offset (const cairo_matrix_t *matrix, cairo_private void _cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix); +cairo_private void +_cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect); + cairo_private cairo_status_t _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps, const cairo_polygon_t *polygon, |