summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-03-28 16:32:42 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-09-29 09:58:19 -0400
commit25c1b0c0e8079355924134a2a84d243b23da69fe (patch)
treeff2fae76e1f5921fc7fe6ab44c30af497ea00c31
parentd97fc0ebe78dea9e851b35dc0d90b9d84808e9a6 (diff)
Flesh out the pixman surface some
-rw-r--r--src/cairo-pixman-surface.c345
1 files changed, 275 insertions, 70 deletions
diff --git a/src/cairo-pixman-surface.c b/src/cairo-pixman-surface.c
index 5a60b663..3a7b3ec0 100644
--- a/src/cairo-pixman-surface.c
+++ b/src/cairo-pixman-surface.c
@@ -41,11 +41,18 @@
#include "cairo-pixman.h"
#include "cairo-default-context-private.h"
+#include "cairo-image-surface-private.h"
+#include "cairo-pattern-private.h"
-/* Limit on the width / height of an image surface in pixels. This is
- * mainly determined by coordinates of things sent to pixman at the
- * moment being in 16.16 format. */
-#define MAX_IMAGE_SIZE 32767
+extern const cairo_surface_backend_t cairo_pixman_surface_backend;
+
+typedef struct _cairo_pixman_surface cairo_pixman_surface_t;
+
+struct _cairo_pixman_surface
+{
+ cairo_surface_t base;
+ pixman_image_t * pimage;
+};
/**
* SECTION:cairo-pixman
@@ -63,16 +70,29 @@
*
* Defined if the pixman surface backend is available.
*
- * @Since: 1.13
+ * @Since: 1.14
*/
+static cairo_content_t
+content_from_pixman_image (pixman_image_t *image)
+{
+ pixman_format_code_t format = pixman_image_get_format (image);
+ cairo_content_t result;
+
+ result = 0;
+ if (PIXMAN_FORMAT_RGB (format))
+ result |= CAIRO_CONTENT_COLOR;
+ if (PIXMAN_FORMAT_A (format))
+ result |= CAIRO_CONTENT_ALPHA;
+
+ return result;
+}
+
/**
* cairo_pixman_surface_create:
- * @format: format of pixels in the surface to create
- * @width: width of the surface, in pixels
- * @height: height of the surface, in pixels
+ * @image: a pixman image
*
- * Creates an image surface of the specified format and
+ * Creates an pixman surface based on the given image
* dimensions. Initially the surface contents are all
* 0. (Specifically, within each pixel, each color or alpha channel
* belonging to format will be 0. The contents of bits within a pixel,
@@ -89,94 +109,278 @@
cairo_surface_t *
cairo_pixman_surface_create (pixman_image_t *image)
{
- return NULL;
+ cairo_pixman_surface_t *surface;
+ pixman_format_code_t format;
+
+ if (!(surface = malloc (sizeof *surface))) {
+ return _cairo_surface_create_in_error (
+ _cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+
+ format = pixman_image_get_format (image);
+ if (!format || !pixman_format_supported_destination (format)) {
+ /* FIXME: This error status is intended for incorrect
+ * cairo_format_ts, not incorrect pixman formats. In
+ * principle a new error status should be added
+ */
+ return _cairo_surface_create_in_error (
+ _cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+ }
+
+ _cairo_surface_init (&surface->base, &cairo_pixman_surface_backend,
+ NULL, /* device */
+ content_from_pixman_image (image));
+
+ surface->pimage = pixman_image_ref (image);
+
+ return (cairo_surface_t *)surface;
}
static cairo_status_t
-_cairo_pixman_surface_finish (void *abstract_surface)
+cairo_pixman_surface_finish (void *abstract_surface)
{
+ cairo_pixman_surface_t *surface = abstract_surface;
+
+ pixman_image_unref (surface->pimage);
+ surface->pimage = NULL;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
-_cairo_pixman_surface_create_similar (void *abstract_other,
- cairo_content_t content,
- int width,
- int height)
+cairo_pixman_surface_create_similar (void *abstract_other,
+ cairo_content_t content,
+ int width,
+ int height)
{
+ cairo_pixman_surface_t *other = abstract_other;
+ pixman_format_code_t format;
+ pixman_image_t *copy;
+
+ format = pixman_image_get_format (other->pimage);
+
+ copy = pixman_image_create_bits (format, width, height, NULL, -1);
+
+ return cairo_pixman_surface_create (copy);
}
static cairo_surface_t *
-_cairo_pixman_surface_map_to_image (void *abstract_other,
- const cairo_rectangle_int_t *extents)
+create_image_surface (cairo_pixman_surface_t *psurface)
{
+ pixman_image_t *pimage = psurface->pimage;
+ pixman_format_code_t pformat = pixman_image_get_format (pimage);
+ cairo_bool_t must_copy = FALSE;
+ cairo_surface_t *image;
+ cairo_format_t format;
+
+ switch (pformat)
+ {
+ case PIXMAN_a8r8g8b8:
+ format = CAIRO_FORMAT_ARGB32;
+ break;
+
+ case PIXMAN_x8r8g8b8:
+ format = CAIRO_FORMAT_RGB24;
+ break;
+
+ case PIXMAN_a8:
+ format = CAIRO_FORMAT_A8;
+ break;
+
+ case PIXMAN_a1:
+ format = CAIRO_FORMAT_A1;
+ break;
+
+ case PIXMAN_r5g6b5:
+ format = CAIRO_FORMAT_RGB16_565;
+ break;
+
+ case PIXMAN_x2r10g10b10:
+ format = CAIRO_FORMAT_RGB30;
+ break;
+
+ default:
+ format = CAIRO_FORMAT_ARGB32;
+ must_copy = TRUE;
+ break;
+ }
+
+ if (must_copy)
+ {
+ int width = pixman_image_get_width (pimage);
+ int height = pixman_image_get_height (pimage);
+ pixman_image_t *dest;
+
+ image = cairo_image_surface_create (format, width, height);
+
+ dest = ((cairo_image_surface_t *)image)->pixman_image;
+
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ pimage, NULL, dest,
+ 0, 0, 0, 0, 0, 0, width, height);
+ }
+ else
+ {
+ image = _cairo_image_surface_create_for_pixman_image (pimage, pformat);
+ }
+
+ return image;
+}
+
+static cairo_surface_t *
+cairo_pixman_surface_map_to_image (void *abstract_other,
+ const cairo_rectangle_int_t *extents)
+{
+ cairo_pixman_surface_t *surface = abstract_other;
+
+ /* FIXME: if we need to copy, we should only copy extents */
+ return create_image_surface (surface);
}
static cairo_int_status_t
-_cairo_pixman_surface_unmap_image (void *abstract_surface,
- cairo_image_surface_t *image)
+cairo_pixman_surface_unmap_image (void *abstract_surface,
+ cairo_image_surface_t *image)
{
+ cairo_pixman_surface_t *surface = abstract_surface;
+
+ if (image->pixman_image != surface->pimage)
+ {
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ image->pixman_image, NULL, surface->pimage,
+ 0, 0, 0, 0, 0, 0,
+ pixman_image_get_width (surface->pimage),
+ pixman_image_get_height (surface->pimage));
+ }
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
-_cairo_pixman_surface_source (void *abstract_surface,
- cairo_rectangle_int_t *extents)
+cairo_pixman_surface_source (void *abstract_surface,
+ cairo_rectangle_int_t *extents)
{
+ cairo_pixman_surface_t *surface = abstract_surface;
+
+ extents->x = extents->y = 0;
+ extents->width = pixman_image_get_width (surface->pimage);
+ extents->height = pixman_image_get_height (surface->pimage);
+
+ return &surface->base;
}
static cairo_status_t
-_cairo_pixman_surface_acquire_source_image (void *abstract_surface,
- cairo_image_surface_t **image_out,
- void **image_extra)
+cairo_pixman_surface_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
{
- *image_out = abstract_surface;
+ cairo_pixman_surface_t *psurface;
+
+ *image_out = (cairo_image_surface_t *)create_image_surface (psurface);
*image_extra = NULL;
+ /* FIXME: create_image_surface can fail (or should be able to fail) */
return CAIRO_STATUS_SUCCESS;
}
static void
-_cairo_pixman_surface_release_source_image (void *abstract_surface,
+cairo_pixman_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
+ cairo_surface_destroy ((cairo_surface_t *)image);
}
static cairo_surface_t *
-_cairo_pixman_surface_snapshot (void *abstract_surface)
+cairo_pixman_surface_snapshot (void *abstract_surface)
{
+ /* huh? */
}
static cairo_bool_t
-_cairo_pixman_surface_get_extents (void *abstract_surface,
- cairo_rectangle_int_t *rectangle)
+cairo_pixman_surface_get_extents (void *abstract_surface,
+ cairo_rectangle_int_t *rectangle)
{
+ cairo_pixman_surface_t *psurface = abstract_surface;
+
+ rectangle->x = 0;
+ rectangle->y = 0;
+ rectangle->width = pixman_image_get_width (psurface->pimage);
+ rectangle->height = pixman_image_get_height (psurface->pimage);
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
-_cairo_pixman_surface_get_font_options (void *abstract_surface,
+cairo_pixman_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
+ _cairo_font_options_init_default (options);
+
+ cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
+ _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
}
-static cairo_int_status_t
-_cairo_pixman_surface_paint (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip)
+static pixman_image_t *
+pimage_from_solid_pattern (cairo_solid_pattern_t *solid)
+{
+ pixman_color_t pcolor;
+
+ pcolor.red = _cairo_color_double_to_short (solid->color.red);
+ pcolor.green = _cairo_color_double_to_short (solid->color.green);
+ pcolor.blue = _cairo_color_double_to_short (solid->color.blue);
+ pcolor.alpha = _cairo_color_double_to_short (solid->color.alpha);
+
+ return pixman_image_create_solid_fill (&pcolor);
+}
+
+static pixman_image_t *
+pimage_from_surface_pattern (cairo_surface_pattern_t *surface)
{
+
+}
+
+static pixman_image_t *
+pimage_from_pattern (const cairo_pattern_t *pattern)
+{
+ switch (pattern->type)
+ {
+ case CAIRO_PATTERN_TYPE_SOLID:
+ return pimage_from_solid_pattern ((cairo_solid_pattern_t *)pattern);
+ break;
+
+ case CAIRO_PATTERN_TYPE_SURFACE:
+ return pimage_from_surface_pattern ((cairo_surface_pattern_t *)pattern);
+ break;
+
+ case CAIRO_PATTERN_TYPE_LINEAR:
+ case CAIRO_PATTERN_TYPE_RADIAL:
+ case CAIRO_PATTERN_TYPE_MESH:
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ break;
+ }
}
static cairo_int_status_t
-_cairo_pixman_surface_mask (void *abstract_surface,
+cairo_pixman_surface_paint (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
const cairo_clip_t *clip)
{
+ pixman_image_t *iamge = pimage_from_pattern (source);
+
}
static cairo_int_status_t
-_cairo_pixman_surface_stroke (void *abstract_surface,
+cairo_pixman_surface_mask (void *abstract_surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ const cairo_clip_t *clip)
+{
+}
+
+static cairo_int_status_t
+cairo_pixman_surface_stroke (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_path_fixed_t *path,
@@ -190,19 +394,19 @@ _cairo_pixman_surface_stroke (void *abstract_surface,
}
static cairo_int_status_t
-_cairo_pixman_surface_fill (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias,
- const cairo_clip_t *clip)
+cairo_pixman_surface_fill (void *abstract_surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ const cairo_clip_t *clip)
{
}
static cairo_int_status_t
-_cairo_pixman_surface_glyphs (void *abstract_surface,
+cairo_pixman_surface_glyphs (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
@@ -210,38 +414,39 @@ _cairo_pixman_surface_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font,
const cairo_clip_t *clip)
{
+
}
-const cairo_surface_backend_t _cairo_pixman_surface_backend =
+const cairo_surface_backend_t cairo_pixman_surface_backend =
{
CAIRO_SURFACE_TYPE_IMAGE,
- _cairo_pixman_surface_finish,
-
+ cairo_pixman_surface_finish,
+
_cairo_default_context_create,
-
- _cairo_pixman_surface_create_similar,
+
+ cairo_pixman_surface_create_similar,
NULL, /* create similar image */
- _cairo_pixman_surface_map_to_image,
- _cairo_pixman_surface_unmap_image,
-
- _cairo_pixman_surface_source,
- _cairo_pixman_surface_acquire_source_image,
- _cairo_pixman_surface_release_source_image,
- _cairo_pixman_surface_snapshot,
-
+ cairo_pixman_surface_map_to_image,
+ cairo_pixman_surface_unmap_image,
+
+ cairo_pixman_surface_source,
+ cairo_pixman_surface_acquire_source_image,
+ cairo_pixman_surface_release_source_image,
+ cairo_pixman_surface_snapshot,
+
NULL, /* copy_page */
NULL, /* show_page */
-
- _cairo_pixman_surface_get_extents,
- _cairo_pixman_surface_get_font_options,
-
+
+ cairo_pixman_surface_get_extents,
+ cairo_pixman_surface_get_font_options,
+
NULL, /* flush */
NULL,
-
- _cairo_pixman_surface_paint,
- _cairo_pixman_surface_mask,
- _cairo_pixman_surface_stroke,
- _cairo_pixman_surface_fill,
+
+ cairo_pixman_surface_paint,
+ cairo_pixman_surface_mask,
+ cairo_pixman_surface_stroke,
+ cairo_pixman_surface_fill,
NULL, /* fill-stroke */
- _cairo_pixman_surface_glyphs,
+ cairo_pixman_surface_glyphs,
};