Пример #1
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;
}
static cairo_int_status_t
_paint_page (cairo_paginated_surface_t *surface)
{
    cairo_surface_t *analysis;
    cairo_int_status_t status;
    cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback;

    if (unlikely (surface->target->status))
	return (cairo_int_status_t)surface->target->status;

    analysis = _cairo_analysis_surface_create (surface->target);
    if (unlikely (analysis->status))
	return (cairo_int_status_t)_cairo_surface_set_error (surface->target, (cairo_int_status_t)analysis->status);

    surface->backend->set_paginated_mode (surface->target,
	                                  CAIRO_PAGINATED_MODE_ANALYZE);
    status = (cairo_int_status_t)_cairo_recording_surface_replay_and_create_regions (surface->recording_surface,
								 analysis);
    if (status)
	goto FAIL;

    assert (analysis->status == CAIRO_STATUS_SUCCESS);

     if (surface->backend->set_bounding_box) {
	 cairo_box_t bbox;

	 _cairo_analysis_surface_get_bounding_box (analysis, &bbox);
	 status = surface->backend->set_bounding_box (surface->target, &bbox);
	 if (unlikely (status))
	     goto FAIL;
     }

    if (surface->backend->set_fallback_images_required) {
	cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis);

	status = surface->backend->set_fallback_images_required (surface->target,
								 has_fallbacks);
	if (unlikely (status))
	    goto FAIL;
    }

    /* Finer grained fallbacks are currently only supported for some
     * surface types */
    if (surface->backend->supports_fine_grained_fallbacks != NULL &&
	surface->backend->supports_fine_grained_fallbacks (surface->target))
    {
	has_supported = _cairo_analysis_surface_has_supported (analysis);
	has_page_fallback = FALSE;
	has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
    }
    else
    {
	if (_cairo_analysis_surface_has_unsupported (analysis)) {
	    has_supported = FALSE;
	    has_page_fallback = TRUE;
	} else {
	    has_supported = TRUE;
	    has_page_fallback = FALSE;
	}
	has_finegrained_fallback = FALSE;
    }

    if (has_supported) {
	surface->backend->set_paginated_mode (surface->target,
		                              CAIRO_PAGINATED_MODE_RENDER);

	status = (cairo_int_status_t)_cairo_recording_surface_replay_region (surface->recording_surface,
							 NULL,
							 surface->target,
							 CAIRO_RECORDING_REGION_NATIVE);
	assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
	if (unlikely (status))
	    goto FAIL;
    }

    if (has_page_fallback) {
	cairo_rectangle_int_t extents;
	cairo_bool_t is_bounded;

	surface->backend->set_paginated_mode (surface->target,
		                              CAIRO_PAGINATED_MODE_FALLBACK);

	is_bounded = _cairo_surface_get_extents (surface->target, &extents);
	if (! is_bounded) {
	    status = CAIRO_INT_STATUS_UNSUPPORTED;
	    goto FAIL;
	}

	status = _paint_fallback_image (surface, &extents);
	if (unlikely (status))
	    goto FAIL;
    }

    if (has_finegrained_fallback) {
        cairo_region_t *region;
        int num_rects, i;

	surface->backend->set_paginated_mode (surface->target,
		                              CAIRO_PAGINATED_MODE_FALLBACK);

	region = _cairo_analysis_surface_get_unsupported (analysis);

	num_rects = cairo_region_num_rectangles (region);
	for (i = 0; i < num_rects; i++) {
	    cairo_rectangle_int_t rect;

	    cairo_region_get_rectangle (region, i, &rect);
	    status = _paint_fallback_image (surface, &rect);
	    if (unlikely (status))
		goto FAIL;
	}
    }

  FAIL:
    cairo_surface_destroy (analysis);

    return _cairo_surface_set_error (surface->target, status);
}
Пример #3
0
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;
}