Пример #1
0
/* Composites a region representing a set of trapezoids.
 */
static cairo_status_t
_composite_trap_region (cairo_clip_t            *clip,
			cairo_pattern_t         *src,
			cairo_operator_t         op,
			cairo_surface_t         *dst,
			cairo_region_t          *trap_region,
			cairo_rectangle_int_t   *extents)
{
    cairo_status_t status;
    cairo_pattern_union_t solid_pattern;
    cairo_pattern_union_t mask;
    int num_rects = _cairo_region_num_boxes (trap_region);
    unsigned int clip_serial;
    cairo_surface_t *clip_surface = clip ? clip->surface : NULL;

    if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
	_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
				   CAIRO_CONTENT_COLOR);
	src = &solid_pattern.base;
	op = CAIRO_OPERATOR_DEST_OUT;
    }

    if (num_rects == 0)
	return CAIRO_STATUS_SUCCESS;

    if (num_rects > 1) {
      if (_cairo_surface_get_clip_mode (dst) != CAIRO_CLIP_MODE_REGION)
	    return CAIRO_INT_STATUS_UNSUPPORTED;

	clip_serial = _cairo_surface_allocate_clip_serial (dst);
	status = _cairo_surface_set_clip_region (dst,
						 trap_region,
						 clip_serial);
	if (status)
	    return status;
    }

    if (clip_surface)
	_cairo_pattern_init_for_surface (&mask.surface, clip_surface);

    status = _cairo_surface_composite (op,
				       src,
				       clip_surface ? &mask.base : NULL,
				       dst,
				       extents->x, extents->y,
				       extents->x - (clip_surface ? clip->surface_rect.x : 0),
				       extents->y - (clip_surface ? clip->surface_rect.y : 0),
				       extents->x, extents->y,
				       extents->width, extents->height);

    /* Restore the original clip if we modified it temporarily. */
    if (num_rects > 1) {
	cairo_status_t status2 = _cairo_surface_set_clip (dst, clip);
	if (status == CAIRO_STATUS_SUCCESS)
	    status = status2;
    }

    if (clip_surface)
      _cairo_pattern_fini (&mask.base);

    if (src == &solid_pattern.base)
	_cairo_pattern_fini (&solid_pattern.base);

    return status;
}
Пример #2
0
cairo_rectangle_list_t *
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
    cairo_rectangle_list_t *list;
    cairo_rectangle_t *rectangles = NULL;
    int n_boxes = 0;

    if (clip->all_clipped)
	goto DONE;

    if (clip->path || clip->surface) {
	_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
    }

    if (clip->has_region) {
        int i;

	n_boxes = _cairo_region_num_boxes (&clip->region);

	if (n_boxes) {
	    rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
	    if (unlikely (rectangles == NULL)) {
		_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
		return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
	    }

	    for (i = 0; i < n_boxes; ++i) {
		cairo_box_int_t box;
		cairo_rectangle_int_t clip_rect;

		_cairo_region_get_box (&clip->region, i, &box);

		clip_rect.x = box.p1.x;
		clip_rect.y = box.p1.y;
		clip_rect.width  = box.p2.x - box.p1.x;
		clip_rect.height = box.p2.y - box.p1.y;
		
		if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
		    _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
		    free (rectangles);
		    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
		}
	    }
	}
    } else {
        cairo_rectangle_int_t extents;

	n_boxes = 1;

	rectangles = malloc(sizeof (cairo_rectangle_t));
	if (unlikely (rectangles == NULL)) {
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
	    return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
	}

	if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) ||
	    !_cairo_clip_int_rect_to_user(gstate, &extents, rectangles))
	{
	    _cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
	    free (rectangles);
	    return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
	}
    }

 DONE:
    list = malloc (sizeof (cairo_rectangle_list_t));
    if (unlikely (list == NULL)) {
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
        free (rectangles);
        return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
    }

    list->status = CAIRO_STATUS_SUCCESS;
    list->rectangles = rectangles;
    list->num_rectangles = n_boxes;
    return list;
}