2 * Unit tests for metafile functions
4 * Copyright (c) 2002 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/test.h"
31 static LOGFONTA orig_lf
;
32 static BOOL emr_processed
= FALSE
;
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
38 static INT (WINAPI
* pGetRelAbs
)(HDC
, DWORD
);
39 static INT (WINAPI
* pSetRelAbs
)(HDC
, INT
);
40 static COLORREF (WINAPI
*pSetDCBrushColor
)(HDC
,COLORREF
);
41 static COLORREF (WINAPI
*pSetDCPenColor
)(HDC
,COLORREF
);
43 #define GDI_GET_PROC(func) \
44 p ## func = (void *)GetProcAddress(hGDI, #func); \
46 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
48 static void init_function_pointers(void)
55 hGDI
= GetModuleHandleA("gdi32.dll");
57 GDI_GET_PROC(GetRelAbs
);
58 GDI_GET_PROC(SetRelAbs
);
59 GDI_GET_PROC(SetDCBrushColor
);
60 GDI_GET_PROC(SetDCPenColor
);
63 static DWORD
rgn_rect_count(HRGN hrgn
)
69 if (!(size
= GetRegionData(hrgn
, 0, NULL
))) return 0;
70 if (!(data
= HeapAlloc(GetProcessHeap(), 0, size
))) return 0;
71 GetRegionData(hrgn
, size
, data
);
72 size
= data
->rdh
.nCount
;
73 HeapFree(GetProcessHeap(), 0, data
);
77 static int CALLBACK
eto_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
78 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
83 INT
*orig_dx
= (INT
*)param
;
87 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
88 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
92 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
97 ok(GetTextAlign(hdc
) == 0, "text align %08x\n", GetTextAlign(hdc
));
98 ok(GetBkColor(hdc
) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc
));
99 ok(GetTextColor(hdc
) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc
));
100 ok(GetROP2(hdc
) == R2_COPYPEN
, "rop %d\n", GetROP2(hdc
));
101 ok(GetArcDirection(hdc
) == AD_COUNTERCLOCKWISE
, "arc dir %d\n", GetArcDirection(hdc
));
102 ok(GetPolyFillMode(hdc
) == ALTERNATE
, "poly fill %d\n", GetPolyFillMode(hdc
));
103 ok(GetStretchBltMode(hdc
) == BLACKONWHITE
, "stretchblt mode %d\n", GetStretchBltMode(hdc
));
105 /* GetBkMode, GetRelAbs do not get reset to the default value */
106 ok(GetBkMode(hdc
) == OPAQUE
, "bk mode %d\n", GetBkMode(hdc
));
107 if(pSetRelAbs
&& pGetRelAbs
)
108 ok(pGetRelAbs(hdc
, 0) == RELATIVE
, "relabs %d\n", pGetRelAbs(hdc
, 0));
113 case EMR_EXTTEXTOUTA
:
115 const EMREXTTEXTOUTA
*emr_ExtTextOutA
= (const EMREXTTEXTOUTA
*)emr
;
116 dx
= (const INT
*)((const char *)emr
+ emr_ExtTextOutA
->emrtext
.offDx
);
118 ret
= GetObjectA(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(device_lf
), &device_lf
);
119 ok( ret
== sizeof(device_lf
), "GetObjectA error %d\n", GetLastError());
121 /* compare up to lfOutPrecision, other values are not interesting,
122 * and in fact sometimes arbitrary adapted by Win9x.
124 ok(!memcmp(&orig_lf
, &device_lf
, FIELD_OFFSET(LOGFONTA
, lfOutPrecision
)), "fonts don't match\n");
125 ok(!lstrcmpA(orig_lf
.lfFaceName
, device_lf
.lfFaceName
), "font names don't match\n");
127 for(i
= 0; i
< emr_ExtTextOutA
->emrtext
.nChars
; i
++)
129 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
130 n_record
, i
, dx
[i
], orig_dx
[i
]);
133 emr_processed
= TRUE
;
137 case EMR_EXTTEXTOUTW
:
139 const EMREXTTEXTOUTW
*emr_ExtTextOutW
= (const EMREXTTEXTOUTW
*)emr
;
140 dx
= (const INT
*)((const char *)emr
+ emr_ExtTextOutW
->emrtext
.offDx
);
142 SetLastError(0xdeadbeef);
143 ret
= GetObjectA(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(device_lf
), &device_lf
);
144 ok( ret
== sizeof(device_lf
) ||
145 broken(ret
== (sizeof(device_lf
) - LF_FACESIZE
+ strlen(device_lf
.lfFaceName
) + 1)), /* NT4 */
146 "GetObjectA error %d\n", GetLastError());
148 /* compare up to lfOutPrecision, other values are not interesting,
149 * and in fact sometimes arbitrary adapted by Win9x.
151 ok(!memcmp(&orig_lf
, &device_lf
, FIELD_OFFSET(LOGFONTA
, lfOutPrecision
)), "fonts don't match\n");
152 ok(!lstrcmpA(orig_lf
.lfFaceName
, device_lf
.lfFaceName
), "font names don't match\n");
154 for(i
= 0; i
< emr_ExtTextOutW
->emrtext
.nChars
; i
++)
156 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
157 n_record
, i
, dx
[i
], orig_dx
[i
]);
160 emr_processed
= TRUE
;
171 static void test_ExtTextOut(void)
174 HDC hdcDisplay
, hdcMetafile
;
175 HENHMETAFILE hMetafile
;
177 static const char text
[] = "Simple text to test ExtTextOut on metafiles";
179 static const RECT rc
= { 0, 0, 100, 100 };
182 assert(sizeof(dx
)/sizeof(dx
[0]) >= lstrlenA(text
));
184 /* Win9x doesn't play EMFs on invisible windows */
185 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
186 0, 0, 200, 200, 0, 0, 0, NULL
);
187 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
189 hdcDisplay
= GetDC(hwnd
);
190 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
192 trace("hdcDisplay %p\n", hdcDisplay
);
194 SetMapMode(hdcDisplay
, MM_TEXT
);
196 memset(&orig_lf
, 0, sizeof(orig_lf
));
198 orig_lf
.lfCharSet
= ANSI_CHARSET
;
199 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
200 orig_lf
.lfWeight
= FW_DONTCARE
;
201 orig_lf
.lfHeight
= 7;
202 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
203 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
204 hFont
= CreateFontIndirectA(&orig_lf
);
205 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
207 hFont
= SelectObject(hdcDisplay
, hFont
);
209 len
= lstrlenA(text
);
210 for (i
= 0; i
< len
; i
++)
212 ret
= GetCharWidthA(hdcDisplay
, text
[i
], text
[i
], &dx
[i
]);
213 ok( ret
, "GetCharWidthA error %d\n", GetLastError());
215 hFont
= SelectObject(hdcDisplay
, hFont
);
217 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
218 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
220 trace("hdcMetafile %p\n", hdcMetafile
);
222 ok(GetDeviceCaps(hdcMetafile
, TECHNOLOGY
) == DT_RASDISPLAY
,
223 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
225 hFont
= SelectObject(hdcMetafile
, hFont
);
227 /* 1. pass NULL lpDx */
228 ret
= ExtTextOutA(hdcMetafile
, 0, 0, 0, &rc
, text
, lstrlenA(text
), NULL
);
229 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
231 /* 2. pass custom lpDx */
232 ret
= ExtTextOutA(hdcMetafile
, 0, 20, 0, &rc
, text
, lstrlenA(text
), dx
);
233 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
235 hFont
= SelectObject(hdcMetafile
, hFont
);
236 ret
= DeleteObject(hFont
);
237 ok( ret
, "DeleteObject error %d\n", GetLastError());
239 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
240 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
242 ok(!GetObjectType(hdcMetafile
), "CloseEnhMetaFile has to destroy metafile hdc\n");
244 ret
= PlayEnhMetaFile(hdcDisplay
, hMetafile
, &rc
);
245 ok( ret
, "PlayEnhMetaFile error %d\n", GetLastError());
247 SetTextAlign(hdcDisplay
, TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
);
248 SetBkColor(hdcDisplay
, RGB(0xff, 0, 0));
249 SetTextColor(hdcDisplay
, RGB(0, 0xff, 0));
250 SetROP2(hdcDisplay
, R2_NOT
);
251 SetArcDirection(hdcDisplay
, AD_CLOCKWISE
);
252 SetPolyFillMode(hdcDisplay
, WINDING
);
253 SetStretchBltMode(hdcDisplay
, HALFTONE
);
255 if(pSetRelAbs
) pSetRelAbs(hdcDisplay
, RELATIVE
);
256 SetBkMode(hdcDisplay
, OPAQUE
);
258 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, &rc
);
259 ok( ret
, "EnumEnhMetaFile error %d\n", GetLastError());
261 ok( GetTextAlign(hdcDisplay
) == (TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
),
262 "text align %08x\n", GetTextAlign(hdcDisplay
));
263 ok( GetBkColor(hdcDisplay
) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay
));
264 ok( GetTextColor(hdcDisplay
) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay
));
265 ok( GetROP2(hdcDisplay
) == R2_NOT
, "rop2 %d\n", GetROP2(hdcDisplay
));
266 ok( GetArcDirection(hdcDisplay
) == AD_CLOCKWISE
, "arc dir %d\n", GetArcDirection(hdcDisplay
));
267 ok( GetPolyFillMode(hdcDisplay
) == WINDING
, "poly fill %d\n", GetPolyFillMode(hdcDisplay
));
268 ok( GetStretchBltMode(hdcDisplay
) == HALFTONE
, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay
));
270 ok(emr_processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
272 ok(!EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
273 "A valid hdc has to require a valid rc\n");
275 ok(EnumEnhMetaFile(NULL
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
276 "A null hdc does not require a valid rc\n");
278 ret
= DeleteEnhMetaFile(hMetafile
);
279 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
280 ret
= ReleaseDC(hwnd
, hdcDisplay
);
281 ok( ret
, "ReleaseDC error %d\n", GetLastError());
285 struct eto_scale_test_record
294 static int CALLBACK
eto_scale_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
295 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
297 struct eto_scale_test_record
*test
= (struct eto_scale_test_record
*)param
;
299 if (emr
->iType
== EMR_EXTTEXTOUTW
)
301 const EMREXTTEXTOUTW
*pExtTextOutW
= (const EMREXTTEXTOUTW
*)emr
;
302 trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
303 test
->graphics_mode
, test
->map_mode
,
304 pExtTextOutW
->exScale
, pExtTextOutW
->eyScale
,
305 test
->ex_scale
, test
->ey_scale
);
306 ok(fabs(test
->ex_scale
- pExtTextOutW
->exScale
) < 0.001,
307 "Got exScale %f, expected %f\n", pExtTextOutW
->exScale
, test
->ex_scale
);
308 ok(fabs(test
->ey_scale
- pExtTextOutW
->eyScale
) < 0.001,
309 "Got eyScale %f, expected %f\n", pExtTextOutW
->eyScale
, test
->ey_scale
);
310 test
->processed
= TRUE
;
316 static void test_ExtTextOutScale(void)
318 const RECT rc
= { 0, 0, 100, 100 };
319 const WCHAR str
[] = {'a',0 };
320 struct eto_scale_test_record test
;
321 HDC hdcDisplay
, hdcMetafile
;
322 HENHMETAFILE hMetafile
;
324 SIZE wndext
, vportext
;
325 int horzSize
, vertSize
, horzRes
, vertRes
;
329 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
330 0, 0, 200, 200, 0, 0, 0, NULL
);
331 ok(hwnd
!= 0, "CreateWindowExA failed\n");
333 hdcDisplay
= GetDC(hwnd
);
334 ok(hdcDisplay
!= 0, "GetDC failed\n");
336 horzSize
= GetDeviceCaps(hdcDisplay
, HORZSIZE
);
337 horzRes
= GetDeviceCaps(hdcDisplay
, HORZRES
);
338 vertSize
= GetDeviceCaps(hdcDisplay
, VERTSIZE
);
339 vertRes
= GetDeviceCaps(hdcDisplay
, VERTRES
);
340 ok(horzSize
&& horzRes
&& vertSize
&& vertRes
, "GetDeviceCaps failed\n");
342 for (i
= 0; i
< 16; i
++)
344 test
.graphics_mode
= i
/ 8 + 1;
345 test
.map_mode
= i
% 8 + 1;
347 ret
= SetGraphicsMode(hdcDisplay
, test
.graphics_mode
);
348 ok(ret
, "SetGraphicsMode failed\n");
349 ret
= SetMapMode(hdcDisplay
, test
.map_mode
);
350 ok(ret
, "SetMapMode failed\n");
352 if ((test
.map_mode
== MM_ISOTROPIC
) || (test
.map_mode
== MM_ANISOTROPIC
))
354 ret
= SetWindowExtEx(hdcDisplay
, 1, 1, NULL
);
355 ok(ret
, "SetWindowExtEx failed\n");
356 ret
= SetViewportExtEx(hdcDisplay
, -20, -10, NULL
);
357 ok(ret
, "SetViewportExtEx failed\n");
360 ret
= GetViewportExtEx(hdcDisplay
, &vportext
);
361 ok(ret
, "GetViewportExtEx failed\n");
362 ret
= GetWindowExtEx(hdcDisplay
, &wndext
);
363 ok(ret
, "GetWindowExtEx failed\n");
365 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
366 test
.graphics_mode
, test
.map_mode
,
367 wndext
.cx
, wndext
.cy
, vportext
.cx
, vportext
.cy
,
368 horzSize
, horzRes
, vertSize
, vertRes
);
370 if (test
.graphics_mode
== GM_COMPATIBLE
)
372 test
.ex_scale
= 100.0 * ((FLOAT
)horzSize
/ (FLOAT
)horzRes
) /
373 ((FLOAT
)wndext
.cx
/ (FLOAT
)vportext
.cx
);
374 test
.ey_scale
= 100.0 * ((FLOAT
)vertSize
/ (FLOAT
)vertRes
) /
375 ((FLOAT
)wndext
.cy
/ (FLOAT
)vportext
.cy
);
383 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
384 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n");
386 ret
= SetGraphicsMode(hdcMetafile
, test
.graphics_mode
);
387 ok(ret
, "SetGraphicsMode failed\n");
388 ret
= SetMapMode(hdcMetafile
, test
.map_mode
);
389 ok(ret
, "SetMapMode failed\n");
391 if ((test
.map_mode
== MM_ISOTROPIC
) || (test
.map_mode
== MM_ANISOTROPIC
))
393 ret
= SetWindowExtEx(hdcMetafile
, 1, 1, NULL
);
394 ok(ret
, "SetWindowExtEx failed\n");
395 ret
= SetViewportExtEx(hdcMetafile
, -20, -10, NULL
);
396 ok(ret
, "SetViewportExtEx failed\n");
399 ret
= ExtTextOutW(hdcMetafile
, 0, 0, 0, 0, str
, 1, NULL
);
400 ok(ret
, "ExtTextOutW failed\n");
402 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
403 ok(hMetafile
!= 0, "CloseEnhMetaFile failed\n");
406 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_scale_enum_proc
, &test
, &rc
);
407 ok(ret
, "EnumEnhMetaFile failed\n");
408 ok(test
.processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
410 ret
= DeleteEnhMetaFile(hMetafile
);
411 ok(ret
, "DeleteEnhMetaFile failed\n");
414 ret
= ReleaseDC(hwnd
, hdcDisplay
);
415 ok(ret
, "ReleaseDC failed\n");
420 static void check_dc_state(HDC hdc
, int restore_no
,
421 int wnd_org_x
, int wnd_org_y
, int wnd_ext_x
, int wnd_ext_y
,
422 int vp_org_x
, int vp_org_y
, int vp_ext_x
, int vp_ext_y
)
426 POINT vp_org
, win_org
;
427 SIZE vp_size
, win_size
;
428 FLOAT xscale
, yscale
, edx
, edy
;
430 SetLastError(0xdeadbeef);
431 ret
= GetWorldTransform(hdc
, &xform
);
432 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) goto win9x_here
;
433 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
435 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no
, xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
437 ok(xform
.eM12
== 0.0, "%d: expected eM12 0.0, got %f\n", restore_no
, xform
.eM12
);
438 ok(xform
.eM21
== 0.0, "%d: expected eM21 0.0, got %f\n", restore_no
, xform
.eM21
);
440 xscale
= (FLOAT
)vp_ext_x
/ (FLOAT
)wnd_ext_x
;
441 trace("x scale %f\n", xscale
);
442 ok(fabs(xscale
- xform
.eM11
) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
443 restore_no
, vp_ext_x
, wnd_ext_x
, xform
.eM11
);
445 yscale
= (FLOAT
)vp_ext_y
/ (FLOAT
)wnd_ext_y
;
446 trace("y scale %f\n", yscale
);
447 ok(fabs(yscale
- xform
.eM22
) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
448 restore_no
, vp_ext_y
, wnd_ext_y
, xform
.eM22
);
450 edx
= (FLOAT
)vp_org_x
- xform
.eM11
* (FLOAT
)wnd_org_x
;
451 ok(fabs(edx
- xform
.eDx
) < 0.01, "%d: edx %f != eDx %f\n", restore_no
, edx
, xform
.eDx
);
452 edy
= (FLOAT
)vp_org_y
- xform
.eM22
* (FLOAT
)wnd_org_y
;
453 ok(fabs(edy
- xform
.eDy
) < 0.01, "%d: edy %f != eDy %f\n", restore_no
, edy
, xform
.eDy
);
459 GetWindowOrgEx(hdc
, &win_org
);
460 GetViewportOrgEx(hdc
, &vp_org
);
461 GetWindowExtEx(hdc
, &win_size
);
462 GetViewportExtEx(hdc
, &vp_size
);
464 ok(wnd_org_x
== win_org
.x
, "%d: wnd_org_x: %d != %d\n", restore_no
, wnd_org_x
, win_org
.x
);
465 ok(wnd_org_y
== win_org
.y
, "%d: wnd_org_y: %d != %d\n", restore_no
, wnd_org_y
, win_org
.y
);
467 ok(vp_org_x
== vp_org
.x
, "%d: vport_org_x: %d != %d\n", restore_no
, vp_org_x
, vp_org
.x
);
468 ok(vp_org_y
== vp_org
.y
, "%d: vport_org_y: %d != %d\n", restore_no
, vp_org_y
, vp_org
.y
);
470 ok(wnd_ext_x
== win_size
.cx
, "%d: wnd_ext_x: %d != %d\n", restore_no
, wnd_ext_x
, win_size
.cx
);
471 ok(wnd_ext_y
== win_size
.cy
, "%d: wnd_ext_y: %d != %d\n", restore_no
, wnd_ext_y
, win_size
.cy
);
473 ok(vp_ext_x
== vp_size
.cx
, "%d: vport_ext_x: %d != %d\n", restore_no
, vp_ext_x
, vp_size
.cx
);
474 ok(vp_ext_y
== vp_size
.cy
, "%d: vport_ext_y: %d != %d\n", restore_no
, vp_ext_y
, vp_size
.cy
);
477 static int CALLBACK
savedc_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
478 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
484 static int save_state
;
485 static int restore_no
;
486 static int select_no
;
488 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
489 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
492 SetLastError(0xdeadbeef);
493 ret
= GetWorldTransform(hdc
, &xform
);
494 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
496 ret
= GetWindowOrgEx(hdc
, &pt
);
497 ok(ret
, "GetWindowOrgEx error %u\n", GetLastError());
498 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
499 ret
= GetViewportOrgEx(hdc
, &pt
);
500 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
501 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
502 ret
= GetWindowExtEx(hdc
, &size
);
503 ok(ret
, "GetWindowExtEx error %u\n", GetLastError());
504 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
505 ret
= GetViewportExtEx(hdc
, &size
);
506 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
507 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
511 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
512 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
515 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
521 static RECT exp_bounds
= { 0, 0, 150, 150 };
523 const ENHMETAHEADER
*emf
= (const ENHMETAHEADER
*)emr
;
525 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
526 emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
,
527 emf
->rclFrame
.left
, emf
->rclFrame
.top
, emf
->rclFrame
.right
, emf
->rclFrame
.bottom
);
528 trace("mm %d x %d, device %d x %d\n", emf
->szlMillimeters
.cx
, emf
->szlMillimeters
.cy
,
529 emf
->szlDevice
.cx
, emf
->szlDevice
.cy
);
531 SetRect(&bounds
, emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
);
532 ok(EqualRect(&bounds
, &exp_bounds
), "wrong bounds\n");
537 check_dc_state(hdc
, restore_no
, 0, 0, 1, 1, 0, 0, 1, 1);
543 const EMRLINETO
*line
= (const EMRLINETO
*)emr
;
544 trace("EMR_LINETO %d,%d\n", line
->ptl
.x
, line
->ptl
.x
);
547 case EMR_SETWINDOWORGEX
:
549 const EMRSETWINDOWORGEX
*org
= (const EMRSETWINDOWORGEX
*)emr
;
550 trace("EMR_SETWINDOWORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
553 case EMR_SETWINDOWEXTEX
:
555 const EMRSETWINDOWEXTEX
*ext
= (const EMRSETWINDOWEXTEX
*)emr
;
556 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
559 case EMR_SETVIEWPORTORGEX
:
561 const EMRSETVIEWPORTORGEX
*org
= (const EMRSETVIEWPORTORGEX
*)emr
;
562 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
565 case EMR_SETVIEWPORTEXTEX
:
567 const EMRSETVIEWPORTEXTEX
*ext
= (const EMRSETVIEWPORTEXTEX
*)emr
;
568 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
573 trace("EMR_SAVEDC\n");
578 const EMRRESTOREDC
*restoredc
= (const EMRRESTOREDC
*)emr
;
579 trace("EMR_RESTOREDC: %d\n", restoredc
->iRelative
);
584 ok(restoredc
->iRelative
== -1, "first restore %d\n", restoredc
->iRelative
);
585 check_dc_state(hdc
, restore_no
, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
588 ok(restoredc
->iRelative
== -3, "second restore %d\n", restoredc
->iRelative
);
589 check_dc_state(hdc
, restore_no
, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
592 ok(restoredc
->iRelative
== -2, "third restore %d\n", restoredc
->iRelative
);
593 check_dc_state(hdc
, restore_no
, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
596 ok(restore_no
<= 3, "restore_no %d\n", restore_no
);
597 save_state
+= restoredc
->iRelative
;
600 case EMR_SELECTOBJECT
:
602 const EMRSELECTOBJECT
*selectobj
= (const EMRSELECTOBJECT
*)emr
;
603 trace("EMR_SELECTOBJECT: %x\n",selectobj
->ihObject
);
608 ok(save_state
== 0, "EOF save_state %d\n", save_state
);
609 ok(select_no
== 3, "Too many/few selects %i\n",select_no
);
614 SetLastError(0xdeadbeef);
615 ret
= GetWorldTransform(hdc
, &xform
);
616 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
618 ret
= GetWindowOrgEx(hdc
, &pt
);
619 ok(ret
, "GetWindowOrgEx error %u\n", GetLastError());
620 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
621 ret
= GetViewportOrgEx(hdc
, &pt
);
622 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
623 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
624 ret
= GetWindowExtEx(hdc
, &size
);
625 ok(ret
, "GetWindowExtEx error %u\n", GetLastError());
626 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
627 ret
= GetViewportExtEx(hdc
, &size
);
628 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
629 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
633 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
634 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
640 static void test_SaveDC(void)
642 HDC hdcMetafile
, hdcDisplay
;
643 HENHMETAFILE hMetafile
;
648 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
649 static const RECT rc
= { 0, 0, 150, 150 };
651 /* Win9x doesn't play EMFs on invisible windows */
652 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
653 0, 0, 200, 200, 0, 0, 0, NULL
);
654 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
656 hdcDisplay
= GetDC(hwnd
);
657 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
659 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
660 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
662 SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
664 /* Need to write something to the emf, otherwise Windows won't play it back */
665 LineTo(hdcMetafile
, 150, 150);
667 SetWindowOrgEx(hdcMetafile
, 0, 0, NULL
);
668 SetViewportOrgEx(hdcMetafile
, 0, 0, NULL
);
669 SetWindowExtEx(hdcMetafile
, 110, 110, NULL
);
670 SetViewportExtEx(hdcMetafile
, 120, 120, NULL
);
672 /* Force Win9x to update DC state */
673 SetPixelV(hdcMetafile
, 50, 50, 0);
675 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
676 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
677 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
678 ret
= GetViewportExtEx(hdcMetafile
, &size
);
679 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
680 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
681 ret
= SaveDC(hdcMetafile
);
682 ok(ret
== 1, "ret = %d\n", ret
);
684 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
685 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
686 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
687 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
689 /* Force Win9x to update DC state */
690 SetPixelV(hdcMetafile
, 50, 50, 0);
692 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
693 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
694 ok(pt
.x
== 10,"Expecting ViewportOrg x of 10, got %i\n",pt
.x
);
695 ret
= GetViewportExtEx(hdcMetafile
, &size
);
696 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
697 ok(size
.cx
== 200,"Expecting ViewportExt cx of 200, got %i\n",size
.cx
);
698 ret
= SaveDC(hdcMetafile
);
699 ok(ret
== 2, "ret = %d\n", ret
);
701 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
702 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
703 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
704 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
705 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
706 SetBkColor( hdcMetafile
, 0 );
708 /* Force Win9x to update DC state */
709 SetPixelV(hdcMetafile
, 50, 50, 0);
711 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
712 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
713 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
714 ret
= GetViewportExtEx(hdcMetafile
, &size
);
715 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
716 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
717 ret
= SaveDC(hdcMetafile
);
718 ok(ret
== 3, "ret = %d\n", ret
);
720 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
721 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
722 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
723 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
725 SetPolyFillMode( hdcMetafile
, WINDING
);
726 SetBkColor( hdcMetafile
, 0x123456 );
727 ok( GetPolyFillMode( hdcMetafile
) == WINDING
, "PolyFillMode not restored\n" );
728 ok( GetBkColor( hdcMetafile
) == 0x123456, "Background color not restored\n" );
730 /* Force Win9x to update DC state */
731 SetPixelV(hdcMetafile
, 50, 50, 0);
733 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
734 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
735 ok(pt
.x
== 30,"Expecting ViewportOrg x of 30, got %i\n",pt
.x
);
736 ret
= GetViewportExtEx(hdcMetafile
, &size
);
737 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
738 ok(size
.cx
== 400,"Expecting ViewportExt cx of 400, got %i\n",size
.cx
);
739 ret
= RestoreDC(hdcMetafile
, -1);
740 ok(ret
, "ret = %d\n", ret
);
742 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
743 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
744 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
745 ret
= GetViewportExtEx(hdcMetafile
, &size
);
746 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
747 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
748 ok( GetPolyFillMode( hdcMetafile
) == ALTERNATE
, "PolyFillMode not restored\n" );
749 ok( GetBkColor( hdcMetafile
) == 0, "Background color not restored\n" );
750 ret
= SaveDC(hdcMetafile
);
751 ok(ret
== 3, "ret = %d\n", ret
);
753 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
754 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
755 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
756 ret
= GetViewportExtEx(hdcMetafile
, &size
);
757 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
758 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
759 ret
= RestoreDC(hdcMetafile
, 1);
760 ok(ret
, "ret = %d\n", ret
);
761 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
762 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
763 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
764 ret
= GetViewportExtEx(hdcMetafile
, &size
);
765 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
766 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
768 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
769 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
770 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
771 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
773 /* Force Win9x to update DC state */
774 SetPixelV(hdcMetafile
, 50, 50, 0);
776 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
777 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
778 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
779 ret
= GetViewportExtEx(hdcMetafile
, &size
);
780 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
781 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
782 ret
= SaveDC(hdcMetafile
);
783 ok(ret
== 1, "ret = %d\n", ret
);
785 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
786 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
787 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
788 ret
= GetViewportExtEx(hdcMetafile
, &size
);
789 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
790 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
791 ret
= SaveDC(hdcMetafile
);
792 ok(ret
== 2, "ret = %d\n", ret
);
794 memset(&orig_lf
, 0, sizeof(orig_lf
));
795 orig_lf
.lfCharSet
= ANSI_CHARSET
;
796 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
797 orig_lf
.lfWeight
= FW_DONTCARE
;
798 orig_lf
.lfHeight
= 7;
799 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
800 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
801 hFont
= CreateFontIndirectA(&orig_lf
);
802 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
804 hFontOld
= SelectObject(hdcMetafile
, hFont
);
806 hFont2
= CreateFontIndirectA(&orig_lf
);
807 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
808 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
809 ok(hFontCheck
== hFont
, "Font not selected\n");
811 /* Force Win9x to update DC state */
812 SetPixelV(hdcMetafile
, 50, 50, 0);
814 ret
= RestoreDC(hdcMetafile
, 1);
815 ok(ret
, "ret = %d\n", ret
);
816 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
817 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
818 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
819 ret
= GetViewportExtEx(hdcMetafile
, &size
);
820 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
821 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
823 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
824 ok(hFontOld
== hFontCheck
&& hFontCheck
!= hFont
&& hFontCheck
!= hFont2
,
825 "Font not reverted with DC Restore\n");
827 ret
= RestoreDC(hdcMetafile
, -20);
828 ok(!ret
, "ret = %d\n", ret
);
829 ret
= RestoreDC(hdcMetafile
, 20);
830 ok(!ret
, "ret = %d\n", ret
);
832 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
833 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
835 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, savedc_emf_enum_proc
, 0, &rc
);
836 ok( ret
== 1, "EnumEnhMetaFile rets %d\n", ret
);
838 ret
= DeleteObject(hFont
);
839 ok( ret
, "DeleteObject error %d\n", GetLastError());
840 ret
= DeleteObject(hFont2
);
841 ok( ret
, "DeleteObject error %d\n", GetLastError());
842 ret
= DeleteEnhMetaFile(hMetafile
);
843 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
844 ret
= ReleaseDC(hwnd
, hdcDisplay
);
845 ok( ret
, "ReleaseDC error %d\n", GetLastError());
849 static void test_mf_SaveDC(void)
856 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
858 hdcMetafile
= CreateMetaFileA(NULL
);
859 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
861 ret
= SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
862 ok (ret
, "SetMapMode should not fail\n");
864 /* Need to write something to the emf, otherwise Windows won't play it back */
865 LineTo(hdcMetafile
, 150, 150);
868 SetWindowOrgEx(hdcMetafile
, 0, 0, &pt
);
869 ok( pt
.x
== 5555 && pt
.y
== 5555, "wrong origin %d,%d\n", pt
.x
, pt
.y
);
871 SetViewportOrgEx(hdcMetafile
, 0, 0, &pt
);
872 ok( pt
.x
== 5555 && pt
.y
== 5555, "wrong origin %d,%d\n", pt
.x
, pt
.y
);
873 size
.cx
= size
.cy
= 5555;
874 SetWindowExtEx(hdcMetafile
, 110, 110, &size
);
875 ok( size
.cx
== 5555 && size
.cy
== 5555, "wrong size %d,%d\n", size
.cx
, size
.cy
);
876 size
.cx
= size
.cy
= 5555;
877 SetViewportExtEx(hdcMetafile
, 120, 120, &size
);
878 ok( size
.cx
== 5555 && size
.cy
== 5555, "wrong size %d,%d\n", size
.cx
, size
.cy
);
880 /* Force Win9x to update DC state */
881 SetPixelV(hdcMetafile
, 50, 50, 0);
883 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
884 todo_wine
ok (!ret
, "GetViewportOrgEx should fail\n");
885 ret
= GetViewportExtEx(hdcMetafile
, &size
);
886 todo_wine
ok (!ret
, "GetViewportExtEx should fail\n");
887 ret
= SaveDC(hdcMetafile
);
888 ok(ret
== 1, "ret = %d\n", ret
);
890 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
891 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
892 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
893 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
895 /* Force Win9x to update DC state */
896 SetPixelV(hdcMetafile
, 50, 50, 0);
898 ret
= SaveDC(hdcMetafile
);
899 ok(ret
== 1, "ret = %d\n", ret
);
901 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
902 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
903 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
904 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
906 /* Force Win9x to update DC state */
907 SetPixelV(hdcMetafile
, 50, 50, 0);
908 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
909 SetBkColor( hdcMetafile
, 0 );
911 ret
= SaveDC(hdcMetafile
);
912 ok(ret
== 1, "ret = %d\n", ret
);
914 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
915 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
916 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
917 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
919 SetPolyFillMode( hdcMetafile
, WINDING
);
920 SetBkColor( hdcMetafile
, 0x123456 );
921 todo_wine
ok( !GetPolyFillMode( hdcMetafile
), "GetPolyFillMode succeeded\n" );
922 todo_wine
ok( GetBkColor( hdcMetafile
) == CLR_INVALID
, "GetBkColor succeeded\n" );
924 /* Force Win9x to update DC state */
925 SetPixelV(hdcMetafile
, 50, 50, 0);
927 ret
= RestoreDC(hdcMetafile
, -1);
928 ok(ret
, "ret = %d\n", ret
);
930 ret
= SaveDC(hdcMetafile
);
931 ok(ret
== 1, "ret = %d\n", ret
);
933 ret
= RestoreDC(hdcMetafile
, 1);
934 ok(ret
, "ret = %d\n", ret
);
936 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
937 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
938 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
939 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
941 /* Force Win9x to update DC state */
942 SetPixelV(hdcMetafile
, 50, 50, 0);
944 ret
= SaveDC(hdcMetafile
);
945 ok(ret
== 1, "ret = %d\n", ret
);
947 ret
= SaveDC(hdcMetafile
);
948 ok(ret
== 1, "ret = %d\n", ret
);
950 memset(&orig_lf
, 0, sizeof(orig_lf
));
951 orig_lf
.lfCharSet
= ANSI_CHARSET
;
952 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
953 orig_lf
.lfWeight
= FW_DONTCARE
;
954 orig_lf
.lfHeight
= 7;
955 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
956 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
957 hFont
= CreateFontIndirectA(&orig_lf
);
958 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
960 hFontOld
= SelectObject(hdcMetafile
, hFont
);
962 hFont2
= CreateFontIndirectA(&orig_lf
);
963 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
964 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
965 ok(hFontCheck
== hFont
, "Font not selected\n");
967 /* Force Win9x to update DC state */
968 SetPixelV(hdcMetafile
, 50, 50, 0);
970 ret
= RestoreDC(hdcMetafile
, 1);
971 ok(ret
, "ret = %d\n", ret
);
973 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
974 ok(hFontOld
!= hFontCheck
&& hFontCheck
== hFont2
, "Font incorrectly reverted with DC Restore\n");
976 /* restore level is ignored */
977 ret
= RestoreDC(hdcMetafile
, -20);
978 ok(ret
, "ret = %d\n", ret
);
979 ret
= RestoreDC(hdcMetafile
, 20);
980 ok(ret
, "ret = %d\n", ret
);
981 ret
= RestoreDC(hdcMetafile
, 0);
982 ok(ret
, "ret = %d\n", ret
);
984 hMetafile
= CloseMetaFile(hdcMetafile
);
985 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
987 ret
= DeleteMetaFile(hMetafile
);
988 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
989 ret
= DeleteObject(hFont
);
990 ok( ret
, "DeleteObject error %d\n", GetLastError());
991 ret
= DeleteObject(hFont2
);
992 ok( ret
, "DeleteObject error %d\n", GetLastError());
996 /* Win-format metafile (mfdrv) tests */
997 /* These tests compare the generated metafiles byte-by-byte */
998 /* with the nominal results. */
1000 /* Maximum size of sample metafiles in bytes. */
1001 #define MF_BUFSIZE 512
1003 /* 8x8 bitmap data for a pattern brush */
1004 static const unsigned char SAMPLE_PATTERN_BRUSH
[] = {
1005 0x01, 0x00, 0x02, 0x00,
1006 0x03, 0x00, 0x04, 0x00,
1007 0x05, 0x00, 0x06, 0x00,
1008 0x07, 0x00, 0x08, 0x00
1011 /* Sample metafiles to be compared to the outputs of the
1015 static const unsigned char MF_BLANK_BITS
[] = {
1016 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1021 static const unsigned char MF_GRAPHICS_BITS
[] = {
1022 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1023 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1025 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1026 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1027 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1028 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1029 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1030 0x00, 0x00, 0x00, 0x00
1033 static const unsigned char MF_PATTERN_BRUSH_BITS
[] = {
1034 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1035 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1037 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1038 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1039 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1040 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1044 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1045 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1046 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1047 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1048 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1052 static const unsigned char MF_DCBRUSH_BITS
[] =
1054 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1055 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1056 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1057 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1058 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1059 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1062 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1063 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1064 0x00, 0x00, 0x00, 0x00
1067 static const unsigned char MF_TEXTOUT_ON_PATH_BITS
[] =
1069 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1070 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1071 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1072 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1073 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1074 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1078 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS
[] =
1080 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1084 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1085 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1086 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1087 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1089 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1090 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1093 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1094 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1095 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1097 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1099 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1100 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1102 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1103 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1104 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1105 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1106 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1107 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1108 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1110 0x14, 0x00, 0x00, 0x00
1113 static const unsigned char MF_LINETO_BITS
[] = {
1114 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1115 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1117 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1121 static const unsigned char EMF_LINETO_BITS
[] = {
1122 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1124 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1127 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1128 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1129 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1132 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1135 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1136 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1137 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1138 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1139 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1140 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1141 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1143 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1145 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1146 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1147 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1148 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1149 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1150 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1151 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1152 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1153 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1154 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1155 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1156 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1157 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1159 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1163 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS
[] = {
1164 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1166 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1168 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1169 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1170 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1171 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1174 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1177 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1178 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1179 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1180 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1181 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1182 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1183 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1185 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1186 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1187 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1188 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1189 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1190 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1191 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1192 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1194 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1195 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1196 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1197 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1198 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1199 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1201 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1205 static const unsigned char EMF_LINETO_MM_TEXT_BITS
[] = {
1206 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1208 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1211 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1212 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1213 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1216 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1219 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1220 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1221 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1222 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1223 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1224 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1225 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1226 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1227 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1229 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1230 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1232 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1234 0x14, 0x00, 0x00, 0x00
1237 static const unsigned char EMF_BITBLT
[] =
1239 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1244 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1245 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1246 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1249 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1252 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1253 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1255 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1257 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1264 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1265 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1266 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1267 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1281 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1289 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1293 static const unsigned char EMF_DCBRUSH_BITS
[] =
1295 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1296 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1297 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1298 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1299 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1300 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1301 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1302 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1305 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1308 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1309 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1310 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1311 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1312 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1315 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1316 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1317 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1320 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1321 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1322 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1323 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1324 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1325 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1326 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1327 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1328 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1329 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1330 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1331 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1332 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1333 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1335 0x14, 0x00, 0x00, 0x00
1338 static const unsigned char EMF_BEZIER_BITS
[] =
1340 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1342 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1345 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1346 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1347 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1349 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1350 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1352 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1353 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1354 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1356 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1357 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1358 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1359 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1360 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1361 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1362 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1363 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1364 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1365 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1366 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1367 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1368 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1369 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1370 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1371 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1372 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1373 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1374 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1375 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1376 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1377 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1378 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1380 0x14, 0x00, 0x00, 0x00
1383 /* For debugging or dumping the raw metafiles produced by
1384 * new test functions.
1386 static INT CALLBACK
mf_enum_proc(HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
,
1387 INT nobj
, LPARAM param
)
1389 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1390 hdc
, mr
->rdFunction
, mr
->rdSize
, (void *)param
);
1394 /* For debugging or dumping the raw metafiles produced by
1395 * new test functions.
1398 static void dump_mf_bits (const HMETAFILE mf
, const char *desc
)
1400 BYTE buf
[MF_BUFSIZE
];
1403 if (!winetest_debug
) return;
1405 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1406 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1408 printf ("MetaFile %s has bits:\n{\n ", desc
);
1409 for (i
=0; i
<mfsize
; i
++)
1411 printf ("0x%02x", buf
[i
]);
1414 else if (i
% 8 == 7)
1422 /* Compare the metafile produced by a test function with the
1423 * expected raw metafile data in "bits".
1424 * Return value is 0 for a perfect match,
1425 * -1 if lengths aren't equal,
1426 * otherwise returns the number of non-matching bytes.
1429 static int compare_mf_bits (const HMETAFILE mf
, const unsigned char *bits
, UINT bsize
,
1432 unsigned char buf
[MF_BUFSIZE
];
1436 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1437 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1438 if (mfsize
< MF_BUFSIZE
)
1439 ok (mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n",
1440 desc
, mfsize
, bsize
);
1442 ok (bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1443 desc
, mfsize
, bsize
);
1444 if (mfsize
!= bsize
)
1448 for (i
=0; i
<bsize
; i
++)
1450 if (buf
[i
] != bits
[i
])
1453 ok (diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1454 desc
, mfsize
, bsize
, diff
);
1459 static int compare_mf_disk_bits(LPCSTR name
, const BYTE
*bits
, UINT bsize
, const char *desc
)
1461 unsigned char buf
[MF_BUFSIZE
];
1462 DWORD mfsize
, rd_size
, i
;
1467 hfile
= CreateFileA(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1468 assert(hfile
!= INVALID_HANDLE_VALUE
);
1470 mfsize
= GetFileSize(hfile
, NULL
);
1471 assert(mfsize
<= MF_BUFSIZE
);
1473 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &rd_size
, NULL
);
1474 ok( ret
&& rd_size
== mfsize
, "ReadFile: error %d\n", GetLastError());
1478 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n", desc
, mfsize
, bsize
);
1480 if (mfsize
!= bsize
)
1484 for (i
=0; i
<bsize
; i
++)
1486 if (buf
[i
] != bits
[i
])
1489 ok(diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1490 desc
, mfsize
, bsize
, diff
);
1495 /* For debugging or dumping the raw EMFs produced by
1496 * new test functions.
1498 static void dump_emf_bits(const HENHMETAFILE mf
, const char *desc
)
1500 BYTE buf
[MF_BUFSIZE
];
1503 if (!winetest_debug
) return;
1505 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1506 ok (mfsize
> 0, "%s: GetEnhMetaFileBits failed\n", desc
);
1508 printf("EMF %s has bits:\n{\n ", desc
);
1509 for (i
= 0; i
< mfsize
; i
++)
1511 printf ("0x%02x", buf
[i
]);
1514 else if (i
% 8 == 7)
1522 static void dump_emf_records(const HENHMETAFILE mf
, const char *desc
)
1525 BYTE buf
[MF_BUFSIZE
];
1526 UINT mfsize
, offset
;
1528 if (!winetest_debug
) return;
1530 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1531 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1533 printf("EMF %s has records:\n", desc
);
1537 while(offset
< mfsize
)
1539 EMR
*emr
= (EMR
*)(emf
+ offset
);
1540 printf("emr->iType %d, emr->nSize %u\n", emr
->iType
, emr
->nSize
);
1541 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1542 offset
+= emr
->nSize
;
1546 static void dump_emf_record(const ENHMETARECORD
*emr
, const char *desc
)
1551 if (!winetest_debug
) return;
1553 printf ("%s: EMF record %u has bits:\n{\n", desc
, emr
->iType
);
1554 buf
= (const BYTE
*)emr
;
1555 for (i
= 0; i
< emr
->nSize
; i
++)
1557 printf ("0x%02x", buf
[i
]);
1558 if (i
== emr
->nSize
- 1)
1560 else if (i
% 8 == 7)
1568 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW
*eto
)
1570 trace("rclBounds %d,%d - %d,%d\n", eto
->rclBounds
.left
, eto
->rclBounds
.top
,
1571 eto
->rclBounds
.right
, eto
->rclBounds
.bottom
);
1572 trace("iGraphicsMode %u\n", eto
->iGraphicsMode
);
1573 trace("exScale: %f\n", eto
->exScale
);
1574 trace("eyScale: %f\n", eto
->eyScale
);
1575 trace("emrtext.ptlReference %d,%d\n", eto
->emrtext
.ptlReference
.x
, eto
->emrtext
.ptlReference
.y
);
1576 trace("emrtext.nChars %u\n", eto
->emrtext
.nChars
);
1577 trace("emrtext.offString %#x\n", eto
->emrtext
.offString
);
1578 trace("emrtext.fOptions %#x\n", eto
->emrtext
.fOptions
);
1579 trace("emrtext.rcl %d,%d - %d,%d\n", eto
->emrtext
.rcl
.left
, eto
->emrtext
.rcl
.top
,
1580 eto
->emrtext
.rcl
.right
, eto
->emrtext
.rcl
.bottom
);
1581 trace("emrtext.offDx %#x\n", eto
->emrtext
.offDx
);
1584 static BOOL
match_emf_record(const ENHMETARECORD
*emr1
, const ENHMETARECORD
*emr2
,
1585 const char *desc
, BOOL ignore_scaling
)
1589 ok(emr1
->iType
== emr2
->iType
, "%s: emr->iType %u != %u\n",
1590 desc
, emr1
->iType
, emr2
->iType
);
1592 ok(emr1
->nSize
== emr2
->nSize
, "%s: emr->nSize %u != %u\n",
1593 desc
, emr1
->nSize
, emr2
->nSize
);
1595 /* iType and nSize mismatches are fatal */
1596 if (emr1
->iType
!= emr2
->iType
|| emr1
->nSize
!= emr2
->nSize
) return FALSE
;
1598 /* contents of EMR_GDICOMMENT are not interesting */
1599 if (emr1
->iType
== EMR_GDICOMMENT
) return TRUE
;
1601 /* different Windows versions setup DC scaling differently when
1602 * converting an old style metafile to an EMF.
1604 if (ignore_scaling
&& (emr1
->iType
== EMR_SETWINDOWEXTEX
||
1605 emr1
->iType
== EMR_SETVIEWPORTEXTEX
))
1608 if (emr1
->iType
== EMR_EXTTEXTOUTW
|| emr1
->iType
== EMR_EXTTEXTOUTA
)
1610 EMREXTTEXTOUTW
*eto1
, *eto2
;
1612 eto1
= HeapAlloc(GetProcessHeap(), 0, emr1
->nSize
);
1613 memcpy(eto1
, emr1
, emr1
->nSize
);
1614 eto2
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1615 memcpy(eto2
, emr2
, emr2
->nSize
);
1617 /* different Windows versions setup DC scaling differently */
1618 eto1
->exScale
= eto1
->eyScale
= 0.0;
1619 eto2
->exScale
= eto2
->eyScale
= 0.0;
1621 diff
= memcmp(eto1
, eto2
, emr1
->nSize
);
1624 dump_EMREXTTEXTOUT(eto1
);
1625 dump_EMREXTTEXTOUT(eto2
);
1627 HeapFree(GetProcessHeap(), 0, eto1
);
1628 HeapFree(GetProcessHeap(), 0, eto2
);
1630 else if (emr1
->iType
== EMR_EXTSELECTCLIPRGN
&& !lstrcmpA(desc
, "emf_clipping"))
1632 /* We have to take care of NT4 differences here */
1633 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1636 ENHMETARECORD
*emr_nt4
;
1638 emr_nt4
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1639 memcpy(emr_nt4
, emr2
, emr2
->nSize
);
1640 /* Correct the nRgnSize field */
1641 emr_nt4
->dParm
[5] = sizeof(RECT
);
1643 diff
= memcmp(emr1
, emr_nt4
, emr1
->nSize
);
1645 win_skip("Catered for NT4 differences\n");
1647 HeapFree(GetProcessHeap(), 0, emr_nt4
);
1650 else if (emr1
->iType
== EMR_POLYBEZIERTO16
|| emr1
->iType
== EMR_POLYBEZIER16
)
1652 EMRPOLYBEZIER16
*eto1
, *eto2
;
1654 eto1
= (EMRPOLYBEZIER16
*)emr1
;
1655 eto2
= (EMRPOLYBEZIER16
*)emr2
;
1657 diff
= eto1
->cpts
!= eto2
->cpts
;
1659 diff
= memcmp(eto1
->apts
, eto2
->apts
, eto1
->cpts
* sizeof(POINTS
));
1661 else if (emr1
->iType
== EMR_POLYBEZIERTO
|| emr1
->iType
== EMR_POLYBEZIER
)
1663 EMRPOLYBEZIER
*eto1
, *eto2
;
1665 eto1
= (EMRPOLYBEZIER
*)emr1
;
1666 eto2
= (EMRPOLYBEZIER
*)emr2
;
1668 diff
= eto1
->cptl
!= eto2
->cptl
;
1670 diff
= memcmp(eto1
->aptl
, eto2
->aptl
, eto1
->cptl
* sizeof(POINTL
));
1673 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1675 ok(diff
== 0, "%s: contents of record %u don't match\n", desc
, emr1
->iType
);
1679 dump_emf_record(emr1
, "expected bits");
1680 dump_emf_record(emr2
, "actual bits");
1683 return diff
== 0; /* report all non-fatal record mismatches */
1686 /* Compare the EMF produced by a test function with the
1687 * expected raw EMF data in "bits".
1688 * Return value is 0 for a perfect match,
1689 * -1 if lengths aren't equal,
1690 * otherwise returns the number of non-matching bytes.
1692 static int compare_emf_bits(const HENHMETAFILE mf
, const unsigned char *bits
,
1693 UINT bsize
, const char *desc
,
1694 BOOL ignore_scaling
)
1696 unsigned char buf
[MF_BUFSIZE
];
1697 UINT mfsize
, offset1
, offset2
, diff_nt4
, diff_9x
;
1698 const ENHMETAHEADER
*emh1
, *emh2
;
1700 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1701 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1703 /* ENHMETAHEADER size could differ, depending on platform */
1704 diff_nt4
= sizeof(SIZEL
);
1705 diff_9x
= sizeof(SIZEL
) + 3 * sizeof(DWORD
);
1707 if (mfsize
< MF_BUFSIZE
)
1709 ok(mfsize
== bsize
||
1710 broken(mfsize
== bsize
- diff_nt4
) || /* NT4 */
1711 broken(mfsize
== bsize
- diff_9x
), /* Win9x/WinME */
1712 "%s: mfsize=%d, bsize=%d\n", desc
, mfsize
, bsize
);
1715 ok(bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1716 desc
, mfsize
, bsize
);
1718 /* basic things must match */
1719 emh1
= (const ENHMETAHEADER
*)bits
;
1720 emh2
= (const ENHMETAHEADER
*)buf
;
1721 ok(emh1
->iType
== EMR_HEADER
, "expected EMR_HEADER, got %u\n", emh1
->iType
);
1722 ok(emh1
->nSize
== sizeof(ENHMETAHEADER
), "expected sizeof(ENHMETAHEADER), got %u\n", emh1
->nSize
);
1723 ok(emh2
->nBytes
== mfsize
, "expected emh->nBytes %u, got %u\n", mfsize
, emh2
->nBytes
);
1724 ok(emh1
->dSignature
== ENHMETA_SIGNATURE
, "expected ENHMETA_SIGNATURE, got %u\n", emh1
->dSignature
);
1726 ok(emh1
->iType
== emh2
->iType
, "expected EMR_HEADER, got %u\n", emh2
->iType
);
1727 ok(emh1
->nSize
== emh2
->nSize
||
1728 broken(emh1
->nSize
- diff_nt4
== emh2
->nSize
) ||
1729 broken(emh1
->nSize
- diff_9x
== emh2
->nSize
),
1730 "expected nSize %u, got %u\n", emh1
->nSize
, emh2
->nSize
);
1731 ok(emh1
->dSignature
== emh2
->dSignature
, "expected dSignature %u, got %u\n", emh1
->dSignature
, emh2
->dSignature
);
1732 ok(emh1
->nBytes
== emh2
->nBytes
||
1733 broken(emh1
->nBytes
- diff_nt4
== emh2
->nBytes
) ||
1734 broken(emh1
->nBytes
- diff_9x
== emh2
->nBytes
),
1735 "expected nBytes %u, got %u\n", emh1
->nBytes
, emh2
->nBytes
);
1736 ok(emh1
->nRecords
== emh2
->nRecords
, "expected nRecords %u, got %u\n", emh1
->nRecords
, emh2
->nRecords
);
1738 if(!winetest_interactive
)
1740 skip("skipping match_emf_record(), bug ROSTESTS-4\n");
1744 offset1
= emh1
->nSize
;
1745 offset2
= emh2
->nSize
; /* Needed for Win9x/WinME/NT4 */
1746 while (offset1
< emh1
->nBytes
)
1748 const ENHMETARECORD
*emr1
= (const ENHMETARECORD
*)(bits
+ offset1
);
1749 const ENHMETARECORD
*emr2
= (const ENHMETARECORD
*)(buf
+ offset2
);
1751 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1752 desc
, emr1
->iType
, emr1
->nSize
, emr2
->iType
, emr2
->nSize
);
1754 if (!match_emf_record(emr1
, emr2
, desc
, ignore_scaling
)) return -1;
1756 /* We have already bailed out if iType or nSize don't match */
1757 offset1
+= emr1
->nSize
;
1758 offset2
+= emr2
->nSize
;
1764 /* tests blitting to an EMF */
1765 static void test_emf_BitBlt(void)
1767 HDC hdcDisplay
, hdcMetafile
, hdcBitmap
;
1768 HBITMAP hBitmap
, hOldBitmap
;
1769 HENHMETAFILE hMetafile
;
1771 BITMAPINFOHEADER bmih
=
1773 sizeof(BITMAPINFOHEADER
),
1774 BMP_DIM
,/* biWidth */
1775 BMP_DIM
,/* biHeight */
1777 24, /* biBitCount */
1778 BI_RGB
, /* biCompression */
1779 0, /* biXPelsPerMeter */
1780 0, /* biYPelsPerMeter */
1782 0, /* biClrImportant */
1787 hdcDisplay
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1788 ok( hdcDisplay
!= 0, "CreateDCA error %d\n", GetLastError() );
1790 hdcBitmap
= CreateCompatibleDC(hdcDisplay
);
1791 ok( hdcBitmap
!= 0, "CreateCompatibleDC failed\n" );
1792 bmih
.biXPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSX
), 100, 3937);
1793 bmih
.biYPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSY
), 100, 3937);
1794 hBitmap
= CreateDIBSection(hdcDisplay
, (const BITMAPINFO
*)&bmih
,
1795 DIB_RGB_COLORS
, &bits
, NULL
, 0);
1796 hOldBitmap
= SelectObject(hdcBitmap
, hBitmap
);
1798 hdcMetafile
= CreateEnhMetaFileA(hdcBitmap
, NULL
, NULL
, NULL
);
1799 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1801 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1802 ret
= BitBlt(hdcBitmap
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, BLACKNESS
);
1803 ok( ret
, "BitBlt(BLACKNESS) failed\n" );
1805 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, SRCCOPY
);
1806 ok( ret
, "BitBlt(SRCCOPY) failed\n" );
1807 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, WHITENESS
);
1808 ok( ret
, "BitBlt(WHITENESS) failed\n" );
1810 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1811 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1813 if(compare_emf_bits(hMetafile
, EMF_BITBLT
, sizeof(EMF_BITBLT
),
1814 "emf_BitBlt", FALSE
) != 0)
1816 dump_emf_bits(hMetafile
, "emf_BitBlt");
1817 dump_emf_records(hMetafile
, "emf_BitBlt");
1820 SelectObject(hdcBitmap
, hOldBitmap
);
1821 DeleteObject(hBitmap
);
1822 DeleteDC(hdcBitmap
);
1823 DeleteDC(hdcDisplay
);
1827 static void test_emf_DCBrush(void)
1830 HENHMETAFILE hMetafile
;
1836 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
1838 win_skip( "SetDCBrush/PenColor not supported\n" );
1842 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
1843 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1845 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
1846 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
1848 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
1849 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
1851 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
1852 ok( color
== 0xffffff, "SetDCBrushColor returned %x\n", color
);
1854 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
1855 ok( color
== 0, "SetDCPenColor returned %x\n", color
);
1857 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
1859 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
1860 ok( color
== 0x555555, "SetDCBrushColor returned %x\n", color
);
1862 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1863 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1865 if (compare_emf_bits (hMetafile
, EMF_DCBRUSH_BITS
, sizeof(EMF_DCBRUSH_BITS
),
1866 "emf_DC_Brush", FALSE
) != 0)
1868 dump_emf_bits(hMetafile
, "emf_DC_Brush");
1869 dump_emf_records(hMetafile
, "emf_DC_Brush");
1871 ret
= DeleteEnhMetaFile(hMetafile
);
1872 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
1873 ret
= DeleteObject(hBrush
);
1874 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1875 ret
= DeleteObject(hPen
);
1876 ok( ret
, "DeleteObject(HPEN) error %d\n", GetLastError());
1879 /* Test a blank metafile. May be used as a template for new tests. */
1881 static void test_mf_Blank(void)
1884 HMETAFILE hMetafile
;
1889 hdcMetafile
= CreateMetaFileA(NULL
);
1890 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1891 trace("hdcMetafile %p\n", hdcMetafile
);
1893 /* Tests on metafile initialization */
1894 caps
= GetDeviceCaps (hdcMetafile
, TECHNOLOGY
);
1895 ok (caps
== DT_METAFILE
,
1896 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps
);
1898 hMetafile
= CloseMetaFile(hdcMetafile
);
1899 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1900 type
= GetObjectType(hMetafile
);
1901 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1902 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1904 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1907 dump_mf_bits(hMetafile
, "mf_Blank");
1908 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1911 ret
= DeleteMetaFile(hMetafile
);
1912 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1915 static void test_CopyMetaFile(void)
1918 HMETAFILE hMetafile
, hmf_copy
;
1920 char temp_path
[MAX_PATH
];
1921 char mf_name
[MAX_PATH
];
1924 hdcMetafile
= CreateMetaFileA(NULL
);
1925 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1926 trace("hdcMetafile %p\n", hdcMetafile
);
1928 hMetafile
= CloseMetaFile(hdcMetafile
);
1929 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1930 type
= GetObjectType(hMetafile
);
1931 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1933 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1936 dump_mf_bits(hMetafile
, "mf_Blank");
1937 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1940 GetTempPathA(MAX_PATH
, temp_path
);
1941 GetTempFileNameA(temp_path
, "wmf", 0, mf_name
);
1943 hmf_copy
= CopyMetaFileA(hMetafile
, mf_name
);
1944 ok(hmf_copy
!= 0, "CopyMetaFile error %d\n", GetLastError());
1946 type
= GetObjectType(hmf_copy
);
1947 ok(type
== OBJ_METAFILE
, "CopyMetaFile created object with type %d\n", type
);
1949 ret
= DeleteMetaFile(hMetafile
);
1950 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1952 if (compare_mf_disk_bits(mf_name
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
), "mf_blank") != 0)
1954 dump_mf_bits(hmf_copy
, "mf_Blank");
1955 EnumMetaFile(0, hmf_copy
, mf_enum_proc
, 0);
1958 ret
= DeleteMetaFile(hmf_copy
);
1959 ok( ret
, "DeleteMetaFile(%p) error %d\n", hmf_copy
, GetLastError());
1961 DeleteFileA(mf_name
);
1964 static void test_SetMetaFileBits(void)
1972 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), MF_GRAPHICS_BITS
);
1973 trace("hmf %p\n", hmf
);
1974 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1975 type
= GetObjectType(hmf
);
1976 ok(type
== OBJ_METAFILE
, "SetMetaFileBitsEx created object with type %d\n", type
);
1978 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1980 dump_mf_bits(hmf
, "mf_Graphics");
1981 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1984 ret
= DeleteMetaFile(hmf
);
1985 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1987 /* NULL data crashes XP SP1 */
1988 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1990 /* Now with zero size */
1991 SetLastError(0xdeadbeef);
1992 hmf
= SetMetaFileBitsEx(0, MF_GRAPHICS_BITS
);
1993 trace("hmf %p\n", hmf
);
1994 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1995 ok(GetLastError() == ERROR_INVALID_DATA
||
1996 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
1997 "wrong error %d\n", GetLastError());
1999 /* Now with odd size */
2000 SetLastError(0xdeadbeef);
2001 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
) - 1, MF_GRAPHICS_BITS
);
2002 trace("hmf %p\n", hmf
);
2003 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2004 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2006 /* Now with zeroed out header fields */
2007 assert(sizeof(buf
) >= sizeof(MF_GRAPHICS_BITS
));
2008 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2009 mh
= (METAHEADER
*)buf
;
2010 /* corruption of any of the below fields leads to a failure */
2013 mh
->mtHeaderSize
= 0;
2014 SetLastError(0xdeadbeef);
2015 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2016 trace("hmf %p\n", hmf
);
2017 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2018 ok(GetLastError() == ERROR_INVALID_DATA
||
2019 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
2020 "wrong error %d\n", GetLastError());
2022 /* Now with corrupted mtSize field */
2023 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2024 mh
= (METAHEADER
*)buf
;
2025 /* corruption of mtSize doesn't lead to a failure */
2027 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2028 trace("hmf %p\n", hmf
);
2029 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2031 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2033 dump_mf_bits(hmf
, "mf_Graphics");
2034 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2037 ret
= DeleteMetaFile(hmf
);
2038 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2040 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2041 /* Now with zeroed out mtSize field */
2042 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2043 mh
= (METAHEADER
*)buf
;
2044 /* zeroing mtSize doesn't lead to a failure */
2046 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2047 trace("hmf %p\n", hmf
);
2048 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2050 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2052 dump_mf_bits(hmf
, "mf_Graphics");
2053 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2056 ret
= DeleteMetaFile(hmf
);
2057 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2061 /* Simple APIs from mfdrv/graphics.c
2064 static void test_mf_Graphics(void)
2067 HMETAFILE hMetafile
;
2071 hdcMetafile
= CreateMetaFileA(NULL
);
2072 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2073 trace("hdcMetafile %p\n", hdcMetafile
);
2075 ret
= MoveToEx(hdcMetafile
, 1, 1, NULL
);
2076 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2077 ret
= LineTo(hdcMetafile
, 2, 2);
2078 ok( ret
, "LineTo error %d.\n", GetLastError());
2079 ret
= MoveToEx(hdcMetafile
, 1, 1, &oldpoint
);
2080 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2082 /* oldpoint gets garbage under Win XP, so the following test would
2083 * work under Wine but fails under Windows:
2085 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2086 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2087 * oldpoint.x, oldpoint.y);
2090 ret
= Ellipse(hdcMetafile
, 0, 0, 2, 2);
2091 ok( ret
, "Ellipse error %d.\n", GetLastError());
2093 hMetafile
= CloseMetaFile(hdcMetafile
);
2094 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2095 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2097 if (compare_mf_bits (hMetafile
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
),
2098 "mf_Graphics") != 0)
2100 dump_mf_bits(hMetafile
, "mf_Graphics");
2101 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2104 ret
= DeleteMetaFile(hMetafile
);
2105 ok( ret
, "DeleteMetaFile(%p) error %d\n",
2106 hMetafile
, GetLastError());
2109 static void test_mf_PatternBrush(void)
2112 HMETAFILE hMetafile
;
2117 orig_lb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(LOGBRUSH
));
2119 orig_lb
->lbStyle
= BS_PATTERN
;
2120 orig_lb
->lbColor
= RGB(0, 0, 0);
2121 orig_lb
->lbHatch
= (ULONG_PTR
)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH
);
2122 ok((HBITMAP
)orig_lb
->lbHatch
!= NULL
, "CreateBitmap error %d.\n", GetLastError());
2124 hBrush
= CreateBrushIndirect (orig_lb
);
2125 ok(hBrush
!= 0, "CreateBrushIndirect error %d\n", GetLastError());
2127 hdcMetafile
= CreateMetaFileA(NULL
);
2128 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2129 trace("hdcMetafile %p\n", hdcMetafile
);
2131 hBrush
= SelectObject(hdcMetafile
, hBrush
);
2132 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2134 hMetafile
= CloseMetaFile(hdcMetafile
);
2135 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2136 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2138 if (compare_mf_bits (hMetafile
, MF_PATTERN_BRUSH_BITS
, sizeof(MF_PATTERN_BRUSH_BITS
),
2139 "mf_Pattern_Brush") != 0)
2141 dump_mf_bits(hMetafile
, "mf_Pattern_Brush");
2142 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2145 ret
= DeleteMetaFile(hMetafile
);
2146 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
2147 ret
= DeleteObject(hBrush
);
2148 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2149 ret
= DeleteObject((HBITMAP
)orig_lb
->lbHatch
);
2150 ok( ret
, "DeleteObject(HBITMAP) error %d\n",
2152 HeapFree (GetProcessHeap(), 0, orig_lb
);
2155 static void test_mf_DCBrush(void)
2158 HMETAFILE hMetafile
;
2164 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
2166 win_skip( "SetDCBrush/PenColor not supported\n" );
2170 hdcMetafile
= CreateMetaFileA(NULL
);
2171 ok( hdcMetafile
!= 0, "CreateMetaFileA failed\n" );
2173 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
2174 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2176 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
2177 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
2179 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
2180 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2182 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
2183 ok( color
== CLR_INVALID
, "SetDCPenColor returned %x\n", color
);
2185 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
2187 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
2188 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2190 hMetafile
= CloseMetaFile(hdcMetafile
);
2191 ok( hMetafile
!= 0, "CloseMetaFile failed\n" );
2193 if (compare_mf_bits(hMetafile
, MF_DCBRUSH_BITS
, sizeof(MF_DCBRUSH_BITS
), "mf_DCBrush") != 0)
2195 dump_mf_bits(hMetafile
, "mf_DCBrush");
2196 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2198 ret
= DeleteMetaFile(hMetafile
);
2199 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2202 static void test_mf_ExtTextOut_on_path(void)
2205 HMETAFILE hMetafile
;
2207 static const INT dx
[4] = { 3, 5, 8, 12 };
2209 hdcMetafile
= CreateMetaFileA(NULL
);
2210 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2211 trace("hdcMetafile %p\n", hdcMetafile
);
2213 ret
= BeginPath(hdcMetafile
);
2214 ok(!ret
, "BeginPath on metafile DC should fail\n");
2216 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2217 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2219 ret
= EndPath(hdcMetafile
);
2220 ok(!ret
, "EndPath on metafile DC should fail\n");
2222 hMetafile
= CloseMetaFile(hdcMetafile
);
2223 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2225 if (compare_mf_bits(hMetafile
, MF_TEXTOUT_ON_PATH_BITS
, sizeof(MF_TEXTOUT_ON_PATH_BITS
),
2226 "mf_TextOut_on_path") != 0)
2228 dump_mf_bits(hMetafile
, "mf_TextOut_on_path");
2229 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2232 ret
= DeleteMetaFile(hMetafile
);
2233 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2236 static void test_emf_ExtTextOut_on_path(void)
2239 HDC hdcDisplay
, hdcMetafile
;
2240 HENHMETAFILE hMetafile
;
2242 static const INT dx
[4] = { 3, 5, 8, 12 };
2244 /* Win9x doesn't play EMFs on invisible windows */
2245 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2246 0, 0, 200, 200, 0, 0, 0, NULL
);
2247 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2249 hdcDisplay
= GetDC(hwnd
);
2250 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
2252 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
2253 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2255 ret
= BeginPath(hdcMetafile
);
2256 ok(ret
, "BeginPath error %d\n", GetLastError());
2258 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2259 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2261 ret
= EndPath(hdcMetafile
);
2262 ok(ret
, "EndPath error %d\n", GetLastError());
2264 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2265 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2267 /* this doesn't succeed yet: EMF has correct size, all EMF records
2268 * are there, but their contents don't match for different reasons.
2270 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_ON_PATH_BITS
),
2271 "emf_TextOut_on_path", FALSE
) != 0)
2273 dump_emf_bits(hMetafile
, "emf_TextOut_on_path");
2274 dump_emf_records(hMetafile
, "emf_TextOut_on_path");
2277 ret
= DeleteEnhMetaFile(hMetafile
);
2278 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2279 ret
= ReleaseDC(hwnd
, hdcDisplay
);
2280 ok(ret
, "ReleaseDC error %d\n", GetLastError());
2281 DestroyWindow(hwnd
);
2284 static const unsigned char EMF_CLIPPING
[] =
2286 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2288 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2290 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2291 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2292 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2293 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2295 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2296 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2298 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2299 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2300 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2301 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2302 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2303 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2304 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2305 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2306 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2307 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2308 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2309 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2310 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2311 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2314 static void translate( POINT
*pt
, UINT count
, const XFORM
*xform
)
2318 FLOAT x
= (FLOAT
)pt
->x
;
2319 FLOAT y
= (FLOAT
)pt
->y
;
2320 pt
->x
= (LONG
)floor( x
* xform
->eM11
+ y
* xform
->eM21
+ xform
->eDx
+ 0.5 );
2321 pt
->y
= (LONG
)floor( x
* xform
->eM12
+ y
* xform
->eM22
+ xform
->eDy
+ 0.5 );
2326 /* Compare rectangles allowing rounding errors */
2327 static BOOL
is_equal_rect(const RECT
*rc1
, const RECT
*rc2
)
2329 return abs(rc1
->left
- rc2
->left
) <= 1 &&
2330 abs(rc1
->top
- rc2
->top
) <= 1 &&
2331 abs(rc1
->right
- rc2
->right
) <= 1 &&
2332 abs(rc1
->bottom
- rc2
->bottom
) <= 1;
2335 static int CALLBACK
clip_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2336 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
2338 if (emr
->iType
== EMR_EXTSELECTCLIPRGN
)
2340 const EMREXTSELECTCLIPRGN
*clip
= (const EMREXTSELECTCLIPRGN
*)emr
;
2344 char buf
[sizeof(RGNDATAHEADER
) + sizeof(RECT
)];
2346 const union _rgn
*rgn1
;
2348 RECT rect
, rc_transformed
;
2349 const RECT
*rc
= (const RECT
*)param
;
2355 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2356 clip
->cbRgnData
, clip
->iMode
);
2358 ok(clip
->iMode
== RGN_COPY
, "expected RGN_COPY, got %u\n", clip
->iMode
);
2359 ok(clip
->cbRgnData
>= sizeof(RGNDATAHEADER
) + sizeof(RECT
),
2360 "too small data block: %u bytes\n", clip
->cbRgnData
);
2361 if (clip
->cbRgnData
< sizeof(RGNDATAHEADER
) + sizeof(RECT
))
2364 rgn1
= (const union _rgn
*)clip
->RgnData
;
2366 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2367 rgn1
->data
.rdh
.dwSize
, rgn1
->data
.rdh
.iType
,
2368 rgn1
->data
.rdh
.nCount
, rgn1
->data
.rdh
.nRgnSize
,
2369 rgn1
->data
.rdh
.rcBound
.left
, rgn1
->data
.rdh
.rcBound
.top
,
2370 rgn1
->data
.rdh
.rcBound
.right
, rgn1
->data
.rdh
.rcBound
.bottom
);
2372 ok(EqualRect(&rgn1
->data
.rdh
.rcBound
, rc
), "rects don't match\n");
2374 rect
= *(const RECT
*)rgn1
->data
.Buffer
;
2375 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2376 ok(EqualRect(&rect
, rc
), "rects don't match\n");
2378 ok(rgn1
->data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn1
->data
.rdh
.dwSize
);
2379 ok(rgn1
->data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn1
->data
.rdh
.iType
);
2380 ok(rgn1
->data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn1
->data
.rdh
.nCount
);
2381 ok(rgn1
->data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2382 broken(rgn1
->data
.rdh
.nRgnSize
== 168), /* NT4 */
2383 "expected sizeof(RECT), got %u\n", rgn1
->data
.rdh
.nRgnSize
);
2385 hrgn
= CreateRectRgn(0, 0, 0, 0);
2387 memset(&xform
, 0, sizeof(xform
));
2388 SetLastError(0xdeadbeef);
2389 ret
= GetWorldTransform(hdc
, &xform
);
2390 is_win9x
= !ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
;
2392 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
2394 trace("xform.eM11 %f, xform.eM22 %f\n", xform
.eM11
, xform
.eM22
);
2396 ret
= GetClipRgn(hdc
, hrgn
);
2397 ok(ret
== 0, "GetClipRgn returned %d, expected 0\n", ret
);
2399 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
2401 ret
= GetClipRgn(hdc
, hrgn
);
2402 ok(ret
== 1, "GetClipRgn returned %d, expected 1\n", ret
);
2404 /* Win9x returns empty clipping region */
2405 if (is_win9x
) return 1;
2407 ret
= GetRegionData(hrgn
, 0, NULL
);
2408 ok(ret
== sizeof(rgn2
.data
.rdh
) + sizeof(RECT
), "expected sizeof(rgn), got %u\n", ret
);
2410 ret
= GetRegionData(hrgn
, sizeof(rgn2
), &rgn2
.data
);
2411 ok(ret
== sizeof(rgn2
), "expected sizeof(rgn2), got %u\n", ret
);
2413 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2414 rgn2
.data
.rdh
.dwSize
, rgn2
.data
.rdh
.iType
,
2415 rgn2
.data
.rdh
.nCount
, rgn2
.data
.rdh
.nRgnSize
,
2416 rgn2
.data
.rdh
.rcBound
.left
, rgn2
.data
.rdh
.rcBound
.top
,
2417 rgn2
.data
.rdh
.rcBound
.right
, rgn2
.data
.rdh
.rcBound
.bottom
);
2419 rect
= rgn2
.data
.rdh
.rcBound
;
2420 rc_transformed
= *rc
;
2421 translate((POINT
*)&rc_transformed
, 2, &xform
);
2422 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2423 rc_transformed
.right
, rc_transformed
.bottom
);
2424 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2426 rect
= *(const RECT
*)rgn2
.data
.Buffer
;
2427 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2428 rc_transformed
= *rc
;
2429 translate((POINT
*)&rc_transformed
, 2, &xform
);
2430 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2431 rc_transformed
.right
, rc_transformed
.bottom
);
2432 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2434 ok(rgn2
.data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn2
.data
.rdh
.dwSize
);
2435 ok(rgn2
.data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn2
.data
.rdh
.iType
);
2436 ok(rgn2
.data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn2
.data
.rdh
.nCount
);
2437 ok(rgn2
.data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2438 broken(rgn2
.data
.rdh
.nRgnSize
== 168), /* NT4 */
2439 "expected sizeof(RECT), got %u\n", rgn2
.data
.rdh
.nRgnSize
);
2446 static void test_emf_clipping(void)
2448 static const RECT rc
= { 0, 0, 100, 100 };
2449 RECT rc_clip
= { 100, 100, 1024, 1024 };
2455 RECT rc_res
, rc_sclip
;
2457 SetLastError(0xdeadbeef);
2458 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2459 ok(hdc
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2461 /* Need to write something to the emf, otherwise Windows won't play it back */
2464 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2465 ret
= SelectClipRgn(hdc
, hrgn
);
2466 ok(ret
== SIMPLEREGION
, "expected SIMPLEREGION, got %d\n", ret
);
2468 SetLastError(0xdeadbeef);
2469 hemf
= CloseEnhMetaFile(hdc
);
2470 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2472 if (compare_emf_bits(hemf
, EMF_CLIPPING
, sizeof(EMF_CLIPPING
),
2473 "emf_clipping", FALSE
) != 0)
2475 dump_emf_bits(hemf
, "emf_clipping");
2476 dump_emf_records(hemf
, "emf_clipping");
2481 /* Win9x doesn't play EMFs on invisible windows */
2482 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2483 0, 0, 200, 200, 0, 0, 0, NULL
);
2484 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2488 ret
= EnumEnhMetaFile(hdc
, hemf
, clip_emf_enum_proc
, &rc_clip
, &rc
);
2489 ok(ret
, "EnumEnhMetaFile error %d\n", GetLastError());
2491 DeleteEnhMetaFile(hemf
);
2492 ReleaseDC(hwnd
, hdc
);
2493 DestroyWindow(hwnd
);
2495 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2497 SetRect(&rc_sclip
, 100, 100, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2498 hrgn
= CreateRectRgn(rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
);
2499 SelectClipRgn(hdc
, hrgn
);
2500 SetRect(&rc_res
, -1, -1, -1, -1);
2501 ret
= GetClipBox(hdc
, &rc_res
);
2502 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2503 ok(EqualRect(&rc_res
, &rc_sclip
),
2504 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2505 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2506 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2508 OffsetRect(&rc_sclip
, -100, -100);
2509 ret
= OffsetClipRgn(hdc
, -100, -100);
2510 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2511 SetRect(&rc_res
, -1, -1, -1, -1);
2512 ret
= GetClipBox(hdc
, &rc_res
);
2513 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2514 ok(EqualRect(&rc_res
, &rc_sclip
),
2515 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2516 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2517 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2519 ret
= IntersectClipRect(hdc
, 0, 0, 100, 100);
2520 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2521 if (ret
== COMPLEXREGION
)
2523 /* XP returns COMPLEXREGION although region contains only 1 rect */
2524 ret
= GetClipRgn(hdc
, hrgn
);
2525 ok(ret
== 1, "expected 1, got %d\n", ret
);
2526 ret
= rgn_rect_count(hrgn
);
2527 ok(ret
== 1, "expected 1, got %d\n", ret
);
2529 SetRect(&rc_res
, -1, -1, -1, -1);
2530 ret
= GetClipBox(hdc
, &rc_res
);
2531 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2532 ok(EqualRect(&rc_res
, &rc
),
2533 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2534 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
2535 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2537 SetRect(&rc_sclip
, 0, 0, 100, 50);
2538 ret
= ExcludeClipRect(hdc
, 0, 50, 100, 100);
2539 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2540 if (ret
== COMPLEXREGION
)
2542 /* XP returns COMPLEXREGION although region contains only 1 rect */
2543 ret
= GetClipRgn(hdc
, hrgn
);
2544 ok(ret
== 1, "expected 1, got %d\n", ret
);
2545 ret
= rgn_rect_count(hrgn
);
2546 ok(ret
== 1, "expected 1, got %d\n", ret
);
2548 SetRect(&rc_res
, -1, -1, -1, -1);
2549 ret
= GetClipBox(hdc
, &rc_res
);
2550 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2551 ok(EqualRect(&rc_res
, &rc_sclip
),
2552 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2553 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2554 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2556 hemf
= CloseEnhMetaFile(hdc
);
2557 DeleteEnhMetaFile(hemf
);
2561 static const unsigned char MF_CLIP_BITS
[] = {
2563 0x01, 0x00, /* mtType */
2564 0x09, 0x00, /* mtHeaderSize */
2565 0x00, 0x03, /* mtVersion */
2566 0x32, 0x00, 0x00, 0x00, /* mtSize */
2567 0x01, 0x00, /* mtNoObjects */
2568 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2569 0x00, 0x00, /* reserved */
2571 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2572 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2573 0xff, 0x06, /* META_CREATEREGION */
2574 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2575 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2576 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2577 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2580 /* METARECORD for SelectObject */
2581 0x04, 0x00, 0x00, 0x00,
2582 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2586 0x04, 0x00, 0x00, 0x00,
2587 0xf0, 0x01, /* META_DELETEOBJECT */
2590 /* METARECORD for MoveTo(1,0x30) */
2591 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2592 0x14, 0x02, /* META_MOVETO */
2596 /* METARECORD for LineTo(0x20, 0x30) */
2597 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2598 0x13, 0x02, /* META_LINETO */
2603 0x03, 0x00, 0x00, 0x00,
2607 static int clip_mf_enum_proc_seen_selectclipregion
;
2608 static int clip_mf_enum_proc_seen_selectobject
;
2610 static int CALLBACK
clip_mf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2611 METARECORD
*mr
, int n_objs
, LPARAM param
)
2613 switch (mr
->rdFunction
) {
2614 case META_SELECTCLIPREGION
:
2615 clip_mf_enum_proc_seen_selectclipregion
++;
2617 case META_SELECTOBJECT
:
2618 clip_mf_enum_proc_seen_selectobject
++;
2624 static void test_mf_clipping(void)
2626 /* left top right bottom */
2627 static RECT rc_clip
= { 0x11, 0x22, 0x33, 0x44 };
2634 SetLastError(0xdeadbeef);
2635 hdc
= CreateMetaFileA(NULL
);
2636 ok(hdc
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2638 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2639 ret
= SelectClipRgn(hdc
, hrgn
);
2640 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2641 ok(ret
== NULLREGION
, "expected NULLREGION, got %d\n", ret
);
2643 /* Draw a line that starts off left of the clip region and ends inside it */
2644 MoveToEx(hdc
, 0x1, 0x30, NULL
);
2645 LineTo(hdc
, 0x20, 0x30);
2647 SetLastError(0xdeadbeef);
2648 hmf
= CloseMetaFile(hdc
);
2649 ok(hmf
!= 0, "CloseMetaFile error %d\n", GetLastError());
2651 if (compare_mf_bits(hmf
, MF_CLIP_BITS
, sizeof(MF_CLIP_BITS
),
2652 "mf_clipping") != 0)
2654 dump_mf_bits(hmf
, "mf_clipping");
2659 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2660 0, 0, 200, 200, 0, 0, 0, NULL
);
2661 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2665 ret
= EnumMetaFile(hdc
, hmf
, clip_mf_enum_proc
, (LPARAM
)&rc_clip
);
2666 ok(ret
, "EnumMetaFile error %d\n", GetLastError());
2668 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2669 ok(clip_mf_enum_proc_seen_selectclipregion
== 0,
2670 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion
);
2671 ok(clip_mf_enum_proc_seen_selectobject
== 1,
2672 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject
);
2674 DeleteMetaFile(hmf
);
2675 ReleaseDC(hwnd
, hdc
);
2676 DestroyWindow(hwnd
);
2679 static INT CALLBACK
EmfEnumProc(HDC hdc
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
, INT nObj
, LPARAM lpData
)
2681 LPMETAFILEPICT lpMFP
= (LPMETAFILEPICT
)lpData
;
2682 POINT mapping
[2] = { { 0, 0 }, { 10, 10 } };
2683 /* When using MM_TEXT Win9x does not update the mapping mode
2684 * until a record is played which actually outputs something */
2685 PlayEnhMetaFileRecord(hdc
, lpHTable
, lpEMFR
, nObj
);
2686 LPtoDP(hdc
, mapping
, 2);
2687 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2688 lpEMFR
->iType
, lpEMFR
->nSize
,
2689 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
);
2691 if (lpEMFR
->iType
== EMR_LINETO
)
2694 if (!lpMFP
|| lpMFP
->mm
== MM_TEXT
)
2698 x1
= (INT
)floor(10 * 100.0 / LINE_X
+ 0.5);
2699 y1
= (INT
)floor(10 * 100.0 / LINE_Y
+ 0.5);
2703 ok(lpMFP
->mm
== MM_ANISOTROPIC
, "mm=%d\n", lpMFP
->mm
);
2705 x0
= MulDiv(0, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2706 y0
= MulDiv(0, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2707 x1
= MulDiv(10, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2708 y1
= MulDiv(10, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2710 ok(mapping
[0].x
== x0
&& mapping
[0].y
== y0
&& mapping
[1].x
== x1
&& mapping
[1].y
== y1
,
2711 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2712 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
,
2718 static HENHMETAFILE
create_converted_emf(const METAFILEPICT
*mfp
)
2727 hdcMf
= CreateMetaFileA(NULL
);
2728 ok(hdcMf
!= NULL
, "CreateMetaFile failed with error %d\n", GetLastError());
2729 ret
= LineTo(hdcMf
, (INT
)LINE_X
, (INT
)LINE_Y
);
2730 ok(ret
, "LineTo failed with error %d\n", GetLastError());
2731 hmf
= CloseMetaFile(hdcMf
);
2732 ok(hmf
!= NULL
, "CloseMetaFile failed with error %d\n", GetLastError());
2734 if (compare_mf_bits (hmf
, MF_LINETO_BITS
, sizeof(MF_LINETO_BITS
), "mf_LineTo") != 0)
2736 dump_mf_bits(hmf
, "mf_LineTo");
2737 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2740 size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
2741 ok(size
, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2742 pBits
= HeapAlloc(GetProcessHeap(), 0, size
);
2743 GetMetaFileBitsEx(hmf
, size
, pBits
);
2744 DeleteMetaFile(hmf
);
2745 hemf
= SetWinMetaFileBits(size
, pBits
, NULL
, mfp
);
2746 HeapFree(GetProcessHeap(), 0, pBits
);
2750 static void test_mf_conversions(void)
2752 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2754 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2757 RECT rect
= { 0, 0, 100, 100 };
2758 mfp
.mm
= MM_ANISOTROPIC
;
2762 hemf
= create_converted_emf(&mfp
);
2764 if (compare_emf_bits(hemf
, EMF_LINETO_MM_ANISOTROPIC_BITS
, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS
),
2765 "emf_LineTo MM_ANISOTROPIC", TRUE
) != 0)
2767 dump_emf_bits(hemf
, "emf_LineTo MM_ANISOTROPIC");
2768 dump_emf_records(hemf
, "emf_LineTo MM_ANISOTROPIC");
2771 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2773 DeleteEnhMetaFile(hemf
);
2774 DeleteDC(hdcOffscreen
);
2777 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2779 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2782 RECT rect
= { 0, 0, 100, 100 };
2787 hemf
= create_converted_emf(&mfp
);
2789 if (compare_emf_bits(hemf
, EMF_LINETO_MM_TEXT_BITS
, sizeof(EMF_LINETO_MM_TEXT_BITS
),
2790 "emf_LineTo MM_TEXT", TRUE
) != 0)
2792 dump_emf_bits(hemf
, "emf_LineTo MM_TEXT");
2793 dump_emf_records(hemf
, "emf_LineTo MM_TEXT");
2796 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2798 DeleteEnhMetaFile(hemf
);
2799 DeleteDC(hdcOffscreen
);
2802 trace("Testing MF->EMF conversion (NULL mfp)\n");
2804 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2806 RECT rect
= { 0, 0, 100, 100 };
2807 hemf
= create_converted_emf(NULL
);
2809 if (compare_emf_bits(hemf
, EMF_LINETO_BITS
, sizeof(EMF_LINETO_BITS
),
2810 "emf_LineTo NULL", TRUE
) != 0)
2812 dump_emf_bits(hemf
, "emf_LineTo NULL");
2813 dump_emf_records(hemf
, "emf_LineTo NULL");
2816 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, NULL
, &rect
);
2818 DeleteEnhMetaFile(hemf
);
2819 DeleteDC(hdcOffscreen
);
2823 static BOOL
getConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
2824 LONG mm
, LONG xExt
, LONG yExt
,
2825 RECTL
* rclBounds
, RECTL
* rclFrame
)
2828 METAFILEPICT
* mfpPtr
= NULL
;
2830 ENHMETAHEADER header
;
2841 emf
= SetWinMetaFileBits(buffer_size
, buffer
, NULL
, mfpPtr
);
2842 ok(emf
!= NULL
, "SetWinMetaFileBits failed\n");
2843 if (!emf
) return FALSE
;
2844 res
= GetEnhMetaFileHeader(emf
, sizeof(header
), &header
);
2845 ok(res
!= 0, "GetEnhMetaHeader failed\n");
2846 DeleteEnhMetaFile(emf
);
2847 if (!res
) return FALSE
;
2849 *rclBounds
= header
.rclBounds
;
2850 *rclFrame
= header
.rclFrame
;
2854 static void checkConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
2855 LONG mm
, LONG xExt
, LONG yExt
,
2856 RECTL
* rclBoundsExpected
, RECTL
* rclFrameExpected
)
2858 RECTL rclBounds
, rclFrame
;
2860 if (getConvertedFrameAndBounds(buffer_size
, buffer
, mfpIsNull
, mm
, xExt
, yExt
, &rclBounds
, &rclFrame
))
2867 msg
= "mfp == NULL";
2871 const char * mm_str
;
2874 case MM_ANISOTROPIC
: mm_str
= "MM_ANISOTROPIC"; break;
2875 case MM_ISOTROPIC
: mm_str
= "MM_ISOTROPIC"; break;
2876 default: mm_str
= "Unexpected";
2878 sprintf(buf
, "mm=%s, xExt=%d, yExt=%d", mm_str
, xExt
, yExt
);
2882 ok(rclBounds
.left
== rclBoundsExpected
->left
, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected
->left
, rclBounds
.left
, msg
);
2883 ok(rclBounds
.top
== rclBoundsExpected
->top
, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected
->top
, rclBounds
.top
, msg
);
2884 ok(rclBounds
.right
== rclBoundsExpected
->right
, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected
->right
, rclBounds
.right
, msg
);
2885 ok(rclBounds
.bottom
== rclBoundsExpected
->bottom
, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected
->bottom
, rclBounds
.bottom
, msg
);
2886 ok(rclFrame
.left
== rclFrameExpected
->left
, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected
->left
, rclFrame
.left
, msg
);
2887 ok(rclFrame
.top
== rclFrameExpected
->top
, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected
->top
, rclFrame
.top
, msg
);
2888 ok(rclFrame
.right
== rclFrameExpected
->right
, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected
->right
, rclFrame
.right
, msg
);
2889 ok(rclFrame
.bottom
== rclFrameExpected
->bottom
, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected
->bottom
, rclFrame
.bottom
, msg
);
2893 static void test_SetWinMetaFileBits(void)
2901 RECTL rclBoundsAnisotropic
, rclFrameAnisotropic
;
2902 RECTL rclBoundsIsotropic
, rclFrameIsotropic
;
2903 RECTL rclBounds
, rclFrame
;
2907 wmfDC
= CreateMetaFileA(NULL
);
2908 ok(wmfDC
!= NULL
, "CreateMetaFile failed\n");
2911 SetWindowExtEx(wmfDC
, 100, 100, NULL
);
2912 rect
.left
= rect
.top
= 0;
2913 rect
.right
= rect
.bottom
= 50;
2914 FillRect(wmfDC
, &rect
, GetStockObject(BLACK_BRUSH
));
2915 wmf
= CloseMetaFile(wmfDC
);
2916 ok(wmf
!= NULL
, "Metafile creation failed\n");
2919 buffer_size
= GetMetaFileBitsEx(wmf
, 0, NULL
);
2920 ok(buffer_size
!= 0, "GetMetaFileBitsEx failed\n");
2921 if (buffer_size
== 0)
2923 DeleteMetaFile(wmf
);
2927 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
);
2928 ok(buffer
!= NULL
, "HeapAlloc failed\n");
2931 DeleteMetaFile(wmf
);
2935 res
= GetMetaFileBitsEx(wmf
, buffer_size
, buffer
);
2936 ok(res
== buffer_size
, "GetMetaFileBitsEx failed\n");
2937 DeleteMetaFile(wmf
);
2938 if (res
!= buffer_size
)
2940 HeapFree(GetProcessHeap(), 0, buffer
);
2944 /* Get the reference bounds and frame */
2945 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2946 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2948 ok(rclBoundsAnisotropic
.left
== 0 && rclBoundsAnisotropic
.top
== 0 &&
2949 rclBoundsIsotropic
.left
== 0 && rclBoundsIsotropic
.top
== 0,
2950 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2952 ok(rclBoundsAnisotropic
.right
>= rclBoundsIsotropic
.right
, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2953 ok(rclBoundsAnisotropic
.bottom
>= rclBoundsIsotropic
.bottom
, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2954 diffx
= rclBoundsIsotropic
.right
- rclBoundsIsotropic
.bottom
;
2955 if (diffx
< 0) diffx
= -diffx
;
2956 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2958 dc
= CreateCompatibleDC(NULL
);
2960 /* Allow 1 mm difference (rounding errors) */
2961 diffx
= rclBoundsAnisotropic
.right
- GetDeviceCaps(dc
, HORZRES
) / 2;
2962 diffy
= rclBoundsAnisotropic
.bottom
- GetDeviceCaps(dc
, VERTRES
) / 2;
2963 if (diffx
< 0) diffx
= -diffx
;
2964 if (diffy
< 0) diffy
= -diffy
;
2967 ok(diffx
<= 1 && diffy
<= 1,
2968 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2969 GetDeviceCaps(dc
, HORZRES
) / 2, GetDeviceCaps(dc
, VERTRES
) / 2, rclBoundsAnisotropic
.right
, rclBoundsAnisotropic
.bottom
);
2972 /* Allow 1 mm difference (rounding errors) */
2973 diffx
= rclFrameAnisotropic
.right
/ 100 - GetDeviceCaps(dc
, HORZSIZE
) / 2;
2974 diffy
= rclFrameAnisotropic
.bottom
/ 100 - GetDeviceCaps(dc
, VERTSIZE
) / 2;
2975 if (diffx
< 0) diffx
= -diffx
;
2976 if (diffy
< 0) diffy
= -diffy
;
2979 ok(diffx
<= 1 && diffy
<= 1,
2980 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2981 GetDeviceCaps(dc
, HORZSIZE
) / 2, GetDeviceCaps(dc
, VERTSIZE
) / 2, rclFrameAnisotropic
.right
/ 100, rclFrameAnisotropic
.bottom
/ 100);
2985 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2986 checkConvertedFrameAndBounds(buffer_size
, buffer
, TRUE
, 0, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2988 /* If xExt or yExt is zero or negative, the whole device surface is used */
2989 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2990 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2991 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2992 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2993 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2994 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2995 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2996 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2997 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2998 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2999 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3000 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3002 /* MSDN says that negative xExt and yExt values specify a ratio.
3003 Check that this is wrong and the whole device surface is used */
3004 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -1000, -100, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3005 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -1000, -100, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3007 /* Ordinary conversions */
3009 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3011 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3012 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3013 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0 && rclBounds
.right
> rclBounds
.bottom
,
3014 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3017 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3019 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3020 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3021 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0,
3022 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3024 /* Wine has a rounding error */
3025 diffx
= rclBounds
.right
- rclBounds
.bottom
;
3026 if (diffx
< 0) diffx
= -diffx
;
3027 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3030 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_HIMETRIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3032 ok(rclFrame
.right
- rclFrame
.left
!= 30000 && rclFrame
.bottom
- rclFrame
.top
!= 20000,
3033 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3036 HeapFree(GetProcessHeap(), 0, buffer
);
3039 static BOOL
near_match(int x
, int y
)
3041 int epsilon
= min(abs(x
), abs(y
));
3043 epsilon
= max(epsilon
/100, 2);
3045 if(x
< y
- epsilon
|| x
> y
+ epsilon
) return FALSE
;
3049 static void getwinmetafilebits(UINT mode
, int scale
, RECT
*rc
)
3052 HDC display_dc
, emf_dc
;
3053 ENHMETAHEADER
*enh_header
;
3054 UINT size
, emf_size
, i
;
3057 METAHEADER
*mh
= NULL
;
3059 INT horz_res
, vert_res
, horz_size
, vert_size
;
3060 INT curve_caps
, line_caps
, poly_caps
;
3062 display_dc
= GetDC(NULL
);
3063 ok(display_dc
!= NULL
, "display_dc is NULL\n");
3065 horz_res
= GetDeviceCaps(display_dc
, HORZRES
);
3066 vert_res
= GetDeviceCaps(display_dc
, VERTRES
);
3067 horz_size
= GetDeviceCaps(display_dc
, HORZSIZE
);
3068 vert_size
= GetDeviceCaps(display_dc
, VERTSIZE
);
3070 emf_dc
= CreateEnhMetaFileA(display_dc
, NULL
, rc
, NULL
);
3071 ok(emf_dc
!= NULL
, "emf_dc is NULL\n");
3073 curve_caps
= GetDeviceCaps(emf_dc
, CURVECAPS
);
3074 ok(curve_caps
== 511, "expect 511 got %d\n", curve_caps
);
3076 line_caps
= GetDeviceCaps(emf_dc
, LINECAPS
);
3077 ok(line_caps
== 254, "expect 254 got %d\n", line_caps
);
3079 poly_caps
= GetDeviceCaps(emf_dc
, POLYGONALCAPS
);
3080 ok(poly_caps
== 255, "expect 511 got %d\n", poly_caps
);
3082 for(i
= 0; i
< 3000; i
++) /* This is enough to take emf_size > 0xffff */
3083 Rectangle(emf_dc
, 0, 0, 1000, 20);
3084 emf
= CloseEnhMetaFile(emf_dc
);
3085 ok(emf
!= NULL
, "emf is NULL\n");
3087 emf_size
= GetEnhMetaFileBits(emf
, 0, NULL
);
3088 enh_header
= HeapAlloc(GetProcessHeap(), 0, emf_size
);
3089 emf_size
= GetEnhMetaFileBits(emf
, emf_size
, (BYTE
*)enh_header
);
3090 DeleteEnhMetaFile(emf
);
3091 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3092 have different resolutions */
3093 enh_header
->szlDevice
.cx
*= scale
;
3094 emf
= SetEnhMetaFileBits(emf_size
, (BYTE
*)enh_header
);
3095 ok(emf
!= NULL
, "emf is NULL\n");
3096 ok(EqualRect((RECT
*)&enh_header
->rclFrame
, rc
), "Frame rectangles differ\n");
3098 size
= GetWinMetaFileBits(emf
, 0, NULL
, mode
, display_dc
);
3100 broken(size
== 0), /* some versions of winxp fail for some reason */
3101 "GetWinMetaFileBits returns 0\n");
3103 mh
= HeapAlloc(GetProcessHeap(), 0, size
);
3104 GetWinMetaFileBits(emf
, size
, (BYTE
*)mh
, mode
, display_dc
);
3106 for(i
= 0; i
< size
/ 2; i
++) check
+= ((WORD
*)mh
)[i
];
3107 ok(check
== 0, "check %04x\n", check
);
3109 rec
= (METARECORD
*)(mh
+ 1);
3111 while(rec
->rdSize
&& rec
->rdFunction
)
3113 const DWORD chunk_size
= 0x2000;
3114 DWORD mfcomment_chunks
= (emf_size
+ chunk_size
- 1) / chunk_size
;
3116 if(rec_num
< mfcomment_chunks
)
3118 DWORD this_chunk_size
= chunk_size
;
3120 if(rec_num
== mfcomment_chunks
- 1)
3121 this_chunk_size
= emf_size
- rec_num
* chunk_size
;
3123 ok(rec
->rdSize
== (this_chunk_size
+ 44) / 2, "%04x: got %04x expected %04x\n", rec_num
, rec
->rdSize
, (this_chunk_size
+ 44) / 2);
3124 ok(rec
->rdFunction
== META_ESCAPE
, "%04x: got %04x\n", rec_num
, rec
->rdFunction
);
3125 if(rec
->rdSize
< (this_chunk_size
+ 44) / 2) break;
3126 ok(rec
->rdParm
[0] == MFCOMMENT
, "got %04x\n", rec
->rdParm
[0]);
3127 ok(rec
->rdParm
[1] == this_chunk_size
+ 34, "got %04x %x\n", rec
->rdParm
[1], emf_size
+ 34);
3128 ok(rec
->rdParm
[2] == 0x4d57, "got %04x\n", rec
->rdParm
[2]); /* WMFC */
3129 ok(rec
->rdParm
[3] == 0x4346, "got %04x\n", rec
->rdParm
[3]); /* " */
3130 ok(rec
->rdParm
[4] == 1, "got %04x\n", rec
->rdParm
[4]);
3131 ok(rec
->rdParm
[5] == 0, "got %04x\n", rec
->rdParm
[5]);
3132 ok(rec
->rdParm
[6] == 0, "got %04x\n", rec
->rdParm
[6]);
3133 ok(rec
->rdParm
[7] == 1, "got %04x\n", rec
->rdParm
[7]);
3134 /* parm[8] is the checksum, tested above */
3135 if(rec_num
> 0) ok(rec
->rdParm
[8] == 0, "got %04x\n", rec
->rdParm
[8]);
3136 ok(rec
->rdParm
[9] == 0, "got %04x\n", rec
->rdParm
[9]);
3137 ok(rec
->rdParm
[10] == 0, "got %04x\n", rec
->rdParm
[10]);
3138 ok(rec
->rdParm
[11] == mfcomment_chunks
, "got %04x\n", rec
->rdParm
[11]); /* num chunks */
3139 ok(rec
->rdParm
[12] == 0, "got %04x\n", rec
->rdParm
[12]);
3140 ok(rec
->rdParm
[13] == this_chunk_size
, "got %04x expected %04x\n", rec
->rdParm
[13], this_chunk_size
);
3141 ok(rec
->rdParm
[14] == 0, "got %04x\n", rec
->rdParm
[14]);
3142 ok(*(DWORD
*)(rec
->rdParm
+ 15) == emf_size
- this_chunk_size
- rec_num
* chunk_size
, "got %08x\n", *(DWORD
*)(rec
->rdParm
+ 15)); /* DWORD size remaining after current chunk */
3143 ok(*(DWORD
*)(rec
->rdParm
+ 17) == emf_size
, "got %08x emf_size %08x\n", *(DWORD
*)(rec
->rdParm
+ 17), emf_size
);
3144 ok(!memcmp(rec
->rdParm
+ 19, (char*)enh_header
+ rec_num
* chunk_size
, this_chunk_size
), "bits mismatch\n");
3147 else if(rec_num
== mfcomment_chunks
)
3149 ok(rec
->rdFunction
== META_SETMAPMODE
, "got %04x\n", rec
->rdFunction
);
3150 ok(rec
->rdParm
[0] == mode
, "got %04x\n", rec
->rdParm
[0]);
3152 else if(rec_num
== mfcomment_chunks
+ 1)
3155 ok(rec
->rdFunction
== META_SETWINDOWORG
, "got %04x\n", rec
->rdFunction
);
3160 case MM_ANISOTROPIC
:
3161 pt
.y
= MulDiv(rc
->top
, vert_res
, vert_size
* 100) + 1;
3162 pt
.x
= MulDiv(rc
->left
, horz_res
, horz_size
* 100);
3165 pt
.y
= MulDiv(-rc
->top
, 1, 10) + 1;
3166 pt
.x
= MulDiv( rc
->left
, 1, 10);
3169 pt
.y
= -rc
->top
+ 1;
3170 pt
.x
= (rc
->left
>= 0) ? rc
->left
: rc
->left
+ 1; /* strange but true */
3173 pt
.y
= MulDiv(-rc
->top
, 10, 254) + 1;
3174 pt
.x
= MulDiv( rc
->left
, 10, 254);
3177 pt
.y
= MulDiv(-rc
->top
, 100, 254) + 1;
3178 pt
.x
= MulDiv( rc
->left
, 100, 254);
3181 pt
.y
= MulDiv(-rc
->top
, 72 * 20, 2540) + 1;
3182 pt
.x
= MulDiv( rc
->left
, 72 * 20, 2540);
3187 ok(near_match((short)rec
->rdParm
[0], pt
.y
), "got %d expect %d\n", (short)rec
->rdParm
[0], pt
.y
);
3188 ok(near_match((short)rec
->rdParm
[1], pt
.x
), "got %d expect %d\n", (short)rec
->rdParm
[1], pt
.x
);
3190 if(rec_num
== mfcomment_chunks
+ 2)
3192 ok(rec
->rdFunction
== META_SETWINDOWEXT
, "got %04x\n", rec
->rdFunction
);
3193 ok(near_match((short)rec
->rdParm
[0], MulDiv(rc
->bottom
- rc
->top
, vert_res
, vert_size
* 100)),
3194 "got %d\n", (short)rec
->rdParm
[0]);
3195 ok(near_match((short)rec
->rdParm
[1], MulDiv(rc
->right
- rc
->left
, horz_res
, horz_size
* 100)),
3196 "got %d\n", (short)rec
->rdParm
[1]);
3200 rec
= (METARECORD
*)((WORD
*)rec
+ rec
->rdSize
);
3204 HeapFree(GetProcessHeap(), 0, mh
);
3205 HeapFree(GetProcessHeap(), 0, enh_header
);
3206 DeleteEnhMetaFile(emf
);
3208 ReleaseDC(NULL
, display_dc
);
3211 static void test_GetWinMetaFileBits(void)
3216 { 1000, 2000, 3000, 6000},
3217 {-1000, 2000, 3000, 6000},
3218 { 1000, -2000, 3000, 6000},
3219 { 1005, 2005, 3000, 6000},
3220 {-1005, -2005, 3000, 6000},
3221 {-1005, -2010, 3000, 6000},
3222 {-1005, 2010, 3000, 6000},
3228 for(mode
= MM_MIN
; mode
<= MM_MAX
; mode
++)
3231 trace("mode %d\n", mode
);
3233 for(rc
= frames
; rc
->right
- rc
->left
> 0; rc
++)
3235 trace("frame %d,%d - %d,%d\n", rc
->left
, rc
->top
, rc
->right
, rc
->bottom
);
3236 getwinmetafilebits(mode
, 1, rc
);
3237 getwinmetafilebits(mode
, 2, rc
);
3242 static BOOL (WINAPI
*pGdiIsMetaPrintDC
)(HDC
);
3243 static BOOL (WINAPI
*pGdiIsMetaFileDC
)(HDC
);
3244 static BOOL (WINAPI
*pGdiIsPlayMetafileDC
)(HDC
);
3246 static void test_gdiis(void)
3248 RECT rect
= {0,0,100,100};
3249 HDC hdc
, hemfDC
, hmfDC
;
3253 /* resolve all the functions */
3254 hgdi32
= GetModuleHandleA("gdi32.dll");
3255 pGdiIsMetaPrintDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaPrintDC");
3256 pGdiIsMetaFileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaFileDC");
3257 pGdiIsPlayMetafileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsPlayMetafileDC");
3259 if(!pGdiIsMetaPrintDC
|| !pGdiIsMetaFileDC
|| !pGdiIsPlayMetafileDC
)
3261 win_skip("Needed GdiIs* functions are not available\n");
3265 /* try with nothing */
3266 ok(!pGdiIsMetaPrintDC(NULL
), "ismetaprint with NULL parameter\n");
3267 ok(!pGdiIsMetaFileDC(NULL
), "ismetafile with NULL parameter\n");
3268 ok(!pGdiIsPlayMetafileDC(NULL
), "isplaymetafile with NULL parameter\n");
3270 /* try with a metafile */
3271 hmfDC
= CreateMetaFileA(NULL
);
3272 ok(!pGdiIsMetaPrintDC(hmfDC
), "ismetaprint on metafile\n");
3273 ok(pGdiIsMetaFileDC(hmfDC
), "ismetafile on metafile\n");
3274 ok(!pGdiIsPlayMetafileDC(hmfDC
), "isplaymetafile on metafile\n");
3275 DeleteMetaFile(CloseMetaFile(hmfDC
));
3277 /* try with an enhanced metafile */
3279 hemfDC
= CreateEnhMetaFileW(hdc
, NULL
, &rect
, NULL
);
3280 ok(hemfDC
!= NULL
, "failed to create emf\n");
3282 ok(!pGdiIsMetaPrintDC(hemfDC
), "ismetaprint on emf\n");
3283 ok(pGdiIsMetaFileDC(hemfDC
), "ismetafile on emf\n");
3284 ok(!pGdiIsPlayMetafileDC(hemfDC
), "isplaymetafile on emf\n");
3286 hemf
= CloseEnhMetaFile(hemfDC
);
3287 ok(hemf
!= NULL
, "failed to close EMF\n");
3288 DeleteEnhMetaFile(hemf
);
3289 ReleaseDC(NULL
,hdc
);
3292 static void test_SetEnhMetaFileBits(void)
3298 memset(data
, 0xAA, sizeof(data
));
3299 SetLastError(0xdeadbeef);
3300 hemf
= SetEnhMetaFileBits(sizeof(data
), data
);
3301 ok(!hemf
, "SetEnhMetaFileBits should fail\n");
3302 ok(GetLastError() == ERROR_INVALID_DATA
||
3303 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x, WinMe */
3304 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3306 emh
= (ENHMETAHEADER
*)data
;
3307 memset(emh
, 0, sizeof(*emh
));
3309 emh
->iType
= EMR_HEADER
;
3310 emh
->nSize
= sizeof(*emh
);
3311 emh
->dSignature
= ENHMETA_SIGNATURE
;
3312 /* emh->nVersion = 0x10000; XP doesn't care about version */
3313 emh
->nBytes
= sizeof(*emh
);
3314 /* emh->nRecords = 1; XP doesn't care about records */
3315 emh
->nHandles
= 1; /* XP refuses to load a EMF if nHandles == 0 */
3317 SetLastError(0xdeadbeef);
3318 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3319 ok(hemf
!= 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3320 DeleteEnhMetaFile(hemf
);
3322 /* XP refuses to load unaligned EMF */
3324 SetLastError(0xdeadbeef);
3325 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3327 broken(hemf
!= NULL
), /* Win9x, WinMe */
3328 "SetEnhMetaFileBits should fail\n");
3329 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3330 DeleteEnhMetaFile(hemf
);
3332 emh
->dSignature
= 0;
3334 SetLastError(0xdeadbeef);
3335 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3337 broken(hemf
!= NULL
), /* Win9x, WinMe */
3338 "SetEnhMetaFileBits should fail\n");
3339 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3340 DeleteEnhMetaFile(hemf
);
3343 static void test_emf_polybezier(void)
3350 SetLastError(0xdeadbeef);
3351 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3352 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3354 pts
[0].x
= pts
[0].y
= 10;
3355 pts
[1].x
= pts
[1].y
= 20;
3356 pts
[2].x
= pts
[2].y
= 15;
3357 pts
[3].x
= pts
[3].y
= 25;
3358 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO16 */
3359 ok( ret
, "PolyBezierTo failed\n" );
3360 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER16 */
3361 ok( ret
, "PolyBezier failed\n" );
3363 pts
[0].x
= pts
[0].y
= 32769;
3364 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER */
3365 ok( ret
, "PolyBezier failed\n" );
3366 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO */
3367 ok( ret
, "PolyBezierTo failed\n" );
3369 hemf
= CloseEnhMetaFile(hdcMetafile
);
3370 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3372 if(compare_emf_bits(hemf
, EMF_BEZIER_BITS
, sizeof(EMF_BEZIER_BITS
),
3373 "emf_Bezier", FALSE
) != 0)
3375 dump_emf_bits(hemf
, "emf_Bezier");
3376 dump_emf_records(hemf
, "emf_Bezier");
3379 DeleteEnhMetaFile(hemf
);
3382 START_TEST(metafile
)
3384 init_function_pointers();
3386 /* For enhanced metafiles (enhmfdrv) */
3388 test_ExtTextOutScale();
3392 test_emf_ExtTextOut_on_path();
3393 test_emf_clipping();
3394 test_emf_polybezier();
3396 /* For win-format metafiles (mfdrv) */
3400 test_mf_PatternBrush();
3402 test_CopyMetaFile();
3403 test_SetMetaFileBits();
3404 test_mf_ExtTextOut_on_path();
3407 /* For metafile conversions */
3408 test_mf_conversions();
3409 test_SetWinMetaFileBits();
3410 test_GetWinMetaFileBits();
3413 test_SetEnhMetaFileBits();