1
/*
2
 * Copyright © 2008 Chris Wilson
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
static cairo_test_status_t
30
1
preamble (cairo_test_context_t *ctx)
31
{
32
1
    cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
33
    cairo_surface_t *surface;
34
    cairo_t *cr;
35

            
36
1
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
37
1
    cr = cairo_create (surface);
38
1
    cairo_surface_destroy (surface);
39

            
40
1
    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
41

            
42
    /* simple rectangle */
43
1
    cairo_new_path (cr);
44
1
    cairo_rectangle (cr, -10, -10, 20, 20);
45
1
    if (! cairo_in_fill (cr, 0, 0)) {
46
	cairo_test_log (ctx, "Error: Failed to find point inside rectangle\n");
47
	ret = CAIRO_TEST_FAILURE;
48
    }
49

            
50
    /* rectangular boundary tests */
51
1
    if (! cairo_in_fill (cr, -10, -10)) {
52
	cairo_test_log (ctx, "Error: Failed to find top-left vertex inside rectangle\n");
53
	ret = CAIRO_TEST_FAILURE;
54
    }
55
1
    if (! cairo_in_fill (cr, -10, 10)) {
56
	cairo_test_log (ctx, "Error: Failed to find bottom-left vertex inside rectangle\n");
57
	ret = CAIRO_TEST_FAILURE;
58
    }
59
1
    if (! cairo_in_fill (cr, 10, -10)) {
60
	cairo_test_log (ctx, "Error: Failed to find top-right vertex inside rectangle\n");
61
	ret = CAIRO_TEST_FAILURE;
62
    }
63
1
    if (! cairo_in_fill (cr, 10, 10)) {
64
	cairo_test_log (ctx, "Error: Failed to find bottom-right vertex inside rectangle\n");
65
	ret = CAIRO_TEST_FAILURE;
66
    }
67
1
    if (! cairo_in_fill (cr, -10, 0)) {
68
	cairo_test_log (ctx, "Error: Failed to find left edge inside rectangle\n");
69
	ret = CAIRO_TEST_FAILURE;
70
    }
71
1
    if (! cairo_in_fill (cr, 0, -10)) {
72
	cairo_test_log (ctx, "Error: Failed to find top edge inside rectangle\n");
73
	ret = CAIRO_TEST_FAILURE;
74
    }
75
1
    if (! cairo_in_fill (cr, 10, 0)) {
76
	cairo_test_log (ctx, "Error: Failed to find right edge inside rectangle\n");
77
	ret = CAIRO_TEST_FAILURE;
78
    }
79
1
    if (! cairo_in_fill (cr, 0, 10)) {
80
	cairo_test_log (ctx, "Error: Failed to find bottom edge inside rectangle\n");
81
	ret = CAIRO_TEST_FAILURE;
82
    }
83

            
84
    /* simple circle */
85
1
    cairo_new_path (cr);
86
1
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
87
1
    if (! cairo_in_fill (cr, 0, 0)) {
88
	cairo_test_log (ctx, "Error: Failed to find point inside circle [even-odd]\n");
89
	ret = CAIRO_TEST_FAILURE;
90
    }
91

            
92
    /* holey rectangle */
93
1
    cairo_new_path (cr);
94
1
    cairo_rectangle (cr, -10, -10, 20, 20);
95
1
    cairo_rectangle (cr, -5, -5, 10, 10);
96
1
    if (cairo_in_fill (cr, 0, 0)) {
97
	cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular eo-hole\n");
98
	ret = CAIRO_TEST_FAILURE;
99
    }
100

            
101
    /* holey circle */
102
1
    cairo_new_path (cr);
103
1
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
104
1
    cairo_arc (cr, 0, 0, 5, 0, 2 * M_PI);
105
1
    if (cairo_in_fill (cr, 0, 0)) {
106
	cairo_test_log (ctx, "Error: Found an unexpected point inside circular eo-hole\n");
107
	ret = CAIRO_TEST_FAILURE;
108
    }
109

            
110

            
111
1
    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
112

            
113
    /* simple rectangle */
114
1
    cairo_new_path (cr);
115
1
    cairo_rectangle (cr, -10, -10, 20, 20);
116
1
    if (! cairo_in_fill (cr, 0, 0)) {
117
	cairo_test_log (ctx, "Error: Failed to find point inside rectangle\n");
118
	ret = CAIRO_TEST_FAILURE;
119
    }
