summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-paginated-surface-private.h15
-rw-r--r--src/cairo-paginated-surface.c241
-rw-r--r--src/cairo-pdf-surface.c3
-rw-r--r--src/cairo-ps-surface.c470
4 files changed, 467 insertions, 262 deletions
diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h
index 79438e4ab..c4c656b48 100644
--- a/src/cairo-paginated-surface-private.h
+++ b/src/cairo-paginated-surface-private.h
@@ -38,11 +38,24 @@
#include "cairoint.h"
+typedef enum {
+ CAIRO_PAGINATED_MODE_EVALUATE, /* evaluate page regions */
+ CAIRO_PAGINATED_MODE_RENDER /* render page contents */
+} cairo_paginated_mode_t;
+
+typedef void (*cairo_paginated_set_mode_t) (cairo_surface_t *target,
+ cairo_paginated_mode_t mode);
+
+typedef struct {
+ cairo_paginated_set_mode_t set_mode;
+} cairo_paginated_funcs_t;
+
cairo_private cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
- int height);
+ int height,
+ const cairo_paginated_funcs_t *funcs);
cairo_private cairo_surface_t *
_cairo_paginated_surface_get_target (cairo_surface_t *surface);
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 6317d7083..6d4c02e14 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -31,6 +31,7 @@
*
* Contributor(s):
* Carl Worth <cworth@cworth.org>
+ * Keith Packard <keithp@keithp.com>
*/
/* The paginated surface layer exists to provide as much code sharing
@@ -85,6 +86,9 @@ typedef struct _cairo_paginated_surface {
/* The target surface to hold the final result. */
cairo_surface_t *target;
+ /* Paginated-surface specific functions for the target */
+ const cairo_paginated_funcs_t *funcs;
+
/* A cairo_meta_surface to record all operations. To be replayed
* against target, and also against image surface as necessary for
* fallbacks. */
@@ -97,11 +101,27 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
static cairo_int_status_t
_cairo_paginated_surface_show_page (void *abstract_surface);
+typedef struct {
+ cairo_surface_t base;
+ int width;
+ int height;
+
+ cairo_surface_t *target;
+
+ cairo_bool_t fallback;
+} cairo_evaluate_surface_t;
+
+static cairo_evaluate_surface_t *
+_cairo_evaluate_surface_create (cairo_surface_t *target,
+ int width,
+ int height);
+
cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
- int height)
+ int height,
+ const cairo_paginated_funcs_t *funcs)
{
cairo_paginated_surface_t *surface;
@@ -116,6 +136,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
surface->height = height;
surface->target = target;
+ surface->funcs = funcs;
surface->meta = _cairo_meta_surface_create (content, width, height);
if (cairo_surface_status (surface->meta))
@@ -191,25 +212,49 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface,
cairo_surface_destroy (&image->base);
}
-static void
+static cairo_int_status_t
_paint_page (cairo_paginated_surface_t *surface)
{
+ cairo_evaluate_surface_t *evaluate;
cairo_surface_t *image;
cairo_pattern_t *pattern;
+ cairo_status_t status;
- image = _cairo_image_surface_create_with_content (surface->content,
- surface->width,
- surface->height);
+ evaluate = _cairo_evaluate_surface_create (surface->target,
+ surface->width, surface->height);
- _cairo_meta_surface_replay (surface->meta, image);
+ surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_EVALUATE);
+ _cairo_meta_surface_replay (surface->meta, &evaluate->base);
+ surface->funcs->set_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
+
+ if (evaluate->base.status) {
+ status = evaluate->base.status;
+ cairo_surface_destroy (&evaluate->base);
+ return status;
+ }
+
+ if (evaluate->fallback)
+ {
+ image = _cairo_image_surface_create_with_content (surface->content,
+ surface->width,
+ surface->height);
- pattern = cairo_pattern_create_for_surface (image);
+ _cairo_meta_surface_replay (surface->meta, image);
- _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
+ pattern = cairo_pattern_create_for_surface (image);
- cairo_pattern_destroy (pattern);
+ _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
- cairo_surface_destroy (image);
+ cairo_pattern_destroy (pattern);
+
+ cairo_surface_destroy (image);
+ }
+ else
+ {
+ _cairo_meta_surface_replay (surface->meta, surface->target);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -409,3 +454,179 @@ const cairo_surface_backend_t cairo_paginated_surface_backend = {
_cairo_paginated_surface_show_glyphs,
_cairo_paginated_surface_snapshot
};
+
+static cairo_int_status_t
+_cairo_evaluate_surface_paint (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source)
+{
+ cairo_evaluate_surface_t *surface = abstract_surface;
+ cairo_status_t status;
+
+ if (!surface->target->backend->paint)
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ else
+ status = (*surface->target->backend->paint) (surface->target, op,
+ source);
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ surface->fallback = TRUE;
+ status = CAIRO_STATUS_SUCCESS;
+ }
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_evaluate_surface_mask (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_pattern_t *mask)
+{
+ cairo_evaluate_surface_t *surface = abstract_surface;
+ cairo_status_t status;
+
+ if (!surface->target->backend->mask)
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ else
+ status = (*surface->target->backend->mask) (surface->target, op,
+ source, mask);
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ surface->fallback = TRUE;
+ status = CAIRO_STATUS_SUCCESS;
+ }
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_evaluate_surface_stroke (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias)
+{
+ cairo_evaluate_surface_t *surface = abstract_surface;
+ cairo_status_t status;
+
+ if (!surface->target->backend->stroke)
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ else
+ status = (*surface->target->backend->stroke) (surface->target, op,
+ source, path, style,
+ ctm, ctm_inverse,
+ tolerance, antialias);
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ surface->fallback = TRUE;
+ status = CAIRO_STATUS_SUCCESS;
+ }
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_evaluate_surface_fill (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias)
+{
+ cairo_evaluate_surface_t *surface = abstract_surface;
+ cairo_status_t status;
+
+ if (!surface->target->backend->fill)
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ else
+ status = (*surface->target->backend->fill) (surface->target, op,
+ source, path, fill_rule,
+ tolerance, antialias);
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ surface->fallback = TRUE;
+ status = CAIRO_STATUS_SUCCESS;
+ }
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_evaluate_surface_show_glyphs (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_evaluate_surface_t *surface = abstract_surface;
+ cairo_status_t status;
+
+ if (!surface->target->backend->show_glyphs)
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ else
+ status = (*surface->target->backend->show_glyphs) (surface->target, op,
+ source,
+ glyphs, num_glyphs,
+ scaled_font);
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ surface->fallback = TRUE;
+ status = CAIRO_STATUS_SUCCESS;
+ }
+ return status;
+}
+
+static const cairo_surface_backend_t cairo_evaluate_surface_backend = {
+ NULL, /* create_similar */
+ NULL, /* finish_surface */
+ NULL, /* acquire_source_image */
+ NULL, /* release_source_image */
+ NULL, /* acquire_dest_image */
+ NULL, /* release_dest_image */
+ NULL, /* clone_similar */
+ NULL, /* composite */
+ NULL, /* fill_rectangles */
+ NULL, /* composite_trapezoids */
+ NULL, /* copy_page */
+ NULL, /* show_page */
+ NULL, /* set_clip_region */
+ NULL, /* clip_path */
+ NULL, /* get_extents */
+ NULL, /* old_show_glyphs */
+ NULL, /* get_font_options */
+ NULL, /* flush */
+ NULL, /* mark_dirty_rectangle */
+ NULL, /* scaled_font_fini */
+ NULL, /* scaled_glyph_fini */
+ _cairo_evaluate_surface_paint,
+ _cairo_evaluate_surface_mask,
+ _cairo_evaluate_surface_stroke,
+ _cairo_evaluate_surface_fill,
+ _cairo_evaluate_surface_show_glyphs,
+ NULL, /* snapshot */
+};
+
+static cairo_evaluate_surface_t *
+_cairo_evaluate_surface_create (cairo_surface_t *target,
+ int width,
+ int height)
+{
+ cairo_evaluate_surface_t *surface;
+
+ surface = malloc (sizeof (cairo_evaluate_surface_t));
+ if (surface == NULL)
+ goto FAIL;
+
+ _cairo_surface_init (&surface->base, &cairo_evaluate_surface_backend);
+
+ surface->width = width;
+ surface->height = height;
+
+ surface->target = target;
+ surface->fallback = FALSE;
+
+ return surface;
+FAIL:
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
+}
+
+
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 289eeb961..dd2fa9096 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -306,7 +306,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *stream,
return _cairo_paginated_surface_create (target,
CAIRO_CONTENT_COLOR_ALPHA,
- width, height);
+ width, height,
+ NULL); /* XXX */
}
/**
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 371290cc2..2cf8a9d6b 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -56,6 +56,7 @@
*/
static const cairo_surface_backend_t cairo_ps_surface_backend;
+static const cairo_paginated_funcs_t cairo_ps_paginated_funcs;
typedef struct cairo_ps_surface {
cairo_surface_t base;
@@ -71,6 +72,8 @@ typedef struct cairo_ps_surface {
cairo_bool_t need_start_page;
int num_pages;
+ cairo_paginated_mode_t mode;
+
#if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED
cairo_array_t fonts;
#endif
@@ -141,6 +144,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->height = height;
surface->x_dpi = PS_SURFACE_DPI_DEFAULT;
surface->y_dpi = PS_SURFACE_DPI_DEFAULT;
+ surface->mode = CAIRO_PAGINATED_MODE_EVALUATE;
#if DONE_ADDING_DEVICE_SCALE_SUPPORT_AFTER_SWITCHING_TO_PAGINATED
surface->base.device_x_scale = surface->x_dpi / 72.0;
surface->base.device_y_scale = surface->y_dpi / 72.0;
@@ -157,7 +161,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
return _cairo_paginated_surface_create (&surface->base,
CAIRO_CONTENT_COLOR_ALPHA,
- width, height);
+ width, height,
+ &cairo_ps_paginated_funcs);
}
/**
@@ -472,17 +477,6 @@ _cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface)
}
#endif
-/* XXX: This function wil go away in favor of the new "analysis mode"
- * of cairo_paginated_surface_t */
-static cairo_int_status_t
-_cairo_ps_surface_add_fallback_area (cairo_ps_surface_t *surface,
- int x, int y,
- unsigned int width,
- unsigned int height)
-{
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_bool_t
color_is_gray (cairo_color_t *color)
{
@@ -493,66 +487,66 @@ color_is_gray (cairo_color_t *color)
}
static cairo_bool_t
-color_is_translucent (const cairo_color_t *color)
+color_is_opaque (const cairo_color_t *color)
{
- return color->alpha < 0.999;
+ return color->alpha >= 0.999;
}
static cairo_bool_t
-format_is_translucent (cairo_format_t format)
+format_is_opaque (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_ARGB32:
- return TRUE;
- case CAIRO_FORMAT_RGB24:
return FALSE;
- case CAIRO_FORMAT_A8:
+ case CAIRO_FORMAT_RGB24:
return TRUE;
+ case CAIRO_FORMAT_A8:
+ return FALSE;
case CAIRO_FORMAT_A1:
return TRUE;
}
- return TRUE;
+ return FALSE;
}
static cairo_bool_t
-surface_is_translucent (const cairo_surface_t *surface)
+surface_is_opaque (const cairo_surface_t *surface)
{
if (_cairo_surface_is_image (surface)) {
const cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
- return format_is_translucent (image_surface->format);
+ return format_is_opaque (image_surface->format);
}
return TRUE;
}
static cairo_bool_t
-gradient_is_translucent (const cairo_gradient_pattern_t *gradient)
+gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
{
- return TRUE; /* XXX no gradient support */
+ return FALSE; /* XXX no gradient support */
#if 0
int i;
for (i = 0; i < gradient->n_stops; i++)
- if (color_is_translucent (&gradient->stops[i].color))
- return TRUE;
- return FALSE;
+ if (!color_is_opaque (&gradient->stops[i].color))
+ return FALSE;
+ return TRUE;
#endif
}
static cairo_bool_t
-pattern_is_translucent (const cairo_pattern_t *abstract_pattern)
+pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
{
const cairo_pattern_union_t *pattern;
pattern = (cairo_pattern_union_t *) abstract_pattern;
switch (pattern->base.type) {
case CAIRO_PATTERN_TYPE_SOLID:
- return color_is_translucent (&pattern->solid.color);
+ return color_is_opaque (&pattern->solid.color);
case CAIRO_PATTERN_TYPE_SURFACE:
- return surface_is_translucent (pattern->surface.surface);
+ return surface_is_opaque (pattern->surface.surface);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
- return gradient_is_translucent (&pattern->gradient.base);
+ return gradient_is_opaque (&pattern->gradient.base);
}
ASSERT_NOT_REACHED;
@@ -624,35 +618,35 @@ operator_always_translucent (cairo_operator_t op)
}
static cairo_bool_t
-color_operation_needs_fallback (cairo_operator_t op,
- const cairo_color_t *color)
+pattern_surface_supported (const cairo_surface_pattern_t *pattern)
{
- if (operator_always_opaque (op))
+ if (pattern->surface->backend->acquire_source_image == NULL)
return FALSE;
- if (operator_always_translucent (op))
- return TRUE;
- return color_is_translucent (color);
+ return TRUE;
}
static cairo_bool_t
-pattern_type_supported (const cairo_pattern_t *pattern)
+pattern_supported (const cairo_pattern_t *pattern)
{
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
return TRUE;
+ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
+ return pattern_surface_supported ((const cairo_surface_pattern_t *) pattern);
+
return FALSE;
}
static cairo_bool_t
-pattern_operation_needs_fallback (cairo_operator_t op,
+pattern_operation_supported (cairo_operator_t op,
const cairo_pattern_t *pattern)
{
- if (! pattern_type_supported (pattern))
- return TRUE;
- if (operator_always_opaque (op))
+ if (! pattern_supported (pattern))
return FALSE;
- if (operator_always_translucent (op))
+ if (operator_always_opaque (op))
return TRUE;
- return pattern_is_translucent (pattern);
+ if (operator_always_translucent (op))
+ return FALSE;
+ return pattern_is_opaque (pattern);
}
/* PS Output - this section handles output of the parts of the meta
@@ -812,7 +806,15 @@ static void
emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern)
{
- /* XXX: NYI */
+ cairo_image_surface_t *image;
+ cairo_status_t status;
+ void *image_extra;
+
+ status = _cairo_surface_acquire_source_image (pattern->surface,
+ &image,
+ &image_extra);
+ assert (status == CAIRO_STATUS_SUCCESS);
+ emit_image (surface, image, &pattern->base.matrix);
}
static void
@@ -855,200 +857,6 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
}
}
-
-static cairo_int_status_t
-_cairo_ps_surface_composite (cairo_operator_t op,
- cairo_pattern_t *src_pattern,
- cairo_pattern_t *mask_pattern,
- void *abstract_dst,
- int src_x,
- int src_y,
- int mask_x,
- int mask_y,
- int dst_x,
- int dst_y,
- unsigned int width,
- unsigned int height)
-{
- cairo_ps_surface_t *surface = abstract_dst;
- cairo_output_stream_t *stream = surface->stream;
- cairo_surface_pattern_t *surface_pattern;
- cairo_status_t status;
- cairo_image_surface_t *image;
- void *image_extra;
-
- if (surface->need_start_page)
- _cairo_ps_surface_start_page (surface);
-
- if (mask_pattern) {
- /* FIXME: Investigate how this can be done... we'll probably
- * need pixmap fallbacks for this, though. */
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_composite: with mask\n");
- goto bail;
- }
-
- status = CAIRO_STATUS_SUCCESS;
- switch (src_pattern->type) {
- case CAIRO_PATTERN_TYPE_SOLID:
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_composite: solid\n");
- goto bail;
-
- case CAIRO_PATTERN_TYPE_SURFACE:
- surface_pattern = (cairo_surface_pattern_t *) src_pattern;
-
- if (src_pattern->extend != CAIRO_EXTEND_NONE) {
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_composite: repeating image\n");
- goto bail;
- }
-
-
- status = _cairo_surface_acquire_source_image (surface_pattern->surface,
- &image,
- &image_extra);
- if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_composite: src_pattern not available as image\n");
- goto bail;
- } else if (status) {
- break;
- }
- status = emit_image (surface, image, &src_pattern->matrix);
- _cairo_surface_release_source_image (surface_pattern->surface,
- image, image_extra);
- break;
-
- case CAIRO_PATTERN_TYPE_LINEAR:
- case CAIRO_PATTERN_TYPE_RADIAL:
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_composite: gradient\n");
- goto bail;
- }
-
- return status;
-bail:
- return _cairo_ps_surface_add_fallback_area (surface, dst_x, dst_y, width, height);
-}
-
-static cairo_int_status_t
-_cairo_ps_surface_fill_rectangles (void *abstract_surface,
- cairo_operator_t op,
- const cairo_color_t *color,
- cairo_rectangle_t *rects,
- int num_rects)
-{
- cairo_ps_surface_t *surface = abstract_surface;
- cairo_output_stream_t *stream = surface->stream;
- cairo_solid_pattern_t solid;
- int i;
-
- if (!num_rects)
- return CAIRO_STATUS_SUCCESS;
-
- if (surface->need_start_page)
- _cairo_ps_surface_start_page (surface);
-
- if (color_operation_needs_fallback (op, color)) {
- int min_x = rects[0].x;
- int min_y = rects[0].y;
- int max_x = rects[0].x + rects[0].width;
- int max_y = rects[0].y + rects[0].height;
-
- for (i = 1; i < num_rects; i++) {
- if (rects[i].x < min_x) min_x = rects[i].x;
- if (rects[i].y < min_y) min_y = rects[i].y;
- if (rects[i].x + rects[i].width > max_x) max_x = rects[i].x + rects[i].width;
- if (rects[i].y + rects[i].height > max_y) max_y = rects[i].y + rects[i].height;
- }
- return _cairo_ps_surface_add_fallback_area (surface, min_x, min_y, max_x - min_x, max_y - min_y);
- }
-
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_fill_rectangles\n");
-
- _cairo_pattern_init_solid (&solid, color);
- emit_pattern (surface, &solid.base);
- _cairo_pattern_fini (&solid.base);
-
- _cairo_output_stream_printf (stream, "[");
- for (i = 0; i < num_rects; i++) {
- _cairo_output_stream_printf (stream,
- " %d %d %d %d",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height);
- }
-
- _cairo_output_stream_printf (stream, " ] rectfill\n");
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static double
-intersect (cairo_line_t *line, cairo_fixed_t y)
-{
- return _cairo_fixed_to_double (line->p1.x) +
- _cairo_fixed_to_double (line->p2.x - line->p1.x) *
- _cairo_fixed_to_double (y - line->p1.y) /
- _cairo_fixed_to_double (line->p2.y - line->p1.y);
-}
-
-static cairo_int_status_t
-_cairo_ps_surface_composite_trapezoids (cairo_operator_t op,
- cairo_pattern_t *pattern,
- void *abstract_dst,
- cairo_antialias_t antialias,
- int x_src,
- int y_src,
- int x_dst,
- int y_dst,
- unsigned int width,
- unsigned int height,
- cairo_trapezoid_t *traps,
- int num_traps)
-{
- cairo_ps_surface_t *surface = abstract_dst;
- cairo_output_stream_t *stream = surface->stream;
- int i;
-
- if (pattern_operation_needs_fallback (op, pattern))
- return _cairo_ps_surface_add_fallback_area (surface, x_dst, y_dst, width, height);
-
- if (surface->need_start_page)
- _cairo_ps_surface_start_page (surface);
-
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_composite_trapezoids\n");
-
- emit_pattern (surface, pattern);
-
- for (i = 0; i < num_traps; i++) {
- double left_x1, left_x2, right_x1, right_x2, top, bottom;
-
- left_x1 = intersect (&traps[i].left, traps[i].top);
- left_x2 = intersect (&traps[i].left, traps[i].bottom);
- right_x1 = intersect (&traps[i].right, traps[i].top);
- right_x2 = intersect (&traps[i].right, traps[i].bottom);
- top = _cairo_fixed_to_double (traps[i].top);
- bottom = _cairo_fixed_to_double (traps[i].bottom);
-
- _cairo_output_stream_printf
- (stream,
- "%f %f moveto %f %f lineto %f %f lineto %f %f lineto "
- "closepath\n",
- left_x1, top,
- left_x2, bottom,
- right_x2, bottom,
- right_x1, top);
- }
-
- _cairo_output_stream_printf (stream,
- "fill\n");
-
- return CAIRO_STATUS_SUCCESS;
-}
-
typedef struct
{
cairo_output_stream_t *output_stream;
@@ -1135,6 +943,9 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
cairo_ps_surface_path_info_t info;
const char *ps_operator;
+ if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_intersect_clip_path\n");
@@ -1265,7 +1076,153 @@ _cairo_ps_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
#endif
static cairo_int_status_t
-_cairo_ps_surface_fill (void *abstract_surface,
+_cairo_ps_surface_paint (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+ cairo_output_stream_t *stream = surface->stream;
+ cairo_ps_surface_path_info_t info;
+
+ if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) {
+ if (!pattern_operation_supported (op, source))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (surface->need_start_page)
+ _cairo_ps_surface_start_page (surface);
+
+ _cairo_output_stream_printf (stream,
+ "%% _cairo_ps_surface_paint\n");
+
+ emit_pattern (surface, source);
+
+ info.output_stream = stream;
+ info.has_current_point = FALSE;
+
+ _cairo_output_stream_printf (stream, "0 0 moveto\n");
+ _cairo_output_stream_printf (stream, "%f 0 lineto\n", surface->width);
+ _cairo_output_stream_printf (stream, "%f %f lineto\n",
+ surface->width, surface->height);
+ _cairo_output_stream_printf (stream, "0 %f lineto\n", surface->height);
+ _cairo_output_stream_printf (stream, "closepath fill\n");
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static int
+_cairo_ps_line_cap (cairo_line_cap_t cap)
+{
+ switch (cap) {
+ case CAIRO_LINE_CAP_BUTT:
+ return 0;
+ case CAIRO_LINE_CAP_ROUND:
+ return 1;
+ case CAIRO_LINE_CAP_SQUARE:
+ return 2;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+}
+
+static int
+_cairo_ps_line_join (cairo_line_join_t join)
+{
+ switch (join) {
+ case CAIRO_LINE_JOIN_MITER:
+ return 0;
+ case CAIRO_LINE_JOIN_ROUND:
+ return 1;
+ case CAIRO_LINE_JOIN_BEVEL:
+ return 2;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_stroke (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+ cairo_output_stream_t *stream = surface->stream;
+ cairo_int_status_t status;
+ cairo_ps_surface_path_info_t info;
+
+ if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) {
+ if (!pattern_operation_supported (op, source))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ if (surface->need_start_page)
+ _cairo_ps_surface_start_page (surface);
+
+ _cairo_output_stream_printf (stream,
+ "%% _cairo_ps_surface_stroke\n");
+
+ emit_pattern (surface, source);
+
+
+ info.output_stream = stream;
+ info.has_current_point = FALSE;
+
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_ps_surface_path_move_to,
+ _cairo_ps_surface_path_line_to,
+ _cairo_ps_surface_path_curve_to,
+ _cairo_ps_surface_path_close_path,
+ &info);
+
+ /*
+ * Switch to user space to set line parameters
+ */
+ _cairo_output_stream_printf (stream,
+ "gsave\n");
+ _cairo_output_stream_printf (stream,
+ "[%f %f %f %f 0 0] concat\n",
+ ctm->xx, ctm->yx, ctm->xy, ctm->yy);
+ /* line width */
+ _cairo_output_stream_printf (stream, "%f setlinewidth\n",
+ style->line_width);
+ /* line cap */
+ _cairo_output_stream_printf (stream, "%d setlinecap\n",
+ _cairo_ps_line_cap (style->line_cap));
+ /* line join */
+ _cairo_output_stream_printf (stream, "%d setlinejoin\n",
+ _cairo_ps_line_join (style->line_join));
+ /* dashes */
+ if (style->num_dashes) {
+ int d;
+ _cairo_output_stream_printf (stream, "[");
+ for (d = 0; d < style->num_dashes; d++)
+ _cairo_output_stream_printf (stream, " %f", style->dash[d]);
+ _cairo_output_stream_printf (stream, "] %f setdash\n",
+ style->dash_offset);
+ }
+ /* miter limit */
+ _cairo_output_stream_printf (stream, "%f setmiterlimit\n",
+ style->miter_limit);
+ _cairo_output_stream_printf (stream,
+ "stroke\n");
+ _cairo_output_stream_printf (stream,
+ "grestore\n");
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_ps_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
@@ -1279,12 +1236,12 @@ _cairo_ps_surface_fill (void *abstract_surface,
cairo_ps_surface_path_info_t info;
const char *ps_operator;
- if (pattern_operation_needs_fallback (op, source))
- return _cairo_ps_surface_add_fallback_area (surface,
- 0, 0,
- surface->width,
- surface->height);
-
+ if (surface->mode == CAIRO_PAGINATED_MODE_EVALUATE) {
+ if (!pattern_operation_supported (op, source))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
if (surface->need_start_page)
_cairo_ps_surface_start_page (surface);
@@ -1329,9 +1286,9 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
- _cairo_ps_surface_composite,
- _cairo_ps_surface_fill_rectangles,
- _cairo_ps_surface_composite_trapezoids,
+ NULL, /* composite */
+ NULL, /* fill_rectangles */
+ NULL, /* composite_trapezoids */
_cairo_ps_surface_copy_page,
_cairo_ps_surface_show_page,
NULL, /* set_clip_region */
@@ -1350,9 +1307,22 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
/* Here are the drawing functions */
- NULL, /* paint */
+ _cairo_ps_surface_paint, /* paint */
NULL, /* mask */
- NULL, /* stroke */
+ _cairo_ps_surface_stroke,
_cairo_ps_surface_fill,
NULL /* show_glyphs */
};
+
+static void
+_cairo_ps_paginated_set_mode (cairo_surface_t *target,
+ cairo_paginated_mode_t mode)
+{
+ cairo_ps_surface_t *surface = (cairo_ps_surface_t *) target;
+
+ surface->mode = mode;
+}
+
+static const cairo_paginated_funcs_t cairo_ps_paginated_funcs = {
+ _cairo_ps_paginated_set_mode,
+};