gdi32: Add support for DIBINDEX colors in 1-bpp blits.
[wine.git] / dlls / gdi32 / tests / dc.c
blobadd2c04aa2adcbb3701c168a0b1c2db420870224
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 < sizeof(caps)/sizeof(caps[0]); 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 < sizeof(caps)/sizeof(caps[0]); 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;
405 ok( abs(hdc_caps - GetDeviceCaps( ref_dc, caps[i] )) <= precision,
406 "mismatched caps on %s for %u: %u/%u (scale %d)\n", descr, caps[i],
407 hdc_caps, GetDeviceCaps( ref_dc, caps[i] ), scale );
410 SetLastError( 0xdeadbeef );
411 ret = GetDeviceGammaRamp( hdc, &ramp );
412 if (GetObjectType( hdc ) != OBJ_DC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER)
414 ok( !ret, "GetDeviceGammaRamp succeeded on %s (type %d)\n", descr, GetObjectType( hdc ) );
415 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
416 "wrong error %u on %s\n", GetLastError(), descr );
418 else
419 ok( ret || broken(!ret) /* NT4 */, "GetDeviceGammaRamp failed on %s (type %d), error %u\n", descr, GetObjectType( hdc ), GetLastError() );
420 type = GetClipBox( hdc, &rect );
421 todo_wine_if (GetObjectType( hdc ) == OBJ_ENHMETADC)
422 ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
424 type = GetBoundsRect( hdc, &rect, 0 );
425 ok( type == DCB_RESET || broken(type == DCB_SET) /* XP */,
426 "GetBoundsRect returned type %x for %s\n", type, descr );
427 if (type == DCB_RESET)
428 ok( rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0,
429 "GetBoundsRect returned %s type %x for %s\n", wine_dbgstr_rect( &rect ),
430 type, descr );
431 type = SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
432 ok( type == (DCB_RESET | DCB_DISABLE) || broken(type == (DCB_SET | DCB_ENABLE)) /* XP */,
433 "SetBoundsRect returned %x for %s (hdc type %d)\n", type, descr, GetObjectType( hdc ) );
435 SetMapMode( hdc, MM_TEXT );
436 Rectangle( hdc, 2, 2, 4, 4 );
437 type = GetBoundsRect( hdc, &rect, DCB_RESET );
438 todo_wine_if (GetObjectType( hdc ) == OBJ_ENHMETADC || (GetObjectType( hdc ) == OBJ_DC && GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER))
439 ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
440 "GetBoundsRect returned %s type %x for %s\n", wine_dbgstr_rect( &rect ),
441 type, descr );
444 type = GetClipBox( ref_dc, &rect );
445 if (type != COMPLEXREGION && type != ERROR) /* region can be complex on multi-monitor setups */
447 RECT ref_rect;
449 ok( type == SIMPLEREGION, "GetClipBox returned %d on %s\n", type, descr );
450 if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY)
452 todo_wine_if (GetSystemMetrics( SM_CXSCREEN ) != GetSystemMetrics( SM_CXVIRTUALSCREEN ))
453 ok( GetDeviceCaps( ref_dc, DESKTOPHORZRES ) == GetSystemMetrics( SM_CXSCREEN ),
454 "Got DESKTOPHORZRES %d on %s, expected %d\n",
455 GetDeviceCaps( ref_dc, DESKTOPHORZRES ), descr, GetSystemMetrics( SM_CXSCREEN ) );
457 todo_wine_if (GetSystemMetrics( SM_CYSCREEN ) != GetSystemMetrics( SM_CYVIRTUALSCREEN ))
458 ok( GetDeviceCaps( ref_dc, DESKTOPVERTRES ) == GetSystemMetrics( SM_CYSCREEN ),
459 "Got DESKTOPVERTRES %d on %s, expected %d\n",
460 GetDeviceCaps( ref_dc, DESKTOPVERTRES ), descr, GetSystemMetrics( SM_CYSCREEN ) );
462 SetRect( &ref_rect, GetSystemMetrics( SM_XVIRTUALSCREEN ), GetSystemMetrics( SM_YVIRTUALSCREEN ),
463 GetSystemMetrics( SM_XVIRTUALSCREEN ) + GetSystemMetrics( SM_CXVIRTUALSCREEN ),
464 GetSystemMetrics( SM_YVIRTUALSCREEN ) + GetSystemMetrics( SM_CYVIRTUALSCREEN ) );
466 else
468 SetRect( &ref_rect, 0, 0, GetDeviceCaps( ref_dc, DESKTOPHORZRES ),
469 GetDeviceCaps( ref_dc, DESKTOPVERTRES ) );
472 todo_wine_if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY && GetObjectType( hdc ) != OBJ_ENHMETADC &&
473 (GetSystemMetrics( SM_XVIRTUALSCREEN ) || GetSystemMetrics( SM_YVIRTUALSCREEN )))
474 ok( EqualRect( &rect, &ref_rect ), "GetClipBox returned %s on %s\n",
475 wine_dbgstr_rect( &rect ), descr );
478 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_ACCUMULATE );
479 SetMapMode( ref_dc, MM_TEXT );
480 Rectangle( ref_dc, 3, 3, 5, 5 );
481 type = GetBoundsRect( ref_dc, &rect, DCB_RESET );
482 /* it may or may not work on non-memory DCs */
483 ok( (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && type == DCB_RESET) ||
484 (rect.left == 3 && rect.top == 3 && rect.right == 5 && rect.bottom == 5 && type == DCB_SET),
485 "GetBoundsRect returned %s type %x on %s\n", wine_dbgstr_rect( &rect ), type, descr );
487 if (GetObjectType( hdc ) == OBJ_MEMDC)
489 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
490 BITMAPINFO *info = (BITMAPINFO *)buffer;
491 HBITMAP dib, old;
493 memset( buffer, 0, sizeof(buffer) );
494 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
495 info->bmiHeader.biWidth = 16;
496 info->bmiHeader.biHeight = 16;
497 info->bmiHeader.biPlanes = 1;
498 info->bmiHeader.biBitCount = 8;
499 info->bmiHeader.biCompression = BI_RGB;
500 dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
501 old = SelectObject( hdc, dib );
503 for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
504 ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
505 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
506 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
508 SetLastError( 0xdeadbeef );
509 ret = GetDeviceGammaRamp( hdc, &ramp );
510 ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
511 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
512 "wrong error %u on %s\n", GetLastError(), descr );
514 type = GetClipBox( hdc, &rect );
515 ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
516 ok( rect.left == 0 && rect.top == 0 && rect.right == 16 && rect.bottom == 16,
517 "GetClipBox returned %s on memdc for %s\n", wine_dbgstr_rect( &rect ), descr );
519 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
520 SetMapMode( hdc, MM_TEXT );
521 Rectangle( hdc, 5, 5, 12, 14 );
522 type = GetBoundsRect( hdc, &rect, DCB_RESET );
523 ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
524 "GetBoundsRect returned %s type %x on memdc for %s\n", wine_dbgstr_rect( &rect ),
525 type, descr );
527 SelectObject( hdc, old );
528 DeleteObject( dib );
531 /* restore hdc state */
532 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_DISABLE );
533 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_DISABLE );
536 static void test_CreateCompatibleDC(void)
538 BOOL bRet;
539 HDC hdc, hNewDC, hdcMetafile, screen_dc;
540 HBITMAP bitmap;
541 INT caps;
542 DEVMODEA dm;
544 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
546 bRet = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm);
547 ok(bRet, "EnumDisplaySettingsEx failed\n");
548 dm.u1.s1.dmScale = 200;
549 dm.dmFields |= DM_SCALE;
550 hdc = CreateDCA( "DISPLAY", NULL, NULL, &dm );
552 screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
553 test_device_caps( hdc, screen_dc, "display dc", 1 );
554 ResetDCA( hdc, &dm );
555 test_device_caps( hdc, screen_dc, "display dc", 1 );
556 DeleteDC( hdc );
558 /* Create a DC compatible with the screen */
559 hdc = CreateCompatibleDC(NULL);
560 ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
561 ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
562 caps = GetDeviceCaps( hdc, TECHNOLOGY );
563 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
565 test_device_caps( hdc, screen_dc, "display dc", 1 );
567 /* Delete this DC, this should succeed */
568 bRet = DeleteDC(hdc);
569 ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
571 /* Try to create a DC compatible to the deleted DC. This has to fail */
572 hNewDC = CreateCompatibleDC(hdc);
573 ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
575 hdc = GetDC( 0 );
576 hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
577 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
578 hNewDC = CreateCompatibleDC( hdcMetafile );
579 ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
580 ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
581 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
582 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
583 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
584 ResetDCA( hdcMetafile, &dm );
585 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
586 DeleteDC( hNewDC );
587 DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
588 ReleaseDC( 0, hdc );
590 hdcMetafile = CreateMetaFileA(NULL);
591 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
592 hNewDC = CreateCompatibleDC( hdcMetafile );
593 ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
594 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
595 ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
596 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
597 ResetDCA( hdcMetafile, &dm );
598 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
599 DeleteMetaFile( CloseMetaFile( hdcMetafile ));
601 DeleteObject( bitmap );
602 DeleteDC( screen_dc );
605 static void test_DC_bitmap(void)
607 PIXELFORMATDESCRIPTOR descr;
608 HDC hdc, hdcmem;
609 DWORD bits[64];
610 HBITMAP hbmp, oldhbmp;
611 COLORREF col;
612 int i, bitspixel;
613 int ret, ret2;
615 /* fill bitmap data with b&w pattern */
616 for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
618 hdc = GetDC(0);
619 ok( hdc != NULL, "CreateDC rets %p\n", hdc);
620 bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
621 /* create a memory dc */
622 hdcmem = CreateCompatibleDC( hdc);
623 ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
625 /* test DescribePixelFormat with descr == NULL */
626 ret2 = DescribePixelFormat(hdcmem, 0, sizeof(descr), NULL);
627 ok(ret2 > 0, "expected ret2 > 0, got %d\n", ret2);
628 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), NULL);
629 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
630 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), NULL);
631 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
633 /* test DescribePixelFormat with descr != NULL */
634 memset(&descr, 0, sizeof(descr));
635 ret = DescribePixelFormat(hdcmem, 0, sizeof(descr), &descr);
636 ok(ret == 0, "expected ret == 0, got %d\n", ret);
637 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
639 memset(&descr, 0, sizeof(descr));
640 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), &descr);
641 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
642 ok(descr.nSize == sizeof(descr), "expected desc.nSize == sizeof(descr), got %d\n", descr.nSize);
644 memset(&descr, 0, sizeof(descr));
645 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), &descr);
646 ok(ret == 0, "expected ret == 0, got %d\n", ret);
647 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
649 /* test monochrome bitmap: should always work */
650 hbmp = CreateBitmap(32, 32, 1, 1, bits);
651 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
652 oldhbmp = SelectObject( hdcmem, hbmp);
653 ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
654 col = GetPixel( hdcmem, 0, 0);
655 ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
656 col = GetPixel( hdcmem, 1, 1);
657 ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
658 col = GetPixel( hdcmem, 100, 1);
659 ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
660 SelectObject( hdcmem, oldhbmp);
661 DeleteObject( hbmp);
663 /* test with 2 bits color depth, not likely to succeed */
664 hbmp = CreateBitmap(16, 16, 1, 2, bits);
665 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
666 oldhbmp = SelectObject( hdcmem, hbmp);
667 if( bitspixel != 2)
668 ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return NULL\n");
669 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
670 DeleteObject( hbmp);
672 /* test with 16 bits color depth, might succeed */
673 hbmp = CreateBitmap(6, 6, 1, 16, bits);
674 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
675 oldhbmp = SelectObject( hdcmem, hbmp);
676 if( bitspixel == 16) {
677 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
678 col = GetPixel( hdcmem, 0, 0);
679 ok( col == 0xffffff,
680 "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
681 col = GetPixel( hdcmem, 1, 1);
682 ok( col == 0x000000,
683 "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
685 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
686 DeleteObject( hbmp);
688 /* test with 32 bits color depth, probably succeed */
689 hbmp = CreateBitmap(4, 4, 1, 32, bits);
690 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
691 oldhbmp = SelectObject( hdcmem, hbmp);
692 if( bitspixel == 32) {
693 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
694 col = GetPixel( hdcmem, 0, 0);
695 ok( col == 0xffffff,
696 "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
697 col = GetPixel( hdcmem, 1, 1);
698 ok( col == 0x000000,
699 "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
701 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
702 DeleteObject( hbmp);
703 ReleaseDC( 0, hdc );
706 static void test_DeleteDC(void)
708 HWND hwnd;
709 HDC hdc, hdc_test;
710 WNDCLASSEXA cls;
711 int ret;
713 /* window DC */
714 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
715 0, 0, 0, NULL);
716 ok(hwnd != 0, "CreateWindowExA failed\n");
718 hdc = GetDC(hwnd);
719 ok(hdc != 0, "GetDC failed\n");
720 ret = GetObjectType(hdc);
721 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
722 ret = DeleteDC(hdc);
723 ok(ret, "DeleteDC failed\n");
724 ret = GetObjectType(hdc);
725 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
727 hdc = GetWindowDC(hwnd);
728 ok(hdc != 0, "GetDC failed\n");
729 ret = GetObjectType(hdc);
730 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
731 ret = DeleteDC(hdc);
732 ok(ret, "DeleteDC failed\n");
733 ret = GetObjectType(hdc);
734 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
736 DestroyWindow(hwnd);
738 /* desktop window DC */
739 hwnd = GetDesktopWindow();
740 ok(hwnd != 0, "GetDesktopWindow failed\n");
742 hdc = GetDC(hwnd);
743 ok(hdc != 0, "GetDC failed\n");
744 ret = GetObjectType(hdc);
745 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
746 ret = DeleteDC(hdc);
747 ok(ret, "DeleteDC failed\n");
748 ret = GetObjectType(hdc);
749 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
751 hdc = GetWindowDC(hwnd);
752 ok(hdc != 0, "GetDC failed\n");
753 ret = GetObjectType(hdc);
754 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
755 ret = DeleteDC(hdc);
756 ok(ret, "DeleteDC failed\n");
757 ret = GetObjectType(hdc);
758 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
760 /* CS_CLASSDC */
761 memset(&cls, 0, sizeof(cls));
762 cls.cbSize = sizeof(cls);
763 cls.style = CS_CLASSDC;
764 cls.hInstance = GetModuleHandleA(NULL);
765 cls.lpszClassName = "Wine class DC";
766 cls.lpfnWndProc = DefWindowProcA;
767 ret = RegisterClassExA(&cls);
768 ok(ret, "RegisterClassExA failed\n");
770 hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
771 0, 0, 0, NULL);
772 ok(hwnd != 0, "CreateWindowExA failed\n");
774 hdc = GetDC(hwnd);
775 ok(hdc != 0, "GetDC failed\n");
776 ret = GetObjectType(hdc);
777 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
778 ret = DeleteDC(hdc);
779 ok(ret, "DeleteDC failed\n");
780 ret = GetObjectType(hdc);
781 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
782 ret = ReleaseDC(hwnd, hdc);
783 ok(ret, "ReleaseDC failed\n");
784 ret = GetObjectType(hdc);
785 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
787 hdc_test = hdc;
789 hdc = GetWindowDC(hwnd);
790 ok(hdc != 0, "GetDC failed\n");
791 ret = GetObjectType(hdc);
792 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
793 ret = DeleteDC(hdc);
794 ok(ret, "DeleteDC failed\n");
795 ret = GetObjectType(hdc);
796 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
798 DestroyWindow(hwnd);
800 ret = GetObjectType(hdc_test);
801 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
803 ret = UnregisterClassA("Wine class DC", GetModuleHandleA(NULL));
804 ok(ret, "UnregisterClassA failed\n");
806 ret = GetObjectType(hdc_test);
807 ok(!ret, "GetObjectType should fail for a deleted DC\n");
809 /* CS_OWNDC */
810 memset(&cls, 0, sizeof(cls));
811 cls.cbSize = sizeof(cls);
812 cls.style = CS_OWNDC;
813 cls.hInstance = GetModuleHandleA(NULL);
814 cls.lpszClassName = "Wine own DC";
815 cls.lpfnWndProc = DefWindowProcA;
816 ret = RegisterClassExA(&cls);
817 ok(ret, "RegisterClassExA failed\n");
819 hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
820 0, 0, 0, NULL);
821 ok(hwnd != 0, "CreateWindowExA failed\n");
823 hdc = GetDC(hwnd);
824 ok(hdc != 0, "GetDC failed\n");
825 ret = GetObjectType(hdc);
826 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
827 ret = DeleteDC(hdc);
828 ok(ret, "DeleteDC failed\n");
829 ret = GetObjectType(hdc);
830 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
831 ret = ReleaseDC(hwnd, hdc);
832 ok(ret, "ReleaseDC failed\n");
833 ret = GetObjectType(hdc);
834 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
836 hdc = GetWindowDC(hwnd);
837 ok(hdc != 0, "GetDC failed\n");
838 ret = GetObjectType(hdc);
839 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
840 ret = DeleteDC(hdc);
841 ok(ret, "DeleteDC failed\n");
842 ret = GetObjectType(hdc);
843 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
845 DestroyWindow(hwnd);
847 ret = UnregisterClassA("Wine own DC", GetModuleHandleA(NULL));
848 ok(ret, "UnregisterClassA failed\n");
851 static void test_boundsrect(void)
853 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
854 BITMAPINFO *info = (BITMAPINFO *)buffer;
855 HDC hdc;
856 HBITMAP bitmap, dib, old;
857 RECT rect, expect, set_rect;
858 UINT ret;
859 int i, level;
861 hdc = CreateCompatibleDC(0);
862 ok(hdc != NULL, "CreateCompatibleDC failed\n");
863 bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
864 old = SelectObject( hdc, bitmap );
866 ret = GetBoundsRect(hdc, NULL, 0);
867 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
869 ret = GetBoundsRect(hdc, NULL, ~0U);
870 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
872 /* Test parameter handling order. */
873 SetRect(&set_rect, 10, 20, 40, 50);
874 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
875 ok(ret & DCB_RESET,
876 "Expected return flag DCB_RESET to be set, got %u\n", ret);
878 ret = GetBoundsRect(hdc, NULL, DCB_RESET);
879 ok(ret == 0,
880 "Expected GetBoundsRect to return 0, got %u\n", ret);
882 ret = GetBoundsRect(hdc, &rect, 0);
883 ok(ret == DCB_RESET,
884 "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
885 SetRectEmpty(&expect);
886 ok(EqualRect(&rect, &expect), "Expected output rectangle (0,0)-(0,0), got %s\n",
887 wine_dbgstr_rect(&rect));
889 ret = GetBoundsRect(NULL, NULL, 0);
890 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
892 ret = GetBoundsRect(NULL, NULL, ~0U);
893 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
895 ret = SetBoundsRect(NULL, NULL, 0);
896 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
898 ret = SetBoundsRect(NULL, NULL, ~0U);
899 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
901 SetRect(&set_rect, 10, 20, 40, 50);
902 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
903 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
905 ret = GetBoundsRect(hdc, &rect, 0);
906 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
907 SetRect(&expect, 10, 20, 40, 50);
908 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
910 SetMapMode( hdc, MM_ANISOTROPIC );
911 SetViewportExtEx( hdc, 2, 2, NULL );
912 ret = GetBoundsRect(hdc, &rect, 0);
913 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
914 SetRect(&expect, 5, 10, 20, 25);
915 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
917 SetViewportOrgEx( hdc, 20, 30, NULL );
918 ret = GetBoundsRect(hdc, &rect, 0);
919 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
920 SetRect(&expect, -5, -5, 10, 10);
921 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
923 SetRect(&set_rect, 10, 20, 40, 50);
924 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
925 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
927 ret = GetBoundsRect(hdc, &rect, 0);
928 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
929 SetRect(&expect, 10, 20, 40, 50);
930 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
932 SetMapMode( hdc, MM_TEXT );
933 SetViewportOrgEx( hdc, 0, 0, NULL );
934 ret = GetBoundsRect(hdc, &rect, 0);
935 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
936 SetRect(&expect, 40, 70, 100, 130);
937 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
939 if (pSetLayout)
941 pSetLayout( hdc, LAYOUT_RTL );
942 ret = GetBoundsRect(hdc, &rect, 0);
943 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
944 SetRect(&expect, 159, 70, 99, 130);
945 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
946 SetRect(&set_rect, 50, 25, 30, 35);
947 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
948 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
949 ret = GetBoundsRect(hdc, &rect, 0);
950 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
951 SetRect(&expect, 50, 25, 30, 35);
952 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
954 pSetLayout( hdc, LAYOUT_LTR );
955 ret = GetBoundsRect(hdc, &rect, 0);
956 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
957 SetRect(&expect, 149, 25, 169, 35);
958 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
961 /* empty rect resets, except on nt4 */
962 SetRect(&expect, 20, 20, 10, 10);
963 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
964 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
965 ret = GetBoundsRect(hdc, &rect, 0);
966 ok(ret == DCB_RESET || broken(ret == DCB_SET) /* nt4 */,
967 "GetBoundsRect returned %x\n", ret);
968 if (ret == DCB_RESET)
970 SetRectEmpty(&expect);
971 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
973 SetRect(&expect, 20, 20, 20, 20);
974 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
975 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
976 ret = GetBoundsRect(hdc, &rect, 0);
977 ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
978 SetRectEmpty(&expect);
979 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
982 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
983 MoveToEx( hdc, 10, 10, NULL );
984 LineTo( hdc, 20, 20 );
985 ret = GetBoundsRect( hdc, &rect, 0 );
986 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
987 SetRect( &expect, 10, 10, 21, 21 );
988 ok( EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
989 SetRect( &rect, 8, 8, 23, 23 );
990 expect = rect;
991 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
992 ret = GetBoundsRect( hdc, &rect, 0 );
993 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
994 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
996 level = SaveDC( hdc );
997 LineTo( hdc, 30, 25 );
998 ret = GetBoundsRect( hdc, &rect, 0 );
999 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1000 SetRect( &expect, 8, 8, 31, 26 );
1001 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1002 SetBoundsRect( hdc, NULL, DCB_DISABLE );
1003 LineTo( hdc, 40, 40 );
1004 ret = GetBoundsRect( hdc, &rect, 0 );
1005 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1006 SetRect( &expect, 8, 8, 31, 26 );
1007 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1008 SetRect( &rect, 6, 6, 30, 30 );
1009 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1010 ret = GetBoundsRect( hdc, &rect, 0 );
1011 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1012 SetRect( &expect, 6, 6, 31, 30 );
1013 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1015 RestoreDC( hdc, level );
1016 ret = GetBoundsRect( hdc, &rect, 0 );
1017 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1018 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1019 LineTo( hdc, 40, 40 );
1020 ret = GetBoundsRect( hdc, &rect, 0 );
1021 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1022 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1024 SelectObject( hdc, old );
1025 ret = GetBoundsRect( hdc, &rect, 0 );
1026 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1027 SetRect( &expect, 6, 6, 1, 1 );
1028 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1029 SetBoundsRect( hdc, NULL, DCB_ENABLE );
1030 LineTo( hdc, 50, 40 );
1032 SelectObject( hdc, bitmap );
1033 ret = GetBoundsRect( hdc, &rect, 0 );
1034 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1035 SetRect( &expect, 6, 6, 51, 41 );
1036 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1037 SelectObject( hdc, GetStockObject( NULL_PEN ));
1038 LineTo( hdc, 50, 50 );
1039 ret = GetBoundsRect( hdc, &rect, 0 );
1040 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1041 SetRect( &expect, 6, 6, 51, 51 );
1042 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1044 memset( buffer, 0, sizeof(buffer) );
1045 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1046 info->bmiHeader.biWidth = 256;
1047 info->bmiHeader.biHeight = 256;
1048 info->bmiHeader.biPlanes = 1;
1049 info->bmiHeader.biBitCount = 8;
1050 info->bmiHeader.biCompression = BI_RGB;
1051 dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, NULL, NULL, 0 );
1052 ok( dib != 0, "failed to create DIB\n" );
1053 SelectObject( hdc, dib );
1054 ret = GetBoundsRect( hdc, &rect, 0 );
1055 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1056 SetRect( &expect, 6, 6, 51, 51 );
1057 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1058 LineTo( hdc, 55, 30 );
1059 ret = GetBoundsRect( hdc, &rect, 0 );
1060 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1061 SetRect( &expect, 6, 6, 56, 51 );
1062 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1063 LineTo( hdc, 300, 30 );
1064 ret = GetBoundsRect( hdc, &rect, 0 );
1065 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1066 SetRect( &expect, 6, 6, 256, 51 );
1067 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1068 LineTo( hdc, -300, -300 );
1069 ret = GetBoundsRect( hdc, &rect, 0 );
1070 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1071 SetRect( &expect, 0, 0, 256, 51 );
1072 ok(EqualRect(&rect, &expect), "Got %s\n", wine_dbgstr_rect(&rect));
1074 /* test the wide pen heuristics */
1075 SetBoundsRect( hdc, NULL, DCB_ENABLE | DCB_RESET );
1076 for (i = 0; i < 1000; i++)
1078 static const UINT endcaps[3] = { PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT };
1079 static const UINT joins[3] = { PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER };
1080 LOGBRUSH brush = { BS_SOLID, RGB(0,0,0), 0 };
1081 UINT join = joins[i % 3];
1082 UINT endcap = endcaps[(i / 3) % 3];
1083 INT inflate, width = 1 + i / 9;
1084 HPEN pen = ExtCreatePen( PS_GEOMETRIC | join | endcap | PS_SOLID, width, &brush, 0, NULL );
1085 HPEN old = SelectObject( hdc, pen );
1086 MoveToEx( hdc, 100, 100, NULL );
1087 LineTo( hdc, 160, 100 );
1088 LineTo( hdc, 100, 160 );
1089 LineTo( hdc, 160, 160 );
1090 GetBoundsRect( hdc, &rect, DCB_RESET );
1091 SetRect( &expect, 100, 100, 161, 161 );
1093 inflate = width + 2;
1094 if (join == PS_JOIN_MITER)
1096 inflate *= 5;
1097 if (endcap == PS_ENDCAP_SQUARE)
1098 InflateRect( &expect, (inflate * 3 + 1) / 2, (inflate * 3 + 1) / 2 );
1099 else
1100 InflateRect( &expect, inflate, inflate );
1102 else
1104 if (endcap == PS_ENDCAP_SQUARE)
1105 InflateRect( &expect, inflate - inflate / 4, inflate - inflate / 4 );
1106 else
1107 InflateRect( &expect, (inflate + 1) / 2, (inflate + 1) / 2 );
1109 expect.left = max( expect.left, 0 );
1110 expect.top = max( expect.top, 0 );
1111 expect.right = min( expect.right, 256 );
1112 expect.bottom = min( expect.bottom, 256 );
1113 ok(EqualRect(&rect, &expect), "Got %s expected %s %u/%x/%x\n", wine_dbgstr_rect(&rect),
1114 wine_dbgstr_rect(&expect), width, endcap, join);
1115 DeleteObject( SelectObject( hdc, old ));
1118 DeleteDC( hdc );
1119 DeleteObject( bitmap );
1120 DeleteObject( dib );
1123 static void test_desktop_colorres(void)
1125 HDC hdc = GetDC(NULL);
1126 int bitspixel, colorres;
1128 bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
1129 ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
1131 colorres = GetDeviceCaps(hdc, COLORRES);
1132 ok(colorres != 0 ||
1133 broken(colorres == 0), /* Win9x */
1134 "Expected to get valid COLORRES capability value\n");
1136 if (colorres)
1138 switch (bitspixel)
1140 case 8:
1141 ok(colorres == 18,
1142 "Expected COLORRES to be 18, got %d\n", colorres);
1143 break;
1144 case 16:
1145 ok(colorres == 16,
1146 "Expected COLORRES to be 16, got %d\n", colorres);
1147 break;
1148 case 24:
1149 case 32:
1150 ok(colorres == 24,
1151 "Expected COLORRES to be 24, got %d\n", bitspixel);
1152 break;
1153 default:
1154 ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
1155 break;
1159 ReleaseDC(NULL, hdc);
1162 static void test_gamma(void)
1164 BOOL ret;
1165 HDC hdc = GetDC(NULL);
1166 WORD oldramp[3][256], ramp[3][256];
1167 INT i;
1169 ret = GetDeviceGammaRamp(hdc, &oldramp);
1170 if (!ret)
1172 win_skip("GetDeviceGammaRamp failed, skipping tests\n");
1173 goto done;
1176 /* try to set back old ramp */
1177 ret = SetDeviceGammaRamp(hdc, &oldramp);
1178 if (!ret)
1180 win_skip("SetDeviceGammaRamp failed, skipping tests\n");
1181 goto done;
1184 memcpy(ramp, oldramp, sizeof(ramp));
1186 /* set one color ramp to zeros */
1187 memset(ramp[0], 0, sizeof(ramp[0]));
1188 ret = SetDeviceGammaRamp(hdc, &ramp);
1189 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1191 /* set one color ramp to a flat straight rising line */
1192 for (i = 0; i < 256; i++) ramp[0][i] = i;
1193 ret = SetDeviceGammaRamp(hdc, &ramp);
1194 todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
1196 /* set one color ramp to a steep straight rising line */
1197 for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
1198 ret = SetDeviceGammaRamp(hdc, &ramp);
1199 ok(ret, "SetDeviceGammaRamp failed\n");
1201 /* try a bright gamma ramp */
1202 ramp[0][0] = 0;
1203 ramp[0][1] = 0x7FFF;
1204 for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
1205 ret = SetDeviceGammaRamp(hdc, &ramp);
1206 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1208 /* try ramps which are not uniform */
1209 ramp[0][0] = 0;
1210 for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
1211 ret = SetDeviceGammaRamp(hdc, &ramp);
1212 ok(ret, "SetDeviceGammaRamp failed\n");
1213 ramp[0][0] = 0;
1214 for (i = 2; i < 256; i+=2)
1216 ramp[0][i - 1] = ramp[0][i - 2];
1217 ramp[0][i] = ramp[0][i - 2] + 512;
1219 ret = SetDeviceGammaRamp(hdc, &ramp);
1220 ok(ret, "SetDeviceGammaRamp failed\n");
1222 /* cleanup: set old ramp again */
1223 ret = SetDeviceGammaRamp(hdc, &oldramp);
1224 ok(ret, "SetDeviceGammaRamp failed\n");
1226 done:
1227 ReleaseDC(NULL, hdc);
1230 static BOOL is_postscript_printer(HDC hdc)
1232 char tech[256];
1234 if (ExtEscape(hdc, GETTECHNOLOGY, 0, NULL, sizeof(tech), tech) > 0)
1235 return strcmp(tech, "PostScript") == 0;
1237 return FALSE;
1240 static HDC create_printer_dc(int scale, BOOL reset)
1242 char buffer[260];
1243 DWORD len;
1244 PRINTER_INFO_2A *pbuf = NULL;
1245 DRIVER_INFO_3A *dbuf = NULL;
1246 HANDLE hprn = 0;
1247 HDC hdc = 0;
1248 HMODULE winspool = LoadLibraryA( "winspool.drv" );
1249 BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
1250 BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
1251 BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
1252 BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
1253 BOOL (WINAPI *pClosePrinter)(HANDLE);
1255 pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
1256 pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
1257 pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
1258 pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
1259 pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
1261 if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
1262 goto done;
1264 len = sizeof(buffer);
1265 if (!pGetDefaultPrinterA( buffer, &len )) goto done;
1266 if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
1268 pGetPrinterA( hprn, 2, NULL, 0, &len );
1269 pbuf = HeapAlloc( GetProcessHeap(), 0, len );
1270 if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
1272 pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
1273 dbuf = HeapAlloc( GetProcessHeap(), 0, len );
1274 if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
1276 pbuf->pDevMode->u1.s1.dmScale = scale;
1277 pbuf->pDevMode->dmFields |= DM_SCALE;
1279 hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
1280 trace( "hdc %p for driver '%s' printer '%s' port '%s' is %sPostScript\n", hdc,
1281 dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName,
1282 is_postscript_printer(hdc) ? "" : "NOT " );
1284 if (reset) ResetDCA( hdc, pbuf->pDevMode );
1285 done:
1286 HeapFree( GetProcessHeap(), 0, dbuf );
1287 HeapFree( GetProcessHeap(), 0, pbuf );
1288 if (hprn) pClosePrinter( hprn );
1289 if (winspool) FreeLibrary( winspool );
1290 if (!hdc) skip( "could not create a DC for the default printer\n" );
1291 return hdc;
1294 static void test_printer_dc(void)
1296 HDC memdc, display_memdc, enhmf_dc;
1297 HBITMAP orig, bmp;
1298 DWORD ret;
1299 HDC hdc, hdc_200;
1301 hdc = create_printer_dc(100, FALSE);
1302 hdc_200 = create_printer_dc(200, FALSE);
1304 if (!hdc || !hdc_200) return;
1306 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1307 DeleteDC( hdc_200 );
1309 hdc_200 = create_printer_dc(200, TRUE);
1310 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1311 DeleteDC( hdc_200 );
1313 memdc = CreateCompatibleDC( hdc );
1314 display_memdc = CreateCompatibleDC( 0 );
1316 ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
1317 ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
1319 ret = GetDeviceCaps( hdc, TECHNOLOGY );
1320 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1322 ret = GetDeviceCaps( memdc, TECHNOLOGY );
1323 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1325 ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
1326 ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
1328 bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
1329 orig = SelectObject( memdc, bmp );
1330 ok( orig != NULL, "SelectObject failed\n" );
1331 ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1333 test_device_caps( memdc, hdc, "printer dc", 1 );
1335 ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
1336 SelectObject( memdc, orig );
1337 DeleteObject( bmp );
1339 bmp = CreateBitmap( 100, 100, 1, 1, NULL );
1340 orig = SelectObject( display_memdc, bmp );
1341 ok( orig != NULL, "SelectObject failed\n" );
1342 ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
1343 ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1344 ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1345 ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1347 ret = GetPixel( hdc, 0, 0 );
1348 ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
1350 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1351 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1352 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1353 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1355 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1356 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1357 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1358 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1360 DeleteDC( memdc );
1361 DeleteDC( display_memdc );
1362 DeleteDC( hdc );
1363 DeleteObject( bmp );
1366 START_TEST(dc)
1368 pSetLayout = (void *)GetProcAddress( GetModuleHandleA("gdi32.dll"), "SetLayout");
1369 test_dc_values();
1370 test_savedc();
1371 test_savedc_2();
1372 test_GdiConvertToDevmodeW();
1373 test_CreateCompatibleDC();
1374 test_DC_bitmap();
1375 test_DeleteDC();
1376 test_boundsrect();
1377 test_desktop_colorres();
1378 test_gamma();
1379 test_printer_dc();