Beispiel #1
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    size_t i, j, k, x, y;

    for (k = 0; k < ARRAY_SIZE (clip_funcs); k++) {
	for (j = 0; j < ARRAY_SIZE (draw_funcs); j++) {
	    for (i = 0; i < ARRAY_SIZE (pattern_funcs); i++) {
		x = i * (WIDTH + PAD) + PAD;
		y = (ARRAY_SIZE (draw_funcs) * k + j) * (HEIGHT + PAD) + PAD;

		cairo_save (cr);

		cairo_move_to (cr, x, y);
		clip_funcs[k] (cr, x, y);
		pattern_funcs[i] (cr, x, y);
		draw_funcs[j] (cr, x, y);
		if (cairo_status (cr))
		    cairo_test_log ("%d %d HERE!\n", (int)i, (int)j);

		cairo_restore (cr);
	    }
	}
    }

    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
	cairo_test_log ("%d %d .HERE!\n", (int)i, (int)j);

    return CAIRO_TEST_SUCCESS;
}
Beispiel #2
0
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    int x,y;
    int width = 10;
    int height = 10;
    cairo_surface_t *surf;
    cairo_t *cr;
    int false_positive_count = 0;
    cairo_status_t status;
    cairo_test_status_t ret;

    surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
    cr = cairo_create (surf);
    cairo_surface_destroy (surf);

    /* Empty horizontal trapezoid. */
    cairo_move_to (cr, 0, height/3);
    cairo_line_to (cr, width, height/3);
    cairo_close_path (cr);

    /* Empty non-horizontal trapezoid #1. */
    cairo_move_to (cr, 0, 0);
    cairo_line_to (cr, width, height/2);
    cairo_close_path (cr);

    /* Empty non-horizontal trapezoid #2 intersecting #1. */
    cairo_move_to (cr, 0, height/2);
    cairo_line_to (cr, width, 0);
    cairo_close_path (cr);

    status = cairo_status (cr);

    /* Point sample the tessellated path. */
    for (y = 0; y < height; y++) {
	for (x = 0; x < width; x++) {
	    if (cairo_in_fill (cr, x, y)) {
		false_positive_count++;
	    }
	}
    }
    cairo_destroy (cr);

    /* Check that everything went well. */
    ret = CAIRO_TEST_SUCCESS;
    if (CAIRO_STATUS_SUCCESS != status) {
	cairo_test_log (ctx, "Failed to create a test surface and path: %s\n",
			cairo_status_to_string (status));
	ret = CAIRO_TEST_XFAILURE;
    }

    if (0 != false_positive_count) {
	cairo_test_log (ctx, "Point sampling found %d false positives "
			"from cairo_in_fill()\n",
			false_positive_count);
	ret = CAIRO_TEST_XFAILURE;
    }

    return ret;
}
Beispiel #3
0
static cairo_bool_t
check_count (const cairo_test_context_t *ctx,
	     const char *message, cairo_bool_t uses_clip_rects,
             cairo_rectangle_list_t *list, int expected)
{
    if (!uses_clip_rects) {
        if (expected == 0 && list->num_rectangles == 0)
            return 1;
	if (list->num_rectangles == expected)
	    return 1;
	if (list->status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
	    return 1;
        cairo_test_log (ctx, "Error: %s; cairo_copy_clip_rectangle_list unexpectedly got %d rectangles\n",
                        message, list->num_rectangles);
        return 0;
    }

    if (list->status != CAIRO_STATUS_SUCCESS) {
        cairo_test_log (ctx, "Error: %s; cairo_copy_clip_rectangle_list failed with \"%s\"\n",
                        message, cairo_status_to_string(list->status));
        return 0;
    }

    if (list->num_rectangles == expected)
        return 1;
    cairo_test_log (ctx, "Error: %s; expected %d rectangles, got %d\n", message,
                    expected, list->num_rectangles);
    return 0;
}
Beispiel #4
0
int
main (void)
{
    cairo_test_context_t ctx;
    cairo_surface_t *surface;
    cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial;
    cairo_test_status_t result = CAIRO_TEST_SUCCESS;

    cairo_test_init (&ctx, "pattern-get-type");
    cairo_test_log (&ctx, "Creating patterns of all types\n");

    solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2);
    solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6);
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
					  1, 1);
    surface_pattern = cairo_pattern_create_for_surface (surface);
    linear = cairo_pattern_create_linear (0.0, 0.0, 10.0, 10.0);
    radial = cairo_pattern_create_radial (10.0, 10.0, 0.1,
					  10.0, 10.0, 1.0);

    cairo_test_log (&ctx, "Verifying return values of cairo_pattern_get_type\n");

    if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID)
	result = CAIRO_TEST_FAILURE;

    if (cairo_pattern_get_type (solid_rgba) != CAIRO_PATTERN_TYPE_SOLID)
	result = CAIRO_TEST_FAILURE;

    if (cairo_pattern_get_type (surface_pattern) != CAIRO_PATTERN_TYPE_SURFACE)
	result = CAIRO_TEST_FAILURE;

    if (cairo_pattern_get_type (linear) != CAIRO_PATTERN_TYPE_LINEAR)
	result = CAIRO_TEST_FAILURE;

    if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL)
	result = CAIRO_TEST_FAILURE;

    cairo_test_log (&ctx, "Cleaning up\n");

    cairo_pattern_destroy (solid_rgb);
    cairo_pattern_destroy (solid_rgba);
    cairo_pattern_destroy (surface_pattern);
    cairo_surface_destroy (surface);
    cairo_pattern_destroy (linear);
    cairo_pattern_destroy (radial);

    cairo_test_fini (&ctx);

    return result;
}
Beispiel #5
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    char *filename;
    cairo_surface_t *surface;

    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.ref.png");

    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	cairo_test_status_t result;

	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}

	free (filename);
	return result;
    }

    cairo_set_source_surface (cr, surface, 0, 0);
    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
    cairo_paint (cr);

    cairo_surface_destroy (surface);

    free (filename);
    return CAIRO_TEST_SUCCESS;
}
Beispiel #6
0
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    cairo_t *cr;
    const char *filename = "svg-clip.out.svg";
    cairo_surface_t *surface;

    if (! cairo_test_is_target_enabled (ctx, "svg11") &&
	! cairo_test_is_target_enabled (ctx, "svg12"))
    {
	return CAIRO_TEST_UNTESTED;
    }

    surface = cairo_svg_surface_create (filename,
					WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
    if (cairo_surface_status (surface)) {
	cairo_test_log (ctx,
			"Failed to create svg surface for file %s: %s\n",
			filename, cairo_status_to_string (cairo_surface_status (surface)));
	return CAIRO_TEST_FAILURE;
    }

    cr = cairo_create (surface);

    test_clip (cr, WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
    cairo_show_page (cr);

    cairo_destroy (cr);
    cairo_surface_destroy (surface);

    printf ("svg-clip: Please check %s to make sure it looks happy.\n",
	    filename);
    return CAIRO_TEST_SUCCESS;
}
Beispiel #7
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    size_t i, j, x, y;
    cairo_pattern_t *pattern;

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);

    for (j = 0; j < ARRAY_SIZE (draw_funcs); j++) {
	for (i = 0; i < ARRAY_SIZE (operators); i++) {
	    x = i * (WIDTH + PAD) + PAD;
	    y = j * (HEIGHT + PAD) + PAD;

	    cairo_save (cr);

	    pattern = cairo_pattern_create_linear (x + WIDTH, y,
						   x,         y + HEIGHT);
	    cairo_pattern_add_color_stop_rgba (pattern, 0.2,
					       0.0, 0.0, 1.0, 1.0); /* Solid blue */
	    cairo_pattern_add_color_stop_rgba (pattern, 0.8,
					       0.0, 0.0, 1.0, 0.0); /* Transparent blue */
	    cairo_set_source (cr, pattern);
	    cairo_pattern_destroy (pattern);

	    cairo_rectangle (cr, x, y, WIDTH, HEIGHT);
	    cairo_fill_preserve (cr);
	    cairo_clip (cr);

	    cairo_set_operator (cr, operators[i]);
	    cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);

	    draw_funcs[j] (cr, x, y);
	    if (cairo_status (cr))
		cairo_test_log (ctx, "%d %d HERE!\n", (int)i, (int)j);

	    cairo_restore (cr);
	}
    }

    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
	cairo_test_log (ctx, "%d %d .HERE!\n", (int)i, (int)j);

    return CAIRO_TEST_SUCCESS;
}
static cairo_bool_t
check_count (const cairo_test_context_t *ctx,
	     const char *message,
             cairo_rectangle_list_t *list, int expected)
{
    if (list->status != CAIRO_STATUS_SUCCESS) {
        cairo_test_log (ctx, "Error: %s; cairo_copy_clip_rectangle_list failed with \"%s\"\n",
                        message, cairo_status_to_string(list->status));
        return 0;
    }

    if (list->num_rectangles == expected)
        return 1;
    cairo_test_log (ctx, "Error: %s; expected %d rectangles, got %d\n", message,
                    expected, list->num_rectangles);
    return 0;
}
Beispiel #9
0
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 cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    cairo_surface_t *surface;
    cairo_t *cr;
    cairo_status_t status;
    size_t i;
    char *filename;
    const char *path = cairo_test_mkdir (CAIRO_TEST_OUTPUT_DIR) ? CAIRO_TEST_OUTPUT_DIR : ".";

    if (! cairo_test_is_target_enabled (ctx, "pdf"))
	return CAIRO_TEST_UNTESTED;

    xasprintf (&filename, "%s/%s.pdf", path, BASENAME);

    /* The initial size passed here is the default size that will be
     * inheritable by each page. That is, any page for which this
     * initial size applies will not have its own /MediaBox entry in
     * its dictionary. */
    surface = cairo_pdf_surface_create (filename,
					INCHES_TO_POINTS(8.5),
					INCHES_TO_POINTS(11));

    cr = cairo_create (surface);

    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, TEXT_SIZE);

    for (i = 0; i < ARRAY_LENGTH (pages); i++) {
	cairo_pdf_surface_set_size (surface,
				   pages[i].width_in_points,
				   pages[i].height_in_points);

	cairo_move_to (cr, TEXT_SIZE, TEXT_SIZE);
	cairo_show_text (cr, pages[i].page_size);
	cairo_show_text (cr, " - ");
	cairo_show_text (cr, pages[i].orientation);
	cairo_show_page (cr);
    }

    status = cairo_status (cr);

    cairo_destroy (cr);
    cairo_surface_destroy (surface);
    free (filename);

    if (status) {
	cairo_test_log (ctx, "Failed to create pdf surface for file %s: %s\n",
			filename, cairo_status_to_string (status));
	return CAIRO_TEST_FAILURE;
    }

    printf ("pdf-features: Please check %s to ensure it looks/prints correctly.\n", filename);
    return CAIRO_TEST_SUCCESS;
}
Beispiel #11
0
static void
print_surface (const cairo_test_context_t *ctx, cairo_surface_t *surface)
{
    cairo_test_log (ctx,
		    "%s (%dx%d)\n",
		    format_to_string (cairo_image_surface_get_format (surface)),
		    cairo_image_surface_get_width (surface),
		    cairo_image_surface_get_height (surface));
}
Beispiel #12
0
static void *
xcalloc (const cairo_test_context_t *ctx, size_t a, size_t b)
{
    void *ptr = calloc (a, b);
    if (ptr == NULL) {
        cairo_test_log (ctx, "xlib-surface: unable to allocate memory, skipping\n");
        abort ();
    }
    return ptr;
}
Beispiel #13
0
static cairo_bool_t
check_unrepresentable (const cairo_test_context_t *ctx, const char *message, cairo_rectangle_list_t *list)
{
    if (list->status != CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) {
        cairo_test_log (ctx, "Error: %s; cairo_copy_clip_rectangle_list got unexpected result \"%s\"\n"
                        " (we expected CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)",
                        message, cairo_status_to_string(list->status));
        return 0;
    }
    return 1;
}
Beispiel #14
0
static int
double_buf_equal (const cairo_test_context_t *ctx, double *a, double *b, int nc)
{
    int i;
    for (i = 0; i < nc; i++) {
        if (!CAIRO_TEST_DOUBLE_EQUALS(a[i],b[i])) {
            cairo_test_log (ctx, "Error: doubles not equal: %g, %g\n",
                            a[i], b[i]);
            return 0;
        }
    }
    return 1;
}
Beispiel #15
0
static cairo_bool_t
check_clip_extents (const char *message, cairo_t *cr,
                    double x, double y, double width, double height)
{
    double ext_x1, ext_y1, ext_x2, ext_y2;
    cairo_clip_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
    if (ext_x1 == x && ext_y1 == y && ext_x2 == x + width && ext_y2 == y + height)
        return 1;
    cairo_test_log ("Error: %s; clip extents %f,%f,%f,%f should be %f,%f,%f,%f\n",
                    message, ext_x1, ext_y1, ext_x2 - ext_x1, ext_y2 - ext_y1,
                    x, y, width, height);
    return 0;
}
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    cairo_surface_t *surface;
    cairo_test_status_t test_status;
    cairo_status_t status_before, status_after;
    unsigned int i;

    /* Test an error surface */
    for (i = 0; i < ARRAY_LENGTH (tests); i++) {
        surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, INT_MAX, INT_MAX);
        status_before = cairo_surface_status (surface);
        assert (status_before);

        test_status = tests[i].func (surface);

        status_after = cairo_surface_status (surface);
        cairo_surface_destroy (surface);

        if (test_status != CAIRO_TEST_SUCCESS) {
            cairo_test_log (ctx,
                            "Failed test %s with %d\n",
                            tests[i].name, (int) test_status);
            return test_status;
        }

        if (status_before != status_after) {
            cairo_test_log (ctx,
                            "Failed test %s: Modified surface status from %u (%s) to %u (%s)\n",
                            tests[i].name,
                            status_before, cairo_status_to_string (status_before),
                            status_after, cairo_status_to_string (status_after));
            return CAIRO_TEST_ERROR;
        }
    }

    return CAIRO_TEST_SUCCESS;
}
Beispiel #17
0
static cairo_bool_t
check_rectangles_contain (const cairo_test_context_t *ctx,
			  const char *message,
                          cairo_rectangle_list_t *list,
                          double x, double y, double width, double height)
{
    int i;

    for (i = 0; i < list->num_rectangles; ++i) {
        if (list->rectangles[i].x == x && list->rectangles[i].y == y &&
            list->rectangles[i].width == width && list->rectangles[i].height == height)
            return 1;
    }
    cairo_test_log (ctx, "Error: %s; rectangle list does not contain rectangle %f,%f,%f,%f\n",
                    message, x, y, width, height);
    return 0;
}
Beispiel #18
0
int
main (void)
{
    cairo_test_context_t ctx;
    cairo_t *cr;
    const char *filename = "svg-surface.svg";
    cairo_surface_t *surface;

    cairo_test_init (&ctx, "svg-surface");
    if (! (cairo_test_is_target_enabled (&ctx, "svg11") ||
	   cairo_test_is_target_enabled (&ctx, "svg12")))
    {
	cairo_test_fini (&ctx);
	return CAIRO_TEST_UNTESTED;
    }

    surface = cairo_svg_surface_create (filename,
					WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
    if (cairo_surface_status (surface)) {
	cairo_test_log (&ctx,
			"Failed to create svg surface for file %s: %s\n",
			filename,
			cairo_status_to_string (cairo_surface_status (surface)));
	cairo_test_fini (&ctx);
	return CAIRO_TEST_FAILURE;
    }

    cr = cairo_create (surface);

    draw (cr, WIDTH_IN_POINTS, HEIGHT_IN_POINTS);

    cairo_show_page (cr);

    cairo_destroy (cr);
    cairo_surface_destroy (surface);

    printf ("svg-surface: Please check svg-surface.svg to make sure it looks happy.\n");

    cairo_test_fini (&ctx);

    return CAIRO_TEST_SUCCESS;
}
Beispiel #19
0
static cairo_test_status_t
check_font_extents (const cairo_test_context_t *ctx, cairo_t *cr, const char *comment)
{
    cairo_font_extents_t font_extents, ref_font_extents = {11, 2, 13, 6, 0};
    cairo_status_t status;

    memset (&font_extents, 0xff, sizeof (cairo_font_extents_t));
    cairo_font_extents (cr, &font_extents);

    status = cairo_status (cr);
    if (status)
	return cairo_test_status_from_status (ctx, status);

    if (! font_extents_equal (&font_extents, &ref_font_extents)) {
	cairo_test_log (ctx, "Error: %s: cairo_font_extents(); extents (%g, %g, %g, %g, %g)\n",
			comment,
		        font_extents.ascent, font_extents.descent,
			font_extents.height,
			font_extents.max_x_advance, font_extents.max_y_advance);
	return CAIRO_TEST_FAILURE;
    }

    return CAIRO_TEST_SUCCESS;
}
Beispiel #20
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    FcPattern *pattern;
    cairo_font_face_t *font_face;
    cairo_font_extents_t font_extents;
    cairo_font_options_t *font_options;
    cairo_status_t status;
    char *filename;
    int face_count;
    struct stat stat_buf;

    xasprintf (&filename, "%s/%s", ctx->srcdir, FONT);

    if (stat (filename, &stat_buf) || ! S_ISREG (stat_buf.st_mode)) {
	cairo_test_log (ctx, "Error finding font: %s: file not found?\n", filename);
	return CAIRO_TEST_FAILURE;
    }

    pattern = FcFreeTypeQuery ((unsigned char *)filename, 0, NULL, &face_count);
    free (filename);
    if (! pattern) {
	cairo_test_log (ctx, "FcFreeTypeQuery failed.\n");
	return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY);
    }

    font_face = cairo_ft_font_face_create_for_pattern (pattern);
    FcPatternDestroy (pattern);

    status = cairo_font_face_status (font_face);
    if (status) {
	cairo_test_log (ctx, "Error creating font face for %s: %s\n",
			filename,
			cairo_status_to_string (status));
	return cairo_test_status_from_status (ctx, status);
    }

    if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) {
	cairo_test_log (ctx, "Unexpected value from cairo_font_face_get_type: %d (expected %d)\n",
			cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT);
	cairo_font_face_destroy (font_face);
	return CAIRO_TEST_FAILURE;
    }

    cairo_set_font_face (cr, font_face);
    cairo_font_face_destroy (font_face);

    font_options = cairo_font_options_create ();

