[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