static cairo_int_status_t
composite_paint (cairo_image_surface_t		*dst,
		 void				*closure,
		 cairo_operator_t		 op,
		 const cairo_pattern_t		*pattern,
		 int				 dst_x,
		 int				 dst_y,
		 const cairo_rectangle_int_t	*extents)
{
    cairo_rectangle_int_t sample;
    pixman_image_t *src;
    int src_x, src_y;

    _cairo_pattern_sampled_area (pattern, extents, &sample);
    src = _pixman_image_for_pattern (dst,
				     pattern, FALSE,
				     extents, &sample,
				     &src_x, &src_y);
    if (unlikely (src == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    pixman_image_composite32 (_pixman_operator (op),
			      src, NULL, dst->pixman_image,
			      extents->x + src_x, extents->y + src_y,
			      0, 0,
			      extents->x - dst_x, extents->y - dst_y,
			      extents->width, extents->height);

    pixman_image_unref (src);

    return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
composite_mask (cairo_image_surface_t		*dst,
		void				*closure,
		cairo_operator_t		 op,
		const cairo_pattern_t		*pattern,
		int				 dst_x,
		int				 dst_y,
		const cairo_rectangle_int_t	 *extents)
{
    cairo_rectangle_int_t sample;
    pixman_image_t *src, *mask;
    int src_x, src_y;
    int mask_x, mask_y;

    TRACE ((stderr, "%s\n", __FUNCTION__));

    _cairo_pattern_sampled_area (pattern, extents, &sample);
    src = _pixman_image_for_pattern (dst, pattern, FALSE,
				     extents, &sample,
				     &src_x, &src_y);
    if (unlikely (src == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    _cairo_pattern_sampled_area (closure, extents, &sample);
    mask = _pixman_image_for_pattern (dst, closure, TRUE,
				      extents, &sample,
				      &mask_x, &mask_y);
    if (unlikely (mask == NULL)) {
	pixman_image_unref (src);
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    pixman_image_composite32 (_pixman_operator (op),
			      src, mask, dst->pixman_image,
			      extents->x + src_x, extents->y + src_y,
			      extents->x + mask_x, extents->y + mask_y,
			      extents->x - dst_x, extents->y - dst_y,
			      extents->width, extents->height);

    pixman_image_unref (mask);
    pixman_image_unref (src);

    return CAIRO_STATUS_SUCCESS;
}
/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
 */
static cairo_status_t
clip_and_composite_source (const cairo_composite_rectangles_t	*extents,
			   draw_func_t				 draw_func,
			   void					*draw_closure)
{
    cairo_image_surface_t *dst = (cairo_image_surface_t *)extents->surface;
    cairo_image_surface_t *mask;
    pixman_image_t *src;
    int src_x, src_y;
    cairo_status_t status = CAIRO_STATUS_SUCCESS;

    TRACE ((stderr, "%s\n", __FUNCTION__));

    mask = create_composite_mask (dst, draw_closure, draw_func, extents);
    if (unlikely (mask->base.status))
	return mask->base.status;

    pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
			      mask->pixman_image, NULL, dst->pixman_image,
			      0,      0,
			      0,      0,
			      extents->bounded.x, extents->bounded.y,
			      extents->bounded.width, extents->bounded.height);

    src = _pixman_image_for_pattern (dst,
				     &extents->source_pattern.base, FALSE,
				     &extents->bounded,
				     &extents->source_sample_area,
				     &src_x, &src_y);
    if (unlikely (src == NULL)) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto error;
    }

    pixman_image_composite32 (PIXMAN_OP_ADD,
			      src, mask->pixman_image, dst->pixman_image,
			      extents->bounded.x + src_x,  extents->bounded.y + src_y,
			      0, 0,
			      extents->bounded.x, extents->bounded.y,
			      extents->bounded.width, extents->bounded.height);

    pixman_image_unref (src);

error:
    cairo_surface_destroy (&mask->base);
    return status;
}
static cairo_int_status_t
composite_traps (cairo_image_surface_t	*dst,
		 void			*closure,
		 cairo_operator_t	 op,
		 const cairo_pattern_t	*pattern,
		 int			 dst_x,
		 int			 dst_y,
		 const cairo_rectangle_int_t *extents)
{
    composite_traps_info_t *info = closure;
    cairo_rectangle_int_t sample;
    pixman_image_t *src, *mask;
    int src_x, src_y;

    TRACE ((stderr, "%s\n", __FUNCTION__));

    _cairo_pattern_sampled_area (pattern, extents, &sample);
    src = _pixman_image_for_pattern (dst, pattern, FALSE,
				     extents, &sample,
				     &src_x, &src_y);
    if (unlikely (src == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    mask = pixman_image_create_bits (info->antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8,
				     extents->width, extents->height,
				     NULL, 0);
    if (unlikely (mask == NULL)) {
	pixman_image_unref (src);
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    _pixman_image_add_traps (mask, extents->x, extents->y, &info->traps);
    pixman_image_composite32 (_pixman_operator (op),
                              src, mask, dst->pixman_image,
                              extents->x + src_x - dst_x, extents->y + src_y - dst_y,
                              0, 0,
                              extents->x - dst_x, extents->y - dst_y,
                              extents->width, extents->height);

    pixman_image_unref (mask);
    pixman_image_unref (src);

    return  CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
composite_glyphs (cairo_image_surface_t	*dst,
		  void			 *closure,
		  cairo_operator_t	 op,
		  const cairo_pattern_t	*pattern,
		  int			 dst_x,
		  int			 dst_y,
		  const cairo_rectangle_int_t *extents)
{
    cairo_composite_glyphs_info_t *info = closure;
    pixman_image_t *mask;
    cairo_status_t status;
    int i;

    mask = pixman_image_create_bits (PIXMAN_a8,
				     extents->width, extents->height,
				     NULL, 0);
    if (unlikely (mask == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    status = CAIRO_STATUS_SUCCESS;
    _cairo_scaled_font_freeze_cache (info->font);
    for (i = 0; i < info->num_glyphs; i++) {
	cairo_image_surface_t *glyph_surface;
	cairo_scaled_glyph_t *scaled_glyph;
	unsigned long glyph_index = info->glyphs[i].index;
	int x, y;

	status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
					     &scaled_glyph);

	if (unlikely (status))
	    break;

	glyph_surface = scaled_glyph->surface;
	if (glyph_surface->width && glyph_surface->height) {
	    /* round glyph locations to the nearest pixel */
	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
	    x = _cairo_lround (info->glyphs[i].x -
			       glyph_surface->base.device_transform.x0);
	    y = _cairo_lround (info->glyphs[i].y -
			       glyph_surface->base.device_transform.y0);

	    pixman_image_composite32 (PIXMAN_OP_ADD,
				      glyph_surface->pixman_image, NULL, mask,
				      0, 0,
                                      0, 0,
                                      x - extents->x, y - extents->y,
				      glyph_surface->width,
				      glyph_surface->height);
	}
    }
    _cairo_scaled_font_thaw_cache (info->font);

    if (status == CAIRO_STATUS_SUCCESS) {
	cairo_rectangle_int_t sample;
	pixman_image_t *src;
	int src_x, src_y;

	_cairo_pattern_sampled_area (pattern, extents, &sample);
	src = _pixman_image_for_pattern (dst, pattern, FALSE,
					 extents, &sample,
					 &src_x, &src_y);
	if (src != NULL) {
	    dst_x = extents->x - dst_x;
	    dst_y = extents->y - dst_y;
	    pixman_image_composite32 (_pixman_operator (op),
				      src, mask, dst->pixman_image,
				      src_x + dst_x,  src_y + dst_y,
				      0, 0,
				      dst_x, dst_y,
				      extents->width, extents->height);
	    pixman_image_unref (src);
	} else
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }
    pixman_image_unref (mask);

    return status;
}