#define CHECK_FONT_EXTENTS(comment) do {\
    cairo_test_status_t test_status; \
    test_status = check_font_extents (ctx, cr, (comment)); \
    if (test_status != CAIRO_TEST_SUCCESS) { \
	cairo_font_options_destroy (font_options); \
	return test_status; \
    } \
} while (0)

    cairo_font_extents (cr, &font_extents);
    CHECK_FONT_EXTENTS ("default");

    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON);
    cairo_set_font_options (cr, font_options);

    CHECK_FONT_EXTENTS ("HINT_METRICS_ON");

    cairo_move_to (cr, 1, font_extents.ascent - 1);
    cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_NONE");
    cairo_show_text (cr, "the ");

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_SLIGHT");
    cairo_show_text (cr, "quick ");

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_MEDIUM");
    cairo_show_text (cr, "brown");

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_FULL");
    cairo_show_text (cr, " fox");

    /* Switch from show_text to text_path/fill to exercise bug #7889 */
    cairo_text_path (cr, " jumps over a lazy dog");
    cairo_fill (cr);

    /* And test it rotated as well for the sake of bug #7888 */

    cairo_translate (cr, width, height);
    cairo_rotate (cr, M_PI);

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_DEFAULT);
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF");

    cairo_move_to (cr, 1, font_extents.height - font_extents.descent - 1);

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_NONE");
    cairo_show_text (cr, "the ");

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_SLIGHT");
    cairo_show_text (cr, "quick");

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_MEDIUM");
    cairo_show_text (cr, " brown");

    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL);
    cairo_set_font_options (cr, font_options);
    CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_FULL");
    cairo_show_text (cr, " fox");

    cairo_text_path (cr, " jumps over");
    cairo_text_path (cr, " a lazy dog");
    cairo_fill (cr);

    cairo_font_options_destroy (font_options);

    return CAIRO_TEST_SUCCESS;
}
Beispiel #21
0
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    Display *dpy;
    unsigned char *reference_data;
    unsigned char *test_data;
    unsigned char *diff_data;
    cairo_surface_t *reference_surface;
    cairo_bool_t use_pixmap;
    cairo_bool_t set_size;
    cairo_bool_t offscreen;
    cairo_test_status_t status, result = CAIRO_TEST_UNTESTED;
    int stride;

    if (! cairo_test_is_target_enabled (ctx, "xlib"))
        goto CLEANUP_TEST;

    dpy = XOpenDisplay (NULL);
    if (!dpy) {
        cairo_test_log (ctx, "xlib-surface: Cannot open display, skipping\n");
        goto CLEANUP_TEST;
    }

    if (!check_visual (dpy)) {
        cairo_test_log (ctx, "xlib-surface: default visual is not RGB24 or BGR24, skipping\n");
        goto CLEANUP_DISPLAY;
    }

    stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, SIZE);

    reference_data = xcalloc (ctx, SIZE, stride);
    test_data = xcalloc (ctx, SIZE, stride);
    diff_data = xcalloc (ctx, SIZE, stride);

    reference_surface = cairo_image_surface_create_for_data (reference_data,
                        CAIRO_FORMAT_RGB24,
                        SIZE, SIZE,
                        stride);

    draw_pattern (reference_surface);
    cairo_surface_destroy (reference_surface);

    result = CAIRO_TEST_SUCCESS;

    for (set_size = 0; set_size <= 1; set_size++)
        for (use_pixmap = 0; use_pixmap <= 1; use_pixmap++)
            for (offscreen = 0; offscreen <= 1; offscreen++) {
                status = do_test (ctx, dpy,
                                  reference_data, test_data, diff_data,
                                  use_pixmap, set_size, offscreen);
                if (status)
                    result = status;
            }

    free (reference_data);
    free (test_data);
    free (diff_data);

