[cairo-commit] cairo/src cairo-gstate.c, 1.189,
1.190 cairo-surface-fallback.c, 1.1, 1.2 cairoint.h, 1.235, 1.236
Carl Worth
commit at pdx.freedesktop.org
Tue Dec 20 09:37:18 PST 2005
Committed by: cworth
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv23532/src
Modified Files:
cairo-gstate.c cairo-surface-fallback.c cairoint.h
Log Message:
2005-12-20 Carl Worth <cworth at cworth.org>
* src/cairoint.h:
* src/cairo-gstate.c: (_cairo_gstate_get_antialias):
* src/cairo-surface-fallback.c: (_create_composite_mask_pattern),
(_clip_and_composite_with_mask), (_clip_and_composite_combine),
(_clip_and_composite_source), (_cairo_rectangle_empty),
(_clip_and_composite), (_composite_trap_region),
(_composite_traps_draw_func), (_clip_and_composite_trapezoids),
(_cairo_surface_fallback_paint), (_cairo_surface_fallback_mask),
(_cairo_surface_fallback_stroke), (_cairo_surface_fallback_fill),
(_cairo_surface_fallback_show_glyphs): Move more fallback code
from cairo-gstate.c to cairo-surface-fallback.c where it
belongs. In the process, clean up the function names a bit and
make the whole mess static.
Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.189
retrieving revision 1.190
diff -u -d -r1.189 -r1.190
--- cairo-gstate.c 19 Dec 2005 23:08:05 -0000 1.189
+++ cairo-gstate.c 20 Dec 2005 17:37:15 -0000 1.190
@@ -838,300 +838,6 @@
return FALSE;
}
-static cairo_status_t
-_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
- cairo_clip_t *clip,
- cairo_draw_func_t draw_func,
- void *draw_closure,
- cairo_surface_t *dst,
- const cairo_rectangle_t *extents)
-{
- cairo_surface_t *mask;
- cairo_status_t status;
-
- mask = cairo_surface_create_similar (dst,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height);
- if (mask->status)
- return CAIRO_STATUS_NO_MEMORY;
-
- status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD,
- NULL, mask,
- extents->x, extents->y,
- extents);
- if (status)
- goto CLEANUP_SURFACE;
-
- if (clip && clip->surface)
- status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
- mask,
- extents->x, extents->y,
- extents);
- if (status)
- goto CLEANUP_SURFACE;
-
- _cairo_pattern_init_for_surface (mask_pattern, mask);
-
- CLEANUP_SURFACE:
- cairo_surface_destroy (mask);
-
- return status;
-}
-
-/* Handles compositing with a clip surface when the operator allows
- * us to combine the clip with the mask
- */
-static cairo_status_t
-_cairo_gstate_clip_and_composite_with_mask (cairo_clip_t *clip,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_draw_func_t draw_func,
- void *draw_closure,
- cairo_surface_t *dst,
- const cairo_rectangle_t *extents)
-{
- cairo_surface_pattern_t mask_pattern;
- cairo_status_t status;
-
- status = _create_composite_mask_pattern (&mask_pattern,
- clip,
- draw_func, draw_closure,
- dst, extents);
- if (status)
- return status;
-
- status = _cairo_surface_composite (op,
- src, &mask_pattern.base, dst,
- extents->x, extents->y,
- 0, 0,
- extents->x, extents->y,
- extents->width, extents->height);
-
- _cairo_pattern_fini (&mask_pattern.base);
-
- return status;
-}
-
-/* Handles compositing with a clip surface when we have to do the operation
- * in two pieces and combine them together.
- */
-static cairo_status_t
-_cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_draw_func_t draw_func,
- void *draw_closure,
- cairo_surface_t *dst,
- const cairo_rectangle_t *extents)
-{
- cairo_surface_t *intermediate;
- cairo_surface_pattern_t dst_pattern;
- cairo_surface_pattern_t intermediate_pattern;
- cairo_status_t status;
-
- /* We'd be better off here creating a surface identical in format
- * to dst, but we have no way of getting that information.
- * A CAIRO_CONTENT_CLONE or something might be useful.
- * cairo_surface_create_similar() also unnecessarily clears the surface.
- */
- intermediate = cairo_surface_create_similar (dst,
- CAIRO_CONTENT_COLOR_ALPHA,
- extents->width,
- extents->height);
- if (intermediate->status)
- return CAIRO_STATUS_NO_MEMORY;
-
- /* Initialize the intermediate surface from the destination surface
- */
- _cairo_pattern_init_for_surface (&dst_pattern, dst);
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
- &dst_pattern.base, NULL, intermediate,
- extents->x, extents->y,
- 0, 0,
- 0, 0,
- extents->width, extents->height);
-
- _cairo_pattern_fini (&dst_pattern.base);
-
- if (status)
- goto CLEANUP_SURFACE;
-
- status = (*draw_func) (draw_closure, op,
- src, intermediate,
- extents->x, extents->y,
- extents);
- if (status)
- goto CLEANUP_SURFACE;
-
- /* Combine that with the clip
- */
- status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_IN,
- intermediate,
- extents->x, extents->y,
- extents);
- if (status)
- goto CLEANUP_SURFACE;
-
- /* Punch the clip out of the destination
- */
- status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_OUT,
- dst,
- 0, 0,
- extents);
- if (status)
- goto CLEANUP_SURFACE;
-
- /* Now add the two results together
- */
- _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
- &intermediate_pattern.base, NULL, dst,
- 0, 0,
- 0, 0,
- extents->x, extents->y,
- extents->width, extents->height);
-
- _cairo_pattern_fini (&intermediate_pattern.base);
-
- CLEANUP_SURFACE:
- cairo_surface_destroy (intermediate);
-
- return status;
-}
-
-/* Handles compositing for CAIRO_OPERATOR_SOURCE, which is special; it's
- * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
- */
-static cairo_status_t
-_cairo_gstate_clip_and_composite_source (cairo_clip_t *clip,
- cairo_pattern_t *src,
- cairo_draw_func_t draw_func,
- void *draw_closure,
- cairo_surface_t *dst,
- const cairo_rectangle_t *extents)
-{
- cairo_surface_pattern_t mask_pattern;
- cairo_status_t status;
-
- /* Create a surface that is mask IN clip
- */
- status = _create_composite_mask_pattern (&mask_pattern,
- clip,
- draw_func, draw_closure,
- dst, extents);
- if (status)
- return status;
-
- /* Compute dest' = dest OUT (mask IN clip)
- */
- status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
- &mask_pattern.base, NULL, dst,
- 0, 0,
- 0, 0,
- extents->x, extents->y,
- extents->width, extents->height);
-
- if (status)
- goto CLEANUP_MASK_PATTERN;
-
- /* Now compute (src IN (mask IN clip)) ADD dest'
- */
- status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
- src, &mask_pattern.base, dst,
- extents->x, extents->y,
- 0, 0,
- extents->x, extents->y,
- extents->width, extents->height);
-
- CLEANUP_MASK_PATTERN:
- _cairo_pattern_fini (&mask_pattern.base);
- return status;
-}
-
-static int
-_cairo_rectangle_empty (const cairo_rectangle_t *rect)
-{
- return rect->width == 0 || rect->height == 0;
-}
-
-/**
- * _cairo_gstate_clip_and_composite:
- * @gstate: a #cairo_gstate_t
- * @op: the operator to draw with
- * @src: source pattern
- * @draw_func: function that can be called to draw with the mask onto a surface.
- * @draw_closure: data to pass to @draw_func.
- * @dst: destination surface
- * @extents: rectangle holding a bounding box for the operation; this
- * rectangle will be used as the size for the temporary
- * surface.
- *
- * When there is a surface clip, we typically need to create an intermediate
- * surface. This function handles the logic of creating a temporary surface
- * drawing to it, then compositing the result onto the target surface.
- *
- * @draw_func is to called to draw the mask; it will be called no more
- * than once.
- *
- * Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded.
- **/
-cairo_status_t
-_cairo_gstate_clip_and_composite (cairo_clip_t *clip,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_draw_func_t draw_func,
- void *draw_closure,
- cairo_surface_t *dst,
- const cairo_rectangle_t *extents)
-{
- cairo_pattern_union_t solid_pattern;
- cairo_status_t status;
-
- if (_cairo_rectangle_empty (extents))
- /* Nothing to do */
- return CAIRO_STATUS_SUCCESS;
-
- if (op == CAIRO_OPERATOR_CLEAR) {
- _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
- src = &solid_pattern.base;
- op = CAIRO_OPERATOR_DEST_OUT;
- }
-
- if ((clip && clip->surface) || op == CAIRO_OPERATOR_SOURCE)
- {
- if (op == CAIRO_OPERATOR_SOURCE)
- status = _cairo_gstate_clip_and_composite_source (clip,
- src,
- draw_func, draw_closure,
- dst, extents);
- else if (_cairo_operator_bounded_by_mask (op))
- status = _cairo_gstate_clip_and_composite_with_mask (clip, op,
- src,
- draw_func, draw_closure,
- dst, extents);
- else
- status = _cairo_gstate_clip_and_composite_combine (clip, op,
- src,
- draw_func, draw_closure,
- dst, extents);
- }
- else
- {
- status = (*draw_func) (draw_closure, op,
- src, dst,
- 0, 0,
- extents);
- }
-
- if (src == &solid_pattern.base)
- _cairo_pattern_fini (&solid_pattern.base);
-
- return status;
-}
-
cairo_status_t
_cairo_gstate_mask (cairo_gstate_t *gstate,
cairo_pattern_t *mask)
@@ -1274,249 +980,6 @@
}
}
-/* Composites a region representing a set of trapezoids.
- */
-static cairo_status_t
-_composite_trap_region (cairo_clip_t *clip,
- cairo_pattern_t *src,
- cairo_operator_t op,
- cairo_surface_t *dst,
- pixman_region16_t *trap_region,
- cairo_rectangle_t *extents)
-{
- cairo_status_t status;
- cairo_pattern_union_t solid_pattern;
- cairo_pattern_union_t mask;
- int num_rects = pixman_region_num_rects (trap_region);
- unsigned int clip_serial;
- cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
-
- if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
- _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
- src = &solid_pattern.base;
- op = CAIRO_OPERATOR_DEST_OUT;
- }
-
- if (num_rects == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (num_rects > 1) {
- if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- clip_serial = _cairo_surface_allocate_clip_serial (dst);
- status = _cairo_surface_set_clip_region (dst,
- trap_region,
- clip_serial);
- if (status)
- return status;
- }
-
- if (clip_surface)
- _cairo_pattern_init_for_surface (&mask.surface, clip_surface);
-
- status = _cairo_surface_composite (op,
- src,
- clip_surface ? &mask.base : NULL,
- dst,
- extents->x, extents->y,
- extents->x - (clip_surface ? clip->surface_rect.x : 0),
- extents->y - (clip_surface ? clip->surface_rect.y : 0),
- extents->x, extents->y,
- extents->width, extents->height);
-
- if (clip_surface)
- _cairo_pattern_fini (&mask.base);
-
- if (src == &solid_pattern.base)
- _cairo_pattern_fini (&solid_pattern.base);
-
- return status;
-}
-
-typedef struct {
- cairo_traps_t *traps;
- cairo_antialias_t antialias;
-} cairo_composite_traps_info_t;
-
-static cairo_status_t
-_composite_traps_draw_func (void *closure,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_surface_t *dst,
- int dst_x,
- int dst_y,
- const cairo_rectangle_t *extents)
-{
- cairo_composite_traps_info_t *info = closure;
- cairo_pattern_union_t pattern;
- cairo_status_t status;
-
- if (dst_x != 0 || dst_y != 0)
- _cairo_traps_translate (info->traps, - dst_x, - dst_y);
-
- _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
- if (!src)
- src = &pattern.base;
-
- status = _cairo_surface_composite_trapezoids (op,
- src, dst, info->antialias,
- extents->x, extents->y,
- extents->x - dst_x, extents->y - dst_y,
- extents->width, extents->height,
- info->traps->traps,
- info->traps->num_traps);
- _cairo_pattern_fini (&pattern.base);
-
- return status;
-}
-
-/* Warning: This call modifies the coordinates of traps */
-cairo_status_t
-_cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
- cairo_operator_t op,
- cairo_surface_t *dst,
- cairo_traps_t *traps,
- cairo_clip_t *clip,
- cairo_antialias_t antialias)
-{
- cairo_status_t status;
- pixman_region16_t *trap_region;
- pixman_region16_t *clear_region = NULL;
- cairo_rectangle_t extents;
- cairo_composite_traps_info_t traps_info;
-
- if (traps->num_traps == 0)
- return CAIRO_STATUS_SUCCESS;
-
- status = _cairo_traps_extract_region (traps, &trap_region);
- if (status)
- return status;
-
- if (_cairo_operator_bounded_by_mask (op))
- {
- if (trap_region) {
- status = _cairo_clip_intersect_to_region (clip, trap_region);
- _cairo_region_extents_rectangle (trap_region, &extents);
- } else {
- cairo_box_t trap_extents;
- _cairo_traps_extents (traps, &trap_extents);
- _cairo_box_round_to_rectangle (&trap_extents, &extents);
- status = _cairo_clip_intersect_to_rectangle (clip, &extents);
- }
- }
- else
- {
- cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
-
- status = _cairo_surface_get_extents (dst, &extents);
- if (status)
- return status;
-
- if (trap_region && !clip_surface) {
- /* If we optimize drawing with an unbounded operator to
- * _cairo_surface_fill_rectangles() or to drawing with a
- * clip region, then we have an additional region to clear.
- */
- status = _cairo_surface_get_extents (dst, &extents);
- if (status)
- return status;
-
- clear_region = _cairo_region_create_from_rectangle (&extents);
- status = _cairo_clip_intersect_to_region (clip, clear_region);
- if (status)
- return status;
-
- _cairo_region_extents_rectangle (clear_region, &extents);
-
- if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
- return CAIRO_STATUS_NO_MEMORY;
-
- if (!pixman_region_not_empty (clear_region)) {
- pixman_region_destroy (clear_region);
- clear_region = NULL;
- }
- } else {
- status = _cairo_clip_intersect_to_rectangle (clip, &extents);
- if (status)
- return status;
- }
- }
-
- if (status)
- goto out;
-
- if (trap_region)
- {
- cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
-
- if ((src->type == CAIRO_PATTERN_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
- !clip_surface)
- {
- const cairo_color_t *color;
-
- if (op == CAIRO_OPERATOR_CLEAR)
- color = CAIRO_COLOR_TRANSPARENT;
- else
- color = &((cairo_solid_pattern_t *)src)->color;
-
- /* Solid rectangles special case */
- status = _cairo_surface_fill_region (dst, op, color, trap_region);
- if (!status && clear_region)
- status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- clear_region);
-
- goto out;
- }
-
- if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
- !clip_surface)
- {
- /* For a simple rectangle, we can just use composite(), for more
- * rectangles, we have to set a clip region. The cost of rasterizing
- * trapezoids is pretty high for most backends currently, so it's
- * worthwhile even if a region is needed.
- *
- * If we have a clip surface, we set it as the mask; this only works
- * for bounded operators other than SOURCE; for unbounded operators,
- * clip and mask cannot be interchanged. For SOURCE, the operator
- * as implemented by the backends is different in it's handling
- * of the mask then what we want.
- *
- * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
- * more than rectangle and the destination doesn't support clip
- * regions. In that case, we fall through.
- */
- status = _composite_trap_region (clip, src, op, dst,
- trap_region, &extents);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- {
- if (!status && clear_region)
- status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- clear_region);
- goto out;
- }
- }
- }
-
- traps_info.traps = traps;
- traps_info.antialias = antialias;
-
- status = _cairo_gstate_clip_and_composite (clip, op, src,
- _composite_traps_draw_func, &traps_info,
- dst, &extents);
-
- out:
- if (trap_region)
- pixman_region_destroy (trap_region);
- if (clear_region)
- pixman_region_destroy (clear_region);
-
- return status;
-}
-
cairo_status_t
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
@@ -2050,4 +1513,3 @@
{
return gstate->antialias;
}
-
Index: cairo-surface-fallback.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface-fallback.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cairo-surface-fallback.c 20 Dec 2005 06:45:42 -0000 1.1
+++ cairo-surface-fallback.c 20 Dec 2005 17:37:15 -0000 1.2
@@ -98,6 +98,551 @@
state->image_extra);
}
+typedef cairo_status_t (*cairo_draw_func_t) (void *closure,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents);
+
+static cairo_status_t
+_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
+ cairo_clip_t *clip,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ cairo_surface_t *mask;
+ cairo_status_t status;
+
+ mask = cairo_surface_create_similar (dst,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height);
+ if (mask->status)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD,
+ NULL, mask,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ if (clip && clip->surface)
+ status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN,
+ mask,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ _cairo_pattern_init_for_surface (mask_pattern, mask);
+
+ CLEANUP_SURFACE:
+ cairo_surface_destroy (mask);
+
+ return status;
+}
+
+/* Handles compositing with a clip surface when the operator allows
+ * us to combine the clip with the mask
+ */
+static cairo_status_t
+_clip_and_composite_with_mask (cairo_clip_t *clip,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ cairo_surface_pattern_t mask_pattern;
+ cairo_status_t status;
+
+ status = _create_composite_mask_pattern (&mask_pattern,
+ clip,
+ draw_func, draw_closure,
+ dst, extents);
+ if (status)
+ return status;
+
+ status = _cairo_surface_composite (op,
+ src, &mask_pattern.base, dst,
+ extents->x, extents->y,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&mask_pattern.base);
+
+ return status;
+}
+
+/* Handles compositing with a clip surface when we have to do the operation
+ * in two pieces and combine them together.
+ */
+static cairo_status_t
+_clip_and_composite_combine (cairo_clip_t *clip,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ cairo_surface_t *intermediate;
+ cairo_surface_pattern_t dst_pattern;
+ cairo_surface_pattern_t intermediate_pattern;
+ cairo_status_t status;
+
+ /* We'd be better off here creating a surface identical in format
+ * to dst, but we have no way of getting that information.
+ * A CAIRO_CONTENT_CLONE or something might be useful.
+ * cairo_surface_create_similar() also unnecessarily clears the surface.
+ */
+ intermediate = cairo_surface_create_similar (dst,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ extents->width,
+ extents->height);
+ if (intermediate->status)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ /* Initialize the intermediate surface from the destination surface
+ */
+ _cairo_pattern_init_for_surface (&dst_pattern, dst);
+
+ status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+ &dst_pattern.base, NULL, intermediate,
+ extents->x, extents->y,
+ 0, 0,
+ 0, 0,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&dst_pattern.base);
+
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ status = (*draw_func) (draw_closure, op,
+ src, intermediate,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ /* Combine that with the clip
+ */
+ status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_IN,
+ intermediate,
+ extents->x, extents->y,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ /* Punch the clip out of the destination
+ */
+ status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_DEST_OUT,
+ dst,
+ 0, 0,
+ extents);
+ if (status)
+ goto CLEANUP_SURFACE;
+
+ /* Now add the two results together
+ */
+ _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
+
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+ &intermediate_pattern.base, NULL, dst,
+ 0, 0,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ _cairo_pattern_fini (&intermediate_pattern.base);
+
+ CLEANUP_SURFACE:
+ cairo_surface_destroy (intermediate);
+
+ return status;
+}
+
+/* Handles compositing for CAIRO_OPERATOR_SOURCE, which is special; it's
+ * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
+ */
+static cairo_status_t
+_clip_and_composite_source (cairo_clip_t *clip,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ cairo_surface_pattern_t mask_pattern;
+ cairo_status_t status;
+
+ /* Create a surface that is mask IN clip
+ */
+ status = _create_composite_mask_pattern (&mask_pattern,
+ clip,
+ draw_func, draw_closure,
+ dst, extents);
+ if (status)
+ return status;
+
+ /* Compute dest' = dest OUT (mask IN clip)
+ */
+ status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
+ &mask_pattern.base, NULL, dst,
+ 0, 0,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ if (status)
+ goto CLEANUP_MASK_PATTERN;
+
+ /* Now compute (src IN (mask IN clip)) ADD dest'
+ */
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+ src, &mask_pattern.base, dst,
+ extents->x, extents->y,
+ 0, 0,
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ CLEANUP_MASK_PATTERN:
+ _cairo_pattern_fini (&mask_pattern.base);
+ return status;
+}
+
+static int
+_cairo_rectangle_empty (const cairo_rectangle_t *rect)
+{
+ return rect->width == 0 || rect->height == 0;
+}
+
+/**
+ * _clip_and_composite:
+ * @clip: a #cairo_clip_t
+ * @op: the operator to draw with
+ * @src: source pattern
+ * @draw_func: function that can be called to draw with the mask onto a surface.
+ * @draw_closure: data to pass to @draw_func.
+ * @dst: destination surface
+ * @extents: rectangle holding a bounding box for the operation; this
+ * rectangle will be used as the size for the temporary
+ * surface.
+ *
+ * When there is a surface clip, we typically need to create an intermediate
+ * surface. This function handles the logic of creating a temporary surface
+ * drawing to it, then compositing the result onto the target surface.
+ *
+ * @draw_func is to called to draw the mask; it will be called no more
+ * than once.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if the drawing succeeded.
+ **/
+static cairo_status_t
+_clip_and_composite (cairo_clip_t *clip,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_draw_func_t draw_func,
+ void *draw_closure,
+ cairo_surface_t *dst,
+ const cairo_rectangle_t *extents)
+{
+ cairo_pattern_union_t solid_pattern;
+ cairo_status_t status;
+
+ if (_cairo_rectangle_empty (extents))
+ /* Nothing to do */
+ return CAIRO_STATUS_SUCCESS;
+
+ if (op == CAIRO_OPERATOR_CLEAR) {
+ _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
+ src = &solid_pattern.base;
+ op = CAIRO_OPERATOR_DEST_OUT;
+ }
+
+ if ((clip && clip->surface) || op == CAIRO_OPERATOR_SOURCE)
+ {
+ if (op == CAIRO_OPERATOR_SOURCE)
+ status = _clip_and_composite_source (clip,
+ src,
+ draw_func, draw_closure,
+ dst, extents);
+ else if (_cairo_operator_bounded_by_mask (op))
+ status = _clip_and_composite_with_mask (clip, op,
+ src,
+ draw_func, draw_closure,
+ dst, extents);
+ else
+ status = _clip_and_composite_combine (clip, op,
+ src,
+ draw_func, draw_closure,
+ dst, extents);
+ }
+ else
+ {
+ status = (*draw_func) (draw_closure, op,
+ src, dst,
+ 0, 0,
+ extents);
+ }
+
+ if (src == &solid_pattern.base)
+ _cairo_pattern_fini (&solid_pattern.base);
+
+ return status;
+}
+
+/* Composites a region representing a set of trapezoids.
+ */
+static cairo_status_t
+_composite_trap_region (cairo_clip_t *clip,
+ cairo_pattern_t *src,
+ cairo_operator_t op,
+ cairo_surface_t *dst,
+ pixman_region16_t *trap_region,
+ cairo_rectangle_t *extents)
+{
+ cairo_status_t status;
+ cairo_pattern_union_t solid_pattern;
+ cairo_pattern_union_t mask;
+ int num_rects = pixman_region_num_rects (trap_region);
+ unsigned int clip_serial;
+ cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+
+ if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
+ _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
+ src = &solid_pattern.base;
+ op = CAIRO_OPERATOR_DEST_OUT;
+ }
+
+ if (num_rects == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (num_rects > 1) {
+ if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ clip_serial = _cairo_surface_allocate_clip_serial (dst);
+ status = _cairo_surface_set_clip_region (dst,
+ trap_region,
+ clip_serial);
+ if (status)
+ return status;
+ }
+
+ if (clip_surface)
+ _cairo_pattern_init_for_surface (&mask.surface, clip_surface);
+
+ status = _cairo_surface_composite (op,
+ src,
+ clip_surface ? &mask.base : NULL,
+ dst,
+ extents->x, extents->y,
+ extents->x - (clip_surface ? clip->surface_rect.x : 0),
+ extents->y - (clip_surface ? clip->surface_rect.y : 0),
+ extents->x, extents->y,
+ extents->width, extents->height);
+
+ if (clip_surface)
+ _cairo_pattern_fini (&mask.base);
+
+ if (src == &solid_pattern.base)
+ _cairo_pattern_fini (&solid_pattern.base);
+
+ return status;
+}
+
+typedef struct {
+ cairo_traps_t *traps;
+ cairo_antialias_t antialias;
+} cairo_composite_traps_info_t;
+
+static cairo_status_t
+_composite_traps_draw_func (void *closure,
+ cairo_operator_t op,
+ cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_t *extents)
+{
+ cairo_composite_traps_info_t *info = closure;
+ cairo_pattern_union_t pattern;
+ cairo_status_t status;
+
+ if (dst_x != 0 || dst_y != 0)
+ _cairo_traps_translate (info->traps, - dst_x, - dst_y);
+
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+ if (!src)
+ src = &pattern.base;
+
+ status = _cairo_surface_composite_trapezoids (op,
+ src, dst, info->antialias,
+ extents->x, extents->y,
+ extents->x - dst_x, extents->y - dst_y,
+ extents->width, extents->height,
+ info->traps->traps,
+ info->traps->num_traps);
+ _cairo_pattern_fini (&pattern.base);
+
+ return status;
+}
+
+/* Warning: This call modifies the coordinates of traps */
+static cairo_status_t
+_clip_and_composite_trapezoids (cairo_pattern_t *src,
+ cairo_operator_t op,
+ cairo_surface_t *dst,
+ cairo_traps_t *traps,
+ cairo_clip_t *clip,
+ cairo_antialias_t antialias)
+{
+ cairo_status_t status;
+ pixman_region16_t *trap_region;
+ pixman_region16_t *clear_region = NULL;
+ cairo_rectangle_t extents;
+ cairo_composite_traps_info_t traps_info;
+
+ if (traps->num_traps == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ status = _cairo_traps_extract_region (traps, &trap_region);
+ if (status)
+ return status;
+
+ if (_cairo_operator_bounded_by_mask (op))
+ {
+ if (trap_region) {
+ status = _cairo_clip_intersect_to_region (clip, trap_region);
+ _cairo_region_extents_rectangle (trap_region, &extents);
+ } else {
+ cairo_box_t trap_extents;
+ _cairo_traps_extents (traps, &trap_extents);
+ _cairo_box_round_to_rectangle (&trap_extents, &extents);
+ status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+ }
+ }
+ else
+ {
+ cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+
+ status = _cairo_surface_get_extents (dst, &extents);
+ if (status)
+ return status;
+
+ if (trap_region && !clip_surface) {
+ /* If we optimize drawing with an unbounded operator to
+ * _cairo_surface_fill_rectangles() or to drawing with a
+ * clip region, then we have an additional region to clear.
+ */
+ status = _cairo_surface_get_extents (dst, &extents);
+ if (status)
+ return status;
+
+ clear_region = _cairo_region_create_from_rectangle (&extents);
+ status = _cairo_clip_intersect_to_region (clip, clear_region);
+ if (status)
+ return status;
+
+ _cairo_region_extents_rectangle (clear_region, &extents);
+
+ if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ if (!pixman_region_not_empty (clear_region)) {
+ pixman_region_destroy (clear_region);
+ clear_region = NULL;
+ }
+ } else {
+ status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+ if (status)
+ return status;
+ }
+ }
+
+ if (status)
+ goto out;
+
+ if (trap_region)
+ {
+ cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+
+ if ((src->type == CAIRO_PATTERN_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
+ !clip_surface)
+ {
+ const cairo_color_t *color;
+
+ if (op == CAIRO_OPERATOR_CLEAR)
+ color = CAIRO_COLOR_TRANSPARENT;
+ else
+ color = &((cairo_solid_pattern_t *)src)->color;
+
+ /* Solid rectangles special case */
+ status = _cairo_surface_fill_region (dst, op, color, trap_region);
+ if (!status && clear_region)
+ status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
+ CAIRO_COLOR_TRANSPARENT,
+ clear_region);
+
+ goto out;
+ }
+
+ if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
+ !clip_surface)
+ {
+ /* For a simple rectangle, we can just use composite(), for more
+ * rectangles, we have to set a clip region. The cost of rasterizing
+ * trapezoids is pretty high for most backends currently, so it's
+ * worthwhile even if a region is needed.
+ *
+ * If we have a clip surface, we set it as the mask; this only works
+ * for bounded operators other than SOURCE; for unbounded operators,
+ * clip and mask cannot be interchanged. For SOURCE, the operator
+ * as implemented by the backends is different in it's handling
+ * of the mask then what we want.
+ *
+ * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
+ * more than rectangle and the destination doesn't support clip
+ * regions. In that case, we fall through.
+ */
+ status = _composite_trap_region (clip, src, op, dst,
+ trap_region, &extents);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ {
+ if (!status && clear_region)
+ status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
+ CAIRO_COLOR_TRANSPARENT,
+ clear_region);
+ goto out;
+ }
+ }
+ }
+
+ traps_info.traps = traps;
+ traps_info.antialias = antialias;
+
+ status = _clip_and_composite (clip, op, src,
+ _composite_traps_draw_func, &traps_info,
+ dst, &extents);
+
+ out:
+ if (trap_region)
+ pixman_region_destroy (trap_region);
+ if (clear_region)
+ pixman_region_destroy (clear_region);
+
+ return status;
+}
+
cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_operator_t op,
@@ -134,12 +679,12 @@
if (status)
return status;
- _cairo_surface_clip_and_composite_trapezoids (source,
- op,
- surface,
- &traps,
- surface->clip,
- CAIRO_ANTIALIAS_NONE);
+ _clip_and_composite_trapezoids (source,
+ op,
+ surface,
+ &traps,
+ surface->clip,
+ CAIRO_ANTIALIAS_NONE);
_cairo_traps_fini (&traps);
@@ -206,12 +751,12 @@
if (status)
return status;
- status = _cairo_gstate_clip_and_composite (surface->clip, op,
- source,
- _cairo_surface_mask_draw_func,
- mask,
- surface,
- &extents);
+ status = _clip_and_composite (surface->clip, op,
+ source,
+ _cairo_surface_mask_draw_func,
+ mask,
+ surface,
+ &extents);
return status;
}
@@ -242,12 +787,12 @@
return status;
}
- _cairo_surface_clip_and_composite_trapezoids (source,
- op,
- surface,
- &traps,
- surface->clip,
- antialias);
+ _clip_and_composite_trapezoids (source,
+ op,
+ surface,
+ &traps,
+ surface->clip,
+ antialias);
_cairo_traps_fini (&traps);
@@ -277,12 +822,12 @@
return status;
}
- status = _cairo_surface_clip_and_composite_trapezoids (source,
- op,
- surface,
- &traps,
- surface->clip,
- antialias);
+ status = _clip_and_composite_trapezoids (source,
+ op,
+ surface,
+ &traps,
+ surface->clip,
+ antialias);
_cairo_traps_fini (&traps);
@@ -389,13 +934,13 @@
glyph_info.glyphs = glyphs;
glyph_info.num_glyphs = num_glyphs;
- status = _cairo_gstate_clip_and_composite (surface->clip,
- op,
- source,
- _cairo_surface_old_show_glyphs_draw_func,
- &glyph_info,
- surface,
- &extents);
+ status = _clip_and_composite (surface->clip,
+ op,
+ source,
+ _cairo_surface_old_show_glyphs_draw_func,
+ &glyph_info,
+ surface,
+ &extents);
return status;
}
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.235
retrieving revision 1.236
diff -u -d -r1.235 -r1.236
--- cairoint.h 19 Dec 2005 01:20:06 -0000 1.235
+++ cairoint.h 20 Dec 2005 17:37:15 -0000 1.236
@@ -1297,23 +1297,6 @@
int num_glyphs,
cairo_path_fixed_t *path);
-typedef cairo_status_t (*cairo_draw_func_t) (void *closure,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_surface_t *dst,
- int dst_x,
- int dst_y,
- const cairo_rectangle_t *extents);
-
-cairo_private cairo_status_t
-_cairo_gstate_clip_and_composite (cairo_clip_t *clip,
- cairo_operator_t op,
- cairo_pattern_t *src,
- cairo_draw_func_t draw_func,
- void *draw_closure,
- cairo_surface_t *dst,
- const cairo_rectangle_t *extents);
-
cairo_private cairo_bool_t
_cairo_operator_bounded_by_mask (cairo_operator_t op);
@@ -1715,14 +1698,6 @@
int ntraps);
cairo_private cairo_status_t
-_cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
- cairo_operator_t op,
- cairo_surface_t *dst,
- cairo_traps_t *traps,
- cairo_clip_t *clip,
- cairo_antialias_t antialias);
-
-cairo_private cairo_status_t
_cairo_surface_copy_page (cairo_surface_t *surface);
cairo_private cairo_status_t
More information about the cairo-commit
mailing list