mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-06 06:10:17 +01:00
[xlib] Check for depth == 0 in create_surface_internal().
Validate that we find an appropriate depth for the Xlib surface, before attempting to create the surface. This was manifesting itself with XInitImage() failures during _draw_image_surface() (actually detected as a segmentation fault in XPutPixel() due to an incomplete XImage). So we also add a couple of asserts to ensure that XInitImage() is successful - which to the best of our knowledge, they should always be.
This commit is contained in:
parent
c014e51dc9
commit
fef03ef98a
1 changed files with 55 additions and 38 deletions
|
|
@ -909,11 +909,15 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
image_masks.green_mask == surface->g_mask &&
|
||||
image_masks.blue_mask == surface->b_mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ximage.bits_per_pixel = image_masks.bpp;
|
||||
ximage.bytes_per_line = image->stride;
|
||||
ximage.data = (char *)image->data;
|
||||
own_data = FALSE;
|
||||
XInitImage (&ximage);
|
||||
|
||||
ret = XInitImage (&ximage);
|
||||
assert (ret != 0);
|
||||
} else {
|
||||
unsigned int stride, rowstride;
|
||||
int x, y, x0, y0, x_off, y_off;
|
||||
|
|
@ -923,6 +927,8 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
|
||||
int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
|
||||
cairo_xlib_visual_info_t *visual_info = NULL;
|
||||
cairo_bool_t true_color;
|
||||
int ret;
|
||||
|
||||
if (surface->depth > 16) {
|
||||
ximage.bits_per_pixel = 32;
|
||||
|
|
@ -942,28 +948,27 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
|
||||
own_data = TRUE;
|
||||
|
||||
XInitImage (&ximage);
|
||||
ret = XInitImage (&ximage);
|
||||
assert (ret != 0);
|
||||
|
||||
_characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
|
||||
_characterize_field (image_masks.red_mask , &i_r_width, &i_r_shift);
|
||||
_characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
|
||||
_characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
|
||||
|
||||
if (surface->visual == NULL || surface->visual->class == TrueColor) {
|
||||
|
||||
true_color = surface->visual == NULL ||
|
||||
surface->visual->class == TrueColor;
|
||||
if (true_color) {
|
||||
_characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
|
||||
_characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
|
||||
_characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
|
||||
_characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
|
||||
|
||||
} else {
|
||||
|
||||
status = _cairo_xlib_screen_get_visual_info (surface->screen_info,
|
||||
surface->visual,
|
||||
&visual_info);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
}
|
||||
|
||||
rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
|
||||
|
|
@ -972,13 +977,15 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
y0 = dst_y + surface->base.device_transform.y0;
|
||||
for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
|
||||
y < ximage.height;
|
||||
y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
|
||||
y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
|
||||
{
|
||||
const int8_t *dither_row = dither_pattern[y_off];
|
||||
|
||||
for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
|
||||
x < ximage.width;
|
||||
x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
|
||||
x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
|
||||
{
|
||||
int dither_adjustment = dither_row[x_off];
|
||||
|
||||
int a, r, g, b;
|
||||
|
||||
if (image_masks.bpp <= 8)
|
||||
|
|
@ -987,20 +994,24 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
in_pixel = ((uint16_t*)row)[x];
|
||||
else
|
||||
in_pixel = row[x];
|
||||
|
||||
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
|
||||
r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
|
||||
g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
|
||||
b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
|
||||
if (surface->visual == NULL || surface->visual->class == TrueColor) {
|
||||
out_pixel = (_field_from_8 (a, o_a_width, o_a_shift) |
|
||||
_field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
|
||||
_field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
|
||||
_field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment));
|
||||
|
||||
if (true_color) {
|
||||
out_pixel = _field_from_8 (a, o_a_width, o_a_shift) |
|
||||
_field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
|
||||
_field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
|
||||
_field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
|
||||
} else {
|
||||
out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
|
||||
}
|
||||
|
||||
XPutPixel (&ximage, x, y, out_pixel);
|
||||
}
|
||||
|
||||
row += rowstride;
|
||||
}
|
||||
}
|
||||
|
|
@ -1194,9 +1205,9 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac
|
|||
_cairo_xlib_surface_create_internal (other->dpy,
|
||||
pixmap,
|
||||
other->screen, other->visual,
|
||||
NULL,
|
||||
other->xrender_format,
|
||||
image->width, image->height,
|
||||
0);
|
||||
other->depth);
|
||||
status = surface->base.status;
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
|
@ -2391,6 +2402,33 @@ _cairo_xlib_surface_create_internal (Display *dpy,
|
|||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
if (xrender_format) {
|
||||
depth = xrender_format->depth;
|
||||
|
||||
/* XXX find matching visual for core/dithering fallbacks? */
|
||||
} else if (visual) {
|
||||
int j, k;
|
||||
|
||||
/* This is ugly, but we have to walk over all visuals
|
||||
* for the display to find the correct depth.
|
||||
*/
|
||||
depth = 0;
|
||||
for (j = 0; j < screen->ndepths; j++) {
|
||||
Depth *d = &screen->depths[j];
|
||||
for (k = 0; k < d->nvisuals; k++) {
|
||||
if (&d->visuals[k] == visual) {
|
||||
depth = d->depth;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
found:
|
||||
;
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
|
||||
|
||||
screen_info = _cairo_xlib_screen_info_get (dpy, screen);
|
||||
if (screen_info == NULL)
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
|
@ -2408,27 +2446,6 @@ _cairo_xlib_surface_create_internal (Display *dpy,
|
|||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
if (xrender_format) {
|
||||
depth = xrender_format->depth;
|
||||
} else if (visual) {
|
||||
int j, k;
|
||||
|
||||
/* This is ugly, but we have to walk over all visuals
|
||||
* for the display to find the depth.
|
||||
*/
|
||||
for (j = 0; j < screen->ndepths; j++) {
|
||||
Depth *d = &screen->depths[j];
|
||||
for (k = 0; k < d->nvisuals; k++) {
|
||||
if (&d->visuals[k] == visual) {
|
||||
depth = d->depth;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
found:
|
||||
;
|
||||
}
|
||||
|
||||
if (! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) {
|
||||
surface->render_major = -1;
|
||||
surface->render_minor = -1;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue