Example #1
0
static cairo_status_t
_cairo_xcb_surface_flush (void *abstract_surface,
			  unsigned flags)
{
    cairo_xcb_surface_t *surface = abstract_surface;
    cairo_status_t status;

    if (flags)
	return CAIRO_STATUS_SUCCESS;

    if (likely (surface->fallback == NULL)) {
	status = CAIRO_STATUS_SUCCESS;
	if (! surface->base.finished && surface->deferred_clear)
	    status = _cairo_xcb_surface_clear (surface);

	return status;
    }

    status = surface->base.status;
    if (status == CAIRO_STATUS_SUCCESS &&
	(! surface->base._finishing || ! surface->owns_pixmap)) {
	status = cairo_surface_status (&surface->fallback->base);

	if (status == CAIRO_STATUS_SUCCESS)
		status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
								  CAIRO_FILL_RULE_WINDING,
								  &surface->fallback_damage);

	if (status == CAIRO_STATUS_SUCCESS)
	    status = _put_image_boxes (surface,
				       surface->fallback,
				       &surface->fallback_damage);

	if (status == CAIRO_STATUS_SUCCESS && ! surface->base._finishing) {
	    _cairo_surface_attach_snapshot (&surface->base,
					    &surface->fallback->base,
					    cairo_surface_finish);
	}
    }

    _cairo_boxes_clear (&surface->fallback_damage);
    cairo_surface_destroy (&surface->fallback->base);
    surface->fallback = NULL;

    return status;
}
Example #2
0
cairo_status_t
_cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
					     cairo_fill_rule_t fill_rule,
					     cairo_antialias_t antialias,
					     cairo_boxes_t *boxes)
{
    cairo_path_fixed_iter_t iter;
    cairo_status_t status;
    cairo_box_t box;

    if (_cairo_path_fixed_is_box (path, &box))
	return _cairo_boxes_add (boxes, antialias, &box);

    _cairo_path_fixed_iter_init (&iter, path);
    while (_cairo_path_fixed_iter_is_fill_box (&iter, &box)) {
	if (box.p1.y == box.p2.y || box.p1.x == box.p2.x)
	    continue;

	if (box.p1.y > box.p2.y) {
	    cairo_fixed_t t;

	    t = box.p1.y;
	    box.p1.y = box.p2.y;
	    box.p2.y = t;

	    t = box.p1.x;
	    box.p1.x = box.p2.x;
	    box.p2.x = t;
	}

	status = _cairo_boxes_add (boxes, antialias, &box);
	if (unlikely (status))
	    return status;
    }

    if (_cairo_path_fixed_iter_at_end (&iter))
	return _cairo_bentley_ottmann_tessellate_boxes (boxes, fill_rule, boxes);

    /* path is not rectangular, try extracting clipped rectilinear edges */
    _cairo_boxes_clear (boxes);
    return _cairo_path_fixed_fill_rectilinear_tessellate_to_boxes (path,
								   fill_rule,
								   antialias,
								   boxes);
}
Example #3
0
cairo_int_status_t
_cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t	*path,
					       const cairo_stroke_style_t	*stroke_style,
					       const cairo_matrix_t	*ctm,
					       cairo_antialias_t	 antialias,
					       cairo_boxes_t		*boxes)
{
    cairo_rectilinear_stroker_t rectilinear_stroker;
    cairo_int_status_t status;
    cairo_box_t box;

    assert (_cairo_path_fixed_stroke_is_rectilinear (path));

    if (! _cairo_rectilinear_stroker_init (&rectilinear_stroker,
					   stroke_style, ctm, antialias,
					   boxes))
    {
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    if (! rectilinear_stroker.dash.dashed &&
	_cairo_path_fixed_is_stroke_box (path, &box) &&
	/* if the segments overlap we need to feed them into the tessellator */
	box.p2.x - box.p1.x > 2* rectilinear_stroker.half_line_x &&
	box.p2.y - box.p1.y > 2* rectilinear_stroker.half_line_y)
    {
	cairo_box_t b;

	/* top */
	b.p1.x = box.p1.x - rectilinear_stroker.half_line_x;
	b.p2.x = box.p2.x + rectilinear_stroker.half_line_x;
	b.p1.y = box.p1.y - rectilinear_stroker.half_line_y;
	b.p2.y = box.p1.y + rectilinear_stroker.half_line_y;
	status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b);
	assert (status == CAIRO_INT_STATUS_SUCCESS);

	/* left  (excluding top/bottom) */
	b.p1.x = box.p1.x - rectilinear_stroker.half_line_x;
	b.p2.x = box.p1.x + rectilinear_stroker.half_line_x;
	b.p1.y = box.p1.y + rectilinear_stroker.half_line_y;
	b.p2.y = box.p2.y - rectilinear_stroker.half_line_y;
	status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b);
	assert (status == CAIRO_INT_STATUS_SUCCESS);

	/* right  (excluding top/bottom) */
	b.p1.x = box.p2.x - rectilinear_stroker.half_line_x;
	b.p2.x = box.p2.x + rectilinear_stroker.half_line_x;
	b.p1.y = box.p1.y + rectilinear_stroker.half_line_y;
	b.p2.y = box.p2.y - rectilinear_stroker.half_line_y;
	status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b);
	assert (status == CAIRO_INT_STATUS_SUCCESS);

	/* bottom */
	b.p1.x = box.p1.x - rectilinear_stroker.half_line_x;
	b.p2.x = box.p2.x + rectilinear_stroker.half_line_x;
	b.p1.y = box.p2.y - rectilinear_stroker.half_line_y;
	b.p2.y = box.p2.y + rectilinear_stroker.half_line_y;
	status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b);
	assert (status == CAIRO_INT_STATUS_SUCCESS);

	goto done;
    }

    if (boxes->num_limits) {
	_cairo_rectilinear_stroker_limit (&rectilinear_stroker,
					  boxes->limits,
					  boxes->num_limits);
    }

    status = (cairo_int_status_t)_cairo_path_fixed_interpret (path,
					  _cairo_rectilinear_stroker_move_to,
					  rectilinear_stroker.dash.dashed ?
					  _cairo_rectilinear_stroker_line_to_dashed :
					  _cairo_rectilinear_stroker_line_to,
					  NULL,
					  _cairo_rectilinear_stroker_close_path,
					  &rectilinear_stroker);
    if (unlikely (status))
	goto BAIL;

    if (rectilinear_stroker.dash.dashed)
	status = (cairo_int_status_t)_cairo_rectilinear_stroker_emit_segments_dashed (&rectilinear_stroker);
    else
	status = (cairo_int_status_t)_cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
    if (unlikely (status))
	goto BAIL;

    /* As we incrementally tessellate, we do not eliminate self-intersections */
    status = (cairo_int_status_t)_cairo_bentley_ottmann_tessellate_boxes (boxes,
						      CAIRO_FILL_RULE_WINDING,
						      boxes);
    if (unlikely (status))
	goto BAIL;

