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; }
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; }