[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