done:
    _cairo_rectilinear_stroker_fini (&rectilinear_stroker);
    return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;

BAIL:
    _cairo_rectilinear_stroker_fini (&rectilinear_stroker);
    _cairo_boxes_clear (boxes);
    return status;
}
static cairo_int_status_t
fixup_unbounded_boxes (const cairo_spans_compositor_t *compositor,
		       const cairo_composite_rectangles_t *extents,
		       cairo_boxes_t *boxes)
{
    cairo_boxes_t tmp, clear;
    cairo_box_t box;
    cairo_int_status_t status;

    assert (boxes->is_pixel_aligned);

    TRACE ((stderr, "%s\n", __FUNCTION__));
    if (extents->bounded.width  == extents->unbounded.width &&
	extents->bounded.height == extents->unbounded.height)
    {
	return CAIRO_STATUS_SUCCESS;
    }

    /* subtract the drawn boxes from the unbounded area */
    _cairo_boxes_init (&clear);

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

    if (boxes->num_boxes) {
	_cairo_boxes_init (&tmp);

	status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
	assert (status == CAIRO_INT_STATUS_SUCCESS);

	tmp.chunks.next = &boxes->chunks;
	tmp.num_boxes += boxes->num_boxes;

	status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
							  CAIRO_FILL_RULE_WINDING,
							  &clear);
	tmp.chunks.next = NULL;
	if (unlikely (status))
	    goto error;
    } else {
	box.p1.x = _cairo_fixed_from_int (extents->unbounded.x);
	box.p2.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);

	status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
	assert (status == CAIRO_INT_STATUS_SUCCESS);
    }

    /* If we have a clip polygon, we need to intersect with that as well */
    if (extents->clip->path) {
	status = fixup_unbounded_polygon (compositor, extents, &clear);
	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
	    status = fixup_unbounded_mask (compositor, extents, &clear);
    } else {
	/* Otherwise just intersect with the clip boxes */
	if (extents->clip->num_boxes) {
	    _cairo_boxes_init_for_array (&tmp,
					 extents->clip->boxes,
					 extents->clip->num_boxes);
	    status = _cairo_boxes_intersect (&clear, &tmp, &clear);
	    if (unlikely (status))
		goto error;
	}

	if (clear.is_pixel_aligned) {
	    status = compositor->fill_boxes (extents->surface,
					     CAIRO_OPERATOR_CLEAR,
					     CAIRO_COLOR_TRANSPARENT,
					     &clear);
	} else {
	    cairo_composite_rectangles_t composite;

	    status = _cairo_composite_rectangles_init_for_boxes (&composite,
								 extents->surface,
								 CAIRO_OPERATOR_CLEAR,
								 &_cairo_pattern_clear.base,
								 &clear,
								 NULL);
	    if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
		status = composite_boxes (compositor, &composite, &clear);
		_cairo_composite_rectangles_fini (&composite);
	    }
	}
    }

error:
    _cairo_boxes_fini (&clear);
    return status;
}