[cairo-commit] cairo/src cairo-features.h.in, 1.5, 1.6 cairo.c, 1.36, 1.37 cairo_fixed.c, 1.3, 1.4 cairo_gstate.c, 1.50, 1.51 cairo_matrix.c, 1.7, 1.8 cairo_xlib_surface.c, 1.19, 1.20 cairoint.h, 1.62, 1.63

Graydon Hoare commit at pdx.freedesktop.org
Thu May 20 16:42:59 PDT 2004


Committed by: graydon

Update of /cvs/cairo/cairo/src
In directory pdx:/tmp/cvs-serv27093/src

Modified Files:
	cairo-features.h.in cairo.c cairo_fixed.c cairo_gstate.c 
	cairo_matrix.c cairo_xlib_surface.c cairoint.h 
Log Message:
2004-05-20  Graydon Hoare  <graydon at redhat.com>

	* configure.in: Add sanity checking feature configury.

	* src/cairo-features.h.in: Add sanity checking feature.

	* src/cairo.c: Add sanity checking.

	* src/cairoint.h: Add prototypes.

	* src/cairo_fixed.c 
	(_cairo_fixed_is_integer): 
	(_cairo_fixed_integer_part): New functions.

	* src/cairo_matrix.c 
	(_cairo_matrix_is_integer_translation): New function.

	* src/cairo_gstate.c
	(extract_transformed_rectangle): Use fixed functions.
	(_cairo_gstate_clip): Arithmetic fixes.
	(_cairo_gstate_clip_and_composite_trapezoids):
	(_cairo_gstate_show_surface):
	(_cairo_gstate_show_text):
	(_cairo_gstate_show_glyphs): Corrections to clipping.

	* src/cairo_xlib_surface.c
	(_cairo_xlib_surface_composite): Add XCopyArea fast path.
	(_cairo_xlib_surface_set_clip_region): Drive clip to drawable.



Index: cairo-features.h.in
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-features.h.in,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** a/cairo-features.h.in	9 Apr 2004 21:19:47 -0000	1.5
--- b/cairo-features.h.in	20 May 2004 23:42:56 -0000	1.6
***************
*** 39,41 ****
--- 39,43 ----
  #define @GL_SURFACE_FEATURE@
  
+ #define @SANITY_CHECKING_FEATURE@
+ 
  #endif

Index: cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** a/cairo.c	17 May 2004 15:03:17 -0000	1.36
--- b/cairo.c	20 May 2004 23:42:56 -0000	1.37
***************
*** 30,33 ****
--- 30,61 ----
  #define CAIRO_TOLERANCE_MINIMUM	0.0002 /* We're limited by 16 bits of sub-pixel precision */
  
+ 
+ #ifdef CAIRO_DO_SANITY_CHECKING
+ #include <assert.h>
+ static int 
+ cairo_sane_state (cairo_t *cr)
+ {    
+     switch (cr->status) {
[...1067 lines suppressed...]
  {
+     CAIRO_CHECK_SANITY (cr);
      if (cr->status)
  	return;
***************
*** 934,937 ****
--- 1113,1117 ----
  					       close_path,
  					       closure);
+     CAIRO_CHECK_SANITY (cr);
  }
  
***************
*** 939,942 ****
--- 1119,1123 ----
  cairo_status (cairo_t *cr)
  {
+     CAIRO_CHECK_SANITY (cr);
      return cr->status;
  }

Index: cairo_fixed.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_fixed.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** a/cairo_fixed.c	13 Feb 2004 03:02:33 -0000	1.3
--- b/cairo_fixed.c	20 May 2004 23:42:56 -0000	1.4
***************
*** 52,53 ****
--- 52,64 ----
  }
  
+ int
+ _cairo_fixed_is_integer (cairo_fixed_t f)
+ {
+     return (f & 0xFFFF) == 0;
+ }
+ 
+ int
+ _cairo_fixed_integer_part (cairo_fixed_t f)
+ {
+     return f >> 16;
+ }

