makefiles: Output rules for building generated .rc files.
[wine.git] / dlls / gdi32 / tests / dc.c
blob5eec74a72c54cdd34aed9849c27f88ec9ea9e6f1
1 /*
2 * Unit tests for dc functions
4 * Copyright (c) 2005 Huw Davies
5 * Copyright (c) 2005 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WINVER 0x0501 /* request latest DEVMODE */
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
27 #include <assert.h>
28 #include <stdio.h>
30 #include "wine/test.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "winspool.h"
35 #include "winerror.h"
37 #ifndef LAYOUT_LTR
38 #define LAYOUT_LTR 0
39 #endif
41 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
43 static void dump_region(HRGN hrgn)
45 DWORD i, size;
46 RGNDATA *data = NULL;
47 RECT *rect;
49 if (!hrgn)
51 printf( "(null) region\n" );
52 return;
54 if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
55 if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
56 GetRegionData( hrgn, size, data );
57 printf( "%d rects:", data->rdh.nCount );
58 for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++)
59 printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom );
60 printf( "\n" );
61 HeapFree( GetProcessHeap(), 0, data );
64 static void test_dc_values(void)
66 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
67 COLORREF color;
68 int extra;
70 ok( hdc != NULL, "CreateDC failed\n" );
71 color = SetBkColor( hdc, 0x12345678 );
72 ok( color == 0xffffff, "initial color %08x\n", color );
73 color = GetBkColor( hdc );
74 ok( color == 0x12345678, "wrong color %08x\n", color );
75 color = SetBkColor( hdc, 0xffffffff );
76 ok( color == 0x12345678, "wrong color %08x\n", color );
77 color = GetBkColor( hdc );
78 ok( color == 0xffffffff, "wrong color %08x\n", color );
79 color = SetBkColor( hdc, 0 );
80 ok( color == 0xffffffff, "wrong color %08x\n", color );
81 color = GetBkColor( hdc );
82 ok( color == 0, "wrong color %08x\n", color );
84 color = SetTextColor( hdc, 0xffeeddcc );
85 ok( color == 0, "initial color %08x\n", color );
86 color = GetTextColor( hdc );
87 ok( color == 0xffeeddcc, "wrong color %08x\n", color );
88 color = SetTextColor( hdc, 0xffffffff );
89 ok( color == 0xffeeddcc, "wrong color %08x\n", color );
90 color = GetTextColor( hdc );
91 ok( color == 0xffffffff, "wrong color %08x\n", color );
92 color = SetTextColor( hdc, 0 );
93 ok( color == 0xffffffff, "wrong color %08x\n", color );
94 color = GetTextColor( hdc );
95 ok( color == 0, "wrong color %08x\n", color );
97 extra = GetTextCharacterExtra( hdc );
98 ok( extra == 0, "initial extra %d\n", extra );
99 SetTextCharacterExtra( hdc, 123 );
100 extra = GetTextCharacterExtra( hdc );
101 ok( extra == 123, "initial extra %d\n", extra );
102 SetMapMode( hdc, MM_LOMETRIC );
103 extra = GetTextCharacterExtra( hdc );
104 ok( extra == 123, "initial extra %d\n", extra );
105 SetMapMode( hdc, MM_TEXT );
106 extra = GetTextCharacterExtra( hdc );
107 ok( extra == 123, "initial extra %d\n", extra );
109 DeleteDC( hdc );
112 static void test_savedc_2(void)
114 HWND hwnd;
115 HDC hdc;
116 HRGN hrgn;
117 RECT rc, rc_clip;
118 int ret;
120 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
121 0, 0, 0, NULL);
122 assert(hwnd != 0);
123 ShowWindow(hwnd, SW_SHOW);
124 UpdateWindow(hwnd);
126 hrgn = CreateRectRgn(0, 0, 0, 0);
127 assert(hrgn != 0);
129 hdc = GetDC(hwnd);
130 ok(hdc != NULL, "GetDC failed\n");
132 ret = GetClipBox(hdc, &rc_clip);
133 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
134 ret = GetClipRgn(hdc, hrgn);
135 ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret);
136 ret = GetRgnBox(hrgn, &rc);
137 ok(ret == NULLREGION, "GetRgnBox returned %d %s instead of NULLREGION\n",
138 ret, wine_dbgstr_rect(&rc));
139 /*dump_region(hrgn);*/
140 SetRect(&rc, 0, 0, 100, 100);
141 ok(EqualRect(&rc, &rc_clip), "rects are not equal: %s - %s\n", wine_dbgstr_rect(&rc),
142 wine_dbgstr_rect(&rc_clip));
144 ret = SaveDC(hdc);
145 ok(ret == 1, "ret = %d\n", ret);
147 ret = IntersectClipRect(hdc, 0, 0, 50, 50);
148 if (ret == COMPLEXREGION)
150 /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
151 trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
152 /* let's make sure that it's a simple region */
153 ret = GetClipRgn(hdc, hrgn);
154 ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
155 dump_region(hrgn);
157 else
158 ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
160 ret = GetClipBox(hdc, &rc_clip);
161 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
162 SetRect(&rc, 0, 0, 50, 50);
163 ok(EqualRect(&rc, &rc_clip), "rects are not equal: %s - %s\n", wine_dbgstr_rect(&rc),
164 wine_dbgstr_rect(&rc_clip));
166 ret = RestoreDC(hdc, 1);
167 ok(ret, "ret = %d\n", ret);
169 ret = GetClipBox(hdc, &rc_clip);
170 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
171 SetRect(&rc, 0, 0, 100, 100);
172 ok(EqualRect(&rc, &rc_clip), "rects are not equal: %s - %s\n", wine_dbgstr_rect(&rc),
173 wine_dbgstr_rect(&rc_clip));
175 DeleteObject(hrgn);
176 ReleaseDC(hwnd, hdc);
177 DestroyWindow(hwnd);
180 static void test_savedc(void)
182 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
183 int ret;
185 ok(hdc != NULL, "CreateDC rets %p\n", hdc);
187 ret = SaveDC(hdc);
188 ok(ret == 1, "ret = %d\n", ret);
189 ret = SaveDC(hdc);
190 ok(ret == 2, "ret = %d\n", ret);
191 ret = SaveDC(hdc);
192 ok(ret == 3, "ret = %d\n", ret);
193 ret = RestoreDC(hdc, -1);
194 ok(ret, "ret = %d\n", ret);
195 ret = SaveDC(hdc);
196 ok(ret == 3, "ret = %d\n", ret);
197 ret = RestoreDC(hdc, 1);
198 ok(ret, "ret = %d\n", ret);
199 ret = SaveDC(hdc);
200 ok(ret == 1, "ret = %d\n", ret);
201 ret = SaveDC(hdc);
202 ok(ret == 2, "ret = %d\n", ret);
203 ret = SaveDC(hdc);
204 ok(ret == 3, "ret = %d\n", ret);
205 ret = RestoreDC(hdc, -2);
206 ok(ret, "ret = %d\n", ret);
207 ret = SaveDC(hdc);
208 ok(ret == 2, "ret = %d\n", ret);
209 ret = RestoreDC(hdc, -2);
210 ok(ret, "ret = %d\n", ret);
211 ret = SaveDC(hdc);
212 ok(ret == 1, "ret = %d\n", ret);
213 ret = SaveDC(hdc);
214 ok(ret == 2, "ret = %d\n", ret);
215 ret = RestoreDC(hdc, -4);
216 ok(!ret, "ret = %d\n", ret);
217 ret = RestoreDC(hdc, 3);
218 ok(!ret, "ret = %d\n", ret);
220 /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
221 ret = RestoreDC(hdc, -3);
222 ok(!ret ||
223 broken(ret), /* Win9x */
224 "ret = %d\n", ret);
226 /* Trying to clear an empty save stack fails. */
227 ret = RestoreDC(hdc, -3);
228 ok(!ret, "ret = %d\n", ret);
230 ret = SaveDC(hdc);
231 ok(ret == 3 ||
232 broken(ret == 1), /* Win9x */
233 "ret = %d\n", ret);
235 /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
236 ret = RestoreDC(hdc, 0);
237 ok(!ret ||
238 broken(ret), /* Win9x */
239 "ret = %d\n", ret);
241 /* Trying to clear an empty save stack fails. */
242 ret = RestoreDC(hdc, 0);
243 ok(!ret, "ret = %d\n", ret);
245 ret = RestoreDC(hdc, 1);
246 ok(ret ||
247 broken(!ret), /* Win9x */
248 "ret = %d\n", ret);
250 DeleteDC(hdc);
253 static void test_GdiConvertToDevmodeW(void)
255 DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
256 DEVMODEA dmA;
257 DEVMODEW *dmW;
258 BOOL ret;
260 pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
261 if (!pGdiConvertToDevmodeW)
263 win_skip("GdiConvertToDevmodeW is not available on this platform\n");
264 return;
267 ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
268 ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
269 ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
270 ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
272 dmW = pGdiConvertToDevmodeW(&dmA);
273 ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
274 ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
275 HeapFree(GetProcessHeap(), 0, dmW);
277 dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
278 dmW = pGdiConvertToDevmodeW(&dmA);
279 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
280 "wrong size %u\n", dmW->dmSize);
281 HeapFree(GetProcessHeap(), 0, dmW);
283 dmA.dmICMMethod = DMICMMETHOD_NONE;
284 dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
285 dmW = pGdiConvertToDevmodeW(&dmA);
286 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
287 "wrong size %u\n", dmW->dmSize);
288 ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
289 "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
290 HeapFree(GetProcessHeap(), 0, dmW);
292 dmA.dmSize = 1024;
293 dmW = pGdiConvertToDevmodeW(&dmA);
294 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
295 "wrong size %u\n", dmW->dmSize);
296 HeapFree(GetProcessHeap(), 0, dmW);
298 SetLastError(0xdeadbeef);
299 dmA.dmSize = 0;
300 dmW = pGdiConvertToDevmodeW(&dmA);
301 ok(!dmW, "GdiConvertToDevmodeW should fail\n");
302 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
304 /* this is the minimal dmSize that XP accepts */
305 dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
306 dmW = pGdiConvertToDevmodeW(&dmA);
307 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
308 "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
309 HeapFree(GetProcessHeap(), 0, dmW);
312 static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale )
314 static const int caps[] =
316 DRIVERVERSION,
317 TECHNOLOGY,
318 HORZSIZE,
319 VERTSIZE,
320 HORZRES,
321 VERTRES,
322 BITSPIXEL,
323 PLANES,
324 NUMBRUSHES,
325 NUMPENS,
326 NUMMARKERS,
327 NUMFONTS,
328 NUMCOLORS,
329 PDEVICESIZE,
330 CURVECAPS,
331 LINECAPS,
332 POLYGONALCAPS,
333 /* TEXTCAPS broken on printer DC on winxp */
334 CLIPCAPS,
335 RASTERCAPS,
336 ASPECTX,
337 ASPECTY,
338 ASPECTXY,
339 LOGPIXELSX,
340 LOGPIXELSY,
341 SIZEPALETTE,
342 NUMRESERVED,
343 COLORRES,
344 PHYSICALWIDTH,
345 PHYSICALHEIGHT,
346 PHYSICALOFFSETX,
347 PHYSICALOFFSETY,
348 SCALINGFACTORX,
349 SCALINGFACTORY,
350 VREFRESH,
351 DESKTOPVERTRES,
352 DESKTOPHORZRES,
353 BLTALIGNMENT,
354 SHADEBLENDCAPS
356 unsigned int i;
357 WORD ramp[3][256];
358 BOOL ret;
359 RECT rect;
360 UINT type;
362 if (GetObjectType( hdc ) == OBJ_METADC)
364 for (i = 0; i < ARRAY_SIZE(caps); i++)
365 ok( GetDeviceCaps( hdc, caps[i] ) == (caps[i] == TECHNOLOGY ? DT_METAFILE : 0),
366 "wrong caps on %s for %u: %u\n", descr, caps[i],
367 GetDeviceCaps( hdc, caps[i] ) );
369 SetLastError( 0xdeadbeef );
370 ret = GetDeviceGammaRamp( hdc, &ramp );
371 ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
372 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
373 "wrong error %u on %s\n", GetLastError(), descr );
374 type = GetClipBox( hdc, &rect );
375 ok( type == ERROR, "GetClipBox returned %d on %s\n", type, descr );
377 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
378 SetMapMode( hdc, MM_TEXT );
379 Rectangle( hdc, 2, 2, 5, 5 );
380 type = GetBoundsRect( hdc, &rect, DCB_RESET );
381 ok( !type, "GetBoundsRect succeeded on %s\n", descr );
382 type = SetBoundsRect( hdc, &rect, DCB_RESET | DCB_ENABLE );
383 ok( !type, "SetBoundsRect succeeded on %s\n", descr );
385 else
387 for (i = 0; i < ARRAY_SIZE(caps); i++)
389 INT precision = 0;
390 INT hdc_caps = GetDeviceCaps( hdc, caps[i] );
392 switch (caps[i])
394 case HORZSIZE:
395 case VERTSIZE:
396 hdc_caps /= scale;
397 precision = 1;
398 break;
399 case LOGPIXELSX:
400 case LOGPIXELSY:
401 hdc_caps *= scale;
402 break;
403 case VREFRESH:
404 if (GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASDISPLAY)
405 ok( hdc_caps > 0, "expected a positive value on %s, got %d\n", descr, hdc_caps );
406 else
407 ok( hdc_caps == 0, "expected 0 on %s, got %d\n", descr, hdc_caps );
408 break;
411 ok( abs(hdc_caps - GetDeviceCaps( ref_dc, caps[i] )) <= precision,
412 "mismatched caps on %s for %u: %u/%u (scale %d)\n", descr, caps[i],
413 hdc_caps, GetDeviceCaps( ref_dc, caps[i] ), scale );
416 SetLastError( 0xdeadbeef );
417 ret = GetDeviceGammaRamp( hdc, &ramp );
418 if (GetObjectType( hdc ) != OBJ_DC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER)
420 ok( !ret, "GetDeviceGammaRamp succeeded on %s (type %d)\n", descr, GetObjectType( hdc ) );
421 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
422 "wrong error %u on %s\n", GetLastError(), descr );
424 else
425 ok( ret || broken(!ret) /* NT4 */, "GetDeviceGammaRamp failed on %s (type %d), error %u\n", descr, GetObjectType( hdc ), GetLastError() );
426 type = GetClipBox( hdc, &rect );
427 todo_wine_if (GetObjectType( hdc ) == OBJ_ENHMETADC)
428 ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
430 type = GetBoundsRect( hdc, &rect, 0 );
431 ok( type == DCB_RESET || broken(type == DCB_SET) /* XP */,
432 "GetBoundsRect returned type %x for %s\n", type, descr );
433 if (type == DCB_RESET)
434 ok( rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0,
435 "GetBoundsRect returned %s type %x for %s\n", wine_dbgstr_rect( &rect ),
436 type, descr );
437 type = SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
438 ok( type == (DCB_RESET | DCB_DISABLE) || broken(type == (DCB_SET | DCB_ENABLE)) /* XP */,
439 "SetBoundsRect returned %x for %s (hdc type %d)\n", type, descr, GetObjectType( hdc ) );
441 SetMapMode( hdc, MM_TEXT );
442 Rectangle( hdc, 2, 2, 4, 4 );
443 type = GetBoundsRect( hdc, &rect, DCB_RESET );
444 todo_wine_if (GetObjectType( hdc ) == OBJ_ENHMETADC || (GetObjectType( hdc ) == OBJ_DC && GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER))
445 ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
446 "GetBoundsRect returned %s type %x for %s\n", wine_dbgstr_rect( &rect ),
447 type, descr );
450 type = GetClipBox( ref_dc, &rect );
451 if (type != COMPLEXREGION && type != ERROR) /* region can be complex on multi-monitor setups */
453 RECT ref_rect;
455 ok( type == SIMPLEREGION, "GetClipBox returned %d on %s\n", type, descr );
456 if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY)
458 todo_wine_if (GetSystemMetrics( SM_CXSCREEN ) != GetSystemMetrics( SM_CXVIRTUALSCREEN ))
459 ok( GetDeviceCaps( ref_dc, DESKTOPHORZRES ) == GetSystemMetrics( SM_CXSCREEN ),
460 "Got DESKTOPHORZRES %d on %s, expected %d\n",
461 GetDeviceCaps( ref_dc, DESKTOPHORZRES ), descr, GetSystemMetrics( SM_CXSCREEN ) );
463 todo_wine_if (GetSystemMetrics( SM_CYSCREEN ) != GetSystemMetrics( SM_CYVIRTUALSCREEN ))
464 ok( GetDeviceCaps( ref_dc, DESKTOPVERTRES ) == GetSystemMetrics( SM_CYSCREEN ),
465 "Got DESKTOPVERTRES %d on %s, expected %d\n",
466 GetDeviceCaps( ref_dc, DESKTOPVERTRES ), descr, GetSystemMetrics( SM_CYSCREEN ) );
468 SetRect( &ref_rect, GetSystemMetrics( SM_XVIRTUALSCREEN ), GetSystemMetrics( SM_YVIRTUALSCREEN ),
469 GetSystemMetrics( SM_XVIRTUALSCREEN ) + GetSystemMetrics( SM_CXVIRTUALSCREEN ),
470 GetSystemMetrics( SM_YVIRTUALSCREEN ) + GetSystemMetrics( SM_CYVIRTUALSCREEN ) );
472 else
474 ok( GetDeviceCaps( ref_dc, DESKTOPHORZRES ) == GetDeviceCaps( ref_dc, HORZRES ),
475 "Got DESKTOPHORZRES %d on %s, expected %d\n",
476 GetDeviceCaps( ref_dc, DESKTOPHORZRES ), descr, GetDeviceCaps( ref_dc, HORZRES ));
477 ok( GetDeviceCaps( ref_dc, DESKTOPVERTRES ) == GetDeviceCaps( ref_dc, VERTRES ),
478 "Got DESKTOPVERTRES %d on %s, expected %d\n",
479 GetDeviceCaps( ref_dc, DESKTOPVERTRES ), descr, GetDeviceCaps( ref_dc, VERTRES ));
480 SetRect( &ref_rect, 0, 0, GetDeviceCaps( ref_dc, DESKTOPHORZRES ),
481 GetDeviceCaps( ref_dc, DESKTOPVERTRES ) );
484 todo_wine_if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY && GetObjectType( hdc ) != OBJ_ENHMETADC &&
485 (GetSystemMetrics( SM_XVIRTUALSCREEN ) || GetSystemMetrics( SM_YVIRTUALSCREEN )))
486 ok( EqualRect( &rect, &ref_rect ), "GetClipBox returned %s on %s\n",
487 wine_dbgstr_rect( &rect ), descr );
490 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_ACCUMULATE );
491 SetMapMode( ref_dc, MM_TEXT );
492 Rectangle( ref_dc, 3, 3, 5, 5 );
493 type = GetBoundsRect( ref_dc, &rect, DCB_RESET );
494 /* it may or may not work on non-memory DCs */
495 ok( (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && type == DCB_RESET) ||
496 (rect.left == 3 && rect.top == 3 && rect.right == 5 && rect.bottom == 5 && type == DCB_SET),
497 "GetBoundsRect returned %s type %x on %s\n", wine_dbgstr_rect( &rect ), type, descr );
499 if (GetObjectType( hdc ) == OBJ_MEMDC)
501 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
502 BITMAPINFO *info = (BITMAPINFO *)buffer;
503 HBITMAP dib, old;
505 memset( buffer, 0, sizeof(buffer) );
506 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
507 info->bmiHeader.biWidth = 16;
508 info->bmiHeader.biHeight = 16;
509 info->bmiHeader.biPlanes = 1;
510 info->bmiHeader.biBitCount = 8;
511 info->bmiHeader.biCompression = BI_RGB;
512 dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
513 old = SelectObject( hdc, dib );
515 for (i = 0; i < ARRAY_SIZE(caps); i++)
516 ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
517 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
518 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
520 SetLastError( 0xdeadbeef );
521 ret = GetDeviceGammaRamp( hdc, &ramp );
522 ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
523 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
524 "wrong error %u on %s\n", GetLastError(), descr );
526 type = GetClipBox( hdc, &rect );
527 ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
528 ok( rect.left == 0 && rect.top == 0 && rect.right == 16 && rect.bottom == 16,
529 "GetClipBox returned %s on memdc for %s\n", wine_dbgstr_rect( &rect ), descr );
531 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
532 SetMapMode( hdc, MM_TEXT );
533 Rectangle( hdc, 5, 5, 12, 14 );
534 type = GetBoundsRect( hdc, &rect, DCB_RESET );
535 ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
536 "GetBoundsRect returned %s type %x on memdc for %s\n", wine_dbgstr_rect( &rect ),
537 type, descr );
539 SelectObject( hdc, old );
540 DeleteObject( dib );
543 /* restore hdc state */
544 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_DISABLE );
545 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_DISABLE );
548 static void test_CreateCompatibleDC(void)
550 BOOL bRet;
551 HDC hdc, hNewDC, hdcMetafile, screen_dc;
552 HBITMAP bitmap;
553 INT caps;
554 DEVMODEA dm;
556 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
558 bRet = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm);
559 ok(bRet, "EnumDisplaySettingsEx failed\n");
560 dm.u1.s1.dmScale = 200;
561 dm.dmFields |= DM_SCALE;
562 hdc = CreateDCA( "DISPLAY", NULL, NULL, &dm );
564 screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
565 test_device_caps( hdc, screen_dc, "display dc", 1 );
566 ResetDCA( hdc, &dm );
567 test_device_caps( hdc, screen_dc, "display dc", 1 );
568 DeleteDC( hdc );
570 /* Create a DC compatible with the screen */
571 hdc = CreateCompatibleDC(NULL);
572 ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
573 ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
574 caps = GetDeviceCaps( hdc, TECHNOLOGY );
575 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
577 test_device_caps( hdc, screen_dc, "display dc", 1 );
579 /* Delete this DC, this should succeed */
580 bRet = DeleteDC(hdc);
581 ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
583 /* Try to create a DC compatible to the deleted DC. This has to fail */
584 hNewDC = CreateCompatibleDC(hdc);
585 ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
587 hdc = GetDC( 0 );
588 hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
589 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
590 hNewDC = CreateCompatibleDC( hdcMetafile );
591 ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
592 ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
593 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
594 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
595 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
596 ResetDCA( hdcMetafile, &dm );
597 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
598 DeleteDC( hNewDC );
599 DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
600 ReleaseDC( 0, hdc );
602 hdcMetafile = CreateMetaFileA(NULL);
603 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
604 hNewDC = CreateCompatibleDC( hdcMetafile );
605 ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
606 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
607 ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
608 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
609 ResetDCA( hdcMetafile, &dm );
610 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
611 DeleteMetaFile( CloseMetaFile( hdcMetafile ));
613 DeleteObject( bitmap );
614 DeleteDC( screen_dc );
617 static void test_DC_bitmap(void)
619 PIXELFORMATDESCRIPTOR descr;
620 HDC hdc, hdcmem;
621 DWORD bits[64];
622 HBITMAP hbmp, oldhbmp;
623 COLORREF col;
624 int i, bitspixel;
625 int ret, ret2;
627 /* fill bitmap data with b&w pattern */
628 for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
630 hdc = GetDC(0);
631 ok( hdc != NULL, "CreateDC rets %p\n", hdc);
632 bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
633 /* create a memory dc */
634 hdcmem = CreateCompatibleDC( hdc);
635 ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
637 /* test DescribePixelFormat with descr == NULL */
638 ret2 = DescribePixelFormat(hdcmem, 0, sizeof(descr), NULL);
639 ok(ret2 > 0, "expected ret2 > 0, got %d\n", ret2);
640 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), NULL);
641 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
642 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), NULL);
643 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
645 /* test DescribePixelFormat with descr != NULL */
646 memset(&descr, 0, sizeof(descr));
647 ret = DescribePixelFormat(hdcmem, 0, sizeof(descr), &descr);
648 ok(ret == 0, "expected ret == 0, got %d\n", ret);
649 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
651 memset(&descr, 0, sizeof(descr));
652 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), &descr);
653 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
654 ok(descr.nSize == sizeof(descr), "expected desc.nSize == sizeof(descr), got %d\n", descr.nSize);
656 memset(&descr, 0, sizeof(descr));
657 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), &descr);
658 ok(ret == 0, "expected ret == 0, got %d\n", ret);
659 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
661 /* test monochrome bitmap: should always work */
662 hbmp = CreateBitmap(32, 32, 1, 1, bits);
663 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
664 oldhbmp = SelectObject( hdcmem, hbmp);
665 ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
666 col = GetPixel( hdcmem, 0, 0);
667 ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
668 col = GetPixel( hdcmem, 1, 1);
669 ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
670 col = GetPixel( hdcmem, 100, 1);
671 ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
672 SelectObject( hdcmem, oldhbmp);
673 DeleteObject( hbmp);
675 /* test with 2 bits color depth, not likely to succeed */
676 hbmp = CreateBitmap(16, 16, 1, 2, bits);
677 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
678 oldhbmp = SelectObject( hdcmem, hbmp);
679 if( bitspixel != 2)
680 ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return NULL\n");
681 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
682 DeleteObject( hbmp);
684 /* test with 16 bits color depth, might succeed */
685 hbmp = CreateBitmap(6, 6, 1, 16, bits);
686 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
687 oldhbmp = SelectObject( hdcmem, hbmp);
688 if( bitspixel == 16) {
689 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
690 col = GetPixel( hdcmem, 0, 0);
691 ok( col == 0xffffff,
692 "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
693 col = GetPixel( hdcmem, 1, 1);
694 ok( col == 0x000000,
695 "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
697 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
698 DeleteObject( hbmp);
700 /* test with 32 bits color depth, probably succeed */
701 hbmp = CreateBitmap(4, 4, 1, 32, bits);
702 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
703 oldhbmp = SelectObject( hdcmem, hbmp);
704 if( bitspixel == 32) {
705 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
706 col = GetPixel( hdcmem, 0, 0);
707 ok( col == 0xffffff,
708 "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
709 col = GetPixel( hdcmem, 1, 1);
710 ok( col == 0x000000,
711 "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
713 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
714 DeleteObject( hbmp);
715 ReleaseDC( 0, hdc );
718 static void test_DeleteDC(void)
720 HWND hwnd;
721 HDC hdc, hdc_test;
722 WNDCLASSEXA cls;
723 int ret;
725 /* window DC */
726 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
727 0, 0, 0, NULL);
728 ok(hwnd != 0, "CreateWindowExA failed\n");
730 hdc = GetDC(hwnd);
731 ok(hdc != 0, "GetDC failed\n");
732 ret = GetObjectType(hdc);
733 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
734 ret = DeleteDC(hdc);
735 ok(ret, "DeleteDC failed\n");
736 ret = GetObjectType(hdc);
737 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
739 hdc = GetWindowDC(hwnd);
740 ok(hdc != 0, "GetDC failed\n");
741 ret = GetObjectType(hdc);
742 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
743 ret = DeleteDC(hdc);
744 ok(ret, "DeleteDC failed\n");
745 ret = GetObjectType(hdc);
746 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
748 DestroyWindow(hwnd);
750 /* desktop window DC */
751 hwnd = GetDesktopWindow();
752 ok(hwnd != 0, "GetDesktopWindow failed\n");
754 hdc = GetDC(hwnd);
755 ok(hdc != 0, "GetDC failed\n");
756 ret = GetObjectType(hdc);
757 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
758 ret = DeleteDC(hdc);
759 ok(ret, "DeleteDC failed\n");
760 ret = GetObjectType(hdc);
761 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
763 hdc = GetWindowDC(hwnd);
764 ok(hdc != 0, "GetDC failed\n");
765 ret = GetObjectType(hdc);
766 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
767 ret = DeleteDC(hdc);
768 ok(ret, "DeleteDC failed\n");
769 ret = GetObjectType(hdc);
770 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
772 /* CS_CLASSDC */
773 memset(&cls, 0, sizeof(cls));
774 cls.cbSize = sizeof(cls);
775 cls.style = CS_CLASSDC;
776 cls.hInstance = GetModuleHandleA(NULL);
777 cls.lpszClassName = "Wine class DC";
778 cls.lpfnWndProc = DefWindowProcA;
779 ret = RegisterClassExA(&cls);
780 ok(ret, "RegisterClassExA failed\n");
782 hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
783 0, 0, 0, NULL);
784 ok(hwnd != 0, "CreateWindowExA failed\n");
786 hdc = GetDC(hwnd);
787 ok(hdc != 0, "GetDC failed\n");
788 ret = GetObjectType(hdc);
789 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
790 ret = DeleteDC(hdc);
791 ok(ret, "DeleteDC failed\n");
792 ret = GetObjectType(hdc);
793 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
794 ret = ReleaseDC(hwnd, hdc);
795 ok(ret, "ReleaseDC failed\n");
796 ret = GetObjectType(hdc);
797 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
799 hdc_test = hdc;
801 hdc = GetWindowDC(hwnd);
802 ok(hdc != 0, "GetDC failed\n");
803 ret = GetObjectType(hdc);
804 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
805 ret = DeleteDC(hdc);
806 ok(ret, "DeleteDC failed\n");
807 ret = GetObjectType(hdc);
808 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
810 DestroyWindow(hwnd);
812 ret = GetObjectType(hdc_test);
813 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
815 ret = UnregisterClassA("Wine class DC", GetModuleHandleA(NULL));
816 ok(ret, "UnregisterClassA failed\n");
818 ret = GetObjectType(hdc_test);
819 ok(!ret, "GetObjectType should fail for a deleted DC\n");
821 /* CS_OWNDC */
822 memset(&cls, 0, sizeof(cls));
823 cls.cbSize = sizeof(cls);
824 cls.style = CS_OWNDC;
825 cls.hInstance = GetModuleHandleA(NULL);
826 cls.lpszClassName = "Wine own DC";
827 cls.lpfnWndProc = DefWindowProcA;
828 ret = RegisterClassExA(&cls);
829 ok(ret, "RegisterClassExA failed\n");
831 hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
832 0, 0, 0, NULL);
833 ok(hwnd != 0, "CreateWindowExA failed\n");
835 hdc = GetDC(hwnd);
836 ok(hdc != 0, "GetDC failed\n");
837 ret = GetObjectType(hdc);
838 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
839 ret = DeleteDC(hdc);
840 ok(ret, "DeleteDC failed\n");
841 ret = GetObjectType(hdc);
842 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
843 ret = ReleaseDC(hwnd, hdc);
844 ok(ret, "ReleaseDC failed\n");
845 ret = GetObjectType(hdc);
846 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
848 hdc = GetWindowDC(hwnd);
849 ok(hdc != 0, "GetDC failed\n");
850 ret = GetObjectType(hdc);
851 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
852 ret = DeleteDC(hdc);
853 ok(ret, "DeleteDC failed\n");
854 ret = GetObjectType(hdc);
855 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
857 DestroyWindow(hwnd);
859 ret = UnregisterClassA("Wine own DC", GetModuleHandleA(NULL));
860 ok(ret, "UnregisterClassA failed\n");
863 static void test_boundsrect(void)
865 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
866 BITMAPINFO *info = (BITMAPINFO *)buffer;
867 HDC hdc;
868 HBITMAP bitmap, dib, old;
869 RECT rect, expect, set_rect;
870 UINT ret;
871 int i, level;
873 hdc = CreateCompatibleDC(0);
874 ok(hdc != NULL, "CreateCompatibleDC failed\n");
875 bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
876 old = SelectObject( hdc, bitmap );
878 ret = GetBoundsRect(hdc, NULL, 0);
879 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
881 ret = GetBoundsRect(hdc, NULL, ~0U);
882 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
884 /* Test parameter handling order. */
885 SetRect(&set_rect, 10, 20, 40, 50);
886 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
887 ok(ret & DCB_RESET,
888 "Expected return flag DCB_RESET to be set, got %u\n", ret);
890 ret = GetBoundsRect(hdc, NULL, DCB_RESET);
891 ok(ret == 0,
892 "Expected GetBoundsRect to return 0, got %u\n", ret);
894 ret = GetBoundsRect(hdc, &rect, 0);
895 ok(ret == DCB_RESET,
896 "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
897 SetRectEmpty(&expect);
898 ok(EqualRect(&rect, &expect), "Expected output rectangle (0,0)-(0,0), got %s\n",
899 wine_dbgstr_rect(&rect));
901 ret = GetBoundsRect(NULL, NULL, 0);
902 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
904 ret = GetBoundsRect(NULL, NULL, ~0U);
905 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
907 ret = SetBoundsRect(NULL, NULL, 0);
908 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
910 ret = SetBoundsRect(NULL, NULL, ~0U);
911 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
913 SetRect(&set_rect, 10, 20, 40, 50);
914 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
915 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
917 ret = GetBoundsRect(hdc, &rect, 0);
918 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
919 SetRect(&expect, 10, 20, 40, 50);
920 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
922 SetMapMode( hdc, MM_ANISOTROPIC );
923 SetViewportExtEx( hdc, 2, 2, NULL );
924 ret = GetBoundsRect(hdc, &rect, 0);
925 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
926 SetRect(&expect, 5, 10, 20, 25);
927 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
929 SetViewportOrgEx( hdc, 20, 30, NULL );
930 ret = GetBoundsRect(hdc, &rect, 0);
931 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
932 SetRect(&expect, -5, -5, 10, 10);
933 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
935 SetRect(&set_rect, 10, 20, 40, 50);
936 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
937 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
939 ret = GetBoundsRect(hdc, &rect, 0);
940 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
941 SetRect(&expect, 10, 20, 40, 50);
942 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
944 SetMapMode( hdc, MM_TEXT );
945 SetViewportOrgEx( hdc, 0, 0, NULL );
946 ret = GetBoundsRect(hdc, &rect, 0);
947 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
948 SetRect(&expect, 40, 70, 100, 130);
949 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
951 if (pSetLayout)
953 pSetLayout( hdc, LAYOUT_RTL );
954 ret = GetBoundsRect(hdc, &rect, 0);
955 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
956 SetRect(&expect, 159, 70, 99, 130);
957 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
958 SetRect(&set_rect, 50, 25, 30, 35);
959 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
960 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
961 ret = GetBoundsRect(hdc, &rect, 0);
962 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
963 SetRect(&expect, 50, 25, 30, 35);
964 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
966 pSetLayout( hdc, LAYOUT_LTR );
967 ret = GetBoundsRect(hdc, &rect, 0);
968 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
969 SetRect(&expect, 149, 25, 169, 35);
970 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
973 /* empty rect resets, except on nt4 */
974 SetRect(&expect, 20, 20, 10, 10);
975 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
976 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
977 ret = GetBoundsRect(hdc, &rect, 0);
978 ok(ret == DCB_RESET || broken(ret == DCB_SET) /* nt4 */,
979 "GetBoundsRect returned %x\n", ret);
980 if (ret == DCB_RESET)
982 SetRectEmpty(&expect);
983 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
985 SetRect(&expect, 20, 20, 20, 20);
986 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
987 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
988 ret = GetBoundsRect(hdc, &rect, 0);
989 ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
990 SetRectEmpty(&expect);
991 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
994 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
995 MoveToEx( hdc, 10, 10, NULL );
996 LineTo( hdc, 20, 20 );
997 ret = GetBoundsRect( hdc, &rect, 0 );
998 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
999 SetRect( &expect, 10, 10, 21, 21 );
1000 ok( EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1001 SetRect( &rect, 8, 8, 23, 23 );
1002 expect = rect;
1003 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1004 ret = GetBoundsRect( hdc, &rect, 0 );
1005 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1006 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1008 level = SaveDC( hdc );
1009 LineTo( hdc, 30, 25 );
1010 ret = GetBoundsRect( hdc, &rect, 0 );
1011 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1012 SetRect( &expect, 8, 8, 31, 26 );
1013 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1014 SetBoundsRect( hdc, NULL, DCB_DISABLE );
1015 LineTo( hdc, 40, 40 );
1016 ret = GetBoundsRect( hdc, &rect, 0 );
1017 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1018 SetRect( &expect, 8, 8, 31, 26 );
1019 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1020 SetRect( &rect, 6, 6, 30, 30 );
1021 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1022 ret = GetBoundsRect( hdc, &rect, 0 );
1023 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1024 SetRect( &expect, 6, 6, 31, 30 );
1025 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1027 RestoreDC( hdc, level );
1028 ret = GetBoundsRect( hdc, &rect, 0 );
1029 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1030 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1031 LineTo( hdc, 40, 40 );
1032 ret = GetBoundsRect( hdc, &rect, 0 );
1033 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1034 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1036 SelectObject( hdc, old );
1037 ret = GetBoundsRect( hdc, &rect, 0 );
1038 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1039 SetRect( &expect, 6, 6, 1, 1 );
1040 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1041 SetBoundsRect( hdc, NULL, DCB_ENABLE );
1042 LineTo( hdc, 50, 40 );
1044 SelectObject( hdc, bitmap );
1045 ret = GetBoundsRect( hdc, &rect, 0 );
1046 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1047 SetRect( &expect, 6, 6, 51, 41 );
1048 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1049 SelectObject( hdc, GetStockObject( NULL_PEN ));
1050 LineTo( hdc, 50, 50 );
1051 ret = GetBoundsRect( hdc, &rect, 0 );
1052 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1053 SetRect( &expect, 6, 6, 51, 51 );
1054 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1056 memset( buffer, 0, sizeof(buffer) );
1057 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1058 info->bmiHeader.biWidth = 256;
1059 info->bmiHeader.biHeight = 256;
1060 info->bmiHeader.biPlanes = 1;
1061 info->bmiHeader.biBitCount = 8;
1062 info->bmiHeader.biCompression = BI_RGB;
1063 dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, NULL, NULL, 0 );
1064 ok( dib != 0, "failed to create DIB\n" );
1065 SelectObject( hdc, dib );
1066 ret = GetBoundsRect( hdc, &rect, 0 );
1067 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1068 SetRect( &expect, 6, 6, 51, 51 );
1069 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1070 LineTo( hdc, 55, 30 );
1071 ret = GetBoundsRect( hdc, &rect, 0 );
1072 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1073 SetRect( &expect, 6, 6, 56, 51 );
1074 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1075 LineTo( hdc, 300, 30 );
1076 ret = GetBoundsRect( hdc, &rect, 0 );
1077 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1078 SetRect( &expect, 6, 6, 256, 51 );
1079 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1080 LineTo( hdc, -300, -300 );
1081 ret = GetBoundsRect( hdc, &rect, 0 );
1082 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1083 SetRect( &expect, 0, 0, 256, 51 );
1084 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1086 /* test the wide pen heuristics */
1087 SetBoundsRect( hdc, NULL, DCB_ENABLE | DCB_RESET );
1088 for (i = 0; i < 1000; i++)
1090 static const UINT endcaps[3] = { PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT };
1091 static const UINT joins[3] = { PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER };
1092 LOGBRUSH brush = { BS_SOLID, RGB(0,0,0), 0 };
1093 UINT join = joins[i % 3];
1094 UINT endcap = endcaps[(i / 3) % 3];
1095 INT inflate, width = 1 + i / 9;
1096 HPEN pen = ExtCreatePen( PS_GEOMETRIC | join | endcap | PS_SOLID, width, &brush, 0, NULL );
1097 HPEN old = SelectObject( hdc, pen );
1098 MoveToEx( hdc, 100, 100, NULL );
1099 LineTo( hdc, 160, 100 );
1100 LineTo( hdc, 100, 160 );
1101 LineTo( hdc, 160, 160 );
1102 GetBoundsRect( hdc, &rect, DCB_RESET );
1103 SetRect( &expect, 100, 100, 161, 161 );
1105 inflate = width + 2;
1106 if (join == PS_JOIN_MITER)
1108 inflate *= 5;
1109 if (endcap == PS_ENDCAP_SQUARE)
1110 InflateRect( &expect, (inflate * 3 + 1) / 2, (inflate * 3 + 1) / 2 );
1111 else
1112 InflateRect( &expect, inflate, inflate );
1114 else
1116 if (endcap == PS_ENDCAP_SQUARE)
1117 InflateRect( &expect, inflate - inflate / 4, inflate - inflate / 4 );
1118 else
1119 InflateRect( &expect, (inflate + 1) / 2, (inflate + 1) / 2 );
1121 expect.left = max( expect.left, 0 );
1122 expect.top = max( expect.top, 0 );
1123 expect.right = min( expect.right, 256 );
1124 expect.bottom = min( expect.bottom, 256 );
1125 ok(EqualRect(&rect, &expect), "Got %s expected %s %u/%x/%x\n", wine_dbgstr_rect(&rect),
1126 wine_dbgstr_rect(&expect), width, endcap, join);
1127 DeleteObject( SelectObject( hdc, old ));
1130 DeleteDC( hdc );
1131 DeleteObject( bitmap );
1132 DeleteObject( dib );
1135 static void test_desktop_colorres(void)
1137 HDC hdc = GetDC(NULL);
1138 int bitspixel, colorres;
1140 bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
1141 ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
1143 colorres = GetDeviceCaps(hdc, COLORRES);
1144 ok(colorres != 0 ||
1145 broken(colorres == 0), /* Win9x */
1146 "Expected to get valid COLORRES capability value\n");
1148 if (colorres)
1150 switch (bitspixel)
1152 case 8:
1153 ok(colorres == 18,
1154 "Expected COLORRES to be 18, got %d\n", colorres);
1155 break;
1156 case 16:
1157 ok(colorres == 16,
1158 "Expected COLORRES to be 16, got %d\n", colorres);
1159 break;
1160 case 24:
1161 case 32:
1162 ok(colorres == 24,
1163 "Expected COLORRES to be 24, got %d\n", bitspixel);
1164 break;
1165 default:
1166 ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
1167 break;
1171 ReleaseDC(NULL, hdc);
1174 static void test_gamma(void)
1176 BOOL ret;
1177 HDC hdc = GetDC(NULL);
1178 WORD oldramp[3][256], ramp[3][256];
1179 INT i;
1181 ret = GetDeviceGammaRamp(hdc, &oldramp);
1182 if (!ret)
1184 win_skip("GetDeviceGammaRamp failed, skipping tests\n");
1185 goto done;
1188 /* try to set back old ramp */
1189 ret = SetDeviceGammaRamp(hdc, &oldramp);
1190 if (!ret)
1192 win_skip("SetDeviceGammaRamp failed, skipping tests\n");
1193 goto done;
1196 memcpy(ramp, oldramp, sizeof(ramp));
1198 /* set one color ramp to zeros */
1199 memset(ramp[0], 0, sizeof(ramp[0]));
1200 ret = SetDeviceGammaRamp(hdc, &ramp);
1201 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1203 /* set one color ramp to a flat straight rising line */
1204 for (i = 0; i < 256; i++) ramp[0][i] = i;
1205 ret = SetDeviceGammaRamp(hdc, &ramp);
1206 todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
1208 /* set one color ramp to a steep straight rising line */
1209 for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
1210 ret = SetDeviceGammaRamp(hdc, &ramp);
1211 ok(ret, "SetDeviceGammaRamp failed\n");
1213 /* try a bright gamma ramp */
1214 ramp[0][0] = 0;
1215 ramp[0][1] = 0x7FFF;
1216 for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
1217 ret = SetDeviceGammaRamp(hdc, &ramp);
1218 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1220 /* try ramps which are not uniform */
1221 ramp[0][0] = 0;
1222 for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
1223 ret = SetDeviceGammaRamp(hdc, &ramp);
1224 ok(ret, "SetDeviceGammaRamp failed\n");
1225 ramp[0][0] = 0;
1226 for (i = 2; i < 256; i+=2)
1228 ramp[0][i - 1] = ramp[0][i - 2];
1229 ramp[0][i] = ramp[0][i - 2] + 512;
1231 ret = SetDeviceGammaRamp(hdc, &ramp);
1232 ok(ret, "SetDeviceGammaRamp failed\n");
1234 /* cleanup: set old ramp again */
1235 ret = SetDeviceGammaRamp(hdc, &oldramp);
1236 ok(ret, "SetDeviceGammaRamp failed\n");
1238 done:
1239 ReleaseDC(NULL, hdc);
1242 static BOOL is_postscript_printer(HDC hdc)
1244 char tech[256];
1246 if (ExtEscape(hdc, GETTECHNOLOGY, 0, NULL, sizeof(tech), tech) > 0)
1247 return strcmp(tech, "PostScript") == 0;
1249 return FALSE;
1252 static HDC create_printer_dc(int scale, BOOL reset)
1254 char buffer[260];
1255 DWORD len;
1256 PRINTER_INFO_2A *pbuf = NULL;
1257 DRIVER_INFO_3A *dbuf = NULL;
1258 HANDLE hprn = 0;
1259 HDC hdc = 0;
1260 HMODULE winspool = LoadLibraryA( "winspool.drv" );
1261 BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
1262 BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
1263 BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
1264 BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
1265 BOOL (WINAPI *pClosePrinter)(HANDLE);
1267 pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
1268 pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
1269 pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
1270 pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
1271 pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
1273 if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
1274 goto done;
1276 len = sizeof(buffer);
1277 if (!pGetDefaultPrinterA( buffer, &len )) goto done;
1278 if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
1280 pGetPrinterA( hprn, 2, NULL, 0, &len );
1281 pbuf = HeapAlloc( GetProcessHeap(), 0, len );
1282 if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
1284 pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
1285 dbuf = HeapAlloc( GetProcessHeap(), 0, len );
1286 if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
1288 pbuf->pDevMode->u1.s1.dmScale = scale;
1289 pbuf->pDevMode->dmFields |= DM_SCALE;
1291 hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
1292 trace( "hdc %p for driver '%s' printer '%s' port '%s' is %sPostScript\n", hdc,
1293 dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName,
1294 is_postscript_printer(hdc) ? "" : "NOT " );
1296 if (reset) ResetDCA( hdc, pbuf->pDevMode );
1297 done:
1298 HeapFree( GetProcessHeap(), 0, dbuf );
1299 HeapFree( GetProcessHeap(), 0, pbuf );
1300 if (hprn) pClosePrinter( hprn );
1301 if (winspool) FreeLibrary( winspool );
1302 if (!hdc) skip( "could not create a DC for the default printer\n" );
1303 return hdc;
1306 static void test_printer_dc(void)
1308 HDC memdc, display_memdc, enhmf_dc;
1309 HBITMAP orig, bmp;
1310 DWORD ret;
1311 HDC hdc, hdc_200;
1313 hdc = create_printer_dc(100, FALSE);
1314 hdc_200 = create_printer_dc(200, FALSE);
1316 if (!hdc || !hdc_200) return;
1318 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1319 DeleteDC( hdc_200 );
1321 hdc_200 = create_printer_dc(200, TRUE);
1322 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1323 DeleteDC( hdc_200 );
1325 memdc = CreateCompatibleDC( hdc );
1326 display_memdc = CreateCompatibleDC( 0 );
1328 ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
1329 ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
1331 ret = GetDeviceCaps( hdc, TECHNOLOGY );
1332 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1334 ret = GetDeviceCaps( memdc, TECHNOLOGY );
1335 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1337 ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
1338 ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
1340 bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
1341 orig = SelectObject( memdc, bmp );
1342 ok( orig != NULL, "SelectObject failed\n" );
1343 ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1345 test_device_caps( memdc, hdc, "printer dc", 1 );
1347 ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
1348 SelectObject( memdc, orig );
1349 DeleteObject( bmp );
1351 bmp = CreateBitmap( 100, 100, 1, 1, NULL );
1352 orig = SelectObject( display_memdc, bmp );
1353 ok( orig != NULL, "SelectObject failed\n" );
1354 ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
1355 ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1356 ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1357 ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1359 ret = GetPixel( hdc, 0, 0 );
1360 ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
1362 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1363 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1364 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1365 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1367 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1368 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1369 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1370 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1372 DeleteDC( memdc );
1373 DeleteDC( display_memdc );
1374 DeleteDC( hdc );
1375 DeleteObject( bmp );
1378 START_TEST(dc)
1380 pSetLayout = (void *)GetProcAddress( GetModuleHandleA("gdi32.dll"), "SetLayout");
1381 test_dc_values();
1382 test_savedc();
1383 test_savedc_2();
1384 test_GdiConvertToDevmodeW();
1385 test_CreateCompatibleDC();
1386 test_DC_bitmap();
1387 test_DeleteDC();
1388 test_boundsrect();
1389 test_desktop_colorres();
1390 test_gamma();
1391 test_printer_dc();