Beispiel #1
0
/*
 * pixman_composite_trapezoids()
 *
 * All the trapezoids are conceptually rendered to an infinitely big image.
 * The (0, 0) coordinates of this image are then aligned with the (x, y)
 * coordinates of the source image, and then both images are aligned with
 * the (x, y) coordinates of the destination. Then, in principle, compositing
 * of these three images takes place across the entire destination.
 *
 * FIXME: However, there is currently a bug, where we restrict this compositing
 * to the bounding box of the trapezoids. This is incorrect for operators such
 * as SRC and IN where blank source pixels do have an effect on the destination.
 */
PIXMAN_EXPORT void
pixman_composite_trapezoids (pixman_op_t		op,
			     pixman_image_t *		src,
			     pixman_image_t *		dst,
			     pixman_format_code_t	mask_format,
			     int			x_src,
			     int			y_src,
			     int			x_dst,
			     int			y_dst,
			     int			n_traps,
			     const pixman_trapezoid_t *	traps)
{
    int i;

    if (n_traps <= 0)
	return;

    _pixman_image_validate (src);
    _pixman_image_validate (dst);

    if (op == PIXMAN_OP_ADD &&
	(src->common.flags & FAST_PATH_IS_OPAQUE)		&&
	(mask_format == dst->common.extended_format_code)	&&
	!(dst->common.have_clip_region))
    {
	for (i = 0; i < n_traps; ++i)
	{
	    const pixman_trapezoid_t *trap = &(traps[i]);
	    
	    if (!pixman_trapezoid_valid (trap))
		continue;
	    
	    pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
	}
    }
    else
    {
	pixman_image_t *tmp;
	pixman_box32_t box;
	
	box.x1 = INT32_MAX;
	box.y1 = INT32_MAX;
	box.x2 = INT32_MIN;
	box.y2 = INT32_MIN;
	
	for (i = 0; i < n_traps; ++i)
	{
	    const pixman_trapezoid_t *trap = &(traps[i]);
	    int y1, y2;
	    
	    if (!pixman_trapezoid_valid (trap))
		continue;
	    
	    y1 = pixman_fixed_to_int (trap->top);
	    if (y1 < box.y1)
		box.y1 = y1;
	    
	    y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
	    if (y2 > box.y2)
		box.y2 = y2;
	    
#define EXTEND_MIN(x)							\
	    if (pixman_fixed_to_int ((x)) < box.x1)			\
		box.x1 = pixman_fixed_to_int ((x));
#define EXTEND_MAX(x)							\
	    if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box.x2)	\
		box.x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
	    
#define EXTEND(x)							\
	    EXTEND_MIN(x);						\
	    EXTEND_MAX(x);
	    
	    EXTEND(trap->left.p1.x);
	    EXTEND(trap->left.p2.x);
	    EXTEND(trap->right.p1.x);
	    EXTEND(trap->right.p2.x);
	}
	
	if (box.x1 >= box.x2 || box.y1 >= box.y2)
	    return;
	
	tmp = pixman_image_create_bits (
	    mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1);
	
	for (i = 0; i < n_traps; ++i)
	{
	    const pixman_trapezoid_t *trap = &(traps[i]);
	    
	    if (!pixman_trapezoid_valid (trap))
		continue;
	    
	    pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1);
	}
	
	pixman_image_composite (op, src, tmp, dst,
				x_src + box.x1, y_src + box.y1,
				0, 0,
				x_dst + box.x1, y_dst + box.y1,
				box.x2 - box.x1, box.y2 - box.y1);
	
	pixman_image_unref (tmp);
    }
}
static pixman_bool_t
get_trap_extents (pixman_op_t op, pixman_image_t *dest,
		  const pixman_trapezoid_t *traps, int n_traps,
		  pixman_box32_t *box)
{
    int i;

    /* When the operator is such that a zero source has an
     * effect on the underlying image, we have to
     * composite across the entire destination
     */
    if (!zero_src_has_no_effect [op])
    {
	box->x1 = 0;
	box->y1 = 0;
	box->x2 = dest->bits.width;
	box->y2 = dest->bits.height;
	return TRUE;
    }
    
    box->x1 = INT32_MAX;
    box->y1 = INT32_MAX;
    box->x2 = INT32_MIN;
    box->y2 = INT32_MIN;
	
    for (i = 0; i < n_traps; ++i)
    {
	const pixman_trapezoid_t *trap = &(traps[i]);
	int y1, y2;
	    
	if (!pixman_trapezoid_valid (trap))
	    continue;
	    
	y1 = pixman_fixed_to_int (trap->top);
	if (y1 < box->y1)
	    box->y1 = y1;
	    
	y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
	if (y2 > box->y2)
	    box->y2 = y2;
	    
#define EXTEND_MIN(x)							\
	if (pixman_fixed_to_int ((x)) < box->x1)			\
	    box->x1 = pixman_fixed_to_int ((x));
#define EXTEND_MAX(x)							\
	if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2)	\
	    box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
	    
#define EXTEND(x)							\
	EXTEND_MIN(x);							\
	EXTEND_MAX(x);
	    
	EXTEND(trap->left.p1.x);
	EXTEND(trap->left.p2.x);
	EXTEND(trap->right.p1.x);
	EXTEND(trap->right.p2.x);
    }
	
    if (box->x1 >= box->x2 || box->y1 >= box->y2)
	return FALSE;

    return TRUE;
}