7c5f2b35d1a93629ccbd2d232b5af547d0edd95c
[reactos.git] / rostests / winetests / gdi32 / dc.c
1 /*
2 * Unit tests for dc functions
3 *
4 * Copyright (c) 2005 Huw Davies
5 * Copyright (c) 2005,2016 Dmitry Timoshkov
6 *
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.
11 *
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.
16 *
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
20 */
21
22
23 #define WINVER 0x0501 /* request latest DEVMODE */
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26
27 #include <assert.h>
28 #include <stdio.h>
29
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"
36
37 #ifndef LAYOUT_LTR
38 #define LAYOUT_LTR 0
39 #endif
40
41 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
42
43 static void dump_region(HRGN hrgn)
44 {
45 DWORD i, size;
46 RGNDATA *data = NULL;
47 RECT *rect;
48
49 if (!hrgn)
50 {
51 printf( "(null) region\n" );
52 return;
53 }
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 );
62 }
63
64 static void test_dc_values(void)
65 {
66 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
67 COLORREF color;
68 int extra;
69
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 );
83
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 );
96
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 );
108
109 DeleteDC( hdc );
110 }
111
112 static void test_savedc_2(void)
113 {
114 HWND hwnd;
115 HDC hdc;
116 HRGN hrgn;
117 RECT rc, rc_clip;
118 int ret;
119
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);
125
126 hrgn = CreateRectRgn(0, 0, 0, 0);
127 assert(hrgn != 0);
128
129 hdc = GetDC(hwnd);
130 ok(hdc != NULL, "GetDC failed\n");
131
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 (%d,%d-%d,%d) instead of NULLREGION\n",
138 ret, rc.left, rc.top, rc.right, rc.bottom);
139 /*dump_region(hrgn);*/
140 SetRect(&rc, 0, 0, 100, 100);
141 ok(EqualRect(&rc, &rc_clip),
142 "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
143 rc.left, rc.top, rc.right, rc.bottom,
144 rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
145
146 ret = SaveDC(hdc);
147 ok(ret == 1, "ret = %d\n", ret);
148
149 ret = IntersectClipRect(hdc, 0, 0, 50, 50);
150 if (ret == COMPLEXREGION)
151 {
152 /* XP returns COMPLEXREGION although dump_region reports only 1 rect */
153 trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
154 /* let's make sure that it's a simple region */
155 ret = GetClipRgn(hdc, hrgn);
156 ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret);
157 dump_region(hrgn);
158 }
159 else
160 ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret);
161
162 ret = GetClipBox(hdc, &rc_clip);
163 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
164 SetRect(&rc, 0, 0, 50, 50);
165 ok(EqualRect(&rc, &rc_clip),
166 "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
167 rc.left, rc.top, rc.right, rc.bottom,
168 rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
169
170 ret = RestoreDC(hdc, 1);
171 ok(ret, "ret = %d\n", ret);
172
173 ret = GetClipBox(hdc, &rc_clip);
174 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret);
175 SetRect(&rc, 0, 0, 100, 100);
176 ok(EqualRect(&rc, &rc_clip),
177 "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n",
178 rc.left, rc.top, rc.right, rc.bottom,
179 rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
180
181 DeleteObject(hrgn);
182 ReleaseDC(hwnd, hdc);
183 DestroyWindow(hwnd);
184 }
185
186 static void test_savedc(void)
187 {
188 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
189 int ret;
190
191 ok(hdc != NULL, "CreateDC rets %p\n", hdc);
192
193 ret = SaveDC(hdc);
194 ok(ret == 1, "ret = %d\n", ret);
195 ret = SaveDC(hdc);
196 ok(ret == 2, "ret = %d\n", ret);
197 ret = SaveDC(hdc);
198 ok(ret == 3, "ret = %d\n", ret);
199 ret = RestoreDC(hdc, -1);
200 ok(ret, "ret = %d\n", ret);
201 ret = SaveDC(hdc);
202 ok(ret == 3, "ret = %d\n", ret);
203 ret = RestoreDC(hdc, 1);
204 ok(ret, "ret = %d\n", ret);
205 ret = SaveDC(hdc);
206 ok(ret == 1, "ret = %d\n", ret);
207 ret = SaveDC(hdc);
208 ok(ret == 2, "ret = %d\n", ret);
209 ret = SaveDC(hdc);
210 ok(ret == 3, "ret = %d\n", ret);
211 ret = RestoreDC(hdc, -2);
212 ok(ret, "ret = %d\n", ret);
213 ret = SaveDC(hdc);
214 ok(ret == 2, "ret = %d\n", ret);
215 ret = RestoreDC(hdc, -2);
216 ok(ret, "ret = %d\n", ret);
217 ret = SaveDC(hdc);
218 ok(ret == 1, "ret = %d\n", ret);
219 ret = SaveDC(hdc);
220 ok(ret == 2, "ret = %d\n", ret);
221 ret = RestoreDC(hdc, -4);
222 ok(!ret, "ret = %d\n", ret);
223 ret = RestoreDC(hdc, 3);
224 ok(!ret, "ret = %d\n", ret);
225
226 /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
227 ret = RestoreDC(hdc, -3);
228 ok(!ret ||
229 broken(ret), /* Win9x */
230 "ret = %d\n", ret);
231
232 /* Trying to clear an empty save stack fails. */
233 ret = RestoreDC(hdc, -3);
234 ok(!ret, "ret = %d\n", ret);
235
236 ret = SaveDC(hdc);
237 ok(ret == 3 ||
238 broken(ret == 1), /* Win9x */
239 "ret = %d\n", ret);
240
241 /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */
242 ret = RestoreDC(hdc, 0);
243 ok(!ret ||
244 broken(ret), /* Win9x */
245 "ret = %d\n", ret);
246
247 /* Trying to clear an empty save stack fails. */
248 ret = RestoreDC(hdc, 0);
249 ok(!ret, "ret = %d\n", ret);
250
251 ret = RestoreDC(hdc, 1);
252 ok(ret ||
253 broken(!ret), /* Win9x */
254 "ret = %d\n", ret);
255
256 DeleteDC(hdc);
257 }
258
259 static void test_GdiConvertToDevmodeW(void)
260 {
261 DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *);
262 DEVMODEA dmA;
263 DEVMODEW *dmW;
264 BOOL ret;
265
266 pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW");
267 if (!pGdiConvertToDevmodeW)
268 {
269 win_skip("GdiConvertToDevmodeW is not available on this platform\n");
270 return;
271 }
272
273 ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA);
274 ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError());
275 ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize);
276 ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize);
277
278 dmW = pGdiConvertToDevmodeW(&dmA);
279 ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize);
280 ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize);
281 HeapFree(GetProcessHeap(), 0, dmW);
282
283 dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields);
284 dmW = pGdiConvertToDevmodeW(&dmA);
285 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields),
286 "wrong size %u\n", dmW->dmSize);
287 HeapFree(GetProcessHeap(), 0, dmW);
288
289 dmA.dmICMMethod = DMICMMETHOD_NONE;
290 dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod);
291 dmW = pGdiConvertToDevmodeW(&dmA);
292 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod),
293 "wrong size %u\n", dmW->dmSize);
294 ok(dmW->dmICMMethod == DMICMMETHOD_NONE,
295 "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod);
296 HeapFree(GetProcessHeap(), 0, dmW);
297
298 dmA.dmSize = 1024;
299 dmW = pGdiConvertToDevmodeW(&dmA);
300 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight),
301 "wrong size %u\n", dmW->dmSize);
302 HeapFree(GetProcessHeap(), 0, dmW);
303
304 SetLastError(0xdeadbeef);
305 dmA.dmSize = 0;
306 dmW = pGdiConvertToDevmodeW(&dmA);
307 ok(!dmW, "GdiConvertToDevmodeW should fail\n");
308 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError());
309
310 /* this is the minimal dmSize that XP accepts */
311 dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields);
312 dmW = pGdiConvertToDevmodeW(&dmA);
313 ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields),
314 "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize);
315 HeapFree(GetProcessHeap(), 0, dmW);
316 }
317
318 static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr, int scale )
319 {
320 static const int caps[] =
321 {
322 DRIVERVERSION,
323 TECHNOLOGY,
324 HORZSIZE,
325 VERTSIZE,
326 HORZRES,
327 VERTRES,
328 BITSPIXEL,
329 PLANES,
330 NUMBRUSHES,
331 NUMPENS,
332 NUMMARKERS,
333 NUMFONTS,
334 NUMCOLORS,
335 PDEVICESIZE,
336 CURVECAPS,
337 LINECAPS,
338 POLYGONALCAPS,
339 /* TEXTCAPS broken on printer DC on winxp */
340 CLIPCAPS,
341 RASTERCAPS,
342 ASPECTX,
343 ASPECTY,
344 ASPECTXY,
345 LOGPIXELSX,
346 LOGPIXELSY,
347 SIZEPALETTE,
348 NUMRESERVED,
349 COLORRES,
350 PHYSICALWIDTH,
351 PHYSICALHEIGHT,
352 PHYSICALOFFSETX,
353 PHYSICALOFFSETY,
354 SCALINGFACTORX,
355 SCALINGFACTORY,
356 VREFRESH,
357 DESKTOPVERTRES,
358 DESKTOPHORZRES,
359 BLTALIGNMENT,
360 SHADEBLENDCAPS
361 };
362 unsigned int i;
363 WORD ramp[3][256];
364 BOOL ret;
365 RECT rect;
366 UINT type;
367
368 if (GetObjectType( hdc ) == OBJ_METADC)
369 {
370 for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
371 ok( GetDeviceCaps( hdc, caps[i] ) == (caps[i] == TECHNOLOGY ? DT_METAFILE : 0),
372 "wrong caps on %s for %u: %u\n", descr, caps[i],
373 GetDeviceCaps( hdc, caps[i] ) );
374
375 SetLastError( 0xdeadbeef );
376 ret = GetDeviceGammaRamp( hdc, &ramp );
377 ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
378 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
379 "wrong error %u on %s\n", GetLastError(), descr );
380 type = GetClipBox( hdc, &rect );
381 ok( type == ERROR, "GetClipBox returned %d on %s\n", type, descr );
382
383 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
384 SetMapMode( hdc, MM_TEXT );
385 Rectangle( hdc, 2, 2, 5, 5 );
386 type = GetBoundsRect( hdc, &rect, DCB_RESET );
387 ok( !type, "GetBoundsRect succeeded on %s\n", descr );
388 type = SetBoundsRect( hdc, &rect, DCB_RESET | DCB_ENABLE );
389 ok( !type, "SetBoundsRect succeeded on %s\n", descr );
390 }
391 else
392 {
393 for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
394 {
395 INT precision = 0;
396 INT hdc_caps = GetDeviceCaps( hdc, caps[i] );
397
398 switch (caps[i])
399 {
400 case HORZSIZE:
401 case VERTSIZE:
402 hdc_caps /= scale;
403 precision = 1;
404 break;
405 case LOGPIXELSX:
406 case LOGPIXELSY:
407 hdc_caps *= scale;
408 break;
409 }
410
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 );
414 }
415
416 SetLastError( 0xdeadbeef );
417 ret = GetDeviceGammaRamp( hdc, &ramp );
418 if (GetObjectType( hdc ) != OBJ_DC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASPRINTER)
419 {
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 );
423 }
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 );
429
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 %d,%d,%d,%d type %x for %s\n",
436 rect.left, rect.top, rect.right, rect.bottom, 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 ) );
440
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 %d,%d,%d,%d type %x for %s\n",
447 rect.left, rect.top, rect.right, rect.bottom, type, descr );
448 }
449
450 type = GetClipBox( ref_dc, &rect );
451 if (type != COMPLEXREGION && type != ERROR) /* region can be complex on multi-monitor setups */
452 {
453 RECT ref_rect;
454
455 ok( type == SIMPLEREGION, "GetClipBox returned %d on %s\n", type, descr );
456 if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY)
457 {
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 ) );
462
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 ) );
467
468 SetRect( &ref_rect, GetSystemMetrics( SM_XVIRTUALSCREEN ), GetSystemMetrics( SM_YVIRTUALSCREEN ),
469 GetSystemMetrics( SM_XVIRTUALSCREEN ) + GetSystemMetrics( SM_CXVIRTUALSCREEN ),
470 GetSystemMetrics( SM_YVIRTUALSCREEN ) + GetSystemMetrics( SM_CYVIRTUALSCREEN ) );
471 }
472 else
473 {
474 SetRect( &ref_rect, 0, 0, GetDeviceCaps( ref_dc, DESKTOPHORZRES ),
475 GetDeviceCaps( ref_dc, DESKTOPVERTRES ) );
476 }
477
478 todo_wine_if (GetDeviceCaps( ref_dc, TECHNOLOGY ) == DT_RASDISPLAY && GetObjectType( hdc ) != OBJ_ENHMETADC &&
479 (GetSystemMetrics( SM_XVIRTUALSCREEN ) || GetSystemMetrics( SM_YVIRTUALSCREEN )))
480 ok( EqualRect( &rect, &ref_rect ), "GetClipBox returned %d,%d,%d,%d on %s\n",
481 rect.left, rect.top, rect.right, rect.bottom, descr );
482 }
483
484 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_ACCUMULATE );
485 SetMapMode( ref_dc, MM_TEXT );
486 Rectangle( ref_dc, 3, 3, 5, 5 );
487 type = GetBoundsRect( ref_dc, &rect, DCB_RESET );
488 /* it may or may not work on non-memory DCs */
489 ok( (rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0 && type == DCB_RESET) ||
490 (rect.left == 3 && rect.top == 3 && rect.right == 5 && rect.bottom == 5 && type == DCB_SET),
491 "GetBoundsRect returned %d,%d,%d,%d type %x on %s\n",
492 rect.left, rect.top, rect.right, rect.bottom, type, descr );
493
494 if (GetObjectType( hdc ) == OBJ_MEMDC)
495 {
496 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
497 BITMAPINFO *info = (BITMAPINFO *)buffer;
498 HBITMAP dib, old;
499
500 memset( buffer, 0, sizeof(buffer) );
501 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
502 info->bmiHeader.biWidth = 16;
503 info->bmiHeader.biHeight = 16;
504 info->bmiHeader.biPlanes = 1;
505 info->bmiHeader.biBitCount = 8;
506 info->bmiHeader.biCompression = BI_RGB;
507 dib = CreateDIBSection( ref_dc, info, DIB_RGB_COLORS, NULL, NULL, 0 );
508 old = SelectObject( hdc, dib );
509
510 for (i = 0; i < sizeof(caps)/sizeof(caps[0]); i++)
511 ok( GetDeviceCaps( hdc, caps[i] ) == GetDeviceCaps( ref_dc, caps[i] ),
512 "mismatched caps on %s and DIB for %u: %u/%u\n", descr, caps[i],
513 GetDeviceCaps( hdc, caps[i] ), GetDeviceCaps( ref_dc, caps[i] ) );
514
515 SetLastError( 0xdeadbeef );
516 ret = GetDeviceGammaRamp( hdc, &ramp );
517 ok( !ret, "GetDeviceGammaRamp succeeded on %s\n", descr );
518 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef), /* nt4 */
519 "wrong error %u on %s\n", GetLastError(), descr );
520
521 type = GetClipBox( hdc, &rect );
522 ok( type == SIMPLEREGION, "GetClipBox returned %d on memdc for %s\n", type, descr );
523 ok( rect.left == 0 && rect.top == 0 && rect.right == 16 && rect.bottom == 16,
524 "GetClipBox returned %d,%d,%d,%d on memdc for %s\n",
525 rect.left, rect.top, rect.right, rect.bottom, descr );
526
527 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
528 SetMapMode( hdc, MM_TEXT );
529 Rectangle( hdc, 5, 5, 12, 14 );
530 type = GetBoundsRect( hdc, &rect, DCB_RESET );
531 ok( rect.left == 5 && rect.top == 5 && rect.right == 12 && rect.bottom == 14 && type == DCB_SET,
532 "GetBoundsRect returned %d,%d,%d,%d type %x on memdc for %s\n",
533 rect.left, rect.top, rect.right, rect.bottom, type, descr );
534
535 SelectObject( hdc, old );
536 DeleteObject( dib );
537 }
538
539 /* restore hdc state */
540 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_DISABLE );
541 SetBoundsRect( ref_dc, NULL, DCB_RESET | DCB_DISABLE );
542 }
543
544 static void test_CreateCompatibleDC(void)
545 {
546 BOOL bRet;
547 HDC hdc, hNewDC, hdcMetafile, screen_dc;
548 HBITMAP bitmap;
549 INT caps;
550 DEVMODEA dm;
551
552 bitmap = CreateBitmap( 10, 10, 1, 1, NULL );
553
554 bRet = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dm);
555 ok(bRet, "EnumDisplaySettingsEx failed\n");
556 dm.u1.s1.dmScale = 200;
557 dm.dmFields |= DM_SCALE;
558 hdc = CreateDCA( "DISPLAY", NULL, NULL, &dm );
559
560 screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
561 test_device_caps( hdc, screen_dc, "display dc", 1 );
562 ResetDCA( hdc, &dm );
563 test_device_caps( hdc, screen_dc, "display dc", 1 );
564 DeleteDC( hdc );
565
566 /* Create a DC compatible with the screen */
567 hdc = CreateCompatibleDC(NULL);
568 ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc);
569 ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" );
570 caps = GetDeviceCaps( hdc, TECHNOLOGY );
571 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
572
573 test_device_caps( hdc, screen_dc, "display dc", 1 );
574
575 /* Delete this DC, this should succeed */
576 bRet = DeleteDC(hdc);
577 ok(bRet == TRUE, "DeleteDC returned %u\n", bRet);
578
579 /* Try to create a DC compatible to the deleted DC. This has to fail */
580 hNewDC = CreateCompatibleDC(hdc);
581 ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC);
582
583 hdc = GetDC( 0 );
584 hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL);
585 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
586 hNewDC = CreateCompatibleDC( hdcMetafile );
587 ok(hNewDC != NULL, "CreateCompatibleDC failed\n");
588 ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" );
589 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
590 ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps );
591 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
592 ResetDCA( hdcMetafile, &dm );
593 test_device_caps( hdcMetafile, hdc, "enhmetafile dc", 1 );
594 DeleteDC( hNewDC );
595 DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile ));
596 ReleaseDC( 0, hdc );
597
598 hdcMetafile = CreateMetaFileA(NULL);
599 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
600 hNewDC = CreateCompatibleDC( hdcMetafile );
601 ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n");
602 caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY );
603 ok( caps == DT_METAFILE, "wrong caps %u\n", caps );
604 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
605 ResetDCA( hdcMetafile, &dm );
606 test_device_caps( hdcMetafile, screen_dc, "metafile dc", 1 );
607 DeleteMetaFile( CloseMetaFile( hdcMetafile ));
608
609 DeleteObject( bitmap );
610 DeleteDC( screen_dc );
611 }
612
613 static void test_DC_bitmap(void)
614 {
615 PIXELFORMATDESCRIPTOR descr;
616 HDC hdc, hdcmem;
617 DWORD bits[64];
618 HBITMAP hbmp, oldhbmp;
619 COLORREF col;
620 int i, bitspixel;
621 int ret, ret2;
622
623 /* fill bitmap data with b&w pattern */
624 for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff;
625
626 hdc = GetDC(0);
627 ok( hdc != NULL, "CreateDC rets %p\n", hdc);
628 bitspixel = GetDeviceCaps( hdc, BITSPIXEL);
629 /* create a memory dc */
630 hdcmem = CreateCompatibleDC( hdc);
631 ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem);
632
633 /* test DescribePixelFormat with descr == NULL */
634 ret2 = DescribePixelFormat(hdcmem, 0, sizeof(descr), NULL);
635 ok(ret2 > 0, "expected ret2 > 0, got %d\n", ret2);
636 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), NULL);
637 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
638 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), NULL);
639 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
640
641 /* test DescribePixelFormat with descr != NULL */
642 memset(&descr, 0, sizeof(descr));
643 ret = DescribePixelFormat(hdcmem, 0, sizeof(descr), &descr);
644 ok(ret == 0, "expected ret == 0, got %d\n", ret);
645 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
646
647 memset(&descr, 0, sizeof(descr));
648 ret = DescribePixelFormat(hdcmem, 1, sizeof(descr), &descr);
649 ok(ret == ret2, "expected ret == %d, got %d\n", ret2, ret);
650 ok(descr.nSize == sizeof(descr), "expected desc.nSize == sizeof(descr), got %d\n", descr.nSize);
651
652 memset(&descr, 0, sizeof(descr));
653 ret = DescribePixelFormat(hdcmem, 0x10000, sizeof(descr), &descr);
654 ok(ret == 0, "expected ret == 0, got %d\n", ret);
655 ok(descr.nSize == 0, "expected descr.nSize == 0, got %d\n", descr.nSize);
656
657 /* test monochrome bitmap: should always work */
658 hbmp = CreateBitmap(32, 32, 1, 1, bits);
659 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
660 oldhbmp = SelectObject( hdcmem, hbmp);
661 ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */
662 col = GetPixel( hdcmem, 0, 0);
663 ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col);
664 col = GetPixel( hdcmem, 1, 1);
665 ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col);
666 col = GetPixel( hdcmem, 100, 1);
667 ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col);
668 SelectObject( hdcmem, oldhbmp);
669 DeleteObject( hbmp);
670
671 /* test with 2 bits color depth, not likely to succeed */
672 hbmp = CreateBitmap(16, 16, 1, 2, bits);
673 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
674 oldhbmp = SelectObject( hdcmem, hbmp);
675 if( bitspixel != 2)
676 ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return NULL\n");
677 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
678 DeleteObject( hbmp);
679
680 /* test with 16 bits color depth, might succeed */
681 hbmp = CreateBitmap(6, 6, 1, 16, bits);
682 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
683 oldhbmp = SelectObject( hdcmem, hbmp);
684 if( bitspixel == 16) {
685 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
686 col = GetPixel( hdcmem, 0, 0);
687 ok( col == 0xffffff,
688 "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col);
689 col = GetPixel( hdcmem, 1, 1);
690 ok( col == 0x000000,
691 "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col);
692 }
693 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
694 DeleteObject( hbmp);
695
696 /* test with 32 bits color depth, probably succeed */
697 hbmp = CreateBitmap(4, 4, 1, 32, bits);
698 ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp);
699 oldhbmp = SelectObject( hdcmem, hbmp);
700 if( bitspixel == 32) {
701 ok( oldhbmp != NULL, "SelectObject returned NULL\n" );
702 col = GetPixel( hdcmem, 0, 0);
703 ok( col == 0xffffff,
704 "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col);
705 col = GetPixel( hdcmem, 1, 1);
706 ok( col == 0x000000,
707 "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col);
708 }
709 if( oldhbmp) SelectObject( hdcmem, oldhbmp);
710 DeleteObject( hbmp);
711 ReleaseDC( 0, hdc );
712 }
713
714 static void test_DeleteDC(void)
715 {
716 HWND hwnd;
717 HDC hdc, hdc_test;
718 WNDCLASSEXA cls;
719 int ret;
720
721 /* window DC */
722 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
723 0, 0, 0, NULL);
724 ok(hwnd != 0, "CreateWindowExA failed\n");
725
726 hdc = GetDC(hwnd);
727 ok(hdc != 0, "GetDC failed\n");
728 ret = GetObjectType(hdc);
729 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
730 ret = DeleteDC(hdc);
731 ok(ret, "DeleteDC failed\n");
732 ret = GetObjectType(hdc);
733 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
734
735 hdc = GetWindowDC(hwnd);
736 ok(hdc != 0, "GetDC failed\n");
737 ret = GetObjectType(hdc);
738 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
739 ret = DeleteDC(hdc);
740 ok(ret, "DeleteDC failed\n");
741 ret = GetObjectType(hdc);
742 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
743
744 DestroyWindow(hwnd);
745
746 /* desktop window DC */
747 hwnd = GetDesktopWindow();
748 ok(hwnd != 0, "GetDesktopWindow failed\n");
749
750 hdc = GetDC(hwnd);
751 ok(hdc != 0, "GetDC failed\n");
752 ret = GetObjectType(hdc);
753 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
754 ret = DeleteDC(hdc);
755 ok(ret, "DeleteDC failed\n");
756 ret = GetObjectType(hdc);
757 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
758
759 hdc = GetWindowDC(hwnd);
760 ok(hdc != 0, "GetDC failed\n");
761 ret = GetObjectType(hdc);
762 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
763 ret = DeleteDC(hdc);
764 ok(ret, "DeleteDC failed\n");
765 ret = GetObjectType(hdc);
766 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
767
768 /* CS_CLASSDC */
769 memset(&cls, 0, sizeof(cls));
770 cls.cbSize = sizeof(cls);
771 cls.style = CS_CLASSDC;
772 cls.hInstance = GetModuleHandleA(NULL);
773 cls.lpszClassName = "Wine class DC";
774 cls.lpfnWndProc = DefWindowProcA;
775 ret = RegisterClassExA(&cls);
776 ok(ret, "RegisterClassExA failed\n");
777
778 hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
779 0, 0, 0, NULL);
780 ok(hwnd != 0, "CreateWindowExA failed\n");
781
782 hdc = GetDC(hwnd);
783 ok(hdc != 0, "GetDC failed\n");
784 ret = GetObjectType(hdc);
785 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
786 ret = DeleteDC(hdc);
787 ok(ret, "DeleteDC failed\n");
788 ret = GetObjectType(hdc);
789 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
790 ret = ReleaseDC(hwnd, hdc);
791 ok(ret, "ReleaseDC failed\n");
792 ret = GetObjectType(hdc);
793 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
794
795 hdc_test = hdc;
796
797 hdc = GetWindowDC(hwnd);
798 ok(hdc != 0, "GetDC failed\n");
799 ret = GetObjectType(hdc);
800 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
801 ret = DeleteDC(hdc);
802 ok(ret, "DeleteDC failed\n");
803 ret = GetObjectType(hdc);
804 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
805
806 DestroyWindow(hwnd);
807
808 ret = GetObjectType(hdc_test);
809 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
810
811 ret = UnregisterClassA("Wine class DC", GetModuleHandleA(NULL));
812 ok(ret, "UnregisterClassA failed\n");
813
814 ret = GetObjectType(hdc_test);
815 ok(!ret, "GetObjectType should fail for a deleted DC\n");
816
817 /* CS_OWNDC */
818 memset(&cls, 0, sizeof(cls));
819 cls.cbSize = sizeof(cls);
820 cls.style = CS_OWNDC;
821 cls.hInstance = GetModuleHandleA(NULL);
822 cls.lpszClassName = "Wine own DC";
823 cls.lpfnWndProc = DefWindowProcA;
824 ret = RegisterClassExA(&cls);
825 ok(ret, "RegisterClassExA failed\n");
826
827 hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100,
828 0, 0, 0, NULL);
829 ok(hwnd != 0, "CreateWindowExA failed\n");
830
831 hdc = GetDC(hwnd);
832 ok(hdc != 0, "GetDC failed\n");
833 ret = GetObjectType(hdc);
834 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
835 ret = DeleteDC(hdc);
836 ok(ret, "DeleteDC failed\n");
837 ret = GetObjectType(hdc);
838 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
839 ret = ReleaseDC(hwnd, hdc);
840 ok(ret, "ReleaseDC failed\n");
841 ret = GetObjectType(hdc);
842 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
843
844 hdc = GetWindowDC(hwnd);
845 ok(hdc != 0, "GetDC failed\n");
846 ret = GetObjectType(hdc);
847 ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret);
848 ret = DeleteDC(hdc);
849 ok(ret, "DeleteDC failed\n");
850 ret = GetObjectType(hdc);
851 ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n");
852
853 DestroyWindow(hwnd);
854
855 ret = UnregisterClassA("Wine own DC", GetModuleHandleA(NULL));
856 ok(ret, "UnregisterClassA failed\n");
857 }
858
859 static void test_boundsrect(void)
860 {
861 char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
862 BITMAPINFO *info = (BITMAPINFO *)buffer;
863 HDC hdc;
864 HBITMAP bitmap, dib, old;
865 RECT rect, expect, set_rect;
866 UINT ret;
867 int i, level;
868
869 hdc = CreateCompatibleDC(0);
870 ok(hdc != NULL, "CreateCompatibleDC failed\n");
871 bitmap = CreateCompatibleBitmap( hdc, 200, 200 );
872 old = SelectObject( hdc, bitmap );
873
874 ret = GetBoundsRect(hdc, NULL, 0);
875 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
876
877 ret = GetBoundsRect(hdc, NULL, ~0U);
878 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
879
880 /* Test parameter handling order. */
881 SetRect(&set_rect, 10, 20, 40, 50);
882 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
883 ok(ret & DCB_RESET,
884 "Expected return flag DCB_RESET to be set, got %u\n", ret);
885
886 ret = GetBoundsRect(hdc, NULL, DCB_RESET);
887 ok(ret == 0,
888 "Expected GetBoundsRect to return 0, got %u\n", ret);
889
890 ret = GetBoundsRect(hdc, &rect, 0);
891 ok(ret == DCB_RESET,
892 "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret);
893 SetRectEmpty(&expect);
894 ok(EqualRect(&rect, &expect) ||
895 broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */
896 "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n",
897 rect.left, rect.top, rect.right, rect.bottom);
898
899 ret = GetBoundsRect(NULL, NULL, 0);
900 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
901
902 ret = GetBoundsRect(NULL, NULL, ~0U);
903 ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret);
904
905 ret = SetBoundsRect(NULL, NULL, 0);
906 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
907
908 ret = SetBoundsRect(NULL, NULL, ~0U);
909 ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret);
910
911 SetRect(&set_rect, 10, 20, 40, 50);
912 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
913 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
914
915 ret = GetBoundsRect(hdc, &rect, 0);
916 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
917 SetRect(&expect, 10, 20, 40, 50);
918 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
919 rect.left, rect.top, rect.right, rect.bottom);
920
921 SetMapMode( hdc, MM_ANISOTROPIC );
922 SetViewportExtEx( hdc, 2, 2, NULL );
923 ret = GetBoundsRect(hdc, &rect, 0);
924 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
925 SetRect(&expect, 5, 10, 20, 25);
926 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
927 rect.left, rect.top, rect.right, rect.bottom);
928
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 (%d,%d)-(%d,%d)\n",
934 rect.left, rect.top, rect.right, rect.bottom);
935
936 SetRect(&set_rect, 10, 20, 40, 50);
937 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
938 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
939
940 ret = GetBoundsRect(hdc, &rect, 0);
941 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
942 SetRect(&expect, 10, 20, 40, 50);
943 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
944 rect.left, rect.top, rect.right, rect.bottom);
945
946 SetMapMode( hdc, MM_TEXT );
947 SetViewportOrgEx( hdc, 0, 0, NULL );
948 ret = GetBoundsRect(hdc, &rect, 0);
949 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
950 SetRect(&expect, 40, 70, 100, 130);
951 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
952 rect.left, rect.top, rect.right, rect.bottom);
953
954 if (pSetLayout)
955 {
956 pSetLayout( hdc, LAYOUT_RTL );
957 ret = GetBoundsRect(hdc, &rect, 0);
958 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
959 SetRect(&expect, 159, 70, 99, 130);
960 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
961 rect.left, rect.top, rect.right, rect.bottom);
962 SetRect(&set_rect, 50, 25, 30, 35);
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_SET, "GetBoundsRect returned %x\n", ret);
967 SetRect(&expect, 50, 25, 30, 35);
968 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
969 rect.left, rect.top, rect.right, rect.bottom);
970
971 pSetLayout( hdc, LAYOUT_LTR );
972 ret = GetBoundsRect(hdc, &rect, 0);
973 ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret);
974 SetRect(&expect, 149, 25, 169, 35);
975 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
976 rect.left, rect.top, rect.right, rect.bottom);
977 }
978
979 /* empty rect resets, except on nt4 */
980 SetRect(&expect, 20, 20, 10, 10);
981 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
982 ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
983 ret = GetBoundsRect(hdc, &rect, 0);
984 ok(ret == DCB_RESET || broken(ret == DCB_SET) /* nt4 */,
985 "GetBoundsRect returned %x\n", ret);
986 if (ret == DCB_RESET)
987 {
988 SetRectEmpty(&expect);
989 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
990 rect.left, rect.top, rect.right, rect.bottom);
991
992 SetRect(&expect, 20, 20, 20, 20);
993 ret = SetBoundsRect(hdc, &set_rect, DCB_SET);
994 ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret);
995 ret = GetBoundsRect(hdc, &rect, 0);
996 ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret);
997 SetRectEmpty(&expect);
998 ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n",
999 rect.left, rect.top, rect.right, rect.bottom);
1000 }
1001
1002 SetBoundsRect( hdc, NULL, DCB_RESET | DCB_ENABLE );
1003 MoveToEx( hdc, 10, 10, NULL );
1004 LineTo( hdc, 20, 20 );
1005 ret = GetBoundsRect( hdc, &rect, 0 );
1006 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1007 SetRect( &expect, 10, 10, 21, 21 );
1008 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1009 SetRect( &rect, 8, 8, 23, 23 );
1010 expect = rect;
1011 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1012 ret = GetBoundsRect( hdc, &rect, 0 );
1013 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1014 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1015
1016 level = SaveDC( hdc );
1017 LineTo( hdc, 30, 25 );
1018 ret = GetBoundsRect( hdc, &rect, 0 );
1019 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1020 SetRect( &expect, 8, 8, 31, 26 );
1021 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1022 SetBoundsRect( hdc, NULL, DCB_DISABLE );
1023 LineTo( hdc, 40, 40 );
1024 ret = GetBoundsRect( hdc, &rect, 0 );
1025 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1026 SetRect( &expect, 8, 8, 31, 26 );
1027 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1028 SetRect( &rect, 6, 6, 30, 30 );
1029 SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
1030 ret = GetBoundsRect( hdc, &rect, 0 );
1031 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1032 SetRect( &expect, 6, 6, 31, 30 );
1033 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1034
1035 RestoreDC( hdc, level );
1036 ret = GetBoundsRect( hdc, &rect, 0 );
1037 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1038 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1039 LineTo( hdc, 40, 40 );
1040 ret = GetBoundsRect( hdc, &rect, 0 );
1041 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1042 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1043
1044 SelectObject( hdc, old );
1045 ret = GetBoundsRect( hdc, &rect, 0 );
1046 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1047 SetRect( &expect, 6, 6, 1, 1 );
1048 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1049 SetBoundsRect( hdc, NULL, DCB_ENABLE );
1050 LineTo( hdc, 50, 40 );
1051
1052 SelectObject( hdc, bitmap );
1053 ret = GetBoundsRect( hdc, &rect, 0 );
1054 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1055 SetRect( &expect, 6, 6, 51, 41 );
1056 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1057 SelectObject( hdc, GetStockObject( NULL_PEN ));
1058 LineTo( hdc, 50, 50 );
1059 ret = GetBoundsRect( hdc, &rect, 0 );
1060 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1061 SetRect( &expect, 6, 6, 51, 51 );
1062 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1063
1064 memset( buffer, 0, sizeof(buffer) );
1065 info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1066 info->bmiHeader.biWidth = 256;
1067 info->bmiHeader.biHeight = 256;
1068 info->bmiHeader.biPlanes = 1;
1069 info->bmiHeader.biBitCount = 8;
1070 info->bmiHeader.biCompression = BI_RGB;
1071 dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, NULL, NULL, 0 );
1072 ok( dib != 0, "failed to create DIB\n" );
1073 SelectObject( hdc, dib );
1074 ret = GetBoundsRect( hdc, &rect, 0 );
1075 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1076 SetRect( &expect, 6, 6, 51, 51 );
1077 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1078 LineTo( hdc, 55, 30 );
1079 ret = GetBoundsRect( hdc, &rect, 0 );
1080 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1081 SetRect( &expect, 6, 6, 56, 51 );
1082 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1083 LineTo( hdc, 300, 30 );
1084 ret = GetBoundsRect( hdc, &rect, 0 );
1085 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1086 SetRect( &expect, 6, 6, 256, 51 );
1087 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1088 LineTo( hdc, -300, -300 );
1089 ret = GetBoundsRect( hdc, &rect, 0 );
1090 ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
1091 SetRect( &expect, 0, 0, 256, 51 );
1092 ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
1093
1094 /* test the wide pen heuristics */
1095 SetBoundsRect( hdc, NULL, DCB_ENABLE | DCB_RESET );
1096 for (i = 0; i < 1000; i++)
1097 {
1098 static const UINT endcaps[3] = { PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT };
1099 static const UINT joins[3] = { PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER };
1100 LOGBRUSH brush = { BS_SOLID, RGB(0,0,0), 0 };
1101 UINT join = joins[i % 3];
1102 UINT endcap = endcaps[(i / 3) % 3];
1103 INT inflate, width = 1 + i / 9;
1104 HPEN pen = ExtCreatePen( PS_GEOMETRIC | join | endcap | PS_SOLID, width, &brush, 0, NULL );
1105 HPEN old = SelectObject( hdc, pen );
1106 MoveToEx( hdc, 100, 100, NULL );
1107 LineTo( hdc, 160, 100 );
1108 LineTo( hdc, 100, 160 );
1109 LineTo( hdc, 160, 160 );
1110 GetBoundsRect( hdc, &rect, DCB_RESET );
1111 SetRect( &expect, 100, 100, 161, 161 );
1112
1113 inflate = width + 2;
1114 if (join == PS_JOIN_MITER)
1115 {
1116 inflate *= 5;
1117 if (endcap == PS_ENDCAP_SQUARE)
1118 InflateRect( &expect, (inflate * 3 + 1) / 2, (inflate * 3 + 1) / 2 );
1119 else
1120 InflateRect( &expect, inflate, inflate );
1121 }
1122 else
1123 {
1124 if (endcap == PS_ENDCAP_SQUARE)
1125 InflateRect( &expect, inflate - inflate / 4, inflate - inflate / 4 );
1126 else
1127 InflateRect( &expect, (inflate + 1) / 2, (inflate + 1) / 2 );
1128 }
1129 expect.left = max( expect.left, 0 );
1130 expect.top = max( expect.top, 0 );
1131 expect.right = min( expect.right, 256 );
1132 expect.bottom = min( expect.bottom, 256 );
1133 ok( EqualRect(&rect, &expect),
1134 "Got %d,%d,%d,%d expected %d,%d,%d,%d %u/%x/%x\n",
1135 rect.left, rect.top, rect.right, rect.bottom,
1136 expect.left, expect.top, expect.right, expect.bottom, width, endcap, join );
1137 DeleteObject( SelectObject( hdc, old ));
1138 }
1139
1140 DeleteDC( hdc );
1141 DeleteObject( bitmap );
1142 DeleteObject( dib );
1143 }
1144
1145 static void test_desktop_colorres(void)
1146 {
1147 HDC hdc = GetDC(NULL);
1148 int bitspixel, colorres;
1149
1150 bitspixel = GetDeviceCaps(hdc, BITSPIXEL);
1151 ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n");
1152
1153 colorres = GetDeviceCaps(hdc, COLORRES);
1154 ok(colorres != 0 ||
1155 broken(colorres == 0), /* Win9x */
1156 "Expected to get valid COLORRES capability value\n");
1157
1158 if (colorres)
1159 {
1160 switch (bitspixel)
1161 {
1162 case 8:
1163 ok(colorres == 18,
1164 "Expected COLORRES to be 18, got %d\n", colorres);
1165 break;
1166 case 16:
1167 ok(colorres == 16,
1168 "Expected COLORRES to be 16, got %d\n", colorres);
1169 break;
1170 case 24:
1171 case 32:
1172 ok(colorres == 24,
1173 "Expected COLORRES to be 24, got %d\n", bitspixel);
1174 break;
1175 default:
1176 ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres);
1177 break;
1178 }
1179 }
1180
1181 ReleaseDC(NULL, hdc);
1182 }
1183
1184 static void test_gamma(void)
1185 {
1186 BOOL ret;
1187 HDC hdc = GetDC(NULL);
1188 WORD oldramp[3][256], ramp[3][256];
1189 INT i;
1190
1191 ret = GetDeviceGammaRamp(hdc, &oldramp);
1192 if (!ret)
1193 {
1194 win_skip("GetDeviceGammaRamp failed, skipping tests\n");
1195 goto done;
1196 }
1197
1198 /* try to set back old ramp */
1199 ret = SetDeviceGammaRamp(hdc, &oldramp);
1200 if (!ret)
1201 {
1202 win_skip("SetDeviceGammaRamp failed, skipping tests\n");
1203 goto done;
1204 }
1205
1206 memcpy(ramp, oldramp, sizeof(ramp));
1207
1208 /* set one color ramp to zeros */
1209 memset(ramp[0], 0, sizeof(ramp[0]));
1210 ret = SetDeviceGammaRamp(hdc, &ramp);
1211 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1212
1213 /* set one color ramp to a flat straight rising line */
1214 for (i = 0; i < 256; i++) ramp[0][i] = i;
1215 ret = SetDeviceGammaRamp(hdc, &ramp);
1216 todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n");
1217
1218 /* set one color ramp to a steep straight rising line */
1219 for (i = 0; i < 256; i++) ramp[0][i] = i * 256;
1220 ret = SetDeviceGammaRamp(hdc, &ramp);
1221 ok(ret, "SetDeviceGammaRamp failed\n");
1222
1223 /* try a bright gamma ramp */
1224 ramp[0][0] = 0;
1225 ramp[0][1] = 0x7FFF;
1226 for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF;
1227 ret = SetDeviceGammaRamp(hdc, &ramp);
1228 ok(!ret, "SetDeviceGammaRamp succeeded\n");
1229
1230 /* try ramps which are not uniform */
1231 ramp[0][0] = 0;
1232 for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512;
1233 ret = SetDeviceGammaRamp(hdc, &ramp);
1234 ok(ret, "SetDeviceGammaRamp failed\n");
1235 ramp[0][0] = 0;
1236 for (i = 2; i < 256; i+=2)
1237 {
1238 ramp[0][i - 1] = ramp[0][i - 2];
1239 ramp[0][i] = ramp[0][i - 2] + 512;
1240 }
1241 ret = SetDeviceGammaRamp(hdc, &ramp);
1242 ok(ret, "SetDeviceGammaRamp failed\n");
1243
1244 /* cleanup: set old ramp again */
1245 ret = SetDeviceGammaRamp(hdc, &oldramp);
1246 ok(ret, "SetDeviceGammaRamp failed\n");
1247
1248 done:
1249 ReleaseDC(NULL, hdc);
1250 }
1251
1252 static BOOL is_postscript_printer(HDC hdc)
1253 {
1254 char tech[256];
1255
1256 if (ExtEscape(hdc, GETTECHNOLOGY, 0, NULL, sizeof(tech), tech) > 0)
1257 return strcmp(tech, "PostScript") == 0;
1258
1259 return FALSE;
1260 }
1261
1262 static HDC create_printer_dc(int scale, BOOL reset)
1263 {
1264 char buffer[260];
1265 DWORD len;
1266 PRINTER_INFO_2A *pbuf = NULL;
1267 DRIVER_INFO_3A *dbuf = NULL;
1268 HANDLE hprn = 0;
1269 HDC hdc = 0;
1270 HMODULE winspool = LoadLibraryA( "winspool.drv" );
1271 BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA);
1272 BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD);
1273 BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
1274 BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD);
1275 BOOL (WINAPI *pClosePrinter)(HANDLE);
1276
1277 pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" );
1278 pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" );
1279 pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" );
1280 pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" );
1281 pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" );
1282
1283 if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter)
1284 goto done;
1285
1286 len = sizeof(buffer);
1287 if (!pGetDefaultPrinterA( buffer, &len )) goto done;
1288 if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done;
1289
1290 pGetPrinterA( hprn, 2, NULL, 0, &len );
1291 pbuf = HeapAlloc( GetProcessHeap(), 0, len );
1292 if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done;
1293
1294 pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len );
1295 dbuf = HeapAlloc( GetProcessHeap(), 0, len );
1296 if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done;
1297
1298 pbuf->pDevMode->u1.s1.dmScale = scale;
1299 pbuf->pDevMode->dmFields |= DM_SCALE;
1300
1301 hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode );
1302 trace( "hdc %p for driver '%s' printer '%s' port '%s' is %sPostScript\n", hdc,
1303 dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName,
1304 is_postscript_printer(hdc) ? "" : "NOT " );
1305
1306 if (reset) ResetDCA( hdc, pbuf->pDevMode );
1307 done:
1308 HeapFree( GetProcessHeap(), 0, dbuf );
1309 HeapFree( GetProcessHeap(), 0, pbuf );
1310 if (hprn) pClosePrinter( hprn );
1311 if (winspool) FreeLibrary( winspool );
1312 if (!hdc) skip( "could not create a DC for the default printer\n" );
1313 return hdc;
1314 }
1315
1316 static void test_printer_dc(void)
1317 {
1318 HDC memdc, display_memdc, enhmf_dc;
1319 HBITMAP orig, bmp;
1320 DWORD ret;
1321 HDC hdc, hdc_200;
1322
1323 hdc = create_printer_dc(100, FALSE);
1324 hdc_200 = create_printer_dc(200, FALSE);
1325
1326 if (!hdc || !hdc_200) return;
1327
1328 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1329 DeleteDC( hdc_200 );
1330
1331 hdc_200 = create_printer_dc(200, TRUE);
1332 test_device_caps( hdc, hdc_200, "printer dc", is_postscript_printer(hdc) ? 2 : 1 );
1333 DeleteDC( hdc_200 );
1334
1335 memdc = CreateCompatibleDC( hdc );
1336 display_memdc = CreateCompatibleDC( 0 );
1337
1338 ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" );
1339 ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" );
1340
1341 ret = GetDeviceCaps( hdc, TECHNOLOGY );
1342 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1343
1344 ret = GetDeviceCaps( memdc, TECHNOLOGY );
1345 ok( ret == DT_RASPRINTER, "wrong type %u\n", ret );
1346
1347 ret = GetDeviceCaps( display_memdc, TECHNOLOGY );
1348 ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret );
1349
1350 bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
1351 orig = SelectObject( memdc, bmp );
1352 ok( orig != NULL, "SelectObject failed\n" );
1353 ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1354
1355 test_device_caps( memdc, hdc, "printer dc", 1 );
1356
1357 ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" );
1358 SelectObject( memdc, orig );
1359 DeleteObject( bmp );
1360
1361 bmp = CreateBitmap( 100, 100, 1, 1, NULL );
1362 orig = SelectObject( display_memdc, bmp );
1363 ok( orig != NULL, "SelectObject failed\n" );
1364 ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" );
1365 ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1366 ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1367 ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" );
1368
1369 ret = GetPixel( hdc, 0, 0 );
1370 ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret );
1371
1372 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1373 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1374 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1375 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1376
1377 enhmf_dc = CreateEnhMetaFileA( hdc, NULL, NULL, NULL );
1378 ok(enhmf_dc != 0, "CreateEnhMetaFileA failed\n");
1379 test_device_caps( enhmf_dc, hdc, "enhmetafile printer dc", 1 );
1380 DeleteEnhMetaFile( CloseEnhMetaFile( enhmf_dc ));
1381
1382 DeleteDC( memdc );
1383 DeleteDC( display_memdc );
1384 DeleteDC( hdc );
1385 DeleteObject( bmp );
1386 }
1387
1388 static void print_something(HDC hdc)
1389 {
1390 static const char psadobe[10] = "%!PS-Adobe";
1391 char buf[1024], *p;
1392 char temp_path[MAX_PATH], file_name[MAX_PATH];
1393 DOCINFOA di;
1394 DWORD ret;
1395 HANDLE hfile;
1396
1397 GetTempPathA(sizeof(temp_path), temp_path);
1398 GetTempFileNameA(temp_path, "ps", 0, file_name);
1399
1400 di.cbSize = sizeof(di);
1401 di.lpszDocName = "Let's dance";
1402 di.lpszOutput = file_name;
1403 di.lpszDatatype = NULL;
1404 di.fwType = 0;
1405 ret = StartDocA(hdc, &di);
1406 ok(ret > 0, "StartDoc failed: %d\n", ret);
1407
1408 strcpy(buf + 2, "\n% ===> before DOWNLOADHEADER <===\n");
1409 *(WORD *)buf = strlen(buf + 2);
1410 ret = Escape(hdc, POSTSCRIPT_PASSTHROUGH, 0, buf, NULL);
1411 ok(ret == *(WORD *)buf, "POSTSCRIPT_PASSTHROUGH failed: %d\n", ret);
1412
1413 strcpy(buf, "deadbeef");
1414 ret = ExtEscape(hdc, DOWNLOADHEADER, 0, NULL, sizeof(buf), buf );
1415 ok(ret == 1, "DOWNLOADHEADER failed\n");
1416 ok(strcmp(buf, "deadbeef") != 0, "DOWNLOADHEADER failed\n");
1417
1418 strcpy(buf + 2, "\n% ===> after DOWNLOADHEADER <===\n");
1419 *(WORD *)buf = strlen(buf + 2);
1420 ret = Escape(hdc, POSTSCRIPT_PASSTHROUGH, 0, buf, NULL);
1421 ok(ret == *(WORD *)buf, "POSTSCRIPT_PASSTHROUGH failed: %d\n", ret);
1422
1423 ret = EndDoc(hdc);
1424 ok(ret == 1, "EndDoc failed\n");
1425
1426 hfile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
1427 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1428 memset(buf, 0, sizeof(buf));
1429 ret = ReadFile(hfile, buf, sizeof(buf), &ret, NULL);
1430 ok(ret, "ReadFile failed\n");
1431 CloseHandle(hfile);
1432
1433 /* skip the HP PCL language selector */
1434 buf[sizeof(buf) - 1] = 0;
1435 p = buf;
1436 while (*p)
1437 {
1438 if (!(p[0] == 0x1b && p[1] == '%') && memcmp(p, "@PJL", 4) != 0)
1439 break;
1440
1441 p = strchr(p, '\n');
1442 if (!p) break;
1443
1444 while (*p == '\r' || *p == '\n') p++;
1445 }
1446 ok(p && !memcmp(p, psadobe, sizeof(psadobe)), "wrong signature: %.14s\n", p ? p : buf);
1447
1448 DeleteFileA(file_name);
1449 }
1450
1451 static void test_pscript_printer_dc(void)
1452 {
1453 HDC hdc;
1454 char buf[256];
1455 DWORD query, ret;
1456
1457 hdc = create_printer_dc(100, FALSE);
1458
1459 if (!hdc) return;
1460
1461 if (!is_postscript_printer(hdc))
1462 {
1463 skip("Default printer is not a PostScript device\n");
1464 DeleteDC( hdc );
1465 return;
1466 }
1467
1468 query = GETFACENAME;
1469 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1470 ok(!ret, "GETFACENAME is supported\n");
1471
1472 query = DOWNLOADFACE;
1473 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1474 ok(ret == 1, "DOWNLOADFACE is not supported\n");
1475
1476 query = OPENCHANNEL;
1477 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1478 ok(ret == 1, "OPENCHANNEL is not supported\n");
1479
1480 query = DOWNLOADHEADER;
1481 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1482 ok(ret == 1, "DOWNLOADHEADER is not supported\n");
1483
1484 query = CLOSECHANNEL;
1485 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1486 ok(ret == 1, "CLOSECHANNEL is not supported\n");
1487
1488 query = POSTSCRIPT_PASSTHROUGH;
1489 ret = Escape(hdc, QUERYESCSUPPORT, sizeof(query), (LPCSTR)&query, NULL);
1490 ok(ret == 1, "POSTSCRIPT_PASSTHROUGH is not supported\n");
1491
1492 ret = ExtEscape(hdc, GETFACENAME, 0, NULL, sizeof(buf), buf);
1493 ok(ret == 1, "GETFACENAME failed\n");
1494 trace("face name: %s\n", buf);
1495
1496 print_something(hdc);
1497
1498 DeleteDC(hdc);
1499 }
1500
1501 START_TEST(dc)
1502 {
1503 pSetLayout = (void *)GetProcAddress( GetModuleHandleA("gdi32.dll"), "SetLayout");
1504 test_dc_values();
1505 test_savedc();
1506 test_savedc_2();
1507 test_GdiConvertToDevmodeW();
1508 test_CreateCompatibleDC();
1509 test_DC_bitmap();
1510 test_DeleteDC();
1511 test_boundsrect();
1512 test_desktop_colorres();
1513 test_gamma();
1514 test_printer_dc();
1515 test_pscript_printer_dc();
1516 }