1
/*
2
 * Copyright 2010 Intel Corporation
3
 *
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:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
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
22
 * SOFTWARE.
23
 *
24
 * Author: Chris Wilson <chris@chris-wilson.co.uk>
25
 */
26

            
27
#include "cairo-test.h"
28

            
29
/* Test the sampling stratagems of the rasterisers by creating pixels
30
 * containing minute holes and seeing how close to the expected
31
 * coverage each rasteriser approaches.
32
 */
33

            
34
#define SIZE 64
35

            
36
#include "../src/cairo-fixed-type-private.h"
37
#define SAMPLE (1 << CAIRO_FIXED_FRAC_BITS)
38

            
39
static uint32_t state;
40

            
41
static uint32_t
42
hars_petruska_f54_1_random (void)
43
{
44
#define rol(x,k) ((x << k) | (x >> (32-k)))
45
    return state = (state ^ rol (state, 5) ^ rol (state, 24)) + 0x37798849;
46
#undef rol
47
}
48

            
49
static double
50
uniform_random (void)
51
{
52
    return hars_petruska_f54_1_random() / (double) UINT32_MAX;
53
}
54

            
55
/* coverage is given in [0,sample] */
56
static void
57
compute_occupancy (uint8_t *occupancy, int coverage, int sample)
58
{
59
    int i, c;
60

            
61
    if (coverage < sample/2) {
62
	memset (occupancy, 0, sample);
63
	if (coverage == 0)
64
	    return;
65

            
66
	for (i = c = 0; i < sample; i++) {
67
	    if ((sample - i) * uniform_random() < coverage - c) {
68
		occupancy[i] = 0xff;
69
		if (++c == coverage)
70
		    return;
71
	    }
72
	}
73
    } else {
74
	coverage = sample - coverage;
75
	memset (occupancy, 0xff, sample);
76
	if (coverage == 0)
77
	    return;
78

            
79
	for (i = c = 0; i < sample; i++) {
80
	    if ((sample - i) * uniform_random() < coverage - c) {
81
		occupancy[i] = 0;
82
		if (++c == coverage)
83
		    return;
84
	    }
85
	}
86
    }
87
}
88

            
89
static cairo_test_status_t
90
3
reference (cairo_t *cr, int width, int height)
91
{
92
    int i;
93

            
94
3
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
95
3
    cairo_paint (cr);
96

            
97
12291
    for (i = 0; i < SIZE*SIZE; i++) {
98
12288
	cairo_set_source_rgba (cr, 1., 1., 1.,
99
			       i / (double) (SIZE * SIZE));
100
12288
	cairo_rectangle (cr, i % SIZE, i / SIZE, 1, 1);
101
12288
	cairo_fill (cr);
102
    }
103

            
104
3
    return CAIRO_TEST_SUCCESS;
105
}
106

            
107
static cairo_test_status_t
108
3
three_quarter_reference (cairo_t *cr, int width, int height)
109
{
110
    int i;
111

            
112
3
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
113
3
    cairo_paint (cr);
114

            
115
12291
    for (i = 0; i < SIZE*SIZE; i++) {
116
12288
	cairo_set_source_rgba (cr, 1., 1., 1.,
117
12288
			       .75 * i / (double) (SIZE * SIZE));
118
12288
	cairo_rectangle (cr, i % SIZE, i / SIZE, 1, 1);
119
12288
	cairo_fill (cr);
120
    }
121

            
122
3
    return CAIRO_TEST_SUCCESS;
123
}
124

            
125
static cairo_test_status_t
126
3
half_reference (cairo_t *cr, int width, int height)
127
{
128
    int i;
129

            
130
3
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
131
3
    cairo_paint (cr);
132

            
133
12291
    for (i = 0; i < SIZE*SIZE; i++) {
134
12288
	cairo_set_source_rgba (cr, 1., 1., 1.,
135
12288
			       .5 * i / (double) (SIZE * SIZE));
136
12288
	cairo_rectangle (cr, i % SIZE, i / SIZE, 1, 1);
137
12288
	cairo_fill (cr);
138
    }
139

            
140
3
    return CAIRO_TEST_SUCCESS;
141
}
142

            
143
static cairo_test_status_t
144
rectangles (cairo_t *cr, int width, int height)
145
{
146
    uint8_t *occupancy;
147
    int i, j, channel;
148

            
149
    state = 0x12345678;
150
    occupancy = xmalloc (SAMPLE*SAMPLE);
151

            
152
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
153
    cairo_paint (cr);
154

            
155
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
156
    for (channel = 0; channel < 3; channel++) {
157
	switch (channel) {
158
	default:
159
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
160
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
161
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
162
	}
163

            
164
	for (i = 0; i < SIZE*SIZE; i++) {
165
	    int xs, ys;
166

            
167
	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
168

            
169
	    xs = i % SIZE * SAMPLE;
170
	    ys = i / SIZE * SAMPLE;
171
	    for (j = 0; j < SAMPLE*SAMPLE; j++) {
172
		if (occupancy[j]) {
173
		    cairo_rectangle (cr,
174
				     (j % SAMPLE + xs) / (double) SAMPLE,
175
				     (j / SAMPLE + ys) / (double) SAMPLE,
176
				     1 / (double) SAMPLE,
177
				     1 / (double) SAMPLE);
178
		}
179
	    }
180
	    cairo_fill (cr);
181
	}
182
    }
183

            
184
    free (occupancy);
185

            
186
    return CAIRO_TEST_SUCCESS;
187
}
188

            
189
static cairo_test_status_t
190
intersecting_quads (cairo_t *cr, int width, int height)
191
{
192
    uint8_t *occupancy;
193
    int i, j, channel;
194

            
195
    state = 0x12345678;
196
    occupancy = xmalloc (SAMPLE*SAMPLE);
197

            
198
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
199
    cairo_paint (cr);
200

            
201
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
202
    for (channel = 0; channel < 3; channel++) {
203
	switch (channel) {
204
	default:
205
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
206
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
207
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
208
	}
209

            
210
	for (i = 0; i < SIZE*SIZE; i++) {
211
	    int xs, ys;
212

            
213
	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
214

            
215
	    xs = i % SIZE * SAMPLE;
216
	    ys = i / SIZE * SAMPLE;
217
	    for (j = 0; j < SAMPLE*SAMPLE; j++) {
218
		if (occupancy[j]) {
219
		    cairo_move_to (cr,
220
				     (j % SAMPLE + xs) / (double) SAMPLE,
221
				     (j / SAMPLE + ys) / (double) SAMPLE);
222
		    cairo_rel_line_to (cr, 1 / (double) SAMPLE, 1 / (double) SAMPLE);
223
		    cairo_rel_line_to (cr, 0, -1 / (double) SAMPLE);
224
		    cairo_rel_line_to (cr, -1 / (double) SAMPLE, 1 / (double) SAMPLE);
225
		    cairo_close_path (cr);
226
		}
227
	    }
228
	    cairo_fill (cr);
229
	}
230
    }
231

            
232
    free (occupancy);
233

            
234
    return CAIRO_TEST_SUCCESS;
235
}
236

            
237
static cairo_test_status_t
238
half_triangles (cairo_t *cr, int width, int height)
239
{
240
    uint8_t *occupancy;
241
    int i, j, channel;
242

            
243
    state = 0x12345678;
244
    occupancy = xmalloc (SAMPLE*SAMPLE);
245

            
246
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
247
    cairo_paint (cr);
248

            
249
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
250
    for (channel = 0; channel < 3; channel++) {
251
	switch (channel) {
252
	default:
253
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
254
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
255
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
256
	}
257

            
258
	for (i = 0; i < SIZE*SIZE; i++) {
259
	    int xs, ys;
260

            
261
	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
262

            
263
	    xs = i % SIZE * SAMPLE;
264
	    ys = i / SIZE * SAMPLE;
265
	    for (j = 0; j < SAMPLE*SAMPLE; j++) {
266
		if (occupancy[j]) {
267
		    int x = j % SAMPLE + xs;
268
		    int y = j / SAMPLE + ys;
269
		    cairo_move_to (cr, x / (double) SAMPLE, y / (double) SAMPLE);
270
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y+1) / (double) SAMPLE);
271
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, y / (double) SAMPLE);
272
		    cairo_close_path (cr);
273
		}
274
	    }
275
	    cairo_fill (cr);
276
	}
277
    }
278

            
279
    free (occupancy);
280

            
281
    return CAIRO_TEST_SUCCESS;
282
}
283

            
284
static cairo_test_status_t
285
overlap_half_triangles (cairo_t *cr, int width, int height)
286
{
287
    uint8_t *occupancy;
288
    int i, j, channel;
289

            
290
    state = 0x12345678;
291
    occupancy = xmalloc (SAMPLE*SAMPLE);
292

            
293
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
294
    cairo_paint (cr);
295

            
296
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
297
    for (channel = 0; channel < 3; channel++) {
298
	switch (channel) {
299
	default:
300
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
301
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
302
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
303
	}
304

            
305
	for (i = 0; i < SIZE*SIZE; i++) {
306
	    int xs, ys;
307

            
308
	    compute_occupancy (occupancy, SAMPLE/2*SAMPLE/2 * i / (SIZE * SIZE), SAMPLE/2*SAMPLE/2);
309

            
310
	    xs = i % SIZE * SAMPLE;
311
	    ys = i / SIZE * SAMPLE;
312
	    for (j = 0; j < SAMPLE/2*SAMPLE/2; j++) {
313
		if (occupancy[j]) {
314
		    int x = 2 * (j % (SAMPLE/2)) + xs;
315
		    int y = 2 * (j / (SAMPLE/2)) + ys;
316

            
317
		    /* Add a 4-tile composed of two overlapping triangles.
318
		     *   .__.__.
319
		     *   |\   /|
320
		     *   | \ / |
321
		     *   .  x  |
322
		     *   | / \ |
323
		     *   |/   \|
324
		     *   .     .
325
		     *
326
		     * Coverage should be computable as 50% (due to counter-winding).
327
		     */
328

            
329
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
330
		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+2) / (double) SAMPLE);
331
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
332
		    cairo_close_path (cr);
333

            
334
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
335
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
336
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y+2) / (double) SAMPLE);
337
		    cairo_close_path (cr);
338
		}
