static cairo_surface_t *
_cairo_surface_subsurface_snapshot (void *abstract_surface)
{
    cairo_surface_subsurface_t *surface = abstract_surface;
    cairo_surface_pattern_t pattern;
    cairo_surface_t *clone;
    cairo_status_t status;

    TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->target->unique_id));

    clone = _cairo_surface_create_similar_scratch (surface->target,
						   surface->target->content,
						   surface->extents.width,
						   surface->extents.height);
    if (unlikely (clone->status))
	return clone;

    _cairo_pattern_init_for_surface (&pattern, surface->target);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 surface->extents.x, surface->extents.y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    status = _cairo_surface_paint (clone,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, NULL);
    _cairo_pattern_fini (&pattern.base);

    if (unlikely (status)) {
	cairo_surface_destroy (clone);
	clone = _cairo_surface_create_in_error (status);
    }

    return clone;
}
示例#2
0
cairo_surface_t *
_cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper,
				       cairo_content_t	content,
				       int		width,
				       int		height)
{
    return _cairo_surface_create_similar_scratch (wrapper->target,
						  content, width, height);
}
static cairo_gl_surface_t *
tristrip_to_surface (void *_dst,
		  const cairo_rectangle_int_t *extents,
		  cairo_antialias_t	antialias,
		  cairo_tristrip_t	*strip)
{
    pixman_format_code_t pixman_format;
    pixman_image_t *pixman_image;
    cairo_surface_t *image, *mask;
    cairo_status_t status;

    pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
    pixman_image = pixman_image_create_bits (pixman_format,
					     extents->width,
					     extents->height,
					     NULL, 0);
    if (unlikely (pixman_image == NULL))
	return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    _pixman_image_add_tristrip (pixman_image, extents->x, extents->y, strip);
    image = _cairo_image_surface_create_for_pixman_image (pixman_image,
							  pixman_format);
    if (unlikely (image->status)) {
	pixman_image_unref (pixman_image);
	return (cairo_gl_surface_t *)image;
    }

    mask = _cairo_surface_create_similar_scratch (_dst,
						  CAIRO_CONTENT_COLOR_ALPHA,
						  extents->width,
						  extents->height);
    if (unlikely (mask->status)) {
	cairo_surface_destroy (image);
	return (cairo_gl_surface_t *)mask;
    }

    status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
					   (cairo_image_surface_t *)image,
					   0, 0,
					   extents->width, extents->height,
					   0, 0);
    cairo_surface_destroy (image);
    if (unlikely (status)) {
	cairo_surface_destroy (mask);
	return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status);
    }

    return (cairo_gl_surface_t*)mask;
}
cairo_status_t
_cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
				       cairo_surface_t	*src,
				       cairo_content_t	 content,
				       int		 src_x,
				       int		 src_y,
				       int		 width,
				       int		 height,
				       int		*clone_offset_x,
				       int		*clone_offset_y,
				       cairo_surface_t **clone_out)
{
    cairo_surface_t *new_surface;
    cairo_surface_pattern_t pattern;
    cairo_status_t status;

    new_surface = _cairo_surface_create_similar_scratch (surface,
							 src->content & content,
							 width, height);
    if (new_surface->status)
	return new_surface->status;

    /* We have to copy these here, so that the coordinate spaces are correct */
    new_surface->device_transform = src->device_transform;
    new_surface->device_transform_inverse = src->device_transform_inverse;

    _cairo_pattern_init_for_surface (&pattern, src);
    cairo_matrix_init_translate (&pattern.base.matrix, src_x, src_y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;

    status = _cairo_surface_paint (new_surface,
				   CAIRO_OPERATOR_SOURCE,
				   &pattern.base, NULL);
    _cairo_pattern_fini (&pattern.base);

    if (unlikely (status)) {
	cairo_surface_destroy (new_surface);
	return status;
    }

    *clone_offset_x = src_x;
    *clone_offset_y = src_y;
    *clone_out = new_surface;
    return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_surface_fallback_clone_similar (cairo_surface_t	*surface,
				       cairo_surface_t	*src,
				       int		 src_x,
				       int		 src_y,
				       int		 width,
				       int		 height,
				       cairo_surface_t **clone_out)
{
    cairo_status_t status;
    cairo_surface_t *new_surface = NULL;
    cairo_t *cr;

    new_surface = _cairo_surface_create_similar_scratch (surface,
							 cairo_surface_get_content (src),
							 width, height);
    if (new_surface->status)
	return new_surface->status;

    /* We have to copy these here, so that the coordinate spaces are correct */
    new_surface->device_transform = src->device_transform;
    new_surface->device_transform_inverse = src->device_transform_inverse;

    /* We can't use _cairo_composite directly, because backends that
     * implement the "high-level" API may not have it implemented.
     * (For example, SVG.)  We can fix this by either checking if the
     * destination supports composite first, or we can make clone a
     * required "high-level" operation.
     */
    cr = cairo_create (new_surface);
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_set_source_surface (cr, src, -src_x, -src_y);
    cairo_paint (cr);
    status = cairo_status (cr);
    cairo_destroy (cr);

    if (status == CAIRO_STATUS_SUCCESS)
	*clone_out = new_surface;
    else
	cairo_surface_destroy (new_surface);

    return status;
}
static cairo_int_status_t
traps_to_operand (void *_dst,
		  const cairo_rectangle_int_t *extents,
		  cairo_antialias_t	antialias,
		  cairo_traps_t		*traps,
		  cairo_gl_operand_t	*operand,
		  int dst_x, int dst_y)
{
    pixman_format_code_t pixman_format;
    pixman_image_t *pixman_image;
    cairo_surface_t *image, *mask;
    cairo_surface_pattern_t pattern;
    cairo_status_t status;

    pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1;
    pixman_image = pixman_image_create_bits (pixman_format,
					     extents->width,
					     extents->height,
					     NULL, 0);
    if (unlikely (pixman_image == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    _pixman_image_add_traps (pixman_image, extents->x, extents->y, traps);
    image = _cairo_image_surface_create_for_pixman_image (pixman_image,
							  pixman_format);
    if (unlikely (image->status)) {
	pixman_image_unref (pixman_image);
	return image->status;
    }

    /* GLES2 only supports RGB/RGBA when uploading */
    if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES) {
	cairo_surface_pattern_t pattern;
	cairo_surface_t *rgba_image;

	/* XXX perform this fixup inside _cairo_gl_draw_image() */

	rgba_image =
	    _cairo_image_surface_create_with_pixman_format (NULL,
							    _cairo_is_little_endian () ?  PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8,
							    extents->width,
							    extents->height,
							    0);
	if (unlikely (rgba_image->status))
	    return rgba_image->status;

	_cairo_pattern_init_for_surface (&pattern, image);
	status = _cairo_surface_paint (rgba_image, CAIRO_OPERATOR_SOURCE,
				       &pattern.base, NULL);
	_cairo_pattern_fini (&pattern.base);

	cairo_surface_destroy (image);
	image = rgba_image;

	if (unlikely (status)) {
	    cairo_surface_destroy (image);
	    return status;
	}
    }

    mask = _cairo_surface_create_similar_scratch (_dst,
						  CAIRO_CONTENT_COLOR_ALPHA,
						  extents->width,
						  extents->height);
    if (unlikely (mask->status)) {
	cairo_surface_destroy (image);
	return mask->status;
    }

    status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
					   (cairo_image_surface_t *)image,
					   0, 0,
					   extents->width, extents->height,
					   0, 0);
    cairo_surface_destroy (image);

    if (unlikely (status))
	goto error;

    _cairo_pattern_init_for_surface (&pattern, mask);
    cairo_matrix_init_translate (&pattern.base.matrix,
				 -extents->x+dst_x, -extents->y+dst_y);
    pattern.base.filter = CAIRO_FILTER_NEAREST;
    pattern.base.extend = CAIRO_EXTEND_NONE;
    status = _cairo_gl_operand_init (operand, &pattern.base, _dst,
				     &_cairo_unbounded_rectangle,
				     &_cairo_unbounded_rectangle);
    _cairo_pattern_fini (&pattern.base);

    if (unlikely (status))
	goto error;

    operand->texture.owns_surface = mask;
    return CAIRO_STATUS_SUCCESS;

error:
    cairo_surface_destroy (mask);
    return status;
}