diff options
-rw-r--r-- | src/cairo-paginated-surface-private.h | 15 | ||||
-rw-r--r-- | src/cairo-paginated-surface.c | 241 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 3 | ||||
-rw-r--r-- | src/cairo-ps-surface.c | 470 |
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, +}; |