[cairo-commit] cairo/src cairo-xlib.h, 1.9, 1.10 cairo.h, 1.82, 1.83 cairo_gstate.c, 1.92, 1.93 cairo_surface.c, 1.48, 1.49 cairo_xlib_surface.c, 1.49, 1.50 cairoint.h, 1.106, 1.107

Owen Taylor commit at pdx.freedesktop.org
Thu Mar 17 12:57:45 PST 2005


Committed by: otaylor

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

Modified Files:
	cairo-xlib.h cairo.h cairo_gstate.c cairo_surface.c 
	cairo_xlib_surface.c cairoint.h 
Log Message:
2005-03-17  Owen Taylor  <otaylor at redhat.com>

        * src/cairo.h src/cairo_surface.c src/cairo-xlib.h
        src/cairo_xlib_surface.c: Move cairo_xlib_surface_set_device_offset()
        to a generic cairo_surface_set_device_offset().

        * src/cairo_gstate.c: Take the surface's device offset into
        account.

        * doc/public/cairo-sections.txt: Update.


Index: cairo-xlib.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-xlib.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cairo-xlib.h	16 Mar 2005 00:25:30 -0000	1.9
+++ cairo-xlib.h	17 Mar 2005 20:57:43 -0000	1.10
@@ -80,11 +80,6 @@
 			     int              width,
 			     int              height);
 
-void
-cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
-				      int              x_offset,
-				      int              y_offset);
-
 CAIRO_END_DECLS
 
 #endif /* CAIRO_HAS_XLIB_SURFACE */

Index: cairo.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.h,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -d -r1.82 -r1.83
--- cairo.h	16 Mar 2005 20:08:41 -0000	1.82
+++ cairo.h	17 Mar 2005 20:57:43 -0000	1.83
@@ -883,6 +883,11 @@
 			     void			 *user_data,
 			     cairo_destroy_func_t	 destroy);
 
+void
+cairo_surface_set_device_offset (cairo_surface_t *surface,
+				 double           x_offset,
+				 double           y_offset);
+
 /* Image-surface functions */
 
 cairo_surface_t *

Index: cairo_gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_gstate.c,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -d -r1.92 -r1.93
--- cairo_gstate.c	9 Mar 2005 20:35:36 -0000	1.92
+++ cairo_gstate.c	17 Mar 2005 20:57:43 -0000	1.93
@@ -723,6 +723,26 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+static void
+_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
+{
+    cairo_matrix_transform_point (&gstate->ctm, x, y);
+    if (gstate->surface) {
+	*x += gstate->surface->device_x_offset;
+	*y += gstate->surface->device_y_offset;
+    }
+}
+
+static void
+_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
+{
+    if (gstate->surface) {
+	*x -= gstate->surface->device_x_offset;
+	*y -= gstate->surface->device_y_offset;
+    }
+    cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
+}
+
 cairo_status_t
 _cairo_gstate_inverse_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
 {
@@ -744,7 +764,7 @@
 {
     cairo_point_t point;
 
-    cairo_matrix_transform_point (&gstate->ctm, &x, &y);
+    _cairo_gstate_user_to_backend (gstate, &x, &y);
 
     point.x = _cairo_fixed_from_double (x);
     point.y = _cairo_fixed_from_double (y);
@@ -757,7 +777,7 @@
 {
     cairo_point_t point;
 
-    cairo_matrix_transform_point (&gstate->ctm, &x, &y);
+    _cairo_gstate_user_to_backend (gstate, &x, &y);
 
     point.x = _cairo_fixed_from_double (x);
     point.y = _cairo_fixed_from_double (y);
@@ -773,9 +793,9 @@
 {
     cairo_point_t p0, p1, p2;
 
-    cairo_matrix_transform_point (&gstate->ctm, &x0, &y0);
-    cairo_matrix_transform_point (&gstate->ctm, &x1, &y1);
-    cairo_matrix_transform_point (&gstate->ctm, &x2, &y2);
+    _cairo_gstate_user_to_backend (gstate, &x0, &y0);
+    _cairo_gstate_user_to_backend (gstate, &x1, &y1);
+    _cairo_gstate_user_to_backend (gstate, &x2, &y2);
 
     p0.x = _cairo_fixed_from_double (x0);
     p0.y = _cairo_fixed_from_double (y0);
@@ -1146,7 +1166,7 @@
     } else {
 	x = _cairo_fixed_to_double (point.x);
 	y = _cairo_fixed_to_double (point.y);
-	cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
+	_cairo_gstate_backend_to_user (gstate, &x, &y);
     }
 
     if (x_ret)
@@ -1289,6 +1309,11 @@
     _cairo_path_init_copy (&path, &gstate->path);
 
     cairo_matrix_copy (&gpi.ctm_inverse, &gstate->ctm_inverse);
+    if (gstate->surface)
+	cairo_matrix_translate (&gpi.ctm_inverse,
+				- gstate->surface->device_x_offset,
+				- gstate->surface->device_y_offset);
+				
     gpi.tolerance = gstate->tolerance;
 
     gpi.move_to = move_to;
@@ -1309,6 +1334,20 @@
 				  &gpi);
 }
 
+static void
+_cairo_gstate_pattern_transform (cairo_gstate_t  *gstate,
+				 cairo_pattern_t *pattern)
+{
+    cairo_matrix_t tmp_matrix = gstate->ctm_inverse;
+    
+    if (gstate->surface)
+	cairo_matrix_translate (&tmp_matrix,
+				- gstate->surface->device_x_offset,
+				- gstate->surface->device_y_offset);
+
+    _cairo_pattern_transform (pattern, &tmp_matrix);
+}
+
 /* XXX: gstate->alpha will be going away before too long, and when it
  * does, it may make sense for this function to just disappear.
  */
@@ -1318,7 +1357,7 @@
 				 cairo_pattern_t       *src)
 {
     _cairo_pattern_init_copy (&pattern->base, src);
-    _cairo_pattern_transform (&pattern->base, &gstate->ctm_inverse);
+    _cairo_gstate_pattern_transform (gstate, &pattern->base);
     _cairo_pattern_set_alpha (&pattern->base, gstate->alpha);
 }
 
