Ejemplo n.º 1
0
static cairo_int_status_t
_cairo_analysis_surface_stroke (void			*abstract_surface,
				cairo_operator_t	 op,
				const cairo_pattern_t	*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				double			 tolerance,
				cairo_antialias_t	 antialias,
				cairo_rectangle_int_t   *stroke_extents)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_rectangle_int_t    extents;
    cairo_bool_t             is_empty;

    if (!surface->target->backend->stroke)
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    else
	backend_status = (*surface->target->backend->stroke) (surface->target, op,
							      source, path, style,
							      ctm, ctm_inverse,
							      tolerance, antialias, NULL);

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
	backend_status = _analyze_meta_surface_pattern (surface, source);

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (_cairo_status_is_error (status))
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;

	status = _cairo_pattern_get_extents (source, &source_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
    }

    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_rectangle_int_t mask_extents;

	_cairo_path_fixed_approximate_stroke_extents (path,
						      style, ctm,
						      &mask_extents);

	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
    }
    if (stroke_extents)
	*stroke_extents = extents;

    status = _add_operation (surface, &extents, backend_status);

    return status;
}
Ejemplo n.º 2
0
static cairo_int_status_t
_cairo_analysis_surface_paint (void			*abstract_surface,
			       cairo_operator_t		op,
			       const cairo_pattern_t	*source,
			       const cairo_clip_t		*clip)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	     backend_status;
    cairo_rectangle_int_t  extents;

    if (surface->target->backend->paint == NULL) {
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    } else {
	backend_status =
	    surface->target->backend->paint (surface->target,
					     op, source, clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
	backend_status = _analyze_recording_surface_pattern (surface, source);

    _cairo_analysis_surface_operation_extents (surface,
					       op, source, clip,
					       &extents);

    return _add_operation (surface, &extents, backend_status);
}
Ejemplo n.º 3
0
static cairo_int_status_t
_cairo_analysis_surface_stroke (void			   *abstract_surface,
				cairo_operator_t	    op,
				const cairo_pattern_t	   *source,
				const cairo_path_fixed_t   *path,
				const cairo_stroke_style_t *style,
				const cairo_matrix_t	   *ctm,
				const cairo_matrix_t	   *ctm_inverse,
				double			    tolerance,
				cairo_antialias_t	    antialias,
				const cairo_clip_t	   *clip)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	     backend_status;
    cairo_rectangle_int_t    extents;

    if (surface->target->backend->stroke == NULL) {
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    } else {
	backend_status =
	    surface->target->backend->stroke (surface->target, op,
					      source, path, style,
					      ctm, ctm_inverse,
					      tolerance, antialias,
					      clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }

    _cairo_analysis_surface_operation_extents (surface,
					       op, source, clip,
					       &extents);
    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) {
	cairo_rectangle_int_t rec_extents;
	backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents);
	_cairo_rectangle_intersect (&extents, &rec_extents);
    }

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_rectangle_int_t mask_extents;
	cairo_int_status_t status;

	status = _cairo_path_fixed_stroke_extents (path, style,
						   ctm, ctm_inverse,
						   tolerance,
						   &mask_extents);
	if (unlikely (status))
	    return status;

	_cairo_rectangle_intersect (&extents, &mask_extents);
    }

    return _add_operation (surface, &extents, backend_status);
}
Ejemplo n.º 4
0
static cairo_int_status_t
_cairo_analysis_surface_paint (void			*abstract_surface,
			       cairo_operator_t		op,
			       const cairo_pattern_t	*source,
			       cairo_rectangle_int_t    *paint_extents)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_rectangle_int_t  extents;
    cairo_bool_t is_empty;

    if (!surface->target->backend->paint)
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    else
	backend_status = (*surface->target->backend->paint) (surface->target, op,
                                                             source, NULL);

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
	backend_status = _analyze_meta_surface_pattern (surface, source);

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (_cairo_status_is_error (status))
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;

	status = _cairo_pattern_get_extents (source, &source_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
    }

    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
    if (paint_extents)
	*paint_extents = extents;

    status = _add_operation (surface, &extents, backend_status);

    return status;
}
Ejemplo n.º 5
0
static cairo_int_status_t
_cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
					  cairo_operator_t	     op,
					  const cairo_pattern_t	    *source,
					  const char		    *utf8,
					  int			     utf8_len,
					  cairo_glyph_t		    *glyphs,
					  int			     num_glyphs,
					  const cairo_text_cluster_t *clusters,
					  int			     num_clusters,
					  cairo_text_cluster_flags_t cluster_flags,
					  cairo_scaled_font_t	    *scaled_font,
					  cairo_rectangle_int_t     *show_text_glyphs_extents)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_rectangle_int_t    extents, glyph_extents;
    cairo_bool_t             is_empty;

    /* Adapted from _cairo_surface_show_glyphs */
    backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (surface->target->backend->show_text_glyphs)
	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
								     source,
								     utf8, utf8_len,
								     glyphs, num_glyphs,
								     clusters, num_clusters, cluster_flags,
								     scaled_font, NULL);
    if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
	int remaining_glyphs = num_glyphs;
	backend_status = surface->target->backend->show_glyphs (surface->target, op,
								source,
								glyphs, num_glyphs,
								scaled_font,
								&remaining_glyphs, NULL);
	glyphs += num_glyphs - remaining_glyphs;
	num_glyphs = remaining_glyphs;
	if (remaining_glyphs == 0)
	    backend_status = CAIRO_STATUS_SUCCESS;
    }

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
	backend_status = _analyze_meta_surface_pattern (surface, source);

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (_cairo_status_is_error (status))
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;

	status = _cairo_pattern_get_extents (source, &source_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
    }

    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);

    if (_cairo_operator_bounded_by_mask (op)) {
	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
							  glyphs,
							  num_glyphs,
							  &glyph_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
    }
    if (show_text_glyphs_extents)
	*show_text_glyphs_extents = extents;

    status = _add_operation (surface, &extents, backend_status);

    return status;
}
Ejemplo n.º 6
0
static cairo_int_status_t
_cairo_analysis_surface_mask (void		*abstract_surface,
			      cairo_operator_t	 op,
			      const cairo_pattern_t	*source,
			      const cairo_pattern_t	*mask,
			      cairo_rectangle_int_t 	*mask_extents)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	      status, backend_status;
    cairo_rectangle_int_t   extents;
    cairo_bool_t is_empty;

    if (!surface->target->backend->mask)
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    else
	backend_status = (*surface->target->backend->mask) (surface->target, op,
                                                            source, mask, NULL);

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
	cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
	cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;

	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
	    const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t *) source;
	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
		backend_source_status =
		    _analyze_meta_surface_pattern (surface, source);
		if (_cairo_status_is_error (backend_source_status))
		    return backend_source_status;
	    }
	}

	if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
	    cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask;
	    if (_cairo_surface_is_meta (surface_pattern->surface)) {
		backend_mask_status =
		    _analyze_meta_surface_pattern (surface, mask);
		if (_cairo_status_is_error (backend_mask_status))
		    return backend_mask_status;
	    }
	}

	backend_status =
	    _cairo_analysis_surface_merge_status (backend_source_status,
						  backend_mask_status);
    }

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (_cairo_status_is_error (status))
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;

	status = _cairo_pattern_get_extents (source, &source_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
    }

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_rectangle_int_t mask_extents;

	status = _cairo_pattern_get_extents (mask, &mask_extents);
	if (unlikely (status))
	    return status;

	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
    }

    is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
    if (mask_extents)
	*mask_extents = extents;

    status = _add_operation (surface, &extents, backend_status);

    return status;
}
Ejemplo n.º 7
0
static cairo_int_status_t
_cairo_analysis_surface_show_text_glyphs (void			    *abstract_surface,
					  cairo_operator_t	     op,
					  const cairo_pattern_t	    *source,
					  const char		    *utf8,
					  int			     utf8_len,
					  cairo_glyph_t		    *glyphs,
					  int			     num_glyphs,
					  const cairo_text_cluster_t *clusters,
					  int			     num_clusters,
					  cairo_text_cluster_flags_t cluster_flags,
					  cairo_scaled_font_t	    *scaled_font,
					  const cairo_clip_t		    *clip)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	     status, backend_status;
    cairo_rectangle_int_t    extents, glyph_extents;

    /* Adapted from _cairo_surface_show_glyphs */
    backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (surface->target->backend->show_text_glyphs != NULL) {
	backend_status =
	    surface->target->backend->show_text_glyphs (surface->target, op,
							source,
							utf8, utf8_len,
							glyphs, num_glyphs,
							clusters, num_clusters,
							cluster_flags,
							scaled_font,
							clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }
    if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED &&
	surface->target->backend->show_glyphs != NULL)
    {
	backend_status =
	    surface->target->backend->show_glyphs (surface->target, op,
						   source,
						   glyphs, num_glyphs,
						   scaled_font,
						   clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
	backend_status = _analyze_recording_surface_pattern (surface, source);

    _cairo_analysis_surface_operation_extents (surface,
					       op, source, clip,
					       &extents);

    if (_cairo_operator_bounded_by_mask (op)) {
	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
							  glyphs,
							  num_glyphs,
							  &glyph_extents,
							  NULL);
	if (unlikely (status))
	    return status;

	_cairo_rectangle_intersect (&extents, &glyph_extents);
    }

    return _add_operation (surface, &extents, backend_status);
}
Ejemplo n.º 8
0
static cairo_int_status_t
_cairo_analysis_surface_mask (void			*abstract_surface,
			      cairo_operator_t		 op,
			      const cairo_pattern_t	*source,
			      const cairo_pattern_t	*mask,
			      const cairo_clip_t		*clip)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_int_status_t	      backend_status;
    cairo_rectangle_int_t   extents;

    if (surface->target->backend->mask == NULL) {
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    } else {
	backend_status =
	    surface->target->backend->mask (surface->target,
					    op, source, mask, clip);
	if (_cairo_int_status_is_error (backend_status))
	    return backend_status;
    }

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) {
	cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
	cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;

	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
	    cairo_surface_t *src_surface = ((cairo_surface_pattern_t *)source)->surface;
	    src_surface = _cairo_surface_get_source (src_surface, NULL);
	    if (_cairo_surface_is_recording (src_surface)) {
		backend_source_status =
		    _analyze_recording_surface_pattern (surface, source);
		if (_cairo_int_status_is_error (backend_source_status))
		    return backend_source_status;
	    }
	}

	if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
	    cairo_surface_t *mask_surface = ((cairo_surface_pattern_t *)mask)->surface;
	    mask_surface = _cairo_surface_get_source (mask_surface, NULL);
	    if (_cairo_surface_is_recording (mask_surface)) {
		backend_mask_status =
		    _analyze_recording_surface_pattern (surface, mask);
		if (_cairo_int_status_is_error (backend_mask_status))
		    return backend_mask_status;
	    }
	}

	backend_status =
	    _cairo_analysis_surface_merge_status (backend_source_status,
						  backend_mask_status);
    }

    _cairo_analysis_surface_operation_extents (surface,
					       op, source, clip,
					       &extents);

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_rectangle_int_t mask_extents;

	_cairo_pattern_get_extents (mask, &mask_extents);
	_cairo_rectangle_intersect (&extents, &mask_extents);
    }

    return _add_operation (surface, &extents, backend_status);
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
static cairo_int_status_t
_cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
				     cairo_operator_t	   op,
				     cairo_pattern_t	  *source,
				     cairo_glyph_t	  *glyphs,
				     int		   num_glyphs,
				     cairo_scaled_font_t  *scaled_font,
				     int                  *remaining_glyphs)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_rectangle_int_t    extents, glyph_extents;

    /* Adapted from _cairo_surface_show_glyphs */
    if (surface->target->backend->show_glyphs)
	backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
								   source,
								   glyphs, num_glyphs,
								   scaled_font,
								   remaining_glyphs);
    else if (surface->target->backend->show_text_glyphs)
	backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
								     source,
								     NULL, 0,
								     glyphs, num_glyphs,
								     NULL, 0,
								     FALSE,
								     scaled_font);
    else
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
	backend_status = _analyze_meta_surface_pattern (surface, source);

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;
	status = _cairo_pattern_get_extents (source, &source_extents);
	if (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    _cairo_rectangle_intersect (&extents, &surface->current_clip);

    if (_cairo_operator_bounded_by_mask (op)) {
	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
							  glyphs,
							  num_glyphs,
							  &glyph_extents);
	if (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &glyph_extents);
    }

    status = _add_operation (surface, &extents, backend_status);

    return status;
}
Ejemplo n.º 11
0
static cairo_int_status_t
_cairo_analysis_surface_fill (void			*abstract_surface,
			      cairo_operator_t		 op,
			      cairo_pattern_t		*source,
			      cairo_path_fixed_t	*path,
			      cairo_fill_rule_t		 fill_rule,
			      double			 tolerance,
			      cairo_antialias_t		 antialias)
{
    cairo_analysis_surface_t *surface = abstract_surface;
    cairo_status_t	     status, backend_status;
    cairo_traps_t            traps;
    cairo_rectangle_int_t  extents;

    if (!surface->target->backend->fill)
	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
    else
	backend_status = (*surface->target->backend->fill) (surface->target, op,
						    source, path, fill_rule,
						    tolerance, antialias);

    if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
	backend_status = _analyze_meta_surface_pattern (surface, source);

    status = _cairo_surface_get_extents (&surface->base, &extents);
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    if (_cairo_operator_bounded_by_source (op)) {
	cairo_rectangle_int_t source_extents;
	status = _cairo_pattern_get_extents (source, &source_extents);
	if (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    _cairo_rectangle_intersect (&extents, &surface->current_clip);

    if (_cairo_operator_bounded_by_mask (op)) {
	cairo_box_t box;

	_cairo_box_from_rectangle (&box, &extents);

	_cairo_traps_init (&traps);
	_cairo_traps_limit (&traps, &box);
	status = _cairo_path_fixed_fill_to_traps (path,
						  fill_rule,
						  tolerance,
						  &traps);
	if (status) {
	    _cairo_traps_fini (&traps);
	    return status;
	}

	_cairo_traps_extents (&traps, &box);
	_cairo_traps_fini (&traps);

        _cairo_box_round_to_rectangle (&box, &extents);
    }

    status = _add_operation (surface, &extents, backend_status);

    return status;
}