2 * Copyright © 2006 Novell, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Novell, Inc. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission. Novell, Inc. makes no representations about the
12 * suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
18 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Robert O'Callahan <rocallahan@novell.com>
26 #include "cairo-test.h"
29 static cairo_test_draw_function_t draw
;
33 "Test cairo_copy_clip_rectangle_list and cairo_clip_extents",
39 check_count (const char *message
, cairo_bool_t uses_clip_rects
,
40 cairo_rectangle_list_t
*list
, int expected
)
42 if (!uses_clip_rects
) {
43 if (expected
== 0 && list
->num_rectangles
== 0)
45 if (list
->num_rectangles
== expected
)
47 if (list
->status
== CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
)
49 cairo_test_log ("Error: %s; cairo_copy_clip_rectangle_list unexpectedly got %d rectangles\n",
50 message
, list
->num_rectangles
);
54 if (list
->status
!= CAIRO_STATUS_SUCCESS
) {
55 cairo_test_log ("Error: %s; cairo_copy_clip_rectangle_list failed with \"%s\"\n",
56 message
, cairo_status_to_string(list
->status
));
60 if (list
->num_rectangles
== expected
)
62 cairo_test_log ("Error: %s; expected %d rectangles, got %d\n", message
,
63 expected
, list
->num_rectangles
);
68 check_unrepresentable (const char *message
, cairo_rectangle_list_t
*list
)
70 if (list
->status
!= CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
) {
71 cairo_test_log ("Error: %s; cairo_copy_clip_rectangle_list got unexpected result \"%s\"\n"
72 " (we expected CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)",
73 message
, cairo_status_to_string(list
->status
));
80 check_rectangles_contain (const char *message
, cairo_bool_t uses_clip_rects
,
81 cairo_rectangle_list_t
*list
,
82 double x
, double y
, double width
, double height
)
89 for (i
= 0; i
< list
->num_rectangles
; ++i
) {
90 if (list
->rectangles
[i
].x
== x
&& list
->rectangles
[i
].y
== y
&&
91 list
->rectangles
[i
].width
== width
&& list
->rectangles
[i
].height
== height
)
94 cairo_test_log ("Error: %s; rectangle list does not contain rectangle %f,%f,%f,%f\n",
95 message
, x
, y
, width
, height
);
100 check_clip_extents (const char *message
, cairo_t
*cr
,
101 double x
, double y
, double width
, double height
)
103 double ext_x1
, ext_y1
, ext_x2
, ext_y2
;
104 cairo_clip_extents (cr
, &ext_x1
, &ext_y1
, &ext_x2
, &ext_y2
);
105 if (ext_x1
== x
&& ext_y1
== y
&& ext_x2
== x
+ width
&& ext_y2
== y
+ height
)
107 cairo_test_log ("Error: %s; clip extents %f,%f,%f,%f should be %f,%f,%f,%f\n",
108 message
, ext_x1
, ext_y1
, ext_x2
- ext_x1
, ext_y2
- ext_y1
,
109 x
, y
, width
, height
);
113 static cairo_test_status_t
114 draw (cairo_t
*cr
, int width
, int height
)
116 cairo_surface_t
*surface
;
118 cairo_rectangle_list_t
*rectangle_list
;
120 cairo_bool_t uses_clip_rects
;
122 surface
= cairo_surface_create_similar (cairo_get_group_target (cr
),
123 CAIRO_CONTENT_COLOR
, 100, 100);
124 /* don't use cr accidentally */
126 cr2
= cairo_create (surface
);
127 cairo_surface_destroy (surface
);
129 /* Check the surface type so we ignore cairo_copy_clip_rectangle_list failures
130 * on surface types that don't use rectangle lists for clipping.
131 * Default to FALSE for the internal surface types, (meta, test-fallback, etc.)
133 switch (cairo_surface_get_type (surface
)) {
134 case CAIRO_SURFACE_TYPE_IMAGE
:
135 case CAIRO_SURFACE_TYPE_XLIB
:
136 case CAIRO_SURFACE_TYPE_XCB
:
137 case CAIRO_SURFACE_TYPE_GLITZ
:
138 case CAIRO_SURFACE_TYPE_WIN32
:
139 case CAIRO_SURFACE_TYPE_BEOS
:
140 case CAIRO_SURFACE_TYPE_DIRECTFB
:
141 uses_clip_rects
= TRUE
;
143 case CAIRO_SURFACE_TYPE_QUARTZ
:
144 case CAIRO_SURFACE_TYPE_PDF
:
145 case CAIRO_SURFACE_TYPE_PS
:
146 case CAIRO_SURFACE_TYPE_SVG
:
147 case CAIRO_SURFACE_TYPE_OS2
:
149 uses_clip_rects
= FALSE
;
153 /* first, test basic stuff. This should not be clipped, it should
154 return the surface rectangle. */
155 phase
= "No clip set";
156 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
157 if (!check_count (phase
, uses_clip_rects
, rectangle_list
, 1) ||
158 !check_clip_extents (phase
, cr2
, 0, 0, 100, 100) ||
159 !check_rectangles_contain(phase
, uses_clip_rects
, rectangle_list
, 0, 0, 100, 100)) {
160 cairo_rectangle_list_destroy (rectangle_list
);
161 return CAIRO_TEST_FAILURE
;
163 cairo_rectangle_list_destroy (rectangle_list
);
165 /* Test simple clip rect. */
166 phase
= "Simple clip rect";
168 cairo_rectangle (cr2
, 10, 10, 80, 80);
170 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
171 if (!check_count (phase
, uses_clip_rects
, rectangle_list
, 1) ||
172 !check_clip_extents (phase
, cr2
, 10, 10, 80, 80) ||
173 !check_rectangles_contain(phase
, uses_clip_rects
, rectangle_list
, 10, 10, 80, 80)) {
174 cairo_rectangle_list_destroy (rectangle_list
);
175 return CAIRO_TEST_FAILURE
;
177 cairo_rectangle_list_destroy (rectangle_list
);
180 /* Test everything clipped out. */
181 phase
= "All clipped out";
184 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
185 if (!check_count (phase
, uses_clip_rects
, rectangle_list
, 0)) {
186 cairo_rectangle_list_destroy (rectangle_list
);
187 return CAIRO_TEST_FAILURE
;
189 cairo_rectangle_list_destroy (rectangle_list
);
192 /* test two clip rects */
193 phase
= "Two clip rects";
195 cairo_rectangle (cr2
, 10, 10, 10, 10);
196 cairo_rectangle (cr2
, 20, 20, 10, 10);
198 cairo_rectangle (cr2
, 15, 15, 10, 10);
200 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
201 if (!check_count (phase
, uses_clip_rects
, rectangle_list
, 2) ||
202 !check_clip_extents (phase
, cr2
, 15, 15, 10, 10) ||
203 !check_rectangles_contain(phase
, uses_clip_rects
, rectangle_list
, 15, 15, 5, 5) ||
204 !check_rectangles_contain(phase
, uses_clip_rects
, rectangle_list
, 20, 20, 5, 5)) {
205 cairo_rectangle_list_destroy (rectangle_list
);
206 return CAIRO_TEST_FAILURE
;
208 cairo_rectangle_list_destroy (rectangle_list
);
211 /* test non-rectangular clip */
212 phase
= "Nonrectangular clip";
214 cairo_move_to (cr2
, 0, 0);
215 cairo_line_to (cr2
, 100, 100);
216 cairo_line_to (cr2
, 100, 0);
217 cairo_close_path (cr2
);
219 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
220 /* can't get this in one tight user-space rectangle */
221 if (!check_unrepresentable (phase
, rectangle_list
) ||
222 !check_clip_extents (phase
, cr2
, 0, 0, 100, 100)) {
223 cairo_rectangle_list_destroy (rectangle_list
);
224 return CAIRO_TEST_FAILURE
;
226 cairo_rectangle_list_destroy (rectangle_list
);
229 phase
= "User space, simple scale, getting clip with same transform";
231 cairo_scale (cr2
, 2, 2);
232 cairo_rectangle (cr2
, 5, 5, 40, 40);
234 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
235 if (!check_count (phase
, uses_clip_rects
, rectangle_list
, 1) ||
236 !check_clip_extents (phase
, cr2
, 5, 5, 40, 40) ||
237 !check_rectangles_contain(phase
, uses_clip_rects
, rectangle_list
, 5, 5, 40, 40)) {
238 cairo_rectangle_list_destroy (rectangle_list
);
239 return CAIRO_TEST_FAILURE
;
241 cairo_rectangle_list_destroy (rectangle_list
);
244 phase
= "User space, simple scale, getting clip with no transform";
247 cairo_scale (cr2
, 2, 2);
248 cairo_rectangle (cr2
, 5, 5, 40, 40);
251 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
252 if (!check_count (phase
, uses_clip_rects
, rectangle_list
, 1) ||
253 !check_clip_extents (phase
, cr2
, 10, 10, 80, 80) ||
254 !check_rectangles_contain(phase
, uses_clip_rects
, rectangle_list
, 10, 10, 80, 80)) {
255 cairo_rectangle_list_destroy (rectangle_list
);
256 return CAIRO_TEST_FAILURE
;
258 cairo_rectangle_list_destroy (rectangle_list
);
261 phase
= "User space, rotation, getting clip with no transform";
264 cairo_rotate (cr2
, 12);
265 cairo_rectangle (cr2
, 5, 5, 40, 40);
268 rectangle_list
= cairo_copy_clip_rectangle_list (cr2
);
269 if (!check_unrepresentable (phase
, rectangle_list
)) {
270 cairo_rectangle_list_destroy (rectangle_list
);
271 return CAIRO_TEST_FAILURE
;
273 cairo_rectangle_list_destroy (rectangle_list
);
277 return CAIRO_TEST_SUCCESS
;
283 return cairo_test (&test
);