cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t		*target,
				int			 width,
				int			 height)
{
    cairo_analysis_surface_t *surface;
    cairo_status_t status;

    status = target->status;
    if (unlikely (status))
	return _cairo_surface_create_in_error (status);

    surface = malloc (sizeof (cairo_analysis_surface_t));
    if (unlikely (surface == NULL))
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    /* I believe the content type here is truly arbitrary. I'm quite
     * sure nothing will ever use this value. */
    _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
			 CAIRO_CONTENT_COLOR_ALPHA);

    surface->width = width;
    surface->height = height;
    cairo_matrix_init_identity (&surface->ctm);
    surface->has_ctm = FALSE;

    surface->target = cairo_surface_reference (target);
    surface->first_op  = TRUE;
    surface->has_supported = FALSE;
    surface->has_unsupported = FALSE;

    surface->page_bbox.p1.x = 0;
    surface->page_bbox.p1.y = 0;
    surface->page_bbox.p2.x = 0;
    surface->page_bbox.p2.y = 0;

    _cairo_region_init (&surface->supported_region);
    _cairo_region_init (&surface->fallback_region);

    if (width == -1 && height == -1) {
	surface->current_clip.x      = CAIRO_RECT_INT_MIN;
	surface->current_clip.y      = CAIRO_RECT_INT_MIN;
	surface->current_clip.width  = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
	surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
    } else {
	surface->current_clip.x = 0;
	surface->current_clip.y = 0;
	surface->current_clip.width = width;
	surface->current_clip.height = height;
    }

    return &surface->base;
}
Exemple #2
0
cairo_status_t
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
    clip->mode = other->mode;

    clip->all_clipped = other->all_clipped;

    clip->surface = cairo_surface_reference (other->surface);
    clip->surface_rect = other->surface_rect;

    clip->serial = other->serial;

    _cairo_region_init (&clip->region);

    if (other->has_region) {
	cairo_status_t status;
	status = _cairo_region_copy (&clip->region, &other->region);
	if (status) {
	    _cairo_region_fini (&clip->region);
	    cairo_surface_destroy (clip->surface);
	    return status;
	}
        clip->has_region = TRUE;
    } else {
        clip->has_region = FALSE;
    }

    clip->path = _cairo_clip_path_reference (other->path);

    return CAIRO_STATUS_SUCCESS;
}
cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t		*target)
{
    cairo_analysis_surface_t *surface;
    cairo_status_t status;

    status = target->status;
    if (unlikely (status))
	return _cairo_surface_create_in_error (status);

    surface = malloc (sizeof (cairo_analysis_surface_t));
    if (unlikely (surface == NULL))
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    /* I believe the content type here is truly arbitrary. I'm quite
     * sure nothing will ever use this value. */
    _cairo_surface_init (&surface->base,
			 &cairo_analysis_surface_backend,
			 NULL, /* device */
			 CAIRO_CONTENT_COLOR_ALPHA,
			 target->is_vector);

    cairo_matrix_init_identity (&surface->ctm);
    surface->has_ctm = FALSE;

    surface->target = cairo_surface_reference (target);
    surface->first_op  = TRUE;
    surface->has_supported = FALSE;
    surface->has_unsupported = FALSE;

    _cairo_region_init (&surface->supported_region);
    _cairo_region_init (&surface->fallback_region);

    surface->page_bbox.p1.x = 0;
    surface->page_bbox.p1.y = 0;
    surface->page_bbox.p2.x = 0;
    surface->page_bbox.p2.y = 0;

    return &surface->base;
}
Exemple #4
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;
}
Exemple #5
0
void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
{
    if (target)
	clip->mode = _cairo_surface_get_clip_mode (target);
    else
	clip->mode = CAIRO_CLIP_MODE_MASK;

    clip->all_clipped = FALSE;

    clip->surface = NULL;
    clip->surface_rect.x = 0;
    clip->surface_rect.y = 0;
    clip->surface_rect.width = 0;
    clip->surface_rect.height = 0;

    clip->serial = 0;

    _cairo_region_init (&clip->region);
    clip->has_region = FALSE;

    clip->path = NULL;
}
Exemple #6
0
void
_cairo_clip_reset (cairo_clip_t *clip)
{
    clip->all_clipped = FALSE;

    /* destroy any existing clip-region artifacts */
    cairo_surface_destroy (clip->surface);
    clip->surface = NULL;

    clip->serial = 0;

    if (clip->has_region) {
        /* _cairo_region_fini just releases the resources used but
         * doesn't bother with leaving the region in a valid state.
         * So _cairo_region_init has to be called afterwards. */
	_cairo_region_fini (&clip->region);
        _cairo_region_init (&clip->region);

        clip->has_region = FALSE;
    }

    _cairo_clip_path_destroy (clip->path);
    clip->path = NULL;
}
Exemple #7
0
/**
 * _cairo_traps_extract_region:
 * @traps: a #cairo_traps_t
 * @region: a #cairo_region_t
 *
 * Determines if a set of trapezoids are exactly representable as a
 * cairo region.  If so, the passed-in region is initialized to
 * the area representing the given traps.  It should be finalized
 * with _cairo_region_fini().  If not, %CAIRO_INT_STATUS_UNSUPPORTED
 * is returned.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
 * or %CAIRO_STATUS_NO_MEMORY
 **/
cairo_int_status_t
_cairo_traps_extract_region (const cairo_traps_t  *traps,
			     cairo_region_t       *region)
{
    cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
    cairo_box_int_t *boxes = stack_boxes;
    int i, box_count;
    cairo_int_status_t status;

    if (traps->num_traps == 0) {
	_cairo_region_init (region);
	return CAIRO_STATUS_SUCCESS;
    }

    for (i = 0; i < traps->num_traps; i++) {
	if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
	    traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
	    ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
	    ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
	    ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
	    ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
	{
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	}
    }

    if (traps->num_traps > ARRAY_LENGTH (stack_boxes)) {
	boxes = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_box_int_t));

	if (unlikely (boxes == NULL))
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    box_count = 0;

    for (i = 0; i < traps->num_traps; i++) {
	int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
	int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
	int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
	int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);

	/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
	 * skip these.
	 */
	if (x1 == x2 || y1 == y2)
	    continue;

	boxes[box_count].p1.x = x1;
	boxes[box_count].p1.y = y1;
	boxes[box_count].p2.x = x2;
	boxes[box_count].p2.y = y2;

	box_count++;
    }

    status = _cairo_region_init_boxes (region, boxes, box_count);

    if (boxes != stack_boxes)
	free (boxes);

    if (unlikely (status))
	_cairo_region_fini (region);

    return status;
}