pixman_image_t * FbCreateAlphaPicture (pixman_image_t *dst, pixman_format_t *format, uint16_t width, uint16_t height) { pixman_image_t *image; int own_format = 0; if (width > 32767 || height > 32767) return NULL; if (!format) { own_format = 1; if (dst->polyEdge == PolyEdgeSharp) format = pixman_format_create (PIXMAN_FORMAT_NAME_A1); else format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); if (!format) return NULL; } image = pixman_image_create (format, width, height); if (own_format) pixman_format_destroy (format); /* XXX: Is this a reasonable way to clear the image? Would probably be preferable to use pixman_image_fill_rectangle once such a beast exists. */ memset (image->pixels->data, 0, height * image->pixels->stride); return image; }
static pixman_format_t * _create_pixman_format (cairo_format_t format) { switch (format) { case CAIRO_FORMAT_A1: return pixman_format_create (PIXMAN_FORMAT_NAME_A1); break; case CAIRO_FORMAT_A8: return pixman_format_create (PIXMAN_FORMAT_NAME_A8); break; case CAIRO_FORMAT_RGB24: return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24); break; case CAIRO_FORMAT_ARGB32: default: return pixman_format_create (PIXMAN_FORMAT_NAME_ARGB32); break; } }
/* XXX: There are failure cases in this function. Don't we need to * propagate the errors out? */ void pixman_composite_trapezoids (pixman_operator_t op, pixman_image_t *src, pixman_image_t *dst, int xSrc, int ySrc, const pixman_trapezoid_t *traps, int ntraps) { pixman_image_t *image = NULL; pixman_box16_t traps_bounds, dst_bounds, bounds; pixman_region16_t *traps_region, *dst_region; int16_t xDst, yDst; int16_t xRel, yRel; pixman_format_t *format; if (ntraps == 0) return; /* * Check for solid alpha add */ if (op == PIXMAN_OPERATOR_ADD && miIsSolidAlpha (src)) { for (; ntraps; ntraps--, traps++) fbRasterizeTrapezoid (dst, traps, 0, 0); return; } xDst = traps[0].left.p1.x >> 16; yDst = traps[0].left.p1.y >> 16; pixman_trapezoid_bounds (ntraps, traps, &traps_bounds); traps_region = pixman_region_create_simple (&traps_bounds); /* XXX: If the image has a clip region set, we should really be * fetching it here instead, but it looks like we don't yet expose * a pixman_image_get_clip_region function. */ dst_bounds.x1 = 0; dst_bounds.y1 = 0; dst_bounds.x2 = pixman_image_get_width (dst); dst_bounds.y2 = pixman_image_get_height (dst); dst_region = pixman_region_create_simple (&dst_bounds); pixman_region_intersect (traps_region, traps_region, dst_region); bounds = *(pixman_region_extents (traps_region)); pixman_region_destroy (traps_region); pixman_region_destroy (dst_region); if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) return; format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); if (!format) return; image = FbCreateAlphaPicture (dst, format, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); if (!image) { pixman_format_destroy (format); return; } for (; ntraps; ntraps--, traps++) { if (!xTrapezoidValid(traps)) continue; fbRasterizeTrapezoid (image, traps, -bounds.x1, -bounds.y1); } xRel = bounds.x1 + xSrc - xDst; yRel = bounds.y1 + ySrc - yDst; pixman_composite (op, src, image, dst, xRel, yRel, 0, 0, bounds.x1, bounds.y1, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); pixman_image_destroy (image); pixman_format_destroy (format); }
static cairo_int_status_t _cairo_image_surface_composite_trapezoids (cairo_operator_t op, cairo_pattern_t *pattern, void *abstract_dst, cairo_antialias_t antialias, int src_x, int src_y, int dst_x, int dst_y, unsigned int width, unsigned int height, cairo_trapezoid_t *traps, int num_traps) { cairo_surface_attributes_t attributes; cairo_image_surface_t *dst = abstract_dst; cairo_image_surface_t *src; cairo_int_status_t status; pixman_image_t *mask; pixman_format_t *format; pixman_bits_t *mask_data; int mask_stride; int mask_bpp; /* Special case adding trapezoids onto a mask surface; we want to avoid * creating an intermediate temporary mask unecessarily. * * We make the assumption here that the portion of the trapezoids * contained within the surface is bounded by [dst_x,dst_y,width,height]; * the Cairo core code passes bounds based on the trapezoid extents. * * Currently the check surface->has_clip is needed for correct * functioning, since pixman_add_trapezoids() doesn't obey the * surface clip, which is a libpixman bug , but there's no harm in * falling through to the general case when the surface is clipped * since libpixman would have to generate an intermediate mask anyways. */ if (op == CAIRO_OPERATOR_ADD && _cairo_pattern_is_opaque_solid (pattern) && _cairo_image_surface_is_alpha_only (dst) && !dst->has_clip && antialias != CAIRO_ANTIALIAS_NONE) { pixman_add_trapezoids (dst->pixman_image, 0, 0, (pixman_trapezoid_t *) traps, num_traps); return CAIRO_STATUS_SUCCESS; } status = _cairo_pattern_acquire_surface (pattern, &dst->base, src_x, src_y, width, height, (cairo_surface_t **) &src, &attributes); if (status) return status; status = _cairo_image_surface_set_attributes (src, &attributes); if (status) goto CLEANUP_SOURCE; switch (antialias) { case CAIRO_ANTIALIAS_NONE: format = pixman_format_create (PIXMAN_FORMAT_NAME_A1); mask_stride = (width + 31)/8; mask_bpp = 1; break; default: format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); mask_stride = (width + 3) & ~3; mask_bpp = 8; break; } if (!format) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP_SOURCE; } /* The image must be initially transparent */ mask_data = calloc (1, mask_stride * height); if (!mask_data) { status = CAIRO_STATUS_NO_MEMORY; pixman_format_destroy (format); goto CLEANUP_SOURCE; } mask = pixman_image_create_for_data (mask_data, format, width, height, mask_bpp, mask_stride); pixman_format_destroy (format); if (!mask) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP_IMAGE_DATA; } /* XXX: The pixman_trapezoid_t cast is evil and needs to go away * somehow. */ pixman_add_trapezoids (mask, - dst_x, - dst_y, (pixman_trapezoid_t *) traps, num_traps); pixman_composite (_pixman_operator (op), src->pixman_image, mask, dst->pixman_image, src_x + attributes.x_offset, src_y + attributes.y_offset, 0, 0, dst_x, dst_y, width, height); if (!_cairo_operator_bounded_by_mask (op)) status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base, &attributes, src->width, src->height, width, height, src_x, src_y, 0, 0, dst_x, dst_y, width, height); pixman_image_destroy (mask); CLEANUP_IMAGE_DATA: free (mask_data); CLEANUP_SOURCE: _cairo_pattern_release_surface (pattern, &src->base, &attributes); return status; }