diff --git a/test/Makefile.am b/test/Makefile.am index 3105bad6e..2063f40a0 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 000000000..17f4ff06b 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 000000000..17f4ff06b 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 000000000..ea16dc4bb 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 000000000..ea16dc4bb 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 561ff39c4..100f3583e 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; @@ -98,6 +104,24 @@ reference (cairo_t *cr, int width, int height) return CAIRO_STATUS_SUCCESS; } +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) { @@ -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,7 @@ 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; @@ -233,7 +257,204 @@ 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 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; + + state = 0x12345678; + occupancy = xmalloc (SAMPLE*SAMPLE); + + 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) { + 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 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 */