Index: cairo_gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_gstate.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -C2 -d -r1.50 -r1.51
*** a/cairo_gstate.c	11 May 2004 18:20:06 -0000	1.50
--- b/cairo_gstate.c	20 May 2004 23:42:56 -0000	1.51
***************
*** 1436,1445 ****
  	    goto BAIL2;
  
  	status = _cairo_surface_composite (operator,
  					   pattern.source, intermediate, dst,
  					   0, 0,
  					   0, 0,
! 					   gstate->clip.x,
! 					   gstate->clip.y,
  					   gstate->clip.width,
  					   gstate->clip.height);
--- 1436,1448 ----
  	    goto BAIL2;
  
+ 	if (dst == gstate->clip.surface)
+ 	    xoff = yoff = 0;
+ 	
  	status = _cairo_surface_composite (operator,
  					   pattern.source, intermediate, dst,
  					   0, 0,
  					   0, 0,
! 					   xoff >> 16,
! 					   yoff >> 16,
  					   gstate->clip.width,
  					   gstate->clip.height);
***************
*** 1644,1650 ****
  			      pixman_box16_t *box)
  {
- #define CAIRO_FIXED_IS_INTEGER(x) (((x) & 0xFFFF) == 0)
- #define CAIRO_FIXED_INTEGER_PART(x) ((x) >> 16)
- 
      double a, b, c, d, tx, ty;
      cairo_status_t st;
--- 1647,1650 ----
***************
*** 1659,1681 ****
  	&& tr->traps[0].left.p1.y == tr->traps[0].right.p1.y
  	&& tr->traps[0].left.p2.y == tr->traps[0].right.p2.y
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p1.x)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p1.y)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p2.x)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p2.y)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p1.x)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p1.y)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p2.x)
! 	&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p2.y)) {
  
! 	box->x1 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].left.p1.x);
! 	box->x2 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].right.p1.x);
! 	box->y1 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].left.p1.y);
! 	box->y2 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].left.p2.y);
  	return 1;
      }
      return 0;
- 
- #undef CAIRO_FIXED_IS_INTEGER
- #undef CAIRO_FIXED_INTEGER_PART
  }
  
--- 1659,1678 ----
  	&& tr->traps[0].left.p1.y == tr->traps[0].right.p1.y
  	&& tr->traps[0].left.p2.y == tr->traps[0].right.p2.y
! 	&& _cairo_fixed_is_integer(tr->traps[0].left.p1.x)
! 	&& _cairo_fixed_is_integer(tr->traps[0].left.p1.y)
! 	&& _cairo_fixed_is_integer(tr->traps[0].left.p2.x)
! 	&& _cairo_fixed_is_integer(tr->traps[0].left.p2.y)
! 	&& _cairo_fixed_is_integer(tr->traps[0].right.p1.x)
! 	&& _cairo_fixed_is_integer(tr->traps[0].right.p1.y)
! 	&& _cairo_fixed_is_integer(tr->traps[0].right.p2.x)
! 	&& _cairo_fixed_is_integer(tr->traps[0].right.p2.y)) {
  
! 	box->x1 = (short) _cairo_fixed_integer_part(tr->traps[0].left.p1.x);
! 	box->x2 = (short) _cairo_fixed_integer_part(tr->traps[0].right.p1.x);
! 	box->y1 = (short) _cairo_fixed_integer_part(tr->traps[0].left.p1.y);
! 	box->y2 = (short) _cairo_fixed_integer_part(tr->traps[0].left.p2.y);
  	return 1;
      }
      return 0;
  }
  
***************
*** 1744,1761 ****
  
      if (gstate->clip.surface == NULL) {
! 	double x1, y1, x2, y2;
!       _cairo_path_bounds (&gstate->path,
!                           &x1, &y1, &x2, &y2);
!       gstate->clip.x = floor (x1);
!       gstate->clip.y = floor (y1);
!       gstate->clip.width = ceil (x2 - gstate->clip.x);
!       gstate->clip.height = ceil (y2 - gstate->clip.y);
!       gstate->clip.surface =
!         _cairo_surface_create_similar_solid (gstate->surface,
!                                              CAIRO_FORMAT_A8,
!                                              gstate->clip.width,
!                                              gstate->clip.height,
!                                              &white_color);
!       if (gstate->clip.surface == NULL)
  	    return CAIRO_STATUS_NO_MEMORY;
      }
--- 1741,1758 ----
  
      if (gstate->clip.surface == NULL) {
! 	cairo_box_t extents;
! 
! 	_cairo_traps_extents (&traps, &extents);
! 	gstate->clip.x = extents.p1.x >> 16;
! 	gstate->clip.y = extents.p1.y >> 16;
! 	gstate->clip.width = ((extents.p2.x + 65535) >> 16) - gstate->clip.x;
! 	gstate->clip.height = ((extents.p2.y + 65535) >> 16) - gstate->clip.y;
! 	gstate->clip.surface =
! 	    _cairo_surface_create_similar_solid (gstate->surface,
! 						 CAIRO_FORMAT_A8,
! 						 gstate->clip.width,
! 						 gstate->clip.height,
! 						 &white_color);
! 	if (gstate->clip.surface == NULL)
  	    return CAIRO_STATUS_NO_MEMORY;
      }
***************
*** 1783,1786 ****
--- 1780,1847 ----
  			    int			height)
  {
+ 
+     /* We are dealing with 5 coordinate spaces in this function. this makes
+      * it ugly. 
+      *
+      * - "Image" space is the space of the surface we're reading pixels from.
+      *   it is the surface argument to this function. The surface has a
+      *   matrix attached to it which maps "user" space (see below) into
+      *   image space.
+      *
+      * - "Device" space is the space of the surface we're ultimately writing
+      *   pixels to. It is the current surface of the gstate argument to
+      *   this function.
+      * 
+      * - "User" space is an arbitrary space defined by the user, defined 
+      *   implicitly by the gstate's CTM. The CTM maps from user space to
+      *   device space. The CTM inverse (which is also kept at all times)
+      *   maps from device space to user space.
+      *
+      * - "Clip" space is the space of the surface being used to clip pixels
+      *   during compositing. Space-wise, it is a bounding box (offset+size)
+      *   within device space. This surface is usually smaller than the device
+      *   surface (and possibly the image surface too) and logically occupies
+      *   a bounding box around the "clip path", situated somewhere in device
+      *   space. The clip path is already painted on the clip surface.
+      *
+      * - "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
+      *   surface acting as a source for the pattern)
+      *
+      * To composite these spaces, we temporarily change the image surface 
+      * so that it can be read and written in device coordinates; in a sense
+      * this makes it "spatially compatible" with the clip and device spaces.
+      *
+      *
+      * There is also some confusion about the interaction between a clip and
+      * a pattern; it is assumed that in this "show surface" operation a pattern
+      * is to be used as an auxiliary alpha mask. this might be wrong, but it's 
+      * what we're doing now. 
+      *
+      * so, to follow the operations below, remember that in the compositing
+      * model, each operation is always of the form ((src IN mask) OP dst).
+      * that's the basic operation.
+      *
+      * so the compositing we are trying to do here, in general, involves 2
+      * steps, going via a temporary surface:
+      *
+      *  - combining clip and pattern pixels together into a mask channel.
+      *    this will be ((pattern IN clip) SRC temporary). it ignores the
+      *    pixels already in the temporary, overwriting it with the
+      *    pattern, clipped to the clip mask.
+      *
+      *  - combining temporary and "image" pixels with "device" pixels,
+      *    with a user-provided porter/duff operator. this will be
+      *    ((image IN temporary) OP device).
+      *
+      * if there is no clip, the degenerate case is just the second step
+      * with pattern standing in for temporary.
+      *
+      */
+ 
      cairo_status_t status;
      cairo_matrix_t user_to_image, image_to_user;
***************
*** 1789,1794 ****
      double device_width, device_height;
      cairo_pattern_t pattern;
!     cairo_box_t extents;
! 
      cairo_surface_get_matrix (surface, &user_to_image);
      cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
--- 1850,1855 ----
      double device_width, device_height;
      cairo_pattern_t pattern;
!     cairo_box_t pattern_extents;
!         
      cairo_surface_get_matrix (surface, &user_to_image);
      cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
***************
*** 1809,1837 ****
  
      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);
! 	extents.p1.x = _cairo_fixed_from_double (device_x);
! 	extents.p1.y = _cairo_fixed_from_double (device_y);
! 	extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
! 	extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
! 	status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
  	if (status)
  	    return status;
      }
      
!     /* XXX: The rendered size is sometimes 1 or 2 pixels short from
!        what I expect. Need to fix this. */
!     status = _cairo_surface_composite (gstate->operator,
! 				       surface, pattern.source, gstate->surface,
! 				       device_x, device_y,
! 				       0, 0,
! 				       device_x, device_y,
! 				       device_width,
! 				       device_height);
  
!     _cairo_pattern_fini (&pattern);
  
      /* restore the matrix originally in the surface */
      cairo_surface_set_matrix (surface, &user_to_image);
--- 1870,1951 ----
  
      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;
      }
      
!     if (gstate->clip.surface)
!     {
! 	cairo_surface_t *intermediate;
! 	cairo_color_t empty_color;
  
! 	_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);
! 
! 	/* it is not completely clear what the "right" way to combine the
! 	 pattern and mask surface is. I will use the the clip as a source
! 	 and the pattern as a mask in building up my temporary, because
! 	 this is not *totally* bogus and accomodates the case where
! 	 pattern's source image is NULL reasonably well. feel free to
! 	 correct this if you see a reason. */
  
+ 	status = _cairo_surface_composite (CAIRO_OPERATOR_SRC,
+ 					   gstate->clip.surface,
+ 					   pattern.source,
+ 					   intermediate,
+ 					   0, 0, 
+ 					   0, 0,
+ 					   0, 0,
+ 					   gstate->clip.width, 
+ 					   gstate->clip.height);
+ 
+ 	if (status)
+ 	    goto BAIL;
+ 
+ 	status = _cairo_surface_composite (gstate->operator,
+ 					   surface, 
+ 					   intermediate,
+ 					   gstate->surface,
+ 					   gstate->clip.x, gstate->clip.y,
+ 					   0, 0,
+ 					   gstate->clip.x, gstate->clip.y,
+ 					   gstate->clip.width, 
+ 					   gstate->clip.height);
+ 	
+     BAIL:
+ 	cairo_surface_destroy (intermediate);
+     }
+     else
+     {
+ 	
+ 	/* XXX: The rendered size is sometimes 1 or 2 pixels short from
+ 	   what I expect. Need to fix this. */
+ 	status = _cairo_surface_composite (gstate->operator,
+ 					   surface, 
+ 					   pattern.source, 
+ 					   gstate->surface,
+ 					   device_x, device_y,
+ 					   0, 0,
+ 					   device_x, device_y,
+ 					   device_width,
+ 					   device_height);
+ 
+     }
+ 
+     _cairo_pattern_fini (&pattern);
+     
      /* restore the matrix originally in the surface */
      cairo_surface_set_matrix (surface, &user_to_image);
***************
*** 2005,2012 ****
      if (status)
  	return status;
!     
!     status = _cairo_font_show_text (gstate->font,
! 				    gstate->operator, pattern.source,
! 				    gstate->surface, x, y, utf8);
      
      cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
--- 2119,2178 ----
      if (status)
  	return status;
!     if (gstate->clip.surface)
!     {
! 	cairo_surface_t *intermediate;
! 	cairo_color_t empty_color;
! 
! 	_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);
! 
! 	status = _cairo_font_show_text (gstate->font,
! 					CAIRO_OPERATOR_ADD, pattern.source,
! 					intermediate, 
! 					x - gstate->clip.x, 
! 					y - gstate->clip.y, utf8);
! 
! 	if (status)
! 	    goto BAIL;
! 	
! 	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
! 					   gstate->clip.surface,
! 					   NULL,
! 					   intermediate,
! 					   0, 0, 
! 					   0, 0,
! 					   0, 0,
! 					   gstate->clip.width, 
! 					   gstate->clip.height);
! 
! 	if (status)
! 	    goto BAIL;
! 
! 	status = _cairo_surface_composite (gstate->operator,
! 					   pattern.source,
! 					   intermediate,
! 					   gstate->surface,
! 					   0, 0, 
! 					   0, 0,
! 					   gstate->clip.x, 
! 					   gstate->clip.y,
! 					   gstate->clip.width, 
! 					   gstate->clip.height);
! 
!     BAIL:
! 	cairo_surface_destroy (intermediate);
! 	
!     }
!     else
!     {
! 	status = _cairo_font_show_text (gstate->font,
! 					gstate->operator, pattern.source,
! 					gstate->surface, x, y, utf8);
!     }
      
      cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
***************
*** 2046,2051 ****
  
      _cairo_pattern_init_copy (&pattern, gstate->pattern);
!     _cairo_gstate_glyph_extents (gstate, transformed_glyphs, num_glyphs,
!                                  &text_extents);
      if (status)
  	return status;
--- 2212,2217 ----
  
      _cairo_pattern_init_copy (&pattern, gstate->pattern);
!     status = _cairo_gstate_glyph_extents (gstate, transformed_glyphs, num_glyphs,
! 					  &text_extents);
      if (status)
  	return status;
***************
*** 2060,2068 ****
      if (status)
  	return status;
  
!     status = _cairo_font_show_glyphs (gstate->font, 
! 				      gstate->operator, pattern.source,
! 				      gstate->surface,
! 				      transformed_glyphs, num_glyphs);
      
      cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
--- 2226,2293 ----
      if (status)
  	return status;
+     
+     if (gstate->clip.surface)
+     {
+ 	cairo_surface_t *intermediate;
+ 	cairo_color_t empty_color;
  
! 	_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);
! 
! 	/* move the glyphs again, from dev space to clip space */
! 	for (i = 0; i < num_glyphs; ++i)
! 	{
! 	    transformed_glyphs[i].x -= gstate->clip.x;
! 	    transformed_glyphs[i].y -= gstate->clip.y;
! 	}
! 
! 	status = _cairo_font_show_glyphs (gstate->font, 
! 					  CAIRO_OPERATOR_ADD, 
! 					  pattern.source, intermediate,
! 					  transformed_glyphs, num_glyphs);
! 
! 	if (status)
! 	    goto BAIL;
! 
! 	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
! 					   gstate->clip.surface,
! 					   NULL,
! 					   intermediate,
! 					   0, 0, 
! 					   0, 0,
! 					   0, 0,
! 					   gstate->clip.width, 
! 					   gstate->clip.height);
! 
! 	if (status)
! 	    goto BAIL;
! 
! 	status = _cairo_surface_composite (gstate->operator,
! 					   pattern.source,
! 					   intermediate,
! 					   gstate->surface,
! 					   0, 0, 
! 					   0, 0,
! 					   gstate->clip.x, 
! 					   gstate->clip.y,
! 					   gstate->clip.width, 
! 					   gstate->clip.height);
! 	
!     BAIL:
! 	cairo_surface_destroy (intermediate);
! 
!     }
!     else
!     {
! 	status = _cairo_font_show_glyphs (gstate->font, 
! 					  gstate->operator, pattern.source,
! 					  gstate->surface,
! 					  transformed_glyphs, num_glyphs);
!     }
      
      cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);

Index: cairo_matrix.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_matrix.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** a/cairo_matrix.c	16 Dec 2003 02:02:03 -0000	1.7
--- b/cairo_matrix.c	20 May 2004 23:42:56 -0000	1.8
***************
*** 406,407 ****
--- 406,431 ----
      return CAIRO_STATUS_SUCCESS;
  }
+ 
+ int 
+ _cairo_matrix_is_integer_translation(cairo_matrix_t *mat, 
+ 				     int *itx, int *ity)
+ {
+     double a, b, c, d, tx, ty;
+     int ttx, tty;
+     int ok = 0;
+     cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
+     ttx = _cairo_fixed_from_double (tx);
+     tty = _cairo_fixed_from_double (ty);
+     ok = ((a == 1.0)
+ 	  && (b == 0.0)
+ 	  && (c == 0.0)
+ 	  && (d == 1.0)
+ 	  && (_cairo_fixed_is_integer(ttx))
+ 	  && (_cairo_fixed_is_integer(tty)));
+     if (ok) {
+ 	*itx = _cairo_fixed_integer_part(ttx);
+ 	*ity = _cairo_fixed_integer_part(tty);
+ 	return 1;
+     } 
+     return 0;
+ }

Index: cairo_xlib_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xlib_surface.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C2 -d -r1.19 -r1.20
*** a/cairo_xlib_surface.c	6 Apr 2004 16:36:12 -0000	1.19
--- b/cairo_xlib_surface.c	20 May 2004 23:42:56 -0000	1.20
***************
*** 456,460 ****
      cairo_xlib_surface_t *src_clone = NULL;
      cairo_xlib_surface_t *mask_clone = NULL;
!     
  
      if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
--- 456,461 ----
      cairo_xlib_surface_t *src_clone = NULL;
      cairo_xlib_surface_t *mask_clone = NULL;
!     XGCValues gc_values;
!     int src_x_off, src_y_off, dst_x_off, dst_y_off;
  
      if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
***************
*** 476,479 ****
--- 477,502 ----
      }
  
+     if (operator == CAIRO_OPERATOR_SRC 
+ 	&& !mask
+ 	&& _cairo_matrix_is_integer_translation(&(src->base.matrix), 
+ 						&src_x_off, &src_y_off)
+ 	&& _cairo_matrix_is_integer_translation(&(dst->base.matrix), 
+ 						&dst_x_off, &dst_y_off)) {
+ 	/* Fast path for copying "raw" areas. */
+  	_cairo_xlib_surface_ensure_gc (dst); 
+ 	XGetGCValues(dst->dpy, dst->gc, GCGraphicsExposures, &gc_values);
+ 	XSetGraphicsExposures(dst->dpy, dst->gc, False);
+ 	XCopyArea(dst->dpy, 
+ 		  src->drawable, 
+ 		  dst->drawable, 
+ 		  dst->gc, 
+ 		  src_x + src_x_off, 
+ 		  src_y + src_y_off, 
+ 		  width, height, 
+ 		  dst_x + dst_x_off, 
+ 		  dst_y + dst_y_off);
+ 	XSetGraphicsExposures(dst->dpy, dst->gc, gc_values.graphics_exposures);
+ 
+     } else {	
      XRenderComposite (dst->dpy,
  		      _render_operator (operator),
***************
*** 485,488 ****
--- 508,512 ----
  		      dst_x, dst_y,
  		      width, height);
+     }
  
      /* XXX: This is messed up. If I can xlib_surface_create, then I
***************
*** 578,583 ****
--- 602,610 ----
  				     pixman_region16_t *region)
  {
+ 
      Region xregion;
      XRectangle xr;
+     XRectangle *rects = NULL;
+     XGCValues gc_values;
      pixman_box16_t *box;
      cairo_xlib_surface_t *surf;
***************
*** 594,597 ****
--- 621,628 ----
  	xr.height = surf->height;
  	XUnionRectWithRegion (&xr, xregion, xregion);
+ 	rects = malloc(sizeof(XRectangle));
+ 	rects[0] = xr;
+ 	m = 1;
+ 
      } else {
  	n = pixman_region_num_rects (region);
***************
*** 600,604 ****
  	if (n == 0)
  	    return CAIRO_STATUS_SUCCESS;
! 
  	box = pixman_region_rects (region);
  	xregion = XCreateRegion();
--- 631,635 ----
  	if (n == 0)
  	    return CAIRO_STATUS_SUCCESS;
! 	rects = malloc(sizeof(XRectangle) * n);
  	box = pixman_region_rects (region);
  	xregion = XCreateRegion();
***************
*** 610,620 ****
  	    xr.width = (unsigned short) (box->x2 - box->x1);
  	    xr.height = (unsigned short) (box->y2 - box->y1);
  	    XUnionRectWithRegion (&xr, xregion, xregion);
  	}    
      }
      
      XRenderSetPictureClipRegion (surf->dpy, surf->picture, xregion);
      XDestroyRegion(xregion);
! 
      return CAIRO_STATUS_SUCCESS;
  }
--- 641,658 ----
  	    xr.width = (unsigned short) (box->x2 - box->x1);
  	    xr.height = (unsigned short) (box->y2 - box->y1);
+ 	    rects[n-1] = xr;
  	    XUnionRectWithRegion (&xr, xregion, xregion);
  	}    
      }
      
+     _cairo_xlib_surface_ensure_gc (surf); 
+     XGetGCValues(surf->dpy, surf->gc, GCGraphicsExposures, &gc_values);
+     XSetGraphicsExposures(surf->dpy, surf->gc, False);
+     XSetClipRectangles(surf->dpy, surf->gc, 0, 0, rects, m, Unsorted);
+     free(rects);
+     if (surf->picture)
      XRenderSetPictureClipRegion (surf->dpy, surf->picture, xregion);
      XDestroyRegion(xregion);
!     XSetGraphicsExposures(surf->dpy, surf->gc, gc_values.graphics_exposures);
      return CAIRO_STATUS_SUCCESS;
  }
***************
*** 655,658 ****
--- 693,698 ----
      cairo_xlib_surface_t *surface;
      int render_standard;
+     Window w;
+     unsigned int ignore;
  
      surface = malloc (sizeof (cairo_xlib_surface_t));
***************
*** 693,696 ****
--- 733,742 ----
      }
  
+     XGetGeometry(dpy, drawable, 
+ 		 &w, &ignore, &ignore, 
+ 		 &surface->width,
+ 		 &surface->height,
+ 		 &ignore, &ignore);
+ 
      /* XXX: I'm currently ignoring the colormap. Is that bad? */
      if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface))

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.62
retrieving revision 1.63
diff -C2 -d -r1.62 -r1.63
*** a/cairoint.h	11 May 2004 20:59:09 -0000	1.62
--- b/cairoint.h	20 May 2004 23:42:56 -0000	1.63
***************
*** 621,624 ****
--- 621,630 ----
  _cairo_fixed_to_double (cairo_fixed_t f);
  
+ extern int __internal_linkage
+ _cairo_fixed_is_integer (cairo_fixed_t f);
+ 
+ extern int __internal_linkage
+ _cairo_fixed_integer_part (cairo_fixed_t f);
+ 
  /* cairo_gstate.c */
  extern cairo_gstate_t * __internal_linkage
***************
*** 1288,1291 ****
--- 1294,1300 ----
  _cairo_matrix_compute_scale_factors (cairo_matrix_t *matrix, double *sx, double *sy);
  
+ extern int __internal_linkage
+ _cairo_matrix_is_integer_translation(cairo_matrix_t *matrix, int *itx, int *ity);
+ 
  /* cairo_traps.c */
  extern void __internal_linkage





More information about the cairo-commit mailing list