static cairo_int_status_t
_cairo_win32_gdi_compositor_fill (const cairo_compositor_t	*compositor,
				  cairo_composite_rectangles_t	*composite,
				  const cairo_path_fixed_t	*path,
				  cairo_fill_rule_t		 fill_rule,
				  double			 tolerance,
				  cairo_antialias_t		 antialias)
{
    cairo_int_status_t status;

    status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (check_blit (composite) &&
	_cairo_path_fixed_fill_is_rectilinear (path)) {
	cairo_boxes_t boxes;

	TRACE ((stderr, "%s\n", __FUNCTION__));
	_cairo_boxes_init_with_clip (&boxes, composite->clip);
	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
							      fill_rule,
							      antialias,
							      &boxes);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	    status = draw_boxes (composite, &boxes);
	_cairo_boxes_fini (&boxes);
    }

    return status;
}
Beispiel #2
0
static cairo_status_t
_cairo_xcb_surface_finish (void *abstract_surface)
{
    cairo_xcb_surface_t *surface = abstract_surface;
    cairo_status_t status;

    if (surface->fallback != NULL) {
	cairo_surface_finish (&surface->fallback->base);
	cairo_surface_destroy (&surface->fallback->base);
    }
    _cairo_boxes_fini (&surface->fallback_damage);

    cairo_list_del (&surface->link);

    status = _cairo_xcb_connection_acquire (surface->connection);
    if (status == CAIRO_STATUS_SUCCESS) {
	if (surface->picture != XCB_NONE) {
	    _cairo_xcb_connection_render_free_picture (surface->connection,
						       surface->picture);
	}

	if (surface->owns_pixmap)
	    _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
	_cairo_xcb_connection_release (surface->connection);
    }

    _cairo_xcb_connection_destroy (surface->connection);

    return status;
}
static cairo_int_status_t
_cairo_spans_compositor_stroke (const cairo_compositor_t	*_compositor,
				cairo_composite_rectangles_t	 *extents,
				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_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
    cairo_int_status_t status;

    status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
	cairo_boxes_t boxes;

	_cairo_boxes_init (&boxes);
	if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
	    _cairo_boxes_limit (&boxes,
				extents->clip->boxes,
				extents->clip->num_boxes);

	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
								style,
								ctm,
								antialias,
								&boxes);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	    status = clip_and_composite_boxes (compositor, extents, &boxes);
	_cairo_boxes_fini (&boxes);
    }

    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	cairo_polygon_t polygon;

	if (extents->mask.width  > extents->unbounded.width ||
	    extents->mask.height > extents->unbounded.height)
	{
	    _cairo_polygon_init_with_clip (&polygon, extents->clip);
	}
	else
	{
	    _cairo_polygon_init_with_clip (&polygon, NULL);
	}
	status = _cairo_path_fixed_stroke_to_polygon (path,
						      style,
						      ctm, ctm_inverse,
						      tolerance,
						      &polygon);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
	    status = clip_and_composite_polygon (compositor, extents, &polygon,
						 CAIRO_FILL_RULE_WINDING,
						 antialias);
	}
	_cairo_polygon_fini (&polygon);
    }

    return status;
}
cairo_clip_t *
_cairo_clip_intersect_rectilinear_path (cairo_clip_t *clip,
					const cairo_path_fixed_t *path,
					cairo_fill_rule_t fill_rule,
					cairo_antialias_t antialias)
{
    cairo_status_t status;
    cairo_boxes_t boxes;

    _cairo_boxes_init (&boxes);
    status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
							  fill_rule,
							  antialias,
							  &boxes);
    if (likely (status == CAIRO_STATUS_SUCCESS && boxes.num_boxes))
	clip = _cairo_clip_intersect_boxes (clip, &boxes);
    else
	clip = _cairo_clip_set_all_clipped (clip);
    _cairo_boxes_fini (&boxes);

    return clip;
}
cairo_clip_t *
_cairo_clip_intersect_boxes (cairo_clip_t *clip,
			     const cairo_boxes_t *boxes)
{
    cairo_boxes_t clip_boxes;
    cairo_box_t limits;
    cairo_rectangle_int_t extents;

    if (_cairo_clip_is_all_clipped (clip))
	return clip;

    if (boxes->num_boxes == 0)
	return _cairo_clip_set_all_clipped (clip);

    if (boxes->num_boxes == 1)
	return _cairo_clip_intersect_box (clip, boxes->chunks.base);

    if (clip == NULL)
	clip = _cairo_clip_create ();

    if (clip->num_boxes) {
	_cairo_boxes_init_for_array (&clip_boxes, clip->boxes, clip->num_boxes);
	if (unlikely (_cairo_boxes_intersect (&clip_boxes, boxes, &clip_boxes))) {
	    clip = _cairo_clip_set_all_clipped (clip);
	    goto out;
	}

	if (clip->boxes != &clip->embedded_box)
	    free (clip->boxes);

	clip->boxes = NULL;
	boxes = &clip_boxes;
    }

    if (boxes->num_boxes == 0) {
	clip = _cairo_clip_set_all_clipped (clip);
	goto out;
    } else if (boxes->num_boxes == 1) {
	clip->boxes = &clip->embedded_box;
	clip->boxes[0] = boxes->chunks.base[0];
	clip->num_boxes = 1;
    } else {
	clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
    }
    _cairo_boxes_extents (boxes, &limits);

    _cairo_box_round_to_rectangle (&limits, &extents);
    if (clip->path == NULL)
	clip->extents = extents;
    else if (! _cairo_rectangle_intersect (&clip->extents, &extents))
	clip = _cairo_clip_set_all_clipped (clip);

    if (clip->region) {
	cairo_region_destroy (clip->region);
	clip->region = NULL;
    }
    clip->is_region = FALSE;

out:
    if (boxes == &clip_boxes)
	_cairo_boxes_fini (&clip_boxes);

    return clip;
}
static cairo_int_status_t
_cairo_spans_compositor_stroke (const cairo_compositor_t	*_compositor,
				cairo_composite_rectangles_t	 *extents,
				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_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
    cairo_int_status_t status;

    TRACE_ (_cairo_debug_print_path (stderr, path));

    status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
	cairo_boxes_t boxes;

	_cairo_boxes_init (&boxes);
	if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
	    _cairo_boxes_limit (&boxes,
				extents->clip->boxes,
				extents->clip->num_boxes);

	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
								style,
								ctm,
								antialias,
								&boxes);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	    status = clip_and_composite_boxes (compositor, extents, &boxes);
	_cairo_boxes_fini (&boxes);
    }

    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	cairo_polygon_t polygon;
	cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING;

	if (extents->mask.width  > extents->unbounded.width ||
	    extents->mask.height > extents->unbounded.height)
	{
	    cairo_box_t limits;
	    _cairo_box_from_rectangle (&limits, &extents->unbounded);
	    _cairo_polygon_init (&polygon, &limits, 1);
	}
	else
	{
	    _cairo_polygon_init (&polygon, NULL, 0);
	}
	status = _cairo_path_fixed_stroke_to_polygon (path,
						      style,
						      ctm, ctm_inverse,
						      tolerance,
						      &polygon);
	TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
	if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) {
	    status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
							  extents->clip->boxes,
							  extents->clip->num_boxes);
	}
	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
	    cairo_clip_t *saved_clip = extents->clip;

	    if (extents->is_bounded) {
		extents->clip = _cairo_clip_copy_path (extents->clip);
		extents->clip = _cairo_clip_intersect_box(extents->clip,
							  &polygon.extents);
	    }

	    status = clip_and_composite_polygon (compositor, extents, &polygon,
						 fill_rule, antialias);

	    if (extents->is_bounded) {
		_cairo_clip_destroy (extents->clip);
		extents->clip = saved_clip;
	    }
	}
	_cairo_polygon_fini (&polygon);
    }

    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;
}
static cairo_int_status_t
_cairo_spans_compositor_fill (const cairo_compositor_t		*_compositor,
			      cairo_composite_rectangles_t	 *extents,
			      const cairo_path_fixed_t		*path,
			      cairo_fill_rule_t			 fill_rule,
			      double				 tolerance,
			      cairo_antialias_t			 antialias)
{
    const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
    cairo_int_status_t status;

    TRACE((stderr, "%s op=%d, antialias=%d\n", __FUNCTION__, extents->op, antialias));

    status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
	cairo_boxes_t boxes;

	TRACE((stderr, "%s - rectilinear\n", __FUNCTION__));

	_cairo_boxes_init (&boxes);
	if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
	    _cairo_boxes_limit (&boxes,
				extents->clip->boxes,
				extents->clip->num_boxes);
	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
							      fill_rule,
							      antialias,
							      &boxes);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	    status = clip_and_composite_boxes (compositor, extents, &boxes);
	_cairo_boxes_fini (&boxes);
    }
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	cairo_polygon_t polygon;

	TRACE((stderr, "%s - polygon\n", __FUNCTION__));

	if (extents->mask.width  > extents->unbounded.width ||
	    extents->mask.height > extents->unbounded.height)
	{
	    cairo_box_t limits;
	    TRACE((stderr, "%s - clipping to bounds\n", __FUNCTION__));
	    _cairo_box_from_rectangle (&limits, &extents->unbounded);
	    _cairo_polygon_init (&polygon, &limits, 1);
	}
	else
	{
	    _cairo_polygon_init (&polygon, NULL, 0);
	}

	status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
	if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) {
	    TRACE((stderr, "%s - polygon intersect with %d clip boxes\n",
		   __FUNCTION__, extents->clip->num_boxes));
	    status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
							  extents->clip->boxes,
							  extents->clip->num_boxes);
	}
	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
	    cairo_clip_t *saved_clip = extents->clip;

	    if (extents->is_bounded) {
		TRACE((stderr, "%s - polygon discard clip boxes\n",
		       __FUNCTION__));
		extents->clip = _cairo_clip_copy_path (extents->clip);
		extents->clip = _cairo_clip_intersect_box(extents->clip,
							  &polygon.extents);
	    }

	    status = clip_and_composite_polygon (compositor, extents, &polygon,
						 fill_rule, antialias);

	    if (extents->is_bounded) {
		_cairo_clip_destroy (extents->clip);
		extents->clip = saved_clip;
	    }
	}
	_cairo_polygon_fini (&polygon);

	TRACE((stderr, "%s - polygon status=%d\n", __FUNCTION__, status));
    }

    return status;
}
static cairo_int_status_t
_cairo_spans_compositor_fill (const cairo_compositor_t		*_compositor,
			      cairo_composite_rectangles_t	 *extents,
			      const cairo_path_fixed_t		*path,
			      cairo_fill_rule_t			 fill_rule,
			      double				 tolerance,
			      cairo_antialias_t			 antialias)
{
    const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
    cairo_int_status_t status;

    status = CAIRO_INT_STATUS_UNSUPPORTED;
    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
	cairo_boxes_t boxes;

	_cairo_boxes_init (&boxes);
	if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
	    _cairo_boxes_limit (&boxes,
				extents->clip->boxes,
				extents->clip->num_boxes);
	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
							      fill_rule,
							      antialias,
							      &boxes);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
	    status = clip_and_composite_boxes (compositor, extents, &boxes);
	_cairo_boxes_fini (&boxes);
    }
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	cairo_polygon_t polygon;

	if (extents->mask.width  > extents->unbounded.width ||
	    extents->mask.height > extents->unbounded.height)
	{
	    cairo_box_t limits;
	    _cairo_box_from_rectangle (&limits, &extents->unbounded);
	    _cairo_polygon_init (&polygon, &limits, 1);
	}
	else
	{
	    _cairo_polygon_init (&polygon, NULL, 0);
	}

	status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
	    status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
							  extents->clip->boxes,
							  extents->clip->num_boxes);
	}
	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
	    if (extents->is_bounded) {
		if (extents->clip->boxes != &extents->clip->embedded_box)
		    free (extents->clip->boxes);

		extents->clip->num_boxes = 1;
		extents->clip->boxes = &extents->clip->embedded_box;
		extents->clip->boxes[0] = polygon.extents;
	    }
	    status = clip_and_composite_polygon (compositor, extents, &polygon,
						 fill_rule, antialias);
	}
	_cairo_polygon_fini (&polygon);
    }

    return status;
}