339
	    }
340
	    cairo_fill (cr);
341
	}
342
    }
343

            
344
    free (occupancy);
345

            
346
    return CAIRO_TEST_SUCCESS;
347
}
348

            
349
static cairo_test_status_t
350
overlap_half_triangles_eo (cairo_t *cr, int width, int height)
351
{
352
    uint8_t *occupancy;
353
    int i, j, channel;
354

            
355
    state = 0x12345678;
356
    occupancy = xmalloc (SAMPLE*SAMPLE);
357

            
358
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
359
    cairo_paint (cr);
360

            
361
    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
362

            
363
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
364
    for (channel = 0; channel < 3; channel++) {
365
	switch (channel) {
366
	default:
367
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
368
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
369
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
370
	}
371

            
372
	for (i = 0; i < SIZE*SIZE; i++) {
373
	    int xs, ys;
374

            
375
	    compute_occupancy (occupancy, SAMPLE/2*SAMPLE/2 * i / (SIZE * SIZE), SAMPLE/2*SAMPLE/2);
376

            
377
	    xs = i % SIZE * SAMPLE;
378
	    ys = i / SIZE * SAMPLE;
379
	    for (j = 0; j < SAMPLE/2*SAMPLE/2; j++) {
380
		if (occupancy[j]) {
381
		    int x = 2 * (j % (SAMPLE/2)) + xs;
382
		    int y = 2 * (j / (SAMPLE/2)) + ys;
383

            
384
		    /* Add a 4-tile composed of two overlapping triangles.
385
		     *   .__.__.
386
		     *   |\   /|
387
		     *   | \ / |
388
		     *   .  x  |
389
		     *   | / \ |
390
		     *   |/   \|
391
		     *   .     .
392
		     *
393
		     * Coverage should be computable as 50%, due to even-odd fill rule.
394
		     */
395

            
396
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
397
		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+2) / (double) SAMPLE);
398
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
399
		    cairo_close_path (cr);
400

            
401
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
402
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y+2) / (double) SAMPLE);
403
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
404
		    cairo_close_path (cr);
405
		}
406
	    }
407
	    cairo_fill (cr);
408
	}
409
    }
410

            
411
    free (occupancy);
412

            
413
    return CAIRO_TEST_SUCCESS;
414
}
415

            
416
static cairo_test_status_t
417
overlap_three_quarter_triangles (cairo_t *cr, int width, int height)
418
{
419
    uint8_t *occupancy;
420
    int i, j, channel;
421

            
422
    state = 0x12345678;
423
    occupancy = xmalloc (SAMPLE*SAMPLE);
424

            
425
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
426
    cairo_paint (cr);
427

            
428
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
429
    for (channel = 0; channel < 3; channel++) {
430
	switch (channel) {
431
	default:
432
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
433
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
434
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
435
	}
436

            
437
	for (i = 0; i < SIZE*SIZE; i++) {
438
	    int xs, ys;
439

            
440
	    compute_occupancy (occupancy, SAMPLE/2*SAMPLE/2 * i / (SIZE * SIZE), SAMPLE/2*SAMPLE/2);
441

            
442
	    xs = i % SIZE * SAMPLE;
443
	    ys = i / SIZE * SAMPLE;
444
	    for (j = 0; j < SAMPLE/2*SAMPLE/2; j++) {
445
		if (occupancy[j]) {
446
		    int x = 2 * (j % (SAMPLE/2)) + xs;
447
		    int y = 2 * (j / (SAMPLE/2)) + ys;
448

            
449
		    /* Add a 4-tile composed of two overlapping triangles.
450
		     *   .__.__.
451
		     *   |\   /|
452
		     *   | \ / |
453
		     *   .  x  |
454
		     *   | / \ |
455
		     *   |/   \|
456
		     *   .     .
457
		     *
458
		     * Coverage should be computable as 75%.
459
		     */
460

            
461
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
462
		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+2) / (double) SAMPLE);
463
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
464
		    cairo_close_path (cr);
465

            
466
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
467
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y+2) / (double) SAMPLE);
468
		    cairo_line_to (cr, (x+2) / (double) SAMPLE, (y) / (double) SAMPLE);
469
		    cairo_close_path (cr);
470
		}