CLEANUP_DISPLAY:
    XCloseDisplay (dpy);

CLEANUP_TEST:
    return result;
}
Beispiel #22
0
static cairo_test_status_t
do_test (const cairo_test_context_t *ctx,
         Display        *dpy,
         unsigned char  *reference_data,
         unsigned char  *test_data,
         unsigned char  *diff_data,
         cairo_bool_t    use_pixmap,
         cairo_bool_t    set_size,
         cairo_bool_t    offscreen)
{
    cairo_surface_t *surface;
    cairo_surface_t *test_surface;
    cairo_t *test_cr;
    buffer_diff_result_t result;
    Drawable drawable;
    int screen = DefaultScreen (dpy);

    if (use_pixmap && offscreen)
        return CAIRO_TEST_SUCCESS;

    if (use_pixmap) {
        drawable = XCreatePixmap (dpy, DefaultRootWindow (dpy),
                                  SIZE, SIZE, DefaultDepth (dpy, screen));
    } else {
        XSetWindowAttributes xwa;
        int x, y;

        xwa.override_redirect = True;

        if (offscreen) {
            x = - OFFSCREEN_OFFSET;
            y = - OFFSCREEN_OFFSET;
        } else {
            x = 0;
            y = 0;
        }

        drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
                                  x, y, SIZE, SIZE, 0,
                                  DefaultDepth (dpy, screen), InputOutput,
                                  DefaultVisual (dpy, screen),
                                  CWOverrideRedirect, &xwa);
        XMapWindow (dpy, drawable);
    }

    surface = cairo_xlib_surface_create (dpy,
                                         drawable,
                                         DefaultVisual (dpy, screen),
                                         SIZE, SIZE);

    if (! surface_compare_visual_and_format (surface))
        return CAIRO_TEST_FAILURE;

    if (set_size) {
        cairo_xlib_surface_set_size (surface, SIZE, SIZE);

        if (cairo_xlib_surface_get_width (surface) != SIZE ||
                cairo_xlib_surface_get_height (surface) != SIZE)
            return CAIRO_TEST_FAILURE;
    }

    if (! check_similar_visual_and_format (surface))
        return CAIRO_TEST_FAILURE;

    draw_pattern (surface);

    test_surface = cairo_image_surface_create_for_data (test_data,
                   CAIRO_FORMAT_RGB24,
                   SIZE, SIZE,
                   SIZE * 4);

    test_cr = cairo_create (test_surface);
    cairo_set_source_surface (test_cr, surface, 0, 0);
    cairo_paint (test_cr);

    cairo_destroy (test_cr);
    cairo_surface_destroy (test_surface);

    /* We erase the surface to black in case we get the same
     * memory back again for the pixmap case.
     */
    erase_pattern (surface);
    cairo_surface_destroy (surface);

    if (use_pixmap)
        XFreePixmap (dpy, drawable);
    else
        XDestroyWindow (dpy, drawable);

    if (offscreen) {
        size_t offset = 4 * (SIZE * OFFSCREEN_OFFSET + OFFSCREEN_OFFSET);

        buffer_diff_noalpha (reference_data + offset,
                             test_data + offset,
                             diff_data + offset,
                             SIZE - OFFSCREEN_OFFSET,
                             SIZE - OFFSCREEN_OFFSET,
                             4 * SIZE,
                             &result);
    } else {
        buffer_diff_noalpha (reference_data,
                             test_data,
                             diff_data,
                             SIZE,
                             SIZE,
                             4 * SIZE,
                             &result);
    }

    cairo_test_log (ctx, "xlib-surface: %s, %s, %s: %s\n",
                    set_size ? "   size" : "no-size",
                    use_pixmap ? "pixmap" : "window",
                    use_pixmap ?  "           " : (offscreen ? ", offscreen" : ",  onscreen"),
                    image_diff_is_failure (&result, 0) ? "FAIL" : "PASS");

    if (image_diff_is_failure (&result, 0))
        return CAIRO_TEST_FAILURE;
    else
        return CAIRO_TEST_SUCCESS;
}
Beispiel #23
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_path_t *path;
    cairo_t *cr_error;

    /* Ensure that calling cairo_copy_path on an in-error cairo_t will
     * propagate the error. */
    cr_error = cairo_create (NULL);
    path = cairo_copy_path (cr_error);
    if (path->status != CAIRO_STATUS_NULL_POINTER) {
	cairo_test_log (ctx,
			"Error: cairo_copy_path returned status of %s rather than propagating %s\n",
			cairo_status_to_string (path->status),
			cairo_status_to_string (CAIRO_STATUS_NULL_POINTER));
	cairo_path_destroy (path);
	cairo_destroy (cr_error);
	return CAIRO_TEST_FAILURE;
    }
    cairo_path_destroy (path);

    path = cairo_copy_path_flat (cr_error);
    if (path->status != CAIRO_STATUS_NULL_POINTER) {
	cairo_test_log (ctx,
			"Error: cairo_copy_path_flat returned status of %s rather than propagating %s\n",
			cairo_status_to_string (path->status),
			cairo_status_to_string (CAIRO_STATUS_NULL_POINTER));
	cairo_path_destroy (path);
	cairo_destroy (cr_error);
	return CAIRO_TEST_FAILURE;
    }
    cairo_path_destroy (path);

    cairo_destroy (cr_error);

    /* first check that we can copy an empty path */
    cairo_new_path (cr);
    path = cairo_copy_path (cr);
    if (path->status != CAIRO_STATUS_SUCCESS) {
	cairo_status_t status = path->status;
	cairo_test_log (ctx,
			"Error: cairo_copy_path returned status of %s\n",
			cairo_status_to_string (status));
	cairo_path_destroy (path);
	return cairo_test_status_from_status (ctx, status);
    }
    if (path->num_data != 0) {
	cairo_test_log (ctx,
			"Error: cairo_copy_path did not copy an empty path, returned path contains %d elements\n",
		        path->num_data);
	cairo_path_destroy (path);
	return CAIRO_TEST_FAILURE;
    }
    cairo_append_path (cr, path);
    cairo_path_destroy (path);
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
	cairo_test_log (ctx,
			"Error: cairo_append_path failed with a copy of an empty path, returned status of %s\n",
			cairo_status_to_string (cairo_status (cr)));
	return cairo_test_status_from_status (ctx, cairo_status (cr));
    }

    /* We draw in the default black, so paint white first. */
    cairo_save (cr);
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
    cairo_paint (cr);
    cairo_restore (cr);

    /* copy path, munge, and fill */
    cairo_translate (cr, 5, 5);
    make_path (cr);
    path = cairo_copy_path (cr);

    cairo_new_path (cr);
    munge_and_set_path (cr, path, scale_by_two);
    cairo_path_destroy (path);
    cairo_fill (cr);

    /* copy flattened path, munge, and fill */
    cairo_translate (cr, 0, 15);
    make_path (cr);
    path = cairo_copy_path_flat (cr);

    cairo_new_path (cr);
    munge_and_set_path (cr, path, scale_by_two);
    cairo_path_destroy (path);
    cairo_fill (cr);

    /* append two copies of path, and fill */
    cairo_translate (cr, 0, 15);
    cairo_scale (cr, 2.0, 2.0);
    make_path (cr);
    path = cairo_copy_path (cr);

    cairo_new_path (cr);
    cairo_append_path (cr, path);
    cairo_translate (cr, 2.5, 2.5);
    cairo_append_path (cr, path);

    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
    cairo_fill (cr);

    cairo_path_destroy (path);

    return CAIRO_TEST_SUCCESS;
}
Beispiel #24
0
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;
#ifdef HAVE_SIGNAL_H
    void (*old_segfault_handler)(int);
