summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Knoll <lars@trolltech.com>2006-03-08 06:13:42 +0000
committerLars Knoll <lars@trolltech.com>2006-03-08 06:13:42 +0000
commit00f788fc2785db30ee294281c027f82d09256be6 (patch)
tree0ed69842cb3f85c77c142a33d5f98415fe9691e7
parent4fd03c7cf419c84b8bdfcf25745627659e794300 (diff)
add testing for linear gradients.XORG-7_0_99_901
-rw-r--r--Makefile.am3
-rw-r--r--main.c11
-rw-r--r--rendercheck.h3
-rw-r--r--t_gradient.c238
-rw-r--r--tests.c23
5 files changed, 273 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am
index b326818..41e0957 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,7 +11,8 @@ rendercheck_SOURCES = \
t_dstcoords.c \
t_fill.c \
t_srccoords.c \
- t_tsrccoords.c
+ t_tsrccoords.c \
+ t_gradient.c
INCLUDES = $(RC_CFLAGS)
rendercheck_LDADD = $(RC_LIBS)
diff --git a/main.c b/main.c
index 582e799..ce23e87 100644
--- a/main.c
+++ b/main.c
@@ -104,12 +104,13 @@ describe_format(char *desc, int len, XRenderPictFormat *format)
}
}
-
static void
usage (char *program)
{
fprintf(stderr, "usage: %s [-d|--display display] [-v|--verbose]\n"
- "\t[-t test1,test2,...] [--sync]\n",
+ "\t[-t test1,test2,...] [--sync]\n"
+ "\tAvailable tests: dcoors,scoords,mcoords,tscoords,\n"
+ "\t\ttmcoords,blend,composite,cacomposite,gradients\n",
program);
exit(1);
}
@@ -168,11 +169,13 @@ int main(int argc, char **argv)
enabled_tests |= TEST_COMPOSITE;
} else if (strcmp(test, "cacomposite") == 0) {
enabled_tests |= TEST_CACOMPOSITE;
+ } else if (strcmp(test, "gradients") == 0) {
+ enabled_tests |= TEST_GRADIENTS;
} else {
usage(argv[0]);
}
}
-
+
break;
case 'v':
is_verbose = TRUE;
@@ -243,5 +246,7 @@ int main(int argc, char **argv)
exit(0);
}
}
+
+ XCloseDisplay(dpy);
return 0;
}
diff --git a/rendercheck.h b/rendercheck.h
index 41cb48d..98de62a 100644
--- a/rendercheck.h
+++ b/rendercheck.h
@@ -59,6 +59,7 @@ struct op_info {
#define TEST_BLEND 0x0040
#define TEST_COMPOSITE 0x0080
#define TEST_CACOMPOSITE 0x0100
+#define TEST_GRADIENTS 0x0200
extern int pixmap_move_iter;
extern int win_width, win_height;
@@ -119,3 +120,5 @@ Bool
trans_coords_test(Display *dpy, picture_info *win, picture_info *white,
Bool test_mask);
+Bool linear_gradient_test(Display *dpy, picture_info *win,
+ picture_info *dst, int op, picture_info *dst_color);
diff --git a/t_gradient.c b/t_gradient.c
new file mode 100644
index 0000000..da02724
--- /dev/null
+++ b/t_gradient.c
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include <assert.h>
+#include "rendercheck.h"
+
+typedef struct _stop {
+ double x;
+ color4d color;
+} stop;
+
+static const stop stop_list[][10] = {
+ {
+ { 0., {0, 0, 1.0, 1.0} },
+ { 1., {1.0, 0, 0, 1.0} },
+ { -1, {0, 0, 0, 0} }
+ },
+ {
+ { 0., {0, 0, 1.0, 1.0} },
+ { .5, {0, 1.0, 0, 1.0} },
+ { 1., {1.0, 0, 0, 1.0} },
+ { -1, {0, 0, 0, 0} }
+ },
+ {
+ { 0., {0, 0, 1.0, 0} },
+ { 1., {1.0, 0, 0, 1.0} },
+ { -1, {0, 0, 0, 0} }
+ },
+ {
+ { 0., {0, 0, 1.0, 0} },
+ { .5, {0, 1.0, 0, .75} },
+ { 1., {1.0, 0, 0, .5} },
+ { -1, {0, 0, 0, 0} }
+ }
+};
+const int n_stop_list = sizeof(stop_list)/(10*sizeof(stop));
+
+typedef struct _point {
+ double x;
+ double y;
+} point;
+
+static const point linear_gradient_points[] = {
+ { -5, -5 }, { 5, 5 },
+ { 0, 0 }, { 10, 10 },
+};
+
+typedef struct _pixel {
+ int x;
+ int y;
+} pixel;
+
+static const pixel test_pixels [] = {
+ {0, 0},
+ {0, 5},
+ {5, 0},
+ {5, 5},
+ {3, 7},
+ {7, 3},
+ {20, 20},
+ {30, 13},
+ {39, 39},
+ {-1, -1}
+};
+
+const int n_linear_gradient_points = sizeof(linear_gradient_points)/(2*sizeof(point));
+
+static void gradientPixel(const stop *stops, double pos, unsigned int spread, color4d *result)
+{
+ const int PRECISION = 1<<16;
+ int ipos = pos * PRECISION - 1;
+ int i;
+ double frac;
+
+ /* calculate the actual offset. */
+ if (ipos < 0 || ipos >= PRECISION) {
+ if (spread == RepeatNormal) {
+ ipos = ipos % PRECISION;
+ ipos = ipos < 0 ? PRECISION + ipos : ipos;
+
+ } else if (spread == RepeatReflect) {
+ const int limit = PRECISION * 2 - 1;
+ ipos = ipos % limit;
+ ipos = ipos < 0 ? limit + ipos : ipos;
+ ipos = ipos >= PRECISION ? limit - ipos : ipos;
+
+ } else if (spread == RepeatPad) {
+ if (ipos < 0)
+ ipos = 0;
+ else if (ipos >= PRECISION)
+ ipos = PRECISION-1;
+ } else { /* RepeatNone */
+ result->r = 0;
+ result->g = 0;
+ result->b = 0;
+ result->a = 0;
+ return;
+ }
+ }
+
+ assert(ipos >= 0);
+ assert(ipos < PRECISION);
+
+ pos = ipos/(double)PRECISION;
+
+ if (pos <= stops[0].x) {
+ *result = stops[0].color;
+ return;
+ }
+
+ for (i = 0; i < 10; ++i) {
+ if (stops[i].x >= pos)
+ break;
+ if (stops[i].x < 0) {
+ *result = stops[i-1].color;
+ result->r *= result->a;
+ result->g *= result->a;
+ result->b *= result->a;
+ return;
+ }
+ }
+
+ frac = (pos - stops[i-1].x)/(stops[i].x - stops[i-1].x);
+
+ result->r = (1.-frac)*stops[i-1].color.r + frac*stops[i].color.r;
+ result->g = (1.-frac)*stops[i-1].color.g + frac*stops[i].color.g;
+ result->b = (1.-frac)*stops[i-1].color.b + frac*stops[i].color.b;
+ result->a = (1.-frac)*stops[i-1].color.a + frac*stops[i].color.a;
+
+ result->r *= result->a;
+ result->g *= result->a;
+ result->b *= result->a;
+
+ return;
+}
+
+static void calculate_linear_gradient_color(int x, int y,
+ const point *points,
+ const stop *stops,
+ color4d *tgradient, int repeat)
+{
+ double dx, dy, l, xrel, yrel, pos;
+ dx = points[1].x - points[0].x;
+ dy = points[1].y - points[0].y;
+ l = dx*dx + dy*dy;
+
+ xrel = x - points[0].x;
+ yrel = y - points[0].y;
+
+ pos = (dx*xrel + dy*yrel)/l;
+ gradientPixel(stops, pos, repeat, tgradient);
+}
+
+
+
+Bool linear_gradient_test(Display *dpy, picture_info *win,
+ picture_info *dst, int op, picture_info *dst_color)
+{
+ color4d expected, tested, tdst, tgradient;
+ int i, s, p, repeat;
+ Picture gradient;
+ char testname[40];
+ Bool success = True;
+
+ for (s = 0; s < n_stop_list; ++s) {
+ for (p = 0; p < n_linear_gradient_points; p += 2) {
+ XLinearGradient g;
+ XFixed stops[10];
+ XRenderColor colors[10];
+ const stop *stps = &stop_list[s][0];
+ g.p1.x = XDoubleToFixed(linear_gradient_points[p].x);
+ g.p1.y = XDoubleToFixed(linear_gradient_points[p].y);
+ g.p2.x = XDoubleToFixed(linear_gradient_points[p+1].x);
+ g.p2.y = XDoubleToFixed(linear_gradient_points[p+1].y);
+ for (i = 0; i < 10; ++i) {
+ if (stps[i].x < 0)
+ break;
+ stops[i] = XDoubleToFixed(stps[i].x);
+ colors[i].red = stps[i].color.r*65535;
+ colors[i].green = stps[i].color.g*65535;
+ colors[i].blue = stps[i].color.b*65535;
+ colors[i].alpha = stps[i].color.a*65535;
+ }
+ gradient = XRenderCreateLinearGradient(dpy, &g, stops, colors, i);
+
+ for (repeat = 1; repeat < 4; ++repeat) {
+ const pixel *pix;
+ XRenderPictureAttributes pa;
+ pa.repeat = repeat;
+ XRenderChangePicture(dpy, gradient, CPRepeat, &pa);
+
+ XRenderComposite(dpy, PictOpSrc, dst_color->pict, 0, dst->pict, 0, 0,
+ 0, 0, 0, 0, win_width, win_height);
+ XRenderComposite(dpy, ops[op].op, gradient, 0,
+ dst->pict, 0, 0, 0, 0, 0, 0, win_width, win_height);
+
+ /* Copy the output to the window, so the user sees something visual. */
+ if (win != dst)
+ XRenderComposite(dpy, PictOpSrc, dst->pict, 0, win->pict, 0, 0,
+ 0, 0, 0, 0, win_width, win_height);
+
+ pix = test_pixels;
+ while (pix->x >= 0) {
+
+ get_pixel(dpy, dst, pix->x, pix->y, &tested);
+
+ calculate_linear_gradient_color(pix->x, pix->y, &linear_gradient_points[p],
+ stps, &tgradient, repeat);
+
+ tdst = dst_color->color;
+ color_correct(dst, &tdst);
+ do_composite(ops[op].op, &tgradient, 0, &tdst,
+ &expected, False);
+ color_correct(dst, &expected);
+
+ snprintf(testname, 40, "%s linear gradient", ops[op].name);
+ if (!eval_diff(testname, &expected, &tested, 0, 0, is_verbose)) {
+ printf("gradient: %d stops: %d repeat: %d pos: %d/%d\n"
+ "src color: %.2f %.2f %.2f %.2f\n"
+ "dst color: %.2f %.2f %.2f %.2f\n",
+ p/2, s,
+ repeat, pix->x, pix->y,
+ tgradient.r, tgradient.g,
+ tgradient.b, tgradient.a,
+ dst_color->color.r, dst_color->color.g,
+ dst_color->color.b, dst_color->color.a);
+ success = FALSE;
+ } else if (is_verbose) {
+ printf("src: %d/%d, dst: %s\n", s, p, dst->name);
+ }
+ ++pix;
+ }
+ }
+ XRenderFreePicture(dpy, gradient);
+ }
+ }
+ return success;
+}
+
+
diff --git a/tests.c b/tests.c
index 53b3ec6..58598a3 100644
--- a/tests.c
+++ b/tests.c
@@ -192,7 +192,7 @@ argb_fill(Display *dpy, picture_info *p, int x, int y, int w, int h, float a,
void
begin_test(Display *dpy, picture_info *win)
{
- int i, j, src, dst, mask;
+ int i, j, src, dst = 0, mask;
int num_dests, num_formats;
picture_info *dests, *pictures_1x1, *pictures_10x10, picture_3x3, *pictures_solid;
@@ -459,4 +459,25 @@ begin_test(Display *dpy, picture_info *win)
}
}
}
+
+ if (enabled_tests & TEST_GRADIENTS) {
+ for (i = 0; i < num_ops; i++) {
+ for (j = 0; j <= num_dests; j++) {
+ picture_info *pi;
+
+ if (j != num_dests)
+ pi = &dests[j];
+ else
+ pi = win;
+ printf("Beginning %s linear gradient test on %s\n",
+ ops[i].name, pi->name);
+
+ for (src = 0; src < num_colors; src++) {
+ for (mask = 0; mask < num_colors; mask++) {
+ linear_gradient_test(dpy, win, pi, i, &pictures_1x1[dst]);
+ }
+ }
+ }
+ }
+ }
}