2 * Copyright 2010 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * Author: Chris Wilson <chris@chris-wilson.co.uk>
27 #include "cairo-test.h"
29 /* Test the fidelity of the rasterisation, because Cairo is my favourite
33 #define GENERATE_REFERENCE 0
38 #include "../src/cairo-fixed-type-private.h"
39 #define PRECISION (1 << CAIRO_FIXED_FRAC_BITS)
41 /* XXX beware multithreading! */
42 static uint32_t state;
45 hars_petruska_f54_1_random (void)
47 #define rol(x,k) ((x << k) | (x >> (32-k)))
48 return state = (state ^ rol (state, 5) ^ rol (state, 24)) + 0x37798849;
53 random_offset (int range, int precise)
55 double x = hars_petruska_f54_1_random() / (double) UINT32_MAX * range / WIDTH;
57 x = floor (x * PRECISION) / PRECISION;
61 static cairo_test_status_t
62 rectangles (cairo_t *cr, int width, int height)
68 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
71 #if GENERATE_REFERENCE
72 for (x = 0; x < WIDTH; x++) {
73 cairo_set_source_rgba (cr, 1, 1, 1, x * x * 1.0 / (WIDTH * WIDTH));
74 cairo_rectangle (cr, x, 0, 1, HEIGHT);
78 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
79 for (channel = 0; channel < 3; channel++) {
82 case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
83 case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
84 case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
87 for (x = 0; x < WIDTH; x++) {
88 for (y = 0; y < HEIGHT; y++) {
89 double dx = random_offset (WIDTH - x, TRUE);
90 double dy = random_offset (WIDTH - x, TRUE);
91 cairo_rectangle (cr, x + dx, y + dy, x / (double) WIDTH, x / (double) WIDTH);
98 return CAIRO_TEST_SUCCESS;
101 static cairo_test_status_t
102 intersecting_quads (cairo_t *cr, int width, int height)
108 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
111 #if GENERATE_REFERENCE
112 for (x = 0; x < WIDTH; x++) {
113 cairo_set_source_rgba (cr, 1, 1, 1, x * x * 0.5 / (WIDTH * WIDTH));
114 cairo_rectangle (cr, x, 0, 1, HEIGHT);
118 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
119 for (channel = 0; channel < 3; channel++) {
122 case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
123 case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
124 case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
127 for (x = 0; x < WIDTH; x++) {
128 double step = x / (double) WIDTH;
129 for (y = 0; y < HEIGHT; y++) {
130 double dx = random_offset (WIDTH - x, TRUE);
131 double dy = random_offset (WIDTH - x, TRUE);
132 cairo_move_to (cr, x + dx, y + dy);
133 cairo_rel_line_to (cr, step, step);
134 cairo_rel_line_to (cr, 0, -step);
135 cairo_rel_line_to (cr, -step, step);
136 cairo_close_path (cr);
143 return CAIRO_TEST_SUCCESS;
146 static cairo_test_status_t
147 intersecting_triangles (cairo_t *cr, int width, int height)
153 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
156 #if GENERATE_REFERENCE
157 for (x = 0; x < WIDTH; x++) {
158 cairo_set_source_rgba (cr, 1, 1, 1, x * 0.75 / WIDTH);
159 cairo_rectangle (cr, x, 0, 1, HEIGHT);
163 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
164 for (channel = 0; channel < 3; channel++) {
167 case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
168 case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
169 case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
172 for (x = 0; x < WIDTH; x++) {
173 double step = x / (double) WIDTH;
174 for (y = 0; y < HEIGHT; y++) {
175 double dx = random_offset (WIDTH - x, TRUE);
176 double dy = random_offset (WIDTH - x, TRUE);
179 cairo_move_to (cr, x + dx, y + dy);
180 cairo_rel_line_to (cr, 0, step);
181 cairo_rel_line_to (cr, step, 0);
182 cairo_close_path (cr);
184 /* right, mirrored */
185 cairo_move_to (cr, x + dx + step, y + dy + step);
186 cairo_rel_line_to (cr, 0, -step);
187 cairo_rel_line_to (cr, -step, step);
188 cairo_close_path (cr);
195 return CAIRO_TEST_SUCCESS;
198 static cairo_test_status_t
199 triangles (cairo_t *cr, int width, int height)
205 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
208 #if GENERATE_REFERENCE
209 for (x = 0; x < WIDTH; x++) {
210 cairo_set_source_rgba (cr, 1, 1, 1, x * x * 0.5 / (WIDTH * WIDTH));
211 cairo_rectangle (cr, x, 0, 1, HEIGHT);
215 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
216 for (channel = 0; channel < 3; channel++) {
219 case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
220 case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
221 case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
224 for (x = 0; x < WIDTH; x++) {
225 for (y = 0; y < HEIGHT; y++) {
226 double dx = random_offset (WIDTH - x, TRUE);
227 double dy = random_offset (WIDTH - x, TRUE);
228 cairo_move_to (cr, x + dx, y + dy);
229 cairo_rel_line_to (cr, x / (double) WIDTH, 0);
230 cairo_rel_line_to (cr, 0, x / (double) WIDTH);
231 cairo_close_path (cr);
238 return CAIRO_TEST_SUCCESS;
241 static cairo_test_status_t
242 column_triangles (cairo_t *cr, int width, int height)
244 int x, y, i, channel;
248 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
251 #if GENERATE_REFERENCE
252 for (x = 0; x < WIDTH; x++) {
253 cairo_set_source_rgba (cr, 1, 1, 1, x * 0.5 / WIDTH);
254 cairo_rectangle (cr, x, 0, 1, HEIGHT);
258 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
259 for (channel = 0; channel < 3; channel++) {
262 case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
263 case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
264 case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
267 for (x = 0; x < WIDTH; x++) {
268 double step = x / (double) (2 * WIDTH);
269 for (y = 0; y < HEIGHT; y++) {
270 for (i = 0; i < PRECISION; i++) {
271 double dy = random_offset (WIDTH - x, FALSE);
274 * We want to test some sharing of edges to further
275 * stress the rasterisers, so instead of using one
276 * tall triangle, it is split into two, with vertical
277 * edges on either side that may co-align with their
283 * p --- .... | 2 * step = x / WIDTH
290 * Each column contains two triangles of width one quantum and
291 * total height of (x / WIDTH), thus the total area covered by all
292 * columns in each pixel is .5 * (x / WIDTH).
295 cairo_move_to (cr, x + i / (double) PRECISION, y + dy);
296 cairo_rel_line_to (cr, 0, step);
297 cairo_rel_line_to (cr, 1 / (double) PRECISION, step);
298 cairo_rel_line_to (cr, 0, -step);
299 cairo_close_path (cr);
301 cairo_fill (cr); /* do these per-pixel due to the extra volume of edges */
307 return CAIRO_TEST_SUCCESS;
310 static cairo_test_status_t
311 row_triangles (cairo_t *cr, int width, int height)
313 int x, y, i, channel;
317 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
320 #if GENERATE_REFERENCE
321 for (x = 0; x < WIDTH; x++) {
322 cairo_set_source_rgba (cr, 1, 1, 1, x * 0.5 / WIDTH);
323 cairo_rectangle (cr, x, 0, 1, HEIGHT);
327 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
328 for (channel = 0; channel < 3; channel++) {
331 case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
332 case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
333 case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
336 for (x = 0; x < WIDTH; x++) {
337 double step = x / (double) (2 * WIDTH);
338 for (y = 0; y < HEIGHT; y++) {
339 for (i = 0; i < PRECISION; i++) {
340 double dx = random_offset (WIDTH - x, FALSE);
342 /* See column_triangles() for a transposed description
346 cairo_move_to (cr, x + dx, y + i / (double) PRECISION);
347 cairo_rel_line_to (cr, step, 0);
348 cairo_rel_line_to (cr, step, 1 / (double) PRECISION);
349 cairo_rel_line_to (cr, -step, 0);
350 cairo_close_path (cr);
352 cairo_fill (cr); /* do these per-pixel due to the extra volume of edges */
358 return CAIRO_TEST_SUCCESS;
361 CAIRO_TEST (coverage_rectangles,
362 "Check the fidelity of the rasterisation.",
364 "target=raster slow", /* requirements */
368 CAIRO_TEST (coverage_intersecting_quads,
369 "Check the fidelity of the rasterisation.",
371 "target=raster slow", /* requirements */
373 NULL, intersecting_quads)
375 CAIRO_TEST (coverage_intersecting_triangles,
376 "Check the fidelity of the rasterisation.",
378 "target=raster slow", /* requirements */
380 NULL, intersecting_triangles)
381 CAIRO_TEST (coverage_row_triangles,
382 "Check the fidelity of the rasterisation.",
384 "target=raster slow", /* requirements */
387 CAIRO_TEST (coverage_column_triangles,
388 "Check the fidelity of the rasterisation.",
390 "target=raster slow", /* requirements */
392 NULL, column_triangles)
393 CAIRO_TEST (coverage_triangles,
394 "Check the fidelity of the rasterisation.",
396 "target=raster slow", /* requirements */