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

Uli Schlachter <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
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 <[email protected]>
> ---
>  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
--
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.