[REACTOS]
[reactos.git] / rostests / winetests / gdi32 / clipping.c
1 /*
2 * Unit test suite for clipping
3 *
4 * Copyright 2005 Huw Davies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "wine/test.h"
22 #include "winbase.h"
23 #include "wingdi.h"
24 #include "winuser.h"
25
26 static void test_GetRandomRgn(void)
27 {
28 HWND hwnd = CreateWindowExA(0,"BUTTON","test",WS_VISIBLE|WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
29 HDC hdc;
30 HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
31 int ret;
32 RECT rc, rc2;
33 RECT ret_rc, window_rc;
34
35 ok( hwnd != 0, "CreateWindow failed\n" );
36
37 SetRect(&window_rc, 400, 300, 500, 400);
38 SetWindowPos(hwnd, HWND_TOPMOST, window_rc.left, window_rc.top,
39 window_rc.right - window_rc.left, window_rc.bottom - window_rc.top, 0 );
40 hdc = GetDC(hwnd);
41
42 ret = GetRandomRgn(hdc, hrgn, 1);
43 ok(ret == 0, "GetRandomRgn rets %d\n", ret);
44 ret = GetRandomRgn(hdc, hrgn, 2);
45 ok(ret == 0, "GetRandomRgn rets %d\n", ret);
46 ret = GetRandomRgn(hdc, hrgn, 3);
47 ok(ret == 0, "GetRandomRgn rets %d\n", ret);
48
49 /* Set a clip region */
50 SetRect(&rc, 20, 20, 80, 80);
51 IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
52
53 ret = GetRandomRgn(hdc, hrgn, 1);
54 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
55 GetRgnBox(hrgn, &ret_rc);
56 ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
57 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
58
59 ret = GetRandomRgn(hdc, hrgn, 2);
60 ok(ret == 0, "GetRandomRgn rets %d\n", ret);
61
62 ret = GetRandomRgn(hdc, hrgn, 3);
63 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
64 GetRgnBox(hrgn, &ret_rc);
65 ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
66 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
67
68 /* Move the clip to the meta and clear the clip */
69 SetMetaRgn(hdc);
70
71 ret = GetRandomRgn(hdc, hrgn, 1);
72 ok(ret == 0, "GetRandomRgn rets %d\n", ret);
73 ret = GetRandomRgn(hdc, hrgn, 2);
74 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
75 GetRgnBox(hrgn, &ret_rc);
76 ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
77 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
78
79 ret = GetRandomRgn(hdc, hrgn, 3);
80 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
81 GetRgnBox(hrgn, &ret_rc);
82 ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
83 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
84
85 /* Set a new clip (still got the meta) */
86 SetRect(&rc2, 10, 30, 70, 90);
87 IntersectClipRect(hdc, rc2.left, rc2.top, rc2.right, rc2.bottom);
88
89 ret = GetRandomRgn(hdc, hrgn, 1);
90 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
91 GetRgnBox(hrgn, &ret_rc);
92 ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
93 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
94
95 ret = GetRandomRgn(hdc, hrgn, 2);
96 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
97 GetRgnBox(hrgn, &ret_rc);
98 ok(EqualRect(&rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
99 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
100
101 IntersectRect(&rc2, &rc, &rc2);
102
103 ret = GetRandomRgn(hdc, hrgn, 3);
104 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
105 GetRgnBox(hrgn, &ret_rc);
106 ok(EqualRect(&rc2, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
107 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
108
109
110 ret = GetRandomRgn(hdc, hrgn, SYSRGN);
111 ok(ret != 0, "GetRandomRgn rets %d\n", ret);
112 GetRgnBox(hrgn, &ret_rc);
113 if(GetVersion() & 0x80000000)
114 OffsetRect(&window_rc, -window_rc.left, -window_rc.top);
115 /* the window may be partially obscured so the region may be smaller */
116 IntersectRect( &window_rc, &ret_rc, &ret_rc );
117 ok(EqualRect(&window_rc, &ret_rc) ||
118 broken(IsRectEmpty(&ret_rc)), /* win95 */
119 "GetRandomRgn %d,%d - %d,%d\n",
120 ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
121
122 DeleteObject(hrgn);
123 ReleaseDC(hwnd, hdc);
124 DestroyWindow(hwnd);
125 }
126
127 static void verify_region(HRGN hrgn, const RECT *rc)
128 {
129 union
130 {
131 RGNDATA data;
132 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
133 } rgn;
134 const RECT *rect;
135 DWORD ret;
136
137 ret = GetRegionData(hrgn, 0, NULL);
138 if (IsRectEmpty(rc))
139 ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
140 else
141 ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
142
143 if (!ret) return;
144
145 ret = GetRegionData(hrgn, sizeof(rgn), &rgn.data);
146 if (IsRectEmpty(rc))
147 ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
148 else
149 ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
150
151 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
152 rgn.data.rdh.dwSize, rgn.data.rdh.iType,
153 rgn.data.rdh.nCount, rgn.data.rdh.nRgnSize,
154 rgn.data.rdh.rcBound.left, rgn.data.rdh.rcBound.top,
155 rgn.data.rdh.rcBound.right, rgn.data.rdh.rcBound.bottom);
156 if (rgn.data.rdh.nCount != 0)
157 {
158 rect = (const RECT *)rgn.data.Buffer;
159 trace("rect (%d,%d-%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom);
160 ok(EqualRect(rect, rc), "rects don't match\n");
161 }
162
163 ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", rgn.data.rdh.dwSize);
164 ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn.data.rdh.iType);
165 if (IsRectEmpty(rc))
166 {
167 ok(rgn.data.rdh.nCount == 0, "expected 0, got %u\n", rgn.data.rdh.nCount);
168 ok(rgn.data.rdh.nRgnSize == 0 ||
169 broken(rgn.data.rdh.nRgnSize == 168), /* NT4 */
170 "expected 0, got %u\n", rgn.data.rdh.nRgnSize);
171 }
172 else
173 {
174 ok(rgn.data.rdh.nCount == 1, "expected 1, got %u\n", rgn.data.rdh.nCount);
175 ok(rgn.data.rdh.nRgnSize == sizeof(RECT) ||
176 broken(rgn.data.rdh.nRgnSize == 168), /* NT4 */
177 "expected sizeof(RECT), got %u\n", rgn.data.rdh.nRgnSize);
178 }
179 ok(EqualRect(&rgn.data.rdh.rcBound, rc), "rects don't match\n");
180 }
181
182 static void test_ExtCreateRegion(void)
183 {
184 static const RECT empty_rect;
185 static const RECT rc = { 111, 222, 333, 444 };
186 static const RECT rc_xformed = { 76, 151, 187, 262 };
187 union
188 {
189 RGNDATA data;
190 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
191 } rgn;
192 HRGN hrgn;
193 XFORM xform;
194
195 if (0) /* crashes under Win9x */
196 {
197 SetLastError(0xdeadbeef);
198 hrgn = ExtCreateRegion(NULL, 0, NULL);
199 ok(!hrgn, "ExtCreateRegion should fail\n");
200 ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
201 }
202
203 rgn.data.rdh.dwSize = 0;
204 rgn.data.rdh.iType = 0;
205 rgn.data.rdh.nCount = 0;
206 rgn.data.rdh.nRgnSize = 0;
207 SetRectEmpty(&rgn.data.rdh.rcBound);
208 memcpy(rgn.data.Buffer, &rc, sizeof(rc));
209
210 SetLastError(0xdeadbeef);
211 hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
212 ok(!hrgn, "ExtCreateRegion should fail\n");
213 ok(GetLastError() == 0xdeadbeef, "0xdeadbeef, got %u\n", GetLastError());
214
215 rgn.data.rdh.dwSize = sizeof(rgn.data.rdh) - 1;
216
217 SetLastError(0xdeadbeef);
218 hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
219 ok(!hrgn, "ExtCreateRegion should fail\n");
220 ok(GetLastError() == 0xdeadbeef, "0xdeadbeef, got %u\n", GetLastError());
221
222 /* although XP doesn't care about the type Win9x does */
223 rgn.data.rdh.iType = RDH_RECTANGLES;
224 rgn.data.rdh.dwSize = sizeof(rgn.data.rdh);
225
226 SetLastError(0xdeadbeef);
227 hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
228 ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError());
229 verify_region(hrgn, &empty_rect);
230 DeleteObject(hrgn);
231
232 rgn.data.rdh.nCount = 1;
233 SetRectEmpty(&rgn.data.rdh.rcBound);
234 memcpy(rgn.data.Buffer, &rc, sizeof(rc));
235
236 SetLastError(0xdeadbeef);
237 hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
238 ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError());
239 verify_region(hrgn, &rc);
240 DeleteObject(hrgn);
241
242 rgn.data.rdh.dwSize = sizeof(rgn.data.rdh) + 1;
243
244 SetLastError(0xdeadbeef);
245 hrgn = ExtCreateRegion(NULL, 1, &rgn.data);
246 ok(hrgn != 0 ||
247 broken(GetLastError() == 0xdeadbeef), /* NT4 */
248 "ExtCreateRegion error %u\n", GetLastError());
249 if(hrgn)
250 {
251 verify_region(hrgn, &rc);
252 DeleteObject(hrgn);
253 }
254
255 xform.eM11 = 0.5; /* 50% width */
256 xform.eM12 = 0.0;
257 xform.eM21 = 0.0;
258 xform.eM22 = 0.5; /* 50% height */
259 xform.eDx = 20.0;
260 xform.eDy = 40.0;
261
262 rgn.data.rdh.dwSize = sizeof(rgn.data.rdh);
263
264 SetLastError(0xdeadbeef);
265 hrgn = ExtCreateRegion(&xform, sizeof(rgn), &rgn.data);
266 ok(hrgn != 0, "ExtCreateRegion error %u/%x\n", GetLastError(), GetLastError());
267 verify_region(hrgn, &rc_xformed);
268 DeleteObject(hrgn);
269 }
270
271 static void test_GetClipRgn(void)
272 {
273 HDC hdc;
274 HRGN hrgn, hrgn2, hrgn3, hrgn4;
275 int ret;
276
277 /* Test calling GetClipRgn with NULL device context and region handles. */
278 ret = GetClipRgn(NULL, NULL);
279 ok(ret == -1, "Expected GetClipRgn to return -1, got %d\n", ret);
280
281 hdc = GetDC(NULL);
282 ok(hdc != NULL, "Expected GetDC to return a valid device context handle\n");
283
284 /* Test calling GetClipRgn with a valid device context and NULL region. */
285 ret = GetClipRgn(hdc, NULL);
286 ok(ret == 0 ||
287 ret == -1 /* Win9x */,
288 "Expected GetClipRgn to return 0, got %d\n", ret);
289
290 /* Initialize the test regions. */
291 hrgn = CreateRectRgn(100, 100, 100, 100);
292 ok(hrgn != NULL,
293 "Expected CreateRectRgn to return a handle to a new rectangular region\n");
294
295 hrgn2 = CreateRectRgn(1, 2, 3, 4);
296 ok(hrgn2 != NULL,
297 "Expected CreateRectRgn to return a handle to a new rectangular region\n");
298
299 hrgn3 = CreateRectRgn(1, 2, 3, 4);
300 ok(hrgn3 != NULL,
301 "Expected CreateRectRgn to return a handle to a new rectangular region\n");
302
303 hrgn4 = CreateRectRgn(1, 2, 3, 4);
304 ok(hrgn4 != NULL,
305 "Expected CreateRectRgn to return a handle to a new rectangular region\n");
306
307 /* Try getting a clipping region from the device context
308 * when the device context's clipping region isn't set. */
309 ret = GetClipRgn(hdc, hrgn2);
310 ok(ret == 0, "Expected GetClipRgn to return 0, got %d\n", ret);
311
312 /* The region passed to GetClipRgn should be unchanged. */
313 ret = EqualRgn(hrgn2, hrgn3);
314 ok(ret == 1,
315 "Expected EqualRgn to compare the two regions as equal, got %d\n", ret);
316
317 /* Try setting and getting back a clipping region. */
318 ret = SelectClipRgn(hdc, hrgn);
319 ok(ret == NULLREGION,
320 "Expected SelectClipRgn to return NULLREGION, got %d\n", ret);
321
322 /* Passing a NULL region handle when the device context
323 * has a clipping region results in an error. */
324 ret = GetClipRgn(hdc, NULL);
325 ok(ret == -1, "Expected GetClipRgn to return -1, got %d\n", ret);
326
327 ret = GetClipRgn(hdc, hrgn2);
328 ok(ret == 1, "Expected GetClipRgn to return 1, got %d\n", ret);
329
330 ret = EqualRgn(hrgn, hrgn2);
331 ok(ret == 1,
332 "Expected EqualRgn to compare the two regions as equal, got %d\n", ret);
333
334 /* Try unsetting and then query the clipping region. */
335 ret = SelectClipRgn(hdc, NULL);
336 ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1),
337 "Expected SelectClipRgn to return SIMPLEREGION, got %d\n", ret);
338
339 ret = GetClipRgn(hdc, NULL);
340 ok(ret == 0 ||
341 ret == -1 /* Win9x */,
342 "Expected GetClipRgn to return 0, got %d\n", ret);
343
344 ret = GetClipRgn(hdc, hrgn3);
345 ok(ret == 0, "Expected GetClipRgn to return 0, got %d\n", ret);
346
347 ret = EqualRgn(hrgn3, hrgn4);
348 ok(ret == 1,
349 "Expected EqualRgn to compare the two regions as equal, got %d\n", ret);
350
351 DeleteObject(hrgn4);
352 DeleteObject(hrgn3);
353 DeleteObject(hrgn2);
354 DeleteObject(hrgn);
355 ReleaseDC(NULL, hdc);
356 }
357
358 static void test_memory_dc_clipping(void)
359 {
360 HDC hdc;
361 HRGN hrgn, hrgn_empty;
362 HBITMAP hbmp;
363 RECT rc;
364 int ret;
365
366 hdc = CreateCompatibleDC(0);
367 hrgn_empty = CreateRectRgn(0, 0, 0, 0);
368 hrgn = CreateRectRgn(0, 0, 0, 0);
369 hbmp = CreateCompatibleBitmap(hdc, 100, 100);
370
371 ret = GetClipRgn(hdc, hrgn);
372 ok(ret == 0, "expected 0, got %d\n", ret);
373
374 ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF);
375 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
376
377 ret = GetClipRgn(hdc, hrgn);
378 ok(ret == 1, "expected 1, got %d\n", ret);
379
380 ret = GetRgnBox(hrgn, &rc);
381 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
382 ok(rc.left == 0 && rc.top == 0 && rc.right == 1 && rc.bottom == 1,
383 "expected 0,0-1,1, got %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom);
384
385 ret = ExtSelectClipRgn(hdc, 0, RGN_COPY);
386 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
387
388 ret = GetClipRgn(hdc, hrgn);
389 ok(ret == 0, "expected 0, got %d\n", ret);
390
391 SelectObject(hdc, hbmp);
392
393 ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF);
394 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
395
396 ret = GetClipRgn(hdc, hrgn);
397 ok(ret == 1, "expected 1, got %d\n", ret);
398
399 ret = GetRgnBox(hrgn, &rc);
400 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
401 ok(rc.left == 0 && rc.top == 0 && rc.right == 100 && rc.bottom == 100,
402 "expected 0,0-100,100, got %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom);
403
404 SetRect( &rc, 10, 10, 20, 20 );
405 ret = RectVisible( hdc, &rc );
406 ok( ret, "RectVisible failed for %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom );
407
408 SetRect( &rc, 20, 20, 10, 10 );
409 ret = RectVisible( hdc, &rc );
410 ok( ret, "RectVisible failed for %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom );
411
412 DeleteDC(hdc);
413 DeleteObject(hrgn);
414 DeleteObject(hrgn_empty);
415 DeleteObject(hbmp);
416 }
417
418 static void test_window_dc_clipping(void)
419 {
420 HDC hdc;
421 HRGN hrgn, hrgn_empty;
422 HWND hwnd;
423 RECT rc;
424 int ret, screen_width, screen_height;
425
426 /* Windows versions earlier than Win2k do not support the virtual screen metrics,
427 * so we fall back to the primary screen metrics. */
428 screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
429 if(!screen_width) screen_width = GetSystemMetrics(SM_CXSCREEN);
430 screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
431 if(!screen_height) screen_height = GetSystemMetrics(SM_CYSCREEN);
432
433 trace("screen resolution %d x %d\n", screen_width, screen_height);
434
435 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
436 -100, -100, screen_width * 2, screen_height * 2, 0, 0, 0, NULL);
437 hdc = GetWindowDC(0);
438 hrgn_empty = CreateRectRgn(0, 0, 0, 0);
439 hrgn = CreateRectRgn(0, 0, 0, 0);
440
441 ret = GetClipRgn(hdc, hrgn);
442 ok(ret == 0, "expected 0, got %d\n", ret);
443
444 ret = ExtSelectClipRgn(hdc, hrgn_empty, RGN_DIFF);
445 ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1),
446 "expected SIMPLEREGION, got %d\n", ret);
447
448 ret = GetClipRgn(hdc, hrgn);
449 ok(ret == 1, "expected 1, got %d\n", ret);
450
451 ret = GetRgnBox(hrgn, &rc);
452 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
453 ok(rc.left == 0 && rc.top == 0 && rc.right == screen_width && rc.bottom == screen_height,
454 "expected 0,0-%d,%d, got %d,%d-%d,%d\n", screen_width, screen_height,
455 rc.left, rc.top, rc.right, rc.bottom);
456
457 SetRect( &rc, 10, 10, 20, 20 );
458 ret = RectVisible( hdc, &rc );
459 ok( ret, "RectVisible failed for %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom );
460
461 SetRect( &rc, 20, 20, 10, 10 );
462 ret = RectVisible( hdc, &rc );
463 ok( ret, "RectVisible failed for %d,%d-%d,%d\n", rc.left, rc.top, rc.right, rc.bottom );
464
465 ret = ExtSelectClipRgn(hdc, 0, RGN_COPY);
466 ok(ret == SIMPLEREGION || (ret == COMPLEXREGION && GetSystemMetrics(SM_CMONITORS) > 1),
467 "expected SIMPLEREGION, got %d\n", ret);
468
469 ret = GetClipRgn(hdc, hrgn);
470 ok(ret == 0, "expected 0, got %d\n", ret);
471
472 DeleteDC(hdc);
473 DeleteObject(hrgn);
474 DeleteObject(hrgn_empty);
475 DestroyWindow(hwnd);
476 }
477
478
479 START_TEST(clipping)
480 {
481 test_GetRandomRgn();
482 test_ExtCreateRegion();
483 test_GetClipRgn();
484 test_memory_dc_clipping();
485 test_window_dc_clipping();
486 }