summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2016-06-04 14:43:43 +0930
committerAdrian Johnson <ajohnson@redneon.com>2016-06-05 20:43:36 +0930
commit1c5ec6e3806587eff1fbb640c63838ef2768c2cb (patch)
tree4c980b5835f88fb8c2dc160ae087a780c6caa7a5
parenta14d319e4385033d726861dcd448154d393ffc53 (diff)
Fix PS record-neg-extents test failure
-rw-r--r--src/cairo-analysis-surface.c111
-rw-r--r--src/cairo-debug.c8
-rw-r--r--src/cairo-pdf-surface.c40
-rw-r--r--src/cairo-ps-surface-private.h5
-rw-r--r--src/cairo-ps-surface.c538
-rw-r--r--src/cairo-recording-surface.c5
-rw-r--r--src/cairoint.h3
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,