[cairo] [PATCH] image: Add public API for the creation of a surface for a pixman_image_t

Uli Schlachter psychon at znc.in
Tue Mar 20 07:07:33 PDT 2012


On 20.03.2012 14:12, Chris Wilson wrote:
> Greater interoperablity with pixman is often requested by users dealing
> with quirky hardware that prefers niche formats. As the goal is to keep
> the number of core, well supported cairo_format_t to a minimum, we need
> an alternative mechanism to support the extensive range of formats
> supported by pixman. In the future we will also have to look to
> supporting pixman colorspaces, but for now we only handled RGBA linear
> compositing and so restrict ourselves to that subset of pixman images.
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
>  src/cairo-image-surface.c      |  126 +++++++++++++++++++++++++++++++++++++++-
>  src/cairo.h                    |   10 +++
>  util/cairo-missing/Makefile.am |    2 +-
>  3 files changed, 134 insertions(+), 4 deletions(-)
> 
> diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
> index 2a2d59d..5c682f0 100644
> --- a/src/cairo-image-surface.c
> +++ b/src/cairo-image-surface.c
[...]
> +cairo_surface_t *
> +cairo_image_surface_create_for_pixman_image (pixman_format_code_t format,
> +					     pixman_image_t *image)
> +{
> +    int width, height;
> +    pixman_image_t *copy;
> +    cairo_surface_t *surface;

I would suggest adding:

     if (image == NULL)
          return _cairo_surface_create_in_error (_cairo_error
(CAIRO_STATUS_NULL_POINTER));

> +    if (! pixman_format_supported_destination (format))
> +	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
> +
> +    width = pixman_image_get_width (image);
> +    height = pixman_image_get_width (image);
> +    if (! _cairo_image_surface_is_size_valid (width, height))
> +	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
> +
> +    copy = pixman_image_create_bits (format, width, height,
> +				     pixman_image_get_data (image),
> +				     pixman_image_get_stride (image));
> +    if (unlikely (copy == NULL))
> +	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
> +
> +    surface = _cairo_image_surface_create_for_pixman_image (copy, format);
> +    if (unlikely (surface->status))
> +	return surface;
> +
> +    pixman_image_set_destroy_function (image,
> +				       _pixman_image_destroy_notify,
> +				       surface);
> +    return surface;
> +}
[...]
> + * Return value: the format code of the image, along with the pointer to
> + * the pixman image, or 0 if @surface is not an image surface, or if
[...]
> + **/
> +pixman_format_code_t
> +cairo_image_surface_get_pixman_image (cairo_surface_t *surface,
> +				      pixman_image_t *image)

Shouldn't this be "pixman_image_t **image"? Else...

> +{
> +    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
> +
> +    if (! _cairo_surface_is_image (surface)) {
> +	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
> +	return 0;
> +    }
> +
> +    if (surface->finished) {
> +	_cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
> +	return 0;
> +    }
> +
> +    *image = image_surface->pixman_image;

...this line casts a pixman_image_t* to a pixman_image_t and assigns the result
to *image. (Does this compile? I assume so, but that makes me wonder why it
compiles)

> +    return image_surface->pixman_format;
> +}
> +cairo_format_t
>  _cairo_format_from_content (cairo_content_t content)
>  {
>      switch (content) {
> diff --git a/src/cairo.h b/src/cairo.h
> index d23cd10..bb93336 100644
> --- a/src/cairo.h
> +++ b/src/cairo.h
> @@ -42,6 +42,8 @@
>  #include "cairo-features.h"
>  #include "cairo-deprecated.h"
>  
> +#include <pixman.h>

This is bad. It means that cairo.h now depends on pixman.h which it didn't do
before. If you really want to do that, you should add "pixman" to src/cairo.pc.
Alternatively, we would have to add a cairo-image.h for this which gets its own
pkg-config file, but I guess that is ugly to use.

>  #ifdef  __cplusplus
>  # define CAIRO_BEGIN_DECLS  extern "C" {
>  # define CAIRO_END_DECLS    }
> @@ -2439,6 +2441,14 @@ cairo_image_surface_create_for_data (unsigned char	       *data,
>  				     int			height,
>  				     int			stride);
>  
> +cairo_public cairo_surface_t *
> +cairo_image_surface_create_for_pixman_image (pixman_format_code_t format,
> +					     pixman_image_t *image);
> +
> +cairo_public pixman_format_code_t
> +cairo_image_surface_get_pixman_image (cairo_surface_t *surface,
> +				      pixman_image_t *image);
> +
>  cairo_public unsigned char *
>  cairo_image_surface_get_data (cairo_surface_t *surface);
>  
> diff --git a/util/cairo-missing/Makefile.am b/util/cairo-missing/Makefile.am
> index 9078610..d252b74 100644
> --- a/util/cairo-missing/Makefile.am
> +++ b/util/cairo-missing/Makefile.am
> @@ -1,6 +1,6 @@
>  include $(top_srcdir)/util/cairo-missing/Makefile.sources
>  
> -AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src
> +AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src $(CAIRO_CFLAGS)

I assume this fixes a "pixman.h not found" error and thus is just a band-aid for
the above problem?

Uli
-- 
"Do you know that books smell like nutmeg or some spice from a foreign land?"
                                                  -- Faber in Fahrenheit 451


More information about the cairo mailing list