120

            
121
    /* simple circle */
122
1
    cairo_new_path (cr);
123
1
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
124
1
    if (! cairo_in_fill (cr, 0, 0)) {
125
	cairo_test_log (ctx, "Error: Failed to find point inside circle [nonzero]\n");
126
	ret = CAIRO_TEST_FAILURE;
127
    }
128

            
129
    /* overlapping circle/rectangle */
130
1
    cairo_new_path (cr);
131
1
    cairo_rectangle (cr, -10, -10, 20, 20);
132
1
    cairo_new_sub_path (cr);
133
1
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
134
1
    if (! cairo_in_fill (cr, 0, 0)) {
135
	cairo_test_log (ctx, "Error: Failed to find point inside circle+rectangle\n");
136
	ret = CAIRO_TEST_FAILURE;
137
    }
138

            
139
    /* holey rectangle */
140
1
    cairo_new_path (cr);
141
1
    cairo_rectangle (cr, -10, -10, 20, 20);
142
1
    cairo_rectangle (cr, 5, -5, -10, 10);
143
1
    if (cairo_in_fill (cr, 0, 0)) {
144
	cairo_test_log (ctx, "Error: Found an unexpected point inside rectangular non-zero-hole\n");
145
	ret = CAIRO_TEST_FAILURE;
146
    }
147

            
148
    /* holey circle */
149
1
    cairo_new_path (cr);
150
1
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
151
1
    cairo_arc_negative (cr, 0, 0, 5, 0, -2 * M_PI);
152
1
    if (cairo_in_fill (cr, 0, 0)) {
153
	cairo_test_log (ctx, "Error: Found an unexpected point inside circular non-zero-hole\n");
154
	ret = CAIRO_TEST_FAILURE;
155
    }
156

            
157
    /* not a holey circle */
158
1
    cairo_new_path (cr);
159
1
    cairo_arc (cr, 0, 0, 10, 0, 2 * M_PI);
160
1
    cairo_arc (cr, 0, 0, 5, 0, 2 * M_PI);
161
1
    if (! cairo_in_fill (cr, 0, 0)) {
162
	cairo_test_log (ctx, "Error: Failed to find point inside two circles\n");
163
	ret = CAIRO_TEST_FAILURE;
164
    }
165

            
166
    /* check off-centre */
167
1
    cairo_new_path (cr);
168
1
    cairo_arc (cr, 7.5, 0, 10, 0, 2 * M_PI);
169
1
    cairo_arc_negative (cr, 7.5, 0, 5, 0, -2 * M_PI);
170
1
    if (cairo_in_fill (cr, 7.5, 0)) {
171
	cairo_test_log (ctx, "Error: Found an unexpected point inside off-centre-x circular non-zero-hole\n");
172
	ret = CAIRO_TEST_FAILURE;
173
    }
174
1
    cairo_new_path (cr);
175
1
    cairo_arc (cr, 0, 7.5, 10, 0, 2 * M_PI);
176
1
    cairo_arc_negative (cr, 0, 7.5, 5, 0, -2 * M_PI);
177
1
    if (cairo_in_fill (cr, 0, 7.5)) {
178
	cairo_test_log (ctx, "Error: Found an unexpected point inside off-centre-y circular non-zero-hole\n");
179
	ret = CAIRO_TEST_FAILURE;
180
    }
181
1
    cairo_new_path (cr);
182
1
    cairo_arc (cr, 15, 0, 10, 0, 2 * M_PI);
183
1
    if (! cairo_in_fill (cr, 15, 0)) {
184
	cairo_test_log (ctx, "Error: Failed to find point inside off-centre-x circle\n");
185
	ret = CAIRO_TEST_FAILURE;
186
    }
187
1
    cairo_new_path (cr);
188
1
    cairo_arc (cr, 0, 15, 10, 0, 2 * M_PI);
189
1
    if (! cairo_in_fill (cr, 0, 15)) {
190
	cairo_test_log (ctx, "Error: Failed to find point inside off-centre-y circle\n");
191
	ret = CAIRO_TEST_FAILURE;
192
    }
193

            
194
    /* simple rectangle */
195
1
    cairo_new_path (cr);
196
1
    cairo_rectangle (cr, 10, 0, 5, 5);
197
1
    if (cairo_in_fill (cr, 0, 0)) {
198
	cairo_test_log (ctx, "Error: Found an unexpected point outside rectangle\n");
199
	ret = CAIRO_TEST_FAILURE;
200
    }
