[cairo-commit] cairo/src cairo-ps-surface.c,1.51,1.52
Keith Packard
commit at pdx.freedesktop.org
Sun Oct 9 20:40:14 PDT 2005
Committed by: keithp
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv16677/src
Modified Files:
cairo-ps-surface.c
Log Message:
2005-10-09 Keith Packard <keithp at keithp.com>
reviewed by: cworth
* src/cairo-ps-surface.c: (_ps_output_add_fallback_area),
(_ps_output_finish), (format_is_translucent),
(surface_is_translucent), (gradient_is_translucent),
(pattern_is_translucent), (operator_always_opaque),
(operator_always_translucent), (color_operation_needs_fallback),
(pattern_operation_needs_fallback), (_ps_output_fill_rectangles),
(_ps_output_composite_trapezoids), (_ps_output_show_glyphs),
(_ps_output_fill_path), (_ps_output_render_fallbacks),
(_ps_output_surface_create):
Switch fallback from list of rects to region.
Check operator and patterns for non-ps drawing ability.
Operators can sometimes be always opaque, independent of
the pattern, sometimes always translucent, independent of
the pattern and sometimes depend on whether is
translucent.
Index: cairo-ps-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ps-surface.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- cairo-ps-surface.c 9 Oct 2005 21:28:15 -0000 1.51
+++ cairo-ps-surface.c 10 Oct 2005 03:40:12 -0000 1.52
@@ -34,6 +34,7 @@
* Contributor(s):
* Carl D. Worth <cworth at cworth.org>
* Kristian Høgsberg <krh at redhat.com>
+ * Keith Packard <keithp at keithp.com>
*/
#include "cairoint.h"
@@ -572,17 +573,10 @@
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;
+ pixman_region16_t *fallback_region;
} ps_output_surface_t;
static cairo_int_status_t
@@ -591,23 +585,11 @@
unsigned int width,
unsigned int height)
{
- cairo_ps_fallback_area_t *area;
+ if (!surface->fallback_region)
+ surface->fallback_region = pixman_region_create ();
- /* 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;
+ pixman_region_union_rect (surface->fallback_region, surface->fallback_region,
+ x, y, width, height);
return CAIRO_STATUS_SUCCESS;
}
@@ -616,12 +598,9 @@
_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);
- }
+ if (surface->fallback_region)
+ pixman_region_destroy (surface->fallback_region);
return CAIRO_STATUS_SUCCESS;
}
@@ -642,24 +621,152 @@
}
static cairo_bool_t
-pattern_is_translucent (cairo_pattern_t *abstract_pattern)
+format_is_translucent (cairo_format_t format)
{
- cairo_pattern_union_t *pattern;
+ switch (format) {
+ case CAIRO_FORMAT_ARGB32:
+ return TRUE;
+ case CAIRO_FORMAT_RGB24:
+ return FALSE;
+ case CAIRO_FORMAT_A8:
+ return TRUE;
+ case CAIRO_FORMAT_A1:
+ return TRUE;
+ }
+ return TRUE;
+}
+
+static cairo_bool_t
+surface_is_translucent (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 TRUE;
+}
+
+static cairo_bool_t
+gradient_is_translucent (const cairo_gradient_pattern_t *gradient)
+{
+ return TRUE; /* 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;
+#endif
+}
+
+static cairo_bool_t
+pattern_is_translucent (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_SOLID:
return color_is_translucent (&pattern->solid.color);
case CAIRO_PATTERN_SURFACE:
+ return surface_is_translucent (pattern->surface.surface);
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL:
- return FALSE;
+ return gradient_is_translucent (&pattern->gradient.base);
}
ASSERT_NOT_REACHED;
return FALSE;
}
+static cairo_bool_t
+operator_always_opaque (cairo_operator_t operator)
+{
+ switch (operator) {
+ case CAIRO_OPERATOR_CLEAR:
+
+ case CAIRO_OPERATOR_SOURCE:
+ return TRUE;
+
+ case CAIRO_OPERATOR_OVER:
+ case CAIRO_OPERATOR_IN:
+ case CAIRO_OPERATOR_OUT:
+ case CAIRO_OPERATOR_ATOP:
+ return FALSE;
+
+ case CAIRO_OPERATOR_DEST:
+ return TRUE;
+
+ case CAIRO_OPERATOR_DEST_OVER:
+ case CAIRO_OPERATOR_DEST_IN:
+ case CAIRO_OPERATOR_DEST_OUT:
+ case CAIRO_OPERATOR_DEST_ATOP:
+ return FALSE;
+
+ case CAIRO_OPERATOR_XOR:
+ case CAIRO_OPERATOR_ADD:
+ case CAIRO_OPERATOR_SATURATE:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+static cairo_bool_t
+operator_always_translucent (cairo_operator_t operator)
+{
+ switch (operator) {
+ case CAIRO_OPERATOR_CLEAR:
+
+ case CAIRO_OPERATOR_SOURCE:
+ return FALSE;
+
+ case CAIRO_OPERATOR_OVER:
+ case CAIRO_OPERATOR_IN:
+ case CAIRO_OPERATOR_OUT:
+ case CAIRO_OPERATOR_ATOP:
+ return FALSE;
+
+ case CAIRO_OPERATOR_DEST:
+ return FALSE;
+
+ case CAIRO_OPERATOR_DEST_OVER:
+ case CAIRO_OPERATOR_DEST_IN:
+ case CAIRO_OPERATOR_DEST_OUT:
+ case CAIRO_OPERATOR_DEST_ATOP:
+ return FALSE;
+
+ case CAIRO_OPERATOR_XOR:
+ case CAIRO_OPERATOR_ADD:
+ case CAIRO_OPERATOR_SATURATE:
+ return TRUE;
+ }
+ return TRUE;
+}
+
+static cairo_bool_t
+color_operation_needs_fallback (cairo_operator_t operator,
+ const cairo_color_t *color)
+{
+ if (operator_always_opaque (operator))
+ return FALSE;
+ if (operator_always_translucent (operator))
+ return TRUE;
+ return color_is_translucent (color);
+}
+
+static cairo_bool_t
+pattern_operation_needs_fallback (cairo_operator_t operator,
+ const cairo_pattern_t *pattern)
+{
+ if (operator_always_opaque (operator))
+ return FALSE;
+ if (operator_always_translucent (operator))
+ return TRUE;
+ return pattern_is_translucent (pattern);
+}
+
/* PS Output - this section handles output of the parts of the meta
* surface we can render natively in PS. */
@@ -946,7 +1053,7 @@
if (!num_rects)
return CAIRO_STATUS_SUCCESS;
- if (color_is_translucent (color)) {
+ if (color_operation_needs_fallback (operator, color)) {
int min_x = rects[0].x;
int min_y = rects[0].y;
int max_x = rects[0].x + rects[0].width;
@@ -1008,7 +1115,7 @@
cairo_output_stream_t *stream = surface->parent->stream;
int i;
- if (pattern_is_translucent (pattern))
+ if (pattern_operation_needs_fallback (operator, pattern))
return _ps_output_add_fallback_area (surface, x_dst, y_dst, width, height);
_cairo_output_stream_printf (stream,
@@ -1189,7 +1296,7 @@
if (! _cairo_scaled_font_is_ft (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
- if (pattern_is_translucent (pattern))
+ if (pattern_operation_needs_fallback (operator, pattern))
return _ps_output_add_fallback_area (surface, dest_x, dest_y, width, height);
_cairo_output_stream_printf (stream,
@@ -1242,7 +1349,7 @@
ps_output_path_info_t info;
const char *ps_operator;
- if (pattern_is_translucent (pattern))
+ if (pattern_operation_needs_fallback (operator, pattern))
return _ps_output_add_fallback_area (surface,
0, 0,
surface->parent->width,
@@ -1311,7 +1418,7 @@
int width, height;
ps_output = (ps_output_surface_t *) surface;
- if (ps_output->fallback_areas == NULL)
+ if (ps_output->fallback_region == NULL)
return CAIRO_STATUS_SUCCESS;
width = ps_output->parent->width * ps_output->parent->x_dpi / 72;
@@ -1361,7 +1468,7 @@
_cairo_surface_init (&ps_output->base, &ps_output_backend);
ps_output->parent = parent;
- ps_output->fallback_areas = NULL;
+ ps_output->fallback_region = NULL;
return &ps_output->base;
}
More information about the cairo-commit
mailing list