aboutsummaryrefslogtreecommitdiff
path: root/pixman/test
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/test')
-rw-r--r--pixman/test/Makefile.am4
-rw-r--r--pixman/test/alphamap.c515
-rw-r--r--pixman/test/radial-test.c198
3 files changed, 458 insertions, 259 deletions
diff --git a/pixman/test/Makefile.am b/pixman/test/Makefile.am
index 71e535374..8d8471d1c 100644
--- a/pixman/test/Makefile.am
+++ b/pixman/test/Makefile.am
@@ -92,6 +92,7 @@ TESTPROGRAMS_GTK = \
clip-in \
composite-test \
gradient-test \
+ radial-test \
alpha-test \
screen-test \
convolution-test \
@@ -102,6 +103,9 @@ INCLUDES += $(GTK_CFLAGS)
gradient_test_LDADD = $(GTK_LDADD)
gradient_test_SOURCES = gradient-test.c $(GTK_UTILS)
+radial_test_LDADD = $(GTK_LDADD)
+radial_test_SOURCES = radial-test.c utils.c utils.h $(GTK_UTILS)
+
alpha_test_LDADD = $(GTK_LDADD)
alpha_test_SOURCES = alpha-test.c $(GTK_UTILS)
diff --git a/pixman/test/alphamap.c b/pixman/test/alphamap.c
index ba3130e5d..554b309fb 100644
--- a/pixman/test/alphamap.c
+++ b/pixman/test/alphamap.c
@@ -1,259 +1,256 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include "utils.h"
-
-#define WIDTH 100
-#define HEIGHT 100
-
-static const pixman_format_code_t formats[] =
-{
- PIXMAN_a8r8g8b8,
- PIXMAN_a2r10g10b10,
- PIXMAN_a4r4g4b4,
- PIXMAN_a8
-};
-
-static const pixman_format_code_t alpha_formats[] =
-{
- PIXMAN_null,
- PIXMAN_a8,
- PIXMAN_a2r10g10b10,
- PIXMAN_a4r4g4b4
-};
-
-static const int origins[] =
-{
- 0, 10, -100
-};
-
-static const char *
-format_name (pixman_format_code_t format)
-{
- if (format == PIXMAN_a8)
- return "a8";
- else if (format == PIXMAN_a2r10g10b10)
- return "a2r10g10b10";
- else if (format == PIXMAN_a8r8g8b8)
- return "a8r8g8b8";
- else if (format == PIXMAN_a4r4g4b4)
- return "a4r4g4b4";
- else if (format == PIXMAN_null)
- return "none";
- else
- assert (0);
-
- return "<unknown - bug in alphamap.c>";
-}
-
-static void
-on_destroy (pixman_image_t *image, void *data)
-{
- uint32_t *bits = pixman_image_get_data (image);
-
- fence_free (bits);
-}
-
-static pixman_image_t *
-make_image (pixman_format_code_t format)
-{
- uint32_t *bits;
- uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
- pixman_image_t *image;
-
- bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
-
- image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
-
- if (image && bits)
- pixman_image_set_destroy_function (image, on_destroy, NULL);
-
- return image;
-}
-
-static pixman_image_t *
-create_image (pixman_format_code_t format, pixman_format_code_t alpha_format,
- int alpha_origin_x, int alpha_origin_y)
-{
- pixman_image_t *image = make_image (format);
-
- if (alpha_format != PIXMAN_null)
- {
- pixman_image_t *alpha = make_image (alpha_format);
-
- pixman_image_set_alpha_map (image, alpha,
- alpha_origin_x, alpha_origin_y);
- pixman_image_unref (alpha);
- }
-
- return image;
-}
-
-static uint8_t
-get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
-{
- uint8_t *bits;
- uint8_t r;
-
- if (image->common.alpha_map)
- {
- if (x - orig_x >= 0 && x - orig_x < WIDTH &&
- y - orig_y >= 0 && y - orig_y < HEIGHT)
- {
- image = (pixman_image_t *)image->common.alpha_map;
-
- x -= orig_x;
- y -= orig_y;
- }
- else
- {
- return 0;
- }
- }
-
- bits = (uint8_t *)image->bits.bits;
-
- if (image->bits.format == PIXMAN_a8)
- {
- r = bits[y * WIDTH + x];
- }
- else if (image->bits.format == PIXMAN_a2r10g10b10)
- {
- r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
- r |= r << 2;
- r |= r << 4;
- }
- else if (image->bits.format == PIXMAN_a8r8g8b8)
- {
- r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
- }
- else if (image->bits.format == PIXMAN_a4r4g4b4)
- {
- r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
- r |= r << 4;
- }
- else
- {
- assert (0);
- }
-
- return r;
-}
-
-#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))
-
-static int
-run_test (int s, int d, int sa, int da, int soff, int doff)
-{
- pixman_format_code_t sf = formats[s];
- pixman_format_code_t df = formats[d];
- pixman_format_code_t saf = alpha_formats[sa];
- pixman_format_code_t daf = alpha_formats[da];
- pixman_image_t *src, *dst, *orig_dst;
- pixman_transform_t t1;
- int j, k;
- int n_alpha_bits;
-
- soff = origins[soff];
- doff = origins[doff];
-
- n_alpha_bits = PIXMAN_FORMAT_A (df);
- if (daf != PIXMAN_null)
- n_alpha_bits = PIXMAN_FORMAT_A (daf);
-
-
- src = create_image (sf, saf, soff, soff);
- orig_dst = create_image (df, daf, doff, doff);
- dst = create_image (df, daf, doff, doff);
-
- /* Transformations on destinations should be ignored, so just set some
- * random one.
- */
- pixman_transform_init_identity (&t1);
- pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
- pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
- pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
-
-#if 0
- /* Unfortunately, this is actually broken at the moment, so we can't
- * actually turn it on
- */
- pixman_image_set_transform (dst, &t1);
-#endif
-
- pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
- 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
-
- pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
- 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
-
- for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j)
- {
- for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
- {
- uint8_t sa, da, oda, ref;
-
- sa = get_alpha (src, k, j, soff, soff);
- da = get_alpha (dst, k, j, doff, doff);
- oda = get_alpha (orig_dst, k, j, doff, doff);
-
- if (sa + oda > 255)
- ref = 255;
- else
- ref = sa + oda;
-
- if (da >> (8 - n_alpha_bits) != ref >> (8 - n_alpha_bits))
- {
- printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
- k, j, ref, da, sa, oda);
-
- printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
- format_name (sf),
- format_name (saf),
- soff, soff,
- format_name (df),
- format_name (daf),
- doff, doff);
- return 1;
- }
- }
- }
-
- pixman_image_set_alpha_map (src, NULL, 0, 0);
- pixman_image_set_alpha_map (dst, NULL, 0, 0);
- pixman_image_set_alpha_map (orig_dst, NULL, 0, 0);
-
- pixman_image_unref (src);
- pixman_image_unref (dst);
- pixman_image_unref (orig_dst);
-
- return 0;
-}
-
-int
-main (int argc, char **argv)
-{
- int i, j, a, b, x, y;
-
- for (i = 0; i < ARRAY_LENGTH (formats); ++i)
- {
- for (j = 0; j < ARRAY_LENGTH (formats); ++j)
- {
- for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a)
- {
- for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b)
- {
- for (x = 0; x < ARRAY_LENGTH (origins); ++x)
- {
- for (y = 0; y < ARRAY_LENGTH (origins); ++y)
- {
- if (run_test (i, j, a, b, x, y) != 0)
- return 1;
- }
- }
- }
- }
- }
- }
-
- return 0;
-}
+#include <stdio.h>
+#include <stdlib.h>
+#include "utils.h"
+
+#define WIDTH 100
+#define HEIGHT 100
+
+static const pixman_format_code_t formats[] =
+{
+ PIXMAN_a8r8g8b8,
+ PIXMAN_a2r10g10b10,
+ PIXMAN_a4r4g4b4,
+ PIXMAN_a8
+};
+
+static const pixman_format_code_t alpha_formats[] =
+{
+ PIXMAN_null,
+ PIXMAN_a8,
+ PIXMAN_a2r10g10b10,
+ PIXMAN_a4r4g4b4
+};
+
+static const int origins[] =
+{
+ 0, 10, -100
+};
+
+static const char *
+format_name (pixman_format_code_t format)
+{
+ if (format == PIXMAN_a8)
+ return "a8";
+ else if (format == PIXMAN_a2r10g10b10)
+ return "a2r10g10b10";
+ else if (format == PIXMAN_a8r8g8b8)
+ return "a8r8g8b8";
+ else if (format == PIXMAN_a4r4g4b4)
+ return "a4r4g4b4";
+ else if (format == PIXMAN_null)
+ return "none";
+ else
+ assert (0);
+
+ return "<unknown - bug in alphamap.c>";
+}
+
+static void
+on_destroy (pixman_image_t *image, void *data)
+{
+ uint32_t *bits = pixman_image_get_data (image);
+
+ fence_free (bits);
+}
+
+static pixman_image_t *
+make_image (pixman_format_code_t format)
+{
+ uint32_t *bits;
+ uint8_t bpp = PIXMAN_FORMAT_BPP (format) / 8;
+ pixman_image_t *image;
+
+ bits = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * bpp);
+
+ image = pixman_image_create_bits (format, WIDTH, HEIGHT, bits, WIDTH * bpp);
+
+ if (image && bits)
+ pixman_image_set_destroy_function (image, on_destroy, NULL);
+
+ return image;
+}
+
+static pixman_image_t *
+create_image (pixman_format_code_t format, pixman_format_code_t alpha_format,
+ int alpha_origin_x, int alpha_origin_y)
+{
+ pixman_image_t *image = make_image (format);
+
+ if (alpha_format != PIXMAN_null)
+ {
+ pixman_image_t *alpha = make_image (alpha_format);
+
+ pixman_image_set_alpha_map (image, alpha,
+ alpha_origin_x, alpha_origin_y);
+ pixman_image_unref (alpha);
+ }
+
+ return image;
+}
+
+static uint8_t
+get_alpha (pixman_image_t *image, int x, int y, int orig_x, int orig_y)
+{
+ uint8_t *bits;
+ uint8_t r;
+
+ if (image->common.alpha_map)
+ {
+ if (x - orig_x >= 0 && x - orig_x < WIDTH &&
+ y - orig_y >= 0 && y - orig_y < HEIGHT)
+ {
+ image = (pixman_image_t *)image->common.alpha_map;
+
+ x -= orig_x;
+ y -= orig_y;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ bits = (uint8_t *)image->bits.bits;
+
+ if (image->bits.format == PIXMAN_a8)
+ {
+ r = bits[y * WIDTH + x];
+ }
+ else if (image->bits.format == PIXMAN_a2r10g10b10)
+ {
+ r = ((uint32_t *)bits)[y * WIDTH + x] >> 30;
+ r |= r << 2;
+ r |= r << 4;
+ }
+ else if (image->bits.format == PIXMAN_a8r8g8b8)
+ {
+ r = ((uint32_t *)bits)[y * WIDTH + x] >> 24;
+ }
+ else if (image->bits.format == PIXMAN_a4r4g4b4)
+ {
+ r = ((uint16_t *)bits)[y * WIDTH + x] >> 12;
+ r |= r << 4;
+ }
+ else
+ {
+ assert (0);
+ }
+
+ return r;
+}
+
+#define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0])))
+
+static int
+run_test (int s, int d, int sa, int da, int soff, int doff)
+{
+ pixman_format_code_t sf = formats[s];
+ pixman_format_code_t df = formats[d];
+ pixman_format_code_t saf = alpha_formats[sa];
+ pixman_format_code_t daf = alpha_formats[da];
+ pixman_image_t *src, *dst, *orig_dst;
+ pixman_transform_t t1;
+ int j, k;
+ int n_alpha_bits;
+
+ soff = origins[soff];
+ doff = origins[doff];
+
+ n_alpha_bits = PIXMAN_FORMAT_A (df);
+ if (daf != PIXMAN_null)
+ n_alpha_bits = PIXMAN_FORMAT_A (daf);
+
+
+ src = create_image (sf, saf, soff, soff);
+ orig_dst = create_image (df, daf, doff, doff);
+ dst = create_image (df, daf, doff, doff);
+
+ /* Transformations, repeats and filters on destinations should be ignored,
+ * so just set some random ones.
+ */
+ pixman_transform_init_identity (&t1);
+ pixman_transform_scale (&t1, NULL, pixman_int_to_fixed (100), pixman_int_to_fixed (11));
+ pixman_transform_rotate (&t1, NULL, pixman_double_to_fixed (0.5), pixman_double_to_fixed (0.11));
+ pixman_transform_translate (&t1, NULL, pixman_int_to_fixed (11), pixman_int_to_fixed (17));
+
+ pixman_image_set_transform (dst, &t1);
+ pixman_image_set_filter (dst, PIXMAN_FILTER_BILINEAR, NULL, 0);
+ pixman_image_set_repeat (dst, PIXMAN_REPEAT_REFLECT);
+
+ pixman_image_composite (PIXMAN_OP_SRC, orig_dst, NULL, dst,
+ 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+ pixman_image_composite (PIXMAN_OP_ADD, src, NULL, dst,
+ 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+
+ for (j = MAX (doff, 0); j < MIN (HEIGHT, HEIGHT + doff); ++j)
+ {
+ for (k = MAX (doff, 0); k < MIN (WIDTH, WIDTH + doff); ++k)
+ {
+ uint8_t sa, da, oda, ref;
+
+ sa = get_alpha (src, k, j, soff, soff);
+ da = get_alpha (dst, k, j, doff, doff);
+ oda = get_alpha (orig_dst, k, j, doff, doff);
+
+ if (sa + oda > 255)
+ ref = 255;
+ else
+ ref = sa + oda;
+
+ if (da >> (8 - n_alpha_bits) != ref >> (8 - n_alpha_bits))
+ {
+ printf ("\nWrong alpha value at (%d, %d). Should be 0x%x; got 0x%x. Source was 0x%x, original dest was 0x%x\n",
+ k, j, ref, da, sa, oda);
+
+ printf ("src: %s, alpha: %s, origin %d %d\ndst: %s, alpha: %s, origin: %d %d\n\n",
+ format_name (sf),
+ format_name (saf),
+ soff, soff,
+ format_name (df),
+ format_name (daf),
+ doff, doff);
+ return 1;
+ }
+ }
+ }
+
+ pixman_image_set_alpha_map (src, NULL, 0, 0);
+ pixman_image_set_alpha_map (dst, NULL, 0, 0);
+ pixman_image_set_alpha_map (orig_dst, NULL, 0, 0);
+
+ pixman_image_unref (src);
+ pixman_image_unref (dst);
+ pixman_image_unref (orig_dst);
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ int i, j, a, b, x, y;
+
+ for (i = 0; i < ARRAY_LENGTH (formats); ++i)
+ {
+ for (j = 0; j < ARRAY_LENGTH (formats); ++j)
+ {
+ for (a = 0; a < ARRAY_LENGTH (alpha_formats); ++a)
+ {
+ for (b = 0; b < ARRAY_LENGTH (alpha_formats); ++b)
+ {
+ for (x = 0; x < ARRAY_LENGTH (origins); ++x)
+ {
+ for (y = 0; y < ARRAY_LENGTH (origins); ++y)
+ {
+ if (run_test (i, j, a, b, x, y) != 0)
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/pixman/test/radial-test.c b/pixman/test/radial-test.c
new file mode 100644
index 000000000..5d716c339
--- /dev/null
+++ b/pixman/test/radial-test.c
@@ -0,0 +1,198 @@
+#include "utils.h"
+#include "gtk-utils.h"
+
+#define NUM_GRADIENTS 7
+#define NUM_STOPS 3
+#define NUM_REPEAT 4
+#define SIZE 128
+#define WIDTH (SIZE * NUM_GRADIENTS)
+#define HEIGHT (SIZE * NUM_REPEAT)
+
+/*
+ * We want to test all the possible relative positions of the start
+ * and end circle:
+ *
+ * - The start circle can be smaller/equal/bigger than the end
+ * circle. A radial gradient can be classified in one of these
+ * three cases depending on the sign of dr.
+ *
+ * - The smaller circle can be completely inside/internally
+ * tangent/outside (at least in part) of the bigger circle. This
+ * classification is the same as the one which can be computed by
+ * examining the sign of a = (dx^2 + dy^2 - dr^2).
+ *
+ * - If the two circles have the same size, neither can be inside or
+ * internally tangent
+ *
+ * This test draws radial gradients whose circles always have the same
+ * centers (0, 0) and (1, 0), but with different radiuses. From left
+ * to right:
+ *
+ * - Small start circle completely inside the end circle
+ * 0.25 -> 1.75; dr = 1.5 > 0; a = 1 - 1.50^2 < 0
+ *
+ * - Small start circle internally tangent to the end circle
+ * 0.50 -> 1.50; dr = 1.0 > 0; a = 1 - 1.00^2 = 0
+ *
+ * - Small start circle outside of the end circle
+ * 0.50 -> 1.00; dr = 0.5 > 0; a = 1 - 0.50^2 > 0
+ *
+ * - Start circle with the same size as the end circle
+ * 1.00 -> 1.00; dr = 0.0 = 0; a = 1 - 0.00^2 > 0
+ *
+ * - Small end circle outside of the start circle
+ * 1.00 -> 0.50; dr = -0.5 > 0; a = 1 - 0.50^2 > 0
+ *
+ * - Small end circle internally tangent to the start circle
+ * 1.50 -> 0.50; dr = -1.0 > 0; a = 1 - 1.00^2 = 0
+ *
+ * - Small end circle completely inside the start circle
+ * 1.75 -> 0.25; dr = -1.5 > 0; a = 1 - 1.50^2 < 0
+ *
+ */
+
+const static double radiuses[NUM_GRADIENTS] = {
+ 0.25,
+ 0.50,
+ 0.50,
+ 1.00,
+ 1.00,
+ 1.50,
+ 1.75
+};
+
+#define double_to_color(x) \
+ (((uint32_t) ((x)*65536)) - (((uint32_t) ((x)*65536)) >> 16))
+
+#define PIXMAN_STOP(offset,r,g,b,a) \
+ { pixman_double_to_fixed (offset), \
+ { \
+ double_to_color (r), \
+ double_to_color (g), \
+ double_to_color (b), \
+ double_to_color (a) \
+ } \
+ }
+
+static const pixman_gradient_stop_t stops[NUM_STOPS] = {
+ PIXMAN_STOP (0.0, 1, 0, 0, 0.75),
+ PIXMAN_STOP (0.70710678, 0, 1, 0, 0),
+ PIXMAN_STOP (1.0, 0, 0, 1, 1)
+};
+
+static pixman_image_t *
+create_radial (int index)
+{
+ pixman_point_fixed_t p0, p1;
+ pixman_fixed_t r0, r1;
+ double x0, x1, radius0, radius1, left, right, center;
+
+ x0 = 0;
+ x1 = 1;
+ radius0 = radiuses[index];
+ radius1 = radiuses[NUM_GRADIENTS - index - 1];
+
+ /* center the gradient */
+ left = MIN (x0 - radius0, x1 - radius1);
+ right = MAX (x0 + radius0, x1 + radius1);
+ center = (left + right) * 0.5;
+ x0 -= center;
+ x1 -= center;
+
+ /* scale to make it fit within a 1x1 rect centered in (0,0) */
+ x0 *= 0.25;
+ x1 *= 0.25;
+ radius0 *= 0.25;
+ radius1 *= 0.25;
+
+ p0.x = pixman_double_to_fixed (x0);
+ p0.y = pixman_double_to_fixed (0);
+
+ p1.x = pixman_double_to_fixed (x1);
+ p1.y = pixman_double_to_fixed (0);
+
+ r0 = pixman_double_to_fixed (radius0);
+ r1 = pixman_double_to_fixed (radius1);
+
+ return pixman_image_create_radial_gradient (&p0, &p1,
+ r0, r1,
+ stops, NUM_STOPS);
+}
+
+static const pixman_repeat_t repeat[NUM_REPEAT] = {
+ PIXMAN_REPEAT_NONE,
+ PIXMAN_REPEAT_NORMAL,
+ PIXMAN_REPEAT_REFLECT,
+ PIXMAN_REPEAT_PAD
+};
+
+int
+main (int argc, char **argv)
+{
+ pixman_transform_t transform;
+ pixman_image_t *src_img, *dest_img;
+ int i, j;
+
+ enable_fp_exceptions ();
+
+ dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
+ WIDTH, HEIGHT,
+ NULL, 0);
+
+ pixman_transform_init_identity (&transform);
+
+ /*
+ * The create_radial() function returns gradients centered in the
+ * origin and whose interesting part fits a 1x1 square. We want to
+ * paint these gradients on a SIZExSIZE square and to make things
+ * easier we want the origin in the top-left corner of the square
+ * we want to see.
+ */
+ pixman_transform_translate (NULL, &transform,
+ pixman_double_to_fixed (0.5),
+ pixman_double_to_fixed (0.5));
+
+ pixman_transform_scale (NULL, &transform,
+ pixman_double_to_fixed (SIZE),
+ pixman_double_to_fixed (SIZE));
+
+ /*
+ * Gradients are evaluated at the center of each pixel, so we need
+ * to translate by half a pixel to trigger some interesting
+ * cornercases. In particular, the original implementation of PDF
+ * radial gradients tried to divide by 0 when using this transform
+ * on the "tangent circles" cases.
+ */
+ pixman_transform_translate (NULL, &transform,
+ pixman_double_to_fixed (0.5),
+ pixman_double_to_fixed (0.5));
+
+ for (i = 0; i < NUM_GRADIENTS; i++)
+ {
+ src_img = create_radial (i);
+ pixman_image_set_transform (src_img, &transform);
+
+ for (j = 0; j < NUM_REPEAT; j++)
+ {
+ pixman_image_set_repeat (src_img, repeat[j]);
+
+ pixman_image_composite32 (PIXMAN_OP_OVER,
+ src_img,
+ NULL,
+ dest_img,
+ 0, 0,
+ 0, 0,
+ i * SIZE, j * SIZE,
+ SIZE, SIZE);
+
+ }
+
+ pixman_image_unref (src_img);
+ }
+
+ show_image (dest_img);
+
+ pixman_image_unref (dest_img);
+
+ return 0;
+}