[cairo-commit] test/Makefile.am test/partial-coverage.c test/partial-coverage-overlap-half-triangles-eo.ref.png test/partial-coverage-overlap-half-triangles.ref.png test/partial-coverage-overlap-three-quarter-triangles.ref.png test/partial-coverage-three-quarter-reference.ref.png

Chris Wilson ickle at kemper.freedesktop.org
Thu Jun 10 10:31:03 PDT 2010


 test/Makefile.am                                              |    4 
 test/partial-coverage-overlap-half-triangles-eo.ref.png       |binary
 test/partial-coverage-overlap-half-triangles.ref.png          |binary
 test/partial-coverage-overlap-three-quarter-triangles.ref.png |binary
 test/partial-coverage-three-quarter-reference.ref.png         |binary
 test/partial-coverage.c                                       |  284 +++++++++-
 6 files changed, 269 insertions(+), 19 deletions(-)

New commits:
commit b0056a86b4f6c92fa7eb89baf8483a46979c8cf1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Jun 10 18:27:22 2010 +0100

    test: Exercise partial coverage some more.
    
    Add some overlapping triangles (coarse enough for them to be resolved
    using Cairo's 24.8 fixed point without loss of precision) to exercise
    handling of overlapping subpixel geometry.

diff --git a/test/Makefile.am b/test/Makefile.am
index 3105bad..2063f40 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -864,8 +864,12 @@ REFERENCE_IMAGES = \
 	paint.ref.png \
 	partial-coverage-half-reference.ref.png \
 	partial-coverage-half-triangles.ref.png \
+	partial-coverage-overlap-half-triangles.ref.png \
+	partial-coverage-overlap-half-triangles-eo.ref.png \
+	partial-coverage-overlap-three-quarter-triangles.ref.png \
 	partial-coverage-rectangles.ref.png \
 	partial-coverage-reference.ref.png \
+	partial-coverage-three-quarter-reference.ref.png \
 	partial-coverage-triangles.ref.png \
 	pass-through.ref.png \
 	pass-through.rgb24.ref.png \
diff --git a/test/partial-coverage-overlap-half-triangles-eo.ref.png b/test/partial-coverage-overlap-half-triangles-eo.ref.png
new file mode 100644
index 0000000..17f4ff0
Binary files /dev/null and b/test/partial-coverage-overlap-half-triangles-eo.ref.png differ
diff --git a/test/partial-coverage-overlap-half-triangles.ref.png b/test/partial-coverage-overlap-half-triangles.ref.png
new file mode 100644
index 0000000..17f4ff0
Binary files /dev/null and b/test/partial-coverage-overlap-half-triangles.ref.png differ
diff --git a/test/partial-coverage-overlap-three-quarter-triangles.ref.png b/test/partial-coverage-overlap-three-quarter-triangles.ref.png
new file mode 100644
index 0000000..ea16dc4
Binary files /dev/null and b/test/partial-coverage-overlap-three-quarter-triangles.ref.png differ
diff --git a/test/partial-coverage-three-quarter-reference.ref.png b/test/partial-coverage-three-quarter-reference.ref.png
new file mode 100644
index 0000000..ea16dc4
Binary files /dev/null and b/test/partial-coverage-three-quarter-reference.ref.png differ
diff --git a/test/partial-coverage.c b/test/partial-coverage.c
index 561ff39..100f358 100644
--- a/test/partial-coverage.c
+++ b/test/partial-coverage.c
@@ -52,26 +52,32 @@ uniform_random (void)
     return hars_petruska_f54_1_random() / (double) UINT32_MAX;
 }
 
-/* coverage is given in [0,65535] */
+/* coverage is given in [0,sample] */
 static void
-compute_occupancy (uint8_t *occupancy, int coverage)
+compute_occupancy (uint8_t *occupancy, int coverage, int sample)
 {
     int i, c;
 
-    if (coverage < SAMPLE*SAMPLE/2) {
-	memset (occupancy, 0, SAMPLE*SAMPLE);
-	for (i = c = 0; i < SAMPLE*SAMPLE; i++) {
-	    if ((SAMPLE*SAMPLE - i) * uniform_random() < coverage - c) {
+    if (coverage < sample/2) {
+	memset (occupancy, 0, sample);
+	if (coverage == 0)
+	    return;
+
+	for (i = c = 0; i < sample; i++) {
+	    if ((sample - i) * uniform_random() < coverage - c) {
 		occupancy[i] = 0xff;
 		if (++c == coverage)
 		    return;
 	    }
 	}
     } else {
-	coverage = SAMPLE*SAMPLE - coverage;
-	memset (occupancy, 0xff, SAMPLE*SAMPLE);
-	for (i = c = 0; i < SAMPLE*SAMPLE; i++) {
-	    if ((SAMPLE*SAMPLE - i) * uniform_random() < coverage - c) {
+	coverage = sample - coverage;
+	memset (occupancy, 0xff, sample);
+	if (coverage == 0)
+	    return;
+
+	for (i = c = 0; i < sample; i++) {
+	    if ((sample - i) * uniform_random() < coverage - c) {
 		occupancy[i] = 0;
 		if (++c == coverage)
 		    return;
@@ -99,6 +105,24 @@ reference (cairo_t *cr, int width, int height)
 }
 
 static cairo_test_status_t
+three_quarter_reference (cairo_t *cr, int width, int height)
+{
+    int i;
+
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_paint (cr);
+
+    for (i = 0; i < SIZE*SIZE; i++) {
+	cairo_set_source_rgba (cr, 1., 1., 1.,
+			       .75 * i / (double) (SIZE * SIZE));
+	cairo_rectangle (cr, i % SIZE, i / SIZE, 1, 1);
+	cairo_fill (cr);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_test_status_t
 half_reference (cairo_t *cr, int width, int height)
 {
     int i;
@@ -140,7 +164,7 @@ rectangles (cairo_t *cr, int width, int height)
 	for (i = 0; i < SIZE*SIZE; i++) {
 	    int xs, ys;
 
-	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE));
+	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
 
 	    xs = i % SIZE * SAMPLE;
 	    ys = i / SIZE * SAMPLE;
@@ -186,7 +210,7 @@ half_triangles (cairo_t *cr, int width, int height)
 	for (i = 0; i < SIZE*SIZE; i++) {
 	    int xs, ys;
 
-	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE));
+	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
 
 	    xs = i % SIZE * SAMPLE;
 	    ys = i / SIZE * SAMPLE;
@@ -210,7 +234,72 @@ half_triangles (cairo_t *cr, int width, int height)
 }
 
 static cairo_test_status_t
-full_triangles (cairo_t *cr, int width, int height)
+overlap_half_triangles (cairo_t *cr, int width, int height)
+{
+    uint8_t *occupancy;
+    int i, j, channel;
+
+    state = 0x12345678;
+    occupancy = xmalloc (SAMPLE*SAMPLE);
+
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_paint (cr);
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
+    for (channel = 0; channel < 3; channel++) {
+	switch (channel) {
+	default:
+	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
+	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
+	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
+	}
+
+	for (i = 0; i < SIZE*SIZE; i++) {
+	    int xs, ys;
+
+	    compute_occupancy (occupancy, SAMPLE/2*SAMPLE/2 * i / (SIZE * SIZE), SAMPLE/2*SAMPLE/2);
+
+	    xs = i % SIZE * SAMPLE;
+	    ys = i / SIZE * SAMPLE;
+	    for (j = 0; j < SAMPLE/2*SAMPLE/2; j++) {
+		if (occupancy[j]) {
+		    int x = 2 * (j % (SAMPLE/2)) + xs;
+		    int y = 2 * (j / (SAMPLE/2)) + ys;
+
+		    /* Add a 4-tile composed of two overlapping triangles.
+		     *   .__.__.
+		     *   |\   /|
+		     *   | \ / |
+		     *   .  x  |
+		     *   | / \ |
+		     *   |/   \|
+		     *   .     .
+		     *
+		     * Coverage should be computable as 50% (due to counter-winding).
+		     */
+
+		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+2) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
+		    cairo_close_path (cr);
+
+		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y+2) / (double) SAMPLE);
+		    cairo_close_path (cr);
+		}
+	    }
+	    cairo_fill (cr);
+	}
+    }
+
+    free (occupancy);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+overlap_half_triangles_eo (cairo_t *cr, int width, int height)
 {
     uint8_t *occupancy;
     int i, j, channel;
@@ -221,6 +310,8 @@ full_triangles (cairo_t *cr, int width, int height)
     cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
     cairo_paint (cr);
 
+    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+
     cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
     for (channel = 0; channel < 3; channel++) {
 	switch (channel) {
@@ -233,7 +324,137 @@ full_triangles (cairo_t *cr, int width, int height)
 	for (i = 0; i < SIZE*SIZE; i++) {
 	    int xs, ys;
 
-	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE));
+	    compute_occupancy (occupancy, SAMPLE/2*SAMPLE/2 * i / (SIZE * SIZE), SAMPLE/2*SAMPLE/2);
+
+	    xs = i % SIZE * SAMPLE;
+	    ys = i / SIZE * SAMPLE;
+	    for (j = 0; j < SAMPLE/2*SAMPLE/2; j++) {
+		if (occupancy[j]) {
+		    int x = 2 * (j % (SAMPLE/2)) + xs;
+		    int y = 2 * (j / (SAMPLE/2)) + ys;
+
+		    /* Add a 4-tile composed of two overlapping triangles.
+		     *   .__.__.
+		     *   |\   /|
+		     *   | \ / |
+		     *   .  x  |
+		     *   | / \ |
+		     *   |/   \|
+		     *   .     .
+		     *
+		     * Coverage should be computable as 50%, due to even-odd fill rule.
+		     */
+
+		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+2) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
+		    cairo_close_path (cr);
+
+		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y+2) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
+		    cairo_close_path (cr);
+		}
+	    }
+	    cairo_fill (cr);
+	}
+    }
+
+    free (occupancy);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+overlap_three_quarter_triangles (cairo_t *cr, int width, int height)
+{
+    uint8_t *occupancy;
+    int i, j, channel;
+
+    state = 0x12345678;
+    occupancy = xmalloc (SAMPLE*SAMPLE);
+
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_paint (cr);
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
+    for (channel = 0; channel < 3; channel++) {
+	switch (channel) {
+	default:
+	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
+	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
+	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
+	}
+
+	for (i = 0; i < SIZE*SIZE; i++) {
+	    int xs, ys;
+
+	    compute_occupancy (occupancy, SAMPLE/2*SAMPLE/2 * i / (SIZE * SIZE), SAMPLE/2*SAMPLE/2);
+
+	    xs = i % SIZE * SAMPLE;
+	    ys = i / SIZE * SAMPLE;
+	    for (j = 0; j < SAMPLE/2*SAMPLE/2; j++) {
+		if (occupancy[j]) {
+		    int x = 2 * (j % (SAMPLE/2)) + xs;
+		    int y = 2 * (j / (SAMPLE/2)) + ys;
+
+		    /* Add a 4-tile composed of two overlapping triangles.
+		     *   .__.__.
+		     *   |\   /|
+		     *   | \ / |
+		     *   .  x  |
+		     *   | / \ |
+		     *   |/   \|
+		     *   .     .
+		     *
+		     * Coverage should be computable as 75%.
+		     */
+
+		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+2) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
+		    cairo_close_path (cr);
+
+		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y+2) / (double) SAMPLE);
+		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
+		    cairo_close_path (cr);
+		}
+	    }
+	    cairo_fill (cr);
+	}
+    }
+
+    free (occupancy);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+triangles (cairo_t *cr, int width, int height)
+{
+    uint8_t *occupancy;
+    int i, j, channel;
+
+    state = 0x12345678;
+    occupancy = xmalloc (SAMPLE*SAMPLE);
+
+    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+    cairo_paint (cr);
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
+    for (channel = 0; channel < 3; channel++) {
+	switch (channel) {
+	default:
+	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
+	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
+	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
+	}
+
+	for (i = 0; i < SIZE*SIZE; i++) {
+	    int xs, ys;
+
+	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
 
 	    xs = i % SIZE * SAMPLE;
 	    ys = i / SIZE * SAMPLE;
@@ -276,25 +497,50 @@ CAIRO_TEST (partial_coverage_rectangles,
 	    "raster", /* requirements */
 	    SIZE, SIZE,
 	    NULL, rectangles)
+
 CAIRO_TEST (partial_coverage_triangles,
 	    "Check the fidelity of the rasterisation.",
 	    "coverage raster", /* keywords */
 	    "raster", /* requirements */
 	    SIZE, SIZE,
-	    NULL, full_triangles)
-CAIRO_TEST (partial_coverage_reference,
-	    "Check the fidelity of this test.",
+	    NULL, triangles)
+CAIRO_TEST (partial_coverage_overlap_three_quarter_triangles,
+	    "Check the fidelity of the rasterisation.",
 	    "coverage raster", /* keywords */
 	    "raster", /* requirements */
 	    SIZE, SIZE,
-	    NULL, reference)
-
+	    NULL, overlap_three_quarter_triangles)
+CAIRO_TEST (partial_coverage_overlap_half_triangles_eo,
+	    "Check the fidelity of the rasterisation.",
+	    "coverage raster", /* keywords */
+	    "raster", /* requirements */
+	    SIZE, SIZE,
+	    NULL, overlap_half_triangles_eo)
+CAIRO_TEST (partial_coverage_overlap_half_triangles,
+	    "Check the fidelity of the rasterisation.",
+	    "coverage raster", /* keywords */
+	    "raster", /* requirements */
+	    SIZE, SIZE,
+	    NULL, overlap_half_triangles)
 CAIRO_TEST (partial_coverage_half_triangles,
 	    "Check the fidelity of the rasterisation.",
 	    "coverage raster", /* keywords */
 	    "raster", /* requirements */
 	    SIZE, SIZE,
 	    NULL, half_triangles)
+
+CAIRO_TEST (partial_coverage_reference,
+	    "Check the fidelity of this test.",
+	    "coverage raster", /* keywords */
+	    "raster", /* requirements */
+	    SIZE, SIZE,
+	    NULL, reference)
+CAIRO_TEST (partial_coverage_three_quarter_reference,
+	    "Check the fidelity of this test.",
+	    "coverage raster", /* keywords */
+	    "raster", /* requirements */
+	    SIZE, SIZE,
+	    NULL, three_quarter_reference)
 CAIRO_TEST (partial_coverage_half_reference,
 	    "Check the fidelity of this test.",
 	    "coverage raster", /* keywords */


More information about the cairo-commit mailing list