📄 cairo-test.c
字号:
if (access (ref_name, F_OK) != 0) { free (ref_name); /* Finally, look for the standard reference image. */ xasprintf (&ref_name, "%s/%s%s", srcdir, test->name, CAIRO_TEST_REF_SUFFIX); } } 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, target->content, &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); status = (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 (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: free (png_name); free (ref_name); free (diff_name); free (offset_str); return ret;}static voidsegfault_handler (int signal){ longjmp (jmpbuf, signal);}static cairo_test_status_tcairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, cairo_test_status_t expectation){ volatile int i, j, num_targets; const char *tname; sighandler_t old_segfault_handler; cairo_test_status_t status, ret; cairo_test_target_t **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 (1)) { fail_face = "\033[41m\033[37m\033[1m"; normal_face = "\033[m"; }#endif srcdir = getenv ("srcdir"); if (!srcdir) srcdir = "."; if ((tname = getenv ("CAIRO_TEST_TARGET")) != NULL) { const char *tname = getenv ("CAIRO_TEST_TARGET"); num_targets = 0; targets_to_test = NULL; while (*tname) { int found = 0; const char *end = strpbrk (tname, " \t;:,"); if (!end) end = tname + strlen (tname); for (i = 0; i < sizeof(targets)/sizeof(targets[0]); i++) { if (strncmp (targets[i].name, tname, end - tname) == 0 && !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, "CAIRO_TEST_TARGET '%s' not found in targets list!\n", tname); exit(-1); } if (*end) end++; tname = end; } } else { num_targets = sizeof(targets)/sizeof(targets[0]); targets_to_test = malloc (sizeof(cairo_test_target_t*) * num_targets); for (i = 0; i < num_targets; i++) targets_to_test[i] = &targets[i]; } cairo_test_init (test->name); /* 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. In other words: * * 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 *target = targets_to_test[i]; 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); /* Set up a checkpoint to get back to in case of segfaults. */ old_segfault_handler = signal (SIGSEGV, (sighandler_t) segfault_handler); if (0 == setjmp (jmpbuf)) status = cairo_test_for_target (test, draw, target, dev_offset); else status = CAIRO_TEST_CRASHED; signal (SIGSEGV, (sighandler_t) old_segfault_handler); 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: printf ("%s!!!CRASHED!!!%s\n", fail_face, normal_face); cairo_test_log ("CRASHED\n"); ret = CAIRO_TEST_FAILURE; break; default: case CAIRO_TEST_FAILURE: if (expectation == CAIRO_TEST_FAILURE) { printf ("XFAIL\n"); cairo_test_log ("XFAIL\n"); } else { printf ("%sFAIL%s\n", fail_face, normal_face); cairo_test_log ("FAIL\n"); } ret = status; break; } } } if (ret == CAIRO_TEST_UNTESTED) ret = CAIRO_TEST_FAILURE; fclose (cairo_test_log_file); free (targets_to_test);#if HAVE_FCFINI FcFini ();#endif return ret;}cairo_test_status_tcairo_test_expect_failure (cairo_test_t *test, cairo_test_draw_function_t draw, const char *because){ printf ("\n%s is expected to fail:\n\t%s\n", test->name, because); return cairo_test_expecting (test, draw, CAIRO_TEST_FAILURE);}cairo_test_status_tcairo_test (cairo_test_t *test, cairo_test_draw_function_t draw){ printf ("\n"); return cairo_test_expecting (test, draw, CAIRO_TEST_SUCCESS);}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_tcairo_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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -