From b0056a86b4f6c92fa7eb89baf8483a46979c8cf1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 10 Jun 2010 18:27:22 +0100 Subject: [PATCH] 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. --- test/Makefile.am | 4 + ...coverage-overlap-half-triangles-eo.ref.png | Bin 0 -> 189 bytes ...al-coverage-overlap-half-triangles.ref.png | Bin 0 -> 189 bytes ...ge-overlap-three-quarter-triangles.ref.png | Bin 0 -> 186 bytes ...l-coverage-three-quarter-reference.ref.png | Bin 0 -> 186 bytes test/partial-coverage.c | 284 ++++++++++++++++-- 6 files changed, 269 insertions(+), 19 deletions(-) create mode 100644 test/partial-coverage-overlap-half-triangles-eo.ref.png create mode 100644 test/partial-coverage-overlap-half-triangles.ref.png create mode 100644 test/partial-coverage-overlap-three-quarter-triangles.ref.png create mode 100644 test/partial-coverage-three-quarter-reference.ref.png 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 0000000000000000000000000000000000000000..17f4ff06b367b25be02a7140335f88f322ee4048 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$wj^(N7l!{JxM1({$v}}JPZ!6K zjK;U;Hwqqb;5oeE#`oXn=LkmZWM-eh_gU85c>C|&)zt+&6%2w7ECGxz45E}#S4|(V Ydm1sDN|l^q0ou;s>FVdQ&MBb@0D8kOT>t<8 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..17f4ff06b367b25be02a7140335f88f322ee4048 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$wj^(N7l!{JxM1({$v}}JPZ!6K zjK;U;Hwqqb;5oeE#`oXn=LkmZWM-eh_gU85c>C|&)zt+&6%2w7ECGxz45E}#S4|(V Ydm1sDN|l^q0ou;s>FVdQ&MBb@0D8kOT>t<8 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ea16dc4bb1dcce4a74e9986435bdb4906ee70f24 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$wj^(N7l!{JxM1({$v}~OPZ!6K zjK;U;H*zu<3a}W;fB$>^k897tPBZz4vnOZIoc{COw10=1r_}@10*zq@QyR5kZosd9 zAnt-Me;I+4!^_{yK&s)=cd(+R@A*NJUiale)RcYpK+@wUzn%!oCU1+74v?UytDnm{ Hr-UW|xs*29 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ea16dc4bb1dcce4a74e9986435bdb4906ee70f24 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1SD0tpLGH$wj^(N7l!{JxM1({$v}~OPZ!6K zjK;U;H*zu<3a}W;fB$>^k897tPBZz4vnOZIoc{COw10=1r_}@10*zq@QyR5kZosd9 zAnt-Me;I+4!^_{yK&s)=cd(+R@A*NJUiale)RcYpK+@wUzn%!oCU1+74v?UytDnm{ Hr-UW|xs*29 literal 0 HcmV?d00001 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 */