diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-09-30 19:45:20 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-09-30 19:45:20 -0400 |
commit | 0afc438272c4e1610342b89a654294ccb5a68ed9 (patch) | |
tree | f8d3d2fc0d3546beba4e0c0926dd8fa00ebc4101 | |
parent | 5a8c34cd098f890d5cb5e6e49f38e2659d3e5edd (diff) |
prtooproto
-rw-r--r-- | src/cairo-pixman-surface.c | 628 |
1 files changed, 349 insertions, 279 deletions
diff --git a/src/cairo-pixman-surface.c b/src/cairo-pixman-surface.c index f6ee2600..3eb0fa10 100644 --- a/src/cairo-pixman-surface.c +++ b/src/cairo-pixman-surface.c @@ -343,6 +343,8 @@ typedef union proto_image_t proto_image_t; typedef enum { + BROKEN, + WHITE, REGION, TRAPS, GLYPHS, @@ -406,6 +408,62 @@ proto_image_new (proto_image_type_t type) return image; } +static void +proto_image_free (proto_image_t *image) +{ + if (image->type == BROKEN) + { + /* These are statically allocated */ + return; + } + + switch (image->type) + { + case BROKEN: + case WHITE: + break; + case REGION: + pixman_region32_fini (image->region.region); + break; + case TRAPS: + free (image->traps.traps); + break; + case GLYPHS: + free (image->glyphs.glyphs); + break; + case PIXMAN: + pixman_image_unref (image->pixman.image); + break; + case COMPOSITE: + proto_image_free (image->composite.left); + proto_image_free (image->composite.right); + break; + } + + free (image); +} + +static proto_image_t * +proto_image_new_broken (void) +{ + static const proto_image_t broken = + { + BROKEN + }; + + return (proto_image_t *)&broken; +} + +static proto_image_t * +proto_image_new_white (void) +{ + proto_image_t *image; + + if (!(image = proto_image_new (WHITE))) + return proto_image_new_broken (); + return image; +} + static proto_image_t * proto_image_new_traps (int n_traps, pixman_trapezoid_t *traps) { @@ -416,6 +474,10 @@ proto_image_new_traps (int n_traps, pixman_trapezoid_t *traps) image->traps.n_traps = n_traps; image->traps.traps = traps; } + else + { + image = proto_image_new_broken (); + } return image; } @@ -427,6 +489,8 @@ proto_image_new_region (pixman_region32_t *region) if ((image = proto_image_new (REGION))) image->region.region = region; + else + image = proto_image_new_broken (); return image; } @@ -444,6 +508,10 @@ proto_image_new_glyphs (pixman_glyph_cache_t *glyph_cache, image->glyphs.n_glyphs = n_glyphs; image->glyphs.glyphs = glyphs; } + else + { + image = proto_image_new_broken (); + } return image; } @@ -453,9 +521,10 @@ proto_image_new_pixman (pixman_image_t *pimage) { proto_image_t *image; - if ((image = proto_image_new (PIXMAN))) - image->pixman.image = pimage; + if (!pimage || !(image = proto_image_new (PIXMAN))) + return proto_image_new_broken (); + image->pixman.image = pimage; return image; } @@ -470,10 +539,162 @@ proto_image_new_composite (pixman_op_t op, proto_image_t *left, proto_image_t *r image->composite.left = left; image->composite.right = right; } + else + { + proto_image_free (left); + proto_image_free (right); + + image = proto_image_new_broken (); + } return image; } +static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; + +static cairo_int_status_t +proto_image_resolve (proto_image_t *proto_image, int width, int height, + pixman_image_t **result) +{ + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; + pixman_image_t *white_img; + pixman_format_code_t format; + pixman_image_t *left, *right; + + *result = NULL; + + switch (proto_image->type) + { + case BROKEN: + status = CAIRO_INT_STATUS_NO_MEMORY; + break; + + case WHITE: + *result = pixman_image_create_solid_fill (&white); + if (!*result) + { + status = CAIRO_INT_STATUS_NO_MEMORY; + goto out; + } + break; + + case REGION: + if (!(*result = pixman_image_create_bits ( + PIXMAN_a8, width, height, NULL, -1))) + { + status = CAIRO_INT_STATUS_NO_MEMORY; + goto out; + } + + if (!(white_img = pixman_image_create_solid_fill (&white))) + { + status = CAIRO_INT_STATUS_NO_MEMORY; + goto out; + } + + pixman_image_set_clip_region32 (*result, proto_image->region.region); + pixman_image_composite32 ( + PIXMAN_OP_SRC, white_img, NULL, *result, + 0, 0, 0, 0, 0, 0, width, height); + break; + + case TRAPS: + if (!(*result = pixman_image_create_bits ( + PIXMAN_a8, width, height, NULL, -1))) + { + status = CAIRO_INT_STATUS_NO_MEMORY; + goto out; + } + + pixman_add_trapezoids (*result, 0, 0, + proto_image->traps.n_traps, + proto_image->traps.traps); + break; + + case GLYPHS: + format = pixman_glyph_get_mask_format ( + proto_image->glyphs.glyph_cache, + proto_image->glyphs.n_glyphs, + proto_image->glyphs.glyphs); + + if (!(*result = pixman_image_create_bits ( + format, width, height, NULL, -1))) + { + status = CAIRO_INT_STATUS_NO_MEMORY; + goto out; + } + + pixman_composite_glyphs (PIXMAN_OP_SRC, + white_img, *result, format, + 0, 0, 0, 0, 0, 0, width, height, + proto_image->glyphs.glyph_cache, + proto_image->glyphs.n_glyphs, + proto_image->glyphs.glyphs); + break; + + case PIXMAN: + *result = pixman_image_ref (proto_image->pixman.image); + break; + + case COMPOSITE: + status = proto_image_resolve ( + proto_image->composite.left, width, height, &left); + if (status != CAIRO_INT_STATUS_SUCCESS) + goto out; + + status = proto_image_resolve ( + proto_image->composite.right, width, height, &right); + if (status != CAIRO_INT_STATUS_SUCCESS) + { + pixman_image_unref (left); + goto out; + } + + pixman_image_composite32 ( + proto_image->composite.op, + left, NULL, right, + 0, 0, 0, 0, 0, 0, width, height); + + pixman_image_unref (left); + + *result = right; + break; + } + +out: + if (*result != NULL) + pixman_image_unref (*result); + + return status; +} + +static cairo_int_status_t +composite_proto_images (pixman_op_t operator, + proto_image_t * source, + proto_image_t * mask, + pixman_image_t * dest_img) +{ + pixman_image_t *src_img, *mask_img; + cairo_int_status_t status; + int width, height; + + status = proto_image_resolve (source, width, height, &src_img); + if (status != CAIRO_INT_STATUS_SUCCESS) + return status; + + status = proto_image_resolve (mask, width, height, &mask_img); + if (status != CAIRO_INT_STATUS_SUCCESS) + return status; + + pixman_image_composite32 (operator, src_img, mask_img, dest_img, + 0, 0, 0, 0, 0, 0, width, height); + + pixman_image_unref (src_img); + pixman_image_unref (mask_img); + + return CAIRO_INT_STATUS_SUCCESS; +} + static void set_properties (pixman_image_t *image, cairo_pattern_t *pattern, cairo_matrix_t *matrix) { @@ -545,21 +766,21 @@ set_properties (pixman_image_t *image, cairo_pattern_t *pattern, cairo_matrix_t pixman_image_set_component_alpha (image, pattern->has_component_alpha); } -static cairo_int_status_t -pimage_from_solid_pattern (cairo_solid_pattern_t *solid, - pixman_image_t **result) +static proto_image_t * +pimage_from_solid_pattern (cairo_solid_pattern_t *solid) { pixman_color_t pcolor; + pixman_image_t *pimage; 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); - if (!(*result = pixman_image_create_solid_fill (&pcolor))) - return CAIRO_INT_STATUS_NO_MEMORY; - - return CAIRO_INT_STATUS_SUCCESS; + if (!(pimage = pixman_image_create_solid_fill (&pcolor))) + return proto_image_new_broken (); + else + return proto_image_new_pixman (pimage); } typedef struct acquire_source_cleanup_t @@ -586,13 +807,12 @@ clean_up_acquire (pixman_image_t *image, void *closure) } } -static cairo_int_status_t -pimage_from_surface_pattern (cairo_surface_pattern_t *pattern, - pixman_image_t **result) +static proto_image_t * +pimage_from_surface_pattern (cairo_surface_pattern_t *pattern) { - pixman_image_t *simage; - cairo_int_status_t status; acquire_source_cleanup_t *info = NULL; + pixman_image_t *simage, *result; + cairo_int_status_t status; status = CAIRO_INT_STATUS_SUCCESS; @@ -633,10 +853,7 @@ pimage_from_surface_pattern (cairo_surface_pattern_t *pattern, case CAIRO_SURFACE_TYPE_COGL: default: if (!(info = malloc (sizeof (acquire_source_cleanup_t)))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } + return proto_image_new_broken (); info->surface = pattern->surface; info->image = NULL; @@ -646,51 +863,52 @@ pimage_from_surface_pattern (cairo_surface_pattern_t *pattern, pattern->surface, &info->image, &info->extra); if (status != CAIRO_INT_STATUS_SUCCESS) - goto out; + { + free (info); + return proto_image_new_broken(); + } simage = info->image->pixman_image; break; } /* Then create a clone of that image */ - if (!(*result = pixman_image_create_bits ( + if (!(result = pixman_image_create_bits ( pixman_image_get_format (simage), pixman_image_get_width (simage), pixman_image_get_height (simage), pixman_image_get_data (simage), pixman_image_get_stride (simage)))) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; + clean_up_acquire (NULL, info); + + return proto_image_new_broken (); } if (info) - pixman_image_set_destroy_function (*result, clean_up_acquire, info); + pixman_image_set_destroy_function (result, clean_up_acquire, info); /* Then set the right properties on the clone */ - set_properties (*result, (cairo_pattern_t *)pattern, NULL); - -out: - if (status != CAIRO_INT_STATUS_SUCCESS) - clean_up_acquire (NULL, info); + set_properties (result, (cairo_pattern_t *)pattern, NULL); - return status; + return proto_image_new_pixman (result); } #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */ -static cairo_int_status_t -pimage_from_gradient_pattern (const cairo_gradient_pattern_t *pattern, pixman_image_t **image) +static proto_image_t * +pimage_from_gradient_pattern (const cairo_gradient_pattern_t *pattern) { pixman_gradient_stop_t *pstops; cairo_circle_double_t extremes[2]; pixman_point_fixed_t p1, p2; cairo_int_status_t status; cairo_matrix_t matrix; + pixman_image_t *image; unsigned int i; if (!(pstops = malloc (pattern->n_stops * sizeof (pixman_gradient_stop_t)))) - return CAIRO_INT_STATUS_NO_MEMORY; + return proto_image_new_broken (); for (i = 0; i < pattern->n_stops; i++) { @@ -701,7 +919,8 @@ pimage_from_gradient_pattern (const cairo_gradient_pattern_t *pattern, pixman_im pstops[i].color.alpha = pattern->stops[i].color.alpha_short; } - _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes); + _cairo_gradient_pattern_fit_to_range ( + pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes); p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x); p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y); @@ -712,11 +931,8 @@ pimage_from_gradient_pattern (const cairo_gradient_pattern_t *pattern, pixman_im if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) { - if (!(*image = pixman_image_create_linear_gradient ( - &p1, &p2, pstops, pattern->n_stops))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - } + image = pixman_image_create_linear_gradient ( + &p1, &p2, pstops, pattern->n_stops); } else /* CAIRO_PATTERN_TYPE_RADIAL */ { @@ -725,41 +941,39 @@ pimage_from_gradient_pattern (const cairo_gradient_pattern_t *pattern, pixman_im r1 = _cairo_fixed_16_16_from_double (extremes[0].radius); r2 = _cairo_fixed_16_16_from_double (extremes[1].radius); - if (!(*image = pixman_image_create_radial_gradient ( - &p1, &p2, r1, r2, pstops, pattern->n_stops))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - } + image = pixman_image_create_radial_gradient ( + &p1, &p2, r1, r2, pstops, pattern->n_stops); } - set_properties (*image, (cairo_pattern_t *)pattern, &matrix); - free (pstops); - return status; + if (image) + set_properties (image, (cairo_pattern_t *)pattern, &matrix); + + return proto_image_new_pixman (image); } -static cairo_int_status_t +static proto_image_t * pimage_from_mesh_pattern (cairo_pixman_surface_t *surface, - const cairo_mesh_pattern_t *pattern, - pixman_image_t **image) + const cairo_mesh_pattern_t *pattern) { int width, height; + pixman_image_t *image; width = pixman_image_get_width (surface->pimage); height = pixman_image_get_height (surface->pimage); - *image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0); - if (unlikely (*image == NULL)) - return CAIRO_INT_STATUS_NO_MEMORY; + image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0); - _cairo_mesh_pattern_rasterize (pattern, - pixman_image_get_data (*image), - width, height, - pixman_image_get_stride (*image), - 0, 0); + if (image) + { + _cairo_mesh_pattern_rasterize ( + pattern, pixman_image_get_data (image), + width, height, pixman_image_get_stride (image), + 0, 0); + } - return CAIRO_INT_STATUS_SUCCESS; + return proto_image_new_pixman (image); } typedef struct @@ -786,10 +1000,9 @@ raster_source_clean_up (pixman_image_t *pixman_image, free (info); } -static cairo_int_status_t +static proto_image_t * pimage_from_raster_source_pattern (cairo_pixman_surface_t *psurface, - const cairo_raster_source_pattern_t *pattern, - pixman_image_t **result) + const cairo_raster_source_pattern_t *pattern) { int width, height; cairo_surface_t *surface; @@ -797,8 +1010,9 @@ pimage_from_raster_source_pattern (cairo_pixman_surface_t *psurface raster_info_t *info; cairo_int_status_t status; void *extra; - - *result = NULL; + pixman_image_t *result; + + result = NULL; width = pixman_image_get_width (psurface->pimage); height = pixman_image_get_height (psurface->pimage); @@ -807,33 +1021,37 @@ pimage_from_raster_source_pattern (cairo_pixman_surface_t *psurface &pattern->base, &psurface->base, NULL); if (surface == NULL || surface->status) - return CAIRO_INT_STATUS_NO_MEMORY; + return proto_image_new_broken (); status = _cairo_surface_acquire_source_image (surface, &image, &extra); if (status != CAIRO_INT_STATUS_SUCCESS) { _cairo_raster_source_pattern_release (&pattern->base, surface); - return status; + return proto_image_new_broken (); } - if (!(*result = pixman_image_create_bits ( - image->pixman_format, image->width, image->height, - (uint32_t *) image->data, image->stride))) + result = pixman_image_create_bits ( + image->pixman_format, image->width, image->height, + (uint32_t *) image->data, image->stride); + + if (!result) { _cairo_surface_release_source_image (surface, image, extra); _cairo_raster_source_pattern_release (&pattern->base, surface); - return CAIRO_INT_STATUS_NO_MEMORY; + return proto_image_new_broken (); } - if (!(info = malloc (sizeof (*info)))) + info = malloc (sizeof (*info)); + if (!info) { - pixman_image_unref (*result); + pixman_image_unref (result); + _cairo_surface_release_source_image (surface, image, extra); _cairo_raster_source_pattern_release (&pattern->base, surface); - return CAIRO_INT_STATUS_NO_MEMORY; + return proto_image_new_broken (); } info->pattern = &pattern->base; @@ -842,54 +1060,41 @@ pimage_from_raster_source_pattern (cairo_pixman_surface_t *psurface info->extra = extra; pixman_image_set_destroy_function ( - *result, raster_source_clean_up, info); + result, raster_source_clean_up, info); - set_properties (*result, (cairo_pattern_t *)pattern, NULL); + set_properties (result, (cairo_pattern_t *)pattern, NULL); - return CAIRO_INT_STATUS_SUCCESS; + return proto_image_new_pixman (result); } -static cairo_int_status_t +static proto_image_t * pimage_from_pattern (cairo_pixman_surface_t *surface, - const cairo_pattern_t *pattern, pixman_image_t **image) + const cairo_pattern_t *pattern) { switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - return pimage_from_solid_pattern ( - (cairo_solid_pattern_t *)pattern, image); - break; - + return pimage_from_solid_pattern ((cairo_solid_pattern_t *)pattern); case CAIRO_PATTERN_TYPE_SURFACE: - return pimage_from_surface_pattern ( - (cairo_surface_pattern_t *)pattern, image); - break; - + return pimage_from_surface_pattern ((cairo_surface_pattern_t *)pattern); case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: - return pimage_from_gradient_pattern ( - (cairo_gradient_pattern_t *)pattern, image); - break; - + return pimage_from_gradient_pattern ((cairo_gradient_pattern_t *)pattern); case CAIRO_PATTERN_TYPE_MESH: return pimage_from_mesh_pattern ( - surface, - (cairo_mesh_pattern_t *)pattern, image); + surface, (cairo_mesh_pattern_t *)pattern); break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: return pimage_from_raster_source_pattern ( - surface, - (cairo_raster_source_pattern_t *)pattern, image); + surface, (cairo_raster_source_pattern_t *)pattern); break; } ASSERT_NOT_REACHED; - return CAIRO_INT_STATUS_DEGENERATE; + return proto_image_new_broken(); } -static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; - #define CAIRO_FIXED_16_16_MIN _cairo_fixed_from_int (-32768) #define CAIRO_FIXED_16_16_MAX _cairo_fixed_from_int (32767) @@ -991,36 +1196,23 @@ traps_to_pixman_trapezoids (const cairo_traps_t *traps) return ptraps; } -static cairo_int_status_t -create_clip_image (const cairo_clip_t *clip, int width, int height, - proto_image_t **clip_image) +static proto_image_t * +create_clip_image (const cairo_clip_t *clip) { cairo_int_status_t status; pixman_trapezoid_t *ptraps = NULL; - pixman_image_t *white_img = NULL; cairo_clip_path_t *clip_path; + proto_image_t *clip_image; int i; status = CAIRO_INT_STATUS_SUCCESS; if (!clip) - { - *clip_image = NULL; - goto out; - } - else if (!(*clip_image = pixman_image_create_bits ( - PIXMAN_a8, width, height, NULL, -1))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } - + return proto_image_new_white(); + /* First add the boxes */ if (!(ptraps = malloc (clip->num_boxes * sizeof (pixman_trapezoid_t)))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } + return proto_image_new_broken(); for (i = 0; i < clip->num_boxes; ++i) { @@ -1040,21 +1232,16 @@ create_clip_image (const cairo_clip_t *clip, int width, int height, trap->right.p2.x = _cairo_fixed_to_16_16 (box->p2.x); trap->right.p2.y = _cairo_fixed_to_16_16 (box->p2.y); } - - pixman_add_trapezoids (*clip_image, 0, 0, clip->num_boxes, ptraps); - + + clip_image = proto_image_new_traps (clip->num_boxes, ptraps); + /* Then intersect with all the paths */ - if (!(white_img = pixman_image_create_solid_fill (&white))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } - for (clip_path = clip->path; clip_path != NULL; clip_path = clip_path->prev) { cairo_polygon_t polygon; cairo_traps_t traps; pixman_trapezoid_t *ptraps = NULL; + proto_image_t *trap_image; _cairo_polygon_init (&polygon, NULL, 0); _cairo_traps_init (&traps); @@ -1063,43 +1250,36 @@ create_clip_image (const cairo_clip_t *clip, int width, int height, &clip_path->path, clip_path->tolerance, &polygon); if (status != CAIRO_INT_STATUS_SUCCESS) - goto exit_loop; + goto err; status = _cairo_bentley_ottmann_tessellate_polygon ( &traps, &polygon, clip_path->fill_rule); if (status != CAIRO_INT_STATUS_SUCCESS) - goto exit_loop; + goto err; if (!(ptraps = traps_to_pixman_trapezoids (&traps))) { status = CAIRO_INT_STATUS_NO_MEMORY; - goto exit_loop; + goto err; } - - pixman_composite_trapezoids ( - PIXMAN_OP_IN, white_img, *clip_image, PIXMAN_a8, 0, 0, 0, 0, - traps.num_traps, ptraps); - exit_loop: + trap_image = proto_image_new_traps (traps.num_traps, ptraps); + clip_image = + proto_image_new_composite (PIXMAN_OP_IN, clip_image, trap_image); + continue; + + err: free (ptraps); _cairo_polygon_fini (&polygon); _cairo_traps_fini (&traps); - if (status != CAIRO_INT_STATUS_SUCCESS) - break; + proto_image_free (clip_image); + clip_image = proto_image_new_broken (); + break; } - -out: - if (status != CAIRO_INT_STATUS_SUCCESS && *clip_image) - pixman_image_unref (*clip_image); - - if (white_img) - pixman_image_unref (white_img); - - free (ptraps); - return status; + return clip_image; } static pixman_op_t @@ -1176,106 +1356,6 @@ _pixman_operator (cairo_operator_t op) } static cairo_int_status_t -proto_image_resolve (proto_image_t *proto_image, int width, int height, - pixman_image_t **result) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - pixman_image_t *white_img; - pixman_format_code_t format; - - if (!(white_img = pixman_image_create_solid_fill (&white))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } - - switch (proto_image->type) - { - case REGION: - if (!(*result = pixman_image_create_bits ( - PIXMAN_a8, width, height, NULL, -1))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } - - pixman_image_set_clip_region32 (*result, proto_image->region.region); - pixman_image_composite32 ( - PIXMAN_OP_SRC, white_img, NULL, *result, - 0, 0, 0, 0, 0, 0, width, height); - break; - - case TRAPS: - if (!(*result = pixman_image_create_bits ( - PIXMAN_a8, width, height, NULL, -1))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } - - pixman_add_trapezoids (*result, 0, 0, - proto_image->traps.n_traps, - proto_image->traps.traps); - break; - - case GLYPHS: - format = pixman_glyph_get_mask_format ( - proto_image->glyphs.glyph_cache, - proto_image->glyphs.n_glyphs, - proto_image->glyphs.glyphs); - - if (!(*result = pixman_image_create_bits ( - format, width, height, NULL, -1))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto out; - } - - pixman_composite_glyphs (PIXMAN_OP_SRC, - white_img, *result, format, - 0, 0, 0, 0, 0, 0, width, height, - proto_image->glyphs.glyph_cache, - proto_image->glyphs.n_glyphs, - proto_image->glyphs.glyphs); - break; - - case PIXMAN: - *result = pixman_image_ref (proto_image->pixman.image); - break; - } - -out: - return status; -} - -static cairo_int_status_t -composite_proto_images (pixman_op_t operator, - proto_image_t * source, - proto_image_t * mask, - pixman_image_t * dest_img) -{ - pixman_image_t *src_img, *mask_img; - cairo_int_status_t status; - int width, height; - - status = proto_image_resolve (source, width, height, &src_img); - if (status != CAIRO_INT_STATUS_SUCCESS) - return status; - - status = proto_image_resolve (mask, width, height, &mask_img); - if (status != CAIRO_INT_STATUS_SUCCESS) - return status; - - pixman_image_composite32 (operator, src_img, mask_img, dest_img, - 0, 0, 0, 0, 0, 0, width, height); - - pixman_image_unref (src_img); - pixman_image_unref (mask_img); - - return CAIRO_INT_STATUS_SUCCESS; -} - -static cairo_int_status_t combine_mask_and_clip (pixman_image_t *mask_image, pixman_image_t *clip_image, pixman_image_t **combined) { @@ -1314,7 +1394,7 @@ combine_mask_and_clip (pixman_image_t *mask_image, pixman_image_t *clip_image, return CAIRO_INT_STATUS_SUCCESS; } -static cairo_int_status_t +static proto_image_t * clip_and_composite (cairo_pixman_surface_t *psurface, cairo_operator_t operator, const cairo_pattern_t *source, @@ -1326,6 +1406,8 @@ clip_and_composite (cairo_pixman_surface_t *psurface, int height = pixman_image_get_height (dest_image); proto_image_t *src_image = NULL; proto_image_t *clip_image = NULL; + proto_image_t *result = NULL; + proto_image_t *dest_image = NULL; pixman_image_t *combined = NULL; cairo_int_status_t status; pixman_op_t pop; @@ -1335,46 +1417,23 @@ clip_and_composite (cairo_pixman_surface_t *psurface, if (clip && _cairo_clip_is_all_clipped (clip)) goto out; - status = create_clip_image (clip, width, height, &clip_image); - if (status != CAIRO_INT_STATUS_SUCCESS) - goto out; + clip_image = create_clip_image (clip); - status = pimage_from_pattern (psurface, source, &src_image); - if (status != CAIRO_INT_STATUS_SUCCESS) - goto out; + src_image = pimage_from_pattern (psurface, source); pop = _pixman_operator (operator); +#if 0 + FIXME + dest_image = proto_image_new_dest(); +#endif + if (pop == PIXMAN_OP_CLEAR) { - if (clip_image) - { - pixman_image_composite32 ( - PIXMAN_OP_OUT_REVERSE, - clip_image, mask_image, dest_image, - 0, 0, 0, 0, 0, 0, width, height); - } - else if (mask_image) - { - pixman_image_composite32 ( - PIXMAN_OP_OUT_REVERSE, - mask_image, NULL, dest_image, - 0, 0, 0, 0, 0, 0, width, height); - } - else - { - if (!(combined = pixman_image_create_solid_fill (&white))) - { - status = CAIRO_INT_STATUS_NO_MEMORY; - - goto out; - } - - pixman_image_composite32 ( - PIXMAN_OP_OUT_REVERSE, - combined, NULL, dest_image, - 0, 0, 0, 0, 0, 0, width, height); - } + result = proto_image_new_composite ( + PIXMAN_OP_IN, clip_image, mask_image); + result = proto_image_new_composite ( + PIXMAN_OP_OUT_REVERSE, result, dest_image); } else if (clip_image && (pop == PIXMAN_OP_IN || @@ -1382,6 +1441,17 @@ clip_and_composite (cairo_pixman_surface_t *psurface, pop == PIXMAN_OP_IN_REVERSE || pop == PIXMAN_OP_ATOP_REVERSE)) { + blank = proto_image_new_blank(); + + result = proto_image_new_composite ( + + + result = proto_image_new_composite ( + PIXMAN_OP_SRC, dest_image, + + result = proto_image_new_composite ( + PIXMAN_OP_SRC, dest_image, proto_image_new_blank()); + /* First composite to a temporary surface */ if (!(combined = pixman_image_create_bits ( pixman_image_get_format (psurface->pimage), |