[cairo-commit] 4 commits - boilerplate/buffer-diff.c
boilerplate/buffer-diff.h boilerplate/cairo-boilerplate.c
boilerplate/cairo-boilerplate.h boilerplate/cairo-test.c
boilerplate/cairo-test.h boilerplate/Makefile.am
boilerplate/README boilerplate/read-png.c
boilerplate/read-png.h boilerplate/write-png.c
boilerplate/write-png.h boilerplate/xmalloc.c
test/buffer-diff.c test/buffer-diff.h test/cairo-test.c
test/cairo-test.h test/imagediff.c test/Makefile.am
Carl Worth
cworth at kemper.freedesktop.org
Thu Aug 31 01:40:38 PDT 2006
boilerplate/Makefile.am | 21
boilerplate/README | 14
boilerplate/buffer-diff.c | 348 ------
boilerplate/cairo-boilerplate.c | 1511 ++++++++++++++++++++++++++++
boilerplate/cairo-boilerplate.h | 88 +
boilerplate/cairo-test.c | 2147 ----------------------------------------
boilerplate/read-png.c | 196 ---
boilerplate/read-png.h | 45
boilerplate/write-png.c | 99 -
boilerplate/write-png.h | 35
boilerplate/xmalloc.c | 6
test/Makefile.am | 13
test/buffer-diff.c | 306 +++++
test/cairo-test.c | 683 ++++++++++++
test/cairo-test.h | 13
test/imagediff.c | 2
16 files changed, 2627 insertions(+), 2900 deletions(-)
New commits:
diff-tree d52a1f762d33f3ada919b581e0d62f8ba1c2314c (from 95475218858792ccb20ac6ad28db22e233c783d7)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Aug 31 01:39:06 2006 -0700
Move test-specific stuff out of boilerplate/ and back into test/
This now gives us two separate libtool convenience libraries,
so they have to have separate names now:
libcairoboilerplate.la and libcairotest.la.
diff --git a/boilerplate/Makefile.am b/boilerplate/Makefile.am
index 2cc48ce..4bf07fa 100644
--- a/boilerplate/Makefile.am
+++ b/boilerplate/Makefile.am
@@ -1,23 +1,19 @@
-noinst_LTLIBRARIES = libcairotest.la
+noinst_LTLIBRARIES = libcairoboilerplate.la
-libcairotest_la_SOURCES =\
+libcairoboilerplate_la_SOURCES =\
cairo-boilerplate.c \
cairo-bolierplate.h \
-buffer-diff.c \
-buffer-diff.h \
-cairo-test.c \
-cairo-test.h \
xmalloc.c \
xmalloc.h
if CAIRO_HAS_BEOS_SURFACE
-libcairotest_la_SOURCES += cairo-test-beos.cpp cairo-test-beos.h
+libcairoboilerplate_la_SOURCES += cairo-test-beos.cpp cairo-test-beos.h
# BeOS system headers trigger this warning
-libcairotest_la_CXXFLAGS = -Wno-multichar
+libcairoboilerplate_la_CXXFLAGS = -Wno-multichar
endif
if CAIRO_HAS_DIRECTFB_SURFACE
-libcairotest_la_SOURCES += cairo-test-directfb.c cairo-test-directfb.h
+libcairoboilerplate_la_SOURCES += cairo-test-directfb.c cairo-test-directfb.h
endif
# We're using _GNU_SOURCE to get the prototype for asprintf. This may
diff --git a/boilerplate/buffer-diff.c b/boilerplate/buffer-diff.c
deleted file mode 100644
index b59b5e8..0000000
--- a/boilerplate/buffer-diff.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* 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 at theworths.org> */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#include <pixman.h>
-
-#include "cairo-test.h"
-
-#include "buffer-diff.h"
-#include "xmalloc.h"
-
-static void
-xunlink (const char *pathname)
-{
- if (unlink (pathname) < 0 && errno != ENOENT) {
- cairo_test_log (" Error: Cannot remove %s: %s\n",
- pathname, strerror (errno));
- exit (1);
- }
-}
-
-/* This function should be rewritten to compare all formats supported by
- * cairo_format_t instead of taking a mask as a parameter.
- */
-static int
-buffer_diff_core (unsigned char *_buf_a,
- unsigned char *_buf_b,
- unsigned char *_buf_diff,
- int width,
- int height,
- int stride_a,
- int stride_b,
- int stride_diff,
- pixman_bits_t mask)
-{
- int x, y;
- pixman_bits_t *row_a, *row_b, *row;
- int pixels_changed = 0;
- pixman_bits_t *buf_a = (pixman_bits_t*)_buf_a;
- pixman_bits_t *buf_b = (pixman_bits_t*)_buf_b;
- pixman_bits_t *buf_diff = (pixman_bits_t*)_buf_diff;
-
- stride_a /= sizeof(pixman_bits_t);
- stride_b /= sizeof(pixman_bits_t);
- stride_diff /= sizeof(pixman_bits_t);
- for (y = 0; y < height; y++)
- {
- row_a = buf_a + y * stride_a;
- row_b = buf_b + y * stride_b;
- row = buf_diff + y * stride_diff;
- for (x = 0; x < width; x++)
- {
- /* check if the pixels are the same */
- if ((row_a[x] & mask) != (row_b[x] & mask)) {
- int channel;
- pixman_bits_t diff_pixel = 0;
-
- /* calculate a difference value for all 4 channels */
- for (channel = 0; channel < 4; channel++) {
- int value_a = (row_a[x] >> (channel*8)) & 0xff;
- int value_b = (row_b[x] >> (channel*8)) & 0xff;
- unsigned int diff;
- diff = abs (value_a - value_b);
- diff *= 4; /* emphasize */
- if (diff)
- diff += 128; /* make sure it's visible */
- if (diff > 255)
- diff = 255;
- diff_pixel |= diff << (channel*8);
- }
-
- pixels_changed++;
- row[x] = diff_pixel;
- } else {
- row[x] = 0;
- }
- row[x] |= 0xff000000; /* Set ALPHA to 100% (opaque) */
- }
- }
-
- return pixels_changed;
-}
-
-int
-buffer_diff (unsigned char *buf_a,
- unsigned char *buf_b,
- unsigned char *buf_diff,
- int width,
- int height,
- int stride_a,
- int stride_b,
- int stride_diff)
-{
- return buffer_diff_core(buf_a, buf_b, buf_diff,
- width, height, stride_a, stride_b, stride_diff, 0xffffffff);
-}
-
-int
-buffer_diff_noalpha (unsigned char *buf_a,
- unsigned char *buf_b,
- unsigned char *buf_diff,
- int width,
- int height,
- int stride_a,
- int stride_b,
- int stride_diff)
-{
- return buffer_diff_core(buf_a, buf_b, buf_diff,
- width, height, stride_a, stride_b, stride_diff, 0x00ffffff);
-}
-
-static cairo_status_t
-stdio_write_func (void *closure, const unsigned char *data, unsigned int length)
-{
- FILE *file = closure;
-
- if (fwrite (data, 1, length, file) != length)
- return CAIRO_STATUS_WRITE_ERROR;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Flatten an ARGB surface by blending it over white. The resulting
- * surface, (still in ARGB32 format, but with only alpha==1.0
- * everywhere) is returned in the same surface pointer.
- *
- * The original surface will be destroyed.
- *
- * The (x,y) value specify an origin of interest for the original
- * image. The flattened image will be generated only from the box
- * extending from (x,y) to (width,height).
- */
-static void
-flatten_surface (cairo_surface_t **surface, int x, int y)
-{
- cairo_surface_t *flat;
- cairo_t *cr;
-
- flat = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- cairo_image_surface_get_width (*surface) - x,
- cairo_image_surface_get_height (*surface) - y);
- cairo_surface_set_device_offset (flat, -x, -y);
-
- cr = cairo_create (flat);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_set_source_surface (cr, *surface, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- cairo_surface_destroy (*surface);
- *surface = flat;
-}
-
-/* Image comparison code courtesy of Richard Worth <richard at theworths.org>
- * Returns number of pixels changed, (or -1 on error).
- * Also saves a "diff" image intended to visually show where the
- * images differ.
- */
-static int
-image_diff_core (const char *filename_a,
- const char *filename_b,
- const char *filename_diff,
- int ax,
- int ay,
- int bx,
- int by,
- cairo_bool_t flatten)
-{
- int pixels_changed;
- unsigned int width_a, height_a, stride_a;
- unsigned int width_b, height_b, stride_b;
- cairo_surface_t *surface_a, *surface_b, *surface_diff;
-
- surface_a = cairo_image_surface_create_from_png (filename_a);
- if (cairo_surface_status (surface_a))
- return -1;
-
- surface_b = cairo_image_surface_create_from_png (filename_b);
- if (cairo_surface_status (surface_b)) {
- cairo_surface_destroy (surface_a);
- return -1;
- }
-
- width_a = cairo_image_surface_get_width (surface_a) - ax;
- height_a = cairo_image_surface_get_height (surface_a) - ay;
- width_b = cairo_image_surface_get_width (surface_b) - bx;
- height_b = cairo_image_surface_get_height (surface_b) - by;
-
- if (width_a != width_b ||
- height_a != height_b)
- {
- cairo_test_log ("Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n"
- " for %s vs. %s\n",
- width_a, height_a,
- width_b, height_b,
- filename_a, filename_b);
- cairo_surface_destroy (surface_a);
- cairo_surface_destroy (surface_b);
- return -1;
- }
-
- if (flatten) {
- flatten_surface (&surface_a, ax, ay);
- flatten_surface (&surface_b, bx, by);
- ax = ay = bx = by = 0;
- }
-
- surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- width_a, height_a);
-
- stride_a = cairo_image_surface_get_stride (surface_a);
- stride_b = cairo_image_surface_get_stride (surface_b);
-
- pixels_changed = buffer_diff (cairo_image_surface_get_data (surface_a)
- + (ay * stride_a) + ax * 4,
- cairo_image_surface_get_data (surface_b)
- + (by * stride_b) + by * 4,
- cairo_image_surface_get_data (surface_diff),
- width_a, height_a,
- stride_a, stride_b,
- cairo_image_surface_get_stride (surface_diff));
-
- if (pixels_changed) {
- FILE *png_file;
-
- if (filename_diff)
- png_file = fopen (filename_diff, "wb");
- else
- png_file = stdout;
-
- cairo_surface_write_to_png_stream (surface_diff, stdio_write_func, png_file);
-
- if (png_file != stdout)
- fclose (png_file);
- } else {
- if (filename_diff)
- xunlink (filename_diff);
- }
-
- cairo_surface_destroy (surface_a);
- cairo_surface_destroy (surface_b);
- cairo_surface_destroy (surface_diff);
-
- return pixels_changed;
-}
-
-int
-image_diff (const char *filename_a,
- const char *filename_b,
- const char *filename_diff,
- int ax,
- int ay,
- int bx,
- int by)
-{
- return image_diff_core (filename_a, filename_b, filename_diff,
- ax, ay, bx, by,
- FALSE);
-}
-
-int
-image_diff_flattened (const char *filename_a,
- const char *filename_b,
- const char *filename_diff,
- int ax,
- int ay,
- int bx,
- int by)
-{
- return image_diff_core (filename_a, filename_b, filename_diff,
- ax, ay, bx, by,
- TRUE);
-}
diff --git a/boilerplate/buffer-diff.h b/boilerplate/buffer-diff.h
deleted file mode 100644
index 2be2b39..0000000
--- a/boilerplate/buffer-diff.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* 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 at theworths.org> */
-
-#ifndef BUFFER_DIFF_H
-#define BUFFER_DIFF_H
-
-/* Returns number of pixels changed.
- * Also fills in a "diff" buffer intended to visually show where the
- * images differ.
- */
-int
-buffer_diff (unsigned char *buf_a,
- unsigned char *buf_b,
- unsigned char *buf_diff,
- int width,
- int height,
- int stride_a,
- int stride_b,
- int stride_diff);
-
-/* Returns number of pixels changed ignoring the alpha channel.
- * Also fills in a "diff" buffer intended to visually show where the
- * images differ.
- */
-int
-buffer_diff_noalpha (unsigned char *buf_a,
- unsigned char *buf_b,
- unsigned char *buf_diff,
- int width,
- int height,
- int stride_a,
- int stride_b,
- int stride_diff);
-
-/* Returns number of pixels changed, (or -1 on error).
- * Also saves a "diff" image intended to visually show where the
- * images differ.
- */
-int
-image_diff (const char *filename_a,
- const char *filename_b,
- const char *filename_diff,
- int ax,
- int ay,
- int bx,
- int by);
-
-/* Like image_diff, but blending the contents of b over white first. */
-int
-image_diff_flattened (const char *filename_a,
- const char *filename_b,
- const char *filename_diff,
- int ax,
- int ay,
- int bx,
- int by);
-
-#endif
diff --git a/boilerplate/cairo-test.c b/boilerplate/cairo-test.c
deleted file mode 100644
index 0d915a5..0000000
--- a/boilerplate/cairo-test.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Copyright © 2004 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: Carl D. Worth <cworth at cworth.org>
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <setjmp.h>
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <assert.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#if HAVE_FCFINI
-#include <fontconfig/fontconfig.h>
-#endif
-
-#include "cairo-test.h"
-
-#include "buffer-diff.h"
-#include "xmalloc.h"
-
-/* This is copied from cairoint.h. That makes it painful to keep in
- * sync, but the slim stuff makes cairoint.h "hard" to include when
- * not actually building the cairo library itself. Fortunately, since
- * we're checking all these values, we do have a safeguard for keeping
- * them in sync.
- */
-typedef enum cairo_internal_surface_type {
- CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
- CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
- CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
- CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
- CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
- CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
-} cairo_internal_surface_type_t;
-
-#ifdef _MSC_VER
-#define vsnprintf _vsnprintf
-#define access _access
-#define F_OK 0
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE !FALSE
-#endif
-
-static void
-xunlink (const char *pathname);
-
-static const char *fail_face = "", *normal_face = "";
-
-#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"
-
-#define NUM_DEVICE_OFFSETS 2
-
-/* Static data is messy, but we're coding for tests here, not a
- * general-purpose library, and it keeps the tests cleaner to avoid a
- * context object there, (though not a whole lot). */
-FILE *cairo_test_log_file = NULL;
-const char *srcdir;
-
-/* Used to catch crashes in a test, such that we report it as such and
- * continue testing, although one crasher may already have corrupted memory in
- * an nonrecoverable fashion. */
-jmp_buf jmpbuf;
-
-void
-cairo_test_init (const char *test_name)
-{
- char *log_name;
-
- xasprintf (&log_name, "%s%s", test_name, CAIRO_TEST_LOG_SUFFIX);
- xunlink (log_name);
-
- cairo_test_log_file = fopen (log_name, "a");
- if (cairo_test_log_file == NULL) {
- fprintf (stderr, "Error opening log file: %s\n", log_name);
- cairo_test_log_file = stderr;
- }
- free (log_name);
-
- printf ("\nTESTING %s\n", test_name);
-}
-
-void
-cairo_test_log (const char *fmt, ...)
-{
- va_list va;
- FILE *file = cairo_test_log_file ? cairo_test_log_file : stderr;
-
- va_start (va, fmt);
- vfprintf (file, fmt, va);
- va_end (va);
-}
-
-static void
-xunlink (const char *pathname)
-{
- if (unlink (pathname) < 0 && errno != ENOENT) {
- cairo_test_log ("Error: Cannot remove %s: %s\n",
- pathname, strerror (errno));
- exit (1);
- }
-}
-
-static char *
-cairo_ref_name_for_test_target_format (const char *test_name,
- const char *target_name,
- const char *format)
-{
- char *ref_name = NULL;
-
- /* First look for a target/format-specific reference image. */
- xasprintf (&ref_name, "%s/%s-%s-%s%s", srcdir,
- test_name,
- target_name,
- format,
- CAIRO_TEST_REF_SUFFIX);
- if (access (ref_name, F_OK) != 0)
- free (ref_name);
- else
- goto done;
-
- /* Next, look for taget-specifc reference image. */
- xasprintf (&ref_name, "%s/%s-%s%s", srcdir,
- test_name,
- target_name,
- CAIRO_TEST_REF_SUFFIX);
- if (access (ref_name, F_OK) != 0)
- free (ref_name);
- else
- goto done;
-
- /* Next, look for format-specifc reference image. */
- xasprintf (&ref_name, "%s/%s-%s%s", srcdir,
- test_name,
- format,
- CAIRO_TEST_REF_SUFFIX);
- if (access (ref_name, F_OK) != 0)
- free (ref_name);
- else
- goto done;
-
- /* Finally, look for the standard reference image. */
- xasprintf (&ref_name, "%s/%s%s", srcdir,
- test_name,
- CAIRO_TEST_REF_SUFFIX);
- if (access (ref_name, F_OK) != 0)
- free (ref_name);
- else
- goto done;
-
- ref_name = NULL;
-
-done:
- return ref_name;
-}
-
-static cairo_test_status_t
-cairo_test_for_target (cairo_test_t *test,
- cairo_test_target_t *target,
- int dev_offset)
-{
- cairo_test_status_t status;
- cairo_surface_t *surface;
- cairo_t *cr;
- char *png_name, *ref_name, *diff_name, *offset_str;
- cairo_test_status_t ret;
- cairo_content_t expected_content;
- cairo_font_options_t *font_options;
- const char *format;
-
- /* Get the strings ready that we'll need. */
- format = _cairo_test_content_name (target->content);
- if (dev_offset)
- xasprintf (&offset_str, "-%d", dev_offset);
- else
- offset_str = strdup("");
-
- xasprintf (&png_name, "%s-%s-%s%s%s",
- test->name,
- target->name,
- format,
- offset_str, CAIRO_TEST_PNG_SUFFIX);
- ref_name = cairo_ref_name_for_test_target_format (test->name, target->name, format);
- xasprintf (&diff_name, "%s-%s-%s%s%s",
- test->name,
- target->name,
- format,
- offset_str, CAIRO_TEST_DIFF_SUFFIX);
-
- /* Run the actual drawing code. */
- if (test->width && test->height) {
- test->width += dev_offset;
- test->height += dev_offset;
- }
-
- surface = (target->create_target_surface) (test->name,
- target->content,
- test->width,
- test->height,
- &target->closure);
-
- if (test->width && test->height) {
- test->width -= dev_offset;
- test->height -= dev_offset;;
- }
-
- if (surface == NULL) {
- cairo_test_log ("Error: Failed to set %s target\n", target->name);
- ret = CAIRO_TEST_UNTESTED;
- goto UNWIND_STRINGS;
- }
-
- /* Check that we created a surface of the expected type. */
- if (cairo_surface_get_type (surface) != target->expected_type) {
- cairo_test_log ("Error: Created surface is of type %d (expected %d)\n",
- cairo_surface_get_type (surface), target->expected_type);
- ret = CAIRO_TEST_FAILURE;
- goto UNWIND_SURFACE;
- }
-
- /* Check that we created a surface of the expected content,
- * (ignore the articifical
- * CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value).
- */
- expected_content = target->content;
- if (expected_content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
- expected_content = CAIRO_CONTENT_COLOR_ALPHA;
-
- if (cairo_surface_get_content (surface) != expected_content) {
- cairo_test_log ("Error: Created surface has content %d (expected %d)\n",
- cairo_surface_get_content (surface), expected_content);
- ret = CAIRO_TEST_FAILURE;
- goto UNWIND_SURFACE;
- }
-
- cairo_surface_set_device_offset (surface, dev_offset, dev_offset);
-
- cr = cairo_create (surface);
-
- /* Clear to transparent (or black) depending on whether the target
- * surface supports alpha. */
- cairo_save (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
- cairo_paint (cr);
- cairo_restore (cr);
-
- /* Set all components of font_options to avoid backend differences
- * and reduce number of needed reference images. */
- font_options = cairo_font_options_create ();
- cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
- cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON);
- cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
- cairo_set_font_options (cr, font_options);
- cairo_font_options_destroy (font_options);
-
- status = (test->draw) (cr, test->width, test->height);
-
- /* Then, check all the different ways it could fail. */
- if (status) {
- cairo_test_log ("Error: Function under test failed\n");
- ret = status;
- goto UNWIND_CAIRO;
- }
-
- cairo_show_page (cr);
-
- if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
- cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n",
- cairo_status_to_string (cairo_status (cr)));
- ret = CAIRO_TEST_FAILURE;
- goto UNWIND_CAIRO;
- }
-
- /* Skip image check for tests with no image (width,height == 0,0) */
- if (test->width != 0 && test->height != 0) {
- int pixels_changed;
- xunlink (png_name);
- (target->write_to_png) (surface, png_name);
-
- if (!ref_name) {
- cairo_test_log ("Error: Cannot find reference image for %s/%s-%s-%s%s\n",srcdir,
- test->name,
- target->name,
- format,
- CAIRO_TEST_REF_SUFFIX);
- ret = CAIRO_TEST_FAILURE;
- goto UNWIND_CAIRO;
- }
-
- if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
- pixels_changed = image_diff_flattened (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0);
- else
- pixels_changed = image_diff (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0);
- if (pixels_changed) {
- if (pixels_changed > 0)
- cairo_test_log ("Error: %d pixels differ from reference image %s\n",
- pixels_changed, ref_name);
- ret = CAIRO_TEST_FAILURE;
- goto UNWIND_CAIRO;
- }
- }
-
- ret = CAIRO_TEST_SUCCESS;
-
-UNWIND_CAIRO:
- cairo_destroy (cr);
-UNWIND_SURFACE:
- cairo_surface_destroy (surface);
-
- cairo_debug_reset_static_data ();
-
- if (target->cleanup_target)
- target->cleanup_target (target->closure);
-
-UNWIND_STRINGS:
- if (png_name)
- free (png_name);
- if (ref_name)
- free (ref_name);
- if (diff_name)
- free (diff_name);
- if (offset_str)
- free (offset_str);
-
- return ret;
-}
-
-#ifdef HAVE_SIGNAL_H
-static void
-segfault_handler (int signal)
-{
- longjmp (jmpbuf, signal);
-}
-#endif
-
-static cairo_test_status_t
-cairo_test_expecting (cairo_test_t *test,
- cairo_test_status_t expectation)
-{
- /* we use volatile here to make sure values are not clobbered
- * by longjmp */
- volatile size_t i, j, num_targets;
- volatile cairo_bool_t limited_targets = FALSE, print_fail_on_stdout = TRUE;
- const char *tname;
-#ifdef HAVE_SIGNAL_H
- void (*old_segfault_handler)(int);
-#endif
- volatile cairo_test_status_t status, ret;
- cairo_test_target_t ** volatile targets_to_test;
-
-#ifdef HAVE_UNISTD_H
- if (isatty (2)) {
- fail_face = "\033[41m\033[37m\033[1m";
- normal_face = "\033[m";
- if (isatty (1))
- print_fail_on_stdout = FALSE;
- }
-#endif
-
- srcdir = getenv ("srcdir");
- if (!srcdir)
- srcdir = ".";
-
- cairo_test_init (test->name);
- printf ("%s\n", test->description);
-
- if (expectation == CAIRO_TEST_FAILURE)
- printf ("Expecting failure\n");
-
- if ((tname = getenv ("CAIRO_TEST_TARGET")) != NULL && *tname) {
-
- limited_targets = TRUE;
-
- num_targets = 0;
- targets_to_test = NULL;
-
- while (*tname) {
- int found = 0;
- const char *end = strpbrk (tname, " \t\r\n;:,");
- if (!end)
- end = tname + strlen (tname);
-
- for (i = 0; targets[i].name != NULL; i++) {
- if (0 == strncmp (targets[i].name, tname, end - tname) &&
- !isalnum (targets[i].name[end - tname])) {
- /* realloc isn't exactly the best thing here, but meh. */
- targets_to_test = realloc (targets_to_test, sizeof(cairo_test_target_t *) * (num_targets+1));
- targets_to_test[num_targets++] = &targets[i];
- found = 1;
- }
- }
-
- if (!found) {
- fprintf (stderr, "Cannot test target '%.*s'\n", (int)(end - tname), tname);
- exit(-1);
- }
-
- if (*end)
- end++;
- tname = end;
- }
- } else {
- num_targets = 0;
- for (i = 0; targets[i].name != NULL; i++)
- num_targets++;
- targets_to_test = malloc (sizeof(cairo_test_target_t*) * num_targets);
- for (i = 0; i < num_targets; i++) {
- targets_to_test[i] = &targets[i];
- }
- }
-
- /* The intended logic here is that we return overall SUCCESS
- * iff. there is at least one tested backend and that all tested
- * backends return SUCCESS, OR, there's no backend to test at all.
- * In other words:
- *
- * if no backend to test
- * -> SUCCESS
- * else if any backend not SUCCESS
- * -> FAILURE
- * else if all backends UNTESTED
- * -> FAILURE
- * else (== some backend SUCCESS)
- * -> SUCCESS
- */
- ret = CAIRO_TEST_UNTESTED;
- for (i = 0; i < num_targets; i++) {
- for (j = 0; j < NUM_DEVICE_OFFSETS; j++) {
- cairo_test_target_t * volatile target = targets_to_test[i];
- volatile int dev_offset = j * 25;
-
- cairo_test_log ("Testing %s with %s target (dev offset %d)\n", test->name, target->name, dev_offset);
- printf ("%s-%s-%s [%d]:\t", test->name, target->name,
- _cairo_test_content_name (target->content),
- dev_offset);
-
-#ifdef HAVE_SIGNAL_H
- /* Set up a checkpoint to get back to in case of segfaults. */
- old_segfault_handler = signal (SIGSEGV, segfault_handler);
- if (0 == setjmp (jmpbuf))
-#endif
- status = cairo_test_for_target (test, target, dev_offset);
-#ifdef HAVE_SIGNAL_H
- else
- status = CAIRO_TEST_CRASHED;
- signal (SIGSEGV, old_segfault_handler);
-#endif
-
- cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s OFFSET: %d RESULT: ",
- test->name, target->name,
- _cairo_test_content_name (target->content),
- dev_offset);
-
- switch (status) {
- case CAIRO_TEST_SUCCESS:
- printf ("PASS\n");
- cairo_test_log ("PASS\n");
- if (ret == CAIRO_TEST_UNTESTED)
- ret = CAIRO_TEST_SUCCESS;
- break;
- case CAIRO_TEST_UNTESTED:
- printf ("UNTESTED\n");
- cairo_test_log ("UNTESTED\n");
- break;
- case CAIRO_TEST_CRASHED:
- if (print_fail_on_stdout) {
- printf ("!!!CRASHED!!!\n");
- } else {
- /* eat the test name */
- printf ("\r");
- fflush (stdout);
- }
- cairo_test_log ("CRASHED\n");
- fprintf (stderr, "%s-%s-%s [%d]:\t%s!!!CRASHED!!!%s\n",
- test->name, target->name,
- _cairo_test_content_name (target->content), dev_offset,
- fail_face, normal_face);
- ret = CAIRO_TEST_FAILURE;
- break;
- default:
- case CAIRO_TEST_FAILURE:
- if (expectation == CAIRO_TEST_FAILURE) {
- printf ("XFAIL\n");
- cairo_test_log ("XFAIL\n");
- } else {
- if (print_fail_on_stdout) {
- printf ("FAIL\n");
- } else {
- /* eat the test name */
- printf ("\r");
- fflush (stdout);
- }
- fprintf (stderr, "%s-%s-%s [%d]:\t%sFAIL%s\n",
- test->name, target->name,
- _cairo_test_content_name (target->content), dev_offset,
- fail_face, normal_face);
- cairo_test_log ("FAIL\n");
- }
- ret = status;
- break;
- }
- }
- }
-
- if (ret != CAIRO_TEST_SUCCESS)
- printf ("Check %s%s out for more information.\n", test->name, CAIRO_TEST_LOG_SUFFIX);
-
- /* if no target was requested for test, succeed, otherwise if all
- * were untested, fail. */
- if (ret == CAIRO_TEST_UNTESTED)
- ret = num_targets ? CAIRO_TEST_FAILURE : CAIRO_TEST_SUCCESS;
-
- /* if targets are limited using CAIRO_TEST_TARGET, and expecting failure,
- * make it fail, such that we can pass test suite by limiting backends
- * to test without triggering XPASS failures. */
- if (limited_targets && expectation == CAIRO_TEST_FAILURE && ret == CAIRO_TEST_SUCCESS) {
- printf ("All tested backends passed, but tested targets are manually limited\n"
- "and the test suite expects this test to fail for at least one target.\n"
- "Intentionally failing the test, to not fail the suite.\n");
- ret = CAIRO_TEST_FAILURE;
- }
-
- fclose (cairo_test_log_file);
-
- free (targets_to_test);
-
-#if HAVE_FCFINI
- FcFini ();
-#endif
-
- return ret;
-}
-
-cairo_test_status_t
-cairo_test (cairo_test_t *test)
-{
- cairo_test_status_t expectation = CAIRO_TEST_SUCCESS;
- const char *xfails;
-
- if ((xfails = getenv ("CAIRO_XFAIL_TESTS")) != NULL) {
- while (*xfails) {
- const char *end = strpbrk (xfails, " \t\r\n;:,");
- if (!end)
- end = xfails + strlen (xfails);
-
- if (0 == strncmp (test->name, xfails, end - xfails) &&
- '\0' == test->name[end - xfails]) {
- expectation = CAIRO_TEST_FAILURE;
- break;
- }
-
- if (*end)
- end++;
- xfails = end;
- }
- }
-
- return cairo_test_expecting (test, expectation);
-}
-
-cairo_surface_t *
-cairo_test_create_surface_from_png (const char *filename)
-{
- cairo_surface_t *image;
- char *srcdir = getenv ("srcdir");
-
- image = cairo_image_surface_create_from_png (filename);
- if (cairo_surface_status(image)) {
- /* expect not found when running with srcdir != builddir
- * such as when 'make distcheck' is run
- */
- if (srcdir) {
- char *srcdir_filename;
- xasprintf (&srcdir_filename, "%s/%s", srcdir, filename);
- image = cairo_image_surface_create_from_png (srcdir_filename);
- free (srcdir_filename);
- }
- if (cairo_surface_status(image))
- return NULL;
- }
-
- return image;
-}
-
-cairo_pattern_t *
-cairo_test_create_pattern_from_png (const char *filename)
-{
- cairo_surface_t *image;
- cairo_pattern_t *pattern;
-
- image = cairo_test_create_surface_from_png (filename);
-
- pattern = cairo_pattern_create_for_surface (image);
-
- cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-
- cairo_surface_destroy (image);
-
- return pattern;
-}
-
-static cairo_status_t
-_draw_check (cairo_surface_t *surface, int width, int height)
-{
- cairo_t *cr;
- cairo_status_t status;
-
- cr = cairo_create (surface);
- cairo_set_source_rgb (cr, 0.75, 0.75, 0.75); /* light gray */
- cairo_paint (cr);
-
- cairo_set_source_rgb (cr, 0.25, 0.25, 0.25); /* dark gray */
- cairo_rectangle (cr, width / 2, 0, width / 2, height / 2);
- cairo_rectangle (cr, 0, height / 2, width / 2, height / 2);
- cairo_fill (cr);
-
- status = cairo_status (cr);
-
- cairo_destroy (cr);
-
- return status;
-}
-
-cairo_status_t
-cairo_test_paint_checkered (cairo_t *cr)
-{
- cairo_status_t status;
- cairo_surface_t *check;
-
- check = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 12, 12);
- status = _draw_check (check, 12, 12);
- if (status)
- return status;
-
- cairo_save (cr);
- cairo_set_source_surface (cr, check, 0, 0);
- cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
- cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
- cairo_paint (cr);
- cairo_restore (cr);
-
- cairo_surface_destroy (check);
-
- return CAIRO_STATUS_SUCCESS;
-}
diff --git a/boilerplate/cairo-test.h b/boilerplate/cairo-test.h
deleted file mode 100644
index 75eadb4..0000000
--- a/boilerplate/cairo-test.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright © 2004 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: Carl D. Worth <cworth at cworth.org>
- */
-
-#ifndef _CAIRO_TEST_H_
-#define _CAIRO_TEST_H_
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include <cairo.h>
-
-#define CAIRO_BOILERPLATE_LOG(...) cairo_test_log (__VA_ARGS__)
-#include "cairo-boilerplate.h"
-
-CAIRO_BEGIN_DECLS
-
-#if HAVE_STDINT_H
-# include <stdint.h>
-#elif HAVE_INTTYPES_H
-# include <inttypes.h>
-#elif HAVE_SYS_INT_TYPES_H
-# include <sys/int_types.h>
-#elif defined(_MSC_VER)
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-# ifndef HAVE_UINT64_T
-# define HAVE_UINT64_T 1
-# endif
-#else
-#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, \etc.)
-#endif
-
-typedef enum cairo_test_status {
- CAIRO_TEST_SUCCESS = 0,
- CAIRO_TEST_FAILURE,
- CAIRO_TEST_UNTESTED,
- CAIRO_TEST_CRASHED
-} cairo_test_status_t;
-
-typedef cairo_test_status_t (cairo_test_draw_function_t) (cairo_t *cr, int width, int height);
-
-typedef struct _cairo_test {
- const char *name;
- const char *description;
- int width;
- int height;
- cairo_test_draw_function_t *draw;
-} cairo_test_t;
-
-/* The standard test interface which works by examining result image.
- *
- * cairo_test() accepts a test struct which will be called once for
- * each testable backend. The following checks will be performed for
- * each backend:
- *
- * 1) If draw() does not return CAIRO_TEST_SUCCESS then this backend
- * fails.
- *
- * 2) Otherwise, if cairo_status(cr) indicates an error then this
- * backend fails.
- *
- * 3) Otherwise, if the image size is 0, then this backend passes.
- *
- * 4) Otherwise, if every channel of every pixel exactly matches the
- * reference image then this backend passes. If not, this backend
- * fails.
- *
- * The overall test result is PASS if and only if there is at least
- * one backend that is tested and if all tested backend pass according
- * to the four criteria above.
- */
-cairo_test_status_t
-cairo_test (cairo_test_t *test);
-
-/* cairo_test_init() and cairo_test_log() exist to help in writing
- * tests for which cairo_test() is not appropriate for one reason or
- * another. For example, some tests might not be doing any drawing at
- * all, or may need to create their own cairo_t rather than be handed
- * one by cairo_test.
- */
-
-/* Initialize test-specific resources, (log files, etc.) */
-void
-cairo_test_init (const char *test_name);
-
-/* Print a message to the log file, ala printf. */
-void
-cairo_test_log (const char *fmt, ...) CAIRO_PRINTF_FORMAT(1, 2);
-
-/* Helper functions that take care of finding source images even when
- * building in a non-srcdir manner, (ie. the tests will be run in a
- * directory that is different from the one where the source image
- * exists). */
-cairo_surface_t *
-cairo_test_create_surface_from_png (const char *filename);
-
-cairo_pattern_t *
-cairo_test_create_pattern_from_png (const char *filename);
-
-cairo_status_t
-cairo_test_paint_checkered (cairo_t *cr);
-
-CAIRO_END_DECLS
-
-#endif
diff --git a/boilerplate/xmalloc.c b/boilerplate/xmalloc.c
index e98541c..10d1cef 100644
--- a/boilerplate/xmalloc.c
+++ b/boilerplate/xmalloc.c
@@ -26,7 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include "cairo-test.h"
+#include "cairo-boilerplate.h"
#include "xmalloc.h"
void *
@@ -36,7 +36,7 @@ xmalloc (size_t size)
buf = malloc (size);
if (!buf) {
- cairo_test_log ("Error: Out of memory. Exiting.\n");
+ CAIRO_BOILERPLATE_LOG ("Error: Out of memory. Exiting.\n");
exit (1);
}
@@ -50,7 +50,7 @@ xcalloc (size_t nmemb, size_t size)
buf = calloc (nmemb, size);
if (!buf) {
- cairo_test_log ("Error: Out of memory. Exiting\n");
+ CAIRO_BOILERPLATE_LOG ("Error: Out of memory. Exiting\n");
exit (1);
}
diff --git a/test/Makefile.am b/test/Makefile.am
index 54834c9..f595dcd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -375,12 +375,23 @@ SUPPORT_PROGS =
# problem.
INCLUDES = \
-D_GNU_SOURCE \
+ -I$(srcdir) \
-I$(top_srcdir)/boilerplate \
-I$(top_srcdir)/pixman/src \
-I$(top_srcdir)/src \
$(CAIRO_CFLAGS)
-LDADD = $(top_builddir)/boilerplate/libcairotest.la $(top_builddir)/src/libcairo.la
+EXTRA_LTLIBRARIES = libcairotest.la
+
+libcairotest_la_SOURCES =\
+ buffer-diff.c \
+ buffer-diff.h \
+ cairo-test.c \
+ cairo-test.h
+
+LDADD = libcairotest.la \
+ $(top_builddir)/boilerplate/libcairoboilerplate.la \
+ $(top_builddir)/src/libcairo.la
if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
LDADD += $(GLITZ_AGL_LIBS)
diff --git a/test/buffer-diff.c b/test/buffer-diff.c
new file mode 100644
index 0000000..b59b5e8
--- /dev/null
+++ b/test/buffer-diff.c
@@ -0,0 +1,306 @@
+/* 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 at theworths.org> */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#include <pixman.h>
+
+#include "cairo-test.h"
+
+#include "buffer-diff.h"
+#include "xmalloc.h"
+
+static void
+xunlink (const char *pathname)
+{
+ if (unlink (pathname) < 0 && errno != ENOENT) {
+ cairo_test_log (" Error: Cannot remove %s: %s\n",
+ pathname, strerror (errno));
+ exit (1);
+ }
+}
+
+/* This function should be rewritten to compare all formats supported by
+ * cairo_format_t instead of taking a mask as a parameter.
+ */
+static int
+buffer_diff_core (unsigned char *_buf_a,
+ unsigned char *_buf_b,
+ unsigned char *_buf_diff,
+ int width,
+ int height,
+ int stride_a,
+ int stride_b,
+ int stride_diff,
+ pixman_bits_t mask)
+{
+ int x, y;
+ pixman_bits_t *row_a, *row_b, *row;
+ int pixels_changed = 0;
+ pixman_bits_t *buf_a = (pixman_bits_t*)_buf_a;
+ pixman_bits_t *buf_b = (pixman_bits_t*)_buf_b;
+ pixman_bits_t *buf_diff = (pixman_bits_t*)_buf_diff;
+
+ stride_a /= sizeof(pixman_bits_t);
+ stride_b /= sizeof(pixman_bits_t);
+ stride_diff /= sizeof(pixman_bits_t);
+ for (y = 0; y < height; y++)
+ {
+ row_a = buf_a + y * stride_a;
+ row_b = buf_b + y * stride_b;
+ row = buf_diff + y * stride_diff;
+ for (x = 0; x < width; x++)
+ {
+ /* check if the pixels are the same */
+ if ((row_a[x] & mask) != (row_b[x] & mask)) {
+ int channel;
+ pixman_bits_t diff_pixel = 0;
+
+ /* calculate a difference value for all 4 channels */
+ for (channel = 0; channel < 4; channel++) {
+ int value_a = (row_a[x] >> (channel*8)) & 0xff;
+ int value_b = (row_b[x] >> (channel*8)) & 0xff;
+ unsigned int diff;
+ diff = abs (value_a - value_b);
+ diff *= 4; /* emphasize */
+ if (diff)
+ diff += 128; /* make sure it's visible */
+ if (diff > 255)
+ diff = 255;
+ diff_pixel |= diff << (channel*8);
+ }
+
+ pixels_changed++;
+ row[x] = diff_pixel;
+ } else {
+ row[x] = 0;
+ }
+ row[x] |= 0xff000000; /* Set ALPHA to 100% (opaque) */
+ }
+ }
+
+ return pixels_changed;
+}
+
+int
+buffer_diff (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride_a,
+ int stride_b,
+ int stride_diff)
+{
+ return buffer_diff_core(buf_a, buf_b, buf_diff,
+ width, height, stride_a, stride_b, stride_diff, 0xffffffff);
+}
+
+int
+buffer_diff_noalpha (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride_a,
+ int stride_b,
+ int stride_diff)
+{
+ return buffer_diff_core(buf_a, buf_b, buf_diff,
+ width, height, stride_a, stride_b, stride_diff, 0x00ffffff);
+}
+
+static cairo_status_t
+stdio_write_func (void *closure, const unsigned char *data, unsigned int length)
+{
+ FILE *file = closure;
+
+ if (fwrite (data, 1, length, file) != length)
+ return CAIRO_STATUS_WRITE_ERROR;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Flatten an ARGB surface by blending it over white. The resulting
+ * surface, (still in ARGB32 format, but with only alpha==1.0
+ * everywhere) is returned in the same surface pointer.
+ *
+ * The original surface will be destroyed.
+ *
+ * The (x,y) value specify an origin of interest for the original
+ * image. The flattened image will be generated only from the box
+ * extending from (x,y) to (width,height).
+ */
+static void
+flatten_surface (cairo_surface_t **surface, int x, int y)
+{
+ cairo_surface_t *flat;
+ cairo_t *cr;
+
+ flat = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ cairo_image_surface_get_width (*surface) - x,
+ cairo_image_surface_get_height (*surface) - y);
+ cairo_surface_set_device_offset (flat, -x, -y);
+
+ cr = cairo_create (flat);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_surface (cr, *surface, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_destroy (*surface);
+ *surface = flat;
+}
+
+/* Image comparison code courtesy of Richard Worth <richard at theworths.org>
+ * Returns number of pixels changed, (or -1 on error).
+ * Also saves a "diff" image intended to visually show where the
+ * images differ.
+ */
+static int
+image_diff_core (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by,
+ cairo_bool_t flatten)
+{
+ int pixels_changed;
+ unsigned int width_a, height_a, stride_a;
+ unsigned int width_b, height_b, stride_b;
+ cairo_surface_t *surface_a, *surface_b, *surface_diff;
+
+ surface_a = cairo_image_surface_create_from_png (filename_a);
+ if (cairo_surface_status (surface_a))
+ return -1;
+
+ surface_b = cairo_image_surface_create_from_png (filename_b);
+ if (cairo_surface_status (surface_b)) {
+ cairo_surface_destroy (surface_a);
+ return -1;
+ }
+
+ width_a = cairo_image_surface_get_width (surface_a) - ax;
+ height_a = cairo_image_surface_get_height (surface_a) - ay;
+ width_b = cairo_image_surface_get_width (surface_b) - bx;
+ height_b = cairo_image_surface_get_height (surface_b) - by;
+
+ if (width_a != width_b ||
+ height_a != height_b)
+ {
+ cairo_test_log ("Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n"
+ " for %s vs. %s\n",
+ width_a, height_a,
+ width_b, height_b,
+ filename_a, filename_b);
+ cairo_surface_destroy (surface_a);
+ cairo_surface_destroy (surface_b);
+ return -1;
+ }
+
+ if (flatten) {
+ flatten_surface (&surface_a, ax, ay);
+ flatten_surface (&surface_b, bx, by);
+ ax = ay = bx = by = 0;
+ }
+
+ surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width_a, height_a);
+
+ stride_a = cairo_image_surface_get_stride (surface_a);
+ stride_b = cairo_image_surface_get_stride (surface_b);
+
+ pixels_changed = buffer_diff (cairo_image_surface_get_data (surface_a)
+ + (ay * stride_a) + ax * 4,
+ cairo_image_surface_get_data (surface_b)
+ + (by * stride_b) + by * 4,
+ cairo_image_surface_get_data (surface_diff),
+ width_a, height_a,
+ stride_a, stride_b,
+ cairo_image_surface_get_stride (surface_diff));
+
+ if (pixels_changed) {
+ FILE *png_file;
+
+ if (filename_diff)
+ png_file = fopen (filename_diff, "wb");
+ else
+ png_file = stdout;
+
+ cairo_surface_write_to_png_stream (surface_diff, stdio_write_func, png_file);
+
+ if (png_file != stdout)
+ fclose (png_file);
+ } else {
+ if (filename_diff)
+ xunlink (filename_diff);
+ }
+
+ cairo_surface_destroy (surface_a);
+ cairo_surface_destroy (surface_b);
+ cairo_surface_destroy (surface_diff);
+
+ return pixels_changed;
+}
+
+int
+image_diff (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by)
+{
+ return image_diff_core (filename_a, filename_b, filename_diff,
+ ax, ay, bx, by,
+ FALSE);
+}
+
+int
+image_diff_flattened (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by)
+{
+ return image_diff_core (filename_a, filename_b, filename_diff,
+ ax, ay, bx, by,
+ TRUE);
+}
diff --git a/test/buffer-diff.h b/test/buffer-diff.h
new file mode 100644
index 0000000..2be2b39
--- /dev/null
+++ b/test/buffer-diff.h
@@ -0,0 +1,80 @@
+/* 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 at theworths.org> */
+
+#ifndef BUFFER_DIFF_H
+#define BUFFER_DIFF_H
+
+/* Returns number of pixels changed.
+ * Also fills in a "diff" buffer intended to visually show where the
+ * images differ.
+ */
+int
+buffer_diff (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride_a,
+ int stride_b,
+ int stride_diff);
+
+/* Returns number of pixels changed ignoring the alpha channel.
+ * Also fills in a "diff" buffer intended to visually show where the
+ * images differ.
+ */
+int
+buffer_diff_noalpha (unsigned char *buf_a,
+ unsigned char *buf_b,
+ unsigned char *buf_diff,
+ int width,
+ int height,
+ int stride_a,
+ int stride_b,
+ int stride_diff);
+
+/* Returns number of pixels changed, (or -1 on error).
+ * Also saves a "diff" image intended to visually show where the
+ * images differ.
+ */
+int
+image_diff (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by);
+
+/* Like image_diff, but blending the contents of b over white first. */
+int
+image_diff_flattened (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by);
+
+#endif
diff --git a/test/cairo-test.c b/test/cairo-test.c
new file mode 100644
index 0000000..0d915a5
--- /dev/null
+++ b/test/cairo-test.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright © 2004 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: Carl D. Worth <cworth at cworth.org>
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <setjmp.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#if HAVE_FCFINI
+#include <fontconfig/fontconfig.h>
+#endif
+
+#include "cairo-test.h"
+
+#include "buffer-diff.h"
+#include "xmalloc.h"
+
+/* This is copied from cairoint.h. That makes it painful to keep in
+ * sync, but the slim stuff makes cairoint.h "hard" to include when
+ * not actually building the cairo library itself. Fortunately, since
+ * we're checking all these values, we do have a safeguard for keeping
+ * them in sync.
+ */
+typedef enum cairo_internal_surface_type {
+ CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
+ CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
+ CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
+ CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+ CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
+} cairo_internal_surface_type_t;
+
+#ifdef _MSC_VER
+#define vsnprintf _vsnprintf
+#define access _access
+#define F_OK 0
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE !FALSE
+#endif
+
+static void
+xunlink (const char *pathname);
+
+static const char *fail_face = "", *normal_face = "";
+
+#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"
+
+#define NUM_DEVICE_OFFSETS 2
+
+/* Static data is messy, but we're coding for tests here, not a
+ * general-purpose library, and it keeps the tests cleaner to avoid a
+ * context object there, (though not a whole lot). */
+FILE *cairo_test_log_file = NULL;
+const char *srcdir;
+
+/* Used to catch crashes in a test, such that we report it as such and
+ * continue testing, although one crasher may already have corrupted memory in
+ * an nonrecoverable fashion. */
+jmp_buf jmpbuf;
+
+void
+cairo_test_init (const char *test_name)
+{
+ char *log_name;
+
+ xasprintf (&log_name, "%s%s", test_name, CAIRO_TEST_LOG_SUFFIX);
+ xunlink (log_name);
+
+ cairo_test_log_file = fopen (log_name, "a");
+ if (cairo_test_log_file == NULL) {
+ fprintf (stderr, "Error opening log file: %s\n", log_name);
+ cairo_test_log_file = stderr;
+ }
+ free (log_name);
+
+ printf ("\nTESTING %s\n", test_name);
+}
+
+void
+cairo_test_log (const char *fmt, ...)
+{
+ va_list va;
+ FILE *file = cairo_test_log_file ? cairo_test_log_file : stderr;
+
+ va_start (va, fmt);
+ vfprintf (file, fmt, va);
+ va_end (va);
+}
+
+static void
+xunlink (const char *pathname)
+{
+ if (unlink (pathname) < 0 && errno != ENOENT) {
+ cairo_test_log ("Error: Cannot remove %s: %s\n",
+ pathname, strerror (errno));
+ exit (1);
+ }
+}
+
+static char *
+cairo_ref_name_for_test_target_format (const char *test_name,
+ const char *target_name,
+ const char *format)
+{
+ char *ref_name = NULL;
+
+ /* First look for a target/format-specific reference image. */
+ xasprintf (&ref_name, "%s/%s-%s-%s%s", srcdir,
+ test_name,
+ target_name,
+ format,
+ CAIRO_TEST_REF_SUFFIX);
+ if (access (ref_name, F_OK) != 0)
+ free (ref_name);
+ else
+ goto done;
+
+ /* Next, look for taget-specifc reference image. */
+ xasprintf (&ref_name, "%s/%s-%s%s", srcdir,
+ test_name,
+ target_name,
+ CAIRO_TEST_REF_SUFFIX);
+ if (access (ref_name, F_OK) != 0)
+ free (ref_name);
+ else
+ goto done;
+
+ /* Next, look for format-specifc reference image. */
+ xasprintf (&ref_name, "%s/%s-%s%s", srcdir,
+ test_name,
+ format,
+ CAIRO_TEST_REF_SUFFIX);
+ if (access (ref_name, F_OK) != 0)
+ free (ref_name);
+ else
+ goto done;
+
+ /* Finally, look for the standard reference image. */
+ xasprintf (&ref_name, "%s/%s%s", srcdir,
+ test_name,
+ CAIRO_TEST_REF_SUFFIX);
+ if (access (ref_name, F_OK) != 0)
+ free (ref_name);
+ else
+ goto done;
+
+ ref_name = NULL;
+
+done:
+ return ref_name;
+}
+
+static cairo_test_status_t
+cairo_test_for_target (cairo_test_t *test,
+ cairo_test_target_t *target,
+ int dev_offset)
+{
+ cairo_test_status_t status;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ char *png_name, *ref_name, *diff_name, *offset_str;
+ cairo_test_status_t ret;
+ cairo_content_t expected_content;
+ cairo_font_options_t *font_options;
+ const char *format;
+
+ /* Get the strings ready that we'll need. */
+ format = _cairo_test_content_name (target->content);
+ if (dev_offset)
+ xasprintf (&offset_str, "-%d", dev_offset);
+ else
+ offset_str = strdup("");
+
+ xasprintf (&png_name, "%s-%s-%s%s%s",
+ test->name,
+ target->name,
+ format,
+ offset_str, CAIRO_TEST_PNG_SUFFIX);
+ ref_name = cairo_ref_name_for_test_target_format (test->name, target->name, format);
+ xasprintf (&diff_name, "%s-%s-%s%s%s",
+ test->name,
+ target->name,
+ format,
+ offset_str, CAIRO_TEST_DIFF_SUFFIX);
+
+ /* Run the actual drawing code. */
+ if (test->width && test->height) {
+ test->width += dev_offset;
+ test->height += dev_offset;
+ }
+
+ surface = (target->create_target_surface) (test->name,
+ target->content,
+ test->width,
+ test->height,
+ &target->closure);
+
+ if (test->width && test->height) {
+ test->width -= dev_offset;
+ test->height -= dev_offset;;
+ }
+
+ if (surface == NULL) {
+ cairo_test_log ("Error: Failed to set %s target\n", target->name);
+ ret = CAIRO_TEST_UNTESTED;
+ goto UNWIND_STRINGS;
+ }
+
+ /* Check that we created a surface of the expected type. */
+ if (cairo_surface_get_type (surface) != target->expected_type) {
+ cairo_test_log ("Error: Created surface is of type %d (expected %d)\n",
+ cairo_surface_get_type (surface), target->expected_type);
+ ret = CAIRO_TEST_FAILURE;
+ goto UNWIND_SURFACE;
+ }
+
+ /* Check that we created a surface of the expected content,
+ * (ignore the articifical
+ * CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value).
+ */
+ expected_content = target->content;
+ if (expected_content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
+ expected_content = CAIRO_CONTENT_COLOR_ALPHA;
+
+ if (cairo_surface_get_content (surface) != expected_content) {
+ cairo_test_log ("Error: Created surface has content %d (expected %d)\n",
+ cairo_surface_get_content (surface), expected_content);
+ ret = CAIRO_TEST_FAILURE;
+ goto UNWIND_SURFACE;
+ }
+
+ cairo_surface_set_device_offset (surface, dev_offset, dev_offset);
+
+ cr = cairo_create (surface);
+
+ /* Clear to transparent (or black) depending on whether the target
+ * surface supports alpha. */
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ /* Set all components of font_options to avoid backend differences
+ * and reduce number of needed reference images. */
+ font_options = cairo_font_options_create ();
+ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON);
+ cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ status = (test->draw) (cr, test->width, test->height);
+
+ /* Then, check all the different ways it could fail. */
+ if (status) {
+ cairo_test_log ("Error: Function under test failed\n");
+ ret = status;
+ goto UNWIND_CAIRO;
+ }
+
+ cairo_show_page (cr);
+
+ if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
+ cairo_test_log ("Error: Function under test left cairo status in an error state: %s\n",
+ cairo_status_to_string (cairo_status (cr)));
+ ret = CAIRO_TEST_FAILURE;
+ goto UNWIND_CAIRO;
+ }
+
+ /* Skip image check for tests with no image (width,height == 0,0) */
+ if (test->width != 0 && test->height != 0) {
+ int pixels_changed;
+ xunlink (png_name);
+ (target->write_to_png) (surface, png_name);
+
+ if (!ref_name) {
+ cairo_test_log ("Error: Cannot find reference image for %s/%s-%s-%s%s\n",srcdir,
+ test->name,
+ target->name,
+ format,
+ CAIRO_TEST_REF_SUFFIX);
+ ret = CAIRO_TEST_FAILURE;
+ goto UNWIND_CAIRO;
+ }
+
+ if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
+ pixels_changed = image_diff_flattened (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0);
+ else
+ pixels_changed = image_diff (png_name, ref_name, diff_name, dev_offset, dev_offset, 0, 0);
+ if (pixels_changed) {
+ if (pixels_changed > 0)
+ cairo_test_log ("Error: %d pixels differ from reference image %s\n",
+ pixels_changed, ref_name);
+ ret = CAIRO_TEST_FAILURE;
+ goto UNWIND_CAIRO;
+ }
+ }
+
+ ret = CAIRO_TEST_SUCCESS;
+
+UNWIND_CAIRO:
+ cairo_destroy (cr);
+UNWIND_SURFACE:
+ cairo_surface_destroy (surface);
+
+ cairo_debug_reset_static_data ();
+
+ if (target->cleanup_target)
+ target->cleanup_target (target->closure);
+
+UNWIND_STRINGS:
+ if (png_name)
+ free (png_name);
+ if (ref_name)
+ free (ref_name);
+ if (diff_name)
+ free (diff_name);
+ if (offset_str)
+ free (offset_str);
+
+ return ret;
+}
+
+#ifdef HAVE_SIGNAL_H
+static void
+segfault_handler (int signal)
+{
+ longjmp (jmpbuf, signal);
+}
+#endif
+
+static cairo_test_status_t
+cairo_test_expecting (cairo_test_t *test,
+ cairo_test_status_t expectation)
+{
+ /* we use volatile here to make sure values are not clobbered
+ * by longjmp */
+ volatile size_t i, j, num_targets;
+ volatile cairo_bool_t limited_targets = FALSE, print_fail_on_stdout = TRUE;
+ const char *tname;
+#ifdef HAVE_SIGNAL_H
+ void (*old_segfault_handler)(int);
+#endif
+ volatile cairo_test_status_t status, ret;
+ cairo_test_target_t ** volatile targets_to_test;
+
+#ifdef HAVE_UNISTD_H
+ if (isatty (2)) {
+ fail_face = "\033[41m\033[37m\033[1m";
+ normal_face = "\033[m";
+ if (isatty (1))
+ print_fail_on_stdout = FALSE;
+ }
+#endif
+
+ srcdir = getenv ("srcdir");
+ if (!srcdir)
+ srcdir = ".";
+
+ cairo_test_init (test->name);
+ printf ("%s\n", test->description);
+
+ if (expectation == CAIRO_TEST_FAILURE)
+ printf ("Expecting failure\n");
+
+ if ((tname = getenv ("CAIRO_TEST_TARGET")) != NULL && *tname) {
+
+ limited_targets = TRUE;
+
+ num_targets = 0;
+ targets_to_test = NULL;
+
+ while (*tname) {
+ int found = 0;
+ const char *end = strpbrk (tname, " \t\r\n;:,");
+ if (!end)
+ end = tname + strlen (tname);
+
+ for (i = 0; targets[i].name != NULL; i++) {
+ if (0 == strncmp (targets[i].name, tname, end - tname) &&
+ !isalnum (targets[i].name[end - tname])) {
+ /* realloc isn't exactly the best thing here, but meh. */
+ targets_to_test = realloc (targets_to_test, sizeof(cairo_test_target_t *) * (num_targets+1));
+ targets_to_test[num_targets++] = &targets[i];
+ found = 1;
+ }
+ }
+
+ if (!found) {
+ fprintf (stderr, "Cannot test target '%.*s'\n", (int)(end - tname), tname);
+ exit(-1);
+ }
+
+ if (*end)
+ end++;
+ tname = end;
+ }
+ } else {
+ num_targets = 0;
+ for (i = 0; targets[i].name != NULL; i++)
+ num_targets++;
+ targets_to_test = malloc (sizeof(cairo_test_target_t*) * num_targets);
+ for (i = 0; i < num_targets; i++) {
+ targets_to_test[i] = &targets[i];
+ }
+ }
+
+ /* The intended logic here is that we return overall SUCCESS
+ * iff. there is at least one tested backend and that all tested
+ * backends return SUCCESS, OR, there's no backend to test at all.
+ * In other words:
+ *
+ * if no backend to test
+ * -> SUCCESS
+ * else if any backend not SUCCESS
+ * -> FAILURE
+ * else if all backends UNTESTED
+ * -> FAILURE
+ * else (== some backend SUCCESS)
+ * -> SUCCESS
+ */
+ ret = CAIRO_TEST_UNTESTED;
+ for (i = 0; i < num_targets; i++) {
+ for (j = 0; j < NUM_DEVICE_OFFSETS; j++) {
+ cairo_test_target_t * volatile target = targets_to_test[i];
+ volatile int dev_offset = j * 25;
+
+ cairo_test_log ("Testing %s with %s target (dev offset %d)\n", test->name, target->name, dev_offset);
+ printf ("%s-%s-%s [%d]:\t", test->name, target->name,
+ _cairo_test_content_name (target->content),
+ dev_offset);
+
+#ifdef HAVE_SIGNAL_H
+ /* Set up a checkpoint to get back to in case of segfaults. */
+ old_segfault_handler = signal (SIGSEGV, segfault_handler);
+ if (0 == setjmp (jmpbuf))
+#endif
+ status = cairo_test_for_target (test, target, dev_offset);
+#ifdef HAVE_SIGNAL_H
+ else
+ status = CAIRO_TEST_CRASHED;
+ signal (SIGSEGV, old_segfault_handler);
+#endif
+
+ cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s OFFSET: %d RESULT: ",
+ test->name, target->name,
+ _cairo_test_content_name (target->content),
+ dev_offset);
+
+ switch (status) {
+ case CAIRO_TEST_SUCCESS:
+ printf ("PASS\n");
+ cairo_test_log ("PASS\n");
+ if (ret == CAIRO_TEST_UNTESTED)
+ ret = CAIRO_TEST_SUCCESS;
+ break;
+ case CAIRO_TEST_UNTESTED:
+ printf ("UNTESTED\n");
+ cairo_test_log ("UNTESTED\n");
+ break;
+ case CAIRO_TEST_CRASHED:
+ if (print_fail_on_stdout) {
+ printf ("!!!CRASHED!!!\n");
+ } else {
+ /* eat the test name */
+ printf ("\r");
+ fflush (stdout);
+ }
+ cairo_test_log ("CRASHED\n");
+ fprintf (stderr, "%s-%s-%s [%d]:\t%s!!!CRASHED!!!%s\n",
+ test->name, target->name,
+ _cairo_test_content_name (target->content), dev_offset,
+ fail_face, normal_face);
+ ret = CAIRO_TEST_FAILURE;
+ break;
+ default:
+ case CAIRO_TEST_FAILURE:
+ if (expectation == CAIRO_TEST_FAILURE) {
+ printf ("XFAIL\n");
+ cairo_test_log ("XFAIL\n");
+ } else {
+ if (print_fail_on_stdout) {
+ printf ("FAIL\n");
+ } else {
+ /* eat the test name */
+ printf ("\r");
+ fflush (stdout);
+ }
+ fprintf (stderr, "%s-%s-%s [%d]:\t%sFAIL%s\n",
+ test->name, target->name,
+ _cairo_test_content_name (target->content), dev_offset,
+ fail_face, normal_face);
+ cairo_test_log ("FAIL\n");
+ }
+ ret = status;
+ break;
+ }
+ }
+ }
+
+ if (ret != CAIRO_TEST_SUCCESS)
+ printf ("Check %s%s out for more information.\n", test->name, CAIRO_TEST_LOG_SUFFIX);
+
+ /* if no target was requested for test, succeed, otherwise if all
+ * were untested, fail. */
+ if (ret == CAIRO_TEST_UNTESTED)
+ ret = num_targets ? CAIRO_TEST_FAILURE : CAIRO_TEST_SUCCESS;
+
+ /* if targets are limited using CAIRO_TEST_TARGET, and expecting failure,
+ * make it fail, such that we can pass test suite by limiting backends
+ * to test without triggering XPASS failures. */
+ if (limited_targets && expectation == CAIRO_TEST_FAILURE && ret == CAIRO_TEST_SUCCESS) {
+ printf ("All tested backends passed, but tested targets are manually limited\n"
+ "and the test suite expects this test to fail for at least one target.\n"
+ "Intentionally failing the test, to not fail the suite.\n");
+ ret = CAIRO_TEST_FAILURE;
+ }
+
+ fclose (cairo_test_log_file);
+
+ free (targets_to_test);
+
+#if HAVE_FCFINI
+ FcFini ();
+#endif
+
+ return ret;
+}
+
+cairo_test_status_t
+cairo_test (cairo_test_t *test)
+{
+ cairo_test_status_t expectation = CAIRO_TEST_SUCCESS;
+ const char *xfails;
+
+ if ((xfails = getenv ("CAIRO_XFAIL_TESTS")) != NULL) {
+ while (*xfails) {
+ const char *end = strpbrk (xfails, " \t\r\n;:,");
+ if (!end)
+ end = xfails + strlen (xfails);
+
+ if (0 == strncmp (test->name, xfails, end - xfails) &&
+ '\0' == test->name[end - xfails]) {
+ expectation = CAIRO_TEST_FAILURE;
+ break;
+ }
+
+ if (*end)
+ end++;
+ xfails = end;
+ }
+ }
+
+ return cairo_test_expecting (test, expectation);
+}
+
+cairo_surface_t *
+cairo_test_create_surface_from_png (const char *filename)
+{
+ cairo_surface_t *image;
+ char *srcdir = getenv ("srcdir");
+
+ image = cairo_image_surface_create_from_png (filename);
+ if (cairo_surface_status(image)) {
+ /* expect not found when running with srcdir != builddir
+ * such as when 'make distcheck' is run
+ */
+ if (srcdir) {
+ char *srcdir_filename;
+ xasprintf (&srcdir_filename, "%s/%s", srcdir, filename);
+ image = cairo_image_surface_create_from_png (srcdir_filename);
+ free (srcdir_filename);
+ }
+ if (cairo_surface_status(image))
+ return NULL;
+ }
+
+ return image;
+}
+
+cairo_pattern_t *
+cairo_test_create_pattern_from_png (const char *filename)
+{
+ cairo_surface_t *image;
+ cairo_pattern_t *pattern;
+
+ image = cairo_test_create_surface_from_png (filename);
+
+ pattern = cairo_pattern_create_for_surface (image);
+
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+
+ cairo_surface_destroy (image);
+
+ return pattern;
+}
+
+static cairo_status_t
+_draw_check (cairo_surface_t *surface, int width, int height)
+{
+ cairo_t *cr;
+ cairo_status_t status;
+
+ cr = cairo_create (surface);
+ cairo_set_source_rgb (cr, 0.75, 0.75, 0.75); /* light gray */
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0.25, 0.25, 0.25); /* dark gray */
+ cairo_rectangle (cr, width / 2, 0, width / 2, height / 2);
+ cairo_rectangle (cr, 0, height / 2, width / 2, height / 2);
+ cairo_fill (cr);
+
+ status = cairo_status (cr);
+
+ cairo_destroy (cr);
+
+ return status;
+}
+
+cairo_status_t
+cairo_test_paint_checkered (cairo_t *cr)
+{
+ cairo_status_t status;
+ cairo_surface_t *check;
+
+ check = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 12, 12);
+ status = _draw_check (check, 12, 12);
+ if (status)
+ return status;
+
+ cairo_save (cr);
+ cairo_set_source_surface (cr, check, 0, 0);
+ cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ cairo_surface_destroy (check);
+
+ return CAIRO_STATUS_SUCCESS;
+}
diff --git a/test/cairo-test.h b/test/cairo-test.h
new file mode 100644
index 0000000..75eadb4
--- /dev/null
+++ b/test/cairo-test.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2004 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: Carl D. Worth <cworth at cworth.org>
+ */
+
+#ifndef _CAIRO_TEST_H_
+#define _CAIRO_TEST_H_
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <cairo.h>
+
+#define CAIRO_BOILERPLATE_LOG(...) cairo_test_log (__VA_ARGS__)
+#include "cairo-boilerplate.h"
+
+CAIRO_BEGIN_DECLS
+
+#if HAVE_STDINT_H
+# include <stdint.h>
+#elif HAVE_INTTYPES_H
+# include <inttypes.h>
+#elif HAVE_SYS_INT_TYPES_H
+# include <sys/int_types.h>
+#elif defined(_MSC_VER)
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+# ifndef HAVE_UINT64_T
+# define HAVE_UINT64_T 1
+# endif
+#else
+#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, \etc.)
+#endif
+
+typedef enum cairo_test_status {
+ CAIRO_TEST_SUCCESS = 0,
+ CAIRO_TEST_FAILURE,
+ CAIRO_TEST_UNTESTED,
+ CAIRO_TEST_CRASHED
+} cairo_test_status_t;
+
+typedef cairo_test_status_t (cairo_test_draw_function_t) (cairo_t *cr, int width, int height);
+
+typedef struct _cairo_test {
+ const char *name;
+ const char *description;
+ int width;
+ int height;
+ cairo_test_draw_function_t *draw;
+} cairo_test_t;
+
+/* The standard test interface which works by examining result image.
+ *
+ * cairo_test() accepts a test struct which will be called once for
+ * each testable backend. The following checks will be performed for
+ * each backend:
+ *
+ * 1) If draw() does not return CAIRO_TEST_SUCCESS then this backend
+ * fails.
+ *
+ * 2) Otherwise, if cairo_status(cr) indicates an error then this
+ * backend fails.
+ *
+ * 3) Otherwise, if the image size is 0, then this backend passes.
+ *
+ * 4) Otherwise, if every channel of every pixel exactly matches the
+ * reference image then this backend passes. If not, this backend
+ * fails.
+ *
+ * The overall test result is PASS if and only if there is at least
+ * one backend that is tested and if all tested backend pass according
+ * to the four criteria above.
+ */
+cairo_test_status_t
+cairo_test (cairo_test_t *test);
+
+/* cairo_test_init() and cairo_test_log() exist to help in writing
+ * tests for which cairo_test() is not appropriate for one reason or
+ * another. For example, some tests might not be doing any drawing at
+ * all, or may need to create their own cairo_t rather than be handed
+ * one by cairo_test.
+ */
+
+/* Initialize test-specific resources, (log files, etc.) */
+void
+cairo_test_init (const char *test_name);
+
+/* Print a message to the log file, ala printf. */
+void
+cairo_test_log (const char *fmt, ...) CAIRO_PRINTF_FORMAT(1, 2);
+
+/* Helper functions that take care of finding source images even when
+ * building in a non-srcdir manner, (ie. the tests will be run in a
+ * directory that is different from the one where the source image
+ * exists). */
+cairo_surface_t *
+cairo_test_create_surface_from_png (const char *filename);
+
+cairo_pattern_t *
+cairo_test_create_pattern_from_png (const char *filename);
+
+cairo_status_t
+cairo_test_paint_checkered (cairo_t *cr);
+
+CAIRO_END_DECLS
+
+#endif
diff-tree 95475218858792ccb20ac6ad28db22e233c783d7 (from 37ce7058906a9a8c7e80bf4ed59c17ec912087cf)
Author: Carl Worth <cworth at cworth.org>
Date: Wed Aug 30 23:41:48 2006 -0700
boilerplate: Remove custom read/write-png code in favor of using cairo surfaces
Also combine image_diff and image_diff_flattened into a single function
diff --git a/boilerplate/Makefile.am b/boilerplate/Makefile.am
index b8ac3d3..2cc48ce 100644
--- a/boilerplate/Makefile.am
+++ b/boilerplate/Makefile.am
@@ -7,10 +7,6 @@ buffer-diff.c \
buffer-diff.h \
cairo-test.c \
cairo-test.h \
-read-png.c \
-read-png.h \
-write-png.c \
-write-png.h \
xmalloc.c \
xmalloc.h
diff --git a/boilerplate/buffer-diff.c b/boilerplate/buffer-diff.c
index ade0cc8..b59b5e8 100644
--- a/boilerplate/buffer-diff.c
+++ b/boilerplate/buffer-diff.c
@@ -39,8 +39,6 @@
#include "cairo-test.h"
#include "buffer-diff.h"
-#include "read-png.h"
-#include "write-png.h"
#include "xmalloc.h"
static void
@@ -143,71 +141,128 @@ buffer_diff_noalpha (unsigned char *buf_
width, height, stride_a, stride_b, stride_diff, 0x00ffffff);
}
+static cairo_status_t
+stdio_write_func (void *closure, const unsigned char *data, unsigned int length)
+{
+ FILE *file = closure;
+
+ if (fwrite (data, 1, length, file) != length)
+ return CAIRO_STATUS_WRITE_ERROR;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/* Flatten an ARGB surface by blending it over white. The resulting
+ * surface, (still in ARGB32 format, but with only alpha==1.0
+ * everywhere) is returned in the same surface pointer.
+ *
+ * The original surface will be destroyed.
+ *
+ * The (x,y) value specify an origin of interest for the original
+ * image. The flattened image will be generated only from the box
+ * extending from (x,y) to (width,height).
+ */
+static void
+flatten_surface (cairo_surface_t **surface, int x, int y)
+{
+ cairo_surface_t *flat;
+ cairo_t *cr;
+
+ flat = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ cairo_image_surface_get_width (*surface) - x,
+ cairo_image_surface_get_height (*surface) - y);
+ cairo_surface_set_device_offset (flat, -x, -y);
+
+ cr = cairo_create (flat);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_surface (cr, *surface, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_destroy (*surface);
+ *surface = flat;
+}
+
/* Image comparison code courtesy of Richard Worth <richard at theworths.org>
* Returns number of pixels changed, (or -1 on error).
* Also saves a "diff" image intended to visually show where the
* images differ.
*/
-int
-image_diff (const char *filename_a,
- const char *filename_b,
- const char *filename_diff,
- int ax,
- int ay,
- int bx,
- int by)
+static int
+image_diff_core (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by,
+ cairo_bool_t flatten)
{
int pixels_changed;
unsigned int width_a, height_a, stride_a;
unsigned int width_b, height_b, stride_b;
- unsigned int stride_diff;
- unsigned char *buf_a, *buf_b, *buf_diff;
- read_png_status_t status;
+ cairo_surface_t *surface_a, *surface_b, *surface_diff;
- status = read_png_argb32 (filename_a, &buf_a, &width_a, &height_a, &stride_a);
- if (status)
+ surface_a = cairo_image_surface_create_from_png (filename_a);
+ if (cairo_surface_status (surface_a))
return -1;
- status = read_png_argb32 (filename_b, &buf_b, &width_b, &height_b, &stride_b);
- if (status) {
- free (buf_a);
+ surface_b = cairo_image_surface_create_from_png (filename_b);
+ if (cairo_surface_status (surface_b)) {
+ cairo_surface_destroy (surface_a);
return -1;
}
- width_a -= ax;
- height_a -= ay;
- width_b -= bx;
- height_b -= by;
+ width_a = cairo_image_surface_get_width (surface_a) - ax;
+ height_a = cairo_image_surface_get_height (surface_a) - ay;
+ width_b = cairo_image_surface_get_width (surface_b) - bx;
+ height_b = cairo_image_surface_get_height (surface_b) - by;
if (width_a != width_b ||
height_a != height_b)
{
- cairo_test_log ("Error: Image size mismatch: (%dx%d@%d) vs. (%dx%d@%d)\n"
+ cairo_test_log ("Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n"
" for %s vs. %s\n",
- width_a, height_a, stride_a,
- width_b, height_b, stride_b,
+ width_a, height_a,
+ width_b, height_b,
filename_a, filename_b);
- free (buf_a);
- free (buf_b);
+ cairo_surface_destroy (surface_a);
+ cairo_surface_destroy (surface_b);
return -1;
}
- stride_diff = 4 * width_a;
- buf_diff = xcalloc (stride_diff * height_a, 1);
+ if (flatten) {
+ flatten_surface (&surface_a, ax, ay);
+ flatten_surface (&surface_b, bx, by);
+ ax = ay = bx = by = 0;
+ }
+
+ surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width_a, height_a);
- pixels_changed = buffer_diff (buf_a + (ay * stride_a) + ax * 4,
- buf_b + (by * stride_b) + by * 4,
- buf_diff,
+ stride_a = cairo_image_surface_get_stride (surface_a);
+ stride_b = cairo_image_surface_get_stride (surface_b);
+
+ pixels_changed = buffer_diff (cairo_image_surface_get_data (surface_a)
+ + (ay * stride_a) + ax * 4,
+ cairo_image_surface_get_data (surface_b)
+ + (by * stride_b) + by * 4,
+ cairo_image_surface_get_data (surface_diff),
width_a, height_a,
- stride_a, stride_b, stride_diff);
+ stride_a, stride_b,
+ cairo_image_surface_get_stride (surface_diff));
if (pixels_changed) {
FILE *png_file;
+
if (filename_diff)
png_file = fopen (filename_diff, "wb");
else
png_file = stdout;
- write_png_argb32 (buf_diff, png_file, width_a, height_a, stride_diff);
+
+ cairo_surface_write_to_png_stream (surface_diff, stdio_write_func, png_file);
+
if (png_file != stdout)
fclose (png_file);
} else {
@@ -215,25 +270,27 @@ image_diff (const char *filename_a,
xunlink (filename_diff);
}
- free (buf_a);
- free (buf_b);
- free (buf_diff);
+ cairo_surface_destroy (surface_a);
+ cairo_surface_destroy (surface_b);
+ cairo_surface_destroy (surface_diff);
return pixels_changed;
}
-/* Like image_diff, but first "flatten" the contents of filename_b by
- * blending over white.
- *
- * Yes, this is an ugly copy-and-paste of another function. I'm doing
- * this for two reasons:
- *
- * 1) I want to rewrite all of the image_diff interfaces anyway
- * (should use cairo_image_surface_create_from_png, should save
- * loaded buffers for re-use).
- *
- * 2) There is a second reason no more.
- */
+int
+image_diff (const char *filename_a,
+ const char *filename_b,
+ const char *filename_diff,
+ int ax,
+ int ay,
+ int bx,
+ int by)
+{
+ return image_diff_core (filename_a, filename_b, filename_diff,
+ ax, ay, bx, by,
+ FALSE);
+}
+
int
image_diff_flattened (const char *filename_a,
const char *filename_b,
@@ -243,106 +300,7 @@ image_diff_flattened (const char *filena
int bx,
int by)
{
- int pixels_changed;
- unsigned int width_a, height_a, stride_a;
- unsigned int width_b, height_b, stride_b;
- unsigned char *buf_a, *buf_b, *buf_diff;
- unsigned char *a_flat, *b_flat;
- cairo_surface_t *buf_a_surface, *a_flat_surface;
- cairo_surface_t *buf_b_surface, *b_flat_surface;
- cairo_t *cr;
- read_png_status_t status;
-
- status = read_png_argb32 (filename_a, &buf_a, &width_a, &height_a, &stride_a);
- if (status)
- return -1;
-
- status = read_png_argb32 (filename_b, &buf_b, &width_b, &height_b, &stride_b);
- if (status) {
- free (buf_a);
- return -1;
- }
-
- width_a -= ax;
- height_a -= ay;
- width_b -= bx;
- height_b -= by;
-
- if (width_a != width_b ||
- height_a != height_b)
- {
- cairo_test_log ("Error: Image size mismatch: (%dx%d@%d) vs. (%dx%d@%d)\n"
- " for %s vs. %s\n",
- width_a, height_a, stride_a,
- width_b, height_b, stride_b,
- filename_a, filename_b);
- free (buf_a);
- free (buf_b);
- return -1;
- }
-
- buf_a_surface = cairo_image_surface_create_for_data (buf_a,
- CAIRO_FORMAT_ARGB32,
- width_a + ax, height_a + ay,
- stride_a);
- buf_b_surface = cairo_image_surface_create_for_data (buf_b,
- CAIRO_FORMAT_ARGB32,
- width_b + bx, height_b + by,
- stride_b);
-
- buf_diff = xcalloc (stride_a * height_a, 1);
-
- a_flat = xcalloc (stride_a * height_a, 1);
- b_flat = xcalloc (stride_b * height_b, 1);
-
- a_flat_surface = cairo_image_surface_create_for_data (a_flat,
- CAIRO_FORMAT_ARGB32,
- width_a, height_a,
- stride_a);
- cairo_surface_set_device_offset (a_flat_surface, -ax, -ay);
- b_flat_surface = cairo_image_surface_create_for_data (b_flat,
- CAIRO_FORMAT_ARGB32,
- width_b, height_b,
- stride_b);
- cairo_surface_set_device_offset (b_flat_surface, -bx, -by);
-
- cr = cairo_create (a_flat_surface);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_set_source_surface (cr, buf_a_surface, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
- cairo_surface_destroy (a_flat_surface);
- cairo_surface_destroy (buf_a_surface);
-
- cr = cairo_create (b_flat_surface);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_set_source_surface (cr, buf_b_surface, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
- cairo_surface_destroy (b_flat_surface);
- cairo_surface_destroy (buf_b_surface);
-
- pixels_changed = buffer_diff (a_flat,
- b_flat,
- buf_diff,
- width_a, height_a,
- stride_a, stride_b, stride_a);
-
- if (pixels_changed) {
- FILE *png_file = fopen (filename_diff, "wb");
- write_png_argb32 (buf_diff, png_file, width_a, height_a, stride_a);
- fclose (png_file);
- } else {
- xunlink (filename_diff);
- }
-
- free (buf_a);
- free (buf_b);
- free (a_flat);
- free (b_flat);
- free (buf_diff);
-
- return pixels_changed;
+ return image_diff_core (filename_a, filename_b, filename_diff,
+ ax, ay, bx, by,
+ TRUE);
}
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 60b4f5c..eb4ab05 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2004 Red Hat, Inc.
+ * Copyright © 2004,2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
diff --git a/boilerplate/cairo-boilerplate.h b/boilerplate/cairo-boilerplate.h
index 183f6a2..f91ebff 100644
--- a/boilerplate/cairo-boilerplate.h
+++ b/boilerplate/cairo-boilerplate.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2004-2006 Red Hat, Inc.
+ * Copyright © 2004,2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
@@ -41,6 +41,14 @@
const char *
_cairo_test_content_name (cairo_content_t content);
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
typedef cairo_surface_t *
(*cairo_test_create_target_surface_t) (const char *name,
cairo_content_t content,
diff --git a/boilerplate/cairo-test.c b/boilerplate/cairo-test.c
index 0243edf..0d915a5 100644
--- a/boilerplate/cairo-test.c
+++ b/boilerplate/cairo-test.c
@@ -48,8 +48,6 @@
#include "cairo-test.h"
#include "buffer-diff.h"
-#include "read-png.h"
-#include "write-png.h"
#include "xmalloc.h"
/* This is copied from cairoint.h. That makes it painful to keep in
diff --git a/boilerplate/read-png.c b/boilerplate/read-png.c
deleted file mode 100644
index bb02e50..0000000
--- a/boilerplate/read-png.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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
- * 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 the
- * University of Southern California not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission. The University of Southern
- * California makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
- * SOUTHERN CALIFORNIA 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: Carl D. Worth <cworth at isi.edu>
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if HAVE_STDINT_H
-# include <stdint.h>
-#elif HAVE_INTTYPES_H
-# include <inttypes.h>
-#elif HAVE_SYS_INT_TYPES_H
-# include <sys/int_types.h>
-#elif defined(_MSC_VER)
- typedef __int8 int8_t;
- typedef unsigned __int8 uint8_t;
- typedef __int16 int16_t;
- typedef unsigned __int16 uint16_t;
- typedef __int32 int32_t;
- typedef unsigned __int32 uint32_t;
- typedef __int64 int64_t;
- typedef unsigned __int64 uint64_t;
-# ifndef HAVE_UINT64_T
-# define HAVE_UINT64_T 1
-# endif
-#else
-#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <png.h>
-
-#include "cairo-test.h"
-#include "read-png.h"
-#include "xmalloc.h"
-
-static void
-premultiply_data (png_structp png,
- png_row_infop row_info,
- png_bytep data)
-{
- size_t i;
-
- for (i = 0; i < row_info->rowbytes; i += 4) {
- uint8_t *base = &data[i];
- uint8_t blue = base[0];
- uint8_t green = base[1];
- uint8_t red = base[2];
- uint8_t alpha = base[3];
- uint32_t p;
-
- 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 (uint32_t));
- }
-}
-
-read_png_status_t
-read_png_argb32 (const char *filename,
- unsigned char **data,
- unsigned int *width,
- unsigned int *height,
- unsigned int *stride)
-{
- size_t i;
- FILE *file;
-#define PNG_SIG_SIZE 8
- unsigned char png_sig[PNG_SIG_SIZE];
- int sig_bytes;
- png_struct *png;
- png_info *info;
- png_uint_32 png_width, png_height;
- int depth, color_type, interlace;
- unsigned int pixel_size;
- png_byte **row_pointers;
-
- file = fopen (filename, "rb");
- if (file == NULL) {
- cairo_test_log ("Error: File not found: %s\n", filename);
- return READ_PNG_FILE_NOT_FOUND;
- }
-
- sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file);
- if (png_check_sig (png_sig, sig_bytes) == 0) {
- fclose (file);
- cairo_test_log ("Error: File is not a PNG image: %s\n", filename);
- return READ_PNG_FILE_NOT_PNG;
- }
-
- /* XXX: Perhaps we'll want some other error handlers? */
- png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
- NULL,
- NULL,
- NULL);
- if (png == NULL) {
- fclose (file);
- cairo_test_log ("Error: Out of memory while reading %s\n", filename);
- return READ_PNG_NO_MEMORY;
- }
-
- info = png_create_info_struct (png);
- if (info == NULL) {
- fclose (file);
- png_destroy_read_struct (&png, NULL, NULL);
- cairo_test_log ("Error: Out of memory while reading %s\n", filename);
- return READ_PNG_NO_MEMORY;
- }
-
- png_init_io (png, file);
- png_set_sig_bytes (png, sig_bytes);
-
- png_read_info (png, info);
-
- png_get_IHDR (png, info,
- &png_width, &png_height, &depth,
- &color_type, &interlace, NULL, NULL);
- *width = png_width;
- *height = png_height;
- *stride = 4 * png_width;
-
- /* convert palette/gray image to rgb */
- if (color_type == PNG_COLOR_TYPE_PALETTE)
- png_set_palette_to_rgb (png);
-
- /* expand gray bit depth if needed */
- if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
- png_set_gray_1_2_4_to_8 (png);
- /* transform transparency to alpha */
- if (png_get_valid(png, info, PNG_INFO_tRNS))
- png_set_tRNS_to_alpha (png);
-
- if (depth == 16)
- png_set_strip_16 (png);
-
- if (depth < 8)
- png_set_packing (png);
-
- /* convert grayscale to RGB */
- if (color_type == PNG_COLOR_TYPE_GRAY
- || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- png_set_gray_to_rgb (png);
-
- if (interlace != PNG_INTERLACE_NONE)
- png_set_interlace_handling (png);
-
- png_set_bgr (png);
- png_set_filler (png, 0xff, PNG_FILLER_AFTER);
-
- png_set_read_user_transform_fn (png, premultiply_data);
-
- png_read_update_info (png, info);
-
- pixel_size = 4;
- *data = xmalloc (png_width * png_height * pixel_size);
-
- row_pointers = malloc (png_height * sizeof(char *));
- for (i=0; i < png_height; i++)
- row_pointers[i] = (png_byte *) (*data + i * png_width * pixel_size);
-
- png_read_image (png, row_pointers);
- png_read_end (png, info);
-
- free (row_pointers);
- fclose (file);
-
- png_destroy_read_struct (&png, &info, NULL);
-
- return READ_PNG_SUCCESS;
-}
diff --git a/boilerplate/read-png.h b/boilerplate/read-png.h
deleted file mode 100644
index 9c9ba43..0000000
--- a/boilerplate/read-png.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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
- * 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 the
- * University of Southern California not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission. The University of Southern
- * California makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
- * SOUTHERN CALIFORNIA 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: Carl D. Worth <cworth at isi.edu>
- */
-
-#ifndef READ_PNG_H
-#define READ_PNG_H
-
-typedef enum {
- READ_PNG_SUCCESS = 0,
- READ_PNG_FILE_NOT_FOUND,
- READ_PNG_FILE_NOT_PNG,
- READ_PNG_NO_MEMORY
-} read_png_status_t;
-
-read_png_status_t
-read_png_argb32 (const char *filename,
- unsigned char **data,
- unsigned int *width,
- unsigned int *height,
- unsigned int *stride);
-
-#endif
diff --git a/boilerplate/write-png.c b/boilerplate/write-png.c
deleted file mode 100644
index c906df5..0000000
--- a/boilerplate/write-png.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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
- * 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 the
- * University of Southern California not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission. The University of Southern
- * California makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
- * SOUTHERN CALIFORNIA 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: Carl D. Worth <cworth at cworth.org>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <png.h>
-
-#include "write-png.h"
-
-static void
-unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
-{
- size_t i;
-
- for (i = 0; i < row_info->rowbytes; i += 4) {
- unsigned char *b = &data[i];
- unsigned int pixel;
- unsigned char alpha;
-
- memcpy (&pixel, b, sizeof (unsigned int));
- alpha = (pixel & 0xff000000) >> 24;
- if (alpha == 0) {
- b[0] = b[1] = b[2] = b[3] = 0;
- } else {
- 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 (unsigned char *buffer, FILE *file,
- int width, int height, int stride)
-{
- int i;
- png_struct *png;
- png_info *info;
- png_byte **rows;
- png_color_16 white;
-
- rows = malloc (height * sizeof(png_byte*));
-
- for (i = 0; i < height; i++) {
- rows[i] = buffer + i * stride;
- }
-
- png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- info = png_create_info_struct (png);
-
- png_init_io (png, file);
- png_set_IHDR (png, info,
- width, height, 8,
- PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
-
- white.red = 0xff;
- white.blue = 0xff;
- white.green = 0xff;
- png_set_bKGD (png, info, &white);
-
- png_set_write_user_transform_fn (png, unpremultiply_data);
- png_set_bgr (png);
-
- png_write_info (png, info);
- png_write_image (png, rows);
- png_write_end (png, info);
-
- png_destroy_write_struct (&png, &info);
-
- free (rows);
-}
diff --git a/boilerplate/write-png.h b/boilerplate/write-png.h
deleted file mode 100644
index 8074666..0000000
--- a/boilerplate/write-png.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
- * 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 the
- * University of Southern California not be used in advertising or
- * publicity pertaining to distribution of the software without
- * specific, written prior permission. The University of Southern
- * California makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
- * SOUTHERN CALIFORNIA 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: Carl D. Worth <cworth at isi.edu>
- */
-
-#ifndef WRITE_PNG_H
-#define WRITE_PNG_H
-
-void
-write_png_argb32 (unsigned char *buffer, FILE * file,
- int width, int height, int stride);
-
-#endif
diff --git a/test/imagediff.c b/test/imagediff.c
index d030e76..9030877 100644
--- a/test/imagediff.c
+++ b/test/imagediff.c
@@ -27,8 +27,6 @@
#include <stdlib.h>
#include "buffer-diff.h"
-#include "read-png.h"
-#include "write-png.h"
#include "xmalloc.h"
int
diff-tree 37ce7058906a9a8c7e80bf4ed59c17ec912087cf (from a0ca4369ff71ca76e593ea8db3e728218814814d)
Author: Carl Worth <cworth at cworth.org>
Date: Wed Aug 30 22:56:36 2006 -0700
Separate the sharable stuff out of cairo-test.c into cairo-boilerplate.c
diff --git a/boilerplate/Makefile.am b/boilerplate/Makefile.am
index 7fa27d9..b8ac3d3 100644
--- a/boilerplate/Makefile.am
+++ b/boilerplate/Makefile.am
@@ -1,6 +1,8 @@
noinst_LTLIBRARIES = libcairotest.la
libcairotest_la_SOURCES =\
+cairo-boilerplate.c \
+cairo-bolierplate.h \
buffer-diff.c \
buffer-diff.h \
cairo-test.c \
@@ -30,6 +32,5 @@ INCLUDES = \
-D_GNU_SOURCE \
-I$(srcdir) \
-I$(top_srcdir)/pixman/src \
- -I$(top_builddir)/src \
-I$(top_srcdir)/src \
$(CAIRO_CFLAGS)
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
new file mode 100644
index 0000000..60b4f5c
--- /dev/null
+++ b/boilerplate/cairo-boilerplate.c
@@ -0,0 +1,1511 @@
+/*
+ * Copyright © 2004 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: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-boilerplate.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <setjmp.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#if HAVE_FCFINI
+#include <fontconfig/fontconfig.h>
+#endif
+
+static const char *vector_ignored_tests[] = {
+ /* We can't match the results of tests that depend on
+ * CAIRO_ANTIALIAS_NONE/SUBPIXEL for vector backends
+ * (nor do we care). */
+ "ft-text-antialias-none",
+ "rectangle-rounding-error",
+ "text-antialias-gray",
+ "text-antialias-none",
+ "text-antialias-subpixel",
+ "unantialiased-shapes",
+ NULL
+};
+
+const char *
+_cairo_test_content_name (cairo_content_t content)
+{
+ /* For the purpose of the content name, we don't distinguish the
+ * flattened content value.
+ */
+ if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
+ content = CAIRO_CONTENT_COLOR_ALPHA;
+
+ switch (content) {
+ case CAIRO_CONTENT_COLOR:
+ return "rgb24";
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ return "argb32";
+ case CAIRO_CONTENT_ALPHA:
+ default:
+ assert (0); /* not reached */
+ return "---";
+ }
+}
+
+static cairo_surface_t *
+create_image_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ cairo_format_t format;
+ *closure = NULL;
+
+ if (content == CAIRO_CONTENT_COLOR_ALPHA) {
+ format = CAIRO_FORMAT_ARGB32;
+ } else if (content == CAIRO_CONTENT_COLOR) {
+ format = CAIRO_FORMAT_RGB24;
+ } else {
+ assert (0); /* not reached */
+ return NULL;
+ }
+
+ return cairo_image_surface_create (format, width, height);
+}
+
+#ifdef CAIRO_HAS_TEST_SURFACES
+
+#include "test-fallback-surface.h"
+#include "test-meta-surface.h"
+#include "test-paginated-surface.h"
+
+static cairo_surface_t *
+create_test_fallback_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ *closure = NULL;
+ return _test_fallback_surface_create (content, width, height);
+}
+
+static cairo_surface_t *
+create_test_meta_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ *closure = NULL;
+ return _test_meta_surface_create (content, width, height);
+}
+
+static const cairo_user_data_key_t test_paginated_closure_key;
+
+typedef struct {
+ unsigned char *data;
+ cairo_content_t content;
+ int width;
+ int height;
+ int stride;
+} test_paginated_closure_t;
+
+static cairo_surface_t *
+create_test_paginated_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ test_paginated_closure_t *tpc;
+ cairo_surface_t *surface;
+
+ *closure = tpc = xmalloc (sizeof (test_paginated_closure_t));
+
+ tpc->content = content;
+ tpc->width = width;
+ tpc->height = height;
+ tpc->stride = width * 4;
+
+ tpc->data = xcalloc (tpc->stride * height, 1);
+
+ surface = _test_paginated_surface_create_for_data (tpc->data,
+ tpc->content,
+ tpc->width,
+ tpc->height,
+ tpc->stride);
+
+ cairo_surface_set_user_data (surface, &test_paginated_closure_key,
+ tpc, NULL);
+
+ return surface;
+}
+
+/* The only reason we go through all these machinations to write a PNG
+ * image is to _really ensure_ that the data actually landed in our
+ * buffer through the paginated surface to the test_paginated_surface.
+ *
+ * If we didn't implement this function then the default
+ * cairo_surface_write_to_png would result in the paginated_surface's
+ * acquire_source_image function replaying the meta-surface to an
+ * intermediate image surface. And in that case the
+ * test_paginated_surface would not be involved and wouldn't be
+ * tested.
+ */
+static cairo_status_t
+test_paginated_write_to_png (cairo_surface_t *surface,
+ const char *filename)
+{
+ cairo_surface_t *image;
+ cairo_format_t format;
+ test_paginated_closure_t *tpc;
+
+ tpc = cairo_surface_get_user_data (surface, &test_paginated_closure_key);
+
+ switch (tpc->content) {
+ case CAIRO_CONTENT_COLOR:
+ format = CAIRO_FORMAT_RGB24;
+ break;
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ format = CAIRO_FORMAT_ARGB32;
+ break;
+ case CAIRO_CONTENT_ALPHA:
+ default:
+ assert (0); /* not reached */
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ image = cairo_image_surface_create_for_data (tpc->data,
+ format,
+ tpc->width,
+ tpc->height,
+ tpc->stride);
+
+ cairo_surface_write_to_png (image, filename);
+
+ cairo_surface_destroy (image);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+cleanup_test_paginated (void *closure)
+{
+ test_paginated_closure_t *tpc = closure;
+
+ free (tpc->data);
+ free (tpc);
+}
+
+#endif
+
+#ifdef CAIRO_HAS_GLITZ_SURFACE
+#include <glitz.h>
+#include <cairo-glitz.h>
+
+static const cairo_user_data_key_t glitz_closure_key;
+
+typedef struct _glitz_target_closure_base {
+ int width;
+ int height;
+ cairo_content_t content;
+} glitz_target_closure_base_t;
+
+#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
+#include <glitz-glx.h>
+
+typedef struct _glitz_glx_target_closure {
+ glitz_target_closure_base_t base;
+ Display *dpy;
+ int scr;
+ Window win;
+} glitz_glx_target_closure_t;
+
+static glitz_surface_t *
+create_glitz_glx_surface (glitz_format_name_t formatname,
+ int width,
+ int height,
+ glitz_glx_target_closure_t *closure)
+{
+ Display * dpy = closure->dpy;
+ int scr = closure->scr;
+ glitz_drawable_format_t templ;
+ glitz_drawable_format_t * dformat = NULL;
+ unsigned long mask;
+ glitz_drawable_t * drawable = NULL;
+ glitz_format_t * format;
+ glitz_surface_t * sr;
+
+ XSizeHints xsh;
+ XSetWindowAttributes xswa;
+ XVisualInfo * vinfo;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.color.red_size = 8;
+ templ.color.green_size = 8;
+ templ.color.blue_size = 8;
+ templ.color.alpha_size = 8;
+ templ.color.fourcc = GLITZ_FOURCC_RGB;
+ templ.samples = 1;
+
+ glitz_glx_init (NULL);
+
+ mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK |
+ GLITZ_FORMAT_RED_SIZE_MASK | GLITZ_FORMAT_GREEN_SIZE_MASK |
+ GLITZ_FORMAT_BLUE_SIZE_MASK;
+ if (formatname == GLITZ_STANDARD_ARGB32)
+ mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
+
+ /* Try for a pbuffer first */
+ if (!getenv("CAIRO_TEST_FORCE_GLITZ_WINDOW"))
+ dformat = glitz_glx_find_pbuffer_format (dpy, scr, mask, &templ, 0);
+
+ if (dformat) {
+ closure->win = None;
+
+ drawable = glitz_glx_create_pbuffer_drawable (dpy, scr, dformat,
+ width, height);
+ if (!drawable)
+ goto FAIL;
+ } else {
+ /* No pbuffer, try window */
+ dformat = glitz_glx_find_window_format (dpy, scr, mask, &templ, 0);
+
+ if (!dformat)
+ goto FAIL;
+
+ vinfo = glitz_glx_get_visual_info_from_format(dpy,
+ DefaultScreen(dpy),
+ dformat);
+
+ if (!vinfo)
+ goto FAIL;
+
+ xsh.flags = PSize;
+ xsh.x = 0;
+ xsh.y = 0;
+ xsh.width = width;
+ xsh.height = height;
+
+ xswa.colormap = XCreateColormap (dpy, RootWindow(dpy, scr),
+ vinfo->visual, AllocNone);
+ closure->win = XCreateWindow (dpy, RootWindow(dpy, scr),
+ xsh.x, xsh.y, xsh.width, xsh.height,
+ 0, vinfo->depth, CopyFromParent,
+ vinfo->visual, CWColormap, &xswa);
+ XFree (vinfo);
+
+ drawable =
+ glitz_glx_create_drawable_for_window (dpy, scr,
+ dformat, closure->win,
+ width, height);
+
+ if (!drawable)
+ goto DESTROY_WINDOW;
+ }
+
+ format = glitz_find_standard_format (drawable, formatname);
+ if (!format)
+ goto DESTROY_DRAWABLE;
+
+ sr = glitz_surface_create (drawable, format, width, height, 0, NULL);
+ if (!sr)
+ goto DESTROY_DRAWABLE;
+
+ if (closure->win == None || dformat->doublebuffer) {
+ glitz_surface_attach (sr, drawable, GLITZ_DRAWABLE_BUFFER_BACK_COLOR);
+ } else {
+ XMapWindow (closure->dpy, closure->win);
+ glitz_surface_attach (sr, drawable, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
+ }
+
+ glitz_drawable_destroy (drawable);
+
+ return sr;
+ DESTROY_DRAWABLE:
+ glitz_drawable_destroy (drawable);
+ DESTROY_WINDOW:
+ if (closure->win)
+ XDestroyWindow (dpy, closure->win);
+ FAIL:
+ return NULL;
+}
+
+static cairo_surface_t *
+create_cairo_glitz_glx_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ int width = width;
+ int height = height;
+ glitz_glx_target_closure_t *gxtc;
+ glitz_surface_t * glitz_surface;
+ cairo_surface_t * surface;
+
+ *closure = gxtc = xmalloc (sizeof (glitz_glx_target_closure_t));
+
+ if (width == 0)
+ width = 1;
+ if (height == 0)
+ height = 1;
+
+ gxtc->dpy = XOpenDisplay (getenv("CAIRO_TEST_GLITZ_DISPLAY"));
+ if (!gxtc->dpy) {
+ CAIRO_BOILERPLATE_LOG ("Failed to open display: %s\n", XDisplayName(0));
+ goto FAIL;
+ }
+
+ XSynchronize (gxtc->dpy, 1);
+
+ gxtc->scr = DefaultScreen(gxtc->dpy);
+
+ switch (content) {
+ case CAIRO_CONTENT_COLOR:
+ glitz_surface = create_glitz_glx_surface (GLITZ_STANDARD_RGB24, width, height, gxtc);
+ break;
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ glitz_surface = create_glitz_glx_surface (GLITZ_STANDARD_ARGB32, width, height, gxtc);
+ break;
+ default:
+ CAIRO_BOILERPLATE_LOG ("Invalid content for glitz-glx test: %d\n", content);
+ goto FAIL_CLOSE_DISPLAY;
+ }
+ if (!glitz_surface) {
+ CAIRO_BOILERPLATE_LOG ("Failed to create glitz-glx surface\n");
+ goto FAIL_CLOSE_DISPLAY;
+ }
+
+ surface = cairo_glitz_surface_create (glitz_surface);
+
+ gxtc->base.width = width;
+ gxtc->base.height = height;
+ gxtc->base.content = content;
+ cairo_surface_set_user_data (surface, &glitz_closure_key,
+ gxtc, NULL);
+
+ return surface;
+
+ FAIL_CLOSE_DISPLAY:
+ XCloseDisplay (gxtc->dpy);
+ FAIL:
+ return NULL;
+}
+
+static void
+cleanup_cairo_glitz_glx (void *closure)
+{
+ glitz_glx_target_closure_t *gxtc = closure;
+
+ glitz_glx_fini ();
+
+ if (gxtc->win)
+ XDestroyWindow (gxtc->dpy, gxtc->win);
+
+ XCloseDisplay (gxtc->dpy);
+
+ free (gxtc);
+}
+
+#endif /* CAIRO_CAN_TEST_GLITZ_GLX_SURFACE */
+
+#if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
+#include <glitz-agl.h>
+
+typedef struct _glitz_agl_target_closure {
+ glitz_target_closure_base_t base;
+} glitz_agl_target_closure_t;
+
+static glitz_surface_t *
+create_glitz_agl_surface (glitz_format_name_t formatname,
+ int width, int height,
+ glitz_agl_target_closure_t *closure)
+{
+ glitz_drawable_format_t *dformat;
+ glitz_drawable_format_t templ;
+ glitz_drawable_t *gdraw;
+ glitz_format_t *format;
+ glitz_surface_t *sr = NULL;
+ unsigned long mask;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.color.red_size = 8;
+ templ.color.green_size = 8;
+ templ.color.blue_size = 8;
+ templ.color.alpha_size = 8;
+ templ.color.fourcc = GLITZ_FOURCC_RGB;
+ templ.samples = 1;
+
+ mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK |
+ GLITZ_FORMAT_RED_SIZE_MASK | GLITZ_FORMAT_GREEN_SIZE_MASK |
+ GLITZ_FORMAT_BLUE_SIZE_MASK;
+ if (formatname == GLITZ_STANDARD_ARGB32)
+ mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
+
+ dformat = glitz_agl_find_pbuffer_format (mask, &templ, 0);
+ if (!dformat) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to find pbuffer format for template.");
+ goto FAIL;
+ }
+
+ gdraw = glitz_agl_create_pbuffer_drawable (dformat, width, height);
+ if (!gdraw) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to create pbuffer drawable.");
+ goto FAIL;
+ }
+
+ format = glitz_find_standard_format (gdraw, formatname);
+ if (!format) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to find standard format for drawable.");
+ goto DESTROY_DRAWABLE;
+ }
+
+ sr = glitz_surface_create (gdraw, format, width, height, 0, NULL);
+ if (!sr) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to create a surface.");
+ goto DESTROY_DRAWABLE;
+ }
+
+ glitz_surface_attach (sr, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
+
+ DESTROY_DRAWABLE:
+ glitz_drawable_destroy (gdraw);
+
+ FAIL:
+ return sr; /* will be NULL unless we create it and attach */
+}
+
+static cairo_surface_t *
+create_cairo_glitz_agl_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ glitz_surface_t *glitz_surface;
+ cairo_surface_t *surface;
+ glitz_agl_target_closure_t *aglc;
+
+ glitz_agl_init ();
+
+ *closure = aglc = xmalloc (sizeof (glitz_agl_target_closure_t));
+
+ switch (content) {
+ case CAIRO_CONTENT_COLOR:
+ glitz_surface = create_glitz_agl_surface (GLITZ_STANDARD_RGB24, width, height, NULL);
+ break;
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ glitz_surface = create_glitz_agl_surface (GLITZ_STANDARD_ARGB32, width, height, NULL);
+ break;
+ default:
+ CAIRO_BOILERPLATE_LOG ("Invalid content for glitz-agl test: %d\n", content);
+ goto FAIL;
+ }
+
+ if (!glitz_surface)
+ goto FAIL;
+
+ surface = cairo_glitz_surface_create (glitz_surface);
+
+ aglc->base.width = width;
+ aglc->base.height = height;
+ aglc->base.content = content;
+ cairo_surface_set_user_data (surface, &glitz_closure_key, aglc, NULL);
+
+ return surface;
+
+ FAIL:
+ return NULL;
+}
+
+static void
+cleanup_cairo_glitz_agl (void *closure)
+{
+ free (closure);
+ glitz_agl_fini ();
+}
+
+#endif /* CAIRO_CAN_TEST_GLITZ_AGL_SURFACE */
+
+#if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
+#include <glitz-wgl.h>
+
+typedef struct _glitz_wgl_target_closure {
+ glitz_target_closure_base_t base;
+} glitz_wgl_target_closure_t;
+
+static glitz_surface_t *
+create_glitz_wgl_surface (glitz_format_name_t formatname,
+ int width, int height,
+ glitz_wgl_target_closure_t *closure)
+{
+ glitz_drawable_format_t *dformat;
+ glitz_drawable_format_t templ;
+ glitz_drawable_t *gdraw;
+ glitz_format_t *format;
+ glitz_surface_t *sr = NULL;
+ unsigned long mask;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.color.red_size = 8;
+ templ.color.green_size = 8;
+ templ.color.blue_size = 8;
+ templ.color.alpha_size = 8;
+ templ.color.fourcc = GLITZ_FOURCC_RGB;
+ templ.samples = 1;
+
+ mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK |
+ GLITZ_FORMAT_RED_SIZE_MASK | GLITZ_FORMAT_GREEN_SIZE_MASK |
+ GLITZ_FORMAT_BLUE_SIZE_MASK;
+ if (formatname == GLITZ_STANDARD_ARGB32)
+ mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
+
+ dformat = glitz_wgl_find_pbuffer_format (mask, &templ, 0);
+ if (!dformat) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to find pbuffer format for template.");
+ goto FAIL;
+ }
+
+ gdraw = glitz_wgl_create_pbuffer_drawable (dformat, width, height);
+ if (!gdraw) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to create pbuffer drawable.");
+ goto FAIL;
+ }
+
+ format = glitz_find_standard_format (gdraw, formatname);
+ if (!format) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to find standard format for drawable.");
+ goto DESTROY_DRAWABLE;
+ }
+
+ sr = glitz_surface_create (gdraw, format, width, height, 0, NULL);
+ if (!sr) {
+ CAIRO_BOILERPLATE_LOG ("Glitz failed to create a surface.");
+ goto DESTROY_DRAWABLE;
+ }
+
+ glitz_surface_attach (sr, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
+
+ DESTROY_DRAWABLE:
+ glitz_drawable_destroy (gdraw);
+
+ FAIL:
+ return sr; /* will be NULL unless we create it and attach */
+}
+
+static cairo_surface_t *
+create_cairo_glitz_wgl_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ glitz_surface_t *glitz_surface;
+ cairo_surface_t *surface;
+ glitz_wgl_target_closure_t *wglc;
+
+ glitz_wgl_init (NULL);
+
+ *closure = wglc = xmalloc (sizeof (glitz_wgl_target_closure_t));
+
+ switch (content) {
+ case CAIRO_CONTENT_COLOR:
+ glitz_surface = create_glitz_wgl_surface (GLITZ_STANDARD_RGB24, width, height, NULL);
+ break;
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ glitz_surface = create_glitz_wgl_surface (GLITZ_STANDARD_ARGB32, width, height, NULL);
+ break;
+ default:
+ CAIRO_BOILERPLATE_LOG ("Invalid content for glitz-wgl test: %d\n", content);
+ goto FAIL;
+ }
+
+ if (!glitz_surface)
+ goto FAIL;
+
+ surface = cairo_glitz_surface_create (glitz_surface);
+
+ wglc->base.width = width;
+ wglc->base.height = height;
+ wglc->base.content = content;
+ cairo_surface_set_user_data (surface, &glitz_closure_key, wglc, NULL);
+
+ return surface;
+
+ FAIL:
+ return NULL;
+}
+
+static void
+cleanup_cairo_glitz_wgl (void *closure)
+{
+ free (closure);
+ glitz_wgl_fini ();
+}
+
+#endif /* CAIRO_CAN_TEST_GLITZ_WGL_SURFACE */
+
+#endif /* CAIRO_HAS_GLITZ_SURFACE */
+
+#if 0 && CAIRO_HAS_QUARTZ_SURFACE
+static cairo_surface_t *
+create_quartz_surface (int width, int height, void **closure)
+{
+#error Not yet implemented
+}
+
+static void
+cleanup_quartz (void *closure)
+{
+#error Not yet implemented
+}
+#endif
+
+/* Testing the win32 surface isn't interesting, since for
+ * ARGB images it just chains to the image backend
+ */
+#if CAIRO_HAS_WIN32_SURFACE
+#include "cairo-win32.h"
+typedef struct _win32_target_closure
+{
+ HDC dc;
+ HBITMAP bmp;
+} win32_target_closure_t;
+
+static cairo_surface_t *
+create_win32_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ int width = width;
+ int height = height;
+
+ BITMAPINFO bmpInfo;
+ unsigned char *bits = NULL;
+ win32_target_closure_t *data = malloc(sizeof(win32_target_closure_t));
+ *closure = data;
+
+ data->dc = CreateCompatibleDC(NULL);
+
+ /* initialize the bitmapinfoheader */
+ memset(&bmpInfo.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
+ bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
+ bmpInfo.bmiHeader.biWidth = width;
+ bmpInfo.bmiHeader.biHeight = -height;
+ bmpInfo.bmiHeader.biPlanes = 1;
+ bmpInfo.bmiHeader.biBitCount = 24;
+ bmpInfo.bmiHeader.biCompression = BI_RGB;
+
+ /* create a DIBSection */
+ data->bmp = CreateDIBSection(data->dc, &bmpInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+
+ /* Flush GDI to make sure the DIBSection is actually created */
+ GdiFlush();
+
+ /* Select the bitmap in to the DC */
+ SelectObject(data->dc, data->bmp);
+
+ return cairo_win32_surface_create(data->dc);
+}
+
+static void
+cleanup_win32 (void *closure)
+{
+ win32_target_closure_t *data = (win32_target_closure_t*)closure;
+ DeleteObject(data->bmp);
+ DeleteDC(data->dc);
+
+ free(closure);
+}
+#endif
+
+#if CAIRO_HAS_XCB_SURFACE
+#include "cairo-xcb-xrender.h"
+typedef struct _xcb_target_closure
+{
+ XCBConnection *c;
+ XCBDRAWABLE drawable;
+} xcb_target_closure_t;
+
+/* XXX: This is a nasty hack. Something like this should be in XCB's
+ * bindings for Render, not here in this test. */
+static XCBRenderPICTFORMINFO
+_format_from_cairo(XCBConnection *c, cairo_format_t fmt)
+{
+ XCBRenderPICTFORMINFO ret = {{ 0 }};
+ struct tmpl_t {
+ XCBRenderDIRECTFORMAT direct;
+ CARD8 depth;
+ };
+ static const struct tmpl_t templates[] = {
+ /* CAIRO_FORMAT_ARGB32 */
+ {
+ {
+ 16, 0xff,
+ 8, 0xff,
+ 0, 0xff,
+ 24, 0xff
+ },
+ 32
+ },
+ /* CAIRO_FORMAT_RGB24 */
+ {
+ {
+ 16, 0xff,
+ 8, 0xff,
+ 0, 0xff,
+ 0, 0x00
+ },
+ 24
+ },
+ /* CAIRO_FORMAT_A8 */
+ {
+ {
+ 0, 0x00,
+ 0, 0x00,
+ 0, 0x00,
+ 0, 0xff
+ },
+ 8
+ },
+ /* CAIRO_FORMAT_A1 */
+ {
+ {
+ 0, 0x00,
+ 0, 0x00,
+ 0, 0x00,
+ 0, 0x01
+ },
+ 1
+ },
+ };
+ const struct tmpl_t *tmpl;
+ XCBRenderQueryPictFormatsRep *r;
+ XCBRenderPICTFORMINFOIter fi;
+
+ if(fmt < 0 || fmt >= (sizeof(templates) / sizeof(*templates)))
+ return ret;
+ tmpl = templates + fmt;
+
+ r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0);
+ if(!r)
+ return ret;
+
+ for(fi = XCBRenderQueryPictFormatsFormatsIter(r); fi.rem; XCBRenderPICTFORMINFONext(&fi))
+ {
+ const XCBRenderDIRECTFORMAT *t, *f;
+ if(fi.data->type != XCBRenderPictTypeDirect)
+ continue;
+ if(fi.data->depth != tmpl->depth)
+ continue;
+ t = &tmpl->direct;
+ f = &fi.data->direct;
+ if(t->red_mask && (t->red_mask != f->red_mask || t->red_shift != f->red_shift))
+ continue;
+ if(t->green_mask && (t->green_mask != f->green_mask || t->green_shift != f->green_shift))
+ continue;
+ if(t->blue_mask && (t->blue_mask != f->blue_mask || t->blue_shift != f->blue_shift))
+ continue;
+ if(t->alpha_mask && (t->alpha_mask != f->alpha_mask || t->alpha_shift != f->alpha_shift))
+ continue;
+
+ ret = *fi.data;
+ }
+
+ free(r);
+ return ret;
+}
+
+static cairo_surface_t *
+create_xcb_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ int width = width;
+ int height = height;
+ XCBSCREEN *root;
+ xcb_target_closure_t *xtc;
+ cairo_surface_t *surface;
+ XCBConnection *c;
+ XCBRenderPICTFORMINFO render_format;
+ cairo_format_t format;
+
+ *closure = xtc = xmalloc (sizeof (xcb_target_closure_t));
+
+ if (width == 0)
+ width = 1;
+ if (height == 0)
+ height = 1;
+
+ xtc->c = c = XCBConnect(NULL,NULL);
+ if (c == NULL) {
+ CAIRO_BOILERPLATE_LOG ("Failed to connect to X server through XCB\n");
+ return NULL;
+ }
+
+ root = XCBSetupRootsIter(XCBGetSetup(c)).data;
+
+ xtc->drawable.pixmap = XCBPIXMAPNew (c);
+ {
+ XCBDRAWABLE root_drawable;
+ root_drawable.window = root->root;
+ XCBCreatePixmap (c, 32, xtc->drawable.pixmap, root_drawable,
+ width, height);
+ }
+
+ switch (content) {
+ case CAIRO_CONTENT_COLOR:
+ format = CAIRO_FORMAT_RGB24;
+ break;
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ format = CAIRO_FORMAT_ARGB32;
+ break;
+ default:
+ CAIRO_BOILERPLATE_LOG ("Invalid content for XCB test: %d\n", content);
+ return NULL;
+ }
+
+ render_format = _format_from_cairo (c, format);
+ if (render_format.id.xid == 0)
+ return NULL;
+ surface = cairo_xcb_surface_create_with_xrender_format (c, xtc->drawable, root,
+ &render_format,
+ width, height);
+
+ return surface;
+}
+
+static void
+cleanup_xcb (void *closure)
+{
+ xcb_target_closure_t *xtc = closure;
+
+ XCBFreePixmap (xtc->c, xtc->drawable.pixmap);
+ XCBDisconnect (xtc->c);
+ free (xtc);
+}
+#endif
+
+#if CAIRO_HAS_XLIB_SURFACE
+#include "cairo-xlib-xrender.h"
+typedef struct _xlib_target_closure
+{
+ Display *dpy;
+ Pixmap pixmap;
+} xlib_target_closure_t;
+
+static cairo_surface_t *
+create_xlib_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ xlib_target_closure_t *xtc;
+ cairo_surface_t *surface;
+ Display *dpy;
+ XRenderPictFormat *xrender_format;
+
+ *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
+
+ if (width == 0)
+ width = 1;
+ if (height == 0)
+ height = 1;
+
+ xtc->dpy = dpy = XOpenDisplay (NULL);
+ if (xtc->dpy == NULL) {
+ CAIRO_BOILERPLATE_LOG ("Failed to open display: %s\n", XDisplayName(0));
+ return NULL;
+ }
+
+ XSynchronize (xtc->dpy, 1);
+
+ /* XXX: Currently we don't do any xlib testing when the X server
+ * doesn't have the Render extension. We could do better here,
+ * (perhaps by converting the tests from ARGB32 to RGB24). One
+ * step better would be to always test the non-Render fallbacks
+ * for each test even if the server does have the Render
+ * extension. That would probably be through another
+ * cairo_test_target which would use an extended version of
+ * cairo_test_xlib_disable_render. */
+ switch (content) {
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
+ break;
+ case CAIRO_CONTENT_COLOR:
+ xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
+ break;
+ case CAIRO_CONTENT_ALPHA:
+ default:
+ CAIRO_BOILERPLATE_LOG ("Invalid content for xlib test: %d\n", content);
+ return NULL;
+ }
+ if (xrender_format == NULL) {
+ CAIRO_BOILERPLATE_LOG ("X server does not have the Render extension.\n");
+ return NULL;
+ }
+
+ xtc->pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+ width, height, xrender_format->depth);
+
+ surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->pixmap,
+ DefaultScreenOfDisplay (dpy),
+ xrender_format,
+ width, height);
+ return surface;
+}
+
+static void
+cleanup_xlib (void *closure)
+{
+ xlib_target_closure_t *xtc = closure;
+
+ XFreePixmap (xtc->dpy, xtc->pixmap);
+ XCloseDisplay (xtc->dpy);
+ free (xtc);
+}
+#endif
+
+#if CAIRO_HAS_BEOS_SURFACE
+/* BeOS test functions are external as they need to be C++ */
+#include "cairo-test-beos.h"
+#endif
+
+#if CAIRO_HAS_DIRECTFB_SURFACE
+#include "cairo-test-directfb.h"
+#endif
+
+#if CAIRO_HAS_PS_SURFACE
+#include "cairo-ps.h"
+
+cairo_user_data_key_t ps_closure_key;
+
+typedef struct _ps_target_closure
+{
+ char *filename;
+ int width;
+ int height;
+ cairo_surface_t *target;
+} ps_target_closure_t;
+
+static cairo_surface_t *
+create_ps_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ ps_target_closure_t *ptc;
+ cairo_surface_t *surface;
+ int i;
+
+ for (i = 0; vector_ignored_tests[i] != NULL; i++)
+ if (strcmp (name, vector_ignored_tests[i]) == 0)
+ return NULL;
+
+ /* Sanitize back to a real cairo_content_t value. */
+ if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
+ content = CAIRO_CONTENT_COLOR_ALPHA;
+
+ *closure = ptc = xmalloc (sizeof (ps_target_closure_t));
+
+ xasprintf (&ptc->filename, "%s-ps-%s-out.ps",
+ name, _cairo_test_content_name (content));
+
+ ptc->width = width;
+ ptc->height = height;
+
+ surface = cairo_ps_surface_create (ptc->filename, width, height);
+ if (cairo_surface_status (surface)) {
+ free (ptc->filename);
+ free (ptc);
+ return NULL;
+ }
+ cairo_surface_set_fallback_resolution (surface, 72., 72.);
+
+ if (content == CAIRO_CONTENT_COLOR) {
+ ptc->target = surface;
+ surface = cairo_surface_create_similar (ptc->target,
+ CAIRO_CONTENT_COLOR,
+ width, height);
+ } else {
+ ptc->target = NULL;
+ }
+
+ cairo_surface_set_user_data (surface, &ps_closure_key, ptc, NULL);
+
+ return surface;
+}
+
+static cairo_status_t
+ps_surface_write_to_png (cairo_surface_t *surface, const char *filename)
+{
+ ps_target_closure_t *ptc = cairo_surface_get_user_data (surface, &ps_closure_key);
+ char command[4096];
+
+ /* Both surface and ptc->target were originally created at the
+ * same dimensions. We want a 1:1 copy here, so we first clear any
+ * device offset on surface.
+ *
+ * In a more realistic use case of device offsets, the target of
+ * this copying would be of a different size than the source, and
+ * the offset would be desirable during the copy operation. */
+ cairo_surface_set_device_offset (surface, 0, 0);
+
+ if (ptc->target) {
+ cairo_t *cr;
+ cr = cairo_create (ptc->target);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_show_page (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_finish (surface);
+ surface = ptc->target;
+ }
+
+ cairo_surface_finish (surface);
+ sprintf (command, "gs -q -r72 -g%dx%d -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=%s %s",
+ ptc->width, ptc->height, filename, ptc->filename);
+ if (system (command) == 0)
+ return CAIRO_STATUS_SUCCESS;
+ return CAIRO_STATUS_WRITE_ERROR;
+}
+
+static void
+cleanup_ps (void *closure)
+{
+ ps_target_closure_t *ptc = closure;
+ if (ptc->target)
+ cairo_surface_destroy (ptc->target);
+ free (ptc->filename);
+ free (ptc);
+}
+#endif /* CAIRO_HAS_PS_SURFACE */
+
+#if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
+#include "cairo-pdf.h"
+
+cairo_user_data_key_t pdf_closure_key;
+
+typedef struct _pdf_target_closure
+{
+ char *filename;
+ int width;
+ int height;
+ cairo_surface_t *target;
+} pdf_target_closure_t;
+
+static cairo_surface_t *
+create_pdf_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ int width = width;
+ int height = height;
+ pdf_target_closure_t *ptc;
+ cairo_surface_t *surface;
+ int i;
+
+ for (i = 0; vector_ignored_tests[i] != NULL; i++)
+ if (strcmp (name, vector_ignored_tests[i]) == 0)
+ return NULL;
+
+ /* Sanitize back to a real cairo_content_t value. */
+ if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
+ content = CAIRO_CONTENT_COLOR_ALPHA;
+
+ *closure = ptc = xmalloc (sizeof (pdf_target_closure_t));
+
+ ptc->width = width;
+ ptc->height = height;
+
+ xasprintf (&ptc->filename, "%s-pdf-%s-out.pdf",
+ name, _cairo_test_content_name (content));
+
+ surface = cairo_pdf_surface_create (ptc->filename, width, height);
+ if (cairo_surface_status (surface)) {
+ free (ptc->filename);
+ free (ptc);
+ return NULL;
+ }
+ cairo_surface_set_fallback_resolution (surface, 72., 72.);
+
+ if (content == CAIRO_CONTENT_COLOR) {
+ ptc->target = surface;
+ surface = cairo_surface_create_similar (ptc->target,
+ CAIRO_CONTENT_COLOR,
+ width, height);
+ } else {
+ ptc->target = NULL;
+ }
+
+ cairo_surface_set_user_data (surface, &pdf_closure_key, ptc, NULL);
+
+ return surface;
+}
+
+static cairo_status_t
+pdf_surface_write_to_png (cairo_surface_t *surface, const char *filename)
+{
+ pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface, &pdf_closure_key);
+ char command[4096];
+
+ /* Both surface and ptc->target were originally created at the
+ * same dimensions. We want a 1:1 copy here, so we first clear any
+ * device offset on surface.
+ *
+ * In a more realistic use case of device offsets, the target of
+ * this copying would be of a different size than the source, and
+ * the offset would be desirable during the copy operation. */
+ cairo_surface_set_device_offset (surface, 0, 0);
+
+ if (ptc->target) {
+ cairo_t *cr;
+ cr = cairo_create (ptc->target);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_show_page (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_finish (surface);
+ surface = ptc->target;
+ }
+
+ cairo_surface_finish (surface);
+ sprintf (command, "./pdf2png %s %s 1",
+ ptc->filename, filename);
+
+ if (system (command) != 0)
+ return CAIRO_STATUS_WRITE_ERROR;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+cleanup_pdf (void *closure)
+{
+ pdf_target_closure_t *ptc = closure;
+ if (ptc->target)
+ cairo_surface_destroy (ptc->target);
+ free (ptc->filename);
+ free (ptc);
+}
+#endif /* CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE */
+
+#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
+#include "cairo-svg.h"
+
+cairo_user_data_key_t svg_closure_key;
+
+typedef struct _svg_target_closure
+{
+ char *filename;
+ int width, height;
+ cairo_surface_t *target;
+} svg_target_closure_t;
+
+static cairo_surface_t *
+create_svg_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure)
+{
+ int width = width;
+ int height = height;
+ int i;
+ svg_target_closure_t *ptc;
+ cairo_surface_t *surface;
+
+ for (i = 0; vector_ignored_tests[i] != NULL; i++)
+ if (strcmp (name, vector_ignored_tests[i]) == 0)
+ return NULL;
+
+ *closure = ptc = xmalloc (sizeof (svg_target_closure_t));
+
+ ptc->width = width;
+ ptc->height = height;
+
+ xasprintf (&ptc->filename, "%s-svg-%s-out.svg",
+ name, _cairo_test_content_name (content));
+
+ surface = cairo_svg_surface_create (ptc->filename, width, height);
+ if (cairo_surface_status (surface)) {
+ free (ptc->filename);
+ free (ptc);
+ return NULL;
+ }
+ cairo_surface_set_fallback_resolution (surface, 72., 72.);
+
+ if (content == CAIRO_CONTENT_COLOR) {
+ ptc->target = surface;
+ surface = cairo_surface_create_similar (ptc->target,
+ CAIRO_CONTENT_COLOR,
+ width, height);
+ } else {
+ ptc->target = NULL;
+ }
+
+ cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
+
+ return surface;
+}
+
+static cairo_status_t
+svg_surface_write_to_png (cairo_surface_t *surface, const char *filename)
+{
+ svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key);
+ char command[4096];
+
+ /* Both surface and ptc->target were originally created at the
+ * same dimensions. We want a 1:1 copy here, so we first clear any
+ * device offset on surface.
+ *
+ * In a more realistic use case of device offsets, the target of
+ * this copying would be of a different size than the source, and
+ * the offset would be desirable during the copy operation. */
+ cairo_surface_set_device_offset (surface, 0, 0);
+
+ if (ptc->target) {
+ cairo_t *cr;
+ cr = cairo_create (ptc->target);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_show_page (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_finish (surface);
+ surface = ptc->target;
+ }
+
+ cairo_surface_finish (surface);
+ sprintf (command, "./svg2png %s %s",
+ ptc->filename, filename);
+
+ if (system (command) != 0)
+ return CAIRO_STATUS_WRITE_ERROR;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+cleanup_svg (void *closure)
+{
+ svg_target_closure_t *ptc = closure;
+ if (ptc->target)
+ cairo_surface_destroy (ptc->target);
+ free (ptc->filename);
+ free (ptc);
+}
+#endif /* CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE */
+
+cairo_test_target_t targets[] =
+{
+ { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA,
+ create_image_surface, cairo_surface_write_to_png, NULL},
+ { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
+ create_image_surface, cairo_surface_write_to_png, NULL},
+#ifdef CAIRO_HAS_TEST_SURFACES
+ { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ create_test_fallback_surface, cairo_surface_write_to_png, NULL },
+ { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+ CAIRO_CONTENT_COLOR,
+ create_test_fallback_surface, cairo_surface_write_to_png, NULL },
+ { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ create_test_meta_surface, cairo_surface_write_to_png, NULL },
+ { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+ CAIRO_CONTENT_COLOR,
+ create_test_meta_surface, cairo_surface_write_to_png, NULL },
+ { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ create_test_paginated_surface,
+ test_paginated_write_to_png,
+ cleanup_test_paginated },
+ { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+ CAIRO_CONTENT_COLOR,
+ create_test_paginated_surface,
+ test_paginated_write_to_png,
+ cleanup_test_paginated },
+#endif
+#ifdef CAIRO_HAS_GLITZ_SURFACE
+#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
+ { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA,
+ create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
+ cleanup_cairo_glitz_glx },
+ { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
+ create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
+ cleanup_cairo_glitz_glx },
+#endif
+#if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
+ { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
+ create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
+ cleanup_cairo_glitz_agl },
+ { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
+ create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
+ cleanup_cairo_glitz_agl },
+#endif
+#if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
+ { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
+ create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
+ cleanup_cairo_glitz_wgl },
+ { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
+ create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
+ cleanup_cairo_glitz_wgl },
+#endif
+#endif /* CAIRO_HAS_GLITZ_SURFACE */
+#if 0 && CAIRO_HAS_QUARTZ_SURFACE
+ { "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR,
+ create_quartz_surface, cairo_surface_write_to_png,
+ cleanup_quartz },
+#endif
+#if CAIRO_HAS_WIN32_SURFACE
+ { "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR,
+ create_win32_surface, cairo_surface_write_to_png, cleanup_win32 },
+#endif
+#if CAIRO_HAS_XCB_SURFACE
+ { "xcb", CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA,
+ create_xcb_surface, cairo_surface_write_to_png, cleanup_xcb},
+#endif
+#if CAIRO_HAS_XLIB_SURFACE
+ { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA,
+ create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
+ { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR,
+ create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
+#endif
+#if CAIRO_HAS_PS_SURFACE
+ { "ps", CAIRO_SURFACE_TYPE_PS,
+ CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
+ create_ps_surface, ps_surface_write_to_png, cleanup_ps },
+
+ /* XXX: We expect type image here only due to a limitation in
+ * the current PS/meta-surface code. A PS surface is
+ * "naturally" COLOR_ALPHA, so the COLOR-only variant goes
+ * through create_similar in create_ps_surface which results
+ * in the similar surface being used as a source. We do not yet
+ * have source support for PS/meta-surfaces, so the
+ * create_similar path for all paginated surfaces currently
+ * returns an image surface.*/
+ { "ps", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
+ create_ps_surface, ps_surface_write_to_png, cleanup_ps },
+#endif
+#if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
+ { "pdf", CAIRO_SURFACE_TYPE_PDF,
+ CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
+ create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
+
+ /* XXX: We expect type image here only due to a limitation in
+ * the current PDF/meta-surface code. A PDF surface is
+ * "naturally" COLOR_ALPHA, so the COLOR-only variant goes
+ * through create_similar in create_pdf_surface which results
+ * in the similar surface being used as a source. We do not yet
+ * have source support for PDF/meta-surfaces, so the
+ * create_similar path for all paginated surfaces currently
+ * returns an image surface.*/
+ { "pdf", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
+ create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
+#endif
+#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
+ { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA,
+ create_svg_surface, svg_surface_write_to_png, cleanup_svg },
+ { "svg", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR,
+ create_svg_surface, svg_surface_write_to_png, cleanup_svg },
+#endif
+#if CAIRO_HAS_BEOS_SURFACE
+ { "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
+ create_beos_surface, cairo_surface_write_to_png, cleanup_beos},
+ { "beos-bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
+ create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
+ { "beos-bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA,
+ create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
+#endif
+
+#if CAIRO_HAS_DIRECTFB_SURFACE
+ { "directfb", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR,
+ create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb},
+ { "directfb-bitmap", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA,
+ create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb},
+#endif
+
+ { NULL }
+};
+
+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);
+
+ if (ret < 0) {
+ cairo_test_log ("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) {
+ CAIRO_BOILERPLATE_LOG ("Failure in vsnprintf\n");
+ exit (1);
+ }
+
+ if (strlen (buffer) == sizeof(buffer) - 1) {
+ CAIRO_BOILERPLATE_LOG ("Overflowed fixed buffer\n");
+ exit (1);
+ }
+
+ *strp = strdup (buffer);
+ if (!*strp) {
+ CAIRO_BOILERPLATE_LOG ("Out of memory\n");
+ exit (1);
+ }
+#endif /* !HAVE_VASNPRINTF */
+}
diff --git a/boilerplate/cairo-boilerplate.h b/boilerplate/cairo-boilerplate.h
new file mode 100644
index 0000000..183f6a2
--- /dev/null
+++ b/boilerplate/cairo-boilerplate.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2004-2006 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: Carl D. Worth <cworth at cworth.org>
+ */
+
+#ifndef _CAIRO_BOILERPLATE_H_
+#define _CAIRO_BOILERPLATE_H_
+
+#include <cairo.h>
+
+#include "xmalloc.h"
+
+#ifndef CAIRO_BOILERPLATE_LOG
+#define CAIRO_BOILERPLATE_LOG(...) fprintf(stderr, __VA_ARGS__)
+#endif
+
+/* A fake format we use for the flattened ARGB output of the PS and
+ * PDF surfaces. */
+#define CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED ((unsigned int) -1)
+
+const char *
+_cairo_test_content_name (cairo_content_t content);
+
+typedef cairo_surface_t *
+(*cairo_test_create_target_surface_t) (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ void **closure);
+
+typedef cairo_status_t
+(*cairo_test_write_to_png_t) (cairo_surface_t *surface, const char *filename);
+
+typedef void
+(*cairo_test_cleanup_target_t) (void *closure);
+
+typedef struct _cairo_test_target
+{
+ const char *name;
+ cairo_surface_type_t expected_type;
+ cairo_content_t content;
+ cairo_test_create_target_surface_t create_target_surface;
+ cairo_test_write_to_png_t write_to_png;
+ cairo_test_cleanup_target_t cleanup_target;
+ void *closure;
+} cairo_test_target_t;
+
+extern cairo_test_target_t targets[];
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \
+ __attribute__((__format__(__printf__, fmt_index, va_index)))
+#else
+#define CAIRO_PRINTF_FORMAT(fmt_index, va_index)
+#endif
+
+void
+xasprintf (char **strp, const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3);
+
+#endif
diff --git a/boilerplate/cairo-test.c b/boilerplate/cairo-test.c
index bf52f8a..0243edf 100644
--- a/boilerplate/cairo-test.c
+++ b/boilerplate/cairo-test.c
@@ -67,19 +67,6 @@ typedef enum cairo_internal_surface_type
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
} cairo_internal_surface_type_t;
-static const char *vector_ignored_tests[] = {
- /* We can't match the results of tests that depend on
- * CAIRO_ANTIALIAS_NONE/SUBPIXEL for vector backends
- * (nor do we care). */
- "ft-text-antialias-none",
- "rectangle-rounding-error",
- "text-antialias-gray",
- "text-antialias-none",
- "text-antialias-subpixel",
- "unantialiased-shapes",
- NULL
-};
-
#ifdef _MSC_VER
#define vsnprintf _vsnprintf
#define access _access
@@ -104,10 +91,6 @@ static const char *fail_face = "", *norm
#define NUM_DEVICE_OFFSETS 2
-/* A fake format we use for the flattened ARGB output of the PS and
- * PDF surfaces. */
-#define CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED ((unsigned int) -1)
-
/* Static data is messy, but we're coding for tests here, not a
* general-purpose library, and it keeps the tests cleaner to avoid a
* context object there, (though not a whole lot). */
@@ -148,49 +131,6 @@ cairo_test_log (const char *fmt, ...)
va_end (va);
}
-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);
-
- if (ret < 0) {
- cairo_test_log ("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) {
- cairo_test_log ("Failure in vsnprintf\n");
- exit (1);
- }
-
- if (strlen (buffer) == sizeof(buffer) - 1) {
- cairo_test_log ("Overflowed fixed buffer\n");
- exit (1);
- }
-
- *strp = strdup (buffer);
- if (!*strp) {
- cairo_test_log ("Out of memory\n");
- exit (1);
- }
-#endif /* !HAVE_VASNPRINTF */
-}
-
static void
xunlink (const char *pathname)
{
@@ -201,1285 +141,6 @@ xunlink (const char *pathname)
}
}
-typedef cairo_surface_t *
-(*cairo_test_create_target_surface_t) (cairo_test_t *test,
- cairo_content_t content,
- void **closure);
-
-typedef cairo_status_t
-(*cairo_test_write_to_png_t) (cairo_surface_t *surface, const char *filename);
-
-typedef void
-(*cairo_test_cleanup_target_t) (void *closure);
-
-typedef struct _cairo_test_target
-{
- const char *name;
- cairo_surface_type_t expected_type;
- cairo_content_t content;
- cairo_test_create_target_surface_t create_target_surface;
- cairo_test_write_to_png_t write_to_png;
- cairo_test_cleanup_target_t cleanup_target;
- void *closure;
-} cairo_test_target_t;
-
-static const char *
-_cairo_test_content_name (cairo_content_t content)
-{
- /* For the purpose of the content name, we don't distinguish the
- * flattened content value.
- */
- if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
- content = CAIRO_CONTENT_COLOR_ALPHA;
-
- switch (content) {
- case CAIRO_CONTENT_COLOR:
- return "rgb24";
- case CAIRO_CONTENT_COLOR_ALPHA:
- return "argb32";
- case CAIRO_CONTENT_ALPHA:
- default:
- assert (0); /* not reached */
- return "---";
- }
-}
-
-static cairo_surface_t *
-create_image_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- cairo_format_t format;
- *closure = NULL;
-
- if (content == CAIRO_CONTENT_COLOR_ALPHA) {
- format = CAIRO_FORMAT_ARGB32;
- } else if (content == CAIRO_CONTENT_COLOR) {
- format = CAIRO_FORMAT_RGB24;
- } else {
- assert (0); /* not reached */
- return NULL;
- }
-
- return cairo_image_surface_create (format, test->width, test->height);
-}
-
-#ifdef CAIRO_HAS_TEST_SURFACES
-
-#include "test-fallback-surface.h"
-#include "test-meta-surface.h"
-#include "test-paginated-surface.h"
-
-static cairo_surface_t *
-create_test_fallback_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- *closure = NULL;
- return _test_fallback_surface_create (content, test->width, test->height);
-}
-
-static cairo_surface_t *
-create_test_meta_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- *closure = NULL;
- return _test_meta_surface_create (content, test->width, test->height);
-}
-
-static const cairo_user_data_key_t test_paginated_closure_key;
-
-typedef struct {
- unsigned char *data;
- cairo_content_t content;
- int width;
- int height;
- int stride;
-} test_paginated_closure_t;
-
-static cairo_surface_t *
-create_test_paginated_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- test_paginated_closure_t *tpc;
- cairo_surface_t *surface;
-
- *closure = tpc = xmalloc (sizeof (test_paginated_closure_t));
-
- tpc->content = content;
- tpc->width = test->width;
- tpc->height = test->height;
- tpc->stride = test->width * 4;
-
- tpc->data = xcalloc (tpc->stride * test->height, 1);
-
- surface = _test_paginated_surface_create_for_data (tpc->data,
- tpc->content,
- tpc->width,
- tpc->height,
- tpc->stride);
-
- cairo_surface_set_user_data (surface, &test_paginated_closure_key,
- tpc, NULL);
-
- return surface;
-}
-
-/* The only reason we go through all these machinations to write a PNG
- * image is to _really ensure_ that the data actually landed in our
- * buffer through the paginated surface to the test_paginated_surface.
- *
- * If we didn't implement this function then the default
- * cairo_surface_write_to_png would result in the paginated_surface's
- * acquire_source_image function replaying the meta-surface to an
- * intermediate image surface. And in that case the
- * test_paginated_surface would not be involved and wouldn't be
- * tested.
- */
-static cairo_status_t
-test_paginated_write_to_png (cairo_surface_t *surface,
- const char *filename)
-{
- cairo_surface_t *image;
- cairo_format_t format;
- test_paginated_closure_t *tpc;
-
- tpc = cairo_surface_get_user_data (surface, &test_paginated_closure_key);
-
- switch (tpc->content) {
- case CAIRO_CONTENT_COLOR:
- format = CAIRO_FORMAT_RGB24;
- break;
- case CAIRO_CONTENT_COLOR_ALPHA:
- format = CAIRO_FORMAT_ARGB32;
- break;
- case CAIRO_CONTENT_ALPHA:
- default:
- assert (0); /* not reached */
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- image = cairo_image_surface_create_for_data (tpc->data,
- format,
- tpc->width,
- tpc->height,
- tpc->stride);
-
- cairo_surface_write_to_png (image, filename);
-
- cairo_surface_destroy (image);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-cleanup_test_paginated (void *closure)
-{
- test_paginated_closure_t *tpc = closure;
-
- free (tpc->data);
- free (tpc);
-}
-
-#endif
-
-#ifdef CAIRO_HAS_GLITZ_SURFACE
-#include <glitz.h>
-#include <cairo-glitz.h>
-
-static const cairo_user_data_key_t glitz_closure_key;
-
-typedef struct _glitz_target_closure_base {
- int width;
- int height;
- cairo_content_t content;
-} glitz_target_closure_base_t;
-
-#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
-#include <glitz-glx.h>
-
-typedef struct _glitz_glx_target_closure {
- glitz_target_closure_base_t base;
- Display *dpy;
- int scr;
- Window win;
-} glitz_glx_target_closure_t;
-
-static glitz_surface_t *
-create_glitz_glx_surface (glitz_format_name_t formatname,
- int width,
- int height,
- glitz_glx_target_closure_t *closure)
-{
- Display * dpy = closure->dpy;
- int scr = closure->scr;
- glitz_drawable_format_t templ;
- glitz_drawable_format_t * dformat = NULL;
- unsigned long mask;
- glitz_drawable_t * drawable = NULL;
- glitz_format_t * format;
- glitz_surface_t * sr;
-
- XSizeHints xsh;
- XSetWindowAttributes xswa;
- XVisualInfo * vinfo;
-
- memset(&templ, 0, sizeof(templ));
- templ.color.red_size = 8;
- templ.color.green_size = 8;
- templ.color.blue_size = 8;
- templ.color.alpha_size = 8;
- templ.color.fourcc = GLITZ_FOURCC_RGB;
- templ.samples = 1;
-
- glitz_glx_init (NULL);
-
- mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK |
- GLITZ_FORMAT_RED_SIZE_MASK | GLITZ_FORMAT_GREEN_SIZE_MASK |
- GLITZ_FORMAT_BLUE_SIZE_MASK;
- if (formatname == GLITZ_STANDARD_ARGB32)
- mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
-
- /* Try for a pbuffer first */
- if (!getenv("CAIRO_TEST_FORCE_GLITZ_WINDOW"))
- dformat = glitz_glx_find_pbuffer_format (dpy, scr, mask, &templ, 0);
-
- if (dformat) {
- closure->win = None;
-
- drawable = glitz_glx_create_pbuffer_drawable (dpy, scr, dformat,
- width, height);
- if (!drawable)
- goto FAIL;
- } else {
- /* No pbuffer, try window */
- dformat = glitz_glx_find_window_format (dpy, scr, mask, &templ, 0);
-
- if (!dformat)
- goto FAIL;
-
- vinfo = glitz_glx_get_visual_info_from_format(dpy,
- DefaultScreen(dpy),
- dformat);
-
- if (!vinfo)
- goto FAIL;
-
- xsh.flags = PSize;
- xsh.x = 0;
- xsh.y = 0;
- xsh.width = width;
- xsh.height = height;
-
- xswa.colormap = XCreateColormap (dpy, RootWindow(dpy, scr),
- vinfo->visual, AllocNone);
- closure->win = XCreateWindow (dpy, RootWindow(dpy, scr),
- xsh.x, xsh.y, xsh.width, xsh.height,
- 0, vinfo->depth, CopyFromParent,
- vinfo->visual, CWColormap, &xswa);
- XFree (vinfo);
-
- drawable =
- glitz_glx_create_drawable_for_window (dpy, scr,
- dformat, closure->win,
- width, height);
-
- if (!drawable)
- goto DESTROY_WINDOW;
- }
-
- format = glitz_find_standard_format (drawable, formatname);
- if (!format)
- goto DESTROY_DRAWABLE;
-
- sr = glitz_surface_create (drawable, format, width, height, 0, NULL);
- if (!sr)
- goto DESTROY_DRAWABLE;
-
- if (closure->win == None || dformat->doublebuffer) {
- glitz_surface_attach (sr, drawable, GLITZ_DRAWABLE_BUFFER_BACK_COLOR);
- } else {
- XMapWindow (closure->dpy, closure->win);
- glitz_surface_attach (sr, drawable, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
- }
-
- glitz_drawable_destroy (drawable);
-
- return sr;
- DESTROY_DRAWABLE:
- glitz_drawable_destroy (drawable);
- DESTROY_WINDOW:
- if (closure->win)
- XDestroyWindow (dpy, closure->win);
- FAIL:
- return NULL;
-}
-
-static cairo_surface_t *
-create_cairo_glitz_glx_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
- glitz_glx_target_closure_t *gxtc;
- glitz_surface_t * glitz_surface;
- cairo_surface_t * surface;
-
- *closure = gxtc = xmalloc (sizeof (glitz_glx_target_closure_t));
-
- if (width == 0)
- width = 1;
- if (height == 0)
- height = 1;
-
- gxtc->dpy = XOpenDisplay (getenv("CAIRO_TEST_GLITZ_DISPLAY"));
- if (!gxtc->dpy) {
- cairo_test_log ("Failed to open display: %s\n", XDisplayName(0));
- goto FAIL;
- }
-
- XSynchronize (gxtc->dpy, 1);
-
- gxtc->scr = DefaultScreen(gxtc->dpy);
-
- switch (content) {
- case CAIRO_CONTENT_COLOR:
- glitz_surface = create_glitz_glx_surface (GLITZ_STANDARD_RGB24, width, height, gxtc);
- break;
- case CAIRO_CONTENT_COLOR_ALPHA:
- glitz_surface = create_glitz_glx_surface (GLITZ_STANDARD_ARGB32, width, height, gxtc);
- break;
- default:
- cairo_test_log ("Invalid content for glitz-glx test: %d\n", content);
- goto FAIL_CLOSE_DISPLAY;
- }
- if (!glitz_surface) {
- cairo_test_log ("Failed to create glitz-glx surface\n");
- goto FAIL_CLOSE_DISPLAY;
- }
-
- surface = cairo_glitz_surface_create (glitz_surface);
-
- gxtc->base.width = test->width;
- gxtc->base.height = test->height;
- gxtc->base.content = content;
- cairo_surface_set_user_data (surface, &glitz_closure_key,
- gxtc, NULL);
-
- return surface;
-
- FAIL_CLOSE_DISPLAY:
- XCloseDisplay (gxtc->dpy);
- FAIL:
- return NULL;
-}
-
-static void
-cleanup_cairo_glitz_glx (void *closure)
-{
- glitz_glx_target_closure_t *gxtc = closure;
-
- glitz_glx_fini ();
-
- if (gxtc->win)
- XDestroyWindow (gxtc->dpy, gxtc->win);
-
- XCloseDisplay (gxtc->dpy);
-
- free (gxtc);
-}
-
-#endif /* CAIRO_CAN_TEST_GLITZ_GLX_SURFACE */
-
-#if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
-#include <glitz-agl.h>
-
-typedef struct _glitz_agl_target_closure {
- glitz_target_closure_base_t base;
-} glitz_agl_target_closure_t;
-
-static glitz_surface_t *
-create_glitz_agl_surface (glitz_format_name_t formatname,
- int width, int height,
- glitz_agl_target_closure_t *closure)
-{
- glitz_drawable_format_t *dformat;
- glitz_drawable_format_t templ;
- glitz_drawable_t *gdraw;
- glitz_format_t *format;
- glitz_surface_t *sr = NULL;
- unsigned long mask;
-
- memset(&templ, 0, sizeof(templ));
- templ.color.red_size = 8;
- templ.color.green_size = 8;
- templ.color.blue_size = 8;
- templ.color.alpha_size = 8;
- templ.color.fourcc = GLITZ_FOURCC_RGB;
- templ.samples = 1;
-
- mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK |
- GLITZ_FORMAT_RED_SIZE_MASK | GLITZ_FORMAT_GREEN_SIZE_MASK |
- GLITZ_FORMAT_BLUE_SIZE_MASK;
- if (formatname == GLITZ_STANDARD_ARGB32)
- mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
-
- dformat = glitz_agl_find_pbuffer_format (mask, &templ, 0);
- if (!dformat) {
- cairo_test_log ("Glitz failed to find pbuffer format for template.");
- goto FAIL;
- }
-
- gdraw = glitz_agl_create_pbuffer_drawable (dformat, width, height);
- if (!gdraw) {
- cairo_test_log ("Glitz failed to create pbuffer drawable.");
- goto FAIL;
- }
-
- format = glitz_find_standard_format (gdraw, formatname);
- if (!format) {
- cairo_test_log ("Glitz failed to find standard format for drawable.");
- goto DESTROY_DRAWABLE;
- }
-
- sr = glitz_surface_create (gdraw, format, width, height, 0, NULL);
- if (!sr) {
- cairo_test_log ("Glitz failed to create a surface.");
- goto DESTROY_DRAWABLE;
- }
-
- glitz_surface_attach (sr, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
-
- DESTROY_DRAWABLE:
- glitz_drawable_destroy (gdraw);
-
- FAIL:
- return sr; /* will be NULL unless we create it and attach */
-}
-
-static cairo_surface_t *
-create_cairo_glitz_agl_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- glitz_surface_t *glitz_surface;
- cairo_surface_t *surface;
- glitz_agl_target_closure_t *aglc;
-
- glitz_agl_init ();
-
- *closure = aglc = xmalloc (sizeof (glitz_agl_target_closure_t));
-
- switch (content) {
- case CAIRO_CONTENT_COLOR:
- glitz_surface = create_glitz_agl_surface (GLITZ_STANDARD_RGB24, test->width, test->height, NULL);
- break;
- case CAIRO_CONTENT_COLOR_ALPHA:
- glitz_surface = create_glitz_agl_surface (GLITZ_STANDARD_ARGB32, test->width, test->height, NULL);
- break;
- default:
- cairo_test_log ("Invalid content for glitz-agl test: %d\n", content);
- goto FAIL;
- }
-
- if (!glitz_surface)
- goto FAIL;
-
- surface = cairo_glitz_surface_create (glitz_surface);
-
- aglc->base.width = test->width;
- aglc->base.height = test->height;
- aglc->base.content = content;
- cairo_surface_set_user_data (surface, &glitz_closure_key, aglc, NULL);
-
- return surface;
-
- FAIL:
- return NULL;
-}
-
-static void
-cleanup_cairo_glitz_agl (void *closure)
-{
- free (closure);
- glitz_agl_fini ();
-}
-
-#endif /* CAIRO_CAN_TEST_GLITZ_AGL_SURFACE */
-
-#if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
-#include <glitz-wgl.h>
-
-typedef struct _glitz_wgl_target_closure {
- glitz_target_closure_base_t base;
-} glitz_wgl_target_closure_t;
-
-static glitz_surface_t *
-create_glitz_wgl_surface (glitz_format_name_t formatname,
- int width, int height,
- glitz_wgl_target_closure_t *closure)
-{
- glitz_drawable_format_t *dformat;
- glitz_drawable_format_t templ;
- glitz_drawable_t *gdraw;
- glitz_format_t *format;
- glitz_surface_t *sr = NULL;
- unsigned long mask;
-
- memset(&templ, 0, sizeof(templ));
- templ.color.red_size = 8;
- templ.color.green_size = 8;
- templ.color.blue_size = 8;
- templ.color.alpha_size = 8;
- templ.color.fourcc = GLITZ_FOURCC_RGB;
- templ.samples = 1;
-
- mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK |
- GLITZ_FORMAT_RED_SIZE_MASK | GLITZ_FORMAT_GREEN_SIZE_MASK |
- GLITZ_FORMAT_BLUE_SIZE_MASK;
- if (formatname == GLITZ_STANDARD_ARGB32)
- mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK;
-
- dformat = glitz_wgl_find_pbuffer_format (mask, &templ, 0);
- if (!dformat) {
- cairo_test_log ("Glitz failed to find pbuffer format for template.");
- goto FAIL;
- }
-
- gdraw = glitz_wgl_create_pbuffer_drawable (dformat, width, height);
- if (!gdraw) {
- cairo_test_log ("Glitz failed to create pbuffer drawable.");
- goto FAIL;
- }
-
- format = glitz_find_standard_format (gdraw, formatname);
- if (!format) {
- cairo_test_log ("Glitz failed to find standard format for drawable.");
- goto DESTROY_DRAWABLE;
- }
-
- sr = glitz_surface_create (gdraw, format, width, height, 0, NULL);
- if (!sr) {
- cairo_test_log ("Glitz failed to create a surface.");
- goto DESTROY_DRAWABLE;
- }
-
- glitz_surface_attach (sr, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
-
- DESTROY_DRAWABLE:
- glitz_drawable_destroy (gdraw);
-
- FAIL:
- return sr; /* will be NULL unless we create it and attach */
-}
-
-static cairo_surface_t *
-create_cairo_glitz_wgl_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- glitz_surface_t *glitz_surface;
- cairo_surface_t *surface;
- glitz_wgl_target_closure_t *wglc;
-
- glitz_wgl_init (NULL);
-
- *closure = wglc = xmalloc (sizeof (glitz_wgl_target_closure_t));
-
- switch (content) {
- case CAIRO_CONTENT_COLOR:
- glitz_surface = create_glitz_wgl_surface (GLITZ_STANDARD_RGB24, test->width, test->height, NULL);
- break;
- case CAIRO_CONTENT_COLOR_ALPHA:
- glitz_surface = create_glitz_wgl_surface (GLITZ_STANDARD_ARGB32, test->width, test->height, NULL);
- break;
- default:
- cairo_test_log ("Invalid content for glitz-wgl test: %d\n", content);
- goto FAIL;
- }
-
- if (!glitz_surface)
- goto FAIL;
-
- surface = cairo_glitz_surface_create (glitz_surface);
-
- wglc->base.width = test->width;
- wglc->base.height = test->height;
- wglc->base.content = content;
- cairo_surface_set_user_data (surface, &glitz_closure_key, wglc, NULL);
-
- return surface;
-
- FAIL:
- return NULL;
-}
-
-static void
-cleanup_cairo_glitz_wgl (void *closure)
-{
- free (closure);
- glitz_wgl_fini ();
-}
-
-#endif /* CAIRO_CAN_TEST_GLITZ_WGL_SURFACE */
-
-#endif /* CAIRO_HAS_GLITZ_SURFACE */
-
-#if 0 && CAIRO_HAS_QUARTZ_SURFACE
-static cairo_surface_t *
-create_quartz_surface (int width, int height, void **closure)
-{
-#error Not yet implemented
-}
-
-static void
-cleanup_quartz (void *closure)
-{
-#error Not yet implemented
-}
-#endif
-
-/* Testing the win32 surface isn't interesting, since for
- * ARGB images it just chains to the image backend
- */
-#if CAIRO_HAS_WIN32_SURFACE
-#include "cairo-win32.h"
-typedef struct _win32_target_closure
-{
- HDC dc;
- HBITMAP bmp;
-} win32_target_closure_t;
-
-static cairo_surface_t *
-create_win32_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
-
- BITMAPINFO bmpInfo;
- unsigned char *bits = NULL;
- win32_target_closure_t *data = malloc(sizeof(win32_target_closure_t));
- *closure = data;
-
- data->dc = CreateCompatibleDC(NULL);
-
- /* initialize the bitmapinfoheader */
- memset(&bmpInfo.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
- bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
- bmpInfo.bmiHeader.biWidth = width;
- bmpInfo.bmiHeader.biHeight = -height;
- bmpInfo.bmiHeader.biPlanes = 1;
- bmpInfo.bmiHeader.biBitCount = 24;
- bmpInfo.bmiHeader.biCompression = BI_RGB;
-
- /* create a DIBSection */
- data->bmp = CreateDIBSection(data->dc, &bmpInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
-
- /* Flush GDI to make sure the DIBSection is actually created */
- GdiFlush();
-
- /* Select the bitmap in to the DC */
- SelectObject(data->dc, data->bmp);
-
- return cairo_win32_surface_create(data->dc);
-}
-
-static void
-cleanup_win32 (void *closure)
-{
- win32_target_closure_t *data = (win32_target_closure_t*)closure;
- DeleteObject(data->bmp);
- DeleteDC(data->dc);
-
- free(closure);
-}
-#endif
-
-#if CAIRO_HAS_XCB_SURFACE
-#include "cairo-xcb-xrender.h"
-typedef struct _xcb_target_closure
-{
- XCBConnection *c;
- XCBDRAWABLE drawable;
-} xcb_target_closure_t;
-
-/* XXX: This is a nasty hack. Something like this should be in XCB's
- * bindings for Render, not here in this test. */
-static XCBRenderPICTFORMINFO
-_format_from_cairo(XCBConnection *c, cairo_format_t fmt)
-{
- XCBRenderPICTFORMINFO ret = {{ 0 }};
- struct tmpl_t {
- XCBRenderDIRECTFORMAT direct;
- CARD8 depth;
- };
- static const struct tmpl_t templates[] = {
- /* CAIRO_FORMAT_ARGB32 */
- {
- {
- 16, 0xff,
- 8, 0xff,
- 0, 0xff,
- 24, 0xff
- },
- 32
- },
- /* CAIRO_FORMAT_RGB24 */
- {
- {
- 16, 0xff,
- 8, 0xff,
- 0, 0xff,
- 0, 0x00
- },
- 24
- },
- /* CAIRO_FORMAT_A8 */
- {
- {
- 0, 0x00,
- 0, 0x00,
- 0, 0x00,
- 0, 0xff
- },
- 8
- },
- /* CAIRO_FORMAT_A1 */
- {
- {
- 0, 0x00,
- 0, 0x00,
- 0, 0x00,
- 0, 0x01
- },
- 1
- },
- };
- const struct tmpl_t *tmpl;
- XCBRenderQueryPictFormatsRep *r;
- XCBRenderPICTFORMINFOIter fi;
-
- if(fmt < 0 || fmt >= (sizeof(templates) / sizeof(*templates)))
- return ret;
- tmpl = templates + fmt;
-
- r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0);
- if(!r)
- return ret;
-
- for(fi = XCBRenderQueryPictFormatsFormatsIter(r); fi.rem; XCBRenderPICTFORMINFONext(&fi))
- {
- const XCBRenderDIRECTFORMAT *t, *f;
- if(fi.data->type != XCBRenderPictTypeDirect)
- continue;
- if(fi.data->depth != tmpl->depth)
- continue;
- t = &tmpl->direct;
- f = &fi.data->direct;
- if(t->red_mask && (t->red_mask != f->red_mask || t->red_shift != f->red_shift))
- continue;
- if(t->green_mask && (t->green_mask != f->green_mask || t->green_shift != f->green_shift))
- continue;
- if(t->blue_mask && (t->blue_mask != f->blue_mask || t->blue_shift != f->blue_shift))
- continue;
- if(t->alpha_mask && (t->alpha_mask != f->alpha_mask || t->alpha_shift != f->alpha_shift))
- continue;
-
- ret = *fi.data;
- }
-
- free(r);
- return ret;
-}
-
-static cairo_surface_t *
-create_xcb_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
- XCBSCREEN *root;
- xcb_target_closure_t *xtc;
- cairo_surface_t *surface;
- XCBConnection *c;
- XCBRenderPICTFORMINFO render_format;
- cairo_format_t format;
-
- *closure = xtc = xmalloc (sizeof (xcb_target_closure_t));
-
- if (width == 0)
- width = 1;
- if (height == 0)
- height = 1;
-
- xtc->c = c = XCBConnect(NULL,NULL);
- if (c == NULL) {
- cairo_test_log ("Failed to connect to X server through XCB\n");
- return NULL;
- }
-
- root = XCBSetupRootsIter(XCBGetSetup(c)).data;
-
- xtc->drawable.pixmap = XCBPIXMAPNew (c);
- {
- XCBDRAWABLE root_drawable;
- root_drawable.window = root->root;
- XCBCreatePixmap (c, 32, xtc->drawable.pixmap, root_drawable,
- width, height);
- }
-
- switch (content) {
- case CAIRO_CONTENT_COLOR:
- format = CAIRO_FORMAT_RGB24;
- break;
- case CAIRO_CONTENT_COLOR_ALPHA:
- format = CAIRO_FORMAT_ARGB32;
- break;
- default:
- cairo_test_log ("Invalid content for XCB test: %d\n", content);
- return NULL;
- }
-
- render_format = _format_from_cairo (c, format);
- if (render_format.id.xid == 0)
- return NULL;
- surface = cairo_xcb_surface_create_with_xrender_format (c, xtc->drawable, root,
- &render_format,
- width, height);
-
- return surface;
-}
-
-static void
-cleanup_xcb (void *closure)
-{
- xcb_target_closure_t *xtc = closure;
-
- XCBFreePixmap (xtc->c, xtc->drawable.pixmap);
- XCBDisconnect (xtc->c);
- free (xtc);
-}
-#endif
-
-#if CAIRO_HAS_XLIB_SURFACE
-#include "cairo-xlib-xrender.h"
-typedef struct _xlib_target_closure
-{
- Display *dpy;
- Pixmap pixmap;
-} xlib_target_closure_t;
-
-static cairo_surface_t *
-create_xlib_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
- xlib_target_closure_t *xtc;
- cairo_surface_t *surface;
- Display *dpy;
- XRenderPictFormat *xrender_format;
-
- *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
-
- if (width == 0)
- width = 1;
- if (height == 0)
- height = 1;
-
- xtc->dpy = dpy = XOpenDisplay (NULL);
- if (xtc->dpy == NULL) {
- cairo_test_log ("Failed to open display: %s\n", XDisplayName(0));
- return NULL;
- }
-
- XSynchronize (xtc->dpy, 1);
-
- /* XXX: Currently we don't do any xlib testing when the X server
- * doesn't have the Render extension. We could do better here,
- * (perhaps by converting the tests from ARGB32 to RGB24). One
- * step better would be to always test the non-Render fallbacks
- * for each test even if the server does have the Render
- * extension. That would probably be through another
- * cairo_test_target which would use an extended version of
- * cairo_test_xlib_disable_render. */
- switch (content) {
- case CAIRO_CONTENT_COLOR_ALPHA:
- xrender_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
- break;
- case CAIRO_CONTENT_COLOR:
- xrender_format = XRenderFindStandardFormat (dpy, PictStandardRGB24);
- break;
- case CAIRO_CONTENT_ALPHA:
- default:
- cairo_test_log ("Invalid content for xlib test: %d\n", content);
- return NULL;
- }
- if (xrender_format == NULL) {
- cairo_test_log ("X server does not have the Render extension.\n");
- return NULL;
- }
-
- xtc->pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
- width, height, xrender_format->depth);
-
- surface = cairo_xlib_surface_create_with_xrender_format (dpy, xtc->pixmap,
- DefaultScreenOfDisplay (dpy),
- xrender_format,
- width, height);
- return surface;
-}
-
-static void
-cleanup_xlib (void *closure)
-{
- xlib_target_closure_t *xtc = closure;
-
- XFreePixmap (xtc->dpy, xtc->pixmap);
- XCloseDisplay (xtc->dpy);
- free (xtc);
-}
-#endif
-
-#if CAIRO_HAS_BEOS_SURFACE
-/* BeOS test functions are external as they need to be C++ */
-#include "cairo-test-beos.h"
-#endif
-
-#if CAIRO_HAS_DIRECTFB_SURFACE
-#include "cairo-test-directfb.h"
-#endif
-
-#if CAIRO_HAS_PS_SURFACE
-#include "cairo-ps.h"
-
-cairo_user_data_key_t ps_closure_key;
-
-typedef struct _ps_target_closure
-{
- char *filename;
- int width;
- int height;
- cairo_surface_t *target;
-} ps_target_closure_t;
-
-static cairo_surface_t *
-create_ps_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
- ps_target_closure_t *ptc;
- cairo_surface_t *surface;
- int i;
-
- for (i = 0; vector_ignored_tests[i] != NULL; i++)
- if (strcmp (test->name, vector_ignored_tests[i]) == 0)
- return NULL;
-
- /* Sanitize back to a real cairo_content_t value. */
- if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
- content = CAIRO_CONTENT_COLOR_ALPHA;
-
- *closure = ptc = xmalloc (sizeof (ps_target_closure_t));
-
- xasprintf (&ptc->filename, "%s-ps-%s-out.ps",
- test->name, _cairo_test_content_name (content));
-
- ptc->width = width;
- ptc->height = height;
-
- surface = cairo_ps_surface_create (ptc->filename, width, height);
- if (cairo_surface_status (surface)) {
- free (ptc->filename);
- free (ptc);
- return NULL;
- }
- cairo_surface_set_fallback_resolution (surface, 72., 72.);
-
- if (content == CAIRO_CONTENT_COLOR) {
- ptc->target = surface;
- surface = cairo_surface_create_similar (ptc->target,
- CAIRO_CONTENT_COLOR,
- width, height);
- } else {
- ptc->target = NULL;
- }
-
- cairo_surface_set_user_data (surface, &ps_closure_key, ptc, NULL);
-
- return surface;
-}
-
-static cairo_status_t
-ps_surface_write_to_png (cairo_surface_t *surface, const char *filename)
-{
- ps_target_closure_t *ptc = cairo_surface_get_user_data (surface, &ps_closure_key);
- char command[4096];
-
- /* Both surface and ptc->target were originally created at the
- * same dimensions. We want a 1:1 copy here, so we first clear any
- * device offset on surface.
- *
- * In a more realistic use case of device offsets, the target of
- * this copying would be of a different size than the source, and
- * the offset would be desirable during the copy operation. */
- cairo_surface_set_device_offset (surface, 0, 0);
-
- if (ptc->target) {
- cairo_t *cr;
- cr = cairo_create (ptc->target);
- cairo_set_source_surface (cr, surface, 0, 0);
- cairo_paint (cr);
- cairo_show_page (cr);
- cairo_destroy (cr);
-
- cairo_surface_finish (surface);
- surface = ptc->target;
- }
-
- cairo_surface_finish (surface);
- sprintf (command, "gs -q -r72 -g%dx%d -dSAFER -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=%s %s",
- ptc->width, ptc->height, filename, ptc->filename);
- if (system (command) == 0)
- return CAIRO_STATUS_SUCCESS;
- return CAIRO_STATUS_WRITE_ERROR;
-}
-
-static void
-cleanup_ps (void *closure)
-{
- ps_target_closure_t *ptc = closure;
- if (ptc->target)
- cairo_surface_destroy (ptc->target);
- free (ptc->filename);
- free (ptc);
-}
-#endif /* CAIRO_HAS_PS_SURFACE */
-
-#if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
-#include "cairo-pdf.h"
-
-cairo_user_data_key_t pdf_closure_key;
-
-typedef struct _pdf_target_closure
-{
- char *filename;
- int width;
- int height;
- cairo_surface_t *target;
-} pdf_target_closure_t;
-
-static cairo_surface_t *
-create_pdf_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
- pdf_target_closure_t *ptc;
- cairo_surface_t *surface;
- int i;
-
- for (i = 0; vector_ignored_tests[i] != NULL; i++)
- if (strcmp (test->name, vector_ignored_tests[i]) == 0)
- return NULL;
-
- /* Sanitize back to a real cairo_content_t value. */
- if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
- content = CAIRO_CONTENT_COLOR_ALPHA;
-
- *closure = ptc = xmalloc (sizeof (pdf_target_closure_t));
-
- ptc->width = width;
- ptc->height = height;
-
- xasprintf (&ptc->filename, "%s-pdf-%s-out.pdf",
- test->name, _cairo_test_content_name (content));
-
- surface = cairo_pdf_surface_create (ptc->filename, width, height);
- if (cairo_surface_status (surface)) {
- free (ptc->filename);
- free (ptc);
- return NULL;
- }
- cairo_surface_set_fallback_resolution (surface, 72., 72.);
-
- if (content == CAIRO_CONTENT_COLOR) {
- ptc->target = surface;
- surface = cairo_surface_create_similar (ptc->target,
- CAIRO_CONTENT_COLOR,
- width, height);
- } else {
- ptc->target = NULL;
- }
-
- cairo_surface_set_user_data (surface, &pdf_closure_key, ptc, NULL);
-
- return surface;
-}
-
-static cairo_status_t
-pdf_surface_write_to_png (cairo_surface_t *surface, const char *filename)
-{
- pdf_target_closure_t *ptc = cairo_surface_get_user_data (surface, &pdf_closure_key);
- char command[4096];
-
- /* Both surface and ptc->target were originally created at the
- * same dimensions. We want a 1:1 copy here, so we first clear any
- * device offset on surface.
- *
- * In a more realistic use case of device offsets, the target of
- * this copying would be of a different size than the source, and
- * the offset would be desirable during the copy operation. */
- cairo_surface_set_device_offset (surface, 0, 0);
-
- if (ptc->target) {
- cairo_t *cr;
- cr = cairo_create (ptc->target);
- cairo_set_source_surface (cr, surface, 0, 0);
- cairo_paint (cr);
- cairo_show_page (cr);
- cairo_destroy (cr);
-
- cairo_surface_finish (surface);
- surface = ptc->target;
- }
-
- cairo_surface_finish (surface);
- sprintf (command, "./pdf2png %s %s 1",
- ptc->filename, filename);
-
- if (system (command) != 0)
- return CAIRO_STATUS_WRITE_ERROR;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-cleanup_pdf (void *closure)
-{
- pdf_target_closure_t *ptc = closure;
- if (ptc->target)
- cairo_surface_destroy (ptc->target);
- free (ptc->filename);
- free (ptc);
-}
-#endif /* CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE */
-
-#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
-#include "cairo-svg.h"
-
-cairo_user_data_key_t svg_closure_key;
-
-typedef struct _svg_target_closure
-{
- char *filename;
- int width, height;
- cairo_surface_t *target;
-} svg_target_closure_t;
-
-static cairo_surface_t *
-create_svg_surface (cairo_test_t *test,
- cairo_content_t content,
- void **closure)
-{
- int width = test->width;
- int height = test->height;
- int i;
- svg_target_closure_t *ptc;
- cairo_surface_t *surface;
-
- for (i = 0; vector_ignored_tests[i] != NULL; i++)
- if (strcmp (test->name, vector_ignored_tests[i]) == 0)
- return NULL;
-
- *closure = ptc = xmalloc (sizeof (svg_target_closure_t));
-
- ptc->width = width;
- ptc->height = height;
-
- xasprintf (&ptc->filename, "%s-svg-%s-out.svg",
- test->name, _cairo_test_content_name (content));
-
- surface = cairo_svg_surface_create (ptc->filename, width, height);
- if (cairo_surface_status (surface)) {
- free (ptc->filename);
- free (ptc);
- return NULL;
- }
- cairo_surface_set_fallback_resolution (surface, 72., 72.);
-
- if (content == CAIRO_CONTENT_COLOR) {
- ptc->target = surface;
- surface = cairo_surface_create_similar (ptc->target,
- CAIRO_CONTENT_COLOR,
- width, height);
- } else {
- ptc->target = NULL;
- }
-
- cairo_surface_set_user_data (surface, &svg_closure_key, ptc, NULL);
-
- return surface;
-}
-
-static cairo_status_t
-svg_surface_write_to_png (cairo_surface_t *surface, const char *filename)
-{
- svg_target_closure_t *ptc = cairo_surface_get_user_data (surface, &svg_closure_key);
- char command[4096];
-
- /* Both surface and ptc->target were originally created at the
- * same dimensions. We want a 1:1 copy here, so we first clear any
- * device offset on surface.
- *
- * In a more realistic use case of device offsets, the target of
- * this copying would be of a different size than the source, and
- * the offset would be desirable during the copy operation. */
- cairo_surface_set_device_offset (surface, 0, 0);
-
- if (ptc->target) {
- cairo_t *cr;
- cr = cairo_create (ptc->target);
- cairo_set_source_surface (cr, surface, 0, 0);
- cairo_paint (cr);
- cairo_show_page (cr);
- cairo_destroy (cr);
-
- cairo_surface_finish (surface);
- surface = ptc->target;
- }
-
- cairo_surface_finish (surface);
- sprintf (command, "./svg2png %s %s",
- ptc->filename, filename);
-
- if (system (command) != 0)
- return CAIRO_STATUS_WRITE_ERROR;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-cleanup_svg (void *closure)
-{
- svg_target_closure_t *ptc = closure;
- if (ptc->target)
- cairo_surface_destroy (ptc->target);
- free (ptc->filename);
- free (ptc);
-}
-#endif /* CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE */
-
static char *
cairo_ref_name_for_test_target_format (const char *test_name,
const char *target_name,
@@ -1572,7 +233,11 @@ cairo_test_for_target (cairo_test_t *t
test->height += dev_offset;
}
- surface = (target->create_target_surface) (test, target->content, &target->closure);
+ surface = (target->create_target_surface) (test->name,
+ target->content,
+ test->width,
+ test->height,
+ &target->closure);
if (test->width && test->height) {
test->width -= dev_offset;
@@ -1722,135 +387,6 @@ cairo_test_expecting (cairo_test_t *test
#endif
volatile cairo_test_status_t status, ret;
cairo_test_target_t ** volatile targets_to_test;
- cairo_test_target_t targets[] =
- {
- { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA,
- create_image_surface, cairo_surface_write_to_png, NULL},
- { "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
- create_image_surface, cairo_surface_write_to_png, NULL},
-#ifdef CAIRO_HAS_TEST_SURFACES
- { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
- CAIRO_CONTENT_COLOR_ALPHA,
- create_test_fallback_surface, cairo_surface_write_to_png, NULL },
- { "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
- CAIRO_CONTENT_COLOR,
- create_test_fallback_surface, cairo_surface_write_to_png, NULL },
- { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
- CAIRO_CONTENT_COLOR_ALPHA,
- create_test_meta_surface, cairo_surface_write_to_png, NULL },
- { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
- CAIRO_CONTENT_COLOR,
- create_test_meta_surface, cairo_surface_write_to_png, NULL },
- { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
- CAIRO_CONTENT_COLOR_ALPHA,
- create_test_paginated_surface,
- test_paginated_write_to_png,
- cleanup_test_paginated },
- { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
- CAIRO_CONTENT_COLOR,
- create_test_paginated_surface,
- test_paginated_write_to_png,
- cleanup_test_paginated },
-#endif
-#ifdef CAIRO_HAS_GLITZ_SURFACE
-#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
- { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA,
- create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
- cleanup_cairo_glitz_glx },
- { "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
- create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
- cleanup_cairo_glitz_glx },
-#endif
-#if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
- { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
- create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
- cleanup_cairo_glitz_agl },
- { "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
- create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
- cleanup_cairo_glitz_agl },
-#endif
-#if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
- { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
- create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
- cleanup_cairo_glitz_wgl },
- { "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
- create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
- cleanup_cairo_glitz_wgl },
-#endif
-#endif /* CAIRO_HAS_GLITZ_SURFACE */
-#if 0 && CAIRO_HAS_QUARTZ_SURFACE
- { "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR,
- create_quartz_surface, cairo_surface_write_to_png,
- cleanup_quartz },
-#endif
-#if CAIRO_HAS_WIN32_SURFACE
- { "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR,
- create_win32_surface, cairo_surface_write_to_png, cleanup_win32 },
-#endif
-#if CAIRO_HAS_XCB_SURFACE
- { "xcb", CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA,
- create_xcb_surface, cairo_surface_write_to_png, cleanup_xcb},
-#endif
-#if CAIRO_HAS_XLIB_SURFACE
- { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA,
- create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
- { "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR,
- create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
-#endif
-#if CAIRO_HAS_PS_SURFACE
- { "ps", CAIRO_SURFACE_TYPE_PS,
- CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
- create_ps_surface, ps_surface_write_to_png, cleanup_ps },
-
- /* XXX: We expect type image here only due to a limitation in
- * the current PS/meta-surface code. A PS surface is
- * "naturally" COLOR_ALPHA, so the COLOR-only variant goes
- * through create_similar in create_ps_surface which results
- * in the similar surface being used as a source. We do not yet
- * have source support for PS/meta-surfaces, so the
- * create_similar path for all paginated surfaces currently
- * returns an image surface.*/
- { "ps", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
- create_ps_surface, ps_surface_write_to_png, cleanup_ps },
-#endif
-#if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
- { "pdf", CAIRO_SURFACE_TYPE_PDF,
- CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
- create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
-
- /* XXX: We expect type image here only due to a limitation in
- * the current PDF/meta-surface code. A PDF surface is
- * "naturally" COLOR_ALPHA, so the COLOR-only variant goes
- * through create_similar in create_pdf_surface which results
- * in the similar surface being used as a source. We do not yet
- * have source support for PDF/meta-surfaces, so the
- * create_similar path for all paginated surfaces currently
- * returns an image surface.*/
- { "pdf", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
- create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
-#endif
-#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
- { "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA,
- create_svg_surface, svg_surface_write_to_png, cleanup_svg },
- { "svg", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR,
- create_svg_surface, svg_surface_write_to_png, cleanup_svg },
-#endif
-#if CAIRO_HAS_BEOS_SURFACE
- { "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
- create_beos_surface, cairo_surface_write_to_png, cleanup_beos},
- { "beos-bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
- create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
- { "beos-bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA,
- create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
-#endif
-
-#if CAIRO_HAS_DIRECTFB_SURFACE
- { "directfb", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR,
- create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb},
- { "directfb-bitmap", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA,
- create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb},
-#endif
- };
#ifdef HAVE_UNISTD_H
if (isatty (2)) {
@@ -1871,7 +407,6 @@ cairo_test_expecting (cairo_test_t *test
if (expectation == CAIRO_TEST_FAILURE)
printf ("Expecting failure\n");
-
if ((tname = getenv ("CAIRO_TEST_TARGET")) != NULL && *tname) {
limited_targets = TRUE;
@@ -1885,7 +420,7 @@ cairo_test_expecting (cairo_test_t *test
if (!end)
end = tname + strlen (tname);
- for (i = 0; i < sizeof(targets)/sizeof(targets[0]); i++) {
+ for (i = 0; targets[i].name != NULL; i++) {
if (0 == strncmp (targets[i].name, tname, end - tname) &&
!isalnum (targets[i].name[end - tname])) {
/* realloc isn't exactly the best thing here, but meh. */
@@ -1905,10 +440,13 @@ cairo_test_expecting (cairo_test_t *test
tname = end;
}
} else {
- num_targets = sizeof(targets)/sizeof(targets[0]);
+ num_targets = 0;
+ for (i = 0; targets[i].name != NULL; i++)
+ num_targets++;
targets_to_test = malloc (sizeof(cairo_test_target_t*) * num_targets);
- for (i = 0; i < num_targets; i++)
+ for (i = 0; i < num_targets; i++) {
targets_to_test[i] = &targets[i];
+ }
}
/* The intended logic here is that we return overall SUCCESS
diff --git a/boilerplate/cairo-test.h b/boilerplate/cairo-test.h
index 8402d13..75eadb4 100644
--- a/boilerplate/cairo-test.h
+++ b/boilerplate/cairo-test.h
@@ -34,6 +34,9 @@
#include <math.h>
#include <cairo.h>
+#define CAIRO_BOILERPLATE_LOG(...) cairo_test_log (__VA_ARGS__)
+#include "cairo-boilerplate.h"
+
CAIRO_BEGIN_DECLS
#if HAVE_STDINT_H
@@ -58,13 +61,6 @@ typedef unsigned __int64 uint64_t;
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, \etc.)
#endif
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
-#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \
- __attribute__((__format__(__printf__, fmt_index, va_index)))
-#else
-#define CAIRO_PRINTF_FORMAT(fmt_index, va_index)
-#endif
-
typedef enum cairo_test_status {
CAIRO_TEST_SUCCESS = 0,
CAIRO_TEST_FAILURE,
@@ -135,9 +131,6 @@ cairo_test_create_pattern_from_png (cons
cairo_status_t
cairo_test_paint_checkered (cairo_t *cr);
-void
-xasprintf (char **strp, const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3);
-
CAIRO_END_DECLS
#endif
diff-tree a0ca4369ff71ca76e593ea8db3e728218814814d (from 5ef4c991f6ad00a37fc0645a38ba2cb9f832d9f1)
Author: Carl Worth <cworth at cworth.org>
Date: Wed Aug 30 22:33:53 2006 -0700
Add boilerplate/README explaining its purpose
diff --git a/boilerplate/README b/boilerplate/README
new file mode 100644
index 0000000..2a27c41
--- /dev/null
+++ b/boilerplate/README
@@ -0,0 +1,14 @@
+This directory provides code that is common to both of cairo's tests
+suites:
+
+ * The test suite for correctness in test/
+ * The test suite for performance in perf/
+
+We call it boilerplate as it consists primarily of the boilerplate
+code necessary for initializing a backend in order to create a surface
+for that backend.
+
+The code here just might be useful for someone looking to get started
+writing cairo code to use a particular backend, (but there are no
+promises that the boilerplate code found here for any particular
+backend is exemplary).
More information about the cairo-commit
mailing list