mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-09 07:18:04 +02:00
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:
parent
aafc2e7497
commit
3a46944637
4 changed files with 171 additions and 176 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue