[cairo-commit] cairo/src cairo.c, 1.44, 1.45 cairo_cache.c, 1.4,
1.5 cairo_fixed.c, 1.8, 1.9 cairo_gstate.c, 1.67,
1.68 cairoint.h, 1.74, 1.75
Alexander Larsson
commit at pdx.freedesktop.org
Mon Dec 20 09:44:01 PST 2004
Committed by: alexl
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv32131/src
Modified Files:
cairo.c cairo_cache.c cairo_fixed.c cairo_gstate.c cairoint.h
Log Message:
2004-12-20 Alexander Larsson <alexl at redhat.com>
* src/cairoint.h:
Add _cairo_gstate_restore_external_state, _cairo_fixed_integer_floor
and _cairo_fixed_integer_ceil.
* src/cairo.c: (cairo_restore):
Call _cairo_gstate_restore_external_state on restore.
* src/cairo_cache.c: (_cache_lookup):
Fix cache-misses.
* src/cairo_fixed.c: (_cairo_fixed_integer_floor),
(_cairo_fixed_integer_ceil):
Implement floor and ceil
* src/cairo_gstate.c:
(_cairo_gstate_restore_external_state):
Restore surface clip region on restroe.
(_calculate_region_for_intermediate_clip_surface),
(_cairo_gstate_clip_and_composite_trapezoids),
(_cairo_gstate_show_surface), (_cairo_gstate_show_glyphs):
Create intermediate clip surfaces of the minimal required
size.
Index: cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- cairo.c 22 Oct 2004 01:40:50 -0000 1.44
+++ cairo.c 20 Dec 2004 17:43:59 -0000 1.45
@@ -159,6 +159,12 @@
if (cr->gstate == NULL)
cr->status = CAIRO_STATUS_INVALID_RESTORE;
+
+ if (cr->status)
+ return;
+
+ cr->status = _cairo_gstate_restore_external_state (cr->gstate);
+
CAIRO_CHECK_SANITY (cr);
}
slim_hidden_def(cairo_restore);
Index: cairo_cache.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_cache.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cairo_cache.c 23 Nov 2004 21:38:09 -0000 1.4
+++ cairo_cache.c 20 Dec 2004 17:43:59 -0000 1.5
@@ -180,10 +180,12 @@
if (predicate != NULL)
{
/* We are looking up an exact entry. */
- if (*probe != NULL
- && *probe != DEAD_ENTRY
- && (*probe)->hashcode == hash
- && predicate (cache, key, *probe))
+ if (*probe == NULL)
+ /* Found an empty spot, there can't be a match */
+ break;
+ else if (*probe != DEAD_ENTRY
+ && (*probe)->hashcode == hash
+ && predicate (cache, key, *probe))
return probe;
}
else
Index: cairo_fixed.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_fixed.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cairo_fixed.c 22 Oct 2004 01:40:50 -0000 1.8
+++ cairo_fixed.c 20 Dec 2004 17:43:59 -0000 1.9
@@ -71,3 +71,21 @@
{
return f >> 16;
}
+
+int
+_cairo_fixed_integer_floor (cairo_fixed_t f)
+{
+ if (f >= 0)
+ return f >> 16;
+ else
+ return -((-f - 1) >> 16) - 1;
+}
+
+int
+_cairo_fixed_integer_ceil (cairo_fixed_t f)
+{
+ if (f >= 0)
+ return ((f - 1)>>16) + 1;
+ else
+ return - (-f >> 16);
+}
Index: cairo_gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_gstate.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- cairo_gstate.c 2 Dec 2004 00:27:18 -0000 1.67
+++ cairo_gstate.c 20 Dec 2004 17:43:59 -0000 1.68
@@ -1363,6 +1363,54 @@
return status;
}
+static cairo_status_t
+_calculate_region_for_intermediate_clip_surface (pixman_region16_t *out,
+ cairo_box_t *extents,
+ cairo_clip_rec_t *clip_rect)
+{
+ cairo_status_t status;
+ pixman_region16_t *extents_region, *clip_region;
+ pixman_box16_t clip_box, pixman_extents;
+
+ pixman_extents.x1 = _cairo_fixed_integer_floor (extents->p1.x);
+ pixman_extents.y1 = _cairo_fixed_integer_floor (extents->p1.y);
+ pixman_extents.x2 = _cairo_fixed_integer_ceil (extents->p2.x);
+ pixman_extents.y2 = _cairo_fixed_integer_ceil (extents->p2.y);
+ extents_region = pixman_region_create_simple (&pixman_extents);
+ if (extents_region == NULL)
+ {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL0;
+ }
+
+ clip_box.x1 = clip_rect->x;
+ clip_box.y1 = clip_rect->y;
+ clip_box.x2 = clip_rect->x + clip_rect->width;
+ clip_box.y2 = clip_rect->y + clip_rect->height;
+ clip_region = pixman_region_create_simple (&clip_box);
+ if (clip_region == NULL)
+ {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL1;
+ }
+
+ if (pixman_region_intersect (out,
+ extents_region,
+ clip_region)
+ == PIXMAN_REGION_STATUS_FAILURE)
+ status = CAIRO_STATUS_NO_MEMORY;
+ else
+ status = CAIRO_STATUS_SUCCESS;
+
+ pixman_region_destroy (extents_region);
+ BAIL1:
+ pixman_region_destroy (clip_region);
+
+ BAIL0:
+ return status;
+}
+
+
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
@@ -1385,25 +1433,38 @@
int i;
cairo_surface_t *intermediate;
cairo_color_t empty_color;
+ pixman_box16_t *draw_extents;
+ pixman_region16_t *draw_region;
- _cairo_color_init (&empty_color);
- _cairo_color_set_alpha (&empty_color, 0.);
- intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
- CAIRO_FORMAT_A8,
- gstate->clip.width,
- gstate->clip.height,
- &empty_color);
- if (intermediate == NULL) {
+ draw_region = pixman_region_create ();
+ if (draw_region == NULL)
+ {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL0;
}
+
+ _cairo_traps_extents (traps, &extents);
+
+ status = _calculate_region_for_intermediate_clip_surface (draw_region,
+ &extents,
+ &gstate->clip);
+ if (status)
+ goto BAIL1;
+
+ /* Shortcut if empty */
+ if (!pixman_region_not_empty (draw_region)) {
+ status = CAIRO_STATUS_SUCCESS;
+ goto BAIL1;
+ }
+
+ draw_extents = pixman_region_extents (draw_region);
/* Ugh. The cairo_composite/(Render) interface doesn't allow
an offset for the trapezoids. Need to manually shift all
- the coordinates to align with the offset origin of the clip
- surface. */
- xoff = _cairo_fixed_from_double (gstate->clip.x);
- yoff = _cairo_fixed_from_double (gstate->clip.y);
+ the coordinates to align with the offset origin of the
+ intermediate surface. */
+ xoff = _cairo_fixed_from_int (draw_extents->x1);
+ yoff = _cairo_fixed_from_int (draw_extents->y1);
for (i=0, t=traps->traps; i < traps->num_traps; i++, t++) {
t->top -= yoff;
t->bottom -= yoff;
@@ -1428,11 +1489,22 @@
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
_cairo_pattern_set_alpha (&pattern, 1.0);
- _cairo_traps_extents (traps, &extents);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
goto BAIL1;
+ _cairo_color_init (&empty_color);
+ _cairo_color_set_alpha (&empty_color, 0.);
+ intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
+ CAIRO_FORMAT_A8,
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1,
+ &empty_color);
+ if (intermediate == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL2;
+ }
+
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
pattern.source, intermediate,
x_src,
@@ -1440,30 +1512,32 @@
traps->traps,
traps->num_traps);
if (status)
- goto BAIL2;
+ goto BAIL3;
status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
gstate->clip.surface,
NULL,
intermediate,
- 0, 0, 0, 0, 0, 0,
- gstate->clip.width, gstate->clip.height);
+ draw_extents->x1 - gstate->clip.x,
+ draw_extents->y1 - gstate->clip.y,
+ 0, 0,
+ 0, 0,
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1);
if (status)
- goto BAIL2;
+ goto BAIL3;
_cairo_pattern_fini (&pattern);
_cairo_pattern_init_copy (&pattern, src);
- extents.p1.x = _cairo_fixed_from_int (gstate->clip.x);
- extents.p1.y = _cairo_fixed_from_int (gstate->clip.y);
- extents.p2.x =
- _cairo_fixed_from_int (gstate->clip.x + gstate->clip.width);
- extents.p2.y =
- _cairo_fixed_from_int (gstate->clip.y + gstate->clip.height);
+ extents.p1.x = _cairo_fixed_from_int (draw_extents->x1);
+ extents.p1.y = _cairo_fixed_from_int (draw_extents->y1);
+ extents.p2.x = _cairo_fixed_from_int (draw_extents->x2);
+ extents.p2.y = _cairo_fixed_from_int (draw_extents->y2);
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
if (status)
- goto BAIL2;
+ goto BAIL3;
if (dst == gstate->clip.surface)
xoff = yoff = 0;
@@ -1474,13 +1548,16 @@
0, 0,
xoff >> 16,
yoff >> 16,
- gstate->clip.width,
- gstate->clip.height);
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1);
+
- BAIL2:
+ BAIL3:
cairo_surface_destroy (intermediate);
- BAIL1:
+ BAIL2:
_cairo_pattern_fini (&pattern);
+ BAIL1:
+ pixman_region_destroy (draw_region);
BAIL0:
if (status)
@@ -1705,6 +1782,25 @@
return 0;
}
+/* Reset surface clip region to the one in the gstate */
+cairo_status_t
+_cairo_gstate_restore_external_state (cairo_gstate_t *gstate)
+{
+ cairo_status_t status;
+
+ status = CAIRO_STATUS_SUCCESS;
+
+ if (gstate->surface)
+ status = _cairo_surface_set_clip_region (gstate->surface,
+ gstate->clip.region);
+
+ /* If not supported we're already using surface clipping */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ status = CAIRO_STATUS_SUCCESS;
+
+ return status;
+}
+
cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate)
{
@@ -1813,7 +1909,7 @@
int height)
{
- /* We are dealing with 5 coordinate spaces in this function. this makes
+ /* We are dealing with 6 coordinate spaces in this function. this makes
* it ugly.
*
* - "Image" space is the space of the surface we're reading pixels from.
@@ -1837,12 +1933,16 @@
* a bounding box around the "clip path", situated somewhere in device
* space. The clip path is already painted on the clip surface.
*
+ * - "Intermediate" space is the subset of the Clip space that the
+ * drawing will affect, and we allocate an intermediate surface
+ * of this size so that we can paint in it.
+ *
* - "Pattern" space is another arbitrary space defined in the pattern
* element of gstate. As pixels are read from image space, they are
* combined with pixels being read from pattern space and pixels
* already existing in device space. User coordinates are converted
* to pattern space, similarly, using a matrix attached to the pattern.
- * (in fact, there is a 6th space in here, which is the space of the
+ * (in fact, there is a 7th space in here, which is the space of the
* surface acting as a source for the pattern)
*
* To composite these spaces, we temporarily change the image surface
@@ -1901,15 +2001,16 @@
_cairo_pattern_init (&pattern);
+ pattern_extents.p1.x = _cairo_fixed_from_double (device_x);
+ pattern_extents.p1.y = _cairo_fixed_from_double (device_y);
+ pattern_extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
+ pattern_extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
+
if ((gstate->pattern->type != CAIRO_PATTERN_SOLID) ||
(gstate->alpha != 1.0)) {
/* I'm allowing any type of pattern for the mask right now.
Maybe this is bad. Will allow for some cool effects though. */
_cairo_pattern_init_copy (&pattern, gstate->pattern);
- pattern_extents.p1.x = _cairo_fixed_from_double (device_x);
- pattern_extents.p1.y = _cairo_fixed_from_double (device_y);
- pattern_extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
- pattern_extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
status = _cairo_gstate_create_pattern (gstate, &pattern, &pattern_extents);
if (status)
return status;
@@ -1919,13 +2020,36 @@
{
cairo_surface_t *intermediate;
cairo_color_t empty_color;
+ pixman_box16_t *draw_extents;
+ pixman_region16_t *draw_region;
+
+ draw_region = pixman_region_create ();
+ if (draw_region == NULL)
+ {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL0;
+ }
+
+ status = _calculate_region_for_intermediate_clip_surface (draw_region,
+ &pattern_extents,
+ &gstate->clip);
+ if (status)
+ goto BAIL1;
+ /* Shortcut if empty */
+ if (!pixman_region_not_empty (draw_region)) {
+ status = CAIRO_STATUS_SUCCESS;
+ goto BAIL1;
+ }
+
+ draw_extents = pixman_region_extents (draw_region);
+
_cairo_color_init (&empty_color);
_cairo_color_set_alpha (&empty_color, .0);
intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
CAIRO_FORMAT_A8,
- gstate->clip.width,
- gstate->clip.height,
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1,
&empty_color);
/* it is not completely clear what the "right" way to combine the
@@ -1939,27 +2063,33 @@
gstate->clip.surface,
pattern.source,
intermediate,
- 0, 0,
+ draw_extents->x1 - gstate->clip.x,
+ draw_extents->y1 - gstate->clip.y,
0, 0,
0, 0,
- gstate->clip.width,
- gstate->clip.height);
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1);
+
if (status)
- goto BAIL;
+ goto BAIL2;
status = _cairo_surface_composite (gstate->operator,
surface,
intermediate,
gstate->surface,
- gstate->clip.x, gstate->clip.y,
+ draw_extents->x1, draw_extents->y1,
0, 0,
- gstate->clip.x, gstate->clip.y,
- gstate->clip.width,
- gstate->clip.height);
+ draw_extents->x1, draw_extents->y1,
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1);
- BAIL:
+ BAIL2:
cairo_surface_destroy (intermediate);
+ BAIL1:
+ pixman_region_destroy (draw_region);
+ BAIL0:
+ ;
}
else
{
@@ -2335,55 +2465,84 @@
transformed_glyphs, num_glyphs,
&bbox);
if (status)
- return status;
+ goto CLEANUP_GLYPHS;
status = _cairo_gstate_create_pattern (gstate, &pattern, &bbox);
if (status)
- return status;
+ goto CLEANUP_GLYPHS;
if (gstate->clip.surface)
{
cairo_surface_t *intermediate;
cairo_color_t empty_color;
+ pixman_box16_t *draw_extents;
+ pixman_region16_t *draw_region;
+
+ draw_region = pixman_region_create ();
+ if (draw_region == NULL)
+ {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL0;
+ }
+
+ status = _calculate_region_for_intermediate_clip_surface (draw_region,
+ &bbox,
+ &gstate->clip);
+ if (status) {
+ goto BAIL1;
+ }
+ /* Shortcut if empty */
+ if (!pixman_region_not_empty (draw_region)) {
+ status = CAIRO_STATUS_SUCCESS;
+ goto BAIL1;
+ }
+
+ draw_extents = pixman_region_extents (draw_region);
+
_cairo_color_init (&empty_color);
_cairo_color_set_alpha (&empty_color, .0);
intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
CAIRO_FORMAT_A8,
- gstate->clip.width,
- gstate->clip.height,
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1,
&empty_color);
+ if (intermediate == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto BAIL1;
+ }
- /* move the glyphs again, from dev space to clip space */
+ /* move the glyphs again, from dev space to intermediate space */
for (i = 0; i < num_glyphs; ++i)
{
- transformed_glyphs[i].x -= gstate->clip.x;
- transformed_glyphs[i].y -= gstate->clip.y;
+ transformed_glyphs[i].x -= draw_extents->x1;
+ transformed_glyphs[i].y -= draw_extents->y1;
}
status = _cairo_unscaled_font_show_glyphs (gstate->font,
&sc,
CAIRO_OPERATOR_ADD,
pattern.source, intermediate,
- gstate->clip.x - pattern.source_offset.x,
- gstate->clip.y - pattern.source_offset.y,
+ draw_extents->x1 - pattern.source_offset.x,
+ draw_extents->y1 - pattern.source_offset.y,
transformed_glyphs, num_glyphs);
if (status)
- goto BAIL;
+ goto BAIL2;
status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
gstate->clip.surface,
NULL,
intermediate,
- 0, 0,
+ draw_extents->x1 - gstate->clip.x,
+ draw_extents->y1 - gstate->clip.y,
0, 0,
0, 0,
- gstate->clip.width,
- gstate->clip.height);
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1);
if (status)
- goto BAIL;
+ goto BAIL2;
status = _cairo_surface_composite (gstate->operator,
pattern.source,
@@ -2391,14 +2550,17 @@
gstate->surface,
0, 0,
0, 0,
- gstate->clip.x,
- gstate->clip.y,
- gstate->clip.width,
- gstate->clip.height);
-
- BAIL:
- cairo_surface_destroy (intermediate);
+ draw_extents->x1,
+ draw_extents->y1,
+ draw_extents->x2 - draw_extents->x1,
+ draw_extents->y2 - draw_extents->y1);
+ BAIL2:
+ cairo_surface_destroy (intermediate);
+ BAIL1:
+ pixman_region_destroy (draw_region);
+ BAIL0:
+ ;
}
else
{
@@ -2413,6 +2575,7 @@
_cairo_pattern_fini (&pattern);
+ CLEANUP_GLYPHS:
free (transformed_glyphs);
return status;
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- cairoint.h 20 Dec 2004 15:32:45 -0000 1.74
+++ cairoint.h 20 Dec 2004 17:43:59 -0000 1.75
@@ -815,6 +815,13 @@
extern int __internal_linkage
_cairo_fixed_integer_part (cairo_fixed_t f);
+extern int __internal_linkage
+_cairo_fixed_integer_floor (cairo_fixed_t f);
+
+ extern int __internal_linkage
+_cairo_fixed_integer_ceil (cairo_fixed_t f);
+
+
/* cairo_gstate.c */
extern cairo_gstate_t * /* XXX-NON-CLASS: __internal_linkage */
_cairo_gstate_create (void);
@@ -1052,6 +1059,9 @@
_cairo_gstate_clip (cairo_gstate_t *gstate);
extern cairo_status_t __internal_linkage
+_cairo_gstate_restore_external_state (cairo_gstate_t *gstate);
+
+extern cairo_status_t __internal_linkage
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_surface_t *surface,
int width,
More information about the cairo-commit
mailing list