1
/*
2
 * Copyright © 2006 M Joonas Pihlaja
3
 * Copyright © 2011 Chris Wilson
4
 *
5
 * Permission is hereby granted, free of charge, to any person
6
 * obtaining a copy of this software and associated documentation
7
 * files (the "Software"), to deal in the Software without
8
 * restriction, including without limitation the rights to use, copy,
9
 * modify, merge, publish, distribute, sublicense, and/or sell copies
10
 * of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE.
24
 *
25
 * Authors:
26
 *   M Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
27
 *   Chris Wilson <chris@chris-wilson.co.uk>
28
 */
29
#include "cairo-test.h"
30

            
31
#define SIZE 512
32
#define STEP (512+2)
33
#define NUM_SEGMENTS 128
34

            
35
static uint32_t state;
36

            
37
static double
38
14592
uniform_random (double minval, double maxval)
39
{
40
    static uint32_t const poly = 0x9a795537U;
41
14592
    uint32_t n = 32;
42
481536
    while (n-->0)
43
466944
	state = 2*state < state ? (2*state ^ poly) : 2*state;
44
14592
    return minval + state * (maxval - minval) / 4294967296.0;
45
}
46

            
47
24
static void nz_path (cairo_t *cr)
48
{
49
    int i;
50

            
51
24
    state = 0xc0ffee;
52

            
53
24
    cairo_move_to (cr, 0, 0);
54
3096
    for (i = 0; i < NUM_SEGMENTS; i++) {
55
3072
	double x = uniform_random (0, SIZE);
56
3072
	double y = uniform_random (0, SIZE);
57
3072
	cairo_line_to (cr, x, y);
58
    }
59
24
    cairo_close_path (cr);
60
24
}
61

            
62
6
static void region_path (cairo_t *cr)
63
{
64
    int i;
65

            
66
6
    state = 0xc0ffee;
67

            
68
774
    for (i = 0; i < NUM_SEGMENTS; i++) {
69
768
	int x = uniform_random (0, SIZE);
70
768
	int y = uniform_random (0, SIZE);
71
768
	int w = uniform_random (0, 40);
72
768
	int h = uniform_random (0, 40);
73
768
	cairo_rectangle (cr, x, y, w, h);
74
    }
75
6
}
76

            
77
6
static void rectangle_path (cairo_t *cr)
78
{
79
    int i;
80

            
81
6
    state = 0xc0ffee;
82

            
83
774
    for (i = 0; i < NUM_SEGMENTS; i++) {
84
768
	double x = uniform_random (0, SIZE);
85
768
	double y = uniform_random (0, SIZE);
86
768
	double w = uniform_random (0, 40);
87
768
	double h = uniform_random (0, 40);
88
768
	cairo_rectangle (cr, x, y, w, h);
89
    }
90
6
}
91

            
92
6
static void arc_path (cairo_t *cr)
93
{
94
    int i;
95

            
96
6
    state = 0xc0ffee;
97

            
98
774
    for (i = 0; i < NUM_SEGMENTS; i++) {
99
768
	double x = uniform_random (0, SIZE);
100
768
	double y = uniform_random (0, SIZE);
101
768
	double r = uniform_random (0, 20);
102
768
	cairo_new_sub_path (cr);
103
768
	cairo_arc (cr, x, y, r, 0, 2*M_PI);
104
    }
105
6
}
106

            
107

            
108
18
static void nz_fill_stroke (cairo_t *cr)
109
{
110
18
    nz_path (cr);
111

            
112
18
    cairo_set_source_rgb (cr, 1, 0, 0);
113
18
    cairo_fill_preserve (cr);
114
18
    cairo_set_source_rgb (cr, 0, 1, 0);
115
18
    cairo_set_line_width (cr, 1.0);
116
18
    cairo_stroke (cr);
117
18
}
118

            
119
18
static void clip_to_quadrant (cairo_t *cr)
120
{
121
18
    cairo_rectangle (cr, 0, 0, SIZE, SIZE);
122
18
    cairo_clip (cr);
123
18
}
124

            
125
static cairo_test_status_t
126
3
draw (cairo_t *cr, int width, int height)
127
{
128
3
    cairo_set_source_rgb (cr, 0, 0, 0);
129
3
    cairo_paint (cr);
130

            
131
3
    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
132

            
133
3
    state = 0xc0ffee;
134
3
    cairo_translate (cr, 1, 1);
135

            
136
    /* no clipping */
137
3
    cairo_save (cr); {
138
3
	clip_to_quadrant (cr);
139

            
140
3
	nz_fill_stroke (cr);
141
3
    } cairo_restore (cr);
142

            
143
3
    cairo_translate (cr, STEP, 0);
144

            
145
    /* random clipping */
146
3
    cairo_save (cr); {
147
3
	clip_to_quadrant (cr);
148

            
149
3
	nz_path (cr);
150
3
	cairo_clip (cr);
151

            
152
3
	nz_fill_stroke (cr);
153

            
154
3
	cairo_set_source_rgba (cr, 1, 1, 1, 0.5);
155
3
	cairo_paint (cr);
156
3
    } cairo_restore (cr);
157

            
158
3
    cairo_translate (cr, STEP, 0);
159

            
160
    /* regional clipping */
161
3
    cairo_save (cr); {
162
3
	clip_to_quadrant (cr);
163

            
164
3
	region_path (cr);
165
3
	cairo_clip (cr);
166

            
167
3
	nz_fill_stroke (cr);
168

            
169
3
	cairo_set_source_rgba (cr, 1, 1, 1, 0.5);
170
3
	cairo_paint (cr);
171
3
    } cairo_restore (cr);
172

            
173
3
    cairo_translate (cr, -2*STEP, STEP);
174

            
175
    /* rectangular clipping */
176
3
    cairo_save (cr); {
177
3
	clip_to_quadrant (cr);
178

            
179
3
	rectangle_path (cr);
180
3
	cairo_clip (cr);
181

            
182
3
	nz_fill_stroke (cr);
183

            
184
3
	cairo_set_source_rgba (cr, 1, 1, 1, 0.5);
185
3
	cairo_paint (cr);
186
3
    } cairo_restore (cr);
187

            
188
3
    cairo_translate (cr, STEP, 0);
189

            
190
    /* circular clipping */
191
3
    cairo_save (cr); {
192
3
	clip_to_quadrant (cr);
193

            
194
3
	arc_path (cr);
195
3
	cairo_clip (cr);
196

            
197
3
	nz_fill_stroke (cr);
198

            
199
3
	cairo_set_source_rgba (cr, 1, 1, 1, 0.5);
200
3
	cairo_paint (cr);
201
3
    } cairo_restore (cr);
202

            
203
3
    cairo_translate (cr, STEP, 0);
204

            
205
    /* all-of-the-above clipping */
206
3
    cairo_save (cr); {
207
3
	clip_to_quadrant (cr);
208

            
209
3
	nz_path (cr);
210
3
	cairo_clip (cr);
211
3
	region_path (cr);
212
3
	cairo_clip (cr);
213
3
	rectangle_path (cr);
214
3
	cairo_clip (cr);
215
3
	arc_path (cr);
216
3
	cairo_clip (cr);
217

            
218
3
	nz_fill_stroke (cr);
219

            
220
3
	cairo_set_source_rgba (cr, 1, 1, 1, 0.5);
221
3
	cairo_paint (cr);
222
3
    } cairo_restore (cr);
223

            
224
3
    return CAIRO_TEST_SUCCESS;
225
}
226

            
227
1
CAIRO_TEST (random_clip,
228
	    "Tests the clip generation and intersection computation",
229
	    "trap, clip", /* keywords */
230
	    NULL, /* requirements */
231
	    3*STEP+2, 2*STEP+2,
232
	    NULL, draw)