[cairo-commit] cairo/src Makefile.am, 1.60, 1.61 cairo-clip.c, 1.3,
1.4 cairo-gstate.c, 1.163, 1.164 cairo-image-surface.c, 1.57,
1.58 cairo-region.c, NONE, 1.1 cairo-surface.c, 1.91,
1.92 cairo-xlib-surface.c, 1.108, 1.109 cairoint.h, 1.197, 1.198
Owen Taylor
commit at pdx.freedesktop.org
Tue Aug 16 18:22:18 PDT 2005
Committed by: otaylor
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv23851/src
Modified Files:
Makefile.am cairo-clip.c cairo-gstate.c cairo-image-surface.c
cairo-surface.c cairo-xlib-surface.c cairoint.h
Added Files:
cairo-region.c
Log Message:
2005-08-16 Owen Taylor <otaylor at redhat.com>
* src/cairo-region.c (_cairo_region_rectangle_extents)
(_cairo_region_create_from_rectangle) src/cairoint.h: Split out
a couple of useful utility functions.
* src/cairo-clip.c src/cairo-gstate.c: Use them.
* src/cairo-surface.c (_cairo_surface_fill_region): Move code to
fill a pixman_region16_t to here.
* src/cairo-surface.c (_cairo_surface_fill_rectangle)
* src/cairo-surface.c (_cairo_surface_fill_rectangles): Document.
* src/cairo-gstate.c (_cairo_surface_clip_and_composite_trapezoids):
Use _cairo_surface_fill_region().
* src/cairo-surface.c (_cairo_surface_composite_fixup_unbounded):
Add a return status, use regions to simplify.
* src/cairoint.h
* src/cairo-image-surface.c (_cairo_image_surface_composite)
* src/cairo-xlib-surface.c (_cairo_xlib_surface_composite)
(_show_glyphs_fixup_unbounded): Handle the return value from
_cairo_surface_composite_fixup_unbounded().
* src/cairo-surface.c src/cairoint.h
(_cairo_surface_composite_shape_fixup_unbounded): Add a variant
of _cairo_surface_composite_fixup_unbounded() to avoid creating
a dummy cairo_surface_attributes_t.
* src/cairo-xlib-surface (_show_glyphs_fixup_unbounded):
Use _cairo_surface_composite_shape_fixup_unbounded().
* src/cairo-image-surface.c (_cairo_image_surface_composite_trapezoids)
* src/cairo-xlib-surface.c (_cairo_xlib_surface_composite_trapezoids):
Call _cairo_surface_composite_shape_fixup_unbounded(), since the source
might still be restricted, even though the mask is unbounded.
* src/cairo-gstate.c (_cairo_surface_clip_and_composite_trapezoids):
Restore the rectangle optizations when drawing with unbounded
operators by adding a clear for the extra area after drawing
the rectangles.
Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairo/src/Makefile.am,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- Makefile.am 10 Aug 2005 19:36:51 -0000 1.60
+++ Makefile.am 17 Aug 2005 01:22:16 -0000 1.61
@@ -109,6 +109,7 @@
cairo-path-stroke.c \
cairo-pen.c \
cairo-polygon.c \
+ cairo-region.c \
cairo-slope.c \
cairo-spline.c \
cairo-surface.c \
Index: cairo-clip.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-clip.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cairo-clip.c 9 Aug 2005 01:35:22 -0000 1.3
+++ cairo-clip.c 17 Aug 2005 01:22:16 -0000 1.4
@@ -45,35 +45,6 @@
static void
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
-/* Creates a region from a cairo_rectangle_t */
-static cairo_status_t
-_region_new_from_rect (cairo_rectangle_t *rect,
- pixman_region16_t **region)
-{
- *region = pixman_region_create ();
- if (pixman_region_union_rect (*region, *region,
- rect->x, rect->y,
- rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (*region);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Gets the bounding box of a region as a cairo_rectangle_t */
-static void
-_region_rect_extents (pixman_region16_t *region,
- cairo_rectangle_t *rect)
-{
- pixman_box16_t *region_extents = pixman_region_extents (region);
-
- rect->x = region_extents->x1;
- rect->y = region_extents->y1;
- rect->width = region_extents->x2 - region_extents->x1;
- rect->height = region_extents->y2 - region_extents->y1;
-}
-
void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
{
@@ -146,18 +117,18 @@
if (clip->region) {
pixman_region16_t *intersection;
- cairo_status_t status;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
pixman_region_status_t pixman_status;
- status = _region_new_from_rect (rectangle, &intersection);
- if (status)
- return status;
+ intersection = _cairo_region_create_from_rectangle (rectangle);
+ if (intersection == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
pixman_status = pixman_region_intersect (intersection,
clip->region,
intersection);
if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
- _region_rect_extents (intersection, rectangle);
+ _cairo_region_extents_rectangle (intersection, rectangle);
else
status = CAIRO_STATUS_NO_MEMORY;
@@ -187,11 +158,11 @@
if (clip->surface) {
pixman_region16_t *clip_rect;
pixman_region_status_t pixman_status;
- cairo_status_t status;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
- status = _region_new_from_rect (&clip->surface_rect, &clip_rect);
- if (status)
- return status;
+ clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
+ if (clip_rect == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
pixman_status = pixman_region_intersect (region,
clip_rect,
Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.163
retrieving revision 1.164
diff -u -d -r1.163 -r1.164
--- cairo-gstate.c 9 Aug 2005 01:35:22 -0000 1.163
+++ cairo-gstate.c 17 Aug 2005 01:22:16 -0000 1.164
@@ -1196,45 +1196,6 @@
return status;
}
-/* Composites a region representing a set of trapezoids in the
- * case of a solid source (so we can use
- * _cairo_surface_fill_rectangles).
- */
-static cairo_status_t
-_composite_trap_region_solid (cairo_clip_t *clip,
- cairo_solid_pattern_t *src,
- cairo_operator_t operator,
- cairo_surface_t *dst,
- pixman_region16_t *region)
-{
- int num_rects = pixman_region_num_rects (region);
- pixman_box16_t *boxes = pixman_region_rects (region);
- cairo_rectangle_t *rects;
- cairo_status_t status;
- int i;
-
- if (!num_rects)
- return CAIRO_STATUS_SUCCESS;
-
- rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
- if (!rects)
- return CAIRO_STATUS_NO_MEMORY;
-
- for (i = 0; i < num_rects; i++) {
- rects[i].x = boxes[i].x1;
- rects[i].y = boxes[i].y1;
- rects[i].width = boxes[i].x2 - boxes[i].x1;
- rects[i].height = boxes[i].y2 - boxes[i].y1;
- }
-
- status = _cairo_surface_fill_rectangles (dst, operator,
- &src->color, rects, num_rects);
-
- free (rects);
-
- return status;
-}
-
typedef struct {
cairo_traps_t *traps;
cairo_antialias_t antialias;
@@ -1272,19 +1233,6 @@
return status;
}
-/* Gets the bounding box of a region as a cairo_rectangle_t */
-static void
-_region_rect_extents (pixman_region16_t *region,
- cairo_rectangle_t *rect)
-{
- pixman_box16_t *region_extents = pixman_region_extents (region);
-
- rect->x = region_extents->x1;
- rect->y = region_extents->y1;
- rect->width = region_extents->x2 - region_extents->x1;
- rect->height = region_extents->y2 - region_extents->y1;
-}
-
/* Warning: This call modifies the coordinates of traps */
cairo_status_t
_cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src,
@@ -1296,6 +1244,7 @@
{
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;
@@ -1310,7 +1259,7 @@
{
if (trap_region) {
status = _cairo_clip_intersect_to_region (clip, trap_region);
- _region_rect_extents (trap_region, &extents);
+ _cairo_region_extents_rectangle (trap_region, &extents);
} else {
cairo_box_t trap_extents;
_cairo_traps_extents (traps, &trap_extents);
@@ -1323,39 +1272,82 @@
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
- status = _cairo_clip_intersect_to_rectangle (clip, &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_operator_bounded (operator))
+ if (trap_region)
{
if (src->type == CAIRO_PATTERN_SOLID && !clip->surface)
{
/* Solid rectangles special case */
- status = _composite_trap_region_solid (clip, (cairo_solid_pattern_t *)src,
- operator, dst, trap_region);
+ status = _cairo_surface_fill_region (dst, operator,
+ &((cairo_solid_pattern_t *)src)->color,
+ trap_region);
+ if (!status && clear_region)
+ status = _cairo_surface_fill_region (dst, operator,
+ CAIRO_COLOR_TRANSPARENT,
+ clear_region);
+
goto out;
}
-
- /* 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.
- *
- * 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, operator, dst,
- trap_region, &extents);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto out;
+
+ if (_cairo_operator_bounded (operator) || !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; for unbounded operators, clip and mask
+ * cannot be interchanged.
+ *
+ * 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, operator, 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;
@@ -1368,6 +1360,8 @@
out:
if (trap_region)
pixman_region_destroy (trap_region);
+ if (clear_region)
+ pixman_region_destroy (clear_region);
return status;
}
Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- cairo-image-surface.c 9 Aug 2005 01:35:22 -0000 1.57
+++ cairo-image-surface.c 17 Aug 2005 01:22:16 -0000 1.58
@@ -583,47 +583,50 @@
return status;
status = _cairo_image_surface_set_attributes (src, &src_attr);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status)
+ goto CLEANUP_SURFACES;
+
+ if (mask)
{
- if (mask)
- {
- status = _cairo_image_surface_set_attributes (mask, &mask_attr);
- if (status == CAIRO_STATUS_SUCCESS)
- pixman_composite (_pixman_operator (operator),
- src->pixman_image,
- mask->pixman_image,
- dst->pixman_image,
- src_x + src_attr.x_offset,
- src_y + src_attr.y_offset,
- mask_x + mask_attr.x_offset,
- mask_y + mask_attr.y_offset,
- dst_x, dst_y,
- width, height);
- }
- else
- {
- pixman_composite (_pixman_operator (operator),
- src->pixman_image,
- NULL,
- dst->pixman_image,
- src_x + src_attr.x_offset,
- src_y + src_attr.y_offset,
- 0, 0,
- dst_x, dst_y,
- width, height);
- }
+ status = _cairo_image_surface_set_attributes (mask, &mask_attr);
+ if (status)
+ goto CLEANUP_SURFACES;
+
+ pixman_composite (_pixman_operator (operator),
+ src->pixman_image,
+ mask->pixman_image,
+ dst->pixman_image,
+ src_x + src_attr.x_offset,
+ src_y + src_attr.y_offset,
+ mask_x + mask_attr.x_offset,
+ mask_y + mask_attr.y_offset,
+ dst_x, dst_y,
+ width, height);
+ }
+ else
+ {
+ pixman_composite (_pixman_operator (operator),
+ src->pixman_image,
+ NULL,
+ dst->pixman_image,
+ src_x + src_attr.x_offset,
+ src_y + src_attr.y_offset,
+ 0, 0,
+ dst_x, dst_y,
+ width, height);
}
-
- if (!_cairo_operator_bounded (operator))
- _cairo_surface_composite_fixup_unbounded (&dst->base,
- &src_attr, src->width, src->height,
- mask ? &mask_attr : NULL,
- mask ? mask->width : 0,
- mask ? mask->height : 0,
- src_x, src_y,
- mask_x, mask_y,
- dst_x, dst_y, width, height);
+ if (!_cairo_operator_bounded (operator))
+ status = _cairo_surface_composite_fixup_unbounded (&dst->base,
+ &src_attr, src->width, src->height,
+ mask ? &mask_attr : NULL,
+ mask ? mask->width : 0,
+ mask ? mask->height : 0,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y, width, height);
+
+ CLEANUP_SURFACES:
if (mask)
_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
@@ -765,7 +768,7 @@
* somehow. */
pixman_add_trapezoids (mask, - dst_x, - dst_y,
(pixman_trapezoid_t *) traps, num_traps);
-
+
pixman_composite (_pixman_operator (operator),
src->pixman_image,
mask,
@@ -775,7 +778,14 @@
0, 0,
dst_x, dst_y,
width, height);
-
+
+ if (!_cairo_operator_bounded (operator))
+ status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
+ &attributes, src->width, src->height,
+ width, height,
+ src_x, src_y,
+ 0, 0,
+ dst_x, dst_y, width, height);
pixman_image_destroy (mask);
CLEANUP_IMAGE_DATA:
--- NEW FILE: cairo-region.c ---
(This appears to be a binary file; contents omitted.)
Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- cairo-surface.c 9 Aug 2005 01:35:22 -0000 1.91
+++ cairo-surface.c 17 Aug 2005 01:22:16 -0000 1.92
@@ -842,6 +842,21 @@
width, height);
}
+/**
+ * _cairo_surface_fill_rectangle:
+ * @surface: a #cairo_surface_t
+ * @operator: the operator to apply to the rectangle
+ * @color: the source color
+ * @x: X coordinate of rectangle, in backend coordinates
+ * @y: Y coordinate of rectangle, in backend coordinates
+ * @width: width of rectangle, in backend coordinates
+ * @height: height of rectangle, in backend coordinates
+ *
+ * Applies an operator to a rectangle using a solid color as the source.
+ * See _cairo_surface_fill_rectangles() for full details.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
+ **/
cairo_status_t
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
cairo_operator_t operator,
@@ -867,6 +882,53 @@
return _cairo_surface_fill_rectangles (surface, operator, color, &rect, 1);
}
+/**
+ * _cairo_surface_fill_region:
+ * @surface: a #cairo_surface_t
+ * @operator: the operator to apply to the region
+ * @color: the source color
+ * @region: the region to modify, in backend coordinates
+ *
+ * Applies an operator to a set of rectangles specified as a
+ * #pixman_region16_t using a solid color as the source.
+ * See _cairo_surface_fill_rectangles() for full details.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
+ **/
+cairo_status_t
+_cairo_surface_fill_region (cairo_surface_t *surface,
+ cairo_operator_t operator,
+ const cairo_color_t *color,
+ pixman_region16_t *region)
+{
+ int num_rects = pixman_region_num_rects (region);
+ pixman_box16_t *boxes = pixman_region_rects (region);
+ cairo_rectangle_t *rects;
+ cairo_status_t status;
+ int i;
+
+ if (!num_rects)
+ return CAIRO_STATUS_SUCCESS;
+
+ rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
+ if (!rects)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ for (i = 0; i < num_rects; i++) {
+ rects[i].x = boxes[i].x1;
+ rects[i].y = boxes[i].y1;
+ rects[i].width = boxes[i].x2 - boxes[i].x1;
+ rects[i].height = boxes[i].y2 - boxes[i].y1;
+ }
+
+ status = _cairo_surface_fill_rectangles (surface, operator,
+ color, rects, num_rects);
+
+ free (rects);
+
+ return status;
+}
+
static cairo_status_t
_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
@@ -941,6 +1003,22 @@
return status;
}
+/**
+ * _cairo_surface_fill_rectangles:
+ * @surface: a #cairo_surface_t
+ * @operator: the operator to apply to the region
+ * @color: the source color
+ * @rects: the rectangles to modify, in backend coordinates
+ * @num_rects: the number of rectangles in @rects
+ *
+ * Applies an operator to a set of rectangles using a solid color
+ * as the source. Note that even if the operator is an unbounded operator
+ * such as %CAIRO_OPERATOR_CLEAR, only the given set of rectangles
+ * is affected. This differs from _cairo_surface_composite_trapezoids()
+ * where the entire destination rectangle is cleared.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
+ **/
cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
@@ -1405,6 +1483,64 @@
return status;
}
+static cairo_status_t
+_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
+ cairo_rectangle_t *src_rectangle,
+ cairo_rectangle_t *mask_rectangle,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
+{
+ cairo_rectangle_t dst_rectangle;
+ cairo_rectangle_t drawn_rectangle;
+ pixman_region16_t *drawn_region;
+ pixman_region16_t *clear_region;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ /* The area that was drawn is the area in the destination rectangle but not within
+ * the source or the mask.
+ */
+ dst_rectangle.x = dst_x;
+ dst_rectangle.y = dst_y;
+ dst_rectangle.width = width;
+ dst_rectangle.height = height;
+
+ drawn_rectangle = dst_rectangle;
+
+ if (src_rectangle)
+ _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
+
+ if (mask_rectangle)
+ _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
+
+ /* Now compute the area that is in dst_rectangle but not in drawn_rectangle
+ */
+ drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle);
+ clear_region = _cairo_region_create_from_rectangle (&dst_rectangle);
+ if (!drawn_region || !clear_region) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_REGIONS;
+ }
+
+ if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_REGIONS;
+ }
+
+ status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
+ CAIRO_COLOR_TRANSPARENT,
+ clear_region);
+
+ CLEANUP_REGIONS:
+ if (drawn_region)
+ pixman_region_destroy (drawn_region);
+ if (clear_region)
+ pixman_region_destroy (clear_region);
+
+ return status;
+}
+
/**
* _cairo_surface_composite_fixup_unbounded:
* @dst: the destination surface
@@ -1429,7 +1565,7 @@
* only the region inside both the source and the mask is affected.
* This function clears the region that should have been drawn but was wasn't.
**/
-void
+cairo_status_t
_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
cairo_surface_attributes_t *src_attr,
int src_width,
@@ -1446,112 +1582,104 @@
unsigned int width,
unsigned int height)
{
- cairo_bool_t have_src = TRUE;
- cairo_bool_t have_mask = mask_attr != NULL;
- cairo_rectangle_t dst_rectangle;
- cairo_rectangle_t drawn_rectangle;
- cairo_rectangle_t rects[4];
- int num_rects = 0;
-
+ cairo_rectangle_t src_tmp, mask_tmp;
+ cairo_rectangle_t *src_rectangle = NULL;
+ cairo_rectangle_t *mask_rectangle = NULL;
+
/* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
* non-repeating sources and masks. Other sources and masks can be ignored.
*/
- if (!_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) ||
- src_attr->extend != CAIRO_EXTEND_NONE)
- have_src = FALSE;
-
- if (have_mask &&
- (!_cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) ||
- mask_attr->extend != CAIRO_EXTEND_NONE))
- have_mask = FALSE;
-
- /* The area that was drawn is the area in the destination rectangle but not within
- * the source or the mask.
- */
- dst_rectangle.x = dst_x;
- dst_rectangle.y = dst_y;
- dst_rectangle.width = width;
- dst_rectangle.height = height;
-
- drawn_rectangle = dst_rectangle;
+ if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
+ src_attr->extend == CAIRO_EXTEND_NONE)
+ {
+ src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
+ src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
+ src_tmp.width = src_width;
+ src_tmp.height = src_height;
- if (have_src) {
- cairo_rectangle_t src_rectangle;
-
- src_rectangle.x = (dst_x - (src_x + src_attr->x_offset));
- src_rectangle.y = (dst_y - (src_y + src_attr->y_offset));
- src_rectangle.width = src_width;
- src_rectangle.height = src_height;
-
- _cairo_rectangle_intersect (&drawn_rectangle, &src_rectangle);
+ src_rectangle = &src_tmp;
}
- if (have_mask) {
- cairo_rectangle_t mask_rectangle;
-
- mask_rectangle.x = (dst_x - (mask_x + mask_attr->x_offset));
- mask_rectangle.y = (dst_y - (mask_y + mask_attr->y_offset));
- mask_rectangle.width = mask_width;
- mask_rectangle.height = mask_height;
+ if (mask_attr &&
+ _cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) &&
+ mask_attr->extend == CAIRO_EXTEND_NONE)
+ {
+ mask_tmp.x = (dst_x - (mask_x + mask_attr->x_offset));
+ mask_tmp.y = (dst_y - (mask_y + mask_attr->y_offset));
+ mask_tmp.width = mask_width;
+ mask_tmp.height = mask_height;
- _cairo_rectangle_intersect (&drawn_rectangle, &mask_rectangle);
+ mask_rectangle = &mask_tmp;
}
- /* Now compute the area that is in dst_rectangle but not in drawn_rectangle;
- * this is the area we must clear; This computation could be done with
- * regions, but the clumsiness of the libpixman API makes this easier.
+ return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
+ dst_x, dst_y, width, height);
+}
+
+/**
+ * _cairo_surface_composite_shape_fixup_unbounded:
+ * @dst: the destination surface
+ * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
+ * @src_width: width of source surface
+ * @src_height: height of source surface
+ * @mask_width: width of mask surface
+ * @mask_height: height of mask surface
+ * @src_x: @src_x from _cairo_surface_composite()
+ * @src_y: @src_y from _cairo_surface_composite()
+ * @mask_x: @mask_x from _cairo_surface_composite()
+ * @mask_y: @mask_y from _cairo_surface_composite()
+ * @dst_x: @dst_x from _cairo_surface_composite()
+ * @dst_y: @dst_y from _cairo_surface_composite()
+ * @width: @width from _cairo_surface_composite()
+ * @height: @height_x from _cairo_surface_composite()
+ *
+ * Like _cairo_surface_composite_fixup_unbounded(), but instead of
+ * handling the case where we have a source pattern and a mask
+ * pattern, handle the case where we are compositing a source pattern
+ * using a mask we create ourselves, as in
+ * _cairo_surface_composite_glyphs() or _cairo_surface_composite_trapezoids()
+ **/
+cairo_status_t
+_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
+ cairo_surface_attributes_t *src_attr,
+ int src_width,
+ int src_height,
+ int mask_width,
+ int mask_height,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
+{
+ cairo_rectangle_t src_tmp, mask_tmp;
+ cairo_rectangle_t *src_rectangle = NULL;
+ cairo_rectangle_t *mask_rectangle = NULL;
+
+ /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
+ * non-repeating sources and masks. Other sources and masks can be ignored.
*/
- if (drawn_rectangle.width == 0 || drawn_rectangle.height == 0)
- {
- rects[num_rects].x = dst_rectangle.x;
- rects[num_rects].y = dst_rectangle.y;
- rects[num_rects].width = dst_rectangle.width;
- rects[num_rects].height = dst_rectangle.height;
-
- num_rects++;
- }
- else
+ if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
+ src_attr->extend == CAIRO_EXTEND_NONE)
{
- if (dst_rectangle.y < drawn_rectangle.y) {
- rects[num_rects].x = dst_rectangle.x;
- rects[num_rects].y = dst_rectangle.y;
- rects[num_rects].width = dst_rectangle.width;
- rects[num_rects].height = drawn_rectangle.y - dst_rectangle.y;
-
- num_rects++;
- }
-
- if (dst_rectangle.x < drawn_rectangle.x) {
- rects[num_rects].x = dst_rectangle.x;
- rects[num_rects].y = drawn_rectangle.y;
- rects[num_rects].width = drawn_rectangle.x - dst_rectangle.x;
- rects[num_rects].height = drawn_rectangle.height;
-
- num_rects++;
- }
-
- if (dst_rectangle.x + dst_rectangle.width > drawn_rectangle.x + drawn_rectangle.width) {
- rects[num_rects].x = drawn_rectangle.x + drawn_rectangle.width;
- rects[num_rects].y = drawn_rectangle.y;
- rects[num_rects].width = (dst_rectangle.x + dst_rectangle.width) - (drawn_rectangle.x + drawn_rectangle.width);
- rects[num_rects].height = drawn_rectangle.height;
-
- num_rects++;
- }
-
- if (dst_rectangle.y + dst_rectangle.height > drawn_rectangle.y + drawn_rectangle.height) {
- rects[num_rects].x = dst_rectangle.x;
- rects[num_rects].y = drawn_rectangle.y + drawn_rectangle.height;
- rects[num_rects].width = dst_rectangle.width;
- rects[num_rects].height = (dst_rectangle.y + dst_rectangle.height) - (drawn_rectangle.y + drawn_rectangle.height);
-
- num_rects++;
- }
- }
-
- if (num_rects > 0) {
- _cairo_surface_fill_rectangles (dst, CAIRO_OPERATOR_SOURCE, CAIRO_COLOR_TRANSPARENT,
- rects, num_rects);
+ src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
+ src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
+ src_tmp.width = src_width;
+ src_tmp.height = src_height;
+
+ src_rectangle = &src_tmp;
}
-}
+ mask_tmp.x = dst_x - mask_x;
+ mask_tmp.y = dst_y - mask_y;
+ mask_tmp.width = mask_width;
+ mask_tmp.height = mask_height;
+
+ mask_rectangle = &mask_tmp;
+
+ return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
+ dst_x, dst_y, width, height);
+}
Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -d -r1.108 -r1.109
--- cairo-xlib-surface.c 9 Aug 2005 20:42:54 -0000 1.108
+++ cairo-xlib-surface.c 17 Aug 2005 01:22:16 -0000 1.109
@@ -1113,18 +1113,20 @@
_cairo_xlib_surface_ensure_dst_picture (dst);
if (mask) {
status = _cairo_xlib_surface_set_attributes (mask, &mask_attr);
- if (status == CAIRO_STATUS_SUCCESS)
- XRenderComposite (dst->dpy,
- _render_operator (operator),
- src->src_picture,
- mask->src_picture,
- dst->dst_picture,
- src_x + src_attr.x_offset,
- src_y + src_attr.y_offset,
- mask_x + mask_attr.x_offset,
- mask_y + mask_attr.y_offset,
- dst_x, dst_y,
- width, height);
+ if (status)
+ goto FAIL;
+
+ XRenderComposite (dst->dpy,
+ _render_operator (operator),
+ src->src_picture,
+ mask->src_picture,
+ dst->dst_picture,
+ src_x + src_attr.x_offset,
+ src_y + src_attr.y_offset,
+ mask_x + mask_attr.x_offset,
+ mask_y + mask_attr.y_offset,
+ dst_x, dst_y,
+ width, height);
} else {
XRenderComposite (dst->dpy,
_render_operator (operator),
@@ -1139,14 +1141,14 @@
}
if (!_cairo_operator_bounded (operator))
- _cairo_surface_composite_fixup_unbounded (&dst->base,
- &src_attr, src->width, src->height,
- mask ? &mask_attr : NULL,
- mask ? mask->width : 0,
- mask ? mask->height : 0,
- src_x, src_y,
- mask_x, mask_y,
- dst_x, dst_y, width, height);
+ status = _cairo_surface_composite_fixup_unbounded (&dst->base,
+ &src_attr, src->width, src->height,
+ mask ? &mask_attr : NULL,
+ mask ? mask->width : 0,
+ mask ? mask->height : 0,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y, width, height);
break;
case DO_XCOPYAREA:
@@ -1413,6 +1415,14 @@
XRenderFreePicture (dst->dpy, mask_picture);
+ status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
+ &attributes, src->width, src->height,
+ width, height,
+ src_x, src_y,
+ 0, 0,
+ dst_x, dst_y, width, height);
+
+
} else {
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
XRenderCompositeTrapezoids (dst->dpy,
@@ -2509,7 +2519,7 @@
* mask created by XRenderCompositeText[N] but should be affected
* by an unbounded operator like CAIRO_OPERATOR_SOURCE.
*/
-static void
+static cairo_status_t
_show_glyphs_fixup_unbounded (cairo_xlib_surface_t *self,
cairo_surface_attributes_t *src_attr,
cairo_xlib_surface_t *src,
@@ -2523,7 +2533,6 @@
int width,
int height)
{
- cairo_surface_attributes_t mask_attr;
int x1 = INT_MAX;
int x2 = INT_MIN;
int y1 = INT_MAX;
@@ -2555,18 +2564,12 @@
if (x1 >= x2 || y1 >= y2)
x1 = x2 = y1 = y2 = 0;
- cairo_matrix_init_identity (&mask_attr.matrix);
- mask_attr.extend = CAIRO_EXTEND_NONE;
- mask_attr.filter = CAIRO_FILTER_NEAREST;
- mask_attr.x_offset = 0;
- mask_attr.y_offset = 0;
-
- _cairo_surface_composite_fixup_unbounded (&self->base,
- src_attr, src->width, src->height,
- &mask_attr, x2 - x1, y2 - y1,
- src_x, src_y,
- dst_x - x1, dst_y - y1,
- dst_x, dst_y, width, height);
+ return _cairo_surface_composite_shape_fixup_unbounded (&self->base,
+ src_attr, src->width, src->height,
+ x2 - x1, y2 - y1,
+ src_x, src_y,
+ dst_x - x1, dst_y - y1,
+ dst_x, dst_y, width, height);
}
static cairo_int_status_t
@@ -2679,12 +2682,13 @@
glyphs, entries, num_glyphs);
}
- if (!_cairo_operator_bounded (operator))
- _show_glyphs_fixup_unbounded (self,
- &attributes, src,
- glyphs, entries, num_glyphs,
- source_x, source_y,
- dest_x, dest_y, width, height);
+ if (status == CAIRO_STATUS_SUCCESS &&
+ !_cairo_operator_bounded (operator))
+ status = _show_glyphs_fixup_unbounded (self,
+ &attributes, src,
+ glyphs, entries, num_glyphs,
+ source_x, source_y,
+ dest_x, dest_y, width, height);
UNLOCK:
_unlock_xlib_glyphset_caches (cache);
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.197
retrieving revision 1.198
diff -u -d -r1.197 -r1.198
--- cairoint.h 16 Aug 2005 23:41:10 -0000 1.197
+++ cairoint.h 17 Aug 2005 01:22:16 -0000 1.198
@@ -1560,15 +1560,6 @@
_cairo_surface_get_clip_mode (cairo_surface_t *surface);
cairo_private cairo_status_t
-_cairo_surface_fill_rectangle (cairo_surface_t *surface,
- cairo_operator_t operator,
- const cairo_color_t *color,
- int x,
- int y,
- int width,
- int height);
-
-cairo_private cairo_status_t
_cairo_surface_composite (cairo_operator_t operator,
cairo_pattern_t *src,
cairo_pattern_t *mask,
@@ -1583,6 +1574,21 @@
unsigned int height);
cairo_private cairo_status_t
+_cairo_surface_fill_rectangle (cairo_surface_t *surface,
+ cairo_operator_t operator,
+ const cairo_color_t *color,
+ int x,
+ int y,
+ int width,
+ int height);
+
+cairo_private cairo_status_t
+_cairo_surface_fill_region (cairo_surface_t *surface,
+ cairo_operator_t operator,
+ const cairo_color_t *color,
+ pixman_region16_t *region);
+
+cairo_private cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t operator,
const cairo_color_t *color,
@@ -1696,7 +1702,7 @@
const cairo_glyph_t *glyphs,
int num_glyphs);
-cairo_private void
+cairo_private cairo_status_t
_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
cairo_surface_attributes_t *src_attr,
int src_width,
@@ -1713,6 +1719,22 @@
unsigned int width,
unsigned int height);
+cairo_private cairo_status_t
+_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
+ cairo_surface_attributes_t *src_attr,
+ int src_width,
+ int src_height,
+ int mask_width,
+ int mask_height,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height);
+
/* cairo_image_surface.c */
cairo_private cairo_format_t
@@ -1958,6 +1980,14 @@
cairo_private cairo_antialias_t
_cairo_gstate_get_antialias (cairo_gstate_t *gstate);
+/* cairo-region.c */
+
+cairo_private pixman_region16_t *
+_cairo_region_create_from_rectangle (cairo_rectangle_t *rect);
+
+cairo_private void
+_cairo_region_extents_rectangle (pixman_region16_t *region,
+ cairo_rectangle_t *rect);
/* cairo_unicode.c */
More information about the cairo-commit
mailing list