aboutsummaryrefslogtreecommitdiff
path: root/pixman/pixman/pixman-trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman/pixman-trap.c')
-rw-r--r--pixman/pixman/pixman-trap.c132
1 files changed, 86 insertions, 46 deletions
diff --git a/pixman/pixman/pixman-trap.c b/pixman/pixman/pixman-trap.c
index 35128ee3d..ab5c8c895 100644
--- a/pixman/pixman/pixman-trap.c
+++ b/pixman/pixman/pixman-trap.c
@@ -387,18 +387,95 @@ pixman_rasterize_trapezoid (pixman_image_t * image,
}
}
+static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
+{
+ FALSE, /* Clear 0 0 */
+ FALSE, /* Src 1 0 */
+ TRUE, /* Dst 0 1 */
+ TRUE, /* Over 1 1-Aa */
+ TRUE, /* OverReverse 1-Ab 1 */
+ FALSE, /* In Ab 0 */
+ FALSE, /* InReverse 0 Aa */
+ FALSE, /* Out 1-Ab 0 */
+ TRUE, /* OutReverse 0 1-Aa */
+ TRUE, /* Atop Ab 1-Aa */
+ FALSE, /* AtopReverse 1-Ab Aa */
+ TRUE, /* Xor 1-Ab 1-Aa */
+ TRUE, /* Add 1 1 */
+};
+
+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;
+}
+
/*
* 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.
+ * 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,
@@ -439,46 +516,9 @@ pixman_composite_trapezoids (pixman_op_t op,
{
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)
+ int i;
+
+ if (!get_trap_extents (op, dst, traps, n_traps, &box))
return;
tmp = pixman_image_create_bits (