@@ -1363,7 +1402,7 @@
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_traps_t traps;
 
-    cairo_matrix_transform_point (&gstate->ctm, &x, &y);
+    _cairo_gstate_user_to_backend (gstate, &x, &y);
 
     _cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
 
@@ -1658,7 +1697,7 @@
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_traps_t traps;
 
-    cairo_matrix_transform_point (&gstate->ctm, &x, &y);
+    _cairo_gstate_user_to_backend (gstate, &x, &y);
 
     _cairo_traps_init (&traps);
 
@@ -1714,8 +1753,8 @@
     *x2 = _cairo_fixed_to_double (extents.p2.x);
     *y2 = _cairo_fixed_to_double (extents.p2.y);
 
-    cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
-    cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
+    _cairo_gstate_backend_to_user (gstate, x1, y1);
+    _cairo_gstate_backend_to_user (gstate, x2, y2);
   
 BAIL:
     _cairo_traps_fini (&traps);
@@ -1745,8 +1784,8 @@
     *x2 = _cairo_fixed_to_double (extents.p2.x);
     *y2 = _cairo_fixed_to_double (extents.p2.y);
 
-    cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
-    cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
+    _cairo_gstate_backend_to_user (gstate, x1, y1);
+    _cairo_gstate_backend_to_user (gstate, x2, y2);
   
 BAIL:
     _cairo_traps_fini (&traps);
@@ -2004,9 +2043,9 @@
      */
 
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    cairo_matrix_t image_to_user, image_to_device;
-    double device_x, device_y;
-    double device_width, device_height;
+    cairo_matrix_t image_to_user, image_to_device, image_to_backend;
+    double backend_x, backend_y;
+    double backend_width, backend_height;
     cairo_surface_pattern_t pattern;
     cairo_box_t pattern_extents;
     cairo_rectangle_t extents;
@@ -2014,13 +2053,23 @@
     cairo_surface_get_matrix (surface, &image_to_user);
     cairo_matrix_invert (&image_to_user);
     cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
+    if (gstate->surface) {
+	cairo_matrix_t device_to_backend;
+	
+	_cairo_matrix_set_translate (&device_to_backend,
+				     gstate->surface->device_x_offset,
+				     gstate->surface->device_y_offset);
+	cairo_matrix_multiply (&image_to_backend, &image_to_device, &device_to_backend);
+    } else {
+	image_to_backend = image_to_device;
+    }
 
-    _cairo_gstate_get_current_point (gstate, &device_x, &device_y);
-    device_width = width;
-    device_height = height;
-    _cairo_matrix_transform_bounding_box (&image_to_device,
-					  &device_x, &device_y,
-					  &device_width, &device_height);
+    _cairo_gstate_get_current_point (gstate, &backend_x, &backend_y);
+    backend_width = width;
+    backend_height = height;
+    _cairo_matrix_transform_bounding_box (&image_to_backend,
+					  &backend_x, &backend_y,
+					  &backend_width, &backend_height);
 
     _cairo_pattern_init_for_surface (&pattern, surface);
 
@@ -2033,13 +2082,13 @@
     else
 	pattern.base.extend = CAIRO_EXTEND_NONE;
     
-    _cairo_pattern_transform (&pattern.base, &gstate->ctm_inverse);
+    _cairo_gstate_pattern_transform (gstate, &pattern.base);
     _cairo_pattern_set_alpha (&pattern.base, gstate->alpha);
 
-    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);
+    pattern_extents.p1.x = _cairo_fixed_from_double (backend_x);
+    pattern_extents.p1.y = _cairo_fixed_from_double (backend_y);
+    pattern_extents.p2.x = _cairo_fixed_from_double (backend_x + backend_width);
+    pattern_extents.p2.y = _cairo_fixed_from_double (backend_y + backend_height);
     _cairo_box_round_to_rectangle (&pattern_extents, &extents);
 
     if (gstate->clip.surface)
