void
pixman_image_destroy (pixman_image_t *image)
{
    pixman_image_destroyClip (image);

    if (image->freeCompClip) {
        pixman_region_destroy (image->pCompositeClip);
        image->pCompositeClip = NULL;
    }

    if (image->freeSourceClip) {
        pixman_region_destroy (image->pSourceClip);
        image->pSourceClip = NULL;
    }

    if (image->owns_pixels) {
        FbPixelsDestroy (image->pixels);
        image->pixels = NULL;
    }

    if (image->transform) {
        free (image->transform);
        image->transform = NULL;
    }

    free (image);
}
int
pixman_image_set_clip_region (pixman_image_t	*image,
                              pixman_region16_t	*region)
{
    pixman_image_destroyClip (image);
    if (region) {
        image->clientClip = pixman_region_create ();
        pixman_region_copy (image->clientClip, region);
        image->clientClipType = CT_REGION;
    }

    if (image->freeCompClip)
        pixman_region_destroy (image->pCompositeClip);
    image->pCompositeClip = pixman_region_create();
    pixman_region_union_rect (image->pCompositeClip, image->pCompositeClip,
                              0, 0, image->pixels->width, image->pixels->height);
    image->freeCompClip = 1;
    if (region) {
        pixman_region_translate (image->pCompositeClip,
                                 - image->clipOrigin.x,
                                 - image->clipOrigin.y);
        pixman_region_intersect (image->pCompositeClip,
                                 image->pCompositeClip,
                                 region);
        pixman_region_translate (image->pCompositeClip,
                                 image->clipOrigin.x,
                                 image->clipOrigin.y);
    }

    image->stateChanges |= CPClipMask;
    return 0;
}
Example #3
0
static cairo_status_t
_cairo_quartz_surface_finish(void *abstract_surface)
{
    cairo_quartz_surface_t *surface = abstract_surface;

    if (surface->clip_region)
        pixman_region_destroy (surface->clip_region);

    return CAIRO_STATUS_SUCCESS;
}
Example #4
0
static cairo_status_t
_cairo_clip_intersect_region (cairo_clip_t    *clip,
			      cairo_traps_t   *traps,
			      cairo_surface_t *target)
{
    pixman_region16_t *region;
    cairo_status_t status;

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

    status = _cairo_traps_extract_region (traps, &region);
    if (status)
	return status;

    if (region == NULL)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    status = CAIRO_STATUS_SUCCESS;
    if (clip->region == NULL) {
	clip->region = region;
    } else {
	pixman_region16_t *intersection = pixman_region_create();

	if (pixman_region_intersect (intersection,
				     clip->region, region)
	    == PIXMAN_REGION_STATUS_SUCCESS) {
	    pixman_region_destroy (clip->region);
	    clip->region = intersection;
	} else {
	    status = CAIRO_STATUS_NO_MEMORY;
	}
	pixman_region_destroy (region);
    }

    clip->serial = _cairo_surface_allocate_clip_serial (target);

    return status;
}
Example #5
0
void
_cairo_clip_fini (cairo_clip_t *clip)
{
    cairo_surface_destroy (clip->surface);
    clip->surface = NULL;

    clip->serial = 0;

    if (clip->region)
	pixman_region_destroy (clip->region);
    clip->region = NULL;

    _cairo_clip_path_destroy (clip->path);
    clip->path = NULL;
}
void
pixman_image_destroyClip (pixman_image_t *image)
{
    switch (image->clientClipType) {
    case CT_NONE:
        return;
    case CT_PIXMAP:
        pixman_image_destroy (image->clientClip);
        break;
    default:
        pixman_region_destroy (image->clientClip);
        break;
    }
    image->clientClip = NULL;
    image->clientClipType = CT_NONE;
}
/**
 * _cairo_region_create_from_rectangle:
 * @rect: a #cairo_rectangle_t
 * 
 * Creates a region with extents initialized from the given
 * rectangle.
 * 
 * Return value: a newly created #pixman_region16_t or %NULL if
 *    memory couldn't a allocated.
 **/
pixman_region16_t *
_cairo_region_create_from_rectangle (cairo_rectangle_t *rect)
{
    /* We can't use pixman_region_create_simple(), because it doesn't
     * have an error return
     */
    pixman_region16_t *region = pixman_region_create ();
    if (pixman_region_union_rect (region, region,
				  rect->x, rect->y,
				  rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
	pixman_region_destroy (region);
	return NULL;
    }
    
    return region;
}
Example #8
0
static cairo_int_status_t
_cairo_quartz_surface_set_clip_region(void *abstract_surface,
                                      pixman_region16_t * region)
{
    cairo_quartz_surface_t *surface = abstract_surface;

    if (surface->clip_region)
        pixman_region_destroy (surface->clip_region);

    if (region) {
        surface->clip_region = pixman_region_create ();
        pixman_region_copy (surface->clip_region, region);
    } else
        surface->clip_region = NULL;

    return CAIRO_STATUS_SUCCESS;
}
Example #9
0
cairo_status_t
_cairo_clip_reset (cairo_clip_t *clip)
{
    /* destroy any existing clip-region artifacts */
    cairo_surface_destroy (clip->surface);
    clip->surface = NULL;

    clip->serial = 0;

    if (clip->region)
	pixman_region_destroy (clip->region);
    clip->region = NULL;

    _cairo_clip_path_destroy (clip->path);
    clip->path = NULL;

    return CAIRO_STATUS_SUCCESS;
}
Example #10
0
/**
 * _cairo_traps_extract_region:
 * @traps: a #cairo_traps_t
 * @region: on return, %NULL is stored here if the trapezoids aren't
 *          exactly representable as a pixman region, otherwise a
 *          a pointer to such a region, newly allocated.
 *          (free with pixman region destroy)
 * 
 * Determines if a set of trapezoids are exactly representable as a
 * pixman region, and if so creates such a region.
 * 
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
 **/
cairo_status_t
_cairo_traps_extract_region (cairo_traps_t      *traps,
			     pixman_region16_t **region)
{
    int i;

    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))) {
	    *region = NULL;
	    return CAIRO_STATUS_SUCCESS;
	}
    
    *region = pixman_region_create ();

    for (i = 0; i < traps->num_traps; i++) {
	int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
	int y = _cairo_fixed_integer_part(traps->traps[i].top);
	int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x;
	int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y;

	/* XXX: Sometimes we get degenerate trapezoids from the tesellator,
	 * if we call pixman_region_union_rect(), it bizarrly fails on such
	 * an empty rectangle, so skip them.
	 */
	if (width == 0 || height == 0)
	  continue;
	
	if (pixman_region_union_rect (*region, *region,
				      x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) {
	    pixman_region_destroy (*region);
	    return CAIRO_STATUS_NO_MEMORY;
	}
    }

    return CAIRO_STATUS_SUCCESS;
}
Example #11
0
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t            *clip,
				    cairo_rectangle_int16_t *rectangle)
{
    if (!clip)
	return CAIRO_STATUS_SUCCESS;

    if (clip->path) {
	/* Intersect path extents here. */
    }

    if (clip->region) {
	pixman_region16_t *intersection;
	cairo_status_t status = CAIRO_STATUS_SUCCESS;
	pixman_region_status_t pixman_status;

	intersection = _cairo_region_create_from_rectangle (rectangle);
	if (intersection == NULL)
	    return CAIRO_STATUS_NO_MEMORY;

	pixman_status = pixman_region_intersect (intersection,
					  clip->region,
					  intersection);
	if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
	    _cairo_region_extents_rectangle (intersection, rectangle);
	else
	    status = CAIRO_STATUS_NO_MEMORY;

	pixman_region_destroy (intersection);

	if (status)
	    return status;
    }

    if (clip->surface)
	_cairo_rectangle_intersect (rectangle, &clip->surface_rect);

    return CAIRO_STATUS_SUCCESS;
}
Example #12
0
cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t      *clip,
				 pixman_region16_t *region)
{
    if (!clip)
	return CAIRO_STATUS_SUCCESS;

    if (clip->path) {
	/* Intersect clip path into region. */
    }

    if (clip->region)
	pixman_region_intersect (region, clip->region, region);

    if (clip->surface) {
	pixman_region16_t *clip_rect;
	pixman_region_status_t pixman_status;
	cairo_status_t status = CAIRO_STATUS_SUCCESS;

	clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
	if (clip_rect == NULL)
	    return CAIRO_STATUS_NO_MEMORY;

	pixman_status = pixman_region_intersect (region,
						 clip_rect,
						 region);
	if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
	    status = CAIRO_STATUS_NO_MEMORY;

	pixman_region_destroy (clip_rect);

	if (status)
	    return status;
    }

    return CAIRO_STATUS_SUCCESS;
}
int
FbComputeCompositeRegion (pixman_region16_t	*region,
                          pixman_image_t	*iSrc,
                          pixman_image_t	*iMask,
                          pixman_image_t	*iDst,
                          int16_t		xSrc,
                          int16_t		ySrc,
                          int16_t		xMask,
                          int16_t		yMask,
                          int16_t		xDst,
                          int16_t		yDst,
                          uint16_t	width,
                          uint16_t	height)
{
    int		v;
    int x1, y1, x2, y2;

    /* XXX: This code previously directly set the extents of the
       region here. I need to decide whether removing that has broken
       this. Also, it might be necessary to just make the pixman_region16_t
       data structure transparent anyway in which case I can just put
       the code back. */
    x1 = xDst;
    v = xDst + width;
    x2 = BOUND(v);
    y1 = yDst;
    v = yDst + height;
    y2 = BOUND(v);
    /* Check for empty operation */
    if (x1 >= x2 ||
            y1 >= y2)
    {
        pixman_region_empty (region);
        return 1;
    }
    /* clip against src */
    if (!FbClipImageSrc (region, iSrc, xDst - xSrc, yDst - ySrc))
    {
        pixman_region_destroy (region);
        return 0;
    }
    if (iSrc->alphaMap)
    {
        if (!FbClipImageSrc (region, iSrc->alphaMap,
                             xDst - (xSrc + iSrc->alphaOrigin.x),
                             yDst - (ySrc + iSrc->alphaOrigin.y)))
        {
            pixman_region_destroy (region);
            return 0;
        }
    }
    /* clip against mask */
    if (iMask)
    {
        if (!FbClipImageSrc (region, iMask, xDst - xMask, yDst - yMask))
        {
            pixman_region_destroy (region);
            return 0;
        }
        if (iMask->alphaMap)
        {
            if (!FbClipImageSrc (region, iMask->alphaMap,
                                 xDst - (xMask + iMask->alphaOrigin.x),
                                 yDst - (yMask + iMask->alphaOrigin.y)))
            {
                pixman_region_destroy (region);
                return 0;
            }
        }
    }
    if (!FbClipImageReg (region, iDst->pCompositeClip, 0, 0))
    {
        pixman_region_destroy (region);
        return 0;
    }
    if (iDst->alphaMap)
    {
        if (!FbClipImageReg (region, iDst->alphaMap->pCompositeClip,
                             -iDst->alphaOrigin.x,
                             -iDst->alphaOrigin.y))
        {
            pixman_region_destroy (region);
            return 0;
        }
    }
    return 1;
}
Example #14
0
/* XXX: There are failure cases in this function. Don't we need to
 * propagate the errors out?
 */