201
1
    if (cairo_in_fill (cr, 20, 20)) {
202
	cairo_test_log (ctx, "Error: Found an unexpected point outside rectangle\n");
203
	ret = CAIRO_TEST_FAILURE;
204
    }
205
1
    if (! cairo_in_fill (cr, 12.5, 2.5)) {
206
	cairo_test_log (ctx, "Error: Failed to find point inside rectangle\n");
207
	ret = CAIRO_TEST_FAILURE;
208
    }
209

            
210
    /* off-centre triangle */
211
1
    cairo_new_path (cr);
212
1
    cairo_move_to (cr, 10, 0);
213
1
    cairo_line_to (cr, 15, 5);
214
1
    cairo_line_to (cr, 5, 5);
215
1
    cairo_close_path (cr);
216
2
    if (cairo_in_fill (cr, 0, 0) ||
217
2
	cairo_in_fill (cr, 5, 0) ||
218
2
	cairo_in_fill (cr, 15, 0) ||
219
2
	cairo_in_fill (cr, 20, 0) ||
220
2
	cairo_in_fill (cr, 0, 10) ||
221
2
	cairo_in_fill (cr, 10, 10) ||
222
2
	cairo_in_fill (cr, 20, 10) ||
223
2
	cairo_in_fill (cr, 7, 2.5) ||
224
1
	cairo_in_fill (cr, 13, 2.5))
225
    {
226
	cairo_test_log (ctx,
227
			"Error: Found an unexpected point outside triangle\n"
228
			"\t(0, 0) -> %s\n"
229
			"\t(5, 0) -> %s\n"
230
			"\t(15, 0) -> %s\n"
231
			"\t(20, 0) -> %s\n"
232
			"\t(0, 10) -> %s\n"
233
			"\t(10, 10) -> %s\n"
234
			"\t(20, 10) -> %s\n"
235
			"\t(7, 2.5) -> %s\n"
236
			"\t(13, 2.5) -> %s\n",
237
			cairo_in_fill (cr, 0, 0) ? "inside" : "outside",
238
			cairo_in_fill (cr, 5, 0) ? "inside" : "outside",
239
			cairo_in_fill (cr, 15, 0) ? "inside" : "outside",
240
			cairo_in_fill (cr, 20, 0) ? "inside" : "outside",
241
			cairo_in_fill (cr, 0, 10) ? "inside" : "outside",
242
			cairo_in_fill (cr, 10, 10) ? "inside" : "outside",
243
			cairo_in_fill (cr, 20, 10) ? "inside" : "outside",
244
			cairo_in_fill (cr, 7, 2.5) ? "inside" : "outside",
245
			cairo_in_fill (cr, 13, 2.5) ? "inside" : "outside");
246
	ret = CAIRO_TEST_FAILURE;
247
    }
248
2
    if (! cairo_in_fill (cr, 7.5, 2.5) ||
249
2
	! cairo_in_fill (cr, 12.5, 2.5) ||
250
1
	! cairo_in_fill (cr, 10, 5))
251
    {
252
	cairo_test_log (ctx,
253
			"Error: Failed to find point on triangle edge\n"
254
			"\t(7.5, 2.5) -> %s\n"
255
			"\t(12.5, 2.5) -> %s\n"
256
			"\t(10, 5) -> %s\n",
257
			cairo_in_fill (cr, 7.5, 2.5) ? "inside" : "outside",
258
			cairo_in_fill (cr, 12.5, 2.5) ? "inside" : "outside",
259
			cairo_in_fill (cr, 10, 5) ? "inside" : "outside");
260
	ret = CAIRO_TEST_FAILURE;
261
    }
262
2
    if (! cairo_in_fill (cr, 8, 2.5) ||
263
1
	! cairo_in_fill (cr, 12, 2.5))
264
    {
265
	cairo_test_log (ctx, "Error: Failed to find point inside triangle\n");
266
	ret = CAIRO_TEST_FAILURE;
267
    }
268

            
269
1
    cairo_destroy (cr);
270

            
271
1
    return ret;
272
}
273

            
274
1
CAIRO_TEST (in_fill_trapezoid,
275
	    "Test cairo_in_fill",
276
	    "in, trap", /* keywords */
277
	    NULL, /* requirements */
278
	    0, 0,
279
	    preamble, NULL)