Use the _cairo_surface_*() functions when replaying.

Fold the "locate fallbacks" pass into the postscript output pass, and add a simple, first implementation of image fallbacks.
This commit is contained in:
Kristian Høgsberg 2005-07-13 12:32:51 +00:00
parent aafc2e7497
commit 3a46944637
4 changed files with 171 additions and 176 deletions

View file

@ -1,3 +1,12 @@
2005-07-13 Kristian Høgsberg <krh@redhat.com>
* src/cairo-meta-surface.c: (_cairo_meta_surface_replay): Use
the _cairo_surface_*() functions when replaying.
* src/cairo-ps-surface.c: Fold the "locate fallbacks" pass into
the postscript output pass, and add a simple, first implementation
of image fallbacks.
2005-07-13 Carl Worth <cworth@cworth.org>
* src/cairoint.h:

View file

@ -90,6 +90,7 @@ typedef struct _cairo_command_composite_trapezoids {
typedef struct _cairo_command_set_clip_region {
cairo_command_type_t type;
pixman_region16_t *region;
unsigned int serial;
} cairo_command_set_clip_region_t;
typedef struct _cairo_command_intersect_clip_path {

View file

@ -293,6 +293,8 @@ _cairo_meta_surface_set_clip_region (void *abstract_surface,
command->region = NULL;
}
command->serial = meta->base.current_clip_serial;
if (_cairo_array_append (&meta->commands, &command, 1) == NULL) {
if (command->region)
pixman_region_destroy (command->region);
@ -490,9 +492,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
command = elements[i];
switch (command->type) {
case CAIRO_COMMAND_COMPOSITE:
if (target->backend->composite == NULL)
break;
status = target->backend->composite
status = _cairo_surface_composite
(command->composite.operator,
&command->composite.src_pattern.base,
command->composite.mask_pattern_pointer,
@ -508,9 +508,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_FILL_RECTANGLES:
if (target->backend->fill_rectangles == NULL)
break;
status = target->backend->fill_rectangles
status = _cairo_surface_fill_rectangles
(target,
command->fill_rectangles.operator,
&command->fill_rectangles.color,
@ -519,9 +517,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS:
if (target->backend->composite_trapezoids == NULL)
break;
status = target->backend->composite_trapezoids
status = _cairo_surface_composite_trapezoids
(command->composite_trapezoids.operator,
&command->composite_trapezoids.pattern.base,
target,
@ -536,17 +532,19 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_SET_CLIP_REGION:
if (target->backend->set_clip_region == NULL)
break;
status = target->backend->set_clip_region
status = _cairo_surface_set_clip_region
(target,
command->set_clip_region.region);
command->set_clip_region.region,
command->set_clip_region.serial);
break;
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
/* XXX Meta surface clipping is broken and requires some
* cairo-gstate.c rewriting. Work around it for now. */
if (target->backend->intersect_clip_path == NULL)
break;
status = target->backend->intersect_clip_path
status = _cairo_surface_intersect_clip_path
(target,
command->intersect_clip_path.path_pointer,
command->intersect_clip_path.fill_rule,
@ -554,9 +552,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
if (target->backend->show_glyphs == NULL)
break;
status = target->backend->show_glyphs
status = _cairo_surface_show_glyphs
(command->show_glyphs.scaled_font,
command->show_glyphs.operator,
&command->show_glyphs.pattern.base,
@ -572,9 +568,12 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
case CAIRO_COMMAND_FILL_PATH:
/* XXX Meta surface fill_path is broken and requires some
* cairo-gstate.c rewriting. Work around it for now. */
if (target->backend->fill_path == NULL)
break;
status = target->backend->fill_path
status = _cairo_surface_fill_path
(command->fill_path.operator,
&command->fill_path.pattern.base,
target,

View file

@ -81,11 +81,6 @@ static cairo_int_status_t
_cairo_ps_surface_render_page (cairo_ps_surface_t *surface,
cairo_surface_t *page, int page_number);
static cairo_int_status_t
_cairo_ps_surface_render_fallbacks (cairo_ps_surface_t *surface,
cairo_surface_t *page);
static cairo_surface_t *
_cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
double width,
@ -550,11 +545,60 @@ _cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface)
return CAIRO_STATUS_SUCCESS;
}
typedef struct _cairo_ps_fallback_area cairo_ps_fallback_area_t;
struct _cairo_ps_fallback_area {
int x, y;
unsigned int width, height;
cairo_ps_fallback_area_t *next;
};
typedef struct _ps_output_surface {
cairo_surface_t base;
cairo_ps_surface_t *parent;
cairo_ps_fallback_area_t *fallback_areas;
} ps_output_surface_t;
static cairo_int_status_t
_ps_output_add_fallback_area (ps_output_surface_t *surface,
int x, int y,
unsigned int width,
unsigned int height)
{
cairo_ps_fallback_area_t *area;
/* FIXME: Do a better job here. Ideally, we would use a 32 bit
* region type, but probably just computing bounding boxes would
* also work fine. */
area = malloc (sizeof (cairo_ps_fallback_area_t));
if (area == NULL)
return CAIRO_STATUS_NO_MEMORY;
area->x = x;
area->y = y;
area->width = width;
area->height = height;
area->next = surface->fallback_areas;
surface->fallback_areas = area;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_ps_output_finish (void *abstract_surface)
{
ps_output_surface_t *surface = abstract_surface;
cairo_ps_fallback_area_t *area, *next;
for (area = surface->fallback_areas; area != NULL; area = next) {
next = area->next;
free (area);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
color_is_gray (cairo_color_t *color)
{
@ -564,6 +608,24 @@ color_is_gray (cairo_color_t *color)
fabs (color->red - color->blue) < epsilon);
}
static cairo_bool_t
pattern_is_translucent (cairo_pattern_t *abstract_pattern)
{
cairo_pattern_union_t *pattern;
pattern = (cairo_pattern_union_t *) abstract_pattern;
switch (pattern->base.type) {
case CAIRO_PATTERN_SOLID:
return pattern->solid.color.alpha < 0.9;
case CAIRO_PATTERN_SURFACE:
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL:
return FALSE;
}
ASSERT_NOT_REACHED;
}
/* PS Output - this section handles output of the parts of the meta
* surface we can render natively in PS. */
@ -872,6 +934,9 @@ _ps_output_composite_trapezoids (cairo_operator_t operator,
cairo_output_stream_t *stream = surface->parent->stream;
int i;
if (pattern_is_translucent (pattern))
return _ps_output_add_fallback_area (surface, x_dst, y_dst, width, height);
_cairo_output_stream_printf (stream,
"%% _ps_output_composite_trapezoids\n");
@ -1051,6 +1116,9 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
if (! _cairo_scaled_font_is_ft (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (pattern_is_translucent (pattern))
return _ps_output_add_fallback_area (surface, dest_x, dest_y, width, height);
_cairo_output_stream_printf (stream,
"%% _ps_output_show_glyphs\n");
@ -1137,7 +1205,7 @@ _ps_output_fill_path (cairo_operator_t operator,
static const cairo_surface_backend_t ps_output_backend = {
NULL, /* create_similar */
NULL, /* finish */
_ps_output_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
@ -1155,11 +1223,75 @@ static const cairo_surface_backend_t ps_output_backend = {
_ps_output_fill_path
};
static cairo_int_status_t
_ps_output_render_fallbacks (cairo_surface_t *surface,
cairo_surface_t *page)
{
ps_output_surface_t *ps_output;
cairo_surface_t *image;
cairo_int_status_t status;
cairo_matrix_t matrix;
int width, height;
ps_output = (ps_output_surface_t *) surface;
if (ps_output->fallback_areas == NULL)
return CAIRO_STATUS_SUCCESS;
width = ps_output->parent->width * ps_output->parent->x_dpi / 72;
height = ps_output->parent->height * ps_output->parent->y_dpi / 72;
image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
if (image == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_surface_fill_rectangle (image,
CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_WHITE,
0, 0, width, height);
if (status)
goto bail;
status = _cairo_meta_surface_replay (page, image);
if (status)
goto bail;
matrix.xx = 1;
matrix.xy = 0;
matrix.yx = 0;
matrix.yy = 1;
matrix.x0 = 0;
matrix.y0 = 0;
status = emit_image (ps_output->parent,
(cairo_image_surface_t *) image, &matrix);
bail:
cairo_surface_destroy (image);
return status;
}
static cairo_surface_t *
_ps_output_surface_create (cairo_ps_surface_t *parent)
{
ps_output_surface_t *ps_output;
ps_output = malloc (sizeof (ps_output_surface_t));
if (ps_output == NULL)
return NULL;
_cairo_surface_init (&ps_output->base, &ps_output_backend);
ps_output->parent = parent;
ps_output->fallback_areas = NULL;
return &ps_output->base;
}
static cairo_int_status_t
_cairo_ps_surface_render_page (cairo_ps_surface_t *surface,
cairo_surface_t *page, int page_number)
{
ps_output_surface_t *ps_output;
cairo_surface_t *ps_output;
cairo_int_status_t status;
_cairo_output_stream_printf (surface->stream,
@ -1167,16 +1299,15 @@ _cairo_ps_surface_render_page (cairo_ps_surface_t *surface,
"gsave\n",
page_number);
ps_output = malloc (sizeof (ps_output_surface_t));
ps_output = _ps_output_surface_create (surface);
if (ps_output == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_surface_init (&ps_output->base, &ps_output_backend);
ps_output->parent = surface;
status = _cairo_meta_surface_replay (page, &ps_output->base);
cairo_surface_destroy (&ps_output->base);
status = _cairo_meta_surface_replay (page, ps_output);
_cairo_ps_surface_render_fallbacks (surface, page);
_ps_output_render_fallbacks (ps_output, page);
cairo_surface_destroy (ps_output);
_cairo_output_stream_printf (surface->stream,
"showpage\n"
@ -1185,148 +1316,3 @@ _cairo_ps_surface_render_page (cairo_ps_surface_t *surface,
return status;
}
typedef struct _cairo_ps_fallback_area cairo_ps_fallback_area_t;
struct _cairo_ps_fallback_area {
/* area */
cairo_ps_fallback_area_t *next;
};
typedef struct _cairo_ps_fallback_info cairo_ps_fallback_info_t;
struct _cairo_ps_fallback_info {
cairo_ps_fallback_area_t *fallback_areas;
};
/* XXX: This code is not compiling correctly (missing return values),
* but also appears to not be used currently. I'm turning it off for
* now. */
#if 0
static cairo_int_status_t
_cairo_ps_fallback_info_add_area (cairo_ps_fallback_info_t *info,
int x, int y,
unsigned int width,
unsigned int height)
{
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
_pattern_is_translucent (cairo_pattern_t *abstract_pattern)
{
cairo_pattern_union_t *pattern;
pattern = (cairo_pattern_union_t *) abstract_pattern;
switch (pattern->base.type) {
case CAIRO_PATTERN_SOLID:
return pattern->solid.color.alpha < 0.999;
case CAIRO_PATTERN_SURFACE:
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL:
return FALSE;
}
ASSERT_NOT_REACHED;
return FALSE;
}
static cairo_int_status_t
_ps_locate_fallbacks_composite (cairo_operator_t operator,
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)
{
}
static cairo_int_status_t
_ps_locate_fallbacks_fill_rectangles (void *abstract_surface,
cairo_operator_t operator,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
}
static cairo_int_status_t
_ps_locate_fallbacks_composite_trapezoids (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
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_fallback_info_t *info;
info = abstract_dst;
if (_pattern_is_translucent (pattern))
_cairo_ps_fallback_info_add_area (info, x_dst, y_dst, width, height);
}
static cairo_int_status_t
_ps_locate_fallbacks_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_surface,
int source_x,
int source_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_ps_locate_fallbacks_fill_path (cairo_operator_t operator,
cairo_pattern_t *pattern,
void *abstract_dst,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance)
{
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t ps_locate_fallbacks_backend = {
NULL, /* create_similar */
NULL, /* finish */
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
_ps_locate_fallbacks_composite,
_ps_locate_fallbacks_fill_rectangles,
_ps_locate_fallbacks_composite_trapezoids,
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_region */
NULL, /* intersect_clip_path */
NULL, /* get_extents */
_ps_locate_fallbacks_show_glyphs,
_ps_locate_fallbacks_fill_path
};
#endif
static cairo_int_status_t
_cairo_ps_surface_render_fallbacks (cairo_ps_surface_t *surface,
cairo_surface_t *page)
{
return CAIRO_STATUS_SUCCESS;
}