void cairo_test_fini (cairo_test_context_t *ctx) { if (ctx->log_file == NULL) return; if (ctx->log_file != stderr) fclose (ctx->log_file); ctx->log_file = NULL; free (ctx->ref_name); cairo_surface_destroy (ctx->ref_image); cairo_surface_destroy (ctx->ref_image_flattened); if (ctx->test_name != NULL) free ((char *) ctx->test_name); if (ctx->own_targets) cairo_boilerplate_free_targets (ctx->targets_to_test); cairo_boilerplate_fini (); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif }
inline void run_cleanup() { // only call this once, on exit // to make sure valgrind output is clean // http://xmlsoft.org/xmlmem.html xmlCleanupCharEncodingHandlers(); xmlCleanupEncodingAliases(); xmlCleanupGlobals(); xmlCleanupParser(); xmlCleanupThreads(); xmlCleanupInputCallbacks(); xmlCleanupOutputCallbacks(); xmlCleanupMemory(); #if defined(HAVE_CAIRO) // http://cairographics.org/manual/cairo-Error-handling.html#cairo-debug-reset-static-data cairo_debug_reset_static_data(); #endif // http://icu-project.org/apiref/icu4c/uclean_8h.html#a93f27d0ddc7c196a1da864763f2d8920 u_cleanup(); #ifdef MAPNIK_USE_PROJ4 // http://trac.osgeo.org/proj/ticket/149 #if PJ_VERSION >= 480 pj_clear_initcache(); #endif // https://trac.osgeo.org/proj/wiki/ProjAPI#EnvironmentFunctions pj_deallocate_grids(); #endif }
gfxQtPlatform::~gfxQtPlatform() { gfxFontconfigUtils::Shutdown(); sFontconfigUtils = nsnull; delete gPlatformFonts; gPlatformFonts = NULL; delete gPlatformFontAliases; gPlatformFontAliases = NULL; delete gPrefFonts; gPrefFonts = NULL; delete gCodepointsWithNoFonts; gCodepointsWithNoFonts = NULL; cairo_debug_reset_static_data(); FT_Done_FreeType(gPlatformFTLibrary); gPlatformFTLibrary = NULL; #if 0 // It would be nice to do this (although it might need to be after // the cairo shutdown that happens in ~gfxPlatform). It even looks // idempotent. But it has fatal assertions that fire if stuff is // leaked, and we hit them. FcFini(); #endif }
static void cairo_perf_fini (void) { cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif }
void destroy(cairo_surface_t *sfc) { Display *dsp = cairo_xlib_surface_get_display(sfc); cairo_surface_destroy(sfc); cairo_debug_reset_static_data(); XCloseDisplay(dsp); }
void cairo_test_fini (void) { fclose (cairo_test_log_file); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif }
static void cairo_perf_fini (cairo_perf_t *perf) { cairo_boilerplate_free_targets (perf->targets); free (perf->times); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif }
void destroy_tabletwm() { shutdown_destroy(); wincache_destroy_element(key_win.window); destroy_keycodes(); menuwin_destroy(); xcb_destroy_window(conn, key_win.window); xcb_flush(conn); cairo_debug_reset_static_data (); for(int i = 0; i < 5; i++) { free(xkb_names[i]); } }
gfxPlatform::~gfxPlatform() { // The cairo folks think we should only clean up in debug builds, // but we're generally in the habit of trying to shut down as // cleanly as possible even in production code, so call this // cairo_debug_* function unconditionally. // // because cairo can assert and thus crash on shutdown, don't do this in release builds #if MOZ_TREE_CAIRO && (defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC)) cairo_debug_reset_static_data(); #endif #if 0 // It would be nice to do this (although it might need to be after // the cairo shutdown that happens in ~gfxPlatform). It even looks // idempotent. But it has fatal assertions that fire if stuff is // leaked, and we hit them. FcFini(); #endif }
/** * cairo_os2_fini: * * Uninitializes the Cairo library. This function is automatically called if * Cairo was compiled to be a DLL (however it's not a problem if it's called * multiple times). But if you link to Cairo statically, you have to call it * once to shut down Cairo, to let it free all the resources it has allocated. * * Since: 1.4 **/ cairo_public void cairo_os2_fini (void) { /* This has to uninitialize some stuffs, like destroy mutex semaphores etc.. */ if (cairo_os2_initialization_count <= 0) return; cairo_os2_initialization_count--; if (cairo_os2_initialization_count > 0) return; DisableFPUException (); cairo_debug_reset_static_data (); #if CAIRO_HAS_FC_FONT # if HAVE_FCFINI /* Uninitialize FontConfig */ FcFini (); # endif #endif #ifdef __WATCOMC__ /* It can happen that the libraries we use have memory leaks, * so there are still memory chunks allocated at this point. * In these cases, Watcom might still have a bigger memory chunk, * called "the heap" allocated from the OS. * As we want to minimize the memory we lose from the point of * view of the OS, we call this function to shrink that heap * as much as possible. */ _heapshrink (); #else /* GCC has a heapmin function that approximately corresponds to * what the Watcom function does */ _heapmin (); #endif }
static void cairo_perf_trace (cairo_perf_t *perf, const cairo_boilerplate_target_t *target, const char *trace) { cairo_surface_t *surface; void *closure; surface = (target->create_surface) (NULL, CAIRO_CONTENT_COLOR_ALPHA, 1, 1, 1, 1, CAIRO_BOILERPLATE_MODE_PERF, 0, &closure); if (surface == NULL) { fprintf (stderr, "Error: Failed to create target surface: %s\n", target->name); return; } cairo_perf_timer_set_synchronize (target->synchronize, closure); execute (perf, closure, surface, trace); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif }
void msCairoCleanup() { cairo_debug_reset_static_data(); }
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; }
int main(int argc, char *argv[]) { struct kdata *d[20], *md; struct kplot *p; cairo_surface_t *surf; size_t i; cairo_t *cr; cairo_status_t st; int rc, c; rc = EXIT_FAILURE; md = kdata_mean_alloc(NULL); for (i = 0; i < 20; i++) { d[i] = kdata_array_alloc(NULL, 100); assert(NULL != d[i]); c = kdata_mean_attach(md, d[i]); assert(c); c = kdata_array_fill(d[i], NULL, fill); assert(c); } if (NULL == (p = kplot_alloc(NULL))) { perror(NULL); goto out; } for (i = 0; i < 20; i++) { if ( ! kplot_attach_data(p, d[i], KPLOT_POINTS, NULL)) { perror(NULL); goto out; } } if ( ! kplot_attach_data(p, md, KPLOT_LINES, NULL)) { perror(NULL); goto out; } for (i = 0; i < 20; i++) { kdata_destroy(d[i]); d[i] = NULL; } kdata_destroy(md); md = NULL; surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 600, 400); st = cairo_surface_status(surf); if (CAIRO_STATUS_SUCCESS != st) { fprintf(stderr, "%s", cairo_status_to_string(st)); cairo_surface_destroy(surf); kplot_free(p); return(EXIT_FAILURE); } cr = cairo_create(surf); cairo_surface_destroy(surf); st = cairo_status(cr); if (CAIRO_STATUS_SUCCESS != st) { fprintf(stderr, "%s", cairo_status_to_string(st)); cairo_destroy(cr); kplot_free(p); return(EXIT_FAILURE); } cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_rectangle(cr, 0.0, 0.0, 600.0, 400.0); cairo_fill(cr); kplot_draw(p, 600.0, 400.0, cr); st = cairo_surface_write_to_png (cairo_get_target(cr), "example5.png"); if (CAIRO_STATUS_SUCCESS != st) { fprintf(stderr, "%s", cairo_status_to_string(st)); cairo_destroy(cr); kplot_free(p); return(EXIT_FAILURE); } cairo_destroy(cr); rc = EXIT_SUCCESS; out: kplot_free(p); for (i = 0; i < 20; i++) kdata_destroy(d[i]); kdata_destroy(md); #ifdef __APPLE__ cairo_debug_reset_static_data(); #endif return(rc); }
static int gt_sketch_page_runner(GT_UNUSED int argc, const char **argv, int parsed_args, void *tool_arguments, GtError *err) { SketchPageArguments *arguments = tool_arguments; int had_err = 0; GtFeatureIndex *features = NULL; GtRange qry_range, sequence_region_range; GtStyle *sty = NULL; GtStr *prog, *gt_style_file; GtDiagram *d = NULL; GtLayout *l = NULL; GtBioseq *bioseq = NULL; GtCanvas *canvas = NULL; const char *seqid = NULL, *outfile; unsigned long start, height, num_pages = 0; double offsetpos, usable_height; cairo_surface_t *surf = NULL; cairo_t *cr = NULL; GtTextWidthCalculator *twc; gt_error_check(err); features = gt_feature_index_memory_new(); if (cairo_version() < CAIRO_VERSION_ENCODE(1, 8, 6)) gt_warning("Your cairo library (version %s) is older than version 1.8.6! " "These versions contain a bug which may result in " "corrupted PDF output!", cairo_version_string()); /* get style */ sty = gt_style_new(err); if (gt_str_length(arguments->stylefile) == 0) { prog = gt_str_new(); gt_str_append_cstr_nt(prog, argv[0], gt_cstr_length_up_to_char(argv[0], ' ')); gt_style_file = gt_get_gtdata_path(gt_str_get(prog), err); gt_str_delete(prog); gt_str_append_cstr(gt_style_file, "/sketch/default.style"); } else { gt_style_file = gt_str_ref(arguments->stylefile); } had_err = gt_style_load_file(sty, gt_str_get(gt_style_file), err); outfile = argv[parsed_args]; if (!had_err) { /* get features */ had_err = gt_feature_index_add_gff3file(features, argv[parsed_args+1], err); if (!had_err && gt_str_length(arguments->seqid) == 0) { seqid = gt_feature_index_get_first_seqid(features); if (seqid == NULL) { gt_error_set(err, "GFF input file must contain a sequence region!"); had_err = -1; } } else if (!had_err && !gt_feature_index_has_seqid(features, gt_str_get(arguments->seqid))) { gt_error_set(err, "sequence region '%s' does not exist in GFF input file", gt_str_get(arguments->seqid)); had_err = -1; } else if (!had_err) seqid = gt_str_get(arguments->seqid); } /* set text */ if (gt_str_length(arguments->text) == 0) { gt_str_delete(arguments->text); arguments->text = gt_str_new_cstr(argv[parsed_args+1]); } if (!had_err) { /* set display range */ gt_feature_index_get_range_for_seqid(features, &sequence_region_range, seqid); qry_range.start = (arguments->range.start == GT_UNDEF_ULONG ? sequence_region_range.start : arguments->range.start); qry_range.end = (arguments->range.end == GT_UNDEF_ULONG ? sequence_region_range.end : arguments->range.end); /* set output format */ if (strcmp(gt_str_get(arguments->format), "pdf") == 0) { surf = cairo_pdf_surface_create(outfile, mm_to_pt(arguments->pwidth), mm_to_pt(arguments->pheight)); } else if (strcmp(gt_str_get(arguments->format), "ps") == 0) { surf = cairo_ps_surface_create(outfile, mm_to_pt(arguments->pwidth), mm_to_pt(arguments->pheight)); } gt_log_log("created page with %.2f:%.2f dimensions\n", mm_to_pt(arguments->pwidth), mm_to_pt(arguments->pheight)); offsetpos = TEXT_SPACER + arguments->theight + TEXT_SPACER; usable_height = mm_to_pt(arguments->pheight) - arguments->theight - arguments->theight - 4*TEXT_SPACER; if (gt_str_length(arguments->seqfile) > 0) { bioseq = gt_bioseq_new(gt_str_get(arguments->seqfile), err); } cr = cairo_create(surf); cairo_set_font_size(cr, 8); twc = gt_text_width_calculator_cairo_new(cr, sty); for (start = qry_range.start; start <= qry_range.end; start += arguments->width) { GtRange single_range; GtCustomTrack *ct = NULL; const char *seq; single_range.start = start; single_range.end = start + arguments->width; if (had_err) break; d = gt_diagram_new(features, seqid, &single_range, sty, err); if (!d) { had_err = -1; break; } if (bioseq) { seq = gt_bioseq_get_sequence(bioseq, 0); ct = gt_custom_track_gc_content_new(seq, gt_bioseq_get_sequence_length(bioseq, 0), 800, 70, 0.4, true); gt_diagram_add_custom_track(d, ct); } l = gt_layout_new_with_twc(d, mm_to_pt(arguments->width), sty, twc, err); had_err = gt_layout_get_height(l, &height, err); if (!had_err) { if (gt_double_smaller_double(usable_height - 10 - 2*TEXT_SPACER - arguments->theight, offsetpos + height)) { draw_header(cr, gt_str_get(arguments->text), argv[parsed_args+1], seqid, num_pages, mm_to_pt(arguments->pwidth), mm_to_pt(arguments->pheight), arguments->theight); cairo_show_page(cr); offsetpos = TEXT_SPACER + arguments->theight + TEXT_SPACER; num_pages++; } canvas = gt_canvas_cairo_context_new(sty, cr, offsetpos, mm_to_pt(arguments->pwidth), height, NULL, err); if (!canvas) had_err = -1; offsetpos += height; if (!had_err) had_err = gt_layout_sketch(l, canvas, err); } gt_canvas_delete(canvas); gt_layout_delete(l); gt_diagram_delete(d); if (ct) gt_custom_track_delete(ct); } draw_header(cr, gt_str_get(arguments->text), argv[parsed_args+1], seqid, num_pages, mm_to_pt(arguments->pwidth), mm_to_pt(arguments->pheight), arguments->theight); cairo_show_page(cr); num_pages++; gt_log_log("finished, should be %lu pages\n", num_pages); gt_text_width_calculator_delete(twc); cairo_destroy(cr); cairo_surface_flush(surf); cairo_surface_finish(surf); cairo_surface_destroy(surf); cairo_debug_reset_static_data(); if (bioseq) gt_bioseq_delete(bioseq); gt_style_delete(sty); gt_str_delete(gt_style_file); gt_feature_index_delete(features); } return had_err; }
static cairo_test_status_t cairo_test_for_target (cairo_test_context_t *ctx, const cairo_boilerplate_target_t *target, int dev_offset, cairo_bool_t similar) { cairo_test_status_t status; cairo_surface_t *surface = NULL; cairo_t *cr; const char *empty_str = ""; char *offset_str; char *base_name, *base_path; char *out_png_path; char *ref_path = NULL, *ref_png_path, *cmp_png_path = NULL; char *new_path = NULL, *new_png_path; char *xfail_path = NULL, *xfail_png_path; char *base_ref_png_path; char *base_new_png_path; char *base_xfail_png_path; char *diff_png_path; char *test_filename = NULL, *pass_filename = NULL, *fail_filename = NULL; cairo_test_status_t ret; cairo_content_t expected_content; cairo_font_options_t *font_options; const char *format; cairo_bool_t have_output = FALSE; cairo_bool_t have_result = FALSE; void *closure; double width, height; cairo_bool_t have_output_dir; #if HAVE_MEMFAULT int malloc_failure_iterations = ctx->malloc_failure; int last_fault_count = 0; #endif /* 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 = (char *) empty_str; xasprintf (&base_name, "%s.%s.%s%s%s", ctx->test_name, target->name, format, similar ? ".similar" : "", offset_str); if (offset_str != empty_str) free (offset_str); ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_ref_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_REF_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_new_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_NEW_SUFFIX, CAIRO_TEST_PNG_EXTENSION); base_xfail_png_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, NULL, NULL, format, CAIRO_TEST_XFAIL_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (target->file_extension != NULL) { ref_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_REF_SUFFIX, target->file_extension); new_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_NEW_SUFFIX, target->file_extension); xfail_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, target->name, target->basename, format, CAIRO_TEST_XFAIL_SUFFIX, target->file_extension); } have_output_dir = _cairo_test_mkdir (ctx->output); xasprintf (&base_path, "%s/%s", have_output_dir ? ctx->output : ".", base_name); xasprintf (&out_png_path, "%s" CAIRO_TEST_OUT_PNG, base_path); xasprintf (&diff_png_path, "%s" CAIRO_TEST_DIFF_PNG, base_path); if (ctx->test->requirements != NULL) { const char *required; required = target->is_vector ? "target=raster" : "target=vector"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_vector ? "vector" : "raster", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } required = target->is_recording ? "target=!recording" : "target=recording"; if (strstr (ctx->test->requirements, required) != NULL) { cairo_test_log (ctx, "Error: Skipping for %s target %s\n", target->is_recording ? "recording" : "non-recording", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } } width = ctx->test->width; height = ctx->test->height; if (width && height) { width += dev_offset; height += dev_offset; } #if HAVE_MEMFAULT REPEAT: MEMFAULT_CLEAR_FAULTS (); MEMFAULT_RESET_LEAKS (); ctx->last_fault_count = 0; last_fault_count = MEMFAULT_COUNT_FAULTS (); /* Pre-initialise fontconfig so that the configuration is loaded without * malloc failures (our primary goal is to test cairo fault tolerance). */ #if HAVE_FCINIT FcInit (); #endif MEMFAULT_ENABLE_FAULTS (); #endif have_output = FALSE; have_result = FALSE; /* Run the actual drawing code. */ ret = CAIRO_TEST_SUCCESS; surface = (target->create_surface) (base_path, target->content, width, height, ctx->test->width + 25 * NUM_DEVICE_OFFSETS, ctx->test->height + 25 * NUM_DEVICE_OFFSETS, CAIRO_BOILERPLATE_MODE_TEST, &closure); if (surface == NULL) { cairo_test_log (ctx, "Error: Failed to set %s target\n", target->name); ret = CAIRO_TEST_UNTESTED; goto UNWIND_STRINGS; } #if HAVE_MEMFAULT if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY) { goto REPEAT; } #endif if (cairo_surface_status (surface)) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created an error surface: %s\n", cairo_status_to_string (cairo_surface_status (surface))); ret = CAIRO_TEST_FAILURE; goto UNWIND_STRINGS; } /* Check that we created a surface of the expected type. */ if (cairo_surface_get_type (surface) != target->expected_type) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n", cairo_surface_get_type (surface), target->expected_type); ret = CAIRO_TEST_UNTESTED; goto UNWIND_SURFACE; } /* Check that we created a surface of the expected content, * (ignore the artificial CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value). */ expected_content = cairo_boilerplate_content (target->content); if (cairo_surface_get_content (surface) != expected_content) { MF (MEMFAULT_PRINT_FAULTS ()); cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n", cairo_surface_get_content (surface), expected_content); ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; } if (cairo_surface_set_user_data (surface, &cairo_boilerplate_output_basename_key, base_path, NULL)) { #if HAVE_MEMFAULT cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_SURFACE; #endif } cairo_surface_set_device_offset (surface, dev_offset, dev_offset); cr = cairo_create (surface); if (cairo_set_user_data (cr, &_cairo_test_context_key, (void*) ctx, NULL)) { #if HAVE_MEMFAULT cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); goto REPEAT; #else ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; #endif } if (similar) cairo_push_group_with_content (cr, expected_content); /* 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); cairo_save (cr); alarm (ctx->timeout); status = (ctx->test->draw) (cr, ctx->test->width, ctx->test->height); alarm (0); cairo_restore (cr); if (similar) { cairo_pop_group_to_source (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); } #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); /* repeat test after malloc failure injection */ if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && (status == CAIRO_TEST_NO_MEMORY || cairo_status (cr) == CAIRO_STATUS_NO_MEMORY || cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY)) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif /* Then, check all the different ways it could fail. */ if (status) { cairo_test_log (ctx, "Error: Function under test failed\n"); ret = status; goto UNWIND_CAIRO; } #if HAVE_MEMFAULT if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && MEMFAULT_HAS_FAULTS ()) { VALGRIND_PRINTF ("Unreported memfaults..."); MEMFAULT_PRINT_FAULTS (); } #endif if (target->finish_surface != NULL) { #if HAVE_MEMFAULT /* We need to re-enable faults as most recording-surface processing * is done during cairo_surface_finish(). */ MEMFAULT_CLEAR_FAULTS (); last_fault_count = MEMFAULT_COUNT_FAULTS (); MEMFAULT_ENABLE_FAULTS (); #endif /* also check for infinite loops whilst replaying */ alarm (ctx->timeout); status = target->finish_surface (surface); alarm (0); #if HAVE_MEMFAULT MEMFAULT_DISABLE_FAULTS (); if (ctx->malloc_failure && MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 && status == CAIRO_STATUS_NO_MEMORY) { cairo_destroy (cr); cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } goto REPEAT; } #endif if (status) { cairo_test_log (ctx, "Error: Failed to finish surface: %s\n", cairo_status_to_string (status)); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* Skip image check for tests with no image (width,height == 0,0) */ if (ctx->test->width != 0 && ctx->test->height != 0) { cairo_surface_t *ref_image; cairo_surface_t *test_image; cairo_surface_t *diff_image; buffer_diff_result_t result; cairo_status_t diff_status; if (ref_png_path == NULL) { cairo_test_log (ctx, "Error: Cannot find reference image for %s\n", base_name); /* we may be running this test to generate reference images */ _xunlink (ctx, out_png_path); /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); diff_status = cairo_surface_write_to_png (test_image, out_png_path); cairo_surface_destroy (test_image); if (diff_status) { if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); } have_output = TRUE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (target->file_extension != NULL) { /* compare vector surfaces */ char *filenames[] = { ref_png_path, ref_path, new_png_path, new_path, xfail_png_path, xfail_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s.out%s", base_path, target->file_extension); xasprintf (&pass_filename, "%s.pass%s", base_path, target->file_extension); xasprintf (&fail_filename, "%s.fail%s", base_path, target->file_extension); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (out_png_path, ref_path)) { cairo_test_log (ctx, "Vector surface matches reference.\n"); have_output = FALSE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_path)) { cairo_test_log (ctx, "Vector surface matches current failure.\n"); have_output = FALSE; ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_path)) { cairo_test_log (ctx, "Vector surface matches known failure.\n"); have_output = FALSE; ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, pass_filename)) { /* identical output as last known PASS */ cairo_test_log (ctx, "Vector surface matches last pass.\n"); have_output = TRUE; ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { /* identical output as last known FAIL, fail */ cairo_test_log (ctx, "Vector surface matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ have_output = TRUE; ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } /* be more generous as we may need to use external renderers */ alarm (4 * ctx->timeout); test_image = target->get_image_surface (surface, 0, ctx->test->width, ctx->test->height); alarm (0); if (cairo_surface_status (test_image)) { cairo_test_log (ctx, "Error: Failed to extract image: %s\n", cairo_status_to_string (cairo_surface_status (test_image))); if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS) ret = CAIRO_TEST_CRASHED; else ret = CAIRO_TEST_FAILURE; cairo_surface_destroy (test_image); goto UNWIND_CAIRO; } _xunlink (ctx, out_png_path); diff_status = cairo_surface_write_to_png (test_image, out_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write output image: %s\n", cairo_status_to_string (diff_status)); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } have_output = TRUE; /* binary compare png files (no decompression) */ if (target->file_extension == NULL) { char *filenames[] = { ref_png_path, new_png_path, xfail_png_path, base_ref_png_path, base_new_png_path, base_xfail_png_path, }; xasprintf (&test_filename, "%s", out_png_path); xasprintf (&pass_filename, "%s.pass.png", base_path); xasprintf (&fail_filename, "%s.fail.png", base_path); if (cairo_test_file_is_older (pass_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, pass_filename); } if (cairo_test_file_is_older (fail_filename, filenames, ARRAY_SIZE (filenames))) { _xunlink (ctx, fail_filename); } if (cairo_test_files_equal (test_filename, pass_filename)) { cairo_test_log (ctx, "PNG file exactly matches last pass.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } if (cairo_test_files_equal (test_filename, fail_filename)) { cairo_test_log (ctx, "PNG file exactly matches last fail.\n"); have_result = TRUE; /* presume these were kept around as well */ cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } } else { if (cairo_test_files_equal (out_png_path, ref_png_path)) { cairo_test_log (ctx, "PNG file exactly matches reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, new_png_path)) { cairo_test_log (ctx, "PNG file exactly matches current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly matches known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } } if (cairo_test_files_equal (out_png_path, base_ref_png_path)) { cairo_test_log (ctx, "PNG file exactly reference image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_SUCCESS; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_new_png_path)) { cairo_test_log (ctx, "PNG file exactly current failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_NEW; goto UNWIND_CAIRO; } if (cairo_test_files_equal (out_png_path, base_xfail_png_path)) { cairo_test_log (ctx, "PNG file exactly known failure image.\n"); have_result = TRUE; cairo_surface_destroy (test_image); ret = CAIRO_TEST_XFAILURE; goto UNWIND_CAIRO; } /* first compare against the ideal reference */ ref_image = cairo_test_get_reference_image (ctx, base_ref_png_path, 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", base_ref_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ctx->test->width, ctx->test->height); cmp_png_path = base_ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); _xunlink (ctx, diff_png_path); if (diff_status || image_diff_is_failure (&result, target->error_tolerance)) { /* that failed, so check against the specific backend */ ref_image = cairo_test_get_reference_image (ctx, ref_png_path, 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_png_path, cairo_status_to_string (cairo_surface_status (ref_image))); cairo_surface_destroy (test_image); ret = CAIRO_TEST_FAILURE; goto UNWIND_CAIRO; } cmp_png_path = ref_png_path; diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status) { cairo_test_log (ctx, "Error: Failed to compare images: %s\n", cairo_status_to_string (diff_status)); ret = CAIRO_TEST_FAILURE; } else if (image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_FAILURE; diff_status = cairo_surface_write_to_png (diff_image, diff_png_path); if (diff_status) { cairo_test_log (ctx, "Error: Failed to write differences image: %s\n", cairo_status_to_string (diff_status)); } else { have_result = TRUE; } cairo_test_copy_file (test_filename, fail_filename); } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } } else { /* success */ cairo_test_copy_file (test_filename, pass_filename); } /* If failed, compare against the current image output, * and attempt to detect systematic failures. */ if (ret == CAIRO_TEST_FAILURE) { char *image_out_path; image_out_path = cairo_test_reference_filename (ctx, base_name, ctx->test_name, "image", "image", format, CAIRO_TEST_OUT_SUFFIX, CAIRO_TEST_PNG_EXTENSION); if (image_out_path != NULL) { if (cairo_test_files_equal (out_png_path, image_out_path)) { ret = CAIRO_TEST_XFAILURE; } else { ref_image = cairo_image_surface_create_from_png (image_out_path); if (cairo_surface_status (ref_image) == CAIRO_STATUS_SUCCESS) { diff_status = image_diff (ctx, test_image, ref_image, diff_image, &result); if (diff_status == CAIRO_STATUS_SUCCESS && !image_diff_is_failure (&result, target->error_tolerance)) { ret = CAIRO_TEST_XFAILURE; } cairo_surface_destroy (ref_image); } } free (image_out_path); } } cairo_surface_destroy (test_image); cairo_surface_destroy (diff_image); } if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n", cairo_status_to_string (cairo_status (cr))); ret = CAIRO_TEST_ERROR; goto UNWIND_CAIRO; } UNWIND_CAIRO: free (test_filename); free (fail_filename); free (pass_filename); test_filename = fail_filename = pass_filename = NULL; #if HAVE_MEMFAULT if (ret == CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); #endif cairo_destroy (cr); UNWIND_SURFACE: cairo_surface_destroy (surface); if (target->cleanup) target->cleanup (closure); #if HAVE_MEMFAULT cairo_debug_reset_static_data (); #if HAVE_FCFINI FcFini (); #endif if (MEMFAULT_COUNT_LEAKS () > 0) { if (ret != CAIRO_TEST_FAILURE) MEMFAULT_PRINT_FAULTS (); MEMFAULT_PRINT_LEAKS (); } if (ret == CAIRO_TEST_SUCCESS && --malloc_failure_iterations > 0) goto REPEAT; #endif if (have_output) cairo_test_log (ctx, "OUTPUT: %s\n", out_png_path); if (have_result) { if (cmp_png_path == NULL) { /* XXX presume we matched the normal ref last time */ cmp_png_path = ref_png_path; } cairo_test_log (ctx, "REFERENCE: %s\nDIFFERENCE: %s\n", cmp_png_path, diff_png_path); } UNWIND_STRINGS: free (out_png_path); free (ref_png_path); free (base_ref_png_path); free (ref_path); free (new_png_path); free (base_new_png_path); free (new_path); free (xfail_png_path); free (base_xfail_png_path); free (xfail_path); free (diff_png_path); free (base_path); free (base_name); return ret; }
int main(int argc, char *argv[]) { struct kplotcfg cfg; struct kpair points1[10]; struct kdata *d1; struct kplot *p; cairo_surface_t *surf; size_t i; cairo_t *cr; cairo_status_t st; int rc; rc = EXIT_FAILURE; d1 = NULL; p = NULL; for (i = 0; i < 10; i++) { points1[i].x = time(NULL) + i * 24 * 60 * 60; points1[i].y = arc4random_uniform(100); } kplotcfg_defaults(&cfg); cfg.xticlabelpad = cfg.yticlabelpad = 10.0; cfg.xticlabelrot = M_PI_4; cfg.xticlabelfmt = format; cfg.xaxislabel = "xxxx"; cfg.yaxislabel = "yyyy"; cfg.yaxislabelrot = M_PI_2 * 3.0; if (NULL == (d1 = kdata_array_alloc(points1, 10))) { perror(NULL); goto out; } else if (NULL == (p = kplot_alloc(&cfg))) { perror(NULL); goto out; } else if ( ! kplot_attach_data(p, d1, KPLOT_POINTS, NULL)) { perror(NULL); goto out; } kdata_destroy(d1); d1 = NULL; surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 600, 400); st = cairo_surface_status(surf); if (CAIRO_STATUS_SUCCESS != st) { fprintf(stderr, "%s", cairo_status_to_string(st)); cairo_surface_destroy(surf); kplot_free(p); return(EXIT_FAILURE); } cr = cairo_create(surf); cairo_surface_destroy(surf); st = cairo_status(cr); if (CAIRO_STATUS_SUCCESS != st) { fprintf(stderr, "%s", cairo_status_to_string(st)); cairo_destroy(cr); kplot_free(p); return(EXIT_FAILURE); } cairo_set_font_size(cr, 14.0); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_rectangle(cr, 0.0, 0.0, 600.0, 400.0); cairo_fill(cr); kplot_draw(p, 600.0, 400.0, cr); st = cairo_surface_write_to_png (cairo_get_target(cr), "example2.png"); if (CAIRO_STATUS_SUCCESS != st) { fprintf(stderr, "%s", cairo_status_to_string(st)); cairo_destroy(cr); kplot_free(p); return(EXIT_FAILURE); } cairo_destroy(cr); rc = EXIT_SUCCESS; out: kplot_free(p); kdata_destroy(d1); #ifdef __APPLE__ cairo_debug_reset_static_data(); #endif return(rc); }