diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 55a8be171..f112bcdf1 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -71,6 +71,7 @@ static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = { CAIRO_HINT_METRICS_DEFAULT } /* font_options */ }, /* base */ + PIXMAN_a8r8g8b8, /* pixman_format */ CAIRO_FORMAT_ARGB32, /* format */ NULL, /* data */ FALSE, /* owns_data */ @@ -173,6 +174,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, surface->pixman_image = pixman_image; + surface->pixman_format = pixman_format; surface->format = _cairo_format_from_pixman_format (pixman_format); surface->data = (unsigned char *) pixman_image_get_data (pixman_image); surface->owns_data = FALSE; @@ -186,49 +188,79 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, return &surface->base; } -static cairo_bool_t -_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format) +/* XXX: This function should really live inside pixman. */ +pixman_format_code_t +_pixman_format_from_masks (cairo_format_masks_t *masks) { - /* XXX: many formats are simply not supported by pixman, so this function - * converts the masks into something we know will be supported. - */ switch (masks->bpp) { case 32: if (masks->alpha_mask == 0xff000000 && - masks->red_mask == 0x00ff0000 && + masks->red_mask == 0x00ff0000 && masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) + masks->blue_mask == 0x000000ff) { - *format = CAIRO_FORMAT_ARGB32; - return TRUE; + return PIXMAN_a8r8g8b8; } if (masks->alpha_mask == 0x00000000 && - masks->red_mask == 0x00ff0000 && + masks->red_mask == 0x00ff0000 && masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) + masks->blue_mask == 0x000000ff) { - *format = CAIRO_FORMAT_RGB24; - return TRUE; + return PIXMAN_x8r8g8b8; } break; case 8: if (masks->alpha_mask == 0xff) { - *format = CAIRO_FORMAT_A8; - return TRUE; + return PIXMAN_a8; } break; case 1: if (masks->alpha_mask == 0x1) { - *format = CAIRO_FORMAT_A1; - return TRUE; + return PIXMAN_a1; } break; } - return FALSE; + + ASSERT_NOT_REACHED; + return 0; } +/* XXX: This function should really live inside pixman. */ +void +_pixman_format_to_masks (pixman_format_code_t pixman_format, + uint32_t *bpp, + uint32_t *red, + uint32_t *green, + uint32_t *blue) +{ + *red = 0x0; + *green = 0x0; + *blue = 0x0; + + switch (pixman_format) + { + case PIXMAN_a8r8g8b8: + case PIXMAN_x8r8g8b8: + default: + *bpp = 32; + *red = 0x00ff0000; + *green = 0x0000ff00; + *blue = 0x000000ff; + break; + + case PIXMAN_a8: + *bpp = 8; + break; + + case PIXMAN_a1: + *bpp = 1; + break; + } +} + + /* XXX: This function really should be eliminated. We don't really * want to advertise a cairo image surface that supports any possible * format. A minimal step would be to replace this function with one @@ -240,18 +272,15 @@ _cairo_image_surface_create_with_masks (unsigned char *data, int height, int stride) { - cairo_format_t format; + pixman_format_code_t pixman_format; - if (!_CAIRO_MASK_FORMAT (masks, &format)) { - _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - return (cairo_surface_t*) &_cairo_surface_nil; - } + pixman_format = _pixman_format_from_masks (masks); - return cairo_image_surface_create_for_data (data, - format, - width, - height, - stride); + return _cairo_image_surface_create_with_pixman_format (data, + pixman_format, + width, + height, + stride); } static pixman_format_code_t @@ -277,7 +306,7 @@ _cairo_format_to_pixman_format_code (cairo_format_t format) return ret; } -static cairo_surface_t * +cairo_surface_t * _cairo_image_surface_create_with_pixman_format (unsigned char *data, pixman_format_code_t pixman_format, int width, diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 7c4fa023f..c95ec16ce 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -344,46 +344,6 @@ _noop_error_handler (Display *display, return False; /* return value is ignored */ } -static cairo_bool_t -_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format) -{ - switch (masks->bpp) { - case 32: - if (masks->alpha_mask == 0xff000000 && - masks->red_mask == 0x00ff0000 && - masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) - { - *format = CAIRO_FORMAT_ARGB32; - return True; - } - if (masks->alpha_mask == 0x00000000 && - masks->red_mask == 0x00ff0000 && - masks->green_mask == 0x0000ff00 && - masks->blue_mask == 0x000000ff) - { - *format = CAIRO_FORMAT_RGB24; - return True; - } - break; - case 8: - if (masks->alpha_mask == 0xff) - { - *format = CAIRO_FORMAT_A8; - return True; - } - break; - case 1: - if (masks->alpha_mask == 0x1) - { - *format = CAIRO_FORMAT_A1; - return True; - } - break; - } - return False; -} - static void _swap_ximage_2bytes (XImage *ximage) { @@ -504,7 +464,7 @@ _get_image_surface (cairo_xlib_surface_t *surface, XImage *ximage; short x1, y1, x2, y2; cairo_format_masks_t masks; - cairo_format_t format; + pixman_format_code_t pixman_format; x1 = 0; y1 = 0; @@ -638,38 +598,15 @@ _get_image_surface (cairo_xlib_surface_t *surface, masks.alpha_mask = 0xffffffff; } - /* - * Prefer to use a standard pixman format instead of the - * general masks case. - */ - if (_CAIRO_MASK_FORMAT (&masks, &format)) - { - image = (cairo_image_surface_t*) - cairo_image_surface_create_for_data ((unsigned char *) ximage->data, - format, - ximage->width, - ximage->height, - ximage->bytes_per_line); - if (image->base.status) - goto FAIL; - } - else - { - /* - * XXX This can't work. We must convert the data to one of the - * supported pixman formats. Pixman needs another function - * which takes data in an arbitrary format and converts it - * to something supported by that library. - */ - image = (cairo_image_surface_t*) - _cairo_image_surface_create_with_masks ((unsigned char *) ximage->data, - &masks, - ximage->width, - ximage->height, - ximage->bytes_per_line); - if (image->base.status) - goto FAIL; - } + pixman_format = _pixman_format_from_masks (&masks); + image = (cairo_image_surface_t*) + _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data, + pixman_format, + ximage->width, + ximage->height, + ximage->bytes_per_line); + if (image->base.status) + goto FAIL; /* Let the surface take ownership of the data */ _cairo_image_surface_assume_ownership_of_data (image); @@ -770,38 +707,6 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface) return CAIRO_STATUS_SUCCESS; } -static void -cairo_format_get_masks (cairo_format_t format, - uint32_t *bpp, - uint32_t *red, - uint32_t *green, - uint32_t *blue) -{ - *red = 0x0; - *green = 0x0; - *blue = 0x0; - - switch (format) - { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - default: - *bpp = 32; - *red = 0x00ff0000; - *green = 0x0000ff00; - *blue = 0x000000ff; - break; - - case CAIRO_FORMAT_A8: - *bpp = 8; - break; - - case CAIRO_FORMAT_A1: - *bpp = 1; - break; - } -} - static cairo_status_t _draw_image_surface (cairo_xlib_surface_t *surface, cairo_image_surface_t *image, @@ -817,7 +722,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface, int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; cairo_status_t status; - cairo_format_get_masks (image->format, &bpp, &red, &green, &blue); + _pixman_format_to_masks (image->pixman_format, &bpp, &red, &green, &blue); ximage.width = image->width; ximage.height = image->height; diff --git a/src/cairoint.h b/src/cairoint.h index 94f5ae3df..884646529 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -915,7 +915,7 @@ typedef struct _cairo_format_masks { struct _cairo_image_surface { cairo_surface_t base; - /* libic-specific fields */ + pixman_format_code_t pixman_format; cairo_format_t format; unsigned char *data; cairo_bool_t owns_data; @@ -2005,6 +2005,23 @@ cairo_private cairo_surface_t * _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, pixman_format_code_t pixman_format); +cairo_private pixman_format_code_t +_pixman_format_from_masks (cairo_format_masks_t *masks); + +void +_pixman_format_to_masks (pixman_format_code_t pixman_format, + uint32_t *bpp, + uint32_t *red, + uint32_t *green, + uint32_t *blue); + +cairo_private cairo_surface_t * +_cairo_image_surface_create_with_pixman_format (unsigned char *data, + pixman_format_code_t pixman_format, + int width, + int height, + int stride); + cairo_private cairo_surface_t * _cairo_image_surface_create_with_masks (unsigned char *data, cairo_format_masks_t *format,