471
	    }
472
	    cairo_fill (cr);
473
	}
474
    }
475

            
476
    free (occupancy);
477

            
478
    return CAIRO_TEST_SUCCESS;
479
}
480

            
481
static cairo_test_status_t
482
triangles (cairo_t *cr, int width, int height)
483
{
484
    uint8_t *occupancy;
485
    int i, j, channel;
486

            
487
    state = 0x12345678;
488
    occupancy = xmalloc (SAMPLE*SAMPLE);
489

            
490
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
491
    cairo_paint (cr);
492

            
493
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
494
    for (channel = 0; channel < 3; channel++) {
495
	switch (channel) {
496
	default:
497
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
498
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
499
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
500
	}
501

            
502
	for (i = 0; i < SIZE*SIZE; i++) {
503
	    int xs, ys;
504

            
505
	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
506

            
507
	    xs = i % SIZE * SAMPLE;
508
	    ys = i / SIZE * SAMPLE;
509
	    for (j = 0; j < SAMPLE*SAMPLE; j++) {
510
		if (occupancy[j]) {
511
		    /* Add a tile composed of two non-overlapping triangles.
512
		     *   .__.
513
		     *   | /|
514
		     *   |/ |
515
		     *   .--.
516
		     */
517
		    int x = j % SAMPLE + xs;
518
		    int y = j / SAMPLE + ys;
519

            
520
		    /* top-left triangle */
521
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
522
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y) / (double) SAMPLE);
523
		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+1) / (double) SAMPLE);
524
		    cairo_close_path (cr);
525

            
526
		    /* bottom-right triangle */
527
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y+1) / (double) SAMPLE);
528
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y+1) / (double) SAMPLE);
529
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y) / (double) SAMPLE);
530
		    cairo_close_path (cr);
531
		}
532
	    }
533
	    cairo_fill (cr);
534
	}
535
    }
536

            
537
    free (occupancy);
538

            
539
    return CAIRO_TEST_SUCCESS;
540
}
541

            
542
static cairo_test_status_t
543
intersecting_triangles (cairo_t *cr, int width, int height)
544
{
545
    uint8_t *occupancy;
546
    int i, j, channel;
547

            
548
    state = 0x12345678;
549
    occupancy = xmalloc (SAMPLE*SAMPLE);
550

            
551
    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
552
    cairo_paint (cr);
553

            
554
    cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
555
    for (channel = 0; channel < 3; channel++) {
556
	switch (channel) {
557
	default:
558
	case 0: cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); break;
559
	case 1: cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); break;
560
	case 2: cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); break;
561
	}
562

            
563
	for (i = 0; i < SIZE*SIZE; i++) {
564
	    int xs, ys;
565

            
566
	    compute_occupancy (occupancy, SAMPLE*SAMPLE * i / (SIZE * SIZE), SAMPLE*SAMPLE);
567

            
568
	    xs = i % SIZE * SAMPLE;
569
	    ys = i / SIZE * SAMPLE;
570
	    for (j = 0; j < SAMPLE*SAMPLE; j++) {
571
		if (occupancy[j]) {
572
		    /* Add 2 overlapping tiles in a single cell, each composed
573
		     * of two non-overlapping triangles.
574
		     *   .--.   .--.
575
		     *   | /|   |\ |
576
		     *   |/ | + | \|
577
		     *   .--.   .--.
578
		     */
579
		    int x = j % SAMPLE + xs;
580
		    int y = j / SAMPLE + ys;
581

            
582
		    /* first pair of triangles, diagonal bottom-left to top-right */
583
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
584
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y) / (double) SAMPLE);
585
		    cairo_line_to (cr, (x) / (double) SAMPLE,   (y+1) / (double) SAMPLE);
586
		    cairo_close_path (cr);
587
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y+1) / (double) SAMPLE);
588
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y+1) / (double) SAMPLE);
589
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y) / (double) SAMPLE);
590
		    cairo_close_path (cr);
