static cairo_int_status_t
composite_polygon (const cairo_spans_compositor_t	*compositor,
		   cairo_composite_rectangles_t		 *extents,
		   cairo_polygon_t			*polygon,
		   cairo_fill_rule_t			 fill_rule,
		   cairo_antialias_t			 antialias)
{
    cairo_abstract_span_renderer_t renderer;
    cairo_scan_converter_t *converter;
    cairo_bool_t needs_clip;
    cairo_int_status_t status;

    needs_clip = composite_needs_clip (extents, &polygon->extents);
    if (needs_clip) {
	return CAIRO_INT_STATUS_UNSUPPORTED;
	converter = _cairo_clip_tor_scan_converter_create (extents->clip,
							   polygon,
							   fill_rule, antialias);
    } else {
	const cairo_rectangle_int_t *r = &extents->bounded;

	if (antialias == CAIRO_ANTIALIAS_FAST) {
	    converter = _cairo_tor22_scan_converter_create (r->x, r->y,
							    r->x + r->width,
							    r->y + r->height,
							    fill_rule, antialias);
	    status = _cairo_tor22_scan_converter_add_polygon (converter, polygon);
	} else if (antialias == CAIRO_ANTIALIAS_NONE) {
	    converter = _cairo_mono_scan_converter_create (r->x, r->y,
							   r->x + r->width,
							   r->y + r->height,
							   fill_rule);
	    status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
	} else {
	    converter = _cairo_tor_scan_converter_create (r->x, r->y,
							  r->x + r->width,
							  r->y + r->height,
							  fill_rule, antialias);
	    status = _cairo_tor_scan_converter_add_polygon (converter, polygon);
	}
    }
    if (unlikely (status))
	goto cleanup_converter;

    status = compositor->renderer_init (&renderer, extents, needs_clip);
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	status = converter->generate (converter, &renderer.base);
    compositor->renderer_fini (&renderer, status);

cleanup_converter:
    converter->destroy (converter);
    return status;
}
static cairo_int_status_t
composite_boxes (const cairo_spans_compositor_t *compositor,
		 cairo_composite_rectangles_t *extents,
		 cairo_boxes_t		*boxes)
{
    cairo_abstract_span_renderer_t renderer;
    cairo_rectangular_scan_converter_t converter;
    const struct _cairo_boxes_chunk *chunk;
    cairo_int_status_t status;
    cairo_box_t box;

    TRACE ((stderr, "%s\n", __FUNCTION__));
    _cairo_box_from_rectangle (&box, &extents->unbounded);
    if (composite_needs_clip (extents, &box)) {
	TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    _cairo_rectangular_scan_converter_init (&converter, &extents->unbounded);
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
	const cairo_box_t *box = chunk->base;
	int i;

	for (i = 0; i < chunk->count; i++) {
	    status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
	    if (unlikely (status))
		goto cleanup_converter;
	}
    }

    status = compositor->renderer_init (&renderer, extents,
					CAIRO_ANTIALIAS_DEFAULT, FALSE);
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	status = converter.base.generate (&converter.base, &renderer.base);
    compositor->renderer_fini (&renderer, status);

cleanup_converter:
    converter.base.destroy (&converter.base);
    return status;
}