cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t		*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_status_t status;
    cairo_traps_t traps;

    _cairo_traps_init (&traps);

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

    status = _clip_and_composite_trapezoids (source,
					     op,
					     surface,
					     &traps,
					     surface->clip,
					     antialias);

    _cairo_traps_fini (&traps);

    return status;
}
cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t		*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_status_t status;
    cairo_traps_t traps;
    cairo_box_t box;
    cairo_rectangle_int_t extents;

    status = _cairo_surface_get_extents (surface, &extents);
    if (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 (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (status)
        return status;

    box.p1.x = _cairo_fixed_from_int (extents.x);
    box.p1.y = _cairo_fixed_from_int (extents.y);
    box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
    box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);

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

    status = _clip_and_composite_trapezoids (source,
					     op,
					     surface,
					     &traps,
					     surface->clip,
					     antialias);

    _cairo_traps_fini (&traps);

    return status;
}
cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t	*surface,
			       cairo_operator_t	 op,
			       cairo_pattern_t	*source)
{
    cairo_status_t status;
    cairo_rectangle_int_t extents;
    cairo_box_t box;
    cairo_traps_t traps;

    status = _cairo_surface_get_extents (surface, &extents);
    if (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 (status)
	    return status;

	_cairo_rectangle_intersect (&extents, &source_extents);
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (status)
	return status;

    box.p1.x = _cairo_fixed_from_int (extents.x);
    box.p1.y = _cairo_fixed_from_int (extents.y);
    box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
    box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);

    status = _cairo_traps_init_box (&traps, &box);
    if (status)
	return status;

    status = _clip_and_composite_trapezoids (source,
				             op,
					     surface,
					     &traps,
					     surface->clip,
					     CAIRO_ANTIALIAS_NONE);

    _cairo_traps_fini (&traps);

    return status;
}
cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t		*surface,
			       cairo_operator_t		 op,
			       const cairo_pattern_t	*source)
{
    cairo_status_t status;
    cairo_rectangle_int_t extents;
    cairo_box_t box;
    cairo_traps_t traps;

    status = _cairo_surface_get_extents (surface, &extents);
    if (unlikely (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;

	if (! _cairo_rectangle_intersect (&extents, &source_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (unlikely (status))
	return status;

    _cairo_box_from_rectangle (&box, &extents);

    _cairo_traps_init_box (&traps, &box);

    status = _clip_and_composite_trapezoids (source,
				             op,
					     surface,
					     &traps,
					     surface->clip,
					     CAIRO_ANTIALIAS_NONE);

    _cairo_traps_fini (&traps);

    return status;
}
cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t		*surface,
				cairo_operator_t	 op,
				cairo_pattern_t		*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*stroke_style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				double			 tolerance,
				cairo_antialias_t	 antialias)
{
    cairo_status_t status;
    cairo_traps_t traps;

    _cairo_traps_init (&traps);

    status = _cairo_path_fixed_stroke_to_traps (path,
						stroke_style,
						ctm, ctm_inverse,
						tolerance,
						&traps);
    if (status) {
	_cairo_traps_fini (&traps);
	return status;
    }

    _clip_and_composite_trapezoids (source,
				    op,
				    surface,
				    &traps,
				    surface->clip,
				    antialias);

    _cairo_traps_fini (&traps);

    return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_surface_fallback_fill (cairo_surface_t		*surface,
			      cairo_operator_t		 op,
			      const cairo_pattern_t	*source,
			      cairo_path_fixed_t	*path,
			      cairo_fill_rule_t		 fill_rule,
			      double			 tolerance,
			      cairo_antialias_t		 antialias)
{
    cairo_status_t status;
    cairo_traps_t traps;
    cairo_box_t box;
    cairo_rectangle_int_t extents;

    status = _cairo_surface_get_extents (surface, &extents);
    if (unlikely (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;

	if (! _cairo_rectangle_intersect (&extents, &source_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (unlikely (status))
        return status;

    if (extents.width == 0 || extents.height == 0)
	return CAIRO_STATUS_SUCCESS;

    /* Ask if the surface would like to render this combination of
     * op/source/dst/antialias with spans or not, but don't actually
     * make a renderer yet.  We'll try to hit the region optimisations
     * in _clip_and_composite_trapezoids() if it looks like the path
     * is a region. */
    /* TODO: Until we have a mono scan converter we won't even try
     * to use spans for CAIRO_ANTIALIAS_NONE. */
    /* TODO: The region filling code should be lifted from
     * _clip_and_composite_trapezoids() and given first priority
     * explicitly before deciding between spans and trapezoids. */
    if (antialias != CAIRO_ANTIALIAS_NONE &&
	!_cairo_path_fixed_is_box (path, &box) &&
	!_cairo_path_fixed_is_region (path) &&
	_cairo_surface_check_span_renderer (
	    op, source, surface, antialias, NULL))
    {
	cairo_composite_spans_fill_info_t info;
	info.path = path;
	info.fill_rule = fill_rule;
	info.tolerance = tolerance;
	info.antialias = antialias;

	if (_cairo_operator_bounded_by_mask (op)) {
	    cairo_rectangle_int_t path_extents;

	    _cairo_path_fixed_approximate_clip_extents (path,
							&path_extents);
	    if (! _cairo_rectangle_intersect (&extents, &path_extents))
		return CAIRO_STATUS_SUCCESS;
	}

	return _clip_and_composite (
	    surface->clip, op, source,
	    _composite_spans_fill_func,
	    &info,
	    surface,
	    &extents);
    }

    /* Fall back to trapezoid fills. */
    _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 (unlikely (status)) {
	_cairo_traps_fini (&traps);
	return status;
    }

    status = _clip_and_composite_trapezoids (source,
					     op,
					     surface,
					     &traps,
					     surface->clip,
					     antialias);

    _cairo_traps_fini (&traps);

    return status;
}
cairo_status_t
_cairo_surface_fallback_stroke (cairo_surface_t		*surface,
				cairo_operator_t	 op,
				const cairo_pattern_t	*source,
				cairo_path_fixed_t	*path,
				cairo_stroke_style_t	*stroke_style,
				cairo_matrix_t		*ctm,
				cairo_matrix_t		*ctm_inverse,
				double			 tolerance,
				cairo_antialias_t	 antialias)
{
    cairo_status_t status;
    cairo_traps_t traps;
    cairo_box_t box;
    cairo_rectangle_int_t extents;

    status = _cairo_surface_get_extents (surface, &extents);
    if (unlikely (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;

	if (! _cairo_rectangle_intersect (&extents, &source_extents))
	    return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
    if (unlikely (status))
        return status;

    if (extents.width == 0 || extents.height == 0)
	return CAIRO_STATUS_SUCCESS;

    _cairo_box_from_rectangle (&box, &extents);

    _cairo_traps_init (&traps);
    _cairo_traps_limit (&traps, &box);

    status = _cairo_path_fixed_stroke_to_traps (path,
						stroke_style,
						ctm, ctm_inverse,
						tolerance,
						&traps);
    if (unlikely (status))
	goto FAIL;

    status = _clip_and_composite_trapezoids (source,
				             op,
					     surface,
					     &traps,
					     surface->clip,
					     antialias);

FAIL:
    _cairo_traps_fini (&traps);

    return status;
}