1 /*
2 * Copyright © 2007 Red Hat, Inc.
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: Carl Worth <cworth@cworth.org>
25 */
26
27 #define _ISOC99_SOURCE /* for INFINITY */
28 #define _GNU_SOURCE 1 /* for fedisableeexcept() et al */
29
30 #include "cairo-test.h"
31
32 #if !defined(INFINITY)
33 #define INFINITY HUGE_VAL
34 #endif
35
36 static cairo_test_status_t
draw(cairo_t * cr,int width,int height)37 draw (cairo_t *cr, int width, int height)
38 {
39 const cairo_test_context_t *ctx = cairo_test_get_context (cr);
40 cairo_status_t status;
41 cairo_surface_t *target;
42 cairo_font_face_t *font_face;
43 cairo_font_options_t *font_options;
44 cairo_scaled_font_t *scaled_font;
45 cairo_pattern_t *pattern;
46 cairo_t *cr2;
47 cairo_matrix_t identity, bogus, inf, invalid = {
48 4.0, 4.0,
49 4.0, 4.0,
50 4.0, 4.0
51 };
52
53 #define CHECK_STATUS(status, function_name) \
54 if ((status) == CAIRO_STATUS_SUCCESS) { \
55 cairo_test_log (ctx, "Error: %s with invalid matrix passed\n", \
56 (function_name)); \
57 return CAIRO_TEST_FAILURE; \
58 } else if ((status) != CAIRO_STATUS_INVALID_MATRIX) { \
59 cairo_test_log (ctx, "Error: %s with invalid matrix returned unexpected status " \
60 "(%d): %s\n", \
61 (function_name), \
62 status, \
63 cairo_status_to_string (status)); \
64 return CAIRO_TEST_FAILURE; \
65 }
66
67 /* clear floating point exceptions (added by cairo_test_init()) */
68 #if HAVE_FEDISABLEEXCEPT
69 fedisableexcept (FE_INVALID);
70 #endif
71
72 /* create a bogus matrix and check results of attempted inversion */
73 bogus.x0 = bogus.xy = bogus.xx = cairo_test_NaN ();
74 bogus.y0 = bogus.yx = bogus.yy = bogus.xx;
75 status = cairo_matrix_invert (&bogus);
76 CHECK_STATUS (status, "cairo_matrix_invert(NaN)");
77
78 inf.x0 = inf.xy = inf.xx = INFINITY;
79 inf.y0 = inf.yx = inf.yy = inf.xx;
80 status = cairo_matrix_invert (&inf);
81 CHECK_STATUS (status, "cairo_matrix_invert(infinity)");
82
83 /* test cairo_matrix_invert with invalid matrix */
84 status = cairo_matrix_invert (&invalid);
85 CHECK_STATUS (status, "cairo_matrix_invert(invalid)");
86
87
88 cairo_matrix_init_identity (&identity);
89
90 target = cairo_get_group_target (cr);
91
92 /* test cairo_transform with invalid matrix */
93 cr2 = cairo_create (target);
94 cairo_transform (cr2, &invalid);
95
96 status = cairo_status (cr2);
97 cairo_destroy (cr2);
98 CHECK_STATUS (status, "cairo_transform(invalid)");
99
100 /* test cairo_transform with bogus matrix */
101 cr2 = cairo_create (target);
102 cairo_transform (cr2, &bogus);
103
104 status = cairo_status (cr2);
105 cairo_destroy (cr2);
106 CHECK_STATUS (status, "cairo_transform(NaN)");
107
108 /* test cairo_transform with ∞ matrix */
109 cr2 = cairo_create (target);
110 cairo_transform (cr2, &inf);
111
112 status = cairo_status (cr2);
113 cairo_destroy (cr2);
114 CHECK_STATUS (status, "cairo_transform(infinity)");
115
116
117 /* test cairo_set_matrix with invalid matrix */
118 cr2 = cairo_create (target);
119 cairo_set_matrix (cr2, &invalid);
120
121 status = cairo_status (cr2);
122 cairo_destroy (cr2);
123 CHECK_STATUS (status, "cairo_set_matrix(invalid)");
124
125 /* test cairo_set_matrix with bogus matrix */
126 cr2 = cairo_create (target);
127 cairo_set_matrix (cr2, &bogus);
128
129 status = cairo_status (cr2);
130 cairo_destroy (cr2);
131 CHECK_STATUS (status, "cairo_set_matrix(NaN)");
132
133 /* test cairo_set_matrix with ∞ matrix */
134 cr2 = cairo_create (target);
135 cairo_set_matrix (cr2, &inf);
136
137 status = cairo_status (cr2);
138 cairo_destroy (cr2);
139 CHECK_STATUS (status, "cairo_set_matrix(infinity)");
140
141
142 /* test cairo_set_font_matrix with invalid matrix */
143 cr2 = cairo_create (target);
144 cairo_set_font_matrix (cr2, &invalid);
145
146 /* draw some text to force the font to be resolved */
147 cairo_show_text (cr2, "hello");
148
149 status = cairo_status (cr2);
150 cairo_destroy (cr2);
151 CHECK_STATUS (status, "cairo_set_font_matrix(invalid)");
152
153 /* test cairo_set_font_matrix with bogus matrix */
154 cr2 = cairo_create (target);
155 cairo_set_font_matrix (cr2, &bogus);
156
157 /* draw some text to force the font to be resolved */
158 cairo_show_text (cr2, "hello");
159
160 status = cairo_status (cr2);
161 cairo_destroy (cr2);
162 CHECK_STATUS (status, "cairo_set_font_matrix(NaN)");
163
164 /* test cairo_set_font_matrix with ∞ matrix */
165 cr2 = cairo_create (target);
166 cairo_set_font_matrix (cr2, &inf);
167
168 /* draw some text to force the font to be resolved */
169 cairo_show_text (cr2, "hello");
170
171 status = cairo_status (cr2);
172 cairo_destroy (cr2);
173 CHECK_STATUS (status, "cairo_set_font_matrix(infinity)");
174
175
176 /* test cairo_scaled_font_create with invalid matrix */
177 cr2 = cairo_create (target);
178 font_face = cairo_get_font_face (cr2);
179 font_options = cairo_font_options_create ();
180 cairo_get_font_options (cr, font_options);
181 scaled_font = cairo_scaled_font_create (font_face,
182 &invalid,
183 &identity,
184 font_options);
185 status = cairo_scaled_font_status (scaled_font);
186 CHECK_STATUS (status, "cairo_scaled_font_create(invalid)");
187
188 cairo_scaled_font_destroy (scaled_font);
189
190 scaled_font = cairo_scaled_font_create (font_face,
191 &identity,
192 &invalid,
193 font_options);
194 status = cairo_scaled_font_status (scaled_font);
195 CHECK_STATUS (status, "cairo_scaled_font_create(invalid)");
196
197 cairo_scaled_font_destroy (scaled_font);
198 cairo_font_options_destroy (font_options);
199 cairo_destroy (cr2);
200
201 /* test cairo_scaled_font_create with bogus matrix */
202 cr2 = cairo_create (target);
203 font_face = cairo_get_font_face (cr2);
204 font_options = cairo_font_options_create ();
205 cairo_get_font_options (cr, font_options);
206 scaled_font = cairo_scaled_font_create (font_face,
207 &bogus,
208 &identity,
209 font_options);
210 status = cairo_scaled_font_status (scaled_font);
211 CHECK_STATUS (status, "cairo_scaled_font_create(NaN)");
212
213 cairo_scaled_font_destroy (scaled_font);
214
215 scaled_font = cairo_scaled_font_create (font_face,
216 &identity,
217 &bogus,
218 font_options);
219 status = cairo_scaled_font_status (scaled_font);
220 CHECK_STATUS (status, "cairo_scaled_font_create(NaN)");
221
222 cairo_scaled_font_destroy (scaled_font);
223 cairo_font_options_destroy (font_options);
224 cairo_destroy (cr2);
225
226 /* test cairo_scaled_font_create with ∞ matrix */
227 cr2 = cairo_create (target);
228 font_face = cairo_get_font_face (cr2);
229 font_options = cairo_font_options_create ();
230 cairo_get_font_options (cr, font_options);
231 scaled_font = cairo_scaled_font_create (font_face,
232 &inf,
233 &identity,
234 font_options);
235 status = cairo_scaled_font_status (scaled_font);
236 CHECK_STATUS (status, "cairo_scaled_font_create(infinity)");
237
238 cairo_scaled_font_destroy (scaled_font);
239
240 scaled_font = cairo_scaled_font_create (font_face,
241 &identity,
242 &inf,
243 font_options);
244 status = cairo_scaled_font_status (scaled_font);
245 CHECK_STATUS (status, "cairo_scaled_font_create(infinity)");
246
247 cairo_scaled_font_destroy (scaled_font);
248 cairo_font_options_destroy (font_options);
249 cairo_destroy (cr2);
250
251
252 /* test cairo_pattern_set_matrix with invalid matrix */
253 pattern = cairo_pattern_create_rgb (1.0, 1.0, 1.0);
254 cairo_pattern_set_matrix (pattern, &invalid);
255 status = cairo_pattern_status (pattern);
256 CHECK_STATUS (status, "cairo_pattern_set_matrix(invalid)");
257 cairo_pattern_destroy (pattern);
258
259 /* test cairo_pattern_set_matrix with bogus matrix */
260 pattern = cairo_pattern_create_rgb (1.0, 1.0, 1.0);
261 cairo_pattern_set_matrix (pattern, &bogus);
262 status = cairo_pattern_status (pattern);
263 CHECK_STATUS (status, "cairo_pattern_set_matrix(NaN)");
264 cairo_pattern_destroy (pattern);
265
266 /* test cairo_pattern_set_matrix with ∞ matrix */
267 pattern = cairo_pattern_create_rgb (1.0, 1.0, 1.0);
268 cairo_pattern_set_matrix (pattern, &inf);
269 status = cairo_pattern_status (pattern);
270 CHECK_STATUS (status, "cairo_pattern_set_matrix(infinity)");
271 cairo_pattern_destroy (pattern);
272
273
274 /* test invalid transformations */
275 cr2 = cairo_create (target);
276 cairo_translate (cr2, bogus.xx, bogus.yy);
277 CHECK_STATUS (status, "cairo_translate(NaN, NaN)");
278 cairo_destroy (cr2);
279
280 cr2 = cairo_create (target);
281 cairo_translate (cr2, 0, bogus.yy);
282 CHECK_STATUS (status, "cairo_translate(0, NaN)");
283 cairo_destroy (cr2);
284
285 cr2 = cairo_create (target);
286 cairo_translate (cr2, bogus.xx, 0);
287 CHECK_STATUS (status, "cairo_translate(NaN, 0)");
288 cairo_destroy (cr2);
289
290 cr2 = cairo_create (target);
291 cairo_translate (cr2, inf.xx, inf.yy);
292 CHECK_STATUS (status, "cairo_translate(∞, ∞)");
293 cairo_destroy (cr2);
294
295 cr2 = cairo_create (target);
296 cairo_translate (cr2, 0, inf.yy);
297 CHECK_STATUS (status, "cairo_translate(0, ∞)");
298 cairo_destroy (cr2);
299
300 cr2 = cairo_create (target);
301 cairo_translate (cr2, inf.xx, 0);
302 CHECK_STATUS (status, "cairo_translate(∞, 0)");
303 cairo_destroy (cr2);
304
305
306 cr2 = cairo_create (target);
307 cairo_scale (cr2, bogus.xx, bogus.yy);
308 CHECK_STATUS (status, "cairo_scale(NaN, NaN)");
309 cairo_destroy (cr2);
310
311 cr2 = cairo_create (target);
312 cairo_scale (cr2, 1, bogus.yy);
313 CHECK_STATUS (status, "cairo_scale(1, NaN)");
314 cairo_destroy (cr2);
315
316 cr2 = cairo_create (target);
317 cairo_scale (cr2, bogus.xx, 1);
318 CHECK_STATUS (status, "cairo_scale(NaN, 1)");
319 cairo_destroy (cr2);
320
321 cr2 = cairo_create (target);
322 cairo_scale (cr2, inf.xx, inf.yy);
323 CHECK_STATUS (status, "cairo_scale(∞, ∞)");
324 cairo_destroy (cr2);
325
326 cr2 = cairo_create (target);
327 cairo_scale (cr2, 1, inf.yy);
328 CHECK_STATUS (status, "cairo_scale(1, ∞)");
329 cairo_destroy (cr2);
330
331 cr2 = cairo_create (target);
332 cairo_scale (cr2, inf.xx, 1);
333 CHECK_STATUS (status, "cairo_scale(∞, 1)");
334 cairo_destroy (cr2);
335
336 cr2 = cairo_create (target);
337 cairo_scale (cr2, bogus.xx, bogus.yy);
338 CHECK_STATUS (status, "cairo_scale(0, 0)");
339 cairo_destroy (cr2);
340
341 cr2 = cairo_create (target);
342 cairo_scale (cr2, 1, bogus.yy);
343 CHECK_STATUS (status, "cairo_scale(1, 0)");
344 cairo_destroy (cr2);
345
346 cr2 = cairo_create (target);
347 cairo_scale (cr2, bogus.xx, 1);
348 CHECK_STATUS (status, "cairo_scale(0, 1)");
349 cairo_destroy (cr2);
350
351
352 cr2 = cairo_create (target);
353 cairo_rotate (cr2, bogus.xx);
354 CHECK_STATUS (status, "cairo_rotate(NaN)");
355 cairo_destroy (cr2);
356
357 cr2 = cairo_create (target);
358 cairo_rotate (cr2, inf.xx);
359 CHECK_STATUS (status, "cairo_rotate(∞)");
360 cairo_destroy (cr2);
361
362 #if HAVE_FECLEAREXCEPT
363 feclearexcept (FE_INVALID);
364 #endif
365
366 return CAIRO_TEST_SUCCESS;
367 }
368
369 CAIRO_TEST (invalid_matrix,
370 "Test that all relevant public functions return CAIRO_STATUS_INVALID_MATRIX as appropriate",
371 "api, matrix", /* keywords */
372 NULL, /* requirements */
373 0, 0,
374 NULL, draw)
375