[cairo-commit] src/cairo-xlib-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jun 11 02:42:54 PDT 2010


 src/cairo-xlib-surface.c |   74 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 65 insertions(+), 9 deletions(-)

New commits:
commit 55037bfb2454a671332d961e061c712ab5471580
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Fri Jun 11 10:35:43 2010 +0100

    xlib: Find matching Visual for XRenderFormat
    
    Not only is this useful for users to know which Visual matches any
    particular Cairo surface, it should also close a few obscure bugs of not
    converting images correctly on upload.
    
    Fixes:
    
      Bug 28492 - cairo_xlib_surface_create_with_xrender_format does not
                  create visual for resulting surface
      https://bugs.freedesktop.org/show_bug.cgi?id=28492
    
      Mozilla Bug 567065 - Try to create offscreen Xlib surface from existing
                           visual if possible
      https://bugzilla.mozilla.org/show_bug.cgi?id=567065
    
      Mozilla Bug 445250 - cairo_draw_with_xlib should provide a non-NULL visual
                           to callback
      https://bugzilla.mozilla.org/show_bug.cgi?id=445250
    
    Reported-by: Oleg Romashin <romaxa at gmail.com>

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 93467ff..7593316 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -183,6 +183,56 @@ static const XTransform identity = { {
       (CAIRO_SURFACE_RENDER_HAS_PDF_OPERATORS(surface) &&	\
        (op) <= CAIRO_OPERATOR_HSL_LUMINOSITY))
 
+static Visual *
+_visual_for_xrender_format(Screen *screen,
+			   XRenderPictFormat *xrender_format)
+{
+    int d, v;
+
+    /* XXX Consider searching through the list of known cairo_visual_t for
+     * the reverse mapping.
+     */
+
+    for (d = 0; d < screen->ndepths; d++) {
+	Depth *d_info = &screen->depths[d];
+
+	if (d_info->depth != xrender_format->depth)
+	    continue;
+
+	for (v = 0; v < d_info->nvisuals; v++) {
+	    Visual *visual = &d_info->visuals[v];
+
+	    switch (visual->class) {
+	    case TrueColor:
+		if (xrender_format->type != PictTypeDirect)
+		    continue;
+		break;
+
+	    case DirectColor:
+		/* Prefer TrueColor to DirectColor.
+		 * (XRenderFindVisualFormat considers both TrueColor and DirectColor
+		 * Visuals to match the same PictFormat.)
+		 */
+		continue;
+
+	    case StaticGray:
+	    case GrayScale:
+	    case StaticColor:
+	    case PseudoColor:
+		if (xrender_format->type != PictTypeIndexed)
+		    continue;
+		break;
+	    }
+
+	    if (xrender_format ==
+		XRenderFindVisualFormat (DisplayOfScreen(screen), visual))
+		return visual;
+	}
+    }
+
+    return NULL;
+}
+
 static cairo_status_t
 _cairo_xlib_surface_set_clip_region (cairo_xlib_surface_t *surface,
 				     cairo_region_t *region)
@@ -306,9 +356,11 @@ _cairo_xlib_surface_create_similar (void	       *abstract_src,
 			     width <= 0 ? 1 : width, height <= 0 ? 1 : height,
 			     xrender_format->depth);
 
-	visual = NULL;
 	if (xrender_format == src->xrender_format)
 	    visual = src->visual;
+	else
+	    visual = _visual_for_xrender_format(src->screen->screen,
+					        xrender_format);
 
 	surface = (cairo_xlib_surface_t *)
 		  _cairo_xlib_surface_create_internal (src->screen, pix,
@@ -3235,8 +3287,8 @@ cairo_xlib_surface_create_with_xrender_format (Display		    *dpy,
     X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
 
     return _cairo_xlib_surface_create_internal (screen, drawable,
-                                                NULL, format,
-                                                width, height, 0);
+						_visual_for_xrender_format (scr, format),
+                                                format, width, height, 0);
 }
 slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
 
@@ -3468,23 +3520,27 @@ cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
  * cairo_xlib_surface_get_visual:
  * @surface: a #cairo_xlib_surface_t
  *
- * Get the X Visual used for underlying X Drawable.
+ * Gets the X Visual associated with @surface, suitable for use with the
+ * underlying X Drawable.  If @surface was created by
+ * cairo_xlib_surface_create(), the return value is the Visual passed to that
+ * constructor.
  *
- * Return value: the visual.
+ * Return value: the Visual or %NULL if there is no appropriate Visual for
+ * @surface.
  *
  * Since: 1.2
  **/
 Visual *
-cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
+cairo_xlib_surface_get_visual (cairo_surface_t *surface)
 {
-    cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
+    cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
 
-    if (! _cairo_surface_is_xlib (abstract_surface)) {
+    if (! _cairo_surface_is_xlib (surface)) {
 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
 	return NULL;
     }
 
-    return surface->visual;
+    return xlib_surface->visual;
 }
 
 /**


More information about the cairo-commit mailing list