Ejemplo n.º 1
0
cairo_status_t
_cairo_clip_rectangle (cairo_clip_t       *clip,
		       const cairo_rectangle_int_t *rectangle)
{
    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    if (rectangle->width == 0 || rectangle->height == 0) {
	_cairo_clip_set_all_clipped (clip);
	return CAIRO_STATUS_SUCCESS;
    }

    /* if a smaller clip has already been set, ignore the new path */
    if (clip->path != NULL) {
	if (rectangle->x <= clip->path->extents.x &&
	    rectangle->y <= clip->path->extents.y &&
	    rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
	    rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
	{
	    return CAIRO_STATUS_SUCCESS;
	}
    }

    return _cairo_clip_intersect_rectangle (clip, rectangle);
}
Ejemplo n.º 2
0
cairo_int_status_t
_cairo_clip_get_region (cairo_clip_t *clip,
			cairo_region_t **region)
{
    cairo_int_status_t status;

    if (clip->all_clipped)
	goto CLIPPED;

    assert (clip->path != NULL);

    status = _cairo_clip_path_to_region (clip->path);
    if (status)
	return status;

    if (cairo_region_is_empty (clip->path->region)) {
	_cairo_clip_set_all_clipped (clip);
	goto CLIPPED;
    }

    if (region)
	*region = clip->path->region;
    return CAIRO_STATUS_SUCCESS;

  CLIPPED:
    if (region)
	*region = NULL;
    return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
Ejemplo n.º 3
0
cairo_clip_t *
_cairo_clip_intersect_box (cairo_clip_t *clip,
			   const cairo_box_t *box)
{
    cairo_rectangle_int_t r;

    _cairo_box_round_to_rectangle (box, &r);
    if (r.width == 0 || r.height == 0)
	return _cairo_clip_set_all_clipped (clip);

    return _cairo_clip_intersect_rectangle_box (clip, &r, box);
}
Ejemplo n.º 4
0
cairo_status_t
_cairo_clip_init_copy_transformed (cairo_clip_t    *clip,
				   cairo_clip_t    *other,
				   const cairo_matrix_t *matrix)
{
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
    int tx, ty;

    if (other == NULL) {
	_cairo_clip_init (clip);
	return CAIRO_STATUS_SUCCESS;
    }

    if (other->all_clipped) {
	_cairo_clip_init (clip);
	clip->all_clipped = TRUE;
	return CAIRO_STATUS_SUCCESS;
    }

    if (_cairo_matrix_is_identity (matrix)) {
	_cairo_clip_init_copy (clip, other);
	return CAIRO_STATUS_SUCCESS;
    }

    if (other->path != NULL) {
	_cairo_clip_init (clip);

	/* if we only need to translate, so we can reuse the caches... */
	/* XXX we still loose the benefit of constructs when the copy is
	 * deleted though. Indirect clip_paths?
	 */
	if (_cairo_matrix_is_integer_translation (matrix, &tx, &ty)) {
	    status = _cairo_clip_path_reapply_clip_path_translate (clip,
								   other->path,
								   tx, ty);
	} else {
	    status = _cairo_clip_path_reapply_clip_path_transform (clip,
								   other->path,
								   matrix);
	    if (clip->path->extents.width == 0 &&
		clip->path->extents.height == 0)
	    {
		_cairo_clip_set_all_clipped (clip);
	    }
	}
    }

    return status;
}
Ejemplo n.º 5
0
cairo_clip_t *
_cairo_clip_from_boxes (const cairo_boxes_t *boxes)
{
    cairo_box_t extents;
    cairo_clip_t *clip = _cairo_clip_create ();
    if (clip == NULL)
	return _cairo_clip_set_all_clipped (clip);

    /* XXX cow-boxes? */
    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);
	if (clip->boxes == NULL)
	    return _cairo_clip_set_all_clipped (clip);
    }

    _cairo_boxes_extents (boxes, &extents);
    _cairo_box_round_to_rectangle (&extents, &clip->extents);

    return clip;
}
Ejemplo n.º 6
0
cairo_status_t
_cairo_clip_clip (cairo_clip_t       *clip,
		  cairo_path_fixed_t *path,
		  cairo_fill_rule_t   fill_rule,
		  double              tolerance,
		  cairo_antialias_t   antialias,
		  cairo_surface_t    *target)
{
    cairo_status_t status;
    cairo_traps_t traps;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    /* catch the empty clip path */
    if (! path->has_current_point) {
	_cairo_clip_set_all_clipped (clip, target);
	return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_path (clip,
					 path, fill_rule, tolerance,
					 antialias);
    if (status == CAIRO_STATUS_SUCCESS)
        clip->serial = _cairo_surface_allocate_clip_serial (target);

    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    _cairo_traps_init (&traps);
    status = _cairo_path_fixed_fill_to_traps (path,
					      fill_rule,
					      tolerance,
					      &traps);
    if (status)
	goto bail;

    status = _cairo_clip_intersect_region (clip, &traps, target);
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	goto bail;

    status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);

 bail:
    _cairo_traps_fini (&traps);

    return status;
}
Ejemplo n.º 7
0
/* XXX consider accepting a matrix, no users yet. */
cairo_status_t
_cairo_clip_init_rectangle (cairo_clip_t *clip,
			    const cairo_rectangle_int_t *rect)
{
    _cairo_clip_init (clip);

    if (rect == NULL)
	return CAIRO_STATUS_SUCCESS;

    if (rect->width == 0 || rect->height == 0) {
	_cairo_clip_set_all_clipped (clip);
	return CAIRO_STATUS_SUCCESS;
    }

    return _cairo_clip_intersect_rectangle (clip, rect);
}
Ejemplo n.º 8
0
static cairo_int_status_t
_cairo_clip_intersect_region (cairo_clip_t    *clip,
			      cairo_traps_t   *traps,
			      cairo_surface_t *target)
{
    cairo_region_t region;
    cairo_int_status_t status;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    if (clip->mode != CAIRO_CLIP_MODE_REGION)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    status = _cairo_traps_extract_region (traps, &region);

    if (status)
	return status;

    status = CAIRO_STATUS_SUCCESS;

    if (!clip->has_region) {
        status = _cairo_region_copy (&clip->region, &region);
	if (status == CAIRO_STATUS_SUCCESS)
	    clip->has_region = TRUE;
    } else {
	cairo_region_t intersection;
        _cairo_region_init (&intersection);

	status = _cairo_region_intersect (&intersection,
		                         &clip->region,
		                         &region);

	if (status == CAIRO_STATUS_SUCCESS)
	    status = _cairo_region_copy (&clip->region, &intersection);

        _cairo_region_fini (&intersection);
    }

    clip->serial = _cairo_surface_allocate_clip_serial (target);
    _cairo_region_fini (&region);

    if (! _cairo_region_not_empty (&clip->region))
	_cairo_clip_set_all_clipped (clip, target);

    return status;
}
Ejemplo n.º 9
0
cairo_clip_t *
_cairo_clip_intersect_rectangle (cairo_clip_t       *clip,
				 const cairo_rectangle_int_t *r)
{
    cairo_box_t box;

    if (_cairo_clip_is_all_clipped (clip))
	return clip;

    if (r->width == 0 || r->height == 0)
	return _cairo_clip_set_all_clipped (clip);

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

    return _cairo_clip_intersect_rectangle_box (clip, r, &box);
}
Ejemplo n.º 10
0
cairo_status_t
_cairo_clip_apply_clip (cairo_clip_t *clip,
			const cairo_clip_t *other)
{
    cairo_status_t status;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    if (other->all_clipped) {
	_cairo_clip_set_all_clipped (clip);
	return CAIRO_STATUS_SUCCESS;
    }

    status = CAIRO_STATUS_SUCCESS;
    if (other->path != NULL)
	status = _cairo_clip_apply_clip_path (clip, other->path);

    return status;
}
Ejemplo n.º 11
0
cairo_status_t
_cairo_clip_clip (cairo_clip_t       *clip,
		  const cairo_path_fixed_t *path,
		  cairo_fill_rule_t   fill_rule,
		  double              tolerance,
		  cairo_antialias_t   antialias)
{
    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    /* catch the empty clip path */
    if (_cairo_path_fixed_fill_is_empty (path)) {
	_cairo_clip_set_all_clipped (clip);
	return CAIRO_STATUS_SUCCESS;
    }

    return _cairo_clip_intersect_path (clip,
				       path, fill_rule, tolerance,
				       antialias);
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
cairo_int_status_t
_cairo_clip_get_boxes (cairo_clip_t *clip,
		       cairo_box_t **boxes,
		       int *count)
{
    cairo_int_status_t status;

    if (clip->all_clipped)
	return CAIRO_INT_STATUS_NOTHING_TO_DO;

    assert (clip->path != NULL);

    status = _cairo_clip_path_to_boxes (clip->path, boxes, count);
    if (status)
	return status;

    if (*count == 0) {
	_cairo_clip_set_all_clipped (clip);
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    }

    return CAIRO_STATUS_SUCCESS;
}
Ejemplo n.º 14
0
static cairo_clip_t *
_cairo_clip_intersect_rectangle_box (cairo_clip_t *clip,
				     const cairo_rectangle_int_t *r,
				     const cairo_box_t *box)
{
    cairo_box_t extents_box;
    cairo_bool_t changed = FALSE;
    int i, j;

    if (clip == NULL) {
	clip = _cairo_clip_create ();
	if (clip == NULL)
	    return _cairo_clip_set_all_clipped (clip);
    }

    if (clip->num_boxes == 0) {
	clip->boxes = &clip->embedded_box;
	clip->boxes[0] = *box;
	clip->num_boxes = 1;
	if (clip->path == NULL) {
	    clip->extents = *r;
	} else {
	    if (! _cairo_rectangle_intersect (&clip->extents, r))
		clip = _cairo_clip_set_all_clipped (clip);
	}
	if (clip->path == NULL)
	    clip->is_region = _cairo_box_is_pixel_aligned (box);
	return clip;
    }

    /* Does the new box wholly subsume the clip? Perform a cheap check
     * for the common condition of a single clip rectangle.
     */
    if (clip->num_boxes == 1 &&
	clip->boxes[0].p1.x >= box->p1.x &&
	clip->boxes[0].p1.y >= box->p1.y &&
	clip->boxes[0].p2.x <= box->p2.x &&
	clip->boxes[0].p2.y <= box->p2.y)
    {
	return clip;
    }

    for (i = j = 0; i < clip->num_boxes; i++) {
	cairo_box_t *b = &clip->boxes[j];

	if (j != i)
	    *b = clip->boxes[i];

	if (box->p1.x > b->p1.x)
	    b->p1.x = box->p1.x, changed = TRUE;
	if (box->p2.x < b->p2.x)
	    b->p2.x = box->p2.x, changed = TRUE;

	if (box->p1.y > b->p1.y)
	    b->p1.y = box->p1.y, changed = TRUE;
	if (box->p2.y < b->p2.y)
	    b->p2.y = box->p2.y, changed = TRUE;

	j += b->p2.x > b->p1.x && b->p2.y > b->p1.y;
    }
    clip->num_boxes = j;

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

    if (! changed)
	return clip;

    extents_box = clip->boxes[0];
    for (i = 1; i < clip->num_boxes; i++) {
	    if (clip->boxes[i].p1.x < extents_box.p1.x)
		extents_box.p1.x = clip->boxes[i].p1.x;

	    if (clip->boxes[i].p1.y < extents_box.p1.y)
		extents_box.p1.y = clip->boxes[i].p1.y;

	    if (clip->boxes[i].p2.x > extents_box.p2.x)
		extents_box.p2.x = clip->boxes[i].p2.x;

	    if (clip->boxes[i].p2.y > extents_box.p2.y)
		extents_box.p2.y = clip->boxes[i].p2.y;
    }

    if (clip->path == NULL) {
	_cairo_box_round_to_rectangle (&extents_box, &clip->extents);
    } else {
	cairo_rectangle_int_t extents_rect;

	_cairo_box_round_to_rectangle (&extents_box, &extents_rect);
	if (! _cairo_rectangle_intersect (&clip->extents, &extents_rect))
	    return _cairo_clip_set_all_clipped (clip);
    }

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

    clip->is_region = FALSE;
    return clip;
}
Ejemplo n.º 15
0
static cairo_status_t
_cairo_clip_intersect_mask (cairo_clip_t      *clip,
			    cairo_traps_t     *traps,
			    cairo_antialias_t antialias,
			    cairo_surface_t   *target)
{
    cairo_pattern_union_t pattern;
    cairo_box_t extents;
    cairo_rectangle_int_t surface_rect, target_rect;
    cairo_surface_t *surface;
    cairo_status_t status;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    /* Represent the clip as a mask surface.  We create a new surface
     * the size of the intersection of the old mask surface and the
     * extents of the new clip path. */

    _cairo_traps_extents (traps, &extents);
    _cairo_box_round_to_rectangle (&extents, &surface_rect);

    if (clip->surface != NULL)
	_cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);

    /* Intersect with the target surface rectangle so we don't use
     * more memory and time than we need to. */

    status = _cairo_surface_get_extents (target, &target_rect);
    if (!status)
	_cairo_rectangle_intersect (&surface_rect, &target_rect);

    if (surface_rect.width == 0 || surface_rect.height == 0) {
	surface = NULL;
	status = CAIRO_STATUS_SUCCESS;
	if (clip->surface != NULL)
	    cairo_surface_destroy (clip->surface);
	goto DONE;
    }

    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);
    /* The clipping operation should ideally be something like the following to
     * avoid having to do as many passes over the data

	if (clip->surface != NULL) {
	    _cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
	} else {
	    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);
	}
	status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
						  &pattern.base,
						  surface,
						  antialias,
						  0, 0,
						  0, 0,
						  surface_rect.width,
						  surface_rect.height,
						  traps->traps,
						  traps->num_traps);

	However this operation is not accelerated by pixman

	I believe the best possible operation would probably an unbounded SRC
	operator.  Using SRC we could potentially avoid having to initialize
	the surface which would be ideal from an efficiency point of view.
	However, _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) is
	bounded by the mask.

    */

    surface = _cairo_surface_create_similar_solid (target,
						   CAIRO_CONTENT_ALPHA,
						   surface_rect.width,
						   surface_rect.height,
						   CAIRO_COLOR_TRANSPARENT,
						   &pattern.base);
    if (surface->status) {
	_cairo_pattern_fini (&pattern.base);
	return surface->status;
    }

    /* Render the new clipping path into the new mask surface. */

    _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);

    status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
						  &pattern.base,
						  surface,
						  antialias,
						  0, 0,
						  0, 0,
						  surface_rect.width,
						  surface_rect.height,
						  traps->traps,
						  traps->num_traps);

    _cairo_pattern_fini (&pattern.base);

    if (status) {
	cairo_surface_destroy (surface);
	return status;
    }

    /* If there was a clip surface already, combine it with the new
     * mask surface using the IN operator, so we get the intersection
     * of the old and new clipping paths. */

    if (clip->surface != NULL) {
	_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);

	status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
					   &pattern.base,
					   NULL,
					   surface,
					   surface_rect.x - clip->surface_rect.x,
					   surface_rect.y - clip->surface_rect.y,
					   0, 0,
					   0, 0,
					   surface_rect.width,
					   surface_rect.height);

	_cairo_pattern_fini (&pattern.base);

	if (status) {
	    cairo_surface_destroy (surface);
	    return status;
	}

	cairo_surface_destroy (clip->surface);
    }

 DONE:
    clip->surface = surface;
    clip->surface_rect = surface_rect;
    clip->serial = _cairo_surface_allocate_clip_serial (target);

    if (surface_rect.width == 0 || surface_rect.height == 0)
	_cairo_clip_set_all_clipped (clip, target);

    return status;
}
Ejemplo n.º 16
0
cairo_status_t
_cairo_clip_clip (cairo_clip_t       *clip,
		  cairo_path_fixed_t *path,
		  cairo_fill_rule_t   fill_rule,
		  double              tolerance,
		  cairo_antialias_t   antialias,
		  cairo_surface_t    *target)
{
    cairo_status_t status;
    cairo_rectangle_int_t rectangle;
    cairo_traps_t traps;
    cairo_box_t ignored_box;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    /* catch the empty clip path */
    if (! path->has_current_point) {
	_cairo_clip_set_all_clipped (clip, target);
	return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_clip_intersect_path (clip,
					 path, fill_rule, tolerance,
					 antialias);
    if (status == CAIRO_STATUS_SUCCESS)
        clip->serial = _cairo_surface_allocate_clip_serial (target);

    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    /* TODO: allow ANTIALIAS_NONE when we have a mono scan converter
     * again. */
    if (antialias != CAIRO_ANTIALIAS_NONE &&
	!_cairo_path_fixed_is_box (path, &ignored_box) &&
	!_cairo_path_fixed_is_region (path))
    {
	status = _cairo_clip_intersect_mask_using_spans (
	    clip, path, fill_rule, tolerance, antialias, target);
	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    return status;
    }

    _cairo_traps_init (&traps);

    /* Limit the traps to the target surface
     * - so we don't add more traps than needed. */
    status = _cairo_surface_get_extents (target, &rectangle);
    if (status == CAIRO_STATUS_SUCCESS) {
	cairo_box_t box;

	_cairo_box_from_rectangle (&box, &rectangle);
	_cairo_traps_limit (&traps, &box);
    }

    status = _cairo_path_fixed_fill_to_traps (path,
					      fill_rule,
					      tolerance,
					      &traps);
    if (unlikely (status))
	goto bail;

    status = _cairo_clip_intersect_region (clip, &traps, target);
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	goto bail;

    status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);

 bail:
    _cairo_traps_fini (&traps);

    return status;
}
Ejemplo n.º 17
0
static cairo_status_t
_cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
					cairo_path_fixed_t *path,
					cairo_fill_rule_t   fill_rule,
					double		    tolerance,
					cairo_antialias_t   antialias,
					cairo_surface_t    *target)
{
    cairo_span_renderer_t *renderer = NULL;
    cairo_pattern_union_t pattern;
    cairo_rectangle_int_t surface_rect;
    cairo_surface_t *surface = NULL;
    cairo_status_t status;
    cairo_operator_t op;
    cairo_composite_rectangles_t rects;

    if (clip->all_clipped)
	return CAIRO_STATUS_SUCCESS;

    _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
			       CAIRO_CONTENT_COLOR);

    /* If we have a clip surface we're going to use IN to combine our
     * new clip with the old clip.  The ADD is done to a transparent
     * surface, as that's a fast way of doing it currently.  We should
     * really be using SOURCE instead, but _cairo_surface_composite()
     * checks that it's not called with SOURCE or DEST. */
    op = clip->surface ? CAIRO_OPERATOR_IN : CAIRO_OPERATOR_ADD;

    /* Test if the target can composite spans.  We're going to assume
     * this is a good indicator of whether a similar surface is going
     * to be able to composite spans too. */
    if ( !_cairo_surface_check_span_renderer (op,
					      &pattern.base,
					      target,
					      antialias,
					      NULL))
    {
	status = CAIRO_INT_STATUS_UNSUPPORTED;
	goto BAIL;
    }

    status = _cairo_surface_get_extents (target, &surface_rect);
    if (status)
	goto BAIL;

    /* We'll create a new surface the size of the intersection of the
     * old mask surface and the extents of the new clip path. */
    {
	cairo_rectangle_int_t extents;

	_cairo_path_fixed_approximate_clip_extents (path, &extents);
	if (! _cairo_rectangle_intersect (&surface_rect, &extents))
	    goto SUCCESS;

	if (clip->surface != NULL &&
	    ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
	    goto SUCCESS;
    }

    /* Make the new mask surface and optionally initialise it from the
     * previous clip if we have one. */
    surface = _cairo_surface_create_similar_solid (target,
						   CAIRO_CONTENT_ALPHA,
						   surface_rect.width,
						   surface_rect.height,
						   CAIRO_COLOR_TRANSPARENT);
    if (surface->status) {
	_cairo_pattern_fini (&pattern.base);
	return surface->status;
    }

    if (clip->surface) {
	cairo_surface_pattern_t old_clip;
	_cairo_pattern_init_for_surface (&old_clip, clip->surface);
	status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
					   &old_clip.base,
					   NULL,
					   surface,
					   surface_rect.x - clip->surface_rect.x,
					   surface_rect.y - clip->surface_rect.y,
					   0, 0,
					   0, 0,
					   surface_rect.width,
					   surface_rect.height);
	_cairo_pattern_fini (&old_clip.base);
	if (status)
	    goto BAIL;
    }

    _cairo_composite_rectangles_init (&rects,
				      surface_rect.x,
				      surface_rect.y,
				      surface_rect.width,
				      surface_rect.height);
    rects.dst.x = 0;
    rects.dst.y = 0;

    /* Render the new clipping path into the new mask surface. We've
     * chosen op to either combine the new clip path with the existing
     * clip mask (if there is one) or just render it. */
    status =_cairo_path_fixed_fill_using_spans (op, &pattern.base,
						path, surface,
						fill_rule, tolerance,
						antialias, &rects);
    if (status)
	goto BAIL;

 SUCCESS:
    if (clip->surface != NULL)
	cairo_surface_destroy (clip->surface);
    clip->surface = surface;
    clip->surface_rect = surface_rect;
    clip->serial = _cairo_surface_allocate_clip_serial (target);
    surface = NULL;

    if (surface_rect.width == 0 || surface_rect.height == 0)
	_cairo_clip_set_all_clipped (clip, target);

 BAIL:
    if (renderer)
	renderer->destroy(renderer);
    if (surface)
	cairo_surface_destroy (surface);
    _cairo_pattern_fini (&pattern.base);
    return status;
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
static cairo_status_t
_cairo_clip_intersect_path (cairo_clip_t       *clip,
			    const cairo_path_fixed_t *path,
			    cairo_fill_rule_t   fill_rule,
			    double              tolerance,
			    cairo_antialias_t   antialias)
{
    cairo_clip_path_t *clip_path;
    cairo_status_t status;
    cairo_rectangle_int_t extents;
    cairo_box_t box;
    cairo_bool_t is_box = FALSE;

    if (clip->path != NULL) {
	if (clip->path->fill_rule == fill_rule &&
	    (path->is_rectilinear ||
	     (tolerance == clip->path->tolerance &&
	      antialias == clip->path->antialias)) &&
	    _cairo_path_fixed_equal (&clip->path->path, path))
	{
	    return CAIRO_STATUS_SUCCESS;
	}
    }

    _cairo_path_fixed_approximate_clip_extents (path, &extents);
    if (extents.width == 0 || extents.height == 0) {
	_cairo_clip_set_all_clipped (clip);
	return CAIRO_STATUS_SUCCESS;
    }

    is_box = _cairo_path_fixed_is_box (path, &box);
    if (clip->path != NULL) {
	if (! _cairo_rectangle_intersect (&extents, &clip->path->extents)) {
	    _cairo_clip_set_all_clipped (clip);
	    return CAIRO_STATUS_SUCCESS;
	}

	/* does this clip wholly subsume the others? */
	if (is_box &&
	    box.p1.x <= _cairo_fixed_from_int (clip->path->extents.x) &&
	    box.p2.x >= _cairo_fixed_from_int (clip->path->extents.x + clip->path->extents.width) &&
	    box.p1.y <= _cairo_fixed_from_int (clip->path->extents.y) &&
	    box.p2.y >= _cairo_fixed_from_int (clip->path->extents.y + clip->path->extents.height))
	{
	    return CAIRO_STATUS_SUCCESS;
	}
    }

    clip_path = _cairo_clip_path_create (clip);
    if (unlikely (clip_path == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    status = _cairo_path_fixed_init_copy (&clip_path->path, path);
    if (unlikely (status)) {
	clip->path = clip->path->prev;
	_cairo_clip_path_destroy (clip_path);
	return status;
    }

    clip_path->extents = extents;
    clip_path->fill_rule = fill_rule;
    clip_path->tolerance = tolerance;
    clip_path->antialias = antialias;
    if (is_box)
	clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;

    return CAIRO_STATUS_SUCCESS;
}