mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 07:38:22 +02:00
Primitive "real" postscript output for stroke/fill/paint
This commit is contained in:
parent
5a3c30eafe
commit
cb3a445150
4 changed files with 467 additions and 262 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
pattern = cairo_pattern_create_for_surface (image);
|
||||
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);
|
||||
|
||||
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
|
||||
_cairo_meta_surface_replay (surface->meta, image);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
pattern = cairo_pattern_create_for_surface (image);
|
||||
|
||||
cairo_surface_destroy (image);
|
||||
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue