[cairo-commit] cairo/src cairo-clip-private.h, 1.1, 1.2 cairo-clip.c, 1.1, 1.2 cairo-ft-font.c, 1.95, 1.96 cairo-gstate.c, 1.159, 1.160 cairo-image-surface.c, 1.55, 1.56 cairo-surface.c, 1.88, 1.89 cairo-xlib-surface.c, 1.104, 1.105 cairoint.h, 1.186, 1.187

Owen Taylor commit at pdx.freedesktop.org
Mon Aug 8 13:46:14 PDT 2005


Committed by: otaylor

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv13802/src

Modified Files:
	cairo-clip-private.h cairo-clip.c cairo-ft-font.c 
	cairo-gstate.c cairo-image-surface.c cairo-surface.c 
	cairo-xlib-surface.c cairoint.h 
Log Message:
2005-08-08  Owen Taylor  <otaylor at redhat.com>

	* src/cairo-gstate.c (_cairo_operator_bounded): Add a function to test
	whether a cairo_operator_t is bounded (does nothing for 0 src/mask)

	* src/cairo-surface.c (_cairo_surface_composite_fixup_unbounded) cairoint.h:
	Add a helper function to take clearing areas that are outside the source/mask
	but are cleared by unbounded operations.

	* src/cairo-image-surface.c (_cairo_image_surface_composite)
	src/cairo-xlib-surface.c (_cairo_xlib_surface_composite): Use 
	_cairo_surface_composite_fixup_unbounded() as needed.

	* src/cairo-image-surface.c src/cairint.h: Keep track of whether the surface 
	has a clip or not ... we need this for determining when we can bypass
	an intermediate mask for composite_trapezoids().

	* src/cairo-image-surface.c (_cairo_image_surface_composite_trapezoids):
	Create an intermediate mask of the right size with pixman_add_trapezoids()
	and composite that.

	* src/cairo-xlib-surface.c (_cairo_xlib_surface_composite_trapezoids):
	When rendering with an unbounded operator, create the intermediate mask
	ourselves and render with ADD to that, then composite the result.

	* src/cairo-ft-font.c (_cairo_ft_scaled_font_show_glyphs): Create an 
	intermediate surface the size of the extents, render the glyphs to that
	then composite the results.

	* src/cairo-xlib-surface.c (glyphset_cache_entry_t): Add the size of the glyph

	* src/cairo-xlib-surface.c (_show_glyphs_fixup_unbounded): Compute the size
	of the glyph mask, then use _cairo_surface_composite_fixup_unbounded().

	* src/cairo-xlib-surface.c (_cairo_xlib_surface_show_glyphs32): Use the right
	mask format. (Unrelated bugfix)

	* src/cairo-gstate.c (_cairo_gstate_clip_and_composite): New function taking
	a drawing function as a parameter to encapsulate shared logic between
	compositing trapezoid, glyphs, and masks.

	* src/cairo-gstate.c (_cairo_gstate_mask, 
	_cairo_surface_clip_and_composite_trapezoids, _cairo_gstate_show_glyphs):
	Use _cairo_gstate_clip_and_composite(). Also fix extents computations for 
	unbounded operators.
	
	* src/cairo-clip.c src/cairo-clip-private.h (_cairo_clip_combine_to_surface): 
	Add the destination as an extra parameter to allow combining to an intermediate
	surface.

	* tests/unbounded-operator.c tests/Makefile.am: Add a test for the
	operation of the 6 unbounded operators against different shapes.

	* tests/clip-operator.c tests/Makefile.am: Add a test that tests
	surface clipping with different shapes against all the operators.

	* test/composite-integer-translate-over-repeat.c (draw): Make use OVER
	like the name and description. With fixed semantics, SOURCE does something
	different.

Index: cairo-clip-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-clip-private.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cairo-clip-private.h	5 Aug 2005 05:45:59 -0000	1.1
+++ cairo-clip-private.h	8 Aug 2005 20:46:11 -0000	1.2
@@ -111,8 +111,11 @@
 				 pixman_region16_t *region);
 
 cairo_private cairo_status_t
-_cairo_clip_combine_to_surface (cairo_clip_t      *clip,
-				cairo_surface_t   *intermediate,
-				cairo_rectangle_t *extents);
+_cairo_clip_combine_to_surface (cairo_clip_t            *clip,
+				cairo_operator_t         operator,
+				cairo_surface_t         *dst,
+				int                      dst_x,
+				int                      dst_y,
+				const cairo_rectangle_t *extents);
 
 #endif /* CAIRO_CLIP_PRIVATE_H */

Index: cairo-clip.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-clip.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cairo-clip.c	5 Aug 2005 05:45:59 -0000	1.1
+++ cairo-clip.c	8 Aug 2005 20:46:11 -0000	1.2
@@ -208,28 +208,32 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
-/* Combines clip->surface using the IN operator with the given
- * intermediate surface, which corresponds to the rectangle of the
- * destination space given by @extents.
+/* Combines the region of clip->surface given by extents in
+ * device backend coordinates into the given temporary surface,
+ * which has its origin at dst_x, dst_y in backend coordinates
  */
 cairo_status_t
-_cairo_clip_combine_to_surface (cairo_clip_t      *clip,
-				cairo_surface_t   *intermediate,
-				cairo_rectangle_t *extents)
+_cairo_clip_combine_to_surface (cairo_clip_t            *clip,
+				cairo_operator_t         operator,
+				cairo_surface_t         *dst,
+				int                      dst_x,
+				int                      dst_y,
+				const cairo_rectangle_t *extents)
 {
     cairo_pattern_union_t pattern;
     cairo_status_t status;
 
     _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
     
-    status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
+    status = _cairo_surface_composite (operator,
 				       &pattern.base,
 				       NULL,
-				       intermediate,
+				       dst,
 				       extents->x - clip->surface_rect.x,
 				       extents->y - clip->surface_rect.y, 
 				       0, 0,
-				       0, 0,
+				       extents->x - dst_x,
+				       extents->y - dst_y,
 				       extents->width, extents->height);
     
     _cairo_pattern_fini (&pattern.base);

Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -d -r1.95 -r1.96
--- cairo-ft-font.c	6 Aug 2005 07:09:17 -0000	1.95
+++ cairo-ft-font.c	8 Aug 2005 20:46:11 -0000	1.96
@@ -1844,6 +1844,26 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_format_t
+_select_text_mask_format (cairo_bool_t	    have_a1_glyphs,
+			  cairo_bool_t 	    have_a8_glyphs,
+			  cairo_bool_t 	    have_argb32_glyphs)
+{
+    if (have_a8_glyphs)
+	return CAIRO_FORMAT_A8;
+
+    if (have_a1_glyphs && have_argb32_glyphs)
+	return CAIRO_FORMAT_A8;
+
+    if (have_a1_glyphs)
+	return CAIRO_FORMAT_A1;
+
+    if (have_argb32_glyphs)
+	return CAIRO_FORMAT_ARGB32;
+
+    /* when there are no glyphs to draw, just pick something */
+    return CAIRO_FORMAT_A8;
+}
 
 static cairo_status_t 
 _cairo_ft_scaled_font_show_glyphs (void		       *abstract_font,
@@ -1859,12 +1879,16 @@
 				   const cairo_glyph_t *glyphs,
 				   int                 	num_glyphs)
 {
-    cairo_image_glyph_cache_entry_t *img;
+    cairo_image_glyph_cache_entry_t **entries;
     cairo_cache_t *cache;
     cairo_glyph_cache_key_t key;
     cairo_ft_scaled_font_t *scaled_font = abstract_font;
     cairo_surface_pattern_t glyph_pattern;
-    cairo_status_t status;
+    cairo_surface_t *mask;
+    cairo_surface_pattern_t mask_pattern;
+    cairo_format_t mask_format = CAIRO_FORMAT_A1;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_bool_t have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs;
     int x, y;
     int i;
 
@@ -1884,44 +1908,98 @@
     key.scale = scaled_font->base.scale;
     key.flags = scaled_font->load_flags;
 
+    entries = malloc (num_glyphs * sizeof (cairo_image_glyph_cache_entry_t));
+    if (!entries)
+	goto CLEANUP_CACHE;
+
+    have_a1_glyphs = FALSE;
+    have_a8_glyphs = FALSE;
+    have_argb32_glyphs = FALSE;
+    
     for (i = 0; i < num_glyphs; i++)
     {
-	img = NULL;
+	entries[i] = NULL;
 	key.index = glyphs[i].index;
 
-	if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL) 
-	    != CAIRO_STATUS_SUCCESS 
-	    || img == NULL 
-	    || img->image == NULL)
+	if (_cairo_cache_lookup (cache, &key, (void **) &entries[i], NULL) != CAIRO_STATUS_SUCCESS)
+	    continue;
+
+	switch (entriesXMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/CVS/Root
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/CVS/Tag
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/CVS/Template
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/DONE
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/fcqueue.h
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/fontcache.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/fontcache.h
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/fontcache.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/Imakefile
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/Makefile
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontcache/Makefile.bak
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/bitsource.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/bitsource.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/bufio.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/bufio.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/CVS
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/CVS/Entries
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/CVS/Repository
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/CVS/Root
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/CVS/Tag
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/CVS/Template
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/decompress.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/decompress.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/defaults.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/defaults.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/dirfile.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/dirfile.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/DONE
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/encparse.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/encparse.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/ffcheck.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/ffcheck.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fileio.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fileio.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/filewr.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/filewr.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontdir.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontdir.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontenc.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontenc.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontencc.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontencc.o
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontencI.h
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontfile.c
/home/compromised/jg/build/XMonolithic/xc/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/XMonolithic/xc/lib/font/fontfile/fontfile.o
/home/compromised/jg/buil-	goto out;
-
-    status = _cairo_clip_combine_to_surface (clip, intermediate, extents);
-    if (status)
-	goto out;
-    
-    _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
-    
-    status = _cairo_surface_composite (operator,
-				       src,
-				       &intermediate_pattern.base,
-				       dst,
-				       extents->x, extents->y,
-				       0, 0,
-				       extents->x, extents->y,
-				       extents->width, extents->height);
-    
-    _cairo_pattern_fini (&intermediate_pattern.base);
-    
- out:
-    cairo_surface_destroy (intermediate);
-    
-    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).
@@ -1077,27 +1233,34 @@
     return status;
 }
 
-/* Composites a set of trapezoids in the general case where
-   clip->surface == NULL
- */
 static cairo_status_t
-_composite_traps (cairo_clip_t      *clip,
-		  cairo_pattern_t   *src,
-		  cairo_operator_t   operator,
-		  cairo_surface_t   *dst,
-		  cairo_traps_t     *traps,
-		  cairo_rectangle_t *extents)
+_composite_traps_draw_func (void                    *closure,
+			    cairo_operator_t         operator,
+			    cairo_pattern_t         *src,
+			    cairo_surface_t         *dst,
+			    int                      dst_x,
+			    int                      dst_y,
+			    const cairo_rectangle_t *extents)
 {
+    cairo_traps_t *traps = closure;
+    cairo_pattern_union_t pattern;
     cairo_status_t status;
+    
+    if (dst_x != 0 || dst_y != 0)
+	_cairo_traps_translate (traps, - dst_x, - dst_y);
 
+    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+    if (!src)
+	src = &pattern.base;
+    
     status = _cairo_surface_composite_trapezoids (operator,
 						  src, dst,
-						  extents->x, extents->y,
-						  extents->x, extents->y,
-						  extents->width,
-						  extents->height,
+						  extents->x,         extents->y,
+						  extents->x - dst_x, extents->y - dst_y,
+						  extents->width,     extents->height,
 						  traps->traps,
 						  traps->num_traps);
+    _cairo_pattern_fini (&pattern.base);
 
     return status;
 }
@@ -1134,65 +1297,65 @@
     if (status)
 	return status;
 
-    if (trap_region) {
-	status = _cairo_clip_intersect_to_region (clip, trap_region);
-	_region_rect_extents (trap_region, &extents);
-    } else {
-	cairo_box_t trap_extents;
-	_cairo_traps_extents (traps, &trap_extents);
-	_cairo_box_round_to_rectangle (&trap_extents, &extents);
+    if (_cairo_operator_bounded (operator))
+    {
+	if (trap_region) {
+	    status = _cairo_clip_intersect_to_region (clip, trap_region);
+	    _region_rect_extents (trap_region, &extents);
+	} else {
+	    cairo_box_t trap_extents;
+	    _cairo_traps_extents (traps, &trap_extents);
+	    _cairo_box_round_to_rectangle (&trap_extents, &extents);
+	    status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+	}
+    }
+    else
+    {
+	status = _cairo_surface_get_extents (dst, &extents);
+	if (status)
+	    return status;
 	status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+	if (status)
+	    return status;
     }
 	
     if (status)
 	goto out;
     
-    if (_cairo_rectangle_empty (&extents))
-	/* Nothing to do */
-	goto out;
-
-    if (clip->surface) {
-	if (trap_region) {
-	    /* If we are compositing a set of rectangles, we can set them as the
-	     * clip region for the destination surface and use the clip surface
-	     * as the mask. A clip region might not be supported, in which case
-	     * we fall through to the next method
-	     */
-	    status = _composite_trap_region (clip, src, operator, dst,
-					     trap_region, &extents);
-	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-		goto out;
-	}
-	
-	/* Handle a clip surface by creating an intermediate surface. */
-	status = _composite_traps_intermediate_surface (clip, src, operator,
-							dst, traps, &extents);
-    } else {
-        /* No clip surface */
-	if (trap_region && src->type == CAIRO_PATTERN_SOLID) {
-	    /* Solid rectangles are handled specially */
+    if (trap_region && _cairo_operator_bounded (operator))
+    {
+	if (src->type == CAIRO_PATTERN_SOLID &&
+	    !clip->surface &&
+	    trap_region->
+	{
+	    /* Solid rectangles special case */
 	    status = _composite_trap_region_solid (clip, (cairo_solid_pattern_t *)src,
 						   operator, dst, trap_region);
-	} else {
-	    if (trap_region) {
-		/* 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.
-		 */
-		status = _composite_trap_region (clip, src, operator, dst,
-						 trap_region, &extents);
-		if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-		    goto out;
-
-		/* If a clip regions aren't supported, fall through */
-	    }
-	  
-	  status = _composite_traps (clip, src, operator,
-				     dst, traps, &extents);
+	    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;
     }
 
+    status = _cairo_gstate_clip_and_composite (clip, operator, src,
+					       _composite_traps_draw_func, traps,
+					       dst,
+					       &extents);
+
  out:
     if (trap_region)
 	pixman_region_destroy (trap_region);
@@ -1209,7 +1372,7 @@
   cairo_status_t status;
   
   _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
-
+  
   status = _cairo_surface_clip_and_composite_trapezoids (&pattern.base,
 							 gstate->operator,
 							 gstate->target,
@@ -1681,6 +1844,58 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+typedef struct {
+    cairo_scaled_font_t *font;
+    cairo_glyph_t *glyphs;
+    int num_glyphs;
+} cairo_show_glyphs_info_t;
+
+static cairo_status_t
+_cairo_gstate_show_glyphs_draw_func (void                    *closure,
+				     cairo_operator_t         operator,
+				     cairo_pattern_t         *src,
+				     cairo_surface_t         *dst,
+				     int                      dst_x,
+				     int                      dst_y,
+				     const cairo_rectangle_t *extents)
+{
+    cairo_show_glyphs_info_t *glyph_info = closure;
+    cairo_pattern_union_t pattern;
+    cairo_status_t status;
+
+    /* Modifying the glyph array is fine because we know that this function
+     * will be called only once, and we've already made a copy of the
+     * glyphs in the wrapper.
+     */
+    if (dst_x != 0 || dst_y != 0) {
+	int i;
+	
+	for (i = 0; i < glyph_info->num_glyphs; ++i)
+	{
+	    glyph_info->glyphs[i].x -= dst_x;
+	    glyph_info->glyphs[i].y -= dst_y;
+	}
+    }
+
+    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
+    if (!src)
+	src = &pattern.base;
+    
+    status = _cairo_scaled_font_show_glyphs (glyph_info->font, 
+					     operator, 
+					     src, dst,
+					     extents->x,         extents->y,
+					     extents->x - dst_x, extents->y - dst_y,
+					     extents->width,     extents->height,
+					     glyph_info->glyphs,
+					     glyph_info->num_glyphs);
+
+    if (src == &pattern.base)
+	_cairo_pattern_fini (&pattern.base);
+
+    return status;
+}
+
 cairo_status_t
 _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, 
 			   cairo_glyph_t *glyphs, 
@@ -1692,6 +1907,7 @@
     cairo_pattern_union_t pattern;
     cairo_box_t bbox;
     cairo_rectangle_t extents;
+    cairo_show_glyphs_info_t glyph_info;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1715,112 +1931,41 @@
 				       &transformed_glyphs[i].x, 
 				       &transformed_glyphs[i].y);
     }
-    
-    status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
-					    transformed_glyphs, num_glyphs, 
-					    &bbox);
-    _cairo_box_round_to_rectangle (&bbox, &extents);
 
-    if (status)
-	goto CLEANUP_GLYPHS;
-
-    if (gstate->clip.surface)
+    if (_cairo_operator_bounded (gstate->operator))
     {
-	cairo_surface_t *intermediate;
-	cairo_surface_pattern_t intermediate_pattern;
-	
-	_cairo_rectangle_intersect (&extents, &gstate->clip.surface_rect);
-
-	/* Shortcut if empty */
-	if (_cairo_rectangle_empty (&extents)) {
-	    status = CAIRO_STATUS_SUCCESS;
-	    goto BAIL1;
-	}
-
-	intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
-							    CAIRO_CONTENT_ALPHA,
-							    extents.width,
-							    extents.height,
-							    CAIRO_COLOR_TRANSPARENT);
-	if (intermediate->status) {
-	    status = CAIRO_STATUS_NO_MEMORY;
-	    goto BAIL1;
-	}
-
-	/* move the glyphs again, from dev space to intermediate space */
-	for (i = 0; i < num_glyphs; ++i)
-	{
-	    transformed_glyphs[i].x -= extents.x;
-	    transformed_glyphs[i].y -= extents.y;
-	}
-
-	_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
-    
-	status = _cairo_scaled_font_show_glyphs (gstate->scaled_font, 
-						 CAIRO_OPERATOR_ADD, 
-						 &pattern.base, intermediate,
-						 extents.x, extents.y,
-						 0, 0,
-						 extents.width, extents.height,
-						 transformed_glyphs, num_glyphs);
-	
-	_cairo_pattern_fini (&pattern.base);
-
-	if (status)
-	    goto BAIL2;
-
-	_cairo_pattern_init_for_surface (&pattern.surface,
-					 gstate->clip.surface);
-    
-	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
-					   &pattern.base,
-					   NULL,
-					   intermediate,
-					   extents.x - gstate->clip.surface_rect.x,
-					   extents.y - gstate->clip.surface_rect.y, 
-					   0, 0,
-					   0, 0,
-					   extents.width, extents.height);
-
-	_cairo_pattern_fini (&pattern.base);
-
+	status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font,
+						transformed_glyphs, num_glyphs, 
+						&bbox);
 	if (status)
-	    goto BAIL2;
-
-	_cairo_pattern_init_for_surface (&intermediate_pattern, intermediate);
-	_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
-    
-	status = _cairo_surface_composite (gstate->operator,
-					   &pattern.base,
-					   &intermediate_pattern.base,
-					   gstate->target,
-					   extents.x, extents.y, 
-					   0, 0,
-					   extents.x, extents.y,
-					   extents.width, extents.height);
-	_cairo_pattern_fini (&pattern.base);
-	_cairo_pattern_fini (&intermediate_pattern.base);
-
-    BAIL2:
-	cairo_surface_destroy (intermediate);
-    BAIL1:
-	;
+	    goto CLEANUP_GLYPHS;
+	
+	_cairo_box_round_to_rectangle (&bbox, &extents);
     }
     else
     {
-	_cairo_pattern_init_copy (&pattern.base, gstate->source);
-	_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
+	status = _cairo_surface_get_extents (gstate->target, &extents);
+	if (status)
+	    goto CLEANUP_GLYPHS;
+    }
+    
+    status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
+    if (status)
+	goto CLEANUP_GLYPHS;
+    
+    _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
 
-	status = _cairo_scaled_font_show_glyphs (gstate->scaled_font, 
-						 gstate->operator, &pattern.base,
-						 gstate->target,
-						 extents.x, extents.y,
-						 extents.x, extents.y,
-						 extents.width, extents.height,
-						 transformed_glyphs, num_glyphs);
+    glyph_info.font = gstate->scaled_font;
+    glyph_info.glyphs = transformed_glyphs;
+    glyph_info.num_glyphs = num_glyphs;
+    
+    status = _cairo_gstate_clip_and_composite (&gstate->clip, gstate->operator,
+					       &pattern.base,
+					       _cairo_gstate_show_glyphs_draw_func, &glyph_info,
+					       gstate->target,
+					       &extents);
 
-	_cairo_pattern_fini (&pattern.base);
-    }
+    _cairo_pattern_fini (&pattern.base);
     
  CLEANUP_GLYPHS:
     free (transformed_glyphs);

Index: cairo-image-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-image-surface.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- cairo-image-surface.c	5 Aug 2005 01:44:29 -0000	1.55
+++ cairo-image-surface.c	8 Aug 2005 20:46:11 -0000	1.56
@@ -69,7 +69,8 @@
 
     surface->format = format;
     surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
-    surface->owns_data = 0;
+    surface->owns_data = FALSE;
+    surface->has_clip = FALSE;
 
     surface->width = pixman_image_get_width (pixman_image);
     surface->height = pixman_image_get_height (pixman_image);
@@ -613,6 +614,16 @@
 	}
     }
 
+    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 (mask)
 	_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
     
@@ -644,6 +655,48 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+static pixman_image_t *
+_create_mask_image (int width,
+		    int height)
+{
+    pixman_image_t *image;
+    pixman_color_t pixman_color = { 0, 0, 0, 0 }; /* transparent */
+    pixman_rectangle_t rect;
+    pixman_format_t *format;
+
+    format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
+    if (!format)
+	return NULL;
+
+    image = pixman_image_create (format, width, height);
+    if (!image)
+	return NULL;
+    
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = width;
+    rect.height = height;
+    
+    pixman_fill_rectangles (PIXMAN_OPERATOR_SRC, image,
+			    &pixman_color, &rect, 1);
+
+    return image;
+}
+
+static cairo_bool_t
+_cairo_image_surface_is_alpha_only (cairo_image_surface_t *surface)
+{
+    int bpp, alpha, red, green, blue;
+    
+    if (surface->format != (cairo_format_t) -1)
+	return surface->format == CAIRO_FORMAT_A1 || surface->format == CAIRO_FORMAT_A8;
+
+    pixman_format_get_masks (pixman_image_get_format (surface->pixman_image),
+			     &bpp, &alpha, &red, &green, &blue);
+
+    return red == 0 && blue == 0 && green == 0;
+}
+
 static cairo_int_status_t
 _cairo_image_surface_composite_trapezoids (cairo_operator_t	operator,
 					   cairo_pattern_t	*pattern,
@@ -661,8 +714,30 @@
     cairo_image_surface_t	*dst = abstract_dst;
     cairo_image_surface_t	*src;
     cairo_int_status_t		status;
-    int				render_reference_x, render_reference_y;
-    int				render_src_x, render_src_y;
+    pixman_image_t		*mask;
+
+    /* Special case adding trapezoids onto a mask surface; we want to avoid
+     * creating an intermediate temporary mask unecessarily.
+     *
+     * We make the assumption here that the portion of the trapezoids
+     * contained within the surface is bounded by [dst_x,dst_y,width,height];
+     * the Cairo core code passes bounds based on the trapezoid extents.
+     *
+     * Currently the check surface->has_clip is needed for correct
+     * functioning, since pixman_add_trapezoids() doesn't obey the
+     * surface clip, which is a libpixman bug , but there's no harm in
+     * falling through to the general case when the surface is clipped
+     * since libpixman would have to generate an intermediate mask anyways.
+     */
+    if (operator == CAIRO_OPERATOR_ADD &&
+	_cairo_pattern_is_opaque_solid (pattern) &&
+	_cairo_image_surface_is_alpha_only (dst) &&
+	!dst->has_clip)
+    {
+	pixman_add_trapezoids (dst->pixman_image, 0, 0,
+			       (pixman_trapezoid_t *) traps, num_traps);
+	return CAIRO_STATUS_SUCCESS;
+    }
 
     status = _cairo_pattern_acquire_surface (pattern, &dst->base,
 					     src_x, src_y, width, height,
@@ -671,28 +746,35 @@
     if (status)
 	return status;
 
-    if (traps[0].left.p1.y < traps[0].left.p2.y) {
-	render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x);
-	render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y);
-    } else {
-	render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p2.x);
-	render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y);
-    }
+    status = _cairo_image_surface_set_attributes (src, &attributes);
+    if (status)
+	goto CLEANUP_SOURCE;
 
-    render_src_x = src_x + render_reference_x - dst_x;
-    render_src_y = src_y + render_reference_y - dst_y;
+    mask = _create_mask_image (width, height);
+    if (!mask) {
+	status = CAIRO_STATUS_NO_MEMORY;
+	goto CLEANUP_MASK;
+    }
 
     /* XXX: The pixman_trapezoid_t cast is evil and needs to go away
      * somehow. */
-    status = _cairo_image_surface_set_attributes (src, &attributes);
-    if (status == CAIRO_STATUS_SUCCESS)
-	pixman_composite_trapezoids (_pixman_operator (operator),
-				     src->pixman_image,
-				     dst->pixman_image,
-				     render_src_x + attributes.x_offset,
-				     render_src_y + attributes.y_offset,
-				     (pixman_trapezoid_t *) traps, num_traps);
+    pixman_add_trapezoids (mask, - dst_x, - dst_y,
+			   (pixman_trapezoid_t *) traps, num_traps);
+    
+    pixman_composite (_pixman_operator (operator),
+		      src->pixman_image,
+		      mask,
+		      dst->pixman_image,
+		      src_x + attributes.x_offset,
+		      src_y + attributes.y_offset,
+		      0, 0,
+		      dst_x, dst_y,
+		      width, height);
+	
+ CLEANUP_MASK:
+    pixman_image_destroy (mask);
 
+ CLEANUP_SOURCE:
     _cairo_pattern_release_surface (pattern, &src->base, &attributes);
 
     return status;
@@ -713,6 +795,8 @@
 {
     pixman_image_set_clip_region (surface->pixman_image, region);
 
+    surface->has_clip = region != NULL;
+
     return CAIRO_STATUS_SUCCESS;
 }
 

Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -d -r1.88 -r1.89
--- cairo-surface.c	5 Aug 2005 05:45:59 -0000	1.88
+++ cairo-surface.c	8 Aug 2005 20:46:11 -0000	1.89
@@ -1396,3 +1396,154 @@
 
     return status;
 }
+
+/**
+ * _cairo_surface_composite_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_attr: mask surface attributes or %NULL if no mask
+ * @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()
+ * 
+ * Eeek! Too many parameters! This is a helper function to take care of fixing
+ * up for bugs in libpixman and RENDER where, when asked to composite an
+ * untransformed surface with an unbounded operator (like CLEAR or SOURCE)
+ * 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_surface_composite_fixup_unbounded (cairo_surface_t            *dst,
+					  cairo_surface_attributes_t *src_attr,
+					  int                         src_width,
+					  int                         src_height,
+					  cairo_surface_attributes_t *mask_attr,
+					  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_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;
+
+    /* 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 (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);
+    }
+
+    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;
+
+	_cairo_rectangle_intersect (&drawn_rectangle, &mask_rectangle);
+    }
+
+    /* 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.
+     */
+    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 (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);
+    }
+}
+

Index: cairo-xlib-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib-surface.c,v
retrieving revision 1.104
retrieving revision 1.105
diff -u -d -r1.104 -r1.105
--- cairo-xlib-surface.c	5 Aug 2005 01:44:29 -0000	1.104
+++ cairo-xlib-surface.c	8 Aug 2005 20:46:11 -0000	1.105
@@ -1137,6 +1137,16 @@
 			      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);
 	break;
 
     case DO_XCOPYAREA:
@@ -1214,6 +1224,96 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+/* Creates an A8 picture of size @width x @height, initialized with @color
+ */
+static Picture
+_create_a8_picture (cairo_xlib_surface_t *surface,
+		    XRenderColor         *color,
+		    int                   width,
+		    int                   height,
+		    cairo_bool_t          repeat)
+{
+    XRenderPictureAttributes pa;
+    unsigned long mask = 0;
+
+    Pixmap pixmap = XCreatePixmap (surface->dpy, surface->drawable,
+				   width, height,
+				   8);
+    Picture picture;
+
+    if (repeat) {
+	pa.repeat = TRUE;
+	mask = CPRepeat;
+    }
+    
+    picture = XRenderCreatePicture (surface->dpy, pixmap,
+				    XRenderFindStandardFormat (surface->dpy, PictStandardA8),
+				    mask, &pa);
+    XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color,
+			  0, 0, width, height);
+    XFreePixmap (surface->dpy, pixmap);
+    
+    return picture;
+}
+
+/* Creates a temporary mask for the trapezoids covering the area
+ * [@dst_x, @dst_y, @width, @height] of the destination surface.
+ */
+static Picture
+_create_trapezoid_mask (cairo_xlib_surface_t *dst,
+			cairo_trapezoid_t    *traps,
+			int                   num_traps,
+			int                   dst_x,
+			int                   dst_y,
+			int                   width,
+			int                   height)
+			
+{
+    XRenderColor transparent = { 0, 0, 0, 0 };
+    XRenderColor solid = { 0xffff, 0xffff, 0xffff, 0xffff };
+    Picture mask_picture, solid_picture;
+    XTrapezoid *offset_traps;
+    int i;
+
+    /* This would be considerably simpler using XRenderAddTraps(), but since
+     * we are only using this in the unbounded-operator case, we stick with
+     * XRenderCompositeTrapezoids, which is available on older versions
+     * of RENDER rather than conditionalizing. We should still hit an
+     * optimization that avoids creating another intermediate surface on
+     * the servers that have XRenderAddTraps().
+     */
+    mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
+    solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
+
+    offset_traps = malloc (sizeof (XTrapezoid) * num_traps);
+    if (!offset_traps)
+	return None;
+
+    for (i = 0; i < num_traps; i++) {
+	offset_traps[i].top = traps[i].top - 0x10000 * dst_y;
+	offset_traps[i].bottom = traps[i].bottom - 0x10000 * dst_y;
+	offset_traps[i].left.p1.x = traps[i].left.p1.x - 0x10000 * dst_x;
+	offset_traps[i].left.p1.y = traps[i].left.p1.y - 0x10000 * dst_y;
+	offset_traps[i].left.p2.x = traps[i].left.p2.x - 0x10000 * dst_x;
+	offset_traps[i].left.p2.y = traps[i].left.p2.y - 0x10000 * dst_y;
+	offset_traps[i].right.p1.x = traps[i].right.p1.x - 0x10000 * dst_x;
+	offset_traps[i].right.p1.y = traps[i].right.p1.y - 0x10000 * dst_y;
+	offset_traps[i].right.p2.x = traps[i].right.p2.x - 0x10000 * dst_x;
+	offset_traps[i].right.p2.y = traps[i].right.p2.y - 0x10000 * dst_y;
+    }
+
+    XRenderCompositeTrapezoids (dst->dpy, PictOpAdd,
+				solid_picture, mask_picture,
+				XRenderFindStandardFormat (dst->dpy, PictStandardA8),
+				0, 0,
+				offset_traps, num_traps);
+    
+    XRenderFreePicture (dst->dpy, solid_picture);
+    free (offset_traps);
+
+    return mask_picture;
+}
+
 static cairo_int_status_t
 _cairo_xlib_surface_composite_trapezoids (cairo_operator_t	operator,
 					  cairo_pattern_t	*pattern,
@@ -1266,10 +1366,43 @@
     render_src_x = src_x + render_reference_x - dst_x;
     render_src_y = src_y + render_reference_y - dst_y;
 
-    /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
     _cairo_xlib_surface_ensure_dst_picture (dst);
     status = _cairo_xlib_surface_set_attributes (src, &attributes);
-    if (status == CAIRO_STATUS_SUCCESS)
+    if (status)
+	goto FAIL;
+
+    if (!_cairo_operator_bounded (operator)) {
+	/* XRenderCompositeTrapezoids() creates a mask only large enough for the
+	 * trapezoids themselves, but if the operator is unbounded, then we need
+	 * to actually composite all the way out to the bounds, so we create
+	 * the mask and composite ourselves. There actually would
+	 * be benefit to doing this in all cases, since RENDER implementations
+	 * will frequently create a too temporary big mask, ignoring destination
+	 * bounds and clip. (XRenderAddTraps() could be used to make creating
+	 * the mask somewhat cheaper.)
+	 */
+	Picture mask_picture = _create_trapezoid_mask (dst, traps, num_traps,
+						       dst_x, dst_y, width, height);
+	if (!mask_picture) {
+	    status = CAIRO_STATUS_NO_MEMORY;
+	    goto FAIL;
+	}
+
+	XRenderComposite (dst->dpy,
+			  _render_operator (operator),
+			  src->src_picture,
+			  mask_picture,
+			  dst->dst_picture,
+			  src_x + attributes.x_offset,
+			  src_y + attributes.y_offset,
+			  0, 0,
+			  dst_x, dst_y,
+			  width, height);
+	
+	XRenderFreePicture (dst->dpy, mask_picture);
+	
+    } else {
+	/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
 	XRenderCompositeTrapezoids (dst->dpy,
 				    _render_operator (operator),
 				    src->src_picture, dst->dst_picture,
@@ -1277,6 +1410,7 @@
 				    render_src_x + attributes.x_offset, 
 				    render_src_y + attributes.y_offset,
 				    (XTrapezoid *) traps, num_traps);
+    }
 
  FAIL:
     _cairo_pattern_release_surface (pattern, &src->base, &attributes);
@@ -1735,6 +1869,7 @@
     cairo_glyph_cache_key_t key;
     GlyphSet glyphset;
     Glyph glyph;
+    cairo_glyph_size_t size;
 } glyphset_cache_entry_t;
 
 static Glyph
@@ -1789,6 +1924,7 @@
 	entry->glyph = None;
 	entry->glyphset = None;
 	entry->key.base.memory = 0;
+	entry->size.x = entry->size.y = entry->size.width = entry->size.height = 0;
 	
 	goto out;
     }
@@ -1797,6 +1933,8 @@
 
     data = im->image->data;
 
+    entry->size = im->size;
+
     glyph_info.width = im->size.width;
     glyph_info.height = im->size.height;
 
@@ -2123,7 +2261,7 @@
 			    _render_operator (operator),
 			    src->src_picture,
 			    self->dst_picture,
-			    cache->a8_pict_format,
+			    mask_format,
 			    source_x, source_y,
 			    0, 0,
 			    elts, count);
@@ -2351,7 +2489,70 @@
     return CAIRO_STATUS_NO_MEMORY;
 }
 
+/* Handles clearing the regions that are outside of the temporary
+ * mask created by XRenderCompositeText[N] but should be affected
+ * by an unbounded operator like CAIRO_OPERATOR_SOURCE.
+ */
+static void
+_show_glyphs_fixup_unbounded (cairo_xlib_surface_t       *self,
+			      cairo_surface_attributes_t *src_attr,
+			      cairo_xlib_surface_t       *src,
+			      const cairo_glyph_t        *glyphs,
+			      glyphset_cache_entry_t    **entries,
+			      int                         num_glyphs,
+			      int                         src_x,
+			      int                         src_y,
+			      int                         dst_x,
+			      int                         dst_y,
+			      int                         width,
+			      int                         height)
+{
+    cairo_surface_attributes_t mask_attr;
+    int x1 = INT_MAX;
+    int x2 = INT_MIN;
+    int y1 = INT_MAX;
+    int y2 = INT_MIN;
+    int i;
 
+    /* Compute the size of the glyph mask as the bounding box
+     * of all the glyphs.
+     */
+    for (i = 0; i < num_glyphs; ++i) {
+	int thisX, thisY;
+	
+	if (entries[i] == NULL || !entries[i]->glyph) 
+	    continue;
+	
+	thisX = (int) floor (glyphs[i].x + 0.5);
+	thisY = (int) floor (glyphs[i].y + 0.5);
+	
+	if (thisX + entries[i]->size.x < x1)
+	    x1 = thisX + entries[i]->size.x;
+	if (thisX + entries[i]->size.x + entries[i]->size.width > x2)
+	    x2 = thisX + entries[i]->size.x + entries[i]->size.width;
+	if (thisY + entries[i]->size.y < y1)
+	    y1 = thisY + entries[i]->size.y;
+	if (thisY + entries[i]->size.y + entries[i]->size.height > y2)
+	    y2 = thisY + entries[i]->size.y + entries[i]->size.height;
+    }
+
+    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);
+}
+    
 static cairo_int_status_t
 _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t    *scaled_font,
 				 cairo_operator_t       operator,
@@ -2462,6 +2663,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);
+
  UNLOCK:
     _unlock_xlib_glyphset_caches (cache);
 

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.186
retrieving revision 1.187
diff -u -d -r1.186 -r1.187
--- cairoint.h	6 Aug 2005 05:29:06 -0000	1.186
+++ cairoint.h	8 Aug 2005 20:46:11 -0000	1.187
@@ -879,7 +879,9 @@
     /* libic-specific fields */
     cairo_format_t format;
     unsigned char *data;
-    int owns_data;
+    cairo_bool_t owns_data;
+    cairo_bool_t has_clip;
+  
 
     int width;
     int height;
@@ -1312,6 +1314,8 @@
 			  int		      num_glyphs,
 			  cairo_path_fixed_t *path);
 
+cairo_bool_t
+_cairo_operator_bounded (cairo_operator_t operator);
 
 /* cairo_color.c */
 cairo_private const cairo_color_t *
@@ -1695,6 +1699,23 @@
 			    const cairo_glyph_t		*glyphs,
 			    int				num_glyphs);
 
+void
+_cairo_surface_composite_fixup_unbounded (cairo_surface_t            *dst,
+					  cairo_surface_attributes_t *src_attr,
+					  int                         src_width,
+					  int                         src_height,
+					  cairo_surface_attributes_t *mask_attr,
+					  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




More information about the cairo-commit mailing list