PIXMAN_EXPORT void pixman_add_triangles (pixman_image_t *image, int32_t x_off, int32_t y_off, int n_tris, const pixman_triangle_t *tris) { pixman_trapezoid_t *traps; if ((traps = convert_triangles (n_tris, tris))) { pixman_add_trapezoids (image, x_off, y_off, n_tris * 2, traps); free (traps); } }
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; }
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; }