コード例 #1
0
ファイル: cairo-xcb-surface.c プロジェクト: mrobinson/cairo
static cairo_status_t
_cairo_xcb_surface_acquire_source_image (void *abstract_surface,
					 cairo_image_surface_t **image_out,
					 void **image_extra)
{
    cairo_xcb_surface_t *surface = abstract_surface;
    cairo_surface_t *image;

    if (surface->fallback != NULL) {
	image = cairo_surface_reference (&surface->fallback->base);
	goto DONE;
    }

    image = _cairo_surface_has_snapshot (&surface->base,
					 &_cairo_image_surface_backend);
    if (image != NULL) {
	image = cairo_surface_reference (image);
	goto DONE;
    }

    image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height);
    if (unlikely (image->status))
	return image->status;

    _cairo_surface_attach_snapshot (&surface->base, image, NULL);

DONE:
    *image_out = (cairo_image_surface_t *) image;
    *image_extra = NULL;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #2
0
/**
 * _cairo_surface_snapshot:
 * @surface: a #cairo_surface_t
 *
 * Make an immutable reference to @surface. It is an error to call a
 * surface-modifying function on the result of this function. The
 * resulting 'snapshot' is a lazily copied-on-write surface i.e. it
 * remains a reference to the original surface until that surface is
 * written to again, at which time a copy is made of the original surface
 * and the snapshot then points to that instead. Multiple snapshots of the
 * same unmodified surface point to the same copy.
 *
 * The caller owns the return value and should call
 * cairo_surface_destroy() when finished with it. This function will not
 * return %NULL, but will return a nil surface instead.
 *
 * Return value: The snapshot surface. Note that the return surface
 * may not necessarily be of the same type as @surface.
 **/
cairo_surface_t *
_cairo_surface_snapshot (cairo_surface_t *surface)
{
    cairo_surface_snapshot_t *snapshot;
    cairo_status_t status;

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

    if (unlikely (surface->status))
	return _cairo_surface_create_in_error (surface->status);

    if (unlikely (surface->finished))
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));

    if (surface->snapshot_of != NULL)
	return cairo_surface_reference (surface);

    if (_cairo_surface_is_snapshot (surface))
	return cairo_surface_reference (surface);

    snapshot = (cairo_surface_snapshot_t *)
	_cairo_surface_has_snapshot (surface, &_cairo_surface_snapshot_backend);
    if (snapshot != NULL)
	return cairo_surface_reference (&snapshot->base);

    snapshot = malloc (sizeof (cairo_surface_snapshot_t));
    if (unlikely (snapshot == NULL))
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));

    _cairo_surface_init (&snapshot->base,
			 &_cairo_surface_snapshot_backend,
			 NULL, /* device */
			 surface->content);
    snapshot->base.type = surface->type;

    CAIRO_MUTEX_INIT (snapshot->mutex);
    snapshot->target = surface;
    snapshot->clone = NULL;

    status = _cairo_surface_copy_mime_data (&snapshot->base, surface);
    if (unlikely (status)) {
	cairo_surface_destroy (&snapshot->base);
	return _cairo_surface_create_in_error (status);
    }

    snapshot->base.device_transform = surface->device_transform;
    snapshot->base.device_transform_inverse = surface->device_transform_inverse;

    _cairo_surface_attach_snapshot (surface,
				    &snapshot->base,
				    _cairo_surface_snapshot_copy_on_write);

    return &snapshot->base;
}
コード例 #3
0
static cairo_int_status_t
_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
				    const cairo_pattern_t    *pattern)
{
    const cairo_surface_pattern_t *surface_pattern;
    cairo_analysis_surface_t *tmp;
    cairo_surface_t *source, *proxy;
    cairo_matrix_t p2d;
    cairo_status_t status, analysis_status;

    assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
    surface_pattern = (const cairo_surface_pattern_t *) pattern;
    assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING);
    source = surface_pattern->surface;

    proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
    if (proxy != NULL) {
	/* nothing untoward found so far */
	return CAIRO_STATUS_SUCCESS;
    }

    tmp = (cairo_analysis_surface_t *)
	_cairo_analysis_surface_create (surface->target);
    if (unlikely (tmp->base.status))
	return tmp->base.status;
    proxy = attach_proxy (source, &tmp->base);

    p2d = pattern->matrix;
    status = cairo_matrix_invert (&p2d);
    assert (status == CAIRO_STATUS_SUCCESS);

    cairo_matrix_multiply (&tmp->ctm, &p2d, &surface->ctm);
    tmp->has_ctm = ! _cairo_matrix_is_identity (&tmp->ctm);

    if (_cairo_surface_is_snapshot (source))
	source = _cairo_surface_snapshot_get_target (source);
    if (_cairo_surface_is_subsurface (source))
	source = _cairo_surface_subsurface_get_target (source);

    status = _cairo_recording_surface_replay_and_create_regions (source,
								 &tmp->base);
    analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS;
    detach_proxy (proxy);
    cairo_surface_destroy (&tmp->base);

    if (unlikely (status))
	return status;

    return analysis_status;
}
コード例 #4
0
cairo_status_t
intel_surface_acquire_source_image (void *abstract_surface,
				    cairo_image_surface_t **image_out,
				    void **image_extra)
{
    intel_surface_t *surface = abstract_surface;
    cairo_surface_t *image;
    cairo_status_t status;
    void *ptr;

    if (surface->drm.fallback != NULL) {
	image = surface->drm.fallback;
	goto DONE;
    }

    image = _cairo_surface_has_snapshot (&surface->drm.base,
	                                 &_cairo_image_surface_backend);
    if (image != NULL)
	goto DONE;

    if (surface->drm.base.backend->flush != NULL) {
	status = surface->drm.base.backend->flush (surface);
	if (unlikely (status))
	    return status;
    }

    ptr = intel_bo_map (to_intel_device (surface->drm.base.device),
			to_intel_bo (surface->drm.bo));
    if (unlikely (ptr == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    image = cairo_image_surface_create_for_data (ptr,
						 surface->drm.format,
						 surface->drm.width,
						 surface->drm.height,
						 surface->drm.stride);
    if (unlikely (image->status))
	return image->status;

    _cairo_surface_attach_snapshot (&surface->drm.base, image, surface_finish_and_destroy);

DONE:
    *image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
    *image_extra = NULL;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #5
0
static cairo_status_t
radeon_surface_acquire_source_image (void *abstract_surface,
				     cairo_image_surface_t **image_out,
				     void **image_extra)
{
    radeon_surface_t *surface = abstract_surface;
    cairo_surface_t *image;
    cairo_status_t status;

    /* XXX batch flush */

    if (surface->base.fallback != NULL) {
	image = surface->base.fallback;
	goto DONE;
    }

    image = _cairo_surface_has_snapshot (&surface->base.base,
	                                 &_cairo_image_surface_backend);
    if (image != NULL)
	goto DONE;

    if (surface->base.base.backend->flush != NULL) {
	status = surface->base.base.backend->flush (surface);
	if (unlikely (status))
	    return status;
    }

    image = radeon_bo_get_image (to_radeon_device (surface->base.base.device),
				to_radeon_bo (surface->base.bo),
				&surface->base);
    status = image->status;
    if (unlikely (status))
	return status;

    _cairo_surface_attach_snapshot (&surface->base.base, image, cairo_surface_destroy);

DONE:
    *image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
    *image_extra = NULL;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #6
0
static cairo_status_t
_cairo_recording_surface_acquire_source_image (void			 *abstract_surface,
					       cairo_image_surface_t	**image_out,
					       void			**image_extra)
{
    cairo_status_t status;
    cairo_recording_surface_t *surface = abstract_surface;
    cairo_surface_t *image;

    image = _cairo_surface_has_snapshot (&surface->base,
					 &_cairo_image_surface_backend);
    if (image != NULL) {
	*image_out = (cairo_image_surface_t *) cairo_surface_reference (image);
	*image_extra = NULL;
	return CAIRO_STATUS_SUCCESS;
    }

    image = _cairo_image_surface_create_with_content (surface->content,
						      surface->extents.width,
						      surface->extents.height);
    if (unlikely (image->status))
	return image->status;

    cairo_surface_set_device_offset (image,
				     -surface->extents.x,
				     -surface->extents.y);

    status = _cairo_recording_surface_replay (&surface->base, image);
    if (unlikely (status)) {
	cairo_surface_destroy (image);
	return status;
    }

    _cairo_surface_attach_snapshot (&surface->base, image, NULL);

    *image_out = (cairo_image_surface_t *) image;
    *image_extra = NULL;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #7
0
ファイル: cairo-xcb-surface.c プロジェクト: ghub/NVprSDK
static cairo_status_t
_cairo_xcb_surface_acquire_source_image (void *abstract_surface,
					 cairo_image_surface_t **image_out,
					 void **image_extra)
{
    cairo_xcb_surface_t *surface = abstract_surface;
    cairo_image_surface_t *image;
    cairo_status_t status;

    if (surface->drm != NULL && ! surface->marked_dirty) {
	return _cairo_surface_acquire_source_image (surface->drm,
						    image_out, image_extra);
    }

    if (surface->fallback != NULL) {
	image = (cairo_image_surface_t *) cairo_surface_reference (surface->fallback);
	goto DONE;
    }

    image = (cairo_image_surface_t *)
	_cairo_surface_has_snapshot (&surface->base,
				     &_cairo_image_surface_backend);
    if (image != NULL) {
	image = (cairo_image_surface_t *) cairo_surface_reference (&image->base);
	goto DONE;
    }

    status = _get_image (surface, FALSE, &image);
    if (unlikely (status))
	return status;

    _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);

DONE:
    *image_out = image;
    *image_extra = NULL;
    return CAIRO_STATUS_SUCCESS;
}
コード例 #8
0
/**
 * _cairo_surface_snapshot
 * @surface: a #cairo_surface_t
 *
 * Make an immutable reference to @surface. It is an error to call a
 * surface-modifying function on the result of this function. The
 * resulting 'snapshot' is a lazily copied-on-write surface i.e. it
 * remains a reference to the original surface until that surface is
 * written to again, at which time a copy is made of the original surface
 * and the snapshot then points to that instead. Multiple snapshots of the
 * same unmodified surface point to the same copy.
 *
 * The caller owns the return value and should call
 * cairo_surface_destroy() when finished with it. This function will not
 * return %NULL, but will return a nil surface instead.
 *
 * Return value: The snapshot surface. Note that the return surface
 * may not necessarily be of the same type as @surface.
 **/
cairo_surface_t *
_cairo_surface_snapshot (cairo_surface_t *surface)
{
    cairo_surface_snapshot_t *snapshot;
    cairo_status_t status;

    if (unlikely (surface->status))
	return _cairo_surface_create_in_error (surface->status);

    if (surface->finished)
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));

    if (surface->snapshot_of != NULL)
	return cairo_surface_reference (surface);

    if (surface->backend->snapshot != NULL) {
	cairo_surface_t *snap;

	snap = _cairo_surface_has_snapshot (surface, surface->backend);
	if (snap != NULL)
	    return cairo_surface_reference (snap);

	snap = surface->backend->snapshot (surface);
	if (snap != NULL) {
	    if (unlikely (snap->status))
		return snap;

	    status = _cairo_surface_copy_mime_data (snap, surface);
	    if (unlikely (status)) {
		cairo_surface_destroy (snap);
		return _cairo_surface_create_in_error (status);
	    }

	    snap->device_transform = surface->device_transform;
	    snap->device_transform_inverse = surface->device_transform_inverse;

	    cairo_surface_attach_snapshot (surface, snap, NULL);

	    return snap;
	}
    }

    snapshot = (cairo_surface_snapshot_t *)
	_cairo_surface_has_snapshot (surface, &_cairo_surface_snapshot_backend);
    if (snapshot != NULL)
	return cairo_surface_reference (&snapshot->base);

    snapshot = malloc (sizeof (cairo_surface_snapshot_t));
    if (unlikely (snapshot == NULL))
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));

    _cairo_surface_init (&snapshot->base,
			 &_cairo_surface_snapshot_backend,
			 NULL, /* device */
			 surface->content);
    snapshot->base.type = surface->type;

    snapshot->target = surface;
    snapshot->clone = NULL;

    status = _cairo_surface_copy_mime_data (&snapshot->base, surface);
    if (unlikely (status)) {
	cairo_surface_destroy (&snapshot->base);
	return _cairo_surface_create_in_error (status);
    }

    snapshot->base.device_transform = surface->device_transform;
    snapshot->base.device_transform_inverse = surface->device_transform_inverse;

    cairo_surface_attach_snapshot (surface,
				    &snapshot->base,
				    _cairo_surface_snapshot_copy_on_write);

    return &snapshot->base;
}
コード例 #9
0
ファイル: cairo-xcb-surface-core.c プロジェクト: ghub/NVprSDK
static cairo_xcb_pixmap_t *
_cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
			   const cairo_surface_pattern_t *pattern,
			   const cairo_rectangle_int_t *extents,
			   int tx, int ty)
{
    cairo_surface_t *source;
    cairo_xcb_pixmap_t *pixmap;

    source =  pattern->surface;
    pixmap = (cairo_xcb_pixmap_t *)
	_cairo_surface_has_snapshot (source, &_cairo_xcb_pixmap_backend);
    if (pixmap != NULL && pixmap->screen == target->screen)
	return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base);

    if (source->type == CAIRO_SURFACE_TYPE_XCB &&
	((cairo_xcb_surface_t *) source)->screen == target->screen)
    {
	cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source;

	if (xcb_source->depth == target->depth)
	    pixmap = _copy_to_pixmap (xcb_source);
    }
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
    else if (source->type == CAIRO_SURFACE_TYPE_XLIB &&
	     ((cairo_xlib_xcb_surface_t *) source)->xcb->screen == target->screen)
    {
	cairo_xcb_surface_t *xcb_source = ((cairo_xlib_xcb_surface_t *) source)->xcb;

	if (xcb_source->depth == target->depth)
	    pixmap = _copy_to_pixmap (xcb_source);
    }