void
pixman_composite_trapezoids (pixman_operator_t	      op,
			     pixman_image_t	      *src,
			     pixman_image_t	      *dst,
			     int		      xSrc,
			     int		      ySrc,
			     const pixman_trapezoid_t *traps,
			     int		      ntraps)
{
    pixman_image_t	*image = NULL;
    pixman_box16_t	traps_bounds, dst_bounds, bounds;
    pixman_region16_t	*traps_region, *dst_region;
    int16_t		xDst, yDst;
    int16_t		xRel, yRel;
    pixman_format_t	*format;

    if (ntraps == 0)
	return;

    /*
     * Check for solid alpha add
     */
    if (op == PIXMAN_OPERATOR_ADD && miIsSolidAlpha (src))
    {
	for (; ntraps; ntraps--, traps++)
	    fbRasterizeTrapezoid (dst, traps, 0, 0);
	return;
    }

    xDst = traps[0].left.p1.x >> 16;
    yDst = traps[0].left.p1.y >> 16;
    
    pixman_trapezoid_bounds (ntraps, traps, &traps_bounds);

    traps_region = pixman_region_create_simple (&traps_bounds);

    /* XXX: If the image has a clip region set, we should really be
     * fetching it here instead, but it looks like we don't yet expose
     * a pixman_image_get_clip_region function. */
    dst_bounds.x1 = 0;
    dst_bounds.y1 = 0;
    dst_bounds.x2 = pixman_image_get_width (dst);
    dst_bounds.y2 = pixman_image_get_height (dst);

    dst_region = pixman_region_create_simple (&dst_bounds);

    pixman_region_intersect (traps_region, traps_region, dst_region);

    bounds = *(pixman_region_extents (traps_region));

    pixman_region_destroy (traps_region);
    pixman_region_destroy (dst_region);

    if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
	return;

    format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
    if (!format)
	return;

    image = FbCreateAlphaPicture (dst, format,
				  bounds.x2 - bounds.x1,
				  bounds.y2 - bounds.y1);
    if (!image)
    {
	pixman_format_destroy (format);
	return;
    }

    for (; ntraps; ntraps--, traps++)
    {
	if (!xTrapezoidValid(traps))
	    continue;
	fbRasterizeTrapezoid (image, traps, 
			      -bounds.x1, -bounds.y1);
    }

    xRel = bounds.x1 + xSrc - xDst;
    yRel = bounds.y1 + ySrc - yDst;
    pixman_composite (op, src, image, dst,
		      xRel, yRel, 0, 0, bounds.x1, bounds.y1,
		      bounds.x2 - bounds.x1,
		      bounds.y2 - bounds.y1);
    pixman_image_destroy (image);

    pixman_format_destroy (format);
}
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
_clip_and_composite_trapezoids (cairo_pattern_t *src,
				cairo_operator_t op,
				cairo_surface_t *dst,
				cairo_traps_t *traps,
				cairo_clip_t *clip,
				cairo_antialias_t antialias)
{
    cairo_status_t status;
    pixman_region16_t *trap_region;
    pixman_region16_t *clear_region = NULL;
    cairo_rectangle_int16_t extents;
    cairo_composite_traps_info_t traps_info;

    if (traps->num_traps == 0)
	return CAIRO_STATUS_SUCCESS;

    status = _cairo_traps_extract_region (traps, &trap_region);
    if (status)
	return status;

    if (_cairo_operator_bounded_by_mask (op))
    {
	if (trap_region) {
	    status = _cairo_clip_intersect_to_region (clip, trap_region);
	    _cairo_region_extents_rectangle (trap_region, &extents);
	} else {
	    cairo_box_t trap_extents;
	    _cairo_traps_extents (traps, &trap_extents);
	    _cairo_box_round_to_rectangle (&trap_extents, &extents);
	    status = _cairo_clip_intersect_to_rectangle (clip, &extents);
	}
    }
    else
    {
	cairo_surface_t *clip_surface = clip ? clip->surface : NULL;

	status = _cairo_surface_get_extents (dst, &extents);
	if (status)
	    return status;

	if (trap_region && !clip_surface) {
	    /* If we optimize drawing with an unbounded operator to
	     * _cairo_surface_fill_rectangles() or to drawing with a
	     * clip region, then we have an additional region to clear.
	     */
	    clear_region = _cairo_region_create_from_rectangle (&extents);
	    if (clear_region == NULL)
		return CAIRO_STATUS_NO_MEMORY;

	    status = _cairo_clip_intersect_to_region (clip, clear_region);
	    if (status)
		return status;

	    _cairo_region_extents_rectangle (clear_region,  &extents);

	    if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
		return CAIRO_STATUS_NO_MEMORY;

	    if (!pixman_region_not_empty (clear_region)) {
		pixman_region_destroy (clear_region);
		clear_region = NULL;
	    }
	} else {
	    status = _cairo_clip_intersect_to_rectangle (clip, &extents);
	    if (status)
		return status;
	}
    }

    if (status)
	goto out;

    if (trap_region)
    {
	cairo_surface_t *clip_surface = clip ? clip->surface : NULL;

	if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
	    !clip_surface)
	{
	    const cairo_color_t *color;

	    if (op == CAIRO_OPERATOR_CLEAR)
		color = CAIRO_COLOR_TRANSPARENT;
	    else
		color = &((cairo_solid_pattern_t *)src)->color;

	    /* Solid rectangles special case */
	    status = _cairo_surface_fill_region (dst, op, color, trap_region);
	    if (!status && clear_region)
		status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
						     CAIRO_COLOR_TRANSPARENT,
						     clear_region);

	    goto out;
	}

	if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
	    !clip_surface)
	{
	    /* For a simple rectangle, we can just use composite(), for more
	     * rectangles, we have to set a clip region. The cost of rasterizing
	     * trapezoids is pretty high for most backends currently, so it's
	     * worthwhile even if a region is needed.
	     *
	     * If we have a clip surface, we set it as the mask; this only works
	     * for bounded operators other than SOURCE; for unbounded operators,
	     * clip and mask cannot be interchanged. For SOURCE, the operator
	     * as implemented by the backends is different in it's handling
	     * of the mask then what we want.
	     *
	     * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
	     * more than rectangle and the destination doesn't support clip
	     * regions. In that case, we fall through.
	     */
	    status = _composite_trap_region (clip, src, op, dst,
					     trap_region, &extents);
	    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
	    {
		if (!status && clear_region)
		    status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
							 CAIRO_COLOR_TRANSPARENT,
							 clear_region);
		goto out;
	    }
	}
    }

    traps_info.traps = traps;
    traps_info.antialias = antialias;

    status = _clip_and_composite (clip, op, src,
				  _composite_traps_draw_func, &traps_info,
				  dst, &extents);

 out:
    if (trap_region)
	pixman_region_destroy (trap_region);
    if (clear_region)
	pixman_region_destroy (clear_region);

    return status;
}
Example #16
0
static void
pixman_color_rects (pixman_image_t	 *dst,
                    pixman_image_t	 *clipPict,
                    pixman_color_t	 *color,
                    int	 nRect,
                    pixman_rectangle_t *rects,
                    int	 xoff,
                    int	 yoff)
{
    pixman_bits_t	pixel;
    pixman_region16_t  *clip;
    pixman_region16_t  *rects_as_region;
    pixman_box16_t     *clipped_rects;
    int	                i, n_clipped_rects;
    FillFunc            func;

    pixman_color_to_pixel (&dst->image_format,
                           color,
                           &pixel);

    /* offset to the right place on the destination image */
    xoff -= dst->pixels->x;
    yoff -= dst->pixels->y;

    clip = pixman_region_create();
    pixman_region_union_rect (clip, clip,
                              dst->pixels->x, dst->pixels->y,
                              dst->pixels->width, dst->pixels->height);

    pixman_region_intersect (clip, clip, clipPict->pCompositeClip);
    if (clipPict->alphaMap)
    {
        pixman_region_translate (clip,
                                 -clipPict->alphaOrigin.x,
                                 -clipPict->alphaOrigin.y);
        pixman_region_intersect (clip, clip, clipPict->alphaMap->pCompositeClip);
        pixman_region_translate (clip,
                                 clipPict->alphaOrigin.x,
                                 clipPict->alphaOrigin.y);
    }

    if (xoff || yoff)
    {
        for (i = 0; i < nRect; i++)
        {
            rects[i].x -= xoff;
            rects[i].y -= yoff;
        }
    }

    rects_as_region = pixman_region_create ();
    for (i = 0; i < nRect; i++)
    {
        pixman_region_union_rect (rects_as_region, rects_as_region,
                                  rects[i].x, rects[i].y,
                                  rects[i].width, rects[i].height);
    }

    pixman_region_intersect (rects_as_region, rects_as_region, clip);
    pixman_region_destroy (clip);

    n_clipped_rects = pixman_region_num_rects (rects_as_region);
    clipped_rects = pixman_region_rects (rects_as_region);

    if (dst->pixels->bpp == 8)
        func = pixman_fill_rect_8bpp;
    else if (dst->pixels->bpp == 32)
        func = pixman_fill_rect_32bpp;
    else if (dst->pixels->bpp == 1)
        func = pixman_fill_rect_1bpp;
    else
        func = pixman_fill_rect_general;

    for (i = 0; i < n_clipped_rects; i++) {
        (*func) (dst,
                 clipped_rects[i].x1,
                 clipped_rects[i].y1,
                 clipped_rects[i].x2 - clipped_rects[i].x1,
                 clipped_rects[i].y2 - clipped_rects[i].y1,
                 &pixel);
    }

    pixman_region_destroy (rects_as_region);

    if (xoff || yoff)
    {
        for (i = 0; i < nRect; i++)
        {
            rects[i].x += xoff;
            rects[i].y += yoff;
        }
    }
}