Пример #1
0
void
gfxContext::PushGroupAndCopyBackground(gfxASurface::gfxContentType content)
{
    if (content == gfxASurface::CONTENT_COLOR_ALPHA &&
        !(GetFlags() & FLAG_DISABLE_COPY_BACKGROUND)) {
        nsRefPtr<gfxASurface> s = CurrentSurface();
        if ((s->GetAllowUseAsSource() || s->GetType() == gfxASurface::SurfaceTypeTee) &&
            (s->GetContentType() == gfxASurface::CONTENT_COLOR ||
             s->GetOpaqueRect().Contains(GetRoundOutDeviceClipExtents(this)))) {
            cairo_push_group_with_content(mCairo, CAIRO_CONTENT_COLOR);
            nsRefPtr<gfxASurface> d = CurrentSurface();

            if (d->GetType() == gfxASurface::SurfaceTypeTee) {
                NS_ASSERTION(s->GetType() == gfxASurface::SurfaceTypeTee, "Mismatched types");
                nsAutoTArray<nsRefPtr<gfxASurface>,2> ss;
                nsAutoTArray<nsRefPtr<gfxASurface>,2> ds;
                static_cast<gfxTeeSurface*>(s.get())->GetSurfaces(&ss);
                static_cast<gfxTeeSurface*>(d.get())->GetSurfaces(&ds);
                NS_ASSERTION(ss.Length() == ds.Length(), "Mismatched lengths");
                gfxPoint translation = d->GetDeviceOffset() - s->GetDeviceOffset();
                for (PRUint32 i = 0; i < ss.Length(); ++i) {
                    CopySurface(ss[i], ds[i], translation);
                }
            } else {
                CopySurface(s, d, gfxPoint(0, 0));
            }
            d->SetOpaqueRect(s->GetOpaqueRect());
            return;
        }
    }
    cairo_push_group_with_content(mCairo, (cairo_content_t) content);
}
Пример #2
0
static VALUE
cr_push_group (int argc, VALUE *argv, VALUE self)
{
  VALUE result = Qnil;
  VALUE content, pop_to_source;
  rb_scan_args (argc, argv, "02", &content, &pop_to_source);

  if (NIL_P(content))
    cairo_push_group (_SELF);
  else
    cairo_push_group_with_content (_SELF, RVAL2CRCONTENT(content));
  cr_check_status (_SELF);

  if (rb_block_given_p ())
    {
      int state = 0;

      if (NIL_P (pop_to_source))
        pop_to_source = Qtrue;

      result = rb_protect (rb_yield, self, &state);
      if (cairo_status(_SELF) == CAIRO_STATUS_SUCCESS)
        {
          if (RVAL2CBOOL (pop_to_source))
            cr_pop_group_to_source (self);
          else
            result = cr_pop_group (self);
        }

      if (state)
        rb_jump_tag (state);
    }

  return result;
}
Пример #3
0
static cairo_bool_t
cairo_test_target_has_similar (const cairo_test_t *test, cairo_boilerplate_target_t *target)
{
    cairo_surface_t *surface;
    cairo_bool_t has_similar = FALSE;

    /* ignore image intermediate targets */
    if (target->expected_type == CAIRO_SURFACE_TYPE_IMAGE)
	return FALSE;

    if (getenv ("CAIRO_TEST_IGNORE_SIMILAR"))
	return FALSE;

    surface = (target->create_surface) (test->name,
					target->content,
					test->width,
					test->height,
					CAIRO_BOILERPLATE_MODE_TEST,
					&target->closure);
    if (surface != NULL) {
	cairo_t * cr = cairo_create (surface);
	cairo_surface_t *similar;
	cairo_push_group_with_content (cr, target->content);
	similar = cairo_get_group_target (cr);
	has_similar = cairo_surface_get_type (similar) == cairo_surface_get_type (surface);

	cairo_destroy (cr);
	cairo_surface_destroy (surface);

	if (target->cleanup)
	    target->cleanup (target->closure);
    }

    return has_similar;
}
Пример #4
0
static int cairo_push_group_with_content_l( lua_State* L )
{
  lua_cairo_t* lc = lua_cairo_check( L, 1 );

  cairo_push_group_with_content( lc->cairo, luaL_checkoption( L, 2, "color", cairo_content_lst ) );

  return( 0 );
}
Пример #5
0
static int
cr_push_group (lua_State *L) {
    cairo_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_CONTEXT);
    cairo_content_t content = CAIRO_CONTENT_COLOR_ALPHA;
    if (!lua_isnoneornil(L, 2))
        content = content_from_lua(L, 2);
    cairo_push_group_with_content(*obj, content);
    return 0;
}
Пример #6
0
static PyObject *
pycairo_push_group_with_content (PycairoContext *o, PyObject *args) {
  cairo_content_t content;

  if (!PyArg_ParseTuple(args, "i:Context.push_group_with_content",
			&content))
    return NULL;
  cairo_push_group_with_content (o->ctx, content);
  RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx);
  Py_RETURN_NONE;
}
Пример #7
0
static cairo_test_status_t
draw_func (cairo_t *cr, int width, int height)
{
    cairo_rectangle_t region[4];
    const cairo_test_context_t *ctx;
    int i, j;

    ctx = cairo_test_get_context (cr);

    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR);
    draw (ctx, cr, NULL, 0);
    for (i = 0; i < NLOOPS; i++) {
	for (j = 0; j < NLOOPS; j++) {
	    region[0].x = i * SIZE / NLOOPS;
	    region[0].y = i * SIZE / NLOOPS;
	    region[0].width = SIZE / 4;
	    region[0].height = SIZE / 4;

	    region[1].x = j * SIZE / NLOOPS;
	    region[1].y = j * SIZE / NLOOPS;
	    region[1].width = SIZE / 4;
	    region[1].height = SIZE / 4;

	    region[2].x = i * SIZE / NLOOPS;
	    region[2].y = j * SIZE / NLOOPS;
	    region[2].width = SIZE / 4;
	    region[2].height = SIZE / 4;

	    region[3].x = j * SIZE / NLOOPS;
	    region[3].y = i * SIZE / NLOOPS;
	    region[3].width = SIZE / 4;
	    region[3].height = SIZE / 4;

	    draw (ctx, cr, region, 4);
	}
    }

    cairo_pop_group_to_source (cr);
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint (cr);

    return CAIRO_TEST_SUCCESS;
}
static void
selection_render_mask (Selection *selection)
{
  cairo_t *cr;

  cr = gdk_cairo_create (gtk_widget_get_window (selection->shell->canvas));

  cairo_push_group_with_content (cr, CAIRO_CONTENT_ALPHA);

  cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
  cairo_set_line_width (cr, 1.0);

  gimp_cairo_add_segments (cr,
                           selection->segs_in,
                           selection->n_segs_in);
  cairo_stroke (cr);

  selection->segs_in_mask = cairo_pop_group (cr);

  cairo_destroy (cr);
}
static cairo_test_status_t
draw_with_extend (cairo_t *cr, int w, int h, cairo_extend_t extend)
{
    cairo_pattern_t *pattern;
    cairo_set_source_rgb (cr, 1,1,1);
    cairo_paint (cr);

    cairo_save (cr);

    /* When the destination surface is created by cairo-test-suite to
     * test device-offset, it is bigger than w x h. This test expects
     * the group to have a size which is exactly w x h, so it must
     * clip to the this rectangle to guarantee that the group will
     * have the correct size.
     */
    cairo_rectangle (cr, 0, 0, w, h);
    cairo_clip (cr);

    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR); {
        /* A two by two checkerboard with black, red and yellow
         * cells. */
        cairo_set_source_rgb (cr, 1,0,0);
        cairo_rectangle (cr, w/2, 0, w-w/2, h/2);
        cairo_fill (cr);
        cairo_set_source_rgb (cr, 1,1,0);
        cairo_rectangle (cr, 0, h/2, w/2, h-h/2);
        cairo_fill (cr);
    }
    pattern = cairo_pop_group (cr);
    cairo_pattern_set_extend(pattern, extend);

    cairo_restore (cr);

    cairo_scale (cr, 0.5, 0.5);
    cairo_set_source (cr, pattern);
    cairo_paint (cr);

    cairo_pattern_destroy (pattern);
    return CAIRO_TEST_SUCCESS;
}
Пример #10
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_pattern_t *gradient, *image;

    cairo_set_source_rgb (cr, 1,1,1);
    cairo_paint (cr);

    cairo_translate (cr, PAD, PAD);

    /* clip to the unit size */
    cairo_rectangle (cr, 0, 0,
                     UNIT_SIZE, UNIT_SIZE);
    cairo_clip (cr);

    cairo_rectangle (cr, 0, 0,
                     UNIT_SIZE, UNIT_SIZE);
    cairo_set_source_rgba (cr, 0, 0, 0, 1);
    cairo_set_line_width (cr, 2);
    cairo_stroke (cr);

    /* start a group */
    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR);

    /* draw a gradient background */
    cairo_save (cr);
    cairo_translate (cr, INNER_PAD, INNER_PAD);
    cairo_new_path (cr);
    cairo_rectangle (cr, 0, 0,
                     UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2));
    gradient = cairo_pattern_create_linear (UNIT_SIZE - (INNER_PAD*2), 0,
                                            UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2));
    cairo_pattern_add_color_stop_rgba (gradient, 0.0, 0.3, 0.3, 0.3, 1.0);
    cairo_pattern_add_color_stop_rgba (gradient, 1.0, 1.0, 1.0, 1.0, 1.0);
    cairo_set_source (cr, gradient);
    cairo_pattern_destroy (gradient);
    cairo_fill (cr);
    cairo_restore (cr);

    /* draw diamond */
    cairo_move_to (cr, UNIT_SIZE / 2, 0);
    cairo_line_to (cr, UNIT_SIZE    , UNIT_SIZE / 2);
    cairo_line_to (cr, UNIT_SIZE / 2, UNIT_SIZE);
    cairo_line_to (cr, 0            , UNIT_SIZE / 2);
    cairo_close_path (cr);
    cairo_set_source_rgba (cr, 0, 0, 1, 1);
    cairo_fill (cr);

    /* draw circle */
    cairo_arc (cr,
               UNIT_SIZE / 2, UNIT_SIZE / 2,
               UNIT_SIZE / 3.5,
               0, M_PI * 2);
    cairo_set_source_rgba (cr, 1, 0, 0, 1);
    cairo_fill (cr);

    /* and put the image on top */
    cairo_translate (cr, UNIT_SIZE/2 - 8, UNIT_SIZE/2 - 8);
    image = argb32_source ();
    cairo_set_source (cr, image);
    cairo_pattern_destroy (image);
    cairo_paint (cr);

    cairo_pop_group_to_source (cr);
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint (cr);

    return CAIRO_TEST_SUCCESS;
}
Пример #11
0
IoObject *IoCairoContext_pushGroupWithContent(IoCairoContext *self, IoObject *locals, IoMessage *m)
{
	cairo_push_group_with_content(CONTEXT(self), IoMessage_locals_intArgAt_(m, locals, 0));
	CHECK_STATUS(self);
	return self;
}
Пример #12
0
/* adapted from pdf2png.c */
static const char *
_poppler_render_page (const char *filename,
		      const char *page_label,
		      cairo_surface_t **surface_out)
{
    PopplerDocument *document;
    PopplerPage *page;
    double width, height;
    GError *error = NULL;
    gchar *absolute, *uri;
    cairo_surface_t *surface;
    cairo_t *cr;
    cairo_status_t status;

    if (g_path_is_absolute (filename)) {
	absolute = g_strdup (filename);
    } else {
	gchar *dir = g_get_current_dir ();
	absolute = g_build_filename (dir, filename, (gchar *) 0);
	g_free (dir);
    }

    uri = g_filename_to_uri (absolute, NULL, &error);
    g_free (absolute);
    if (uri == NULL)
	return error->message; /* XXX g_error_free (error) */

    document = poppler_document_new_from_file (uri, NULL, &error);
    g_free (uri);
    if (document == NULL)
	return error->message; /* XXX g_error_free (error) */

    page = poppler_document_get_page_by_label (document, page_label);
    g_object_unref (document);
    if (page == NULL)
	return "page not found";

    poppler_page_get_size (page, &width, &height);

    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
    cr = cairo_create (surface);

    cairo_set_source_rgb (cr, 1., 1., 1.);
    cairo_paint (cr);
    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);

    poppler_page_render (page, cr);
    g_object_unref (page);

    cairo_pop_group_to_source (cr);
    cairo_paint (cr);

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

    if (status) {
	cairo_surface_destroy (surface);
	return  cairo_status_to_string (status);
    }

    *surface_out = surface;
    return NULL;
}
Пример #13
0
void
cairo_perf_run (cairo_perf_t	   *perf,
		const char	   *name,
		cairo_perf_func_t   perf_func,
		cairo_count_func_t  count_func)
{
    static cairo_bool_t first_run = TRUE;
    unsigned int i, similar, has_similar;
    cairo_time_t *times;
    cairo_stats_t stats = {0.0, 0.0};
    int low_std_dev_count;

    if (perf->list_only) {
	printf ("%s\n", name);
	return;
    }

    if (first_run) {
	if (perf->raw) {
	    printf ("[ # ] %s.%-s %s %s %s ...\n",
		    "backend", "content", "test-size", "ticks-per-ms", "time(ticks)");
	}

	if (perf->summary) {
	    fprintf (perf->summary,
		     "[ # ] %8s.%-4s %28s %8s %8s %5s %5s %s %s\n",
		     "backend", "content", "test-size", "min(ticks)", "min(ms)", "median(ms)",
		     "stddev.", "iterations", "overhead");
	}
	first_run = FALSE;
    }

    times = perf->times;

    if (getenv ("CAIRO_PERF_OUTPUT") != NULL) { /* check output */
	char *filename;
	cairo_status_t status;

	xasprintf (&filename, "%s.%s.%s.%d.out.png",
		   name, perf->target->name,
		   _content_to_string (perf->target->content, 0),
		   perf->size);
	cairo_save (perf->cr);
	perf_func (perf->cr, perf->size, perf->size, 1);
	cairo_restore (perf->cr);
	status = cairo_surface_write_to_png (cairo_get_target (perf->cr), filename);
	if (status) {
	    fprintf (stderr, "Failed to generate output check '%s': %s\n",
		     filename, cairo_status_to_string (status));
	    return;
	}

	free (filename);
    }

    has_similar = cairo_perf_has_similar (perf);
    for (similar = 0; similar <= has_similar; similar++) {
	unsigned loops;

	if (perf->summary) {
	    fprintf (perf->summary,
		     "[%3d] %8s.%-5s %26s.%-3d ",
		     perf->test_number, perf->target->name,
		     _content_to_string (perf->target->content, similar),
		     name, perf->size);
	    fflush (perf->summary);
	}

	/* We run one iteration in advance to warm caches and calibrate. */
	cairo_perf_yield ();
	if (similar)
	    cairo_push_group_with_content (perf->cr,
					   cairo_boilerplate_content (perf->target->content));
	else
	    cairo_save (perf->cr);
	perf_func (perf->cr, perf->size, perf->size, 1);
	loops = cairo_perf_calibrate (perf, perf_func);
	if (similar)
	    cairo_pattern_destroy (cairo_pop_group (perf->cr));
	else
	    cairo_restore (perf->cr);

	low_std_dev_count = 0;
	for (i =0; i < perf->iterations; i++) {
	    cairo_perf_yield ();
	    if (similar)
		cairo_push_group_with_content (perf->cr,
					       cairo_boilerplate_content (perf->target->content));
	    else
		cairo_save (perf->cr);
	    times[i] = perf_func (perf->cr, perf->size, perf->size, loops) ;
	    if (similar)
		cairo_pattern_destroy (cairo_pop_group (perf->cr));
	    else
		cairo_restore (perf->cr);
	    if (perf->raw) {
		if (i == 0)
		    printf ("[*] %s.%s %s.%d %g",
			    perf->target->name,
			    _content_to_string (perf->target->content, similar),
			    name, perf->size,
			    _cairo_time_to_double (_cairo_time_from_s (1.)) / 1000.);
		printf (" %lld", (long long) (times[i] / (double) loops));
	    } else if (! perf->exact_iterations) {
		if (i > 0) {
		    _cairo_stats_compute (&stats, times, i+1);

		    if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV) {
			low_std_dev_count++;
			if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT)
			    break;
		    } else {
			low_std_dev_count = 0;
		    }
		}
	    }
	}

	if (perf->raw)
	    printf ("\n");

	if (perf->summary) {
	    _cairo_stats_compute (&stats, times, i);
	    if (count_func != NULL) {
		double count = count_func (perf->cr, perf->size, perf->size);
		fprintf (perf->summary,
			 "%.3f [%10lld/%d] %#8.3f %#8.3f %#5.2f%% %3d: %.2f\n",
			 stats.min_ticks /(double) loops,
			 (long long) stats.min_ticks, loops,
			 _cairo_time_to_s (stats.min_ticks) * 1000.0 / loops,
			 _cairo_time_to_s (stats.median_ticks) * 1000.0 / loops,
			 stats.std_dev * 100.0, stats.iterations,
			 count / _cairo_time_to_s (stats.min_ticks));
	    } else {
		fprintf (perf->summary,
			 "%.3f [%10lld/%d] %#8.3f %#8.3f %#5.2f%% %3d\n",
			 stats.min_ticks /(double) loops,
			 (long long) stats.min_ticks, loops,
			 _cairo_time_to_s (stats.min_ticks) * 1000.0 / loops,
			 _cairo_time_to_s (stats.median_ticks) * 1000.0 / loops,
			 stats.std_dev * 100.0, stats.iterations);
	    }
	    fflush (perf->summary);
	}

	perf->test_number++;
    }
}
Пример #14
0
void CairoGroup::push_with_content(cairo_content_t content) {
    cairo_push_group_with_content(ct, content);
    pushed = true;
}
Пример #15
0
static cairo_test_status_t
cairo_test_for_target (cairo_test_t			 *test,
		       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;
    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%s",
	       test->name,
	       target->name,
	       format,
	       similar ? "-similar" : "",
	       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%s",
	       test->name,
	       target->name,
	       format,
	       similar ? "-similar" : "",
	       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);
    if (similar)
	cairo_push_group_with_content (cr, target->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);
    status = (test->draw) (cr, test->width, test->height);
    cairo_restore (cr);

    /* 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 (similar) {
	cairo_pop_group_to_source (cr);
	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
	cairo_paint (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) {
	buffer_diff_result_t result;
	cairo_status_t diff_status;
	xunlink (png_name);
	(target->write_to_png) (surface, png_name);

	cairo_test_log ("OUTPUT: %s\n", 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 ("REFERENCE: %s\n", ref_name);
	cairo_test_log ("DIFFERENCE: %s\n", diff_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;
}
Пример #16
0
void
cairo_perf_run (cairo_perf_t		*perf,
		const char		*name,
		cairo_perf_func_t	 perf_func)
{
    static cairo_bool_t first_run = TRUE;
    unsigned int i, similar, has_similar;
    cairo_perf_ticks_t *times;
    cairo_stats_t stats = {0.0, 0.0};
    int low_std_dev_count;

    if (perf->list_only) {
	printf ("%s\n", name);
	return;
    }

    if (first_run) {
	if (perf->raw)
	    printf ("[ # ] %s-%-s %s %s %s ...\n",
		    "backend", "content", "test-size", "ticks-per-ms", "time(ticks)");
	else
	    printf ("[ # ] %8s-%-4s %28s %8s %8s %5s %5s %s\n",
		    "backend", "content", "test-size", "min(ticks)", "min(ms)", "median(ms)",
		    "stddev.", "iterations");
	first_run = FALSE;
    }

    times = perf->times;

    has_similar = cairo_perf_has_similar (perf);
    for (similar = 0; similar <= has_similar; similar++) {
	/* We run one iteration in advance to warm caches, etc. */
	cairo_perf_yield ();
	if (similar)
	    cairo_push_group_with_content (perf->cr,
		                           cairo_boilerplate_content (perf->target->content));
	(perf_func) (perf->cr, perf->size, perf->size);
	if (similar)
	    cairo_pattern_destroy (cairo_pop_group (perf->cr));

	low_std_dev_count = 0;
	for (i =0; i < perf->iterations; i++) {
	    cairo_perf_yield ();
	    if (similar)
		cairo_push_group_with_content (perf->cr,
			                       cairo_boilerplate_content (perf->target->content));
	    times[i] = (perf_func) (perf->cr, perf->size, perf->size);
	    if (similar)
		cairo_pattern_destroy (cairo_pop_group (perf->cr));

	    if (perf->raw) {
		if (i == 0)
		    printf ("[*] %s-%s %s-%d %g",
			    perf->target->name,
			    _content_to_string (perf->target->content, similar),
			    name, perf->size,
			    cairo_perf_ticks_per_second () / 1000.0);
		printf (" %lld", (long long) times[i]);
	    } else if (! perf->exact_iterations) {
		if (i > 0) {
		    _cairo_stats_compute (&stats, times, i+1);

		    if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV)
		    {
			low_std_dev_count++;
			if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT)
			    break;
		    } else {
			low_std_dev_count = 0;
		    }
		}
	    }
	}

	if (perf->raw) {
	    printf ("\n");
	} else {
	    _cairo_stats_compute (&stats, times, i);
	    printf ("[%3d] %8s-%-5s %26s-%-3d ",
		    perf->test_number, perf->target->name,
		    _content_to_string (perf->target->content, similar),
		    name, perf->size);

	    printf ("%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
		    (long long) stats.min_ticks,
		    (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
		    (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
		    stats.std_dev * 100.0, stats.iterations);
	}

	perf->test_number++;
    }
}
Пример #17
0
void Context::pushGroupWithContent( int32_t content )
{
	cairo_push_group_with_content( mCairo, static_cast<cairo_content_t>( content ) );
}
Пример #18
0
cairo_test_similar_t
cairo_test_target_has_similar (const cairo_test_context_t *ctx,
			       const cairo_boilerplate_target_t *target)
{
    cairo_surface_t *surface;
    cairo_test_similar_t has_similar;
    cairo_t * cr;
    cairo_surface_t *similar;
    cairo_status_t status;
    void *closure;
    char *path;

    /* ignore image intermediate targets */
    if (target->expected_type == CAIRO_SURFACE_TYPE_IMAGE)
	return DIRECT;

    if (getenv ("CAIRO_TEST_IGNORE_SIMILAR"))
	return DIRECT;

    xasprintf (&path, "%s/%s",
	       _cairo_test_mkdir (ctx->output) ? ctx->output : ".",
	       ctx->test_name);

    has_similar = DIRECT;
    do {
	do {
	    surface = (target->create_surface) (path,
						target->content,
						ctx->test->width,
						ctx->test->height,
						ctx->test->width + 25 * NUM_DEVICE_OFFSETS,
						ctx->test->height + 25 * NUM_DEVICE_OFFSETS,
						CAIRO_BOILERPLATE_MODE_TEST,
						&closure);
	    if (surface == NULL)
		goto out;
	} while (cairo_test_malloc_failure (ctx, cairo_surface_status (surface)));

	if (cairo_surface_status (surface))
	    goto out;

	cr = cairo_create (surface);
	cairo_push_group_with_content (cr,
				       cairo_boilerplate_content (target->content));
	similar = cairo_get_group_target (cr);
	status = cairo_surface_status (similar);

	if (cairo_surface_get_type (similar) == cairo_surface_get_type (surface))
	    has_similar = SIMILAR;
	else
	    has_similar = DIRECT;

	cairo_destroy (cr);
	cairo_surface_destroy (surface);

	if (target->cleanup)
	    target->cleanup (closure);
    } while (! has_similar && cairo_test_malloc_failure (ctx, status));
out:
    free (path);

    return has_similar;
}
Пример #19
0
	void lime_cairo_push_group_with_content (double handle, int content) {
		
		cairo_push_group_with_content ((cairo_t*)(intptr_t)handle, (cairo_content_t)content);
		
	}
Пример #20
0
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;
}
Пример #21
0
	void lime_cairo_push_group_with_content (value handle, int content) {
		
		cairo_push_group_with_content ((cairo_t*)val_data (handle), (cairo_content_t)content);
		
	}
Пример #22
0
void
gfxContext::PushGroup(gfxASurface::gfxContentType content)
{
    cairo_push_group_with_content(mCairo, (cairo_content_t) content);
}