#endif
    volatile cairo_test_status_t status, ret;
    cairo_boilerplate_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");

    {
	int tmp_num_targets;
	cairo_bool_t tmp_limited_targets;
	targets_to_test = cairo_boilerplate_get_targets (&tmp_num_targets, &tmp_limited_targets);
	num_targets = tmp_num_targets;
	limited_targets = tmp_limited_targets;
    }

    /* 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 backends were manually
     * limited, and none were tested.
     * In other words:
     *
     *  if      backends limited and no backend tested
     *          -> SUCCESS
     *	else if any backend not SUCCESS
     *		-> FAILURE
     *	else if all backends UNTESTED
     *		-> FAILURE
     *	else    (== some backend SUCCESS)
     *		-> SUCCESS
     *
     * Also, on a crash, run no further tests.
     */
    status = ret = CAIRO_TEST_UNTESTED;
    for (i = 0; i < num_targets && status != CAIRO_TEST_CRASHED; i++) {
	for (j = 0; j < NUM_DEVICE_OFFSETS; j++) {
	    cairo_boilerplate_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_boilerplate_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_boilerplate_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_boilerplate_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_boilerplate_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 the set of targets to test was limited using CAIRO_TEST_TARGET, we
     * behave slightly differently, to ensure that limiting the targets does
     * not increase the number of tests failing. */
    if (limited_targets) {

	/* if all untested, success */
	if (ret == CAIRO_TEST_UNTESTED) {
	    printf ("None of the tested backends passed, but tested targets are manually limited.\n"
		    "Passing the test, to not fail the suite.\n");
	    ret = CAIRO_TEST_SUCCESS;
	}

	/* if all passed, but expecting failure, return failure to not
	 * trigger an XPASS failure */
	if (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;
	}

    } else {

	if (ret == CAIRO_TEST_UNTESTED)
	    ret = CAIRO_TEST_FAILURE;

    }

    cairo_test_fini ();

    cairo_boilerplate_free_targets (targets_to_test);

    return ret;
}
Beispiel #25
0
static cairo_test_status_t
cairo_test_for_target (cairo_test_t			 *test,
		       cairo_boilerplate_target_t	 *target,
		       int				  dev_offset)
{
    cairo_test_status_t status;
    cairo_surface_t *surface = NULL;
    cairo_t *cr;
    char *png_name, *ref_name, *diff_name, *offset_str;
    cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
    cairo_content_t expected_content;
    cairo_font_options_t *font_options;
    const char *format;

    /* Get the strings ready that we'll need. */
    format = cairo_boilerplate_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);

    if (target->is_vector) {
	int i;

	for (i = 0; vector_ignored_tests[i] != NULL; i++)
	    if (strcmp (test->name, vector_ignored_tests[i]) == 0) {
		cairo_test_log ("Error: Skipping for vector target %s\n", target->name);
		ret = CAIRO_TEST_UNTESTED;
		goto UNWIND_STRINGS;
	    }
    }

    if (ret == CAIRO_TEST_SUCCESS) {
	/* Run the actual drawing code. */

	if (test->width && test->height) {
	    test->width += dev_offset;
	    test->height += dev_offset;
	}

	surface = (target->create_surface) (test->name,
					    target->content,
					    test->width,
					    test->height,
					    CAIRO_BOILERPLATE_MODE_TEST,
					    &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;
    }

    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) {
	buffer_diff_result_t result;
	cairo_status_t diff_status;
	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;
	}

	cairo_test_log ("Comparing result against reference image: %s\n", ref_name);

	if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED) {
	    diff_status= image_diff_flattened (png_name, ref_name, diff_name,
					       dev_offset, dev_offset, 0, 0, &result);
	} else {
	    diff_status = image_diff (png_name, ref_name, diff_name,
				      dev_offset, dev_offset, 0, 0, &result);
	}
	if (diff_status) {
	    cairo_test_log ("Error: Failed to compare images: %s\n",
			    cairo_status_to_string (diff_status));
	    ret = CAIRO_TEST_FAILURE;
	    goto UNWIND_CAIRO;
	}
	if (result.pixels_changed && result.max_diff > target->error_tolerance) {
	    ret = CAIRO_TEST_FAILURE;
	    goto UNWIND_CAIRO;
	}
    }

UNWIND_CAIRO:
    cairo_destroy (cr);
UNWIND_SURFACE:
    cairo_surface_destroy (surface);

    cairo_debug_reset_static_data ();

    if (target->cleanup)
	target->cleanup (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;
}
static cairo_bool_t
check_result (cairo_test_context_t *ctx,
	      const cairo_boilerplate_target_t *target,
	      const char *test_name,
	      const char *base_name,
	      cairo_surface_t *surface)
{
    const char *format;
    char *ref_name;
    char *png_name;
    char *diff_name;
    cairo_surface_t *test_image, *ref_image, *diff_image;
    buffer_diff_result_t result;
    cairo_status_t status;
    cairo_bool_t ret;

    /* XXX log target, OUTPUT, REFERENCE, DIFFERENCE for index.html */

    if (target->finish_surface != NULL) {
	status = target->finish_surface (surface);
	if (status) {
	    cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
		    cairo_status_to_string (status));
	    cairo_surface_destroy (surface);
	    return FALSE;
	}
    }

    xasprintf (&png_name,  "%s.out.png", base_name);
    xasprintf (&diff_name, "%s.diff.png", base_name);

    test_image = target->get_image_surface (surface, 0, SIZE, SIZE);
    if (cairo_surface_status (test_image)) {
	cairo_test_log (ctx, "Error: Failed to extract page: %s\n",
		        cairo_status_to_string (cairo_surface_status (test_image)));
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	return FALSE;
    }

    _xunlink (ctx, png_name);
    status = cairo_surface_write_to_png (test_image, png_name);
    if (status) {
	cairo_test_log (ctx, "Error: Failed to write output image: %s\n",
		cairo_status_to_string (status));
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	return FALSE;
    }

    format = cairo_boilerplate_content_name (target->content);
    ref_name = cairo_test_reference_filename (ctx,
					      base_name,
					      test_name,
					      target->name,
					      target->basename,
					      format,
					      CAIRO_TEST_REF_SUFFIX,
					      CAIRO_TEST_PNG_EXTENSION);
    if (ref_name == NULL) {
	cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
		        base_name);
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	return FALSE;
    }


    ref_image = cairo_test_get_reference_image (ctx, ref_name,
	    target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
    if (cairo_surface_status (ref_image)) {
	cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
		        ref_name,
		cairo_status_to_string (cairo_surface_status (ref_image)));
	cairo_surface_destroy (ref_image);
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	free (ref_name);
	return FALSE;
    }

    diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
	    SIZE, SIZE);

    ret = TRUE;
    status = image_diff (ctx,
	    test_image, ref_image, diff_image,
	    &result);
    _xunlink (ctx, diff_name);
    if (status) {
	cairo_test_log (ctx, "Error: Failed to compare images: %s\n",
			cairo_status_to_string (status));
	ret = FALSE;
    } else if (result.pixels_changed &&
	       result.max_diff > target->error_tolerance)
    {
	ret = FALSE;

	status = cairo_surface_write_to_png (diff_image, diff_name);
	if (status) {
	    cairo_test_log (ctx, "Error: Failed to write differences image: %s\n",
		    cairo_status_to_string (status));
	}
    }

    cairo_surface_destroy (test_image);
    cairo_surface_destroy (diff_image);
    free (png_name);
    free (diff_name);
    free (ref_name);

    return ret;
}
Beispiel #27
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_surface_t *surface;
    cairo_pattern_t *pattern;
    cairo_t *cr2;

    /*
     * 1. Test file-not-found from surface->pattern->cairo_t
     */

    /* Make a custom context to not interfere with the one passed in. */
    cr2 = cairo_create (cairo_get_target (cr));

    /* First, let's make a nil surface. */
    surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");

    /* Let the error propagate into a nil pattern. */
    pattern = cairo_pattern_create_for_surface (surface);

    /* Then let it propagate into the cairo_t. */
    cairo_set_source (cr2, pattern);
    cairo_paint (cr2);

    cairo_pattern_destroy (pattern);
    cairo_surface_destroy (surface);

    /* Check that the error made it all that way. */
    if (cairo_status (cr2) != CAIRO_STATUS_FILE_NOT_FOUND) {
	cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n",
			cairo_status_to_string (cairo_status (cr2)),
			cairo_status_to_string (CAIRO_STATUS_FILE_NOT_FOUND));
	cairo_destroy (cr2);
	return CAIRO_TEST_FAILURE;
    }

    cairo_destroy (cr2);

    /*
     * 2. Test NULL pointer pattern->cairo_t
     */
    cr2 = cairo_create (cairo_get_target (cr));

    /* First, trigger the NULL pointer status. */
    pattern = cairo_pattern_create_for_surface (NULL);

    /* Then let it propagate into the cairo_t. */
    cairo_set_source (cr2, pattern);
    cairo_paint (cr2);

    cairo_pattern_destroy (pattern);

    /* Check that the error made it all that way. */
    if (cairo_status (cr2) != CAIRO_STATUS_NULL_POINTER) {
	cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n",
			cairo_status_to_string (cairo_status (cr2)),
			cairo_status_to_string (CAIRO_STATUS_NULL_POINTER));
	cairo_destroy (cr2);
	return CAIRO_TEST_FAILURE;
    }

    cairo_destroy (cr2);

    /*
     * 3. Test that cairo_surface_finish can accept NULL or a nil
     *    surface without crashing.
     */

    cairo_surface_finish (NULL);

    surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
    cairo_surface_finish (surface);
    cairo_surface_destroy (surface);

    /*
     * 4. OK, we're straying from the original name, but it's still a
     * similar kind of testing of error paths. Here we're making sure
     * we can still call a cairo_get_* function after triggering an
     * INVALID_RESTORE error.
     */
    cr2 = cairo_create (cairo_get_target (cr));

    /* Trigger invalid restore. */
    cairo_restore (cr2);
    if (cairo_status (cr2) != CAIRO_STATUS_INVALID_RESTORE) {
	cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n",
			cairo_status_to_string (cairo_status (cr2)),
			cairo_status_to_string (CAIRO_STATUS_INVALID_RESTORE));
	cairo_destroy (cr2);
	return CAIRO_TEST_FAILURE;
    }

    /* Test that we can still call cairo_get_fill_rule without crashing. */
    cairo_get_fill_rule (cr2);

    cairo_destroy (cr2);

    /*
     * 5. Create a cairo_t for the NULL surface.
     */
    cr2 = cairo_create (NULL);

    if (cairo_status (cr2) != CAIRO_STATUS_NULL_POINTER) {
	cairo_test_log (ctx, "Error: Received status of \"%s\" rather than expected \"%s\"\n",
			cairo_status_to_string (cairo_status (cr2)),
			cairo_status_to_string (CAIRO_STATUS_NULL_POINTER));
	cairo_destroy (cr2);
	return CAIRO_TEST_FAILURE;
    }

    /* Test that get_target returns something valid */
    if (cairo_get_target (cr2) == NULL) {
	cairo_test_log (ctx, "Error: cairo_get_target() returned NULL\n");
	cairo_destroy (cr2);
	return CAIRO_TEST_FAILURE;
    }

    /* Test that push_group doesn't crash */
    cairo_push_group (cr2);
    cairo_stroke (cr2);
    cairo_pop_group (cr2);

    cairo_destroy (cr2);

    return CAIRO_TEST_SUCCESS;
}
Beispiel #28
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_text_extents_t extents, nil_extents;
    cairo_font_extents_t font_extents, nil_font_extents;
    cairo_scaled_font_t *scaled_font;

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, 16);

    cairo_move_to (cr, 10, 25);
    cairo_show_text (cr, NULL);
    cairo_show_text (cr, "");
    cairo_show_glyphs (cr, NULL, 0);
    cairo_show_glyphs (cr, (void*)8, 0);

    cairo_move_to (cr, 10, 55);
    cairo_text_path (cr, NULL);
    cairo_text_path (cr, "");
    cairo_glyph_path (cr, (void*)8, 0);
    cairo_fill (cr);

    memset (&nil_extents, 0, sizeof (cairo_text_extents_t));

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_text_extents (cr, "", &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_text_extents(\"\"); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_text_extents (cr, NULL, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_text_extents(NULL); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_glyph_extents (cr, (void*)8, 0, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_glyph_extents(); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    scaled_font = cairo_get_scaled_font (cr);

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_scaled_font_text_extents (scaled_font, "", &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_scaled_font_text_extents(\"\"); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_scaled_font_text_extents (scaled_font, NULL, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_scaled_font_text_extents(NULL); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_scaled_font_glyph_extents (scaled_font, (void*)8, 0, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_scaled_font_glyph_extents(NULL); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    /* Lets also try font size 0 while here */
    cairo_set_font_size (cr, 0);

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_text_extents (cr, "test", &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_set_font_size(0); cairo_text_extents(\"test\"); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&nil_font_extents, 0, sizeof (cairo_font_extents_t));

    memset (&font_extents, 0xff, sizeof (cairo_font_extents_t));
    cairo_font_extents (cr,  &font_extents);
    if (! font_extents_equal (&font_extents, &nil_font_extents)) {
	cairo_test_log (ctx, "Error: cairo_set_font_size(0); cairo_font_extents(); extents (%g, %g, %g, %g, %g)\n",
		        font_extents.ascent, font_extents.descent,
			font_extents.height,
			font_extents.max_x_advance, font_extents.max_y_advance);
	return CAIRO_TEST_FAILURE;
    }

    scaled_font = cairo_get_scaled_font (cr);

    memset (&font_extents, 0xff, sizeof (cairo_font_extents_t));
    cairo_scaled_font_extents (scaled_font,  &font_extents);
    if (! font_extents_equal (&font_extents, &nil_font_extents)) {
	cairo_test_log (ctx, "Error: cairo_set_font_size(0); cairo_scaled_font_extents(); extents (%g, %g, %g, %g, %g)\n",
		        font_extents.ascent, font_extents.descent,
			font_extents.height,
			font_extents.max_x_advance, font_extents.max_y_advance);
	return CAIRO_TEST_FAILURE;
    }

    return CAIRO_TEST_SUCCESS;
}
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    cairo_t *cr;
    cairo_test_status_t ret = CAIRO_TEST_UNTESTED;
    struct {
	double x, y;
    } ppi[] = {
	{ 600, 600 },
	{ 600, 72 },

	{ 300, 300 },
	{ 300, 72 },

	{ 150, 150 },
	{ 150, 72 },

	{ 75, 75 },
	{ 75, 72 },

	{ 72, 600 },
	{ 72, 300 },
	{ 72, 150 },
	{ 72, 75 },
	{ 72, 72 },
	{ 72, 37.5 },

	{ 37.5, 72 },
	{ 37.5, 37.5 },
    };
    unsigned int i;
    int n, num_ppi;

    num_ppi = sizeof (ppi) / sizeof (ppi[0]);

#if GENERATE_REFERENCE
    for (n = 0; n < num_ppi; n++) {
	char *ref_name;
	xasprintf (&ref_name, "fallback-resolution.ppi%gx%g.ref.png",
		   ppi[n].x, ppi[n].y);
	generate_reference (ppi[n].x, ppi[n].y, ref_name);
	free (ref_name);
    }
#endif

    for (i = 0; i < ctx->num_targets; i++) {
	const cairo_boilerplate_target_t *target = ctx->targets_to_test[i];
	cairo_surface_t *surface = NULL;
	char *base_name;
	void *closure;
	const char *format;
	cairo_status_t status;

	if (! target->is_vector)
	    continue;

	if (! cairo_test_is_target_enabled (ctx, target->name))
	    continue;

	format = cairo_boilerplate_content_name (target->content);
	xasprintf (&base_name, "fallback-resolution.%s.%s",
		   target->name,
		   format);

	surface = (target->create_surface) (base_name,
					    target->content,
					    SIZE, SIZE,
					    SIZE, SIZE,
					    CAIRO_BOILERPLATE_MODE_TEST,
					    0,
					    &closure);

	if (surface == NULL) {
	    free (base_name);
	    continue;
	}

	if (ret == CAIRO_TEST_UNTESTED)
	    ret = CAIRO_TEST_SUCCESS;

	cairo_surface_destroy (surface);
	if (target->cleanup)
	    target->cleanup (closure);
	free (base_name);

	/* we need to recreate the surface for each resolution as we include
	 * SVG in testing which does not support the paginated interface.
	 */
	for (n = 0; n < num_ppi; n++) {
	    char *test_name;
	    cairo_bool_t pass;

	    xasprintf (&test_name, "fallback-resolution.ppi%gx%g",
		       ppi[n].x, ppi[n].y);
	    xasprintf (&base_name, "%s.%s.%s",
		       test_name,
		       target->name,
		       format);

	    surface = (target->create_surface) (base_name,
						target->content,
						SIZE + 25, SIZE + 25,
						SIZE + 25, SIZE + 25,
						CAIRO_BOILERPLATE_MODE_TEST,
						0,
						&closure);
	    if (surface == NULL || cairo_surface_status (surface)) {
		cairo_test_log (ctx, "Failed to generate surface: %s.%s\n",
				target->name,
				format);
		free (base_name);
		free (test_name);
		ret = CAIRO_TEST_FAILURE;
		continue;
	    }

	    cairo_test_log (ctx,
			    "Testing fallback-resolution %gx%g with %s target\n",
			    ppi[n].x, ppi[n].y, target->name);
	    printf ("%s:\t", base_name);
	    fflush (stdout);

	    if (target->force_fallbacks != NULL)
		target->force_fallbacks (surface, ~0U);
	    cr = cairo_create (surface);
#if SET_TOLERANCE
	    cairo_set_tolerance (cr, 3.0);
#endif

	    cairo_surface_set_device_offset (surface, 25, 25);
	    cairo_surface_set_fallback_resolution (surface,
						   ppi[n].x, ppi[n].y);

	    cairo_save (cr); {
		cairo_set_source_rgb (cr, 1, 1, 1);
		cairo_paint (cr);
	    } cairo_restore (cr);

	    /* First draw the top half in a conventional way. */
	    cairo_save (cr); {
		cairo_rectangle (cr, 0, 0, SIZE, SIZE / 2.0);
		cairo_clip (cr);

		draw (cr, SIZE, SIZE);
	    } cairo_restore (cr);

	    /* Then draw the bottom half in a separate group,
	     * (exposing a bug in 1.6.4 with the group not being
	     * rendered with the correct fallback resolution). */
	    cairo_save (cr); {
		cairo_rectangle (cr, 0, SIZE / 2.0, SIZE, SIZE / 2.0);
		cairo_clip (cr);

		cairo_push_group (cr); {
		    draw (cr, SIZE, SIZE);
		} cairo_pop_group_to_source (cr);

		cairo_paint (cr);
	    } cairo_restore (cr);

	    status = cairo_status (cr);
	    cairo_destroy (cr);

	    pass = FALSE;
	    if (status) {
		cairo_test_log (ctx, "Error: Failed to create target surface: %s\n",
				cairo_status_to_string (status));
		ret = CAIRO_TEST_FAILURE;
	    } else {
		/* extract the image and compare it to our reference */
		if (! check_result (ctx, target, test_name, base_name, surface))
		    ret = CAIRO_TEST_FAILURE;
		else
		    pass = TRUE;
	    }
	    cairo_surface_destroy (surface);
	    if (target->cleanup)
		target->cleanup (closure);

	    free (base_name);
	    free (test_name);

	    if (pass) {
		printf ("PASS\n");
	    } else {
		printf ("FAIL\n");
	    }
	    fflush (stdout);
	}
    }

    return ret;
}
Beispiel #30
0
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
    cairo_surface_t *surface;
    cairo_t *cr;

    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
    cr = cairo_create (surface);
    cairo_surface_destroy (surface);

    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);

    /* simple rectangle */
    cairo_new_path (cr);
    cairo_rectangle (cr, -10, -10, 20, 20);
    if (! cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* rectangular boundary tests */
    if (! cairo_in_fill (cr, -10, -10)) {
	cairo_test_log (ctx, "Error: Failed to find top-left vertex inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, -10, 10)) {
	cairo_test_log (ctx, "Error: Failed to find bottom-left vertex inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 10, -10)) {
	cairo_test_log (ctx, "Error: Failed to find top-right vertex inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 10, 10)) {
	cairo_test_log (ctx, "Error: Failed to find bottom-right vertex inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, -10, 0)) {
	cairo_test_log (ctx, "Error: Failed to find left edge inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 0, -10)) {
	cairo_test_log (ctx, "Error: Failed to find top edge inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 10, 0)) {
	cairo_test_log (ctx, "Error: Failed to find right edge inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 0, 10)) {
	cairo_test_log (ctx, "Error: Failed to find bottom edge inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* simple circle */
    cairo_new_path (cr);
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
    if (! cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside circle [even-odd]\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* holey rectangle */
    cairo_new_path (cr);
    cairo_rectangle (cr, -10, -10, 20, 20);
    cairo_rectangle (cr, -5, -5, 10, 10);
    if (cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular eo-hole\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* holey circle */
    cairo_new_path (cr);
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
    cairo_arc (cr, 0, 0, 5, 0, 2 * M_PI);
    if (cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Found an unexpected point inside circular eo-hole\n");
	ret = CAIRO_TEST_FAILURE;
    }


    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);

    /* simple rectangle */
    cairo_new_path (cr);
    cairo_rectangle (cr, -10, -10, 20, 20);
    if (! cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* simple circle */
    cairo_new_path (cr);
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
    if (! cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside circle [nonzero]\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* overlapping circle/rectangle */
    cairo_new_path (cr);
    cairo_rectangle (cr, -10, -10, 20, 20);
    cairo_new_sub_path (cr);
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
    if (! cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside circle+rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* holey rectangle */
    cairo_new_path (cr);
    cairo_rectangle (cr, -10, -10, 20, 20);
    cairo_rectangle (cr, 5, -5, -10, 10);
    if (cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular non-zero-hole\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* holey circle */
    cairo_new_path (cr);
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
    cairo_arc_negative (cr, 0, 0, 5, 0, -2 * M_PI);
    if (cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Found an unexpected point inside circular non-zero-hole\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* not a holey circle */
    cairo_new_path (cr);
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
    cairo_arc (cr, 0, 0, 5, 0, 2 * M_PI);
    if (! cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside two circles\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* check off-centre */
    cairo_new_path (cr);
    cairo_arc (cr, 7.5, 0, 10, 0, 2 * M_PI);
    cairo_arc_negative (cr, 7.5, 0, 5, 0, -2 * M_PI);
    if (cairo_in_fill (cr, 7.5, 0)) {
	cairo_test_log (ctx, "Error: Found an unexpected point inside off-centre-x circular non-zero-hole\n");
	ret = CAIRO_TEST_FAILURE;
    }
    cairo_new_path (cr);
    cairo_arc (cr, 0, 7.5, 10, 0, 2 * M_PI);
    cairo_arc_negative (cr, 0, 7.5, 5, 0, -2 * M_PI);
    if (cairo_in_fill (cr, 0, 7.5)) {
	cairo_test_log (ctx, "Error: Found an unexpected point inside off-centre-y circular non-zero-hole\n");
	ret = CAIRO_TEST_FAILURE;
    }
    cairo_new_path (cr);
    cairo_arc (cr, 15, 0, 10, 0, 2 * M_PI);
    if (! cairo_in_fill (cr, 15, 0)) {
	cairo_test_log (ctx, "Error: Failed to find point inside off-centre-x circle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    cairo_new_path (cr);
    cairo_arc (cr, 0, 15, 10, 0, 2 * M_PI);
    if (! cairo_in_fill (cr, 0, 15)) {
	cairo_test_log (ctx, "Error: Failed to find point inside off-centre-y circle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* simple rectangle */
    cairo_new_path (cr);
    cairo_rectangle (cr, 10, 0, 5, 5);
    if (cairo_in_fill (cr, 0, 0)) {
	cairo_test_log (ctx, "Error: Found an unexpected point outside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (cairo_in_fill (cr, 20, 20)) {
	cairo_test_log (ctx, "Error: Found an unexpected point outside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 12.5, 2.5)) {
	cairo_test_log (ctx, "Error: Failed to find point inside rectangle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    /* off-centre triangle */
    cairo_new_path (cr);
    cairo_move_to (cr, 10, 0);
    cairo_line_to (cr, 15, 5);
    cairo_line_to (cr, 5, 5);
    cairo_close_path (cr);
    if (cairo_in_fill (cr, 0, 0) ||
	cairo_in_fill (cr, 5, 0) ||
	cairo_in_fill (cr, 15, 0) ||
	cairo_in_fill (cr, 20, 0) ||
	cairo_in_fill (cr, 0, 10) ||
	cairo_in_fill (cr, 10, 10) ||
	cairo_in_fill (cr, 20, 10) ||
	cairo_in_fill (cr, 7, 2.5) ||
	cairo_in_fill (cr, 13, 2.5))
    {
	cairo_test_log (ctx,
			"Error: Found an unexpected point outside triangle\n"
			"\t(0, 0) -> %s\n"
			"\t(5, 0) -> %s\n"
			"\t(15, 0) -> %s\n"
			"\t(20, 0) -> %s\n"
			"\t(0, 10) -> %s\n"
			"\t(10, 10) -> %s\n"
			"\t(20, 10) -> %s\n"
			"\t(7, 2.5) -> %s\n"
			"\t(13, 2.5) -> %s\n",
			cairo_in_fill (cr, 0, 0) ? "inside" : "outside",
			cairo_in_fill (cr, 5, 0) ? "inside" : "outside",
			cairo_in_fill (cr, 15, 0) ? "inside" : "outside",
			cairo_in_fill (cr, 20, 0) ? "inside" : "outside",
			cairo_in_fill (cr, 0, 10) ? "inside" : "outside",
			cairo_in_fill (cr, 10, 10) ? "inside" : "outside",
			cairo_in_fill (cr, 20, 10) ? "inside" : "outside",
			cairo_in_fill (cr, 7, 2.5) ? "inside" : "outside",
			cairo_in_fill (cr, 13, 2.5) ? "inside" : "outside");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 7.5, 2.5) ||
	! cairo_in_fill (cr, 12.5, 2.5) ||
	! cairo_in_fill (cr, 10, 5))
    {
	cairo_test_log (ctx,
			"Error: Failed to find point on triangle edge\n"
			"\t(7.5, 2.5) -> %s\n"
			"\t(12.5, 2.5) -> %s\n"
			"\t(10, 5) -> %s\n",
			cairo_in_fill (cr, 7.5, 2.5) ? "inside" : "outside",
			cairo_in_fill (cr, 12.5, 2.5) ? "inside" : "outside",
			cairo_in_fill (cr, 10, 5) ? "inside" : "outside");
	ret = CAIRO_TEST_FAILURE;
    }
    if (! cairo_in_fill (cr, 8, 2.5) ||
	! cairo_in_fill (cr, 12, 2.5))
    {
	cairo_test_log (ctx, "Error: Failed to find point inside triangle\n");
	ret = CAIRO_TEST_FAILURE;
    }

    cairo_destroy (cr);

    return ret;
}