diff options
author | Karl Tomlinson <karlt+@karlt.net> | 2010-06-11 10:35:43 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-06-11 10:42:15 +0100 |
commit | 55037bfb2454a671332d961e061c712ab5471580 (patch) | |
tree | dbb004938c6164830e0d409a9909e46d319d69f6 /src | |
parent | cf426bce8ebd3aff5d50c6a54bbd731132b3d312 (diff) |
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@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo-xlib-surface.c | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 93467ffe..75933167 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; } /** |