[cairo-commit] 6 commits - perf/cairo-perf-diff.c perf/.gitignore
perf/Makefile.am src/cairo-pen.c test/infinite-join.c
test/Makefile.am
Carl Worth
cworth at kemper.freedesktop.org
Wed Oct 18 15:07:01 PDT 2006
perf/.gitignore | 1
perf/Makefile.am | 6
perf/cairo-perf-diff.c | 478 +++++++++++++++++++++++++++++++++++++++++++++++++
src/cairo-pen.c | 7
test/Makefile.am | 1
test/infinite-join.c | 80 ++++++++
6 files changed, 571 insertions(+), 2 deletions(-)
New commits:
diff-tree e21c155e73569f6533dd01bdd7ec62461e7f215f (from parents)
Merge: a53eabf0a505bcf01e52af1b47b194a482eddf51 10cd23d51fbfc99d6e3e401440eebb56df3b3327
Author: Carl Worth <cworth at cworth.org>
Date: Wed Oct 18 15:03:04 2006 -0700
Merge branch '8379' into cairo
diff --cc test/Makefile.am
index c513949,1630a4e..f5d0667
@@@ -39,10 -38,9 +39,11 @@@
font-matrix-translation \
glyph-cache-pressure \
get-and-set \
+get-clip \
get-group-target \
+get-path-extents \
gradient-alpha \
+ infinite-join \
leaky-dash \
leaky-polygon \
line-width \
diff-tree 10cd23d51fbfc99d6e3e401440eebb56df3b3327 (from 5b7a7f39ad8b726e9ee582bcd10500a1e5b16554)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Sep 21 15:17:59 2006 -0700
Fix infinite-join test case (bug #8379)
The trick for this was to carefully ensure that the pen always has
at least 4 vertices. There was a previous attempt at this in the
code already but the test case had a combination of matrix and radius
that resulted in a value that was just able to sneak past the previous
check.
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index 3d42314..0e24f2d 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -270,7 +270,12 @@ _cairo_pen_vertices_needed (double t
/* number of vertices must be even */
if (num_vertices % 2)
num_vertices++;
+
+ /* And we must always have at least 4 vertices. */
+ if (num_vertices < 4)
+ num_vertices = 4;
}
+
return num_vertices;
}
diff-tree 5b7a7f39ad8b726e9ee582bcd10500a1e5b16554 (from 5492a7c7618a747130b844a509fb79b886f1bc54)
Author: Carl Worth <cworth at cworth.org>
Date: Wed Oct 18 15:01:58 2006 -0700
test/infinite-join: Modify to draw something visible, and make the output a more reasonable size.
The modification was performed with care to ensure that the bug
is still exercised. Also, reference images are added.
diff --git a/test/infinite-join.c b/test/infinite-join.c
index fffb386..74d4206 100644
--- a/test/infinite-join.c
+++ b/test/infinite-join.c
@@ -38,13 +38,18 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"infinite-join",
"Test case for infinite loop when stroking with round joins",
- 120, 70,
+ 8, 8,
draw
};
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
+ /* Paint white, then draw in black. */
+ cairo_set_source_rgb (cr, 1, 1, 1); /* white */
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
/* scaling 2 times causes a slight rounding error in the ctm.
@@ -55,11 +60,13 @@ draw (cairo_t *cr, int width, int height
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_line_width (cr, 20);
+ cairo_translate (cr, -18300, -13200);
+
cairo_new_path (cr);
cairo_move_to (cr, 18928, 13843);
- cairo_line_to (cr, -6928, 13843);
- cairo_line_to (cr, -6928, -6842);
- cairo_line_to (cr, 18928, -6842);
+ cairo_line_to (cr, 18500, 13843);
+ cairo_line_to (cr, 18500, 13400);
+ cairo_line_to (cr, 18928, 13400);
cairo_line_to (cr, 18928, 13843);
cairo_stroke (cr);
diff-tree a53eabf0a505bcf01e52af1b47b194a482eddf51 (from 5c7798a646ecad59dfabac1f9afb96006470054e)
Author: Carl Worth <cworth at cworth.org>
Date: Wed Oct 18 12:14:38 2006 -0700
Add cairo-perf-diff program for comparing two cairo-perf reports.
diff --git a/perf/.gitignore b/perf/.gitignore
index 66b1d8f..5881588 100644
--- a/perf/.gitignore
+++ b/perf/.gitignore
@@ -1,4 +1,5 @@
cairo-perf
+cairo-perf-diff
*.o
*.exe
*.manifest
diff --git a/perf/Makefile.am b/perf/Makefile.am
index ef6dc73..54d3557 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -12,7 +12,7 @@ INCLUDES = \
-I$(top_srcdir)/src \
$(CAIRO_CFLAGS)
-noinst_PROGRAMS = cairo-perf
+noinst_PROGRAMS = cairo-perf cairo-perf-diff
cairo_perf_SOURCES = \
cairo-perf.c \
@@ -31,9 +31,11 @@ else
cairo_perf_SOURCES += cairo-perf-posix.c
endif
+cairo_perf_diff_SOURCES = \
+ cairo-perf-diff.c
+
LDADD = $(top_builddir)/boilerplate/libcairoboilerplate.la \
$(top_builddir)/src/libcairo.la
perf: cairo-perf
./cairo-perf
-
diff --git a/perf/cairo-perf-diff.c b/perf/cairo-perf-diff.c
new file mode 100644
index 0000000..acbef43
--- /dev/null
+++ b/perf/cairo-perf-diff.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Authors: Carl Worth <cworth at cworth.org>
+ */
+
+/* We use _GNU_SOURCE for getline. If someone wants to avoid that
+ * dependence they could conditionally provide a custom implementation
+ * of getline instead. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <math.h>
+
+typedef struct _test_report {
+ int id;
+ char *backend;
+ char *content;
+ char *name;
+ int size;
+ double ticks;
+ double time;
+ double std_dev;
+ int iterations;
+} test_report_t;
+
+typedef struct _test_diff {
+ test_report_t *old;
+ test_report_t *new;
+ double speedup;
+} test_diff_t;
+
+typedef struct _cairo_perf_report {
+ const char *name;
+ test_report_t *tests;
+ int tests_size;
+ int tests_count;
+} cairo_perf_report_t;
+
+typedef enum {
+ TEST_REPORT_STATUS_SUCCESS,
+ TEST_REPORT_STATUS_COMMENT,
+ TEST_REPORT_STATUS_ERROR
+} test_report_status_t;
+
+/* Ad-hoc parsing, macros with a strong dependence on the calling
+ * context, and plenty of other ugliness is here. But at least it's
+ * not perl... */
+#define parse_error(...) fprintf(stderr, __VA_ARGS__); return TEST_REPORT_STATUS_ERROR;
+#define skip_char(c) \
+do { \
+ if (*s && *s == (c)) { \
+ s++; \
+ } else { \
+ parse_error ("expected '%c' but found '%c'", c, *s); \
+ } \
+} while (0)
+#define skip_space() while (*s && (*s == ' ' || *s == '\t')) s++;
+#define parse_int(result) \
+do { \
+ (result) = strtol (s, &end, 10); \
+ if (*s && end != s) { \
+ s = end; \
+ } else { \
+ parse_error("expected integer but found %s", s); \
+ } \
+} while (0)
+#define parse_double(result) \
+do { \
+ (result) = strtod (s, &end); \
+ if (*s && end != s) { \
+ s = end; \
+ } else { \
+ parse_error("expected floating-point value but found %s", s); \
+ } \
+} while (0)
+/* Here a string is simply a sequence of non-whitespace */
+#define parse_string(result) \
+do { \
+ for (end = s; *end; end++) \
+ if (isspace (*end)) \
+ break; \
+ (result) = strndup (s, end - s); \
+ if ((result) == NULL) { \
+ fprintf (stderr, "Out of memory.\n"); \
+ exit (1); \
+ } \
+ s = end; \
+} while (0)
+
+static test_report_status_t
+test_report_parse (test_report_t *report, char *line)
+{
+ char *end;
+ char *s = line;
+
+ /* The code here looks funny unless you understand that these are
+ * all macro calls, (and then the code just looks sick). */
+ if (*s == '\n')
+ return TEST_REPORT_STATUS_COMMENT;
+
+ skip_char ('[');
+ skip_space ();
+ if (*s == '#')
+ return TEST_REPORT_STATUS_COMMENT;
+ parse_int (report->id);
+ skip_char (']');
+
+ skip_space ();
+
+ parse_string (report->backend);
+ end = strrchr (report->backend, '-');
+ if (*end)
+ *end++ = '\0';
+ report->content = end;
+
+ skip_space ();
+
+ parse_string (report->name);
+ end = strrchr (report->name, '-');
+ if (*end)
+ *end++ = '\0';
+ report->size = atoi (end);
+
+ skip_space ();
+
+ parse_double (report->ticks);
+
+ skip_space ();
+
+ parse_double (report->time);
+
+ skip_space ();
+
+ parse_double (report->std_dev);
+ report->std_dev /= 100.0;
+ skip_char ('%');
+
+ skip_space ();
+
+ parse_int (report->iterations);
+
+ skip_space ();
+ skip_char ('\n');
+
+ return TEST_REPORT_STATUS_SUCCESS;
+}
+
+static void
+cairo_perf_report_load (cairo_perf_report_t *report, const char *filename)
+{
+ FILE *file;
+ test_report_status_t status;
+ int line_number = 0;
+ char *line = NULL;
+ size_t line_size = 0;
+
+ report->name = filename;
+ report->tests = NULL;
+ report->tests_size = 0;
+ report->tests_count = 0;
+
+ file = fopen (filename, "r");
+ if (file == NULL) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ while (1) {
+ if (report->tests_count == report->tests_size) {
+ report->tests_size = report->tests_size ? 2 * report->tests_size : 16;
+ report->tests = realloc (report->tests,
+ report->tests_size * sizeof (test_report_t));
+ if (report->tests == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+ }
+
+ line_number++;
+ if (getline (&line, &line_size, file) == -1)
+ break;
+
+ status = test_report_parse (&report->tests[report->tests_count], line);
+ if (status == TEST_REPORT_STATUS_ERROR)
+ fprintf (stderr, "Ignoring unrecognized line %d of %s:\n%s",
+ line_number, filename, line);
+ if (status == TEST_REPORT_STATUS_SUCCESS)
+ report->tests_count++;
+ /* Do nothing on TEST_REPORT_STATUS_COMMENT */
+ }
+
+ if (line)
+ free (line);
+}
+
+static int
+test_diff_cmp (const void *a, const void *b)
+{
+ const test_diff_t *a_diff = a;
+ const test_diff_t *b_diff = b;
+ double a_change, b_change;
+
+ a_change = a_diff->speedup;
+ b_change = b_diff->speedup;
+
+ /* First make all speedups come before all slowdowns. */
+ if (a_change > 1.0 && b_change < 1.0)
+ return -1;
+ if (a_change < 1.0 && b_change > 1.0)
+ return 1;
+
+ /* Then, within each, sort by magnitude of speed change */
+ if (a_change < 1.0)
+ a_change = 1.0 / a_change;
+
+ if (b_change < 1.0)
+ b_change = 1.0 / b_change;
+
+ /* Reverse sort so larger changes come first */
+ if (a_change > b_change)
+ return -1;
+ if (a_change < b_change)
+ return 1;
+ return 0;
+}
+
+static int
+test_report_cmp_backend_then_name (const void *a, const void *b)
+{
+ const test_report_t *a_test = a;
+ const test_report_t *b_test = b;
+ int cmp;
+
+ cmp = strcmp (a_test->backend, b_test->backend);
+ if (cmp)
+ return cmp;
+
+ cmp = strcmp (a_test->content, b_test->content);
+ if (cmp)
+ return cmp;
+
+ cmp = strcmp (a_test->name, b_test->name);
+ if (cmp)
+ return cmp;
+
+ if (a_test->size < b_test->size)
+ return -1;
+ if (a_test->size > b_test->size)
+ return 1;
+ return 0;
+}
+
+static void
+cairo_perf_report_sort_by_backend_then_name (cairo_perf_report_t *report)
+{
+ qsort (report->tests, report->tests_count, sizeof (test_report_t),
+ test_report_cmp_backend_then_name);
+}
+
+#define CHANGE_BAR_WIDTH 70
+static void
+print_change_bar (double change, double max_change)
+{
+ int units_per_cell = (int) ceil (max_change / CHANGE_BAR_WIDTH);
+
+ while (change > units_per_cell) {
+ printf("â");
+ change -= units_per_cell;
+ }
+
+ change /= units_per_cell;
+
+ if (change > 7.5/8.0)
+ printf("â");
+ else if (change > 6.5/8.0)
+ printf("â");
+ else if (change > 5.5/8.0)
+ printf("â");
+ else if (change > 4.5/8.0)
+ printf("â");
+ else if (change > 3.5/8.0)
+ printf("â");
+ else if (change > 2.5/8.0)
+ printf("â");
+ else if (change > 1.5/8.0)
+ printf("â");
+ else if (change > 0.5/8.0)
+ printf("â");
+
+ printf ("\n");
+}
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+static void
+cairo_perf_report_diff (cairo_perf_report_t *old,
+ cairo_perf_report_t *new,
+ double min_change)
+{
+ int i, i_old, i_new;
+ test_report_t *o, *n;
+ double o_min, o_max, n_min, n_max;
+ int cmp;
+ test_diff_t *diff, *diffs;
+ int num_diffs = 0;
+ int printed_speedup = 0, printed_slowdown = 0;
+ double change, max_change;
+
+ diffs = malloc (MAX (old->tests_count, new->tests_count) * sizeof (test_diff_t));
+ if (diffs == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+
+ cairo_perf_report_sort_by_backend_then_name (old);
+ cairo_perf_report_sort_by_backend_then_name (new);
+
+ i_old = 0;
+ i_new = 0;
+ while (i_old < old->tests_count && i_new < new->tests_count) {
+ o = &old->tests[i_old];
+ n = &new->tests[i_new];
+ cmp = test_report_cmp_backend_then_name (o, n);
+ if (cmp < 0) {
+ fprintf (stderr, "Only in old: %s %s\n", o->backend, o->name);
+ i_old++;
+ continue;
+ }
+ if (cmp > 0) {
+ fprintf (stderr, "Only in new: %s %s\n", n->backend, n->name);
+ i_new++;
+ continue;
+ }
+
+ /* Discard as uninteresting a change which doesn't separate
+ * the means by a few standard deviations in each direction,
+ * (that is, require the bulk of each curve to be
+ * non-overlapping). */
+ o_min = o->ticks * (1 - 3 * o->std_dev);
+ o_max = o->ticks * (1 + 3 * o->std_dev);
+ n_min = n->ticks * (1 - 3 * n->std_dev);
+ n_max = n->ticks * (1 + 3 * n->std_dev);
+ if (n_min > o_max ||
+ n_max < o_min)
+ {
+ diffs[num_diffs].old = o;
+ diffs[num_diffs].new = n;
+ diffs[num_diffs].speedup = o->ticks / n->ticks;
+ num_diffs++;
+ }
+
+ i_old++;
+ i_new++;
+ }
+
+ qsort (diffs, num_diffs, sizeof (test_diff_t), test_diff_cmp);
+
+ max_change = 1.0;
+ for (i = 0; i < num_diffs; i++) {
+ change = diffs[i].speedup;
+ if (change < 1.0)
+ change = 1.0 / change;
+ if (change > max_change)
+ max_change = change;
+ }
+
+ for (i = 0; i < num_diffs; i++) {
+ diff = &diffs[i];
+
+ change = diff->speedup;
+ if (change < 1.0)
+ change = 1.0 / change;
+
+ /* Discard as uninteresting a change which is less than the
+ * minimum change required, (default may be overriden on
+ * command-line). */
+ if (change - 1.0 < min_change)
+ continue;
+
+ if (diff->speedup > 1.0 && ! printed_speedup) {
+ printf ("Speedups\n"
+ "========\n");
+ printed_speedup = 1;
+ }
+ if (diff->speedup < 1.0 && ! printed_slowdown) {
+ printf ("Slowdowns\n"
+ "=========\n");
+ printed_slowdown = 1;
+ }
+
+ printf ("%5s-%-4s %26s-%-3d %6.2f %4.2f%% -> %6.2f %4.2f%%: %5.2fx ",
+ diff->old->backend, diff->old->content,
+ diff->old->name, diff->old->size,
+ diff->old->time, diff->old->std_dev * 100,
+ diff->new->time, diff->new->std_dev * 100,
+ change);
+
+ if (diff->speedup > 1.0)
+ printf ("faster\n");
+ else
+ printf ("slower\n");
+
+ print_change_bar (change, max_change);
+ }
+
+ free (diffs);
+}
+
+static void
+usage (const char *argv0)
+{
+ fprintf (stderr, "Usage: %s file1 file2 [minimum_significant_change[%%]]\n", argv0);
+ fprintf (stderr,
+ "Computes significant performance differences for cairo performance reports.\n"
+ "Each file should be the output of the cairo-perf program (or \"make perf\").\n"
+ "The third argument is used to supress all changes below some threshold.\n"
+ "The default value of 5%% ignores any speeedup or slowdown of 5%% or less,\n"
+ "A value of 0 will cause all output to be reported.\n");
+}
+
+int
+main (int argc, const char *argv[])
+{
+ const char *old_filename, *new_filename;
+ cairo_perf_report_t old, new;
+ double min_change;
+ char *end;
+
+ if (argc < 3) {
+ usage (argv[0]);
+ return 1;
+ }
+
+ old_filename = argv[1];
+ new_filename = argv[2];
+
+ min_change = 0.05;
+ if (argc >= 4) {
+ min_change = strtod (argv[3], &end);
+ if (*end && *end == '%')
+ min_change = min_change / 100.0;
+ }
+
+ cairo_perf_report_load (&old, old_filename);
+ cairo_perf_report_load (&new, new_filename);
+
+ cairo_perf_report_diff (&old, &new, min_change);
+
+ return 0;
+}
+
diff-tree 5492a7c7618a747130b844a509fb79b886f1bc54 (from 8744929030ed8d42c271d9abb202975f62de166c)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Sep 21 15:15:02 2006 -0700
Add assert statement so the infinite-join test simply exits rather than looping infinitely.
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index 87de9a4..3d42314 100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
@@ -315,6 +315,8 @@ _cairo_pen_find_active_cw_vertex_index (
break;
}
+ assert (i < pen->num_vertices);
+
*active = i;
return CAIRO_STATUS_SUCCESS;
diff-tree 8744929030ed8d42c271d9abb202975f62de166c (from 303b52919519854b9b5bbc38a9ac115e422dddad)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Sep 21 15:13:47 2006 -0700
Add test case from bug #8379 demonstrating infinite loop during round join
diff --git a/test/Makefile.am b/test/Makefile.am
index d1706ac..1630a4e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -40,6 +40,7 @@ glyph-cache-pressure \
get-and-set \
get-group-target \
gradient-alpha \
+infinite-join \
leaky-dash \
leaky-polygon \
line-width \
diff --git a/test/infinite-join.c b/test/infinite-join.c
new file mode 100644
index 0000000..fffb386
--- /dev/null
+++ b/test/infinite-join.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+/* Test case for bug #8379:
+ *
+ * infinite loop when stroking
+ * https://bugs.freedesktop.org/show_bug.cgi?id=8379
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+ "infinite-join",
+ "Test case for infinite loop when stroking with round joins",
+ 120, 70,
+ draw
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+
+ /* scaling 2 times causes a slight rounding error in the ctm.
+ * Without that, the bug doesn't happen. */
+ cairo_scale (cr, 20 / 100., 20 / 100.);
+ cairo_scale (cr, 1. / 20, 1. / 20);
+
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_width (cr, 20);
+
+ cairo_new_path (cr);
+ cairo_move_to (cr, 18928, 13843);
+ cairo_line_to (cr, -6928, 13843);
+ cairo_line_to (cr, -6928, -6842);
+ cairo_line_to (cr, 18928, -6842);
+ cairo_line_to (cr, 18928, 13843);
+ cairo_stroke (cr);
+
+ return 0;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test);
+}
More information about the cairo-commit
mailing list