@@ -2334,8 +2383,8 @@
     } else {
 	origin_x = _cairo_fixed_to_double (point.x);
 	origin_y = _cairo_fixed_to_double (point.y);
-	cairo_matrix_transform_point (&gstate->ctm_inverse,
-				      &origin_x, &origin_y);
+	_cairo_gstate_backend_to_user (gstate,
+				       &origin_x, &origin_y);
     }
 
     status = _cairo_font_text_to_glyphs (gstate->font, 
@@ -2417,9 +2466,9 @@
     for (i = 0; i < num_glyphs; ++i)
     {
 	transformed_glyphs[i] = glyphs[i];
-	cairo_matrix_transform_point (&gstate->ctm, 
-				      &transformed_glyphs[i].x, 
-				      &transformed_glyphs[i].y);
+	_cairo_gstate_user_to_backend (gstate,
+				       &transformed_glyphs[i].x, 
+				       &transformed_glyphs[i].y);
     }
     
     status = _cairo_font_glyph_bbox (gstate->font,
@@ -2552,9 +2601,9 @@
     for (i = 0; i < num_glyphs; ++i)
     {
 	transformed_glyphs[i] = glyphs[i];
-	cairo_matrix_transform_point (&gstate->ctm, 
-				      &(transformed_glyphs[i].x), 
-				      &(transformed_glyphs[i].y));
+	_cairo_gstate_user_to_backend (gstate,
+				       &(transformed_glyphs[i].x), 
+				       &(transformed_glyphs[i].y));
     }
 
     status = _cairo_font_glyph_path (gstate->font,

Index: cairo_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_surface.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- cairo_surface.c	16 Mar 2005 20:15:29 -0000	1.48
+++ cairo_surface.c	17 Mar 2005 20:57:43 -0000	1.49
@@ -59,6 +59,9 @@
     _cairo_matrix_init (&surface->matrix);
     surface->filter = CAIRO_FILTER_NEAREST;
     surface->repeat = 0;
+
+    surface->device_x_offset = 0;
+    surface->device_y_offset = 0;
 }
 
 cairo_surface_t *
@@ -290,6 +293,33 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+/**
+ * cairo_surface_set_device_offset:
+ * @surface: a #cairo_surface_t
+ * @x_offset: the offset in the X direction, in device units
+ * @y_offset: the offset in the Y direction, in device units
+ * 
+ * Sets an offset that is added to the device coordinates determined
+ * by the CTM when drawing to @surface. One use case for this function
+ * is when we want to create a #cairo_surface_t that redirects drawing
+ * for a portion of an onscreen surface to an offscreen surface in a
+ * way that is completely invisible to the user of the cairo
+ * API. Setting a transformation via cairo_translate() isn't
+ * sufficient to do this, since functions like
+ * cairo_inverse_transform_point() will expose the hidden offset.
+ *
+ * Note that the offset only affects drawing to the surface, not using
+ * the surface in a surface pattern.
+ **/
+void
+cairo_surface_set_device_offset (cairo_surface_t *surface,
+				 double           x_offset,
+				 double           y_offset)
+{
+    surface->device_x_offset = x_offset;
+    surface->device_y_offset = y_offset;
+}
+
 double
 _cairo_surface_pixels_per_inch (cairo_surface_t *surface)
 {

Index: cairo_xlib_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xlib_surface.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- cairo_xlib_surface.c	16 Mar 2005 20:08:41 -0000	1.49
+++ cairo_xlib_surface.c	17 Mar 2005 20:57:43 -0000	1.50
@@ -105,9 +105,6 @@
     int height;
     int depth;
 
-    int x_offset;
-    int y_offset;
-
     Picture picture;
 };
 
@@ -252,8 +249,8 @@
     if (interest_rect) {
 	cairo_rectangle_t rect;
 	
-	rect.x = interest_rect->x + surface->x_offset;
-	rect.y = interest_rect->y + surface->x_offset;
+	rect.x = interest_rect->x;
+	rect.y = interest_rect->y;
 	rect.width = interest_rect->width;
 	rect.height = interest_rect->width;
     
@@ -273,8 +270,8 @@
     }
 
     if (image_rect) {
-	image_rect->x = x1 - surface->x_offset;
-	image_rect->y = y1 - surface->y_offset;
+	image_rect->x = x1;
+	image_rect->y = y1;
 	image_rect->width = x2 - x1;
 	image_rect->height = y2 - y1;
     }
@@ -396,7 +393,7 @@
 
     _cairo_xlib_surface_ensure_gc (surface);
     XPutImage(surface->dpy, surface->drawable, surface->gc,
-	      ximage, 0, 0, dst_x + surface->x_offset, dst_y + surface->y_offset,
+	      ximage, 0, 0, dst_x, dst_y,
 	      image->width, image->height);
 
     /* Foolish XDestroyImage thinks it can free my data, but I won't
@@ -735,7 +732,7 @@
 			      src_x + src_attr.x_offset,
 			      src_y + src_attr.y_offset,
 			      0, 0,
-			      dst_x + dst->x_offset, dst_y + dst->y_offset,
+			      dst_x, dst_y,
 			      width, height);
 	}
     }
@@ -748,20 +745,6 @@
     return status;
 }
 
-static void
-_translate_rects (cairo_rectangle_t *rects,
-		  int                num_rects,
-		  int                x_offset,
-		  int                y_offset)
-{
-    int i;
-
-    for (i = 0; i < num_rects; i++) {
-	rects[i].x += x_offset;
-	rects[i].y += y_offset;
-    }
-}
-
 static cairo_int_status_t
 _cairo_xlib_surface_fill_rectangles (void			*abstract_surface,
 				     cairo_operator_t		operator,
@@ -780,10 +763,6 @@
     render_color.blue  = color->blue_short;
     render_color.alpha = color->alpha_short;
 
-    if (surface->x_offset != 0 || surface->y_offset != 0)
-	_translate_rects (rects, num_rects,
-			  surface->x_offset, surface->y_offset);
-
     /* XXX: This XRectangle cast is evil... it needs to go away somehow. */
     XRenderFillRectangles (surface->dpy,
 			   _render_operator (operator),
@@ -793,31 +772,6 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_translate_traps (cairo_trapezoid_t *traps,
-		  int                num_traps,
-		  int                x_offset,
-		  int                y_offset)
-{
-    cairo_fixed_t xoff, yoff;
-    int i;
-
-    xoff = _cairo_fixed_from_int (x_offset);
-    yoff = _cairo_fixed_from_int (y_offset);
-
-    for (i = 0; i < num_traps; i++) {
-	traps[i].top += yoff;
-	traps[i].bottom += yoff;
-	traps[i].left.p1.x += xoff;
-	traps[i].left.p1.y += yoff;
-	traps[i].left.p2.x += xoff;
-	traps[i].left.p2.y += yoff;
-	traps[i].right.p1.x += xoff;
-	traps[i].right.p1.y += yoff;
-	traps[i].right.p2.x += xoff;
-	traps[i].right.p2.y += yoff;
-    }
-}
 static cairo_int_status_t
 _cairo_xlib_surface_composite_trapezoids (cairo_operator_t	operator,
 					  cairo_pattern_t	*pattern,
@@ -848,9 +802,6 @@
     if (status)
 	return status;
     
-    if (dst->x_offset != 0 || dst->y_offset != 0)
-	_translate_traps (traps, num_traps, dst->x_offset, dst->y_offset);
-
     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);
@@ -859,8 +810,8 @@
 	render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y);
     }
 
-    render_src_x = src_x + render_reference_x - (dst_x + dst->x_offset);
-    render_src_y = src_y + render_reference_y - (dst_y + dst->y_offset);
+    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. */
     status = _cairo_xlib_surface_set_attributes (src, &attributes);
@@ -923,8 +874,8 @@
 	boxes = pixman_region_rects (region);
 	
 	for (i = 0; i < n_boxes; i++) {
-	    rects[i].x = boxes[i].x1 + surface->x_offset;
-	    rects[i].y = boxes[i].y1 + surface->y_offset;
+	    rects[i].x = boxes[i].x1;
+	    rects[i].y = boxes[i].y1;
 	    rects[i].width = boxes[i].x2 - boxes[i].x1;
 	    rects[i].height = boxes[i].y2 - boxes[i].y1;
 	}
@@ -999,8 +950,6 @@
     surface->owns_pixmap = FALSE;
     surface->width = -1;
     surface->height = -1;
-    surface->x_offset = 0;
-    surface->y_offset = 0;
     
     if (visual) {
 	int i, j, k;
@@ -1204,34 +1153,6 @@
     xlib_surface->height = height;
 }
 
-/**
- * cairo_xlib_surface_set_device_offset:
- * @surface: a #cairo_surface_t for the XLib backend
- * @x_offset: offset in the X direction, in pixels
- * @y_offset: offset in the Y direction, in pixels
- * 
- * Sets an offset that is added to the device coordinates determined
- * by the CTM when drawing to @surface. This is useful when we want
- * to redirect drawing to a window to a backing pixmap for a portion
- * of the window in a way that is completely invisible to the user
- * of the Cairo API. Setting a transformation via cairo_translate() isn't
- * sufficient to do this, since functions like
- * cairo_inverse_transform_point() will expose the hidden offset.
- *
- * Note that the offset only affects drawing to the surface, not using
- * the surface in a surface pattern.
- **/
-void
-cairo_xlib_surface_set_device_offset (cairo_surface_t *surface,
-				      int              x_offset,
-				      int              y_offset)
-{
-  cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *)surface;
-
-  xlib_surface->x_offset = x_offset;
-  xlib_surface->y_offset = y_offset;
-}
-
 /* RENDER glyphset cache code */
 
 typedef struct glyphset_cache {
@@ -1488,8 +1409,8 @@
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = g->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
-	thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
+	thisX = (int) floor (glyphs[i].x + 0.5);
+	thisY = (int) floor (glyphs[i].y + 0.5);
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
@@ -1565,8 +1486,8 @@
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = g->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
-	thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
+	thisX = (int) floor (glyphs[i].x + 0.5);
+	thisY = (int) floor (glyphs[i].y + 0.5);
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;
@@ -1641,8 +1562,8 @@
 	elts[i].chars = &(chars[i]);
 	elts[i].nchars = 1;
 	elts[i].glyphset = g->glyphset;
-	thisX = (int) floor (glyphs[i].x + 0.5) + self->x_offset;
-	thisY = (int) floor (glyphs[i].y + 0.5) + self->y_offset;
+	thisX = (int) floor (glyphs[i].x + 0.5);
+	thisY = (int) floor (glyphs[i].y + 0.5);
 	elts[i].xOff = thisX - lastX;
 	elts[i].yOff = thisY - lastY;
 	lastX = thisX;

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -d -r1.106 -r1.107
--- cairoint.h	16 Mar 2005 20:08:41 -0000	1.106
+++ cairoint.h	17 Mar 2005 20:57:43 -0000	1.107
@@ -673,6 +673,9 @@
     cairo_matrix_t matrix;
     cairo_filter_t filter;
     int repeat;
+
+    double device_x_offset;
+    double device_y_offset;
 };
 
 struct _cairo_image_surface {




More information about the cairo-commit mailing list