#endif

    if (pixmap == NULL) {
	cairo_rectangle_int_t rect;

	if (! _cairo_surface_get_extents (source, &rect)) {
	    rect.x = rect.y = 0;
	    rect.width  = target->width;
	    rect.height = target->height;
	}

	pixmap = _render_to_pixmap (target, &pattern->base, &rect);
    }

    if (unlikely (pixmap->base.status))
	return pixmap;

    _cairo_surface_attach_snapshot (source, &pixmap->base, NULL);

    if (pattern->base.extend != CAIRO_EXTEND_NONE) {
	if (extents->x < 0 || extents->y < 0 ||
	    extents->x + extents->width  > pixmap->width ||
	    extents->y + extents->height > pixmap->height)
	{
	    pixmap->repeat = TRUE;
	}
    }

    pixmap->x0 += tx;
    pixmap->y0 += ty;

    return pixmap;
}
コード例 #10
0
ファイル: cairo-analysis-surface.c プロジェクト: behdad/cairo
static cairo_int_status_t
_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
				    const cairo_pattern_t    *pattern,
				    cairo_rectangle_int_t    *extents)
{
    const cairo_surface_pattern_t *surface_pattern;
    cairo_analysis_surface_t *tmp;
    cairo_surface_t *source, *proxy;
    cairo_matrix_t p2d;
    cairo_int_status_t status, analysis_status;
    cairo_bool_t surface_is_unbounded;
    cairo_bool_t unused;

    assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
    surface_pattern = (const cairo_surface_pattern_t *) pattern;
    assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING);
    source = surface_pattern->surface;

    proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
    if (proxy != NULL) {
	/* nothing untoward found so far */
	return CAIRO_STATUS_SUCCESS;
    }

    tmp = (cairo_analysis_surface_t *)
	_cairo_analysis_surface_create (surface->target);
    if (unlikely (tmp->base.status)) {
	status =tmp->base.status;
	goto cleanup1;
    }
    proxy = attach_proxy (source, &tmp->base);

    p2d = pattern->matrix;
    status = cairo_matrix_invert (&p2d);
    assert (status == CAIRO_INT_STATUS_SUCCESS);
    _cairo_analysis_surface_set_ctm (&tmp->base, &p2d);


    source = _cairo_surface_get_source (source, NULL);
    surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT
				     || pattern->extend == CAIRO_EXTEND_REFLECT);
    status = _cairo_recording_surface_replay_and_create_regions (source,
								 &pattern->matrix,
								 &tmp->base,
								 surface_is_unbounded);
    if (unlikely (status))
	goto cleanup2;

    /* black background or mime data fills entire extents */
    if (!(source->content & CAIRO_CONTENT_ALPHA) || _cairo_surface_has_mime_image (source)) {
	cairo_rectangle_int_t rect;

	if (_cairo_surface_get_extents (source, &rect)) {
	    cairo_box_t bbox;

	    _cairo_box_from_rectangle (&bbox, &rect);
	    _cairo_matrix_transform_bounding_box_fixed (&p2d, &bbox, NULL);
	    _cairo_box_round_to_rectangle (&bbox, &rect);
	    status = _add_operation (tmp, &rect, CAIRO_INT_STATUS_SUCCESS);
	    if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
		status = CAIRO_INT_STATUS_SUCCESS;
	    if (unlikely (status))
		goto cleanup2;
	}
    }

    if (tmp->has_supported) {
	surface->has_supported = TRUE;
	unused = cairo_region_union (&surface->supported_region, &tmp->supported_region);
    }

    if (tmp->has_unsupported) {
	surface->has_unsupported = TRUE;
	unused = cairo_region_union (&surface->fallback_region, &tmp->fallback_region);
    }

    analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS;
    if (pattern->extend != CAIRO_EXTEND_NONE) {
	_cairo_unbounded_rectangle_init (extents);
    } else {
	status = cairo_matrix_invert (&tmp->ctm);
	_cairo_matrix_transform_bounding_box_fixed (&tmp->ctm,
						    &tmp->page_bbox, NULL);
	_cairo_box_round_to_rectangle (&tmp->page_bbox, extents);
    }

  cleanup2:
    detach_proxy (proxy);
  cleanup1:
    cairo_surface_destroy (&tmp->base);

    if (unlikely (status))
	return status;

    return analysis_status;
}