summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2007-09-05 22:26:16 +0930
committerAdrian Johnson <ajohnson@redneon.com>2007-09-05 22:26:16 +0930
commitd24f019101dd014983aeb0bf186fe2011694e2ed (patch)
tree6a0d865a4fae519dcc2979978a17ff0d6850640c /src
parentb85032584b32af968dc8d8a0fcfc9f3e1d2770a0 (diff)
downloadcairo-d24f019101dd014983aeb0bf186fe2011694e2ed.tar.gz
Add support for PDF meta-surface patterns
Diffstat (limited to 'src')
-rw-r--r--src/cairo-analysis-surface.c66
-rw-r--r--src/cairo-meta-surface-private.h4
-rw-r--r--src/cairo-meta-surface.c43
-rw-r--r--src/cairo-pdf-surface.c282
-rw-r--r--src/cairo-types-private.h3
5 files changed, 316 insertions, 82 deletions
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index afbd30fb4..f738a6d13 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -39,6 +39,7 @@
#include "cairo-analysis-surface-private.h"
#include "cairo-paginated-private.h"
#include "cairo-region-private.h"
+#include "cairo-meta-surface-private.h"
typedef struct {
cairo_surface_t base;
@@ -57,6 +58,33 @@ typedef struct {
} cairo_analysis_surface_t;
static cairo_int_status_t
+_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
+ cairo_pattern_t *pattern)
+{
+ cairo_surface_pattern_t *surface_pattern;
+ cairo_surface_t *meta_surface;
+ cairo_surface_t *analysis;
+ cairo_status_t status;
+
+ assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
+ surface_pattern = (cairo_surface_pattern_t *) pattern;
+ assert (_cairo_surface_is_meta (surface_pattern->surface));
+
+ meta_surface = surface_pattern->surface;
+ analysis = _cairo_analysis_surface_create (surface->target,
+ surface->width, surface->height);
+ if (analysis == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = _cairo_meta_surface_replay_analyze_meta_pattern (meta_surface, analysis);
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = analysis->status;
+ cairo_surface_destroy (analysis);
+
+ return status;
+}
+
+static cairo_int_status_t
_cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
cairo_rectangle_int_t *rect,
cairo_int_status_t backend_status)
@@ -186,6 +214,10 @@ _cairo_analysis_surface_paint (void *abstract_surface,
backend_status = (*surface->target->backend->paint) (surface->target, op,
source);
+ if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+ backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+ source);
+
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
@@ -222,6 +254,28 @@ _cairo_analysis_surface_mask (void *abstract_surface,
backend_status = (*surface->target->backend->mask) (surface->target, op,
source, mask);
+ if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
+ if (_cairo_surface_is_meta (surface_pattern->surface))
+ backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+ source);
+ if (backend_status != CAIRO_STATUS_SUCCESS &&
+ backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
+ return backend_status;
+ }
+
+ if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
+ if (_cairo_surface_is_meta (surface_pattern->surface))
+ backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+ mask);
+ if (backend_status != CAIRO_STATUS_SUCCESS &&
+ backend_status != CAIRO_INT_STATUS_IMAGE_FALLBACK)
+ return backend_status;
+ }
+ }
+
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
@@ -273,6 +327,10 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
ctm, ctm_inverse,
tolerance, antialias);
+ if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+ backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+ source);
+
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
@@ -342,6 +400,10 @@ _cairo_analysis_surface_fill (void *abstract_surface,
source, path, fill_rule,
tolerance, antialias);
+ if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+ backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+ source);
+
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
@@ -409,6 +471,10 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
glyphs, num_glyphs,
scaled_font);
+ if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
+ backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
+ source);
+
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
diff --git a/src/cairo-meta-surface-private.h b/src/cairo-meta-surface-private.h
index b6d573026..a3360e68b 100644
--- a/src/cairo-meta-surface-private.h
+++ b/src/cairo-meta-surface-private.h
@@ -164,6 +164,10 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
cairo_private cairo_status_t
+_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
+ cairo_surface_t *target);
+
+cairo_private cairo_status_t
_cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface,
cairo_surface_t *target);
cairo_private cairo_status_t
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index d8f5064a7..63f6a9c5e 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -59,6 +59,12 @@
#include "cairo-meta-surface-private.h"
#include "cairo-clip-private.h"
+typedef enum {
+ CAIRO_META_REPLAY,
+ CAIRO_META_CREATE_REGIONS,
+ CAIRO_META_ANALYZE_META_PATTERN
+} cairo_meta_replay_type_t;
+
static const cairo_surface_backend_t cairo_meta_surface_backend;
/* Currently all meta surfaces do have a size which should be passed
@@ -650,7 +656,7 @@ _cairo_command_get_path (cairo_command_t *command)
static cairo_status_t
_cairo_meta_surface_replay_internal (cairo_surface_t *surface,
cairo_surface_t *target,
- cairo_bool_t create_regions,
+ cairo_meta_replay_type_t type,
cairo_meta_region_type_t region)
{
cairo_meta_surface_t *meta;
@@ -675,7 +681,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
for (i = meta->replay_start_idx; i < num_elements; i++) {
command = elements[i];
- if (!create_regions && region != CAIRO_META_REGION_ALL) {
+ if (type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) {
if (command->header.region != region)
continue;
}
@@ -834,7 +840,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
if (dev_path == &path_copy)
_cairo_path_fixed_fini (&path_copy);
- if (create_regions) {
+ if (type == CAIRO_META_CREATE_REGIONS) {
if (status == CAIRO_STATUS_SUCCESS) {
command->header.region = CAIRO_META_REGION_NATIVE;
} else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
@@ -842,6 +848,12 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
status = CAIRO_STATUS_SUCCESS;
}
}
+
+ if (type == CAIRO_META_ANALYZE_META_PATTERN) {
+ if (status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
+ status = CAIRO_STATUS_SUCCESS;
+ }
+
if (status)
break;
}
@@ -855,7 +867,20 @@ cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
{
- return _cairo_meta_surface_replay_internal (surface, target, FALSE, CAIRO_META_REGION_ALL);
+ return _cairo_meta_surface_replay_internal (surface,
+ target,
+ CAIRO_META_REPLAY,
+ CAIRO_META_REGION_ALL);
+}
+
+cairo_status_t
+_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
+ cairo_surface_t *target)
+{
+ return _cairo_meta_surface_replay_internal (surface,
+ target,
+ CAIRO_META_ANALYZE_META_PATTERN,
+ CAIRO_META_REGION_ALL);
}
/* Replay meta to surface. When the return status of each operation is
@@ -868,7 +893,10 @@ cairo_status_t
_cairo_meta_surface_replay_and_create_regions (cairo_surface_t *surface,
cairo_surface_t *target)
{
- return _cairo_meta_surface_replay_internal (surface, target, TRUE, CAIRO_META_REGION_ALL);
+ return _cairo_meta_surface_replay_internal (surface,
+ target,
+ CAIRO_META_CREATE_REGIONS,
+ CAIRO_META_REGION_ALL);
}
cairo_status_t
@@ -876,5 +904,8 @@ _cairo_meta_surface_replay_region (cairo_surface_t *surface,
cairo_surface_t *target,
cairo_meta_region_type_t region)
{
- return _cairo_meta_surface_replay_internal (surface, target, FALSE, region);
+ return _cairo_meta_surface_replay_internal (surface,
+ target,
+ CAIRO_META_REPLAY,
+ region);
}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 3d9ebba4c..1bca1f37d 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -45,6 +45,7 @@
#include "cairo-paginated-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
+#include "cairo-meta-surface-private.h"
#include <time.h>
#include <zlib.h>
@@ -235,6 +236,9 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
static cairo_status_t
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
+static cairo_status_t
+_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
+
static void
_cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface);
@@ -1036,6 +1040,15 @@ _cairo_pdf_group_element_array_finish (cairo_array_t *array)
}
}
+static cairo_surface_t *
+_cairo_pdf_surface_create_similar (void *abstract_surface,
+ cairo_content_t content,
+ int width,
+ int height)
+{
+ return _cairo_meta_surface_create (content, width, height);
+}
+
static cairo_status_t
_cairo_pdf_surface_finish (void *abstract_surface)
{
@@ -1308,14 +1321,120 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
_cairo_output_stream_printf (surface->output, "\r\n");
status = _cairo_pdf_surface_close_stream (surface);
- CLEANUP_COMPRESSED:
+CLEANUP_COMPRESSED:
free (compressed);
- CLEANUP_RGB:
+CLEANUP_RGB:
free (rgb);
- CLEANUP:
+CLEANUP:
+ return status;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
+ cairo_surface_pattern_t *pattern,
+ cairo_pdf_resource_t *resource,
+ int *width,
+ int *height)
+{
+ cairo_surface_t *pat_surface;
+ cairo_surface_attributes_t pat_attr;
+ cairo_image_surface_t *image;
+ void *image_extra;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
+ (cairo_surface_t *)surface,
+ 0, 0, -1, -1,
+ &pat_surface, &pat_attr);
+ if (status)
+ return status;
+
+ status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
+ if (status)
+ goto BAIL2;
+
+ status = _cairo_pdf_surface_emit_image (surface, image, resource);
+ if (status)
+ goto BAIL;
+
+ *width = image->width;
+ *height = image->height;
+
+BAIL:
+ _cairo_surface_release_source_image (pat_surface, image, image_extra);
+BAIL2:
+ _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
+
return status;
}
+static cairo_status_t
+_cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
+ cairo_surface_t *meta_surface,
+ cairo_pdf_resource_t *resource)
+{
+ cairo_array_t group;
+ cairo_array_t *old_group;
+ double old_width, old_height;
+ cairo_matrix_t old_cairo_to_pdf;
+ cairo_rectangle_int16_t meta_extents;
+ cairo_status_t status;
+ int alpha = 0;
+
+ status = _cairo_surface_get_extents (meta_surface, &meta_extents);
+ if (status)
+ return status;
+
+ _cairo_pdf_surface_resume_content_stream (surface);
+ _cairo_pdf_surface_stop_content_stream (surface);
+
+ _cairo_array_init (&group, sizeof (cairo_pdf_group_element_t));
+ old_group = surface->current_group;
+ old_width = surface->width;
+ old_height = surface->height;
+ old_cairo_to_pdf = surface->cairo_to_pdf;
+ surface->current_group = &group;
+ surface->width = meta_extents.width;
+ surface->height = meta_extents.height;
+ cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, surface->height);
+
+ _cairo_pdf_surface_start_content_stream (surface);
+
+ if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
+ status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
+ if (status)
+ return status;
+ _cairo_output_stream_printf (surface->output,
+ "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\r\n",
+ alpha,
+ surface->width,
+ surface->height);
+ }
+
+ status = _cairo_meta_surface_replay (meta_surface, &surface->base);
+ if (status)
+ return status;
+ _cairo_pdf_surface_stop_content_stream (surface);
+
+ _cairo_pdf_surface_open_group (surface);
+ _cairo_pdf_surface_write_group_list (surface, &group);
+ _cairo_pdf_surface_close_group (surface, resource);
+
+ surface->current_group = old_group;
+ surface->width = old_width;
+ surface->height = old_height;
+ surface->cairo_to_pdf = old_cairo_to_pdf;
+
+ _cairo_pdf_surface_start_content_stream (surface);
+
+ _cairo_pdf_group_element_array_finish (&group);
+ _cairo_array_fini (&group);
+
+ _cairo_pdf_surface_pause_content_stream (surface);
+
+ return 0;
+}
+
static void
_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
cairo_solid_pattern_t *pattern)
@@ -1331,81 +1450,84 @@ _cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
static cairo_status_t
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
- cairo_surface_pattern_t *pattern)
+ cairo_surface_pattern_t *pattern)
{
cairo_pdf_resource_t stream;
- cairo_surface_t *pat_surface;
- cairo_surface_attributes_t pat_attr;
- cairo_image_surface_t *image;
- void *image_extra;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_pdf_resource_t image_resource = {0}; /* squelch bogus compiler warning */
+ cairo_pdf_resource_t pattern_resource = {0}; /* squelch bogus compiler warning */
cairo_matrix_t cairo_p2d, pdf_p2d;
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
double xstep, ystep;
- cairo_rectangle_int_t surface_extents;
-
- /* XXX: Should do something clever here for PDF source surfaces ? */
+ cairo_rectangle_int16_t surface_extents;
+ int pattern_width = 0; /* squelch bogus compiler warning */
+ int pattern_height = 0; /* squelch bogus compiler warning */
_cairo_pdf_surface_pause_content_stream (surface);
- status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
- (cairo_surface_t *)surface,
- 0, 0, -1, -1,
- &pat_surface, &pat_attr);
- if (status)
- return status;
-
- status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
- if (status)
- goto BAIL2;
+ if (_cairo_surface_is_meta (pattern->surface)) {
+ cairo_surface_t *meta_surface = pattern->surface;
+ cairo_rectangle_int16_t pattern_extents;
- status = _cairo_pdf_surface_emit_image (surface, image, &image_resource);
+ status = _cairo_pdf_surface_emit_meta_surface (surface,
+ meta_surface,
+ &pattern_resource);
+ status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
+ if (status)
+ return status;
+ pattern_width = pattern_extents.width;
+ pattern_height = pattern_extents.height;
+ } else {
+ status = _cairo_pdf_surface_emit_image_surface (surface,
+ pattern,
+ &pattern_resource,
+ &pattern_width,
+ &pattern_height);
+ }
if (status)
- goto BAIL;
+ return status;
status = _cairo_surface_get_extents (&surface->base, &surface_extents);
if (status)
- goto BAIL;
+ return status;
switch (extend) {
- /* We implement EXTEND_PAD like EXTEND_NONE for now */
+ /* We implement EXTEND_PAD like EXTEND_NONE for now */
case CAIRO_EXTEND_PAD:
case CAIRO_EXTEND_NONE:
- {
- /* In PS/PDF, (as far as I can tell), all patterns are
- * repeating. So we support cairo's EXTEND_NONE semantics
- * by setting the repeat step size to a size large enough
- * to guarantee that no more than a single occurrence will
- * be visible.
- *
- * First, map the surface extents into pattern space (since
- * xstep and ystep are in pattern space). Then use an upper
- * bound on the length of the diagonal of the pattern image
- * and the surface as repeat size. This guarantees to never
- * repeat visibly.
- */
- double x1 = 0.0, y1 = 0.0;
- double x2 = surface->width, y2 = surface->height;
- _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
- &x1, &y1, &x2, &y2,
- NULL);
-
- /* Rather than computing precise bounds of the union, just
- * add the surface extents unconditionally. We only
- * 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) +
- image->width + image->height);
- }
- break;
+ {
+ /* In PS/PDF, (as far as I can tell), all patterns are
+ * repeating. So we support cairo's EXTEND_NONE semantics
+ * by setting the repeat step size to a size large enough
+ * to guarantee that no more than a single occurrence will
+ * be visible.
+ *
+ * First, map the surface extents into pattern space (since
+ * xstep and ystep are in pattern space). Then use an upper
+ * bound on the length of the diagonal of the pattern image
+ * and the surface as repeat size. This guarantees to never
+ * repeat visibly.
+ */
+ double x1 = 0.0, y1 = 0.0;
+ double x2 = surface->width, y2 = surface->height;
+ _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
+ &x1, &y1, &x2, &y2,
+ NULL);
+
+ /* Rather than computing precise bounds of the union, just
+ * add the surface extents unconditionally. We only
+ * 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);
+ }
+ break;
case CAIRO_EXTEND_REPEAT:
case CAIRO_EXTEND_REFLECT:
- xstep = image->width;
- ystep = image->height;
+ xstep = pattern_width;
+ ystep = pattern_height;
break;
- /* All the rest (if any) should have been analyzed away, so this
- * case should be unreachable. */
+ /* All the rest (if any) should have been analyzed away, so this
+ * case should be unreachable. */
default:
ASSERT_NOT_REACHED;
xstep = 0;
@@ -1448,11 +1570,11 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
- cairo_matrix_translate (&pdf_p2d, 0.0, image->height);
+ cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height);
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
stream = _cairo_pdf_surface_open_stream (surface,
- FALSE,
+ FALSE,
" /BBox [0 0 %d %d]\r\n"
" /XStep %f\r\n"
" /YStep %f\r\n"
@@ -1460,23 +1582,29 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
" /TilingType 1\r\n"
" /PaintType 1\r\n"
" /Matrix [ %f %f %f %f %f %f ]\r\n"
- " /Resources << /XObject << /res%d %d 0 R >> >>\r\n",
- image->width, image->height,
+ " /Resources << /XObject << /x%d %d 0 R >> >>\r\n",
+ pattern_width, pattern_height,
xstep, ystep,
pdf_p2d.xx, pdf_p2d.yx,
pdf_p2d.xy, pdf_p2d.yy,
pdf_p2d.x0, pdf_p2d.y0,
- image_resource.id,
- image_resource.id);
+ pattern_resource.id,
+ pattern_resource.id);
- _cairo_output_stream_printf (surface->output,
- "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",
- image->width, image->height,
- image_resource.id);
+ if (_cairo_surface_is_meta (pattern->surface)) {
+ _cairo_output_stream_printf (surface->output,
+ "/x%d Do\r\n",
+ pattern_resource.id);
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "q %d 0 0 %d 0 0 cm /x%d Do Q\r\n",
+ pattern_width, pattern_height,
+ pattern_resource.id);
+ }
status = _cairo_pdf_surface_close_stream (surface);
if (status)
- goto BAIL;
+ return status;
_cairo_pdf_surface_resume_content_stream (surface);
@@ -1485,11 +1613,6 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
surface->emitted_pattern.pattern = stream;
surface->emitted_pattern.alpha = 1.0;
- BAIL:
- _cairo_surface_release_source_image (pat_surface, image, image_extra);
- BAIL2:
- _cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
-
return status;
}
@@ -3436,6 +3559,9 @@ _surface_pattern_supported (cairo_surface_pattern_t *pattern)
{
cairo_extend_t extend;
+ if (_cairo_surface_is_meta (pattern->surface))
+ return TRUE;
+
if (pattern->surface->backend->acquire_source_image == NULL)
return FALSE;
@@ -3524,8 +3650,14 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
if (! _pattern_supported (pattern))
return CAIRO_INT_STATUS_UNSUPPORTED;
- if (op == CAIRO_OPERATOR_OVER)
+ if (op == CAIRO_OPERATOR_OVER) {
+ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+ if ( _cairo_surface_is_meta (surface_pattern->surface))
+ return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
+ }
return CAIRO_STATUS_SUCCESS;
+ }
/* The SOURCE operator is only supported for the fallback images. */
if (op == CAIRO_OPERATOR_SOURCE &&
@@ -4089,7 +4221,7 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
CAIRO_SURFACE_TYPE_PDF,
- NULL, /* create_similar */
+ _cairo_pdf_surface_create_similar,
_cairo_pdf_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index e63dccd3b..45491f7cd 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -136,7 +136,8 @@ typedef enum _cairo_int_status {
CAIRO_INT_STATUS_NOTHING_TO_DO,
CAIRO_INT_STATUS_CACHE_EMPTY,
CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
- CAIRO_INT_STATUS_IMAGE_FALLBACK
+ CAIRO_INT_STATUS_IMAGE_FALLBACK,
+ CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN,
} cairo_int_status_t;
typedef enum _cairo_internal_surface_type {