Beispiel #1
0
static CStatus
CBitmapSurface_Composite(CSurface          *_this,
                         CUInt32            x,
                         CUInt32            y,
                         CUInt32            width,
                         CUInt32            height,
                         pixman_image_t    *src,
                         pixman_image_t    *mask,
                         pixman_operator_t  op)
{
	/* declarations */
	CBitmap *image;

	/* assertions */
	CASSERT((_this != 0));
	CASSERT((src   != 0));
	CASSERT((mask  != 0));

	/* get the image */
	image = ((CBitmapSurface *)_this)->image;

	/* perform the composite synchronously */
	CMutex_Lock(image->lock);
	{
		/* ensure the image data isn't locked */
		if(image->locked)
		{
			CMutex_Unlock(image->lock);
			return CStatus_InvalidOperation_ImageLocked;
		}

		/* perform the composite */
		pixman_composite
			(op, src, mask, image->image, 0, 0, 0, 0, x, y, width, height);
	}
	CMutex_Unlock(image->lock);

	/* return successfully */
	return CStatus_OK;
}
Beispiel #2
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);
}
static cairo_int_status_t
_cairo_image_surface_composite (cairo_operator_t	op,
				cairo_pattern_t		*src_pattern,
				cairo_pattern_t		*mask_pattern,
				void			*abstract_dst,
				int			src_x,
				int			src_y,
				int			mask_x,
				int			mask_y,
				int			dst_x,
				int			dst_y,
				unsigned int		width,
				unsigned int		height)
{
    cairo_surface_attributes_t	src_attr, mask_attr;
    cairo_image_surface_t	*dst = abstract_dst;
    cairo_image_surface_t	*src;
    cairo_image_surface_t	*mask;
    cairo_int_status_t		status;

    status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
					      &dst->base,
					      src_x, src_y,
					      mask_x, mask_y,
					      width, height,
					      (cairo_surface_t **) &src,
					      (cairo_surface_t **) &mask,
					      &src_attr, &mask_attr);
    if (status)
	return status;
    
    status = _cairo_image_surface_set_attributes (src, &src_attr);
    if (status)
      goto CLEANUP_SURFACES;

    if (mask)
    {
	status = _cairo_image_surface_set_attributes (mask, &mask_attr);
	if (status)
	    goto CLEANUP_SURFACES;
	
	pixman_composite (_pixman_operator (op),
			  src->pixman_image,
			  mask->pixman_image,
			  dst->pixman_image,
			  src_x + src_attr.x_offset,
			  src_y + src_attr.y_offset,
			  mask_x + mask_attr.x_offset,
			  mask_y + mask_attr.y_offset,
			  dst_x, dst_y,
			  width, height);
    }
    else
    {
	pixman_composite (_pixman_operator (op),
			  src->pixman_image,
			  NULL,
			  dst->pixman_image,
			  src_x + src_attr.x_offset,
			  src_y + src_attr.y_offset,
			  0, 0,
			  dst_x, dst_y,
			  width, height);
    }
    
    if (!_cairo_operator_bounded_by_source (op))
	status = _cairo_surface_composite_fixup_unbounded (&dst->base,
							   &src_attr, src->width, src->height,
							   mask ? &mask_attr : NULL,
							   mask ? mask->width : 0,
							   mask ? mask->height : 0,
							   src_x, src_y,
							   mask_x, mask_y,
							   dst_x, dst_y, width, height);

 CLEANUP_SURFACES:
    if (mask)
	_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
    
    _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
    
    return status;
}
static cairo_int_status_t
_cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
					   cairo_pattern_t	*pattern,
					   void			*abstract_dst,
					   cairo_antialias_t	antialias,
					   int			src_x,
					   int			src_y,
					   int			dst_x,
					   int			dst_y,
					   unsigned int		width,
					   unsigned int		height,
					   cairo_trapezoid_t	*traps,
					   int			num_traps)
{
    cairo_surface_attributes_t	attributes;
    cairo_image_surface_t	*dst = abstract_dst;
    cairo_image_surface_t	*src;
    cairo_int_status_t		status;
    pixman_image_t		*mask;
    pixman_format_t		*format;
    pixman_bits_t		*mask_data;
    int				mask_stride;
    int				mask_bpp;

    /* Special case adding trapezoids onto a mask surface; we want to avoid
     * creating an intermediate temporary mask unecessarily.
     *
     * We make the assumption here that the portion of the trapezoids
     * contained within the surface is bounded by [dst_x,dst_y,width,height];
     * the Cairo core code passes bounds based on the trapezoid extents.
     *
     * Currently the check surface->has_clip is needed for correct
     * functioning, since pixman_add_trapezoids() doesn't obey the
     * surface clip, which is a libpixman bug , but there's no harm in
     * falling through to the general case when the surface is clipped
     * since libpixman would have to generate an intermediate mask anyways.
     */
    if (op == CAIRO_OPERATOR_ADD &&
	_cairo_pattern_is_opaque_solid (pattern) &&
	_cairo_image_surface_is_alpha_only (dst) &&
	!dst->has_clip &&
	antialias != CAIRO_ANTIALIAS_NONE)
    {
	pixman_add_trapezoids (dst->pixman_image, 0, 0,
			       (pixman_trapezoid_t *) traps, num_traps);
	return CAIRO_STATUS_SUCCESS;
    }

    status = _cairo_pattern_acquire_surface (pattern, &dst->base,
					     src_x, src_y, width, height,
					     (cairo_surface_t **) &src,
					     &attributes);
    if (status)
	return status;

    status = _cairo_image_surface_set_attributes (src, &attributes);
    if (status)
	goto CLEANUP_SOURCE;

    switch (antialias) {
    case CAIRO_ANTIALIAS_NONE:
	format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
	mask_stride = (width + 31)/8;
	mask_bpp = 1;
 	break;
    default:
	format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
	mask_stride = (width + 3) & ~3;
	mask_bpp = 8;
 	break;
    }
    if (!format) {
	status = CAIRO_STATUS_NO_MEMORY;
	goto CLEANUP_SOURCE;
    }

    /* The image must be initially transparent */
    mask_data = calloc (1, mask_stride * height);
    if (!mask_data) {
	status = CAIRO_STATUS_NO_MEMORY;
	pixman_format_destroy (format);
	goto CLEANUP_SOURCE;
    }

    mask = pixman_image_create_for_data (mask_data, format, width, height,
					 mask_bpp, mask_stride);
    pixman_format_destroy (format);
    if (!mask) {
	status = CAIRO_STATUS_NO_MEMORY;
	goto CLEANUP_IMAGE_DATA;
    }

    /* XXX: The pixman_trapezoid_t cast is evil and needs to go away
     * somehow. */
    pixman_add_trapezoids (mask, - dst_x, - dst_y,
			   (pixman_trapezoid_t *) traps, num_traps);

    pixman_composite (_pixman_operator (op),
		      src->pixman_image,
		      mask,
		      dst->pixman_image,
		      src_x + attributes.x_offset,
		      src_y + attributes.y_offset,
		      0, 0,
		      dst_x, dst_y,
		      width, height);

    if (!_cairo_operator_bounded_by_mask (op))
	status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
								 &attributes, src->width, src->height,
								 width, height,
								 src_x, src_y,
								 0, 0,
								 dst_x, dst_y, width, height);
    pixman_image_destroy (mask);

 CLEANUP_IMAGE_DATA:
    free (mask_data);

 CLEANUP_SOURCE:
    _cairo_pattern_release_surface (pattern, &src->base, &attributes);

    return status;
}
void
pixman_fill_rectangles (pixman_operator_t		op,
                        pixman_image_t		*dst,
                        const pixman_color_t		*color,
                        const pixman_rectangle_t	*rects,
                        int			nRects)
{
    pixman_color_t color_s = *color;

    if (color_s.alpha == 0xffff)
    {
        if (op == PIXMAN_OPERATOR_OVER)
            op = PIXMAN_OPERATOR_SRC;
    }
    if (op == PIXMAN_OPERATOR_CLEAR)
        color_s.red = color_s.green = color_s.blue = color_s.alpha = 0;

    if (op == PIXMAN_OPERATOR_SRC || op == PIXMAN_OPERATOR_CLEAR)
    {
        /* We cast away the constness of rects here, because pixman_color_rects
        temporarily modifies it */
        pixman_color_rects (dst, dst, &color_s, nRects, (pixman_rectangle_t *)rects, 0, 0);
        if (dst->alphaMap)
            pixman_color_rects (dst->alphaMap, dst,
                                &color_s, nRects, (pixman_rectangle_t *)rects,
                                dst->alphaOrigin.x,
                                dst->alphaOrigin.y);
    }
    else
    {
        pixman_format_t	rgbaFormat;
        FbPixels	*pixels;
        pixman_image_t		*src;
        pixman_bits_t		pixel;

        pixman_format_init (&rgbaFormat, PICT_a8r8g8b8);

        pixels = FbPixelsCreate (1, 1, rgbaFormat.depth);
        if (!pixels)
            goto bail1;

        pixman_color_to_pixel (&rgbaFormat, &color_s, &pixel);

        /* XXX: Originally, fb had the following:

           (*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one);

           I haven't checked to see what I might be breaking with a
           trivial assignment instead.
        */
        pixels->data[0] = pixel;

        src = pixman_image_createForPixels (pixels, &rgbaFormat);
        if (!src)
            goto bail2;

        pixman_image_set_repeat (src, 1);

        while (nRects--)
        {
            pixman_composite (op, src, NULL, dst, 0, 0, 0, 0,
                              rects->x,
                              rects->y,
                              rects->width,
                              rects->height);
            rects++;
        }

        pixman_image_destroy (src);
bail2:
        FbPixelsDestroy (pixels);
bail1:
        ;
    }
}