PIXMAN_EXPORT void pixman_add_trapezoids (pixman_image_t * image, int16_t x_off, int y_off, int ntraps, const pixman_trapezoid_t *traps) { int i; #if 0 dump_image (image, "before"); #endif for (i = 0; i < ntraps; ++i) { const pixman_trapezoid_t *trap = &(traps[i]); if (!pixman_trapezoid_valid (trap)) continue; pixman_rasterize_trapezoid (image, trap, x_off, y_off); } #if 0 dump_image (image, "after"); #endif }
PIXMAN_EXPORT void pixman_rasterize_trapezoid (pixman_image_t * image, const pixman_trapezoid_t *trap, int x_off, int y_off) { int bpp; int width; int height; pixman_fixed_t x_off_fixed; pixman_fixed_t y_off_fixed; pixman_edge_t l, r; pixman_fixed_t t, b; return_if_fail (image->type == BITS); _pixman_image_validate (image); if (!pixman_trapezoid_valid (trap)) return; width = image->bits.width; height = image->bits.height; bpp = PIXMAN_FORMAT_BPP (image->bits.format); x_off_fixed = pixman_int_to_fixed (x_off); y_off_fixed = pixman_int_to_fixed (y_off); t = trap->top + y_off_fixed; if (t < 0) t = 0; t = pixman_sample_ceil_y (t, bpp); b = trap->bottom + y_off_fixed; if (pixman_fixed_to_int (b) >= height) b = pixman_int_to_fixed (height) - 1; b = pixman_sample_floor_y (b, bpp); if (b >= t) { /* initialize edge walkers */ pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off); pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); pixman_rasterize_edges (image, &l, &r, t, b); } }
/* * 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); } }
/* * 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 these three images are * composited across the entire 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; return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A); 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; int i; if (!get_trap_extents (op, dst, traps, n_traps, &box)) return; if (!(tmp = pixman_image_create_bits ( mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1))) return; 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; }