diff options
Diffstat (limited to 'test')
33 files changed, 1384 insertions, 162 deletions
diff --git a/test/.cvsignore b/test/.cvsignore index 27e57c1d..6194e267 100644 --- a/test/.cvsignore +++ b/test/.cvsignore @@ -2,12 +2,16 @@ .libs Makefile Makefile.in +coverage fill_rule +imagediff leaky_polygon line_width move_to_show_surface +pixman_rotate text_cache_crash text_rotate +clip_twice *-out.png *-diff.png diff --git a/test/Makefile.am b/test/Makefile.am index e7fd3fd6..04d42e2d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,18 +3,27 @@ TESTS = \ fill_rule \ leaky_polygon \ line_width \ +linear_gradient \ move_to_show_surface \ text_cache_crash \ -text_rotate +text_rotate \ +coverage \ +clip_twice \ +pixman_rotate -# And all new test go here too. I really don't like having to repeat +# And all new tests go here too. I really don't like having to repeat # this list. Anyone know a good way to avoid it? Can I use a wildcard # here? -EXTRA_DIST = \ -fill_rule-ref.png \ -leaky_polygon-ref.png \ -line_width-ref.png \ -move_to_show_surface-ref.png +EXTRA_DIST = \ +fill_rule-ref.png \ +leaky_polygon-ref.png \ +line_width-ref.png \ +linear_gradient-ref.png \ +move_to_show_surface-ref.png \ +coverage-ref.png \ +clip_twice-ref.png \ +pixman_rotate-ref.png \ +romedalen.png # Once we can draw the text_rotate.c test case correctly, we should # create and add text_rotate-ref.png to the list of reference PNGs. @@ -29,6 +38,7 @@ move_to_show_surface-ref.png # be fixed before the code is committed. XFAIL_TESTS = \ move_to_show_surface \ +pixman_rotate \ text_rotate check_PROGRAMS = $(TESTS) @@ -42,6 +52,8 @@ INCLUDES = -D_GNU_SOURCE -I$(srcdir) $(CAIRO_CFLAGS) -I$(srcdir)/../src AM_LDFLAGS = $(CAIRO_LIBS) ../src/libcairo.la cairo_test_lib =\ +buffer_diff.c \ +buffer_diff.h \ cairo_test.c \ cairo_test.h \ read_png.c \ @@ -57,8 +69,15 @@ xmalloc.h fill_rule_SOURCES = fill_rule.c $(cairo_test_lib) leaky_polygon_SOURCES = leaky_polygon.c $(cairo_test_lib) line_width_SOURCES = line_width.c $(cairo_test_lib) +linear_gradient_SOURCES = linear_gradient.c $(cairo_test_lib) move_to_show_surface_SOURCES = move_to_show_surface.c $(cairo_test_lib) text_cache_crash_SOURCES = text_cache_crash.c $(cairo_test_lib) text_rotate_SOURCES = text_rotate.c $(cairo_test_lib) +coverage_SOURCES = coverage.c $(cairo_test_lib) +clip_twice_SOURCES = clip_twice.c $(cairo_test_lib) +pixman_rotate_SOURCES = pixman_rotate.c $(cairo_test_lib) + +noinst_PROGRAMS = imagediff +imagediff_SOURCES = imagediff.c $(cairo_test_lib) -CLEANFILES = *-out.png *-diff.png +CLEANFILES = *-out.png *-diff.png *.log diff --git a/test/buffer-diff.c b/test/buffer-diff.c new file mode 100644 index 00000000..07abd62a --- /dev/null +++ b/test/buffer-diff.c @@ -0,0 +1,73 @@ +/* imagediff - Compare two images + * + * Copyright © 2004 Richard D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Richard Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Richard Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * RICHARD WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RICHARD WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Richard D. Worth <richard@theworths.org> */ + +#include "buffer_diff.h" + +/* Image comparison code courttesy of Richard Worth. + * Returns number of pixels changed. + * Also fills out a "diff" image intended to visually show where the + * images differ. + */ +int +buffer_diff (char *buf_a, char *buf_b, char *buf_diff, + int width, int height, int stride) +{ + int x, y; + int total_pixels_changed = 0; + unsigned char *row_a, *row_b, *row; + + for (y = 0; y < height; y++) + { + row_a = buf_a + y * stride; + row_b = buf_b + y * stride; + row = buf_diff + y * stride; + for (x = 0; x < width; x++) + { + int channel; + unsigned char value_a, value_b; + int pixel_changed = 0; + for (channel = 0; channel < 4; channel++) + { + double diff; + value_a = row_a[x * 4 + channel]; + value_b = row_b[x * 4 + channel]; + if (value_a != value_b) + pixel_changed = 1; + diff = value_a - value_b; + row[x * 4 + channel] = 128 + diff / 3.0; + } + if (pixel_changed) { + total_pixels_changed++; + } else { + row[x*4+0] = 0; + row[x*4+1] = 0; + row[x*4+2] = 0; + } + row[x * 4 + 3] = 0xff; /* Set ALPHA to 100% (opaque) */ + } + } + + return total_pixels_changed; +} diff --git a/test/buffer-diff.h b/test/buffer-diff.h new file mode 100644 index 00000000..9ee51c3c --- /dev/null +++ b/test/buffer-diff.h @@ -0,0 +1,38 @@ +/* imagediff - Compare two images + * + * Copyright © 2004 Richard D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Richard Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Richard Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * RICHARD WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RICHARD WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Richard D. Worth <richard@theworths.org> */ + +#ifndef BUFFER_DIFF_H +#define BUFFER_DIFF_H + +/* Image comparison code courttesy of Richard Worth. + * Returns number of pixels changed. + * Also fills out a "diff" image intended to visually show where the + * images differ. + */ +int +buffer_diff (char *buf_a, char *buf_b, char *buf_diff, + int width, int height, int stride); + +#endif diff --git a/test/buffer_diff.c b/test/buffer_diff.c new file mode 100644 index 00000000..07abd62a --- /dev/null +++ b/test/buffer_diff.c @@ -0,0 +1,73 @@ +/* imagediff - Compare two images + * + * Copyright © 2004 Richard D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Richard Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Richard Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * RICHARD WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RICHARD WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Richard D. Worth <richard@theworths.org> */ + +#include "buffer_diff.h" + +/* Image comparison code courttesy of Richard Worth. + * Returns number of pixels changed. + * Also fills out a "diff" image intended to visually show where the + * images differ. + */ +int +buffer_diff (char *buf_a, char *buf_b, char *buf_diff, + int width, int height, int stride) +{ + int x, y; + int total_pixels_changed = 0; + unsigned char *row_a, *row_b, *row; + + for (y = 0; y < height; y++) + { + row_a = buf_a + y * stride; + row_b = buf_b + y * stride; + row = buf_diff + y * stride; + for (x = 0; x < width; x++) + { + int channel; + unsigned char value_a, value_b; + int pixel_changed = 0; + for (channel = 0; channel < 4; channel++) + { + double diff; + value_a = row_a[x * 4 + channel]; + value_b = row_b[x * 4 + channel]; + if (value_a != value_b) + pixel_changed = 1; + diff = value_a - value_b; + row[x * 4 + channel] = 128 + diff / 3.0; + } + if (pixel_changed) { + total_pixels_changed++; + } else { + row[x*4+0] = 0; + row[x*4+1] = 0; + row[x*4+2] = 0; + } + row[x * 4 + 3] = 0xff; /* Set ALPHA to 100% (opaque) */ + } + } + + return total_pixels_changed; +} diff --git a/test/buffer_diff.h b/test/buffer_diff.h new file mode 100644 index 00000000..9ee51c3c --- /dev/null +++ b/test/buffer_diff.h @@ -0,0 +1,38 @@ +/* imagediff - Compare two images + * + * Copyright © 2004 Richard D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Richard Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Richard Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * RICHARD WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RICHARD WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Richard D. Worth <richard@theworths.org> */ + +#ifndef BUFFER_DIFF_H +#define BUFFER_DIFF_H + +/* Image comparison code courttesy of Richard Worth. + * Returns number of pixels changed. + * Also fills out a "diff" image intended to visually show where the + * images differ. + */ +int +buffer_diff (char *buf_a, char *buf_b, char *buf_diff, + int width, int height, int stride); + +#endif diff --git a/test/cairo-test.c b/test/cairo-test.c index 2364570a..06f7672f 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -32,10 +32,12 @@ #include "cairo_test.h" +#include "buffer_diff.h" #include "read_png.h" #include "write_png.h" #include "xmalloc.h" +#define CAIRO_TEST_LOG_SUFFIX ".log" #define CAIRO_TEST_PNG_SUFFIX "-out.png" #define CAIRO_TEST_REF_SUFFIX "-ref.png" #define CAIRO_TEST_DIFF_SUFFIX "-diff.png" @@ -43,9 +45,10 @@ static void xasprintf (char **strp, const char *fmt, ...) { +#ifdef HAVE_VASPRINTF va_list va; int ret; - + va_start (va, fmt); ret = vasprintf (strp, fmt, va); va_end (va); @@ -54,53 +57,42 @@ xasprintf (char **strp, const char *fmt, ...) fprintf (stderr, "Out of memory\n"); exit (1); } +#else /* !HAVE_VASNPRINTF */ +#define BUF_SIZE 1024 + va_list va; + char buffer[BUF_SIZE]; + int ret; + + va_start (va, fmt); + ret = vsnprintf (buffer, sizeof(buffer), fmt, va); + va_end (va); + + if (ret < 0) { + fprintf (stderr, "Failure in vsnprintf\n"); + exit (1); + } + + if (strlen (buffer) == sizeof(buffer) - 1) { + fprintf (stderr, "Overflowed fixed buffer\n"); + exit (1); + } + + *strp = strdup (buffer); + if (!*strp) { + fprintf (stderr, "Out of memory\n"); + exit (1); + } +#endif /* !HAVE_VASNPRINTF */ } -/* Image comparison code courttesy of Richard Worth. - * Returns number of pixels changed. - * Also fills out a "diff" image intended to visually show where the - * images differ. - */ -static int -image_diff (char *buf_a, char *buf_b, char *buf_diff, - int width, int height, int stride) +static void +xunlink (const char *pathname) { - int x, y; - int total_pixels_changed = 0; - unsigned char *row_a, *row_b, *row; - - for (y = 0; y < height; y++) - { - row_a = buf_a + y * stride; - row_b = buf_b + y * stride; - row = buf_diff + y * stride; - for (x = 0; x < width; x++) - { - int channel; - unsigned char value_a, value_b; - int pixel_changed = 0; - for (channel = 0; channel < 4; channel++) - { - double diff; - value_a = row_a[x * 4 + channel]; - value_b = row_b[x * 4 + channel]; - if (value_a != value_b) - pixel_changed = 1; - diff = value_a - value_b; - row[x * 4 + channel] = 128 + diff / 3.0; - } - if (pixel_changed) { - total_pixels_changed++; - } else { - row[x*4+0] = 0; - row[x*4+1] = 0; - row[x*4+2] = 0; - } - row[x * 4 + 3] = 0xff; /* Set ALPHA to 100% (opaque) */ - } + if (unlink (pathname) < 0 && errno != ENOENT) { + fprintf (stderr, " Error: Cannot remove %s: %s\n", + pathname, strerror (errno)); + exit (1); } - - return total_pixels_changed; } cairo_test_status_t @@ -109,12 +101,14 @@ cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw) cairo_t *cr; int stride; unsigned char *png_buf, *ref_buf, *diff_buf; - char *png_name, *ref_name, *diff_name; + char *log_name, *png_name, *ref_name, *diff_name; char *srcdir; int pixels_changed; int ref_width, ref_height, ref_stride; read_png_status_t png_status; cairo_test_status_t ret; + FILE *png_file; + FILE *log_file; /* The cairo part of the test is the easiest part */ cr = cairo_create (); @@ -142,57 +136,68 @@ cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw) srcdir = getenv ("srcdir"); if (!srcdir) srcdir = "."; + xasprintf (&log_name, "%s%s", test->name, CAIRO_TEST_LOG_SUFFIX); xasprintf (&png_name, "%s%s", test->name, CAIRO_TEST_PNG_SUFFIX); xasprintf (&ref_name, "%s/%s%s", srcdir, test->name, CAIRO_TEST_REF_SUFFIX); xasprintf (&diff_name, "%s%s", test->name, CAIRO_TEST_DIFF_SUFFIX); - write_png_argb32 (png_buf, png_name, test->width, test->height, stride); + png_file = fopen (png_name, "w"); + write_png_argb32 (png_buf, png_file, test->width, test->height, stride); + fclose (png_file); + + xunlink (log_name); ref_buf = NULL; png_status = (read_png_argb32 (ref_name, &ref_buf, &ref_width, &ref_height, &ref_stride)); if (png_status) { + log_file = fopen (log_name, "a"); switch (png_status) { case READ_PNG_FILE_NOT_FOUND: - fprintf (stderr, " Error: No reference image found: %s\n", ref_name); + fprintf (log_file, "Error: No reference image found: %s\n", ref_name); break; case READ_PNG_FILE_NOT_PNG: - fprintf (stderr, " Error: %s is not a png image\n", ref_name); + fprintf (log_file, "Error: %s is not a png image\n", ref_name); break; default: - fprintf (stderr, " Error: Failed to read %s\n", ref_name); + fprintf (log_file, "Error: Failed to read %s\n", ref_name); } + fclose (log_file); ret = CAIRO_TEST_FAILURE; goto BAIL; + } else { } if (test->width != ref_width || test->height != ref_height) { - fprintf (stderr, - " Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n" - " for %s vs %s\n", + log_file = fopen (log_name, "a"); + fprintf (log_file, + "Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n" + " for %s vs %s\n", test->width, test->height, ref_width, ref_height, png_name, ref_name); + fclose (log_file); + ret = CAIRO_TEST_FAILURE; goto BAIL; } - pixels_changed = image_diff (png_buf, ref_buf, diff_buf, - test->width, test->height, stride); + pixels_changed = buffer_diff (png_buf, ref_buf, diff_buf, + test->width, test->height, stride); if (pixels_changed) { - fprintf (stderr, " Error: %d pixels differ from reference image %s\n", + log_file = fopen (log_name, "a"); + fprintf (log_file, "Error: %d pixels differ from reference image %s\n", pixels_changed, ref_name); - write_png_argb32 (diff_buf, diff_name, test->width, test->height, stride); + png_file = fopen (diff_name, "w"); + write_png_argb32 (diff_buf, png_file, test->width, test->height, stride); + fclose (png_file); + fclose (log_file); + ret = CAIRO_TEST_FAILURE; goto BAIL; } else { - if (unlink (diff_name) < 0 && errno != ENOENT) { - fprintf (stderr, " Error: Cannot remove %s: %s\n", - diff_name, strerror (errno)); - ret = CAIRO_TEST_FAILURE; - goto BAIL; - } + xunlink (diff_name); } ret = CAIRO_TEST_SUCCESS; @@ -201,9 +206,42 @@ BAIL: free (png_buf); free (ref_buf); free (diff_buf); + free (log_name); free (png_name); free (ref_name); free (diff_name); return ret; } + +cairo_pattern_t * +cairo_test_create_png_pattern (cairo_t *cr, const char *filename) +{ + cairo_surface_t *image; + cairo_pattern_t *pattern; + unsigned char *buffer; + int w, h, stride; + read_png_status_t status; + char *srcdir = getenv ("srcdir"); + + status = read_png_argb32 (filename, &buffer, &w,&h, &stride); + if (status != READ_PNG_SUCCESS) { + if (srcdir) { + char *srcdir_filename; + xasprintf (&srcdir_filename, "%s/%s", srcdir, filename); + status = read_png_argb32 (srcdir_filename, &buffer, &w,&h, &stride); + free (srcdir_filename); + } + } + if (status != READ_PNG_SUCCESS) + return NULL; + + image = cairo_surface_create_for_image (buffer, CAIRO_FORMAT_ARGB32, + w, h, stride); + + cairo_surface_set_repeat (image, 1); + + pattern = cairo_pattern_create_for_surface (image); + + return pattern; +} diff --git a/test/cairo-test.h b/test/cairo-test.h index 58936d56..912ce891 100644 --- a/test/cairo-test.h +++ b/test/cairo-test.h @@ -47,5 +47,9 @@ typedef void (*cairo_test_draw_function_t) (cairo_t *cr, int width, int height) cairo_test_status_t cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw); +cairo_pattern_t * +cairo_test_create_png_pattern (cairo_t *cr, const char *filename); + + #endif diff --git a/test/cairo_test.c b/test/cairo_test.c index 2364570a..06f7672f 100644 --- a/test/cairo_test.c +++ b/test/cairo_test.c @@ -32,10 +32,12 @@ #include "cairo_test.h" +#include "buffer_diff.h" #include "read_png.h" #include "write_png.h" #include "xmalloc.h" +#define CAIRO_TEST_LOG_SUFFIX ".log" #define CAIRO_TEST_PNG_SUFFIX "-out.png" #define CAIRO_TEST_REF_SUFFIX "-ref.png" #define CAIRO_TEST_DIFF_SUFFIX "-diff.png" @@ -43,9 +45,10 @@ static void xasprintf (char **strp, const char *fmt, ...) { +#ifdef HAVE_VASPRINTF va_list va; int ret; - + va_start (va, fmt); ret = vasprintf (strp, fmt, va); va_end (va); @@ -54,53 +57,42 @@ xasprintf (char **strp, const char *fmt, ...) fprintf (stderr, "Out of memory\n"); exit (1); } +#else /* !HAVE_VASNPRINTF */ +#define BUF_SIZE 1024 + va_list va; + char buffer[BUF_SIZE]; + int ret; + + va_start (va, fmt); + ret = vsnprintf (buffer, sizeof(buffer), fmt, va); + va_end (va); + + if (ret < 0) { + fprintf (stderr, "Failure in vsnprintf\n"); + exit (1); + } + + if (strlen (buffer) == sizeof(buffer) - 1) { + fprintf (stderr, "Overflowed fixed buffer\n"); + exit (1); + } + + *strp = strdup (buffer); + if (!*strp) { + fprintf (stderr, "Out of memory\n"); + exit (1); + } +#endif /* !HAVE_VASNPRINTF */ } -/* Image comparison code courttesy of Richard Worth. - * Returns number of pixels changed. - * Also fills out a "diff" image intended to visually show where the - * images differ. - */ -static int -image_diff (char *buf_a, char *buf_b, char *buf_diff, - int width, int height, int stride) +static void +xunlink (const char *pathname) { - int x, y; - int total_pixels_changed = 0; - unsigned char *row_a, *row_b, *row; - - for (y = 0; y < height; y++) - { - row_a = buf_a + y * stride; - row_b = buf_b + y * stride; - row = buf_diff + y * stride; - for (x = 0; x < width; x++) - { - int channel; - unsigned char value_a, value_b; - int pixel_changed = 0; - for (channel = 0; channel < 4; channel++) - { - double diff; - value_a = row_a[x * 4 + channel]; - value_b = row_b[x * 4 + channel]; - if (value_a != value_b) - pixel_changed = 1; - diff = value_a - value_b; - row[x * 4 + channel] = 128 + diff / 3.0; - } - if (pixel_changed) { - total_pixels_changed++; - } else { - row[x*4+0] = 0; - row[x*4+1] = 0; - row[x*4+2] = 0; - } - row[x * 4 + 3] = 0xff; /* Set ALPHA to 100% (opaque) */ - } + if (unlink (pathname) < 0 && errno != ENOENT) { + fprintf (stderr, " Error: Cannot remove %s: %s\n", + pathname, strerror (errno)); + exit (1); } - - return total_pixels_changed; } cairo_test_status_t @@ -109,12 +101,14 @@ cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw) cairo_t *cr; int stride; unsigned char *png_buf, *ref_buf, *diff_buf; - char *png_name, *ref_name, *diff_name; + char *log_name, *png_name, *ref_name, *diff_name; char *srcdir; int pixels_changed; int ref_width, ref_height, ref_stride; read_png_status_t png_status; cairo_test_status_t ret; + FILE *png_file; + FILE *log_file; /* The cairo part of the test is the easiest part */ cr = cairo_create (); @@ -142,57 +136,68 @@ cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw) srcdir = getenv ("srcdir"); if (!srcdir) srcdir = "."; + xasprintf (&log_name, "%s%s", test->name, CAIRO_TEST_LOG_SUFFIX); xasprintf (&png_name, "%s%s", test->name, CAIRO_TEST_PNG_SUFFIX); xasprintf (&ref_name, "%s/%s%s", srcdir, test->name, CAIRO_TEST_REF_SUFFIX); xasprintf (&diff_name, "%s%s", test->name, CAIRO_TEST_DIFF_SUFFIX); - write_png_argb32 (png_buf, png_name, test->width, test->height, stride); + png_file = fopen (png_name, "w"); + write_png_argb32 (png_buf, png_file, test->width, test->height, stride); + fclose (png_file); + + xunlink (log_name); ref_buf = NULL; png_status = (read_png_argb32 (ref_name, &ref_buf, &ref_width, &ref_height, &ref_stride)); if (png_status) { + log_file = fopen (log_name, "a"); switch (png_status) { case READ_PNG_FILE_NOT_FOUND: - fprintf (stderr, " Error: No reference image found: %s\n", ref_name); + fprintf (log_file, "Error: No reference image found: %s\n", ref_name); break; case READ_PNG_FILE_NOT_PNG: - fprintf (stderr, " Error: %s is not a png image\n", ref_name); + fprintf (log_file, "Error: %s is not a png image\n", ref_name); break; default: - fprintf (stderr, " Error: Failed to read %s\n", ref_name); + fprintf (log_file, "Error: Failed to read %s\n", ref_name); } + fclose (log_file); ret = CAIRO_TEST_FAILURE; goto BAIL; + } else { } if (test->width != ref_width || test->height != ref_height) { - fprintf (stderr, - " Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n" - " for %s vs %s\n", + log_file = fopen (log_name, "a"); + fprintf (log_file, + "Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n" + " for %s vs %s\n", test->width, test->height, ref_width, ref_height, png_name, ref_name); + fclose (log_file); + ret = CAIRO_TEST_FAILURE; goto BAIL; } - pixels_changed = image_diff (png_buf, ref_buf, diff_buf, - test->width, test->height, stride); + pixels_changed = buffer_diff (png_buf, ref_buf, diff_buf, + test->width, test->height, stride); if (pixels_changed) { - fprintf (stderr, " Error: %d pixels differ from reference image %s\n", + log_file = fopen (log_name, "a"); + fprintf (log_file, "Error: %d pixels differ from reference image %s\n", pixels_changed, ref_name); - write_png_argb32 (diff_buf, diff_name, test->width, test->height, stride); + png_file = fopen (diff_name, "w"); + write_png_argb32 (diff_buf, png_file, test->width, test->height, stride); + fclose (png_file); + fclose (log_file); + ret = CAIRO_TEST_FAILURE; goto BAIL; } else { - if (unlink (diff_name) < 0 && errno != ENOENT) { - fprintf (stderr, " Error: Cannot remove %s: %s\n", - diff_name, strerror (errno)); - ret = CAIRO_TEST_FAILURE; - goto BAIL; - } + xunlink (diff_name); } ret = CAIRO_TEST_SUCCESS; @@ -201,9 +206,42 @@ BAIL: free (png_buf); free (ref_buf); free (diff_buf); + free (log_name); free (png_name); free (ref_name); free (diff_name); return ret; } + +cairo_pattern_t * +cairo_test_create_png_pattern (cairo_t *cr, const char *filename) +{ + cairo_surface_t *image; + cairo_pattern_t *pattern; + unsigned char *buffer; + int w, h, stride; + read_png_status_t status; + char *srcdir = getenv ("srcdir"); + + status = read_png_argb32 (filename, &buffer, &w,&h, &stride); + if (status != READ_PNG_SUCCESS) { + if (srcdir) { + char *srcdir_filename; + xasprintf (&srcdir_filename, "%s/%s", srcdir, filename); + status = read_png_argb32 (srcdir_filename, &buffer, &w,&h, &stride); + free (srcdir_filename); + } + } + if (status != READ_PNG_SUCCESS) + return NULL; + + image = cairo_surface_create_for_image (buffer, CAIRO_FORMAT_ARGB32, + w, h, stride); + + cairo_surface_set_repeat (image, 1); + + pattern = cairo_pattern_create_for_surface (image); + + return pattern; +} diff --git a/test/cairo_test.h b/test/cairo_test.h index 58936d56..912ce891 100644 --- a/test/cairo_test.h +++ b/test/cairo_test.h @@ -47,5 +47,9 @@ typedef void (*cairo_test_draw_function_t) (cairo_t *cr, int width, int height) cairo_test_status_t cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw); +cairo_pattern_t * +cairo_test_create_png_pattern (cairo_t *cr, const char *filename); + + #endif diff --git a/test/clip-twice-ref.png b/test/clip-twice-ref.png Binary files differnew file mode 100644 index 00000000..ab0ae1ae --- /dev/null +++ b/test/clip-twice-ref.png diff --git a/test/clip-twice.c b/test/clip-twice.c new file mode 100644 index 00000000..00215e62 --- /dev/null +++ b/test/clip-twice.c @@ -0,0 +1,72 @@ +/* + * Copyright © 2005 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Kristian Høgsberg <krh@redhat.com> + */ + +#include "cairo_test.h" + +#define WIDTH 64 +#define HEIGHT 64 + +cairo_test_t test = { + "clip_twice", + "Verifies that the clip mask is updated correctly when it constructed by setting the clip path twice.", + WIDTH, HEIGHT +}; + +static void +draw (cairo_t *cr, int width, int height) +{ + cairo_set_alpha (cr, 1.0); + cairo_new_path (cr); + cairo_arc (cr, WIDTH / 2, HEIGHT / 2, WIDTH / 3, 0, 2 * M_PI); + cairo_clip (cr); + + cairo_new_path (cr); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, WIDTH / 4, HEIGHT / 2); + cairo_line_to (cr, 0, HEIGHT); + cairo_line_to (cr, WIDTH, HEIGHT); + cairo_line_to (cr, 3 * WIDTH / 4, HEIGHT / 2); + cairo_line_to (cr, WIDTH, 0); + cairo_close_path (cr); + cairo_clip (cr); + + cairo_set_rgb_color (cr, 0, 0, 0.6); + + cairo_new_path (cr); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, 0, HEIGHT); + cairo_line_to (cr, WIDTH / 2, 3 * HEIGHT / 4); + cairo_line_to (cr, WIDTH, HEIGHT); + cairo_line_to (cr, WIDTH, 0); + cairo_line_to (cr, WIDTH / 2, HEIGHT / 4); + cairo_close_path (cr); + cairo_fill (cr); +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/clip_twice-ref.png b/test/clip_twice-ref.png Binary files differnew file mode 100644 index 00000000..ab0ae1ae --- /dev/null +++ b/test/clip_twice-ref.png diff --git a/test/clip_twice.c b/test/clip_twice.c new file mode 100644 index 00000000..00215e62 --- /dev/null +++ b/test/clip_twice.c @@ -0,0 +1,72 @@ +/* + * Copyright © 2005 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Kristian Høgsberg <krh@redhat.com> + */ + +#include "cairo_test.h" + +#define WIDTH 64 +#define HEIGHT 64 + +cairo_test_t test = { + "clip_twice", + "Verifies that the clip mask is updated correctly when it constructed by setting the clip path twice.", + WIDTH, HEIGHT +}; + +static void +draw (cairo_t *cr, int width, int height) +{ + cairo_set_alpha (cr, 1.0); + cairo_new_path (cr); + cairo_arc (cr, WIDTH / 2, HEIGHT / 2, WIDTH / 3, 0, 2 * M_PI); + cairo_clip (cr); + + cairo_new_path (cr); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, WIDTH / 4, HEIGHT / 2); + cairo_line_to (cr, 0, HEIGHT); + cairo_line_to (cr, WIDTH, HEIGHT); + cairo_line_to (cr, 3 * WIDTH / 4, HEIGHT / 2); + cairo_line_to (cr, WIDTH, 0); + cairo_close_path (cr); + cairo_clip (cr); + + cairo_set_rgb_color (cr, 0, 0, 0.6); + + cairo_new_path (cr); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, 0, HEIGHT); + cairo_line_to (cr, WIDTH / 2, 3 * HEIGHT / 4); + cairo_line_to (cr, WIDTH, HEIGHT); + cairo_line_to (cr, WIDTH, 0); + cairo_line_to (cr, WIDTH / 2, HEIGHT / 4); + cairo_close_path (cr); + cairo_fill (cr); +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/coverage-ref.png b/test/coverage-ref.png Binary files differnew file mode 100644 index 00000000..9b710405 --- /dev/null +++ b/test/coverage-ref.png diff --git a/test/coverage.c b/test/coverage.c new file mode 100644 index 00000000..00c86a1d --- /dev/null +++ b/test/coverage.c @@ -0,0 +1,182 @@ +/* + * Copyright © 2005 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Kristian Høgsberg <krh@redhat.com> + */ + +#include <math.h> +#include "cairo_test.h" + +#define WIDTH 64 +#define HEIGHT 64 +#define PAD 10 + +/* XXX The test image uses Bitstream Vera Sans as the font - how do we + * ensure that it's available? Can we ship it with this test? */ + +const char fontname[] = "Bitstream Vera Sans"; +const int fontsize = 40; +const char png_filename[] = "romedalen.png"; + +static void +set_solid_pattern (cairo_t *cr, int x, int y) +{ + cairo_set_rgb_color (cr, 0, 0, 0.6); + cairo_set_alpha (cr, 1.0); +} + +static void +set_translucent_pattern (cairo_t *cr, int x, int y) +{ + cairo_set_rgb_color (cr, 0, 0, 0.6); + cairo_set_alpha (cr, 0.5); +} + +static void +set_gradient_pattern (cairo_t *cr, int x, int y) +{ + cairo_pattern_t *pattern; + + pattern = + cairo_pattern_create_linear (x, y, x + WIDTH, y + HEIGHT); + cairo_pattern_add_color_stop (pattern, 0, 1, 1, 1, 1); + cairo_pattern_add_color_stop (pattern, 1, 0, 0, 0.4, 1); + cairo_set_pattern (cr, pattern); + cairo_set_alpha (cr, 1); +} + +static void +set_image_pattern (cairo_t *cr, int x, int y) +{ + cairo_pattern_t *pattern; + + pattern = cairo_test_create_png_pattern (cr, png_filename); + cairo_set_pattern (cr, pattern); + cairo_set_alpha (cr, 1); +} + +static void +set_translucent_image_pattern (cairo_t *cr, int x, int y) +{ + cairo_pattern_t *pattern; + + pattern = cairo_test_create_png_pattern (cr, png_filename); + cairo_set_pattern (cr, pattern); + cairo_set_alpha (cr, 0.5); +} + +static void +draw_text (cairo_t *cr, int x, int y) +{ + cairo_rel_move_to (cr, 0, fontsize); + cairo_show_text (cr, "Aa"); +} + +static void +draw_polygon (cairo_t *cr, int x, int y) +{ + cairo_new_path (cr); + cairo_move_to (cr, x, y); + cairo_line_to (cr, x, y + HEIGHT); + cairo_line_to (cr, x + WIDTH / 2, y + 3 * HEIGHT / 4); + cairo_line_to (cr, x + WIDTH, y + HEIGHT); + cairo_line_to (cr, x + WIDTH, y); + cairo_line_to (cr, x + WIDTH / 2, y + HEIGHT / 4); + cairo_close_path (cr); + cairo_fill (cr); +} + +static void (*pattern_funcs[])(cairo_t *cr, int x, int y) = { + set_solid_pattern, + set_translucent_pattern, + set_gradient_pattern, + set_image_pattern, + set_translucent_image_pattern +}; + +static void (*draw_funcs[])(cairo_t *cr, int x, int y) = { + draw_text, + draw_polygon, +}; + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) +#define IMAGE_WIDTH (ARRAY_SIZE (pattern_funcs) * (WIDTH + PAD) + PAD) +#define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) * 2 + PAD) + +static cairo_test_t test = { + "coverage", + "Various coverage test of cairo", + IMAGE_WIDTH, IMAGE_HEIGHT +}; + + +static void +draw (cairo_t *cr, int width, int height) +{ + /* TODO: pattern fill, gradient fill, clipping, gradient clipping, + path+solid alpha mask clipping */ + + int i, j, x, y; + + cairo_select_font (cr, fontname, + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_scale_font (cr, fontsize); + + for (j = 0; j < ARRAY_SIZE (draw_funcs); j++) { + for (i = 0; i < ARRAY_SIZE (pattern_funcs); i++) { + x = i * (WIDTH + PAD) + PAD; + y = j * (HEIGHT + PAD) + PAD; + cairo_move_to (cr, x, y); + pattern_funcs[i] (cr, x, y); + draw_funcs[j] (cr, x, y); + } + } + + for (j = 0; j < ARRAY_SIZE (draw_funcs); j++) { + for (i = 0; i < ARRAY_SIZE (pattern_funcs); i++) { + x = i * (WIDTH + PAD) + PAD; + y = (ARRAY_SIZE (draw_funcs) + j) * (HEIGHT + PAD) + PAD; + + cairo_save (cr); + + cairo_set_alpha (cr, 1.0); + cairo_new_path (cr); + cairo_arc (cr, x + WIDTH / 2, y + HEIGHT / 2, + WIDTH / 3, 0, 2 * M_PI); + cairo_clip (cr); + + cairo_move_to (cr, x, y); + pattern_funcs[i] (cr, x, y); + draw_funcs[j] (cr, x, y); + + cairo_restore (cr); + + } + } +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/imagediff.c b/test/imagediff.c new file mode 100644 index 00000000..36962f11 --- /dev/null +++ b/test/imagediff.c @@ -0,0 +1,84 @@ +/* imagediff - Compare two images + * + * Copyright © 2004 Richard D. Worth + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Richard Worth + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Richard Worth makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * RICHARD WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL RICHARD WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Richard D. Worth <richard@theworths.org> */ + +#include <stdio.h> +#include <stdlib.h> + +#include "buffer_diff.h" +#include "read_png.h" +#include "write_png.h" +#include "xmalloc.h" + +int +main (int argc, char *argv[]) +{ + unsigned char *buffer_a; + unsigned int width_a, height_a, stride_a; + unsigned char *buffer_b; + unsigned int width_b, height_b, stride_b; + + unsigned char *buffer; + unsigned int width, height, stride; + int buffer_size, total_pixels_changed; + + if (argc < 2) { + fprintf (stderr, "Usage: %s image1.png image2.png\n", argv[0]); + fprintf (stderr, "Computes an output image designed to present a \"visual diff\" such that even\n"); + fprintf (stderr, "small errors in single pixels are readily apparent in the output.\n"); + fprintf (stderr, "The output image is written on stdout.\n"); + exit (1); + } + + read_png_argb32 (argv[1], &buffer_a, &width_a, &height_a, &stride_a); + read_png_argb32 (argv[2], &buffer_b, &width_b, &height_b, &stride_b); + + if ((width_a == width_b) && (height_a == height_b) && (stride_a == stride_b)) + { + width = width_a; + height = height_a; + stride = stride_a; + } else { + fprintf (stderr, "Error. Both images must be the same size\n"); + return 1; + } + + buffer_size = stride * height; + buffer = xmalloc (buffer_size); + + total_pixels_changed = buffer_diff (buffer_a, buffer_b, buffer, + width_a, height_a, stride_a); + + + if (total_pixels_changed) + fprintf (stderr, "Total pixels changed: %d\n", total_pixels_changed); + write_png_argb32 (buffer, stdout, width, height, stride); + + free (buffer); + + return 0; +} + + + diff --git a/test/linear-gradient-ref.png b/test/linear-gradient-ref.png Binary files differnew file mode 100644 index 00000000..77904144 --- /dev/null +++ b/test/linear-gradient-ref.png diff --git a/test/linear-gradient.c b/test/linear-gradient.c new file mode 100644 index 00000000..189b5006 --- /dev/null +++ b/test/linear-gradient.c @@ -0,0 +1,141 @@ +/* + * Copyright © 2005 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor <otaylor@redhat.com> + */ + +#include "cairo_test.h" +#include "stdio.h" + +/* The test matrix is + * + * A) Horizontal B) 5° C) 45° D) Vertical + * 1) Rotated 0° 2) Rotated 45° C) Rotated 90° + * a) 2 stop b) 3 stop + * + * A1a B1a C1a D1a + * A2a B2a C2a D2a + * A3a B3a C3a D3a + * A1b B1b C1b D1b + * A2b B2b C2b D2b + * A3b B3b C3b D3b + */ + +static const double gradient_angles[] = { 0, 45, 90 }; +#define N_GRADIENT_ANGLES 3 +static const double rotate_angles[] = { 0, 45, 90 }; +#define N_ROTATE_ANGLES 3 +static const int n_stops[] = { 2, 3 }; +#define N_N_STOPS 2 + +#define UNIT_SIZE 75 +#define UNIT_SIZE 75 +#define PAD 5 + +#define WIDTH N_GRADIENT_ANGLES * UNIT_SIZE + (N_GRADIENT_ANGLES + 1) * PAD +#define HEIGHT N_N_STOPS * N_ROTATE_ANGLES * UNIT_SIZE + (N_N_STOPS * N_ROTATE_ANGLES + 1) * PAD + +cairo_test_t test = { + "linear_gradient", + "Tests the drawing of linear gradients", + WIDTH, HEIGHT +}; + +static void +draw_unit (cairo_t *cr, + double gradient_angle, + double rotate_angle, + int n_stops) +{ + cairo_pattern_t *pattern; + + cairo_rectangle (cr, 0, 0, 1, 1); + cairo_clip (cr); + cairo_new_path(cr); + + cairo_set_rgb_color (cr, 0.0, 0.0, 0.0); + cairo_rectangle (cr, 0, 0, 1, 1); + cairo_fill (cr); + + cairo_translate (cr, 0.5, 0.5); + cairo_scale (cr, 1 / 1.5, 1 / 1.5); + cairo_rotate (cr, rotate_angle); + + pattern = cairo_pattern_create_linear (-0.5 * cos (gradient_angle), -0.5 * sin (gradient_angle), + 0.5 * cos (gradient_angle), 0.5 * sin (gradient_angle)); + + if (n_stops == 2) { + cairo_pattern_add_color_stop (pattern, 0., + 0.3, 0.3, 0.3, + 1.0); + cairo_pattern_add_color_stop (pattern, 1., + 1.0, 1.0, 1.0, + 1.0); + } else { + cairo_pattern_add_color_stop (pattern, 0., + 1.0, 0.0, 0.0, + 1.0); + cairo_pattern_add_color_stop (pattern, 0.5, + 1.0, 1.0, 1.0, + 1.0); + cairo_pattern_add_color_stop (pattern, 1., + 0.0, 0.0, 1.0, + 1.0); + } + + cairo_set_pattern (cr, pattern); + cairo_pattern_destroy (pattern); + cairo_rectangle (cr, -0.5, -0.5, 1, 1); + cairo_fill (cr); +} + +static void +draw (cairo_t *cr, int width, int height) +{ + int i, j, k; + + cairo_set_rgb_color (cr, 0.5, 0.5, 0.5); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + for (i = 0; i < N_GRADIENT_ANGLES; i++) + for (j = 0; j < N_ROTATE_ANGLES; j++) + for (k = 0; k < N_N_STOPS; k++) { + cairo_save (cr); + cairo_translate (cr, + PAD + (PAD + UNIT_SIZE) * i, + PAD + (PAD + UNIT_SIZE) * (N_ROTATE_ANGLES * k + j)); + cairo_scale (cr, UNIT_SIZE, UNIT_SIZE); + + draw_unit (cr, + gradient_angles[i] * M_PI / 180., + rotate_angles[j] * M_PI / 180., + n_stops[k]); + cairo_restore (cr); + } +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/linear_gradient-ref.png b/test/linear_gradient-ref.png Binary files differnew file mode 100644 index 00000000..77904144 --- /dev/null +++ b/test/linear_gradient-ref.png diff --git a/test/linear_gradient.c b/test/linear_gradient.c new file mode 100644 index 00000000..189b5006 --- /dev/null +++ b/test/linear_gradient.c @@ -0,0 +1,141 @@ +/* + * Copyright © 2005 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Red Hat, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. Red Hat, Inc. makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Owen Taylor <otaylor@redhat.com> + */ + +#include "cairo_test.h" +#include "stdio.h" + +/* The test matrix is + * + * A) Horizontal B) 5° C) 45° D) Vertical + * 1) Rotated 0° 2) Rotated 45° C) Rotated 90° + * a) 2 stop b) 3 stop + * + * A1a B1a C1a D1a + * A2a B2a C2a D2a + * A3a B3a C3a D3a + * A1b B1b C1b D1b + * A2b B2b C2b D2b + * A3b B3b C3b D3b + */ + +static const double gradient_angles[] = { 0, 45, 90 }; +#define N_GRADIENT_ANGLES 3 +static const double rotate_angles[] = { 0, 45, 90 }; +#define N_ROTATE_ANGLES 3 +static const int n_stops[] = { 2, 3 }; +#define N_N_STOPS 2 + +#define UNIT_SIZE 75 +#define UNIT_SIZE 75 +#define PAD 5 + +#define WIDTH N_GRADIENT_ANGLES * UNIT_SIZE + (N_GRADIENT_ANGLES + 1) * PAD +#define HEIGHT N_N_STOPS * N_ROTATE_ANGLES * UNIT_SIZE + (N_N_STOPS * N_ROTATE_ANGLES + 1) * PAD + +cairo_test_t test = { + "linear_gradient", + "Tests the drawing of linear gradients", + WIDTH, HEIGHT +}; + +static void +draw_unit (cairo_t *cr, + double gradient_angle, + double rotate_angle, + int n_stops) +{ + cairo_pattern_t *pattern; + + cairo_rectangle (cr, 0, 0, 1, 1); + cairo_clip (cr); + cairo_new_path(cr); + + cairo_set_rgb_color (cr, 0.0, 0.0, 0.0); + cairo_rectangle (cr, 0, 0, 1, 1); + cairo_fill (cr); + + cairo_translate (cr, 0.5, 0.5); + cairo_scale (cr, 1 / 1.5, 1 / 1.5); + cairo_rotate (cr, rotate_angle); + + pattern = cairo_pattern_create_linear (-0.5 * cos (gradient_angle), -0.5 * sin (gradient_angle), + 0.5 * cos (gradient_angle), 0.5 * sin (gradient_angle)); + + if (n_stops == 2) { + cairo_pattern_add_color_stop (pattern, 0., + 0.3, 0.3, 0.3, + 1.0); + cairo_pattern_add_color_stop (pattern, 1., + 1.0, 1.0, 1.0, + 1.0); + } else { + cairo_pattern_add_color_stop (pattern, 0., + 1.0, 0.0, 0.0, + 1.0); + cairo_pattern_add_color_stop (pattern, 0.5, + 1.0, 1.0, 1.0, + 1.0); + cairo_pattern_add_color_stop (pattern, 1., + 0.0, 0.0, 1.0, + 1.0); + } + + cairo_set_pattern (cr, pattern); + cairo_pattern_destroy (pattern); + cairo_rectangle (cr, -0.5, -0.5, 1, 1); + cairo_fill (cr); +} + +static void +draw (cairo_t *cr, int width, int height) +{ + int i, j, k; + + cairo_set_rgb_color (cr, 0.5, 0.5, 0.5); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + + for (i = 0; i < N_GRADIENT_ANGLES; i++) + for (j = 0; j < N_ROTATE_ANGLES; j++) + for (k = 0; k < N_N_STOPS; k++) { + cairo_save (cr); + cairo_translate (cr, + PAD + (PAD + UNIT_SIZE) * i, + PAD + (PAD + UNIT_SIZE) * (N_ROTATE_ANGLES * k + j)); + cairo_scale (cr, UNIT_SIZE, UNIT_SIZE); + + draw_unit (cr, + gradient_angles[i] * M_PI / 180., + rotate_angles[j] * M_PI / 180., + n_stops[k]); + cairo_restore (cr); + } +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/pixman-rotate-ref.png b/test/pixman-rotate-ref.png Binary files differnew file mode 100644 index 00000000..7e47a4d8 --- /dev/null +++ b/test/pixman-rotate-ref.png diff --git a/test/pixman-rotate.c b/test/pixman-rotate.c new file mode 100644 index 00000000..6a64a9a7 --- /dev/null +++ b/test/pixman-rotate.c @@ -0,0 +1,78 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <cairo.h> +#include <cairo-png.h> +#include <cairo-pdf.h> + +#include "cairo_test.h" + +#define WIDTH 32 +#define HEIGHT WIDTH + +#define IMAGE_WIDTH (3 * WIDTH) +#define IMAGE_HEIGHT IMAGE_WIDTH + +cairo_test_t test = { + "pixman_rotate", + "Exposes pixman off-by-one error when rotating", + IMAGE_WIDTH, IMAGE_HEIGHT +}; + +/* Draw the word cairo at NUM_TEXT different angles */ +static void +draw (cairo_t *cr, int width, int height) +{ + cairo_surface_t *target, *stamp; + + target = cairo_current_target_surface (cr); + cairo_surface_reference (target); + + stamp = cairo_surface_create_similar (target, CAIRO_FORMAT_ARGB32, + WIDTH, HEIGHT); + cairo_set_target_surface (cr, stamp); + cairo_new_path (cr); + cairo_rectangle (cr, WIDTH / 4, HEIGHT / 4, WIDTH / 2, HEIGHT / 2); + cairo_set_rgb_color (cr, 1, 0, 0); + cairo_set_alpha (cr, 0.8); + cairo_fill (cr); + + cairo_rectangle (cr, 0, 0, WIDTH, HEIGHT); + cairo_set_line_width (cr, 2); + cairo_set_rgb_color (cr, 0, 0, 0); + cairo_set_alpha (cr, 1); + cairo_stroke (cr); + + cairo_set_target_surface (cr, target); + + /* Draw a translucent rectangle for reference where the rotated + * image should be. */ + cairo_new_path (cr); + cairo_rectangle (cr, WIDTH, HEIGHT, WIDTH, HEIGHT); + cairo_set_rgb_color (cr, 1, 1, 0); + cairo_set_alpha (cr, 0.3); + cairo_fill (cr); + +#if 1 /* Set to 0 to generate reference image */ + cairo_translate (cr, 2 * WIDTH, 2 * HEIGHT); + cairo_rotate (cr, M_PI); +#else + cairo_translate (cr, WIDTH, HEIGHT); +#endif + + cairo_set_alpha (cr, 1); + cairo_show_surface (cr, stamp, WIDTH + 2, HEIGHT + 2); + + cairo_show_page (cr); + + cairo_surface_destroy (stamp); + cairo_surface_destroy (target); +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/pixman_rotate-ref.png b/test/pixman_rotate-ref.png Binary files differnew file mode 100644 index 00000000..7e47a4d8 --- /dev/null +++ b/test/pixman_rotate-ref.png diff --git a/test/pixman_rotate.c b/test/pixman_rotate.c new file mode 100644 index 00000000..6a64a9a7 --- /dev/null +++ b/test/pixman_rotate.c @@ -0,0 +1,78 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <cairo.h> +#include <cairo-png.h> +#include <cairo-pdf.h> + +#include "cairo_test.h" + +#define WIDTH 32 +#define HEIGHT WIDTH + +#define IMAGE_WIDTH (3 * WIDTH) +#define IMAGE_HEIGHT IMAGE_WIDTH + +cairo_test_t test = { + "pixman_rotate", + "Exposes pixman off-by-one error when rotating", + IMAGE_WIDTH, IMAGE_HEIGHT +}; + +/* Draw the word cairo at NUM_TEXT different angles */ +static void +draw (cairo_t *cr, int width, int height) +{ + cairo_surface_t *target, *stamp; + + target = cairo_current_target_surface (cr); + cairo_surface_reference (target); + + stamp = cairo_surface_create_similar (target, CAIRO_FORMAT_ARGB32, + WIDTH, HEIGHT); + cairo_set_target_surface (cr, stamp); + cairo_new_path (cr); + cairo_rectangle (cr, WIDTH / 4, HEIGHT / 4, WIDTH / 2, HEIGHT / 2); + cairo_set_rgb_color (cr, 1, 0, 0); + cairo_set_alpha (cr, 0.8); + cairo_fill (cr); + + cairo_rectangle (cr, 0, 0, WIDTH, HEIGHT); + cairo_set_line_width (cr, 2); + cairo_set_rgb_color (cr, 0, 0, 0); + cairo_set_alpha (cr, 1); + cairo_stroke (cr); + + cairo_set_target_surface (cr, target); + + /* Draw a translucent rectangle for reference where the rotated + * image should be. */ + cairo_new_path (cr); + cairo_rectangle (cr, WIDTH, HEIGHT, WIDTH, HEIGHT); + cairo_set_rgb_color (cr, 1, 1, 0); + cairo_set_alpha (cr, 0.3); + cairo_fill (cr); + +#if 1 /* Set to 0 to generate reference image */ + cairo_translate (cr, 2 * WIDTH, 2 * HEIGHT); + cairo_rotate (cr, M_PI); +#else + cairo_translate (cr, WIDTH, HEIGHT); +#endif + + cairo_set_alpha (cr, 1); + cairo_show_surface (cr, stamp, WIDTH + 2, HEIGHT + 2); + + cairo_show_page (cr); + + cairo_surface_destroy (stamp); + cairo_surface_destroy (target); +} + +int +main (void) +{ + return cairo_test (&test, draw); +} diff --git a/test/read-png.c b/test/read-png.c index 23f91e83..e7e2a92c 100644 --- a/test/read-png.c +++ b/test/read-png.c @@ -47,9 +47,9 @@ premultiply_data (png_structp png, unsigned char alpha = base[3]; unsigned long p; - red = (unsigned) red * (unsigned) alpha / 255; - green = (unsigned) green * (unsigned) alpha / 255; - blue = (unsigned) blue * (unsigned) alpha / 255; + red = ((unsigned) red * (unsigned) alpha + 127) / 255; + green = ((unsigned) green * (unsigned) alpha + 127) / 255; + blue = ((unsigned) blue * (unsigned) alpha + 127) / 255; p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); memcpy (base, &p, sizeof (unsigned long)); } diff --git a/test/read_png.c b/test/read_png.c index 23f91e83..e7e2a92c 100644 --- a/test/read_png.c +++ b/test/read_png.c @@ -47,9 +47,9 @@ premultiply_data (png_structp png, unsigned char alpha = base[3]; unsigned long p; - red = (unsigned) red * (unsigned) alpha / 255; - green = (unsigned) green * (unsigned) alpha / 255; - blue = (unsigned) blue * (unsigned) alpha / 255; + red = ((unsigned) red * (unsigned) alpha + 127) / 255; + green = ((unsigned) green * (unsigned) alpha + 127) / 255; + blue = ((unsigned) blue * (unsigned) alpha + 127) / 255; p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); memcpy (base, &p, sizeof (unsigned long)); } diff --git a/test/romedalen.png b/test/romedalen.png Binary files differnew file mode 100644 index 00000000..0c41eb0c --- /dev/null +++ b/test/romedalen.png diff --git a/test/testsvg b/test/testsvg new file mode 100755 index 00000000..52044294 --- /dev/null +++ b/test/testsvg @@ -0,0 +1,51 @@ +#!/bin/sh + +IMAGEDIFF=./imagediff + +OUTDIR=testsvg-output +REFDIR=testsvg-reference +DIFFDIR=testsvg-diff +IMAGELIST=testsvg-imagelist + +if [ $# -lt 1 ]; then + argv0=`basename $0` + echo "Usage: $argv0 file.svg [...]" >&2 + exit 1; +fi + +mkdir -p $OUTDIR +mkdir -p $DIFFDIR +rm -f $IMAGELIST + +err=0 +for svg in $@; do + svgbase=`basename $svg` + png=${svgbase/\.svg/.png} + outpng=$OUTDIR/$png + refpng=$REFDIR/$png + diffpng=$DIFFDIR/$png +# if xsvg $svg -p $outpng ; then + if svg2png $svg $outpng ; then + if [ -e $refpng ]; then + if diff $refpng $outpng > /dev/null; then + echo "Rendering of $svg matches." >&2 + else + echo "ERROR: Rendering of $svg differs from reference image." >&2 + $IMAGEDIFF $refpng $outpng > $diffpng + echo $refpng $outpng $diffpng >> $IMAGELIST + err=$(($err+1)) + fi + else + echo "WARNING: No reference file found for $svg (looked in $refpng)" >&2 + fi + else + echo "ERROR: Failed to render $svg" >&2 + err=$(($err+1)) + fi +done + +if [ $err -gt 0 ] ; then + echo "Differences found in $err renderings." +else + echo "All renderings matched reference images." +fi diff --git a/test/write-png.c b/test/write-png.c index 2ea29d06..0ff5bcd3 100644 --- a/test/write-png.c +++ b/test/write-png.c @@ -1,5 +1,5 @@ /* - * Copyright © 2003 USC, Information Sciences Institute + * Copyright © 2003 USC, Information Sciences Institute * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without @@ -22,7 +22,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: Carl D. Worth <cworth@isi.edu> + * Author: Carl D. Worth <cworth@cworth.org> */ #include <stdio.h> @@ -46,26 +46,24 @@ unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data) if (alpha == 0) { b[0] = b[1] = b[2] = b[3] = 0; } else { - b[0] = (((pixel & 0x0000ff) >> 0) * 255) / alpha; - b[1] = (((pixel & 0x00ff00) >> 8) * 255) / alpha; - b[2] = (((pixel & 0xff0000) >> 16) * 255) / alpha; + b[0] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; + b[2] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; b[3] = alpha; } } } void -write_png_argb32 (char *buffer, char *filename, +write_png_argb32 (char *buffer, FILE *file, int width, int height, int stride) { - FILE *f; int i; png_struct *png; png_info *info; png_byte **rows; png_color_16 white; - f = fopen (filename, "w"); rows = malloc (height * sizeof(png_byte*)); for (i = 0; i < height; i++) { @@ -75,7 +73,7 @@ write_png_argb32 (char *buffer, char *filename, png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct (png); - png_init_io (png, f); + png_init_io (png, file); png_set_IHDR (png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, @@ -98,5 +96,4 @@ write_png_argb32 (char *buffer, char *filename, png_destroy_write_struct (&png, &info); free (rows); - fclose (f); } diff --git a/test/write-png.h b/test/write-png.h index a71ca6a3..fe0e92b2 100644 --- a/test/write-png.h +++ b/test/write-png.h @@ -1,5 +1,5 @@ /* - * Copyright © 2003 USC, Information Sciences Institute + * Copyright © 2003 USC, Information Sciences Institute * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without @@ -29,7 +29,7 @@ #define WRITE_PNG_H void -write_png_argb32 (char *buffer, char *filename, +write_png_argb32 (char *buffer, FILE * file, int width, int height, int stride); #endif diff --git a/test/write_png.c b/test/write_png.c index 2ea29d06..0ff5bcd3 100644 --- a/test/write_png.c +++ b/test/write_png.c @@ -1,5 +1,5 @@ /* - * Copyright © 2003 USC, Information Sciences Institute + * Copyright © 2003 USC, Information Sciences Institute * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without @@ -22,7 +22,7 @@ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * Author: Carl D. Worth <cworth@isi.edu> + * Author: Carl D. Worth <cworth@cworth.org> */ #include <stdio.h> @@ -46,26 +46,24 @@ unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data) if (alpha == 0) { b[0] = b[1] = b[2] = b[3] = 0; } else { - b[0] = (((pixel & 0x0000ff) >> 0) * 255) / alpha; - b[1] = (((pixel & 0x00ff00) >> 8) * 255) / alpha; - b[2] = (((pixel & 0xff0000) >> 16) * 255) / alpha; + b[0] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; + b[2] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; b[3] = alpha; } } } void -write_png_argb32 (char *buffer, char *filename, +write_png_argb32 (char *buffer, FILE *file, int width, int height, int stride) { - FILE *f; int i; png_struct *png; png_info *info; png_byte **rows; png_color_16 white; - f = fopen (filename, "w"); rows = malloc (height * sizeof(png_byte*)); for (i = 0; i < height; i++) { @@ -75,7 +73,7 @@ write_png_argb32 (char *buffer, char *filename, png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct (png); - png_init_io (png, f); + png_init_io (png, file); png_set_IHDR (png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, @@ -98,5 +96,4 @@ write_png_argb32 (char *buffer, char *filename, png_destroy_write_struct (&png, &info); free (rows); - fclose (f); } diff --git a/test/write_png.h b/test/write_png.h index a71ca6a3..fe0e92b2 100644 --- a/test/write_png.h +++ b/test/write_png.h @@ -1,5 +1,5 @@ /* - * Copyright © 2003 USC, Information Sciences Institute + * Copyright © 2003 USC, Information Sciences Institute * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without @@ -29,7 +29,7 @@ #define WRITE_PNG_H void -write_png_argb32 (char *buffer, char *filename, +write_png_argb32 (char *buffer, FILE * file, int width, int height, int stride); #endif |