コード例 #1
0
ファイル: cairo-image-surface.c プロジェクト: soubok/libset
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_code_t	 format;
    uint32_t			*mask_data;
    pixman_trapezoid_t		 stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
    pixman_trapezoid_t		*pixman_traps = stack_traps;
    int				 mask_stride;
    int				 i;

    if (height == 0 || width == 0)
	return CAIRO_STATUS_SUCCESS;

    /* Convert traps to pixman traps */
    if (num_traps > ARRAY_LENGTH (stack_traps)) {
	pixman_traps = _cairo_malloc_ab (num_traps, sizeof (pixman_trapezoid_t));
	if (pixman_traps == NULL)
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    for (i = 0; i < num_traps; i++) {
	pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top);
	pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
	pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
	pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
	pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
	pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
	pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
	pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
	pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
	pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
    }

    /* Special case adding trapezoids onto a mask surface; we want to avoid
     * creating an intermediate temporary mask unnecessarily.
     *
     * 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) &&
	dst->base.content == CAIRO_CONTENT_ALPHA &&
	! dst->has_clip &&
	antialias != CAIRO_ANTIALIAS_NONE)
    {
	pixman_add_trapezoids (dst->pixman_image, 0, 0,
			       num_traps, pixman_traps);
	status = CAIRO_STATUS_SUCCESS;
	goto finish;
    }

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

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

    switch (antialias) {
    case CAIRO_ANTIALIAS_NONE:
	format = PIXMAN_a1;
	mask_stride = ((width + 31) / 8) & ~0x03;
	break;
    case CAIRO_ANTIALIAS_GRAY:
    case CAIRO_ANTIALIAS_SUBPIXEL:
    case CAIRO_ANTIALIAS_DEFAULT:
    default:
	format = PIXMAN_a8;
	mask_stride = (width + 3) & ~3;
	break;
    }

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

    mask = pixman_image_create_bits (format, width, height,
				     mask_data, mask_stride);
    if (mask == NULL) {
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
	goto CLEANUP_IMAGE_DATA;
    }

    pixman_add_trapezoids (mask, - dst_x, - dst_y,
			   num_traps, pixman_traps);

    pixman_image_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_unref (mask);

 CLEANUP_IMAGE_DATA:
    free (mask_data);

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

 finish:
    if (pixman_traps != stack_traps)
	free (pixman_traps);

    return status;
}
コード例 #2
0
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;
}
コード例 #3
0
ファイル: cairo-xynth-surface.c プロジェクト: d33tah/whitix
static cairo_int_status_t _cairo_xynth_surface_composite_trapezoids (cairo_operator_t cairo_operator, cairo_pattern_t *pattern, void *abstract_surface, 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)
{
	int i;
	int mask_bpp;
	int mask_stride;
	s_render_t *mask;
	unsigned char *mask_data;
	cairo_int_status_t status;
	cairo_xynth_surface_t *src;
	cairo_xynth_surface_t *dst;
	s_render_trap_t *render_traps;
	S_RENDER_FORMAT render_format;
	cairo_surface_attributes_t attributes;
	ENTER();
	dst = (cairo_xynth_surface_t *) abstract_surface;
	if (num_traps > 0) {
		render_traps = (s_render_trap_t *) malloc(sizeof(s_render_trap_t) * num_traps);
		if (render_traps == NULL) {
			LEAVE();
			status = CAIRO_STATUS_NO_MEMORY;
			goto out0;
		} 
	} else {
		num_traps = 0;
		render_traps = NULL;
	}
	for (i = 0; i < num_traps; i++) {
		render_traps[i].top = traps[i].top;
		render_traps[i].bottom = traps[i].bottom;
		render_traps[i].left1x = traps[i].left.p1.x;
		render_traps[i].left2x = traps[i].left.p2.x;
		render_traps[i].right1x = traps[i].right.p1.x;
		render_traps[i].right2x = traps[i].right.p2.x;
		render_traps[i].left1y = traps[i].left.p1.y;
		render_traps[i].left2y = traps[i].left.p2.y;
		render_traps[i].right1y = traps[i].right.p1.y;
		render_traps[i].right2y = traps[i].right.p2.y;
	}
	if (cairo_operator == CAIRO_OPERATOR_ADD &&
	    _cairo_pattern_is_opaque_solid (pattern) &&
	    dst->cairo.content == CAIRO_CONTENT_ALPHA &&
	    !dst->render->has_clip &&
	    antialias != CAIRO_ANTIALIAS_NONE) {
		s_render_add_trapezoid(dst->render, 0, 0, num_traps, render_traps);
	    	free(render_traps);
	    	return CAIRO_STATUS_SUCCESS;
	}
	status = _cairo_pattern_acquire_surface(pattern, &dst->cairo, src_x, src_y, width, height, (cairo_surface_t **) &src, &attributes);
	if (status) {
		goto out1;
	}
	status = _cairo_xynth_surface_set_attributes(src, &attributes);
	if (status) {
		goto out2;
	}
	switch (antialias) {
		case CAIRO_ANTIALIAS_NONE:
			render_format = S_RENDER_FORMAT_A1;
			mask_stride = (width + 31) / 8;
			mask_bpp = 1;
			break;
		case CAIRO_ANTIALIAS_GRAY:
		case CAIRO_ANTIALIAS_SUBPIXEL:
		case CAIRO_ANTIALIAS_DEFAULT:
		default:
			render_format = S_RENDER_FORMAT_A8;
			mask_stride = (width + 3) & ~3;
			mask_bpp = 8;
			break;
	}
	mask_data = calloc(1, mask_stride * height);
	if (!mask_data) {
		status = CAIRO_STATUS_NO_MEMORY;
		goto out3;
	}
	s_render_init_for_data(&mask, mask_data, render_format, width, height, mask_bpp, mask_stride);
	s_render_add_trapezoid(mask, - dst_x, - dst_y, num_traps, render_traps);
	s_render_composite(_cairo_xynth_operator(cairo_operator),
	                   src->render,
	                   mask,
	                   dst->render,
	                   src_x + attributes.x_offset,
	                   src_y + attributes.y_offset,
	                   0, 0,
	                   dst_x, dst_y,
	                   width, height);
	if (!_cairo_operator_bounded_by_mask(cairo_operator)) {
		status = _cairo_surface_composite_shape_fixup_unbounded(&dst->cairo,
		                                                        &attributes, src->render->width, src->render->height,
		                                                        width, height,
		                                                        src_x, src_y,
		                                                        0, 0,
		                                                        dst_x, dst_y, width, height);
	}
	s_render_uninit(mask);
out3:	free(mask_data);
out2:	_cairo_pattern_release_surface(pattern, &src->cairo, &attributes);
out1:	free(render_traps);
out0:	LEAVE();
	return 0;
}