591

            
592
		    /* second pair of triangles, diagonal top-left to bottom-right */
593
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
594
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y+1) / (double) SAMPLE);
595
		    cairo_line_to (cr, (x+1) / (double) SAMPLE,   (y) / (double) SAMPLE);
596
		    cairo_close_path (cr);
597
		    cairo_move_to (cr, (x) / (double) SAMPLE,   (y) / (double) SAMPLE);
598
		    cairo_line_to (cr, (x+1) / (double) SAMPLE, (y+1) / (double) SAMPLE);
599
		    cairo_line_to (cr, (x) / (double) SAMPLE, (y+1) / (double) SAMPLE);
600
		    cairo_close_path (cr);
601
		}
602
	    }
603
	    cairo_fill (cr);
604
	}
605
    }
606

            
607
    free (occupancy);
608

            
609
    return CAIRO_TEST_SUCCESS;
610
}
611

            
612
1
CAIRO_TEST (partial_coverage_rectangles,
613
	    "Check the fidelity of the rasterisation.",
614
	    "coverage, raster", /* keywords */
615
	    "target=raster slow", /* requirements */
616
	    SIZE, SIZE,
617
	    NULL, rectangles)
618

            
619
1
CAIRO_TEST (partial_coverage_intersecting_quads,
620
	    "Check the fidelity of the rasterisation.",
621
	    "coverage, raster", /* keywords */
622
	    "target=raster slow", /* requirements */
623
	    SIZE, SIZE,
624
	    NULL, intersecting_quads)
625

            
626
1
CAIRO_TEST (partial_coverage_intersecting_triangles,
627
	    "Check the fidelity of the rasterisation.",
628
	    "coverage, raster", /* keywords */
629
	    "target=raster slow", /* requirements */
630
	    SIZE, SIZE,
631
	    NULL, intersecting_triangles)
632
1
CAIRO_TEST (partial_coverage_triangles,
633
	    "Check the fidelity of the rasterisation.",
634
	    "coverage, raster", /* keywords */
635
	    "target=raster slow", /* requirements */
636
	    SIZE, SIZE,
637
	    NULL, triangles)
638
1
CAIRO_TEST (partial_coverage_overlap_three_quarter_triangles,
639
	    "Check the fidelity of the rasterisation.",
640
	    "coverage, raster", /* keywords */
641
	    "target=raster slow", /* requirements */
642
	    SIZE, SIZE,
643
	    NULL, overlap_three_quarter_triangles)
644
1
CAIRO_TEST (partial_coverage_overlap_half_triangles_eo,
645
	    "Check the fidelity of the rasterisation.",
646
	    "coverage, raster", /* keywords */
647
	    "target=raster slow", /* requirements */
648
	    SIZE, SIZE,
649
	    NULL, overlap_half_triangles_eo)
650
1
CAIRO_TEST (partial_coverage_overlap_half_triangles,
651
	    "Check the fidelity of the rasterisation.",
652
	    "coverage, raster", /* keywords */
653
	    "target=raster slow", /* requirements */
654
	    SIZE, SIZE,
655
	    NULL, overlap_half_triangles)
656
1
CAIRO_TEST (partial_coverage_half_triangles,
657
	    "Check the fidelity of the rasterisation.",
658
	    "coverage, raster", /* keywords */
659
	    "target=raster slow", /* requirements */
660
	    SIZE, SIZE,
661
	    NULL, half_triangles)
662

            
663
1
CAIRO_TEST (partial_coverage_reference,
664
	    "Check the fidelity of this test.",
665
	    "coverage, raster", /* keywords */
666
	    "target=raster", /* requirements */
667
	    SIZE, SIZE,
668
	    NULL, reference)
669
1
CAIRO_TEST (partial_coverage_three_quarter_reference,
670
	    "Check the fidelity of this test.",
671
	    "coverage, raster", /* keywords */
672
	    "target=raster", /* requirements */
673
	    SIZE, SIZE,
674
	    NULL, three_quarter_reference)
675
1
CAIRO_TEST (partial_coverage_half_reference,
676
	    "Check the fidelity of this test.",
677
	    "coverage, raster", /* keywords */
678
	    "target=raster", /* requirements */
679
	    SIZE, SIZE,
680
	    NULL, half_reference)