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
;
89 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
94 ok(GetTextAlign(hdc
) == 0, "text align %08x\n", GetTextAlign(hdc
));
95 ok(GetBkColor(hdc
) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc
));
96 ok(GetTextColor(hdc
) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc
));
97 ok(GetROP2(hdc
) == R2_COPYPEN
, "rop %d\n", GetROP2(hdc
));
98 ok(GetArcDirection(hdc
) == AD_COUNTERCLOCKWISE
, "arc dir %d\n", GetArcDirection(hdc
));
99 ok(GetPolyFillMode(hdc
) == ALTERNATE
, "poly fill %d\n", GetPolyFillMode(hdc
));
100 ok(GetStretchBltMode(hdc
) == BLACKONWHITE
, "stretchblt mode %d\n", GetStretchBltMode(hdc
));
102 /* GetBkMode, GetRelAbs do not get reset to the default value */
103 ok(GetBkMode(hdc
) == OPAQUE
, "bk mode %d\n", GetBkMode(hdc
));
104 if(pSetRelAbs
&& pGetRelAbs
)
105 ok(pGetRelAbs(hdc
, 0) == RELATIVE
, "relabs %d\n", pGetRelAbs(hdc
, 0));
110 case EMR_EXTTEXTOUTA
:
112 const EMREXTTEXTOUTA
*emr_ExtTextOutA
= (const EMREXTTEXTOUTA
*)emr
;
113 dx
= (const INT
*)((const char *)emr
+ emr_ExtTextOutA
->emrtext
.offDx
);
115 ret
= GetObjectA(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(device_lf
), &device_lf
);
116 ok( ret
== sizeof(device_lf
), "GetObjectA error %d\n", GetLastError());
118 /* compare up to lfOutPrecision, other values are not interesting,
119 * and in fact sometimes arbitrary adapted by Win9x.
121 ok(!memcmp(&orig_lf
, &device_lf
, FIELD_OFFSET(LOGFONTA
, lfOutPrecision
)), "fonts don't match\n");
122 ok(!lstrcmpA(orig_lf
.lfFaceName
, device_lf
.lfFaceName
), "font names don't match\n");
124 for(i
= 0; i
< emr_ExtTextOutA
->emrtext
.nChars
; i
++)
126 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
127 n_record
, i
, dx
[i
], orig_dx
[i
]);
130 emr_processed
= TRUE
;
134 case EMR_EXTTEXTOUTW
:
136 const EMREXTTEXTOUTW
*emr_ExtTextOutW
= (const EMREXTTEXTOUTW
*)emr
;
137 dx
= (const INT
*)((const char *)emr
+ emr_ExtTextOutW
->emrtext
.offDx
);
139 SetLastError(0xdeadbeef);
140 ret
= GetObjectA(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(device_lf
), &device_lf
);
141 ok( ret
== sizeof(device_lf
) ||
142 broken(ret
== (sizeof(device_lf
) - LF_FACESIZE
+ strlen(device_lf
.lfFaceName
) + 1)), /* NT4 */
143 "GetObjectA error %d\n", GetLastError());
145 /* compare up to lfOutPrecision, other values are not interesting,
146 * and in fact sometimes arbitrary adapted by Win9x.
148 ok(!memcmp(&orig_lf
, &device_lf
, FIELD_OFFSET(LOGFONTA
, lfOutPrecision
)), "fonts don't match\n");
149 ok(!lstrcmpA(orig_lf
.lfFaceName
, device_lf
.lfFaceName
), "font names don't match\n");
151 for(i
= 0; i
< emr_ExtTextOutW
->emrtext
.nChars
; i
++)
153 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
154 n_record
, i
, dx
[i
], orig_dx
[i
]);
157 emr_processed
= TRUE
;
168 static void test_ExtTextOut(void)
171 HDC hdcDisplay
, hdcMetafile
;
172 HENHMETAFILE hMetafile
;
174 static const char text
[] = "Simple text to test ExtTextOut on metafiles";
176 static const RECT rc
= { 0, 0, 100, 100 };
179 assert(sizeof(dx
)/sizeof(dx
[0]) >= lstrlenA(text
));
181 /* Win9x doesn't play EMFs on invisible windows */
182 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
183 0, 0, 200, 200, 0, 0, 0, NULL
);
184 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
186 hdcDisplay
= GetDC(hwnd
);
187 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
189 trace("hdcDisplay %p\n", hdcDisplay
);
191 SetMapMode(hdcDisplay
, MM_TEXT
);
193 memset(&orig_lf
, 0, sizeof(orig_lf
));
195 orig_lf
.lfCharSet
= ANSI_CHARSET
;
196 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
197 orig_lf
.lfWeight
= FW_DONTCARE
;
198 orig_lf
.lfHeight
= 7;
199 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
200 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
201 hFont
= CreateFontIndirectA(&orig_lf
);
202 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
204 hFont
= SelectObject(hdcDisplay
, hFont
);
206 len
= lstrlenA(text
);
207 for (i
= 0; i
< len
; i
++)
209 ret
= GetCharWidthA(hdcDisplay
, text
[i
], text
[i
], &dx
[i
]);
210 ok( ret
, "GetCharWidthA error %d\n", GetLastError());
212 hFont
= SelectObject(hdcDisplay
, hFont
);
214 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
215 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
217 trace("hdcMetafile %p\n", hdcMetafile
);
219 ok(GetDeviceCaps(hdcMetafile
, TECHNOLOGY
) == DT_RASDISPLAY
,
220 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
222 hFont
= SelectObject(hdcMetafile
, hFont
);
224 /* 1. pass NULL lpDx */
225 ret
= ExtTextOutA(hdcMetafile
, 0, 0, 0, &rc
, text
, lstrlenA(text
), NULL
);
226 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
228 /* 2. pass custom lpDx */
229 ret
= ExtTextOutA(hdcMetafile
, 0, 20, 0, &rc
, text
, lstrlenA(text
), dx
);
230 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
232 hFont
= SelectObject(hdcMetafile
, hFont
);
233 ret
= DeleteObject(hFont
);
234 ok( ret
, "DeleteObject error %d\n", GetLastError());
236 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
237 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
239 ok(!GetObjectType(hdcMetafile
), "CloseEnhMetaFile has to destroy metafile hdc\n");
241 ret
= PlayEnhMetaFile(hdcDisplay
, hMetafile
, &rc
);
242 ok( ret
, "PlayEnhMetaFile error %d\n", GetLastError());
244 SetTextAlign(hdcDisplay
, TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
);
245 SetBkColor(hdcDisplay
, RGB(0xff, 0, 0));
246 SetTextColor(hdcDisplay
, RGB(0, 0xff, 0));
247 SetROP2(hdcDisplay
, R2_NOT
);
248 SetArcDirection(hdcDisplay
, AD_CLOCKWISE
);
249 SetPolyFillMode(hdcDisplay
, WINDING
);
250 SetStretchBltMode(hdcDisplay
, HALFTONE
);
252 if(pSetRelAbs
) pSetRelAbs(hdcDisplay
, RELATIVE
);
253 SetBkMode(hdcDisplay
, OPAQUE
);
255 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, &rc
);
256 ok( ret
, "EnumEnhMetaFile error %d\n", GetLastError());
258 ok( GetTextAlign(hdcDisplay
) == (TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
),
259 "text align %08x\n", GetTextAlign(hdcDisplay
));
260 ok( GetBkColor(hdcDisplay
) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay
));
261 ok( GetTextColor(hdcDisplay
) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay
));
262 ok( GetROP2(hdcDisplay
) == R2_NOT
, "rop2 %d\n", GetROP2(hdcDisplay
));
263 ok( GetArcDirection(hdcDisplay
) == AD_CLOCKWISE
, "arc dir %d\n", GetArcDirection(hdcDisplay
));
264 ok( GetPolyFillMode(hdcDisplay
) == WINDING
, "poly fill %d\n", GetPolyFillMode(hdcDisplay
));
265 ok( GetStretchBltMode(hdcDisplay
) == HALFTONE
, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay
));
267 ok(emr_processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
269 ok(!EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
270 "A valid hdc has to require a valid rc\n");
272 ok(EnumEnhMetaFile(NULL
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
273 "A null hdc does not require a valid rc\n");
275 ret
= DeleteEnhMetaFile(hMetafile
);
276 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
277 ret
= ReleaseDC(hwnd
, hdcDisplay
);
278 ok( ret
, "ReleaseDC error %d\n", GetLastError());
282 struct eto_scale_test_record
291 static int CALLBACK
eto_scale_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
292 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
294 struct eto_scale_test_record
*test
= (struct eto_scale_test_record
*)param
;
296 if (emr
->iType
== EMR_EXTTEXTOUTW
)
298 const EMREXTTEXTOUTW
*pExtTextOutW
= (const EMREXTTEXTOUTW
*)emr
;
299 ok(fabs(test
->ex_scale
- pExtTextOutW
->exScale
) < 0.001,
300 "Got exScale %f, expected %f\n", pExtTextOutW
->exScale
, test
->ex_scale
);
301 ok(fabs(test
->ey_scale
- pExtTextOutW
->eyScale
) < 0.001,
302 "Got eyScale %f, expected %f\n", pExtTextOutW
->eyScale
, test
->ey_scale
);
303 test
->processed
= TRUE
;
309 static void test_ExtTextOutScale(void)
311 const RECT rc
= { 0, 0, 100, 100 };
312 const WCHAR str
[] = {'a',0 };
313 struct eto_scale_test_record test
;
314 HDC hdcDisplay
, hdcMetafile
;
315 HENHMETAFILE hMetafile
;
317 SIZE wndext
, vportext
;
318 int horzSize
, vertSize
, horzRes
, vertRes
;
322 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
323 0, 0, 200, 200, 0, 0, 0, NULL
);
324 ok(hwnd
!= 0, "CreateWindowExA failed\n");
326 hdcDisplay
= GetDC(hwnd
);
327 ok(hdcDisplay
!= 0, "GetDC failed\n");
329 horzSize
= GetDeviceCaps(hdcDisplay
, HORZSIZE
);
330 horzRes
= GetDeviceCaps(hdcDisplay
, HORZRES
);
331 vertSize
= GetDeviceCaps(hdcDisplay
, VERTSIZE
);
332 vertRes
= GetDeviceCaps(hdcDisplay
, VERTRES
);
333 ok(horzSize
&& horzRes
&& vertSize
&& vertRes
, "GetDeviceCaps failed\n");
335 for (i
= 0; i
< 16; i
++)
337 test
.graphics_mode
= i
/ 8 + 1;
338 test
.map_mode
= i
% 8 + 1;
340 ret
= SetGraphicsMode(hdcDisplay
, test
.graphics_mode
);
341 ok(ret
, "SetGraphicsMode failed\n");
342 ret
= SetMapMode(hdcDisplay
, test
.map_mode
);
343 ok(ret
, "SetMapMode failed\n");
345 if ((test
.map_mode
== MM_ISOTROPIC
) || (test
.map_mode
== MM_ANISOTROPIC
))
347 ret
= SetWindowExtEx(hdcDisplay
, 1, 1, NULL
);
348 ok(ret
, "SetWindowExtEx failed\n");
349 ret
= SetViewportExtEx(hdcDisplay
, -20, -10, NULL
);
350 ok(ret
, "SetViewportExtEx failed\n");
353 ret
= GetViewportExtEx(hdcDisplay
, &vportext
);
354 ok(ret
, "GetViewportExtEx failed\n");
355 ret
= GetWindowExtEx(hdcDisplay
, &wndext
);
356 ok(ret
, "GetWindowExtEx failed\n");
358 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
359 test
.graphics_mode
, test
.map_mode
,
360 wndext
.cx
, wndext
.cy
, vportext
.cx
, vportext
.cy
,
361 horzSize
, horzRes
, vertSize
, vertRes
);
363 if (test
.graphics_mode
== GM_COMPATIBLE
)
365 test
.ex_scale
= 100.0 * ((FLOAT
)horzSize
/ (FLOAT
)horzRes
) /
366 ((FLOAT
)wndext
.cx
/ (FLOAT
)vportext
.cx
);
367 test
.ey_scale
= 100.0 * ((FLOAT
)vertSize
/ (FLOAT
)vertRes
) /
368 ((FLOAT
)wndext
.cy
/ (FLOAT
)vportext
.cy
);
376 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
377 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n");
379 ret
= SetGraphicsMode(hdcMetafile
, test
.graphics_mode
);
380 ok(ret
, "SetGraphicsMode failed\n");
381 ret
= SetMapMode(hdcMetafile
, test
.map_mode
);
382 ok(ret
, "SetMapMode failed\n");
384 if ((test
.map_mode
== MM_ISOTROPIC
) || (test
.map_mode
== MM_ANISOTROPIC
))
386 ret
= SetWindowExtEx(hdcMetafile
, 1, 1, NULL
);
387 ok(ret
, "SetWindowExtEx failed\n");
388 ret
= SetViewportExtEx(hdcMetafile
, -20, -10, NULL
);
389 ok(ret
, "SetViewportExtEx failed\n");
392 ret
= ExtTextOutW(hdcMetafile
, 0, 0, 0, 0, str
, 1, NULL
);
393 ok(ret
, "ExtTextOutW failed\n");
395 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
396 ok(hMetafile
!= 0, "CloseEnhMetaFile failed\n");
399 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_scale_enum_proc
, &test
, &rc
);
400 ok(ret
, "EnumEnhMetaFile failed\n");
401 ok(test
.processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
403 ret
= DeleteEnhMetaFile(hMetafile
);
404 ok(ret
, "DeleteEnhMetaFile failed\n");
407 ret
= ReleaseDC(hwnd
, hdcDisplay
);
408 ok(ret
, "ReleaseDC failed\n");
413 static void check_dc_state(HDC hdc
, int restore_no
,
414 int wnd_org_x
, int wnd_org_y
, int wnd_ext_x
, int wnd_ext_y
,
415 int vp_org_x
, int vp_org_y
, int vp_ext_x
, int vp_ext_y
)
419 POINT vp_org
, win_org
;
420 SIZE vp_size
, win_size
;
421 FLOAT xscale
, yscale
, edx
, edy
;
423 SetLastError(0xdeadbeef);
424 ret
= GetWorldTransform(hdc
, &xform
);
425 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) goto win9x_here
;
426 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
428 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no
, xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
430 ok(xform
.eM12
== 0.0, "%d: expected eM12 0.0, got %f\n", restore_no
, xform
.eM12
);
431 ok(xform
.eM21
== 0.0, "%d: expected eM21 0.0, got %f\n", restore_no
, xform
.eM21
);
433 xscale
= (FLOAT
)vp_ext_x
/ (FLOAT
)wnd_ext_x
;
434 trace("x scale %f\n", xscale
);
435 ok(fabs(xscale
- xform
.eM11
) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
436 restore_no
, vp_ext_x
, wnd_ext_x
, xform
.eM11
);
438 yscale
= (FLOAT
)vp_ext_y
/ (FLOAT
)wnd_ext_y
;
439 trace("y scale %f\n", yscale
);
440 ok(fabs(yscale
- xform
.eM22
) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
441 restore_no
, vp_ext_y
, wnd_ext_y
, xform
.eM22
);
443 edx
= (FLOAT
)vp_org_x
- xform
.eM11
* (FLOAT
)wnd_org_x
;
444 ok(fabs(edx
- xform
.eDx
) < 0.01, "%d: edx %f != eDx %f\n", restore_no
, edx
, xform
.eDx
);
445 edy
= (FLOAT
)vp_org_y
- xform
.eM22
* (FLOAT
)wnd_org_y
;
446 ok(fabs(edy
- xform
.eDy
) < 0.01, "%d: edy %f != eDy %f\n", restore_no
, edy
, xform
.eDy
);
452 GetWindowOrgEx(hdc
, &win_org
);
453 GetViewportOrgEx(hdc
, &vp_org
);
454 GetWindowExtEx(hdc
, &win_size
);
455 GetViewportExtEx(hdc
, &vp_size
);
457 ok(wnd_org_x
== win_org
.x
, "%d: wnd_org_x: %d != %d\n", restore_no
, wnd_org_x
, win_org
.x
);
458 ok(wnd_org_y
== win_org
.y
, "%d: wnd_org_y: %d != %d\n", restore_no
, wnd_org_y
, win_org
.y
);
460 ok(vp_org_x
== vp_org
.x
, "%d: vport_org_x: %d != %d\n", restore_no
, vp_org_x
, vp_org
.x
);
461 ok(vp_org_y
== vp_org
.y
, "%d: vport_org_y: %d != %d\n", restore_no
, vp_org_y
, vp_org
.y
);
463 ok(wnd_ext_x
== win_size
.cx
, "%d: wnd_ext_x: %d != %d\n", restore_no
, wnd_ext_x
, win_size
.cx
);
464 ok(wnd_ext_y
== win_size
.cy
, "%d: wnd_ext_y: %d != %d\n", restore_no
, wnd_ext_y
, win_size
.cy
);
466 ok(vp_ext_x
== vp_size
.cx
, "%d: vport_ext_x: %d != %d\n", restore_no
, vp_ext_x
, vp_size
.cx
);
467 ok(vp_ext_y
== vp_size
.cy
, "%d: vport_ext_y: %d != %d\n", restore_no
, vp_ext_y
, vp_size
.cy
);
470 static int CALLBACK
savedc_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
471 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
477 static int save_state
;
478 static int restore_no
;
479 static int select_no
;
481 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
482 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
484 SetLastError(0xdeadbeef);
485 ret
= GetWorldTransform(hdc
, &xform
);
486 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
488 ret
= GetWindowOrgEx(hdc
, &pt
);
489 ok(ret
, "GetWindowOrgEx error %u\n", GetLastError());
490 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
491 ret
= GetViewportOrgEx(hdc
, &pt
);
492 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
493 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
494 ret
= GetWindowExtEx(hdc
, &size
);
495 ok(ret
, "GetWindowExtEx error %u\n", GetLastError());
496 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
497 ret
= GetViewportExtEx(hdc
, &size
);
498 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
499 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
503 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
504 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
507 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
513 static RECT exp_bounds
= { 0, 0, 150, 150 };
515 const ENHMETAHEADER
*emf
= (const ENHMETAHEADER
*)emr
;
517 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
518 emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
,
519 emf
->rclFrame
.left
, emf
->rclFrame
.top
, emf
->rclFrame
.right
, emf
->rclFrame
.bottom
);
520 trace("mm %d x %d, device %d x %d\n", emf
->szlMillimeters
.cx
, emf
->szlMillimeters
.cy
,
521 emf
->szlDevice
.cx
, emf
->szlDevice
.cy
);
523 SetRect(&bounds
, emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
);
524 ok(EqualRect(&bounds
, &exp_bounds
), "wrong bounds\n");
529 check_dc_state(hdc
, restore_no
, 0, 0, 1, 1, 0, 0, 1, 1);
535 const EMRLINETO
*line
= (const EMRLINETO
*)emr
;
536 trace("EMR_LINETO %d,%d\n", line
->ptl
.x
, line
->ptl
.x
);
539 case EMR_SETWINDOWORGEX
:
541 const EMRSETWINDOWORGEX
*org
= (const EMRSETWINDOWORGEX
*)emr
;
542 trace("EMR_SETWINDOWORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
545 case EMR_SETWINDOWEXTEX
:
547 const EMRSETWINDOWEXTEX
*ext
= (const EMRSETWINDOWEXTEX
*)emr
;
548 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
551 case EMR_SETVIEWPORTORGEX
:
553 const EMRSETVIEWPORTORGEX
*org
= (const EMRSETVIEWPORTORGEX
*)emr
;
554 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
557 case EMR_SETVIEWPORTEXTEX
:
559 const EMRSETVIEWPORTEXTEX
*ext
= (const EMRSETVIEWPORTEXTEX
*)emr
;
560 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
565 trace("EMR_SAVEDC\n");
570 const EMRRESTOREDC
*restoredc
= (const EMRRESTOREDC
*)emr
;
571 trace("EMR_RESTOREDC: %d\n", restoredc
->iRelative
);
576 ok(restoredc
->iRelative
== -1, "first restore %d\n", restoredc
->iRelative
);
577 check_dc_state(hdc
, restore_no
, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
580 ok(restoredc
->iRelative
== -3, "second restore %d\n", restoredc
->iRelative
);
581 check_dc_state(hdc
, restore_no
, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
584 ok(restoredc
->iRelative
== -2, "third restore %d\n", restoredc
->iRelative
);
585 check_dc_state(hdc
, restore_no
, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
588 ok(restore_no
<= 3, "restore_no %d\n", restore_no
);
589 save_state
+= restoredc
->iRelative
;
592 case EMR_SELECTOBJECT
:
594 const EMRSELECTOBJECT
*selectobj
= (const EMRSELECTOBJECT
*)emr
;
595 trace("EMR_SELECTOBJECT: %x\n",selectobj
->ihObject
);
600 ok(save_state
== 0, "EOF save_state %d\n", save_state
);
601 ok(select_no
== 3, "Too many/few selects %i\n",select_no
);
605 SetLastError(0xdeadbeef);
606 ret
= GetWorldTransform(hdc
, &xform
);
607 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
609 ret
= GetWindowOrgEx(hdc
, &pt
);
610 ok(ret
, "GetWindowOrgEx error %u\n", GetLastError());
611 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
612 ret
= GetViewportOrgEx(hdc
, &pt
);
613 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
614 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
615 ret
= GetWindowExtEx(hdc
, &size
);
616 ok(ret
, "GetWindowExtEx error %u\n", GetLastError());
617 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
618 ret
= GetViewportExtEx(hdc
, &size
);
619 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
620 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
624 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
625 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
631 static void test_SaveDC(void)
633 HDC hdcMetafile
, hdcDisplay
;
634 HENHMETAFILE hMetafile
;
639 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
640 static const RECT rc
= { 0, 0, 150, 150 };
642 /* Win9x doesn't play EMFs on invisible windows */
643 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
644 0, 0, 200, 200, 0, 0, 0, NULL
);
645 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
647 hdcDisplay
= GetDC(hwnd
);
648 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
650 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
651 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
653 SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
655 /* Need to write something to the emf, otherwise Windows won't play it back */
656 LineTo(hdcMetafile
, 150, 150);
658 SetWindowOrgEx(hdcMetafile
, 0, 0, NULL
);
659 SetViewportOrgEx(hdcMetafile
, 0, 0, NULL
);
660 SetWindowExtEx(hdcMetafile
, 110, 110, NULL
);
661 SetViewportExtEx(hdcMetafile
, 120, 120, NULL
);
663 /* Force Win9x to update DC state */
664 SetPixelV(hdcMetafile
, 50, 50, 0);
666 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
667 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
668 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
669 ret
= GetViewportExtEx(hdcMetafile
, &size
);
670 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
671 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
672 ret
= SaveDC(hdcMetafile
);
673 ok(ret
== 1, "ret = %d\n", ret
);
675 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
676 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
677 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
678 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
680 /* Force Win9x to update DC state */
681 SetPixelV(hdcMetafile
, 50, 50, 0);
683 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
684 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
685 ok(pt
.x
== 10,"Expecting ViewportOrg x of 10, got %i\n",pt
.x
);
686 ret
= GetViewportExtEx(hdcMetafile
, &size
);
687 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
688 ok(size
.cx
== 200,"Expecting ViewportExt cx of 200, got %i\n",size
.cx
);
689 ret
= SaveDC(hdcMetafile
);
690 ok(ret
== 2, "ret = %d\n", ret
);
692 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
693 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
694 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
695 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
696 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
697 SetBkColor( hdcMetafile
, 0 );
699 /* Force Win9x to update DC state */
700 SetPixelV(hdcMetafile
, 50, 50, 0);
702 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
703 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
704 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
705 ret
= GetViewportExtEx(hdcMetafile
, &size
);
706 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
707 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
708 ret
= SaveDC(hdcMetafile
);
709 ok(ret
== 3, "ret = %d\n", ret
);
711 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
712 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
713 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
714 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
716 SetPolyFillMode( hdcMetafile
, WINDING
);
717 SetBkColor( hdcMetafile
, 0x123456 );
718 ok( GetPolyFillMode( hdcMetafile
) == WINDING
, "PolyFillMode not restored\n" );
719 ok( GetBkColor( hdcMetafile
) == 0x123456, "Background color not restored\n" );
721 /* Force Win9x to update DC state */
722 SetPixelV(hdcMetafile
, 50, 50, 0);
724 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
725 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
726 ok(pt
.x
== 30,"Expecting ViewportOrg x of 30, got %i\n",pt
.x
);
727 ret
= GetViewportExtEx(hdcMetafile
, &size
);
728 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
729 ok(size
.cx
== 400,"Expecting ViewportExt cx of 400, got %i\n",size
.cx
);
730 ret
= RestoreDC(hdcMetafile
, -1);
731 ok(ret
, "ret = %d\n", ret
);
733 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
734 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
735 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
736 ret
= GetViewportExtEx(hdcMetafile
, &size
);
737 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
738 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
739 ok( GetPolyFillMode( hdcMetafile
) == ALTERNATE
, "PolyFillMode not restored\n" );
740 ok( GetBkColor( hdcMetafile
) == 0, "Background color not restored\n" );
741 ret
= SaveDC(hdcMetafile
);
742 ok(ret
== 3, "ret = %d\n", ret
);
744 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
745 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
746 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
747 ret
= GetViewportExtEx(hdcMetafile
, &size
);
748 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
749 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
750 ret
= RestoreDC(hdcMetafile
, 1);
751 ok(ret
, "ret = %d\n", ret
);
752 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
753 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
754 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
755 ret
= GetViewportExtEx(hdcMetafile
, &size
);
756 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
757 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
759 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
760 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
761 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
762 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
764 /* Force Win9x to update DC state */
765 SetPixelV(hdcMetafile
, 50, 50, 0);
767 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
768 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
769 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
770 ret
= GetViewportExtEx(hdcMetafile
, &size
);
771 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
772 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
773 ret
= SaveDC(hdcMetafile
);
774 ok(ret
== 1, "ret = %d\n", ret
);
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
== 2, "ret = %d\n", ret
);
785 memset(&orig_lf
, 0, sizeof(orig_lf
));
786 orig_lf
.lfCharSet
= ANSI_CHARSET
;
787 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
788 orig_lf
.lfWeight
= FW_DONTCARE
;
789 orig_lf
.lfHeight
= 7;
790 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
791 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
792 hFont
= CreateFontIndirectA(&orig_lf
);
793 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
795 hFontOld
= SelectObject(hdcMetafile
, hFont
);
797 hFont2
= CreateFontIndirectA(&orig_lf
);
798 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
799 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
800 ok(hFontCheck
== hFont
, "Font not selected\n");
802 /* Force Win9x to update DC state */
803 SetPixelV(hdcMetafile
, 50, 50, 0);
805 ret
= RestoreDC(hdcMetafile
, 1);
806 ok(ret
, "ret = %d\n", ret
);
807 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
808 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
809 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
810 ret
= GetViewportExtEx(hdcMetafile
, &size
);
811 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
812 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
814 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
815 ok(hFontOld
== hFontCheck
&& hFontCheck
!= hFont
&& hFontCheck
!= hFont2
,
816 "Font not reverted with DC Restore\n");
818 ret
= RestoreDC(hdcMetafile
, -20);
819 ok(!ret
, "ret = %d\n", ret
);
820 ret
= RestoreDC(hdcMetafile
, 20);
821 ok(!ret
, "ret = %d\n", ret
);
823 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
824 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
826 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, savedc_emf_enum_proc
, 0, &rc
);
827 ok( ret
== 1, "EnumEnhMetaFile rets %d\n", ret
);
829 ret
= DeleteObject(hFont
);
830 ok( ret
, "DeleteObject error %d\n", GetLastError());
831 ret
= DeleteObject(hFont2
);
832 ok( ret
, "DeleteObject error %d\n", GetLastError());
833 ret
= DeleteEnhMetaFile(hMetafile
);
834 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
835 ret
= ReleaseDC(hwnd
, hdcDisplay
);
836 ok( ret
, "ReleaseDC error %d\n", GetLastError());
840 static void test_mf_SaveDC(void)
847 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
849 hdcMetafile
= CreateMetaFileA(NULL
);
850 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
852 ret
= SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
853 ok (ret
, "SetMapMode should not fail\n");
855 /* Need to write something to the emf, otherwise Windows won't play it back */
856 LineTo(hdcMetafile
, 150, 150);
859 SetWindowOrgEx(hdcMetafile
, 0, 0, &pt
);
860 ok( pt
.x
== 5555 && pt
.y
== 5555, "wrong origin %d,%d\n", pt
.x
, pt
.y
);
862 SetViewportOrgEx(hdcMetafile
, 0, 0, &pt
);
863 ok( pt
.x
== 5555 && pt
.y
== 5555, "wrong origin %d,%d\n", pt
.x
, pt
.y
);
864 size
.cx
= size
.cy
= 5555;
865 SetWindowExtEx(hdcMetafile
, 110, 110, &size
);
866 ok( size
.cx
== 5555 && size
.cy
== 5555, "wrong size %d,%d\n", size
.cx
, size
.cy
);
867 size
.cx
= size
.cy
= 5555;
868 SetViewportExtEx(hdcMetafile
, 120, 120, &size
);
869 ok( size
.cx
== 5555 && size
.cy
== 5555, "wrong size %d,%d\n", size
.cx
, size
.cy
);
871 /* Force Win9x to update DC state */
872 SetPixelV(hdcMetafile
, 50, 50, 0);
874 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
875 todo_wine
ok (!ret
, "GetViewportOrgEx should fail\n");
876 ret
= GetViewportExtEx(hdcMetafile
, &size
);
877 todo_wine
ok (!ret
, "GetViewportExtEx should fail\n");
878 ret
= SaveDC(hdcMetafile
);
879 ok(ret
== 1, "ret = %d\n", ret
);
881 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
882 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
883 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
884 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
886 /* Force Win9x to update DC state */
887 SetPixelV(hdcMetafile
, 50, 50, 0);
889 ret
= SaveDC(hdcMetafile
);
890 ok(ret
== 1, "ret = %d\n", ret
);
892 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
893 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
894 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
895 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
897 /* Force Win9x to update DC state */
898 SetPixelV(hdcMetafile
, 50, 50, 0);
899 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
900 SetBkColor( hdcMetafile
, 0 );
902 ret
= SaveDC(hdcMetafile
);
903 ok(ret
== 1, "ret = %d\n", ret
);
905 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
906 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
907 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
908 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
910 SetPolyFillMode( hdcMetafile
, WINDING
);
911 SetBkColor( hdcMetafile
, 0x123456 );
912 todo_wine
ok( !GetPolyFillMode( hdcMetafile
), "GetPolyFillMode succeeded\n" );
913 todo_wine
ok( GetBkColor( hdcMetafile
) == CLR_INVALID
, "GetBkColor succeeded\n" );
915 /* Force Win9x to update DC state */
916 SetPixelV(hdcMetafile
, 50, 50, 0);
918 ret
= RestoreDC(hdcMetafile
, -1);
919 ok(ret
, "ret = %d\n", ret
);
921 ret
= SaveDC(hdcMetafile
);
922 ok(ret
== 1, "ret = %d\n", ret
);
924 ret
= RestoreDC(hdcMetafile
, 1);
925 ok(ret
, "ret = %d\n", ret
);
927 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
928 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
929 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
930 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
932 /* Force Win9x to update DC state */
933 SetPixelV(hdcMetafile
, 50, 50, 0);
935 ret
= SaveDC(hdcMetafile
);
936 ok(ret
== 1, "ret = %d\n", ret
);
938 ret
= SaveDC(hdcMetafile
);
939 ok(ret
== 1, "ret = %d\n", ret
);
941 memset(&orig_lf
, 0, sizeof(orig_lf
));
942 orig_lf
.lfCharSet
= ANSI_CHARSET
;
943 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
944 orig_lf
.lfWeight
= FW_DONTCARE
;
945 orig_lf
.lfHeight
= 7;
946 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
947 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
948 hFont
= CreateFontIndirectA(&orig_lf
);
949 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
951 hFontOld
= SelectObject(hdcMetafile
, hFont
);
953 hFont2
= CreateFontIndirectA(&orig_lf
);
954 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
955 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
956 ok(hFontCheck
== hFont
, "Font not selected\n");
958 /* Force Win9x to update DC state */
959 SetPixelV(hdcMetafile
, 50, 50, 0);
961 ret
= RestoreDC(hdcMetafile
, 1);
962 ok(ret
, "ret = %d\n", ret
);
964 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
965 ok(hFontOld
!= hFontCheck
&& hFontCheck
== hFont2
, "Font incorrectly reverted with DC Restore\n");
967 /* restore level is ignored */
968 ret
= RestoreDC(hdcMetafile
, -20);
969 ok(ret
, "ret = %d\n", ret
);
970 ret
= RestoreDC(hdcMetafile
, 20);
971 ok(ret
, "ret = %d\n", ret
);
972 ret
= RestoreDC(hdcMetafile
, 0);
973 ok(ret
, "ret = %d\n", ret
);
975 hMetafile
= CloseMetaFile(hdcMetafile
);
976 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
978 ret
= DeleteMetaFile(hMetafile
);
979 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
980 ret
= DeleteObject(hFont
);
981 ok( ret
, "DeleteObject error %d\n", GetLastError());
982 ret
= DeleteObject(hFont2
);
983 ok( ret
, "DeleteObject error %d\n", GetLastError());
987 /* Win-format metafile (mfdrv) tests */
988 /* These tests compare the generated metafiles byte-by-byte */
989 /* with the nominal results. */
991 /* Maximum size of sample metafiles in bytes. */
992 #define MF_BUFSIZE 512
994 /* 8x8 bitmap data for a pattern brush */
995 static const unsigned char SAMPLE_PATTERN_BRUSH
[] = {
996 0x01, 0x00, 0x02, 0x00,
997 0x03, 0x00, 0x04, 0x00,
998 0x05, 0x00, 0x06, 0x00,
999 0x07, 0x00, 0x08, 0x00
1002 /* Sample metafiles to be compared to the outputs of the
1006 static const unsigned char MF_BLANK_BITS
[] = {
1007 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1012 static const unsigned char MF_GRAPHICS_BITS
[] = {
1013 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1016 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1017 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1018 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1019 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1020 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1021 0x00, 0x00, 0x00, 0x00
1024 static const unsigned char MF_PATTERN_BRUSH_BITS
[] = {
1025 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1026 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1028 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1029 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1030 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1031 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1032 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1033 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1035 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1036 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1037 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1038 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1039 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1043 static const unsigned char MF_DCBRUSH_BITS
[] =
1045 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1046 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1047 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1048 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1049 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1050 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1053 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1054 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1055 0x00, 0x00, 0x00, 0x00
1058 static const unsigned char MF_TEXTOUT_ON_PATH_BITS
[] =
1060 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1062 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1063 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1064 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1065 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1069 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS
[] =
1071 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1076 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1077 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1078 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1081 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1084 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1085 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1086 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1088 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1089 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1090 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1091 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1094 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1095 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1096 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1097 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1098 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1099 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1101 0x14, 0x00, 0x00, 0x00
1104 static const unsigned char EMF_TEXTOUT_OUTLINE_ON_PATH_BITS
[] =
1106 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff,
1111 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1112 0x0c, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1113 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1115 0x90, 0x06, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00,
1116 0x51, 0x02, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00,
1117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1118 0x00, 0x00, 0x00, 0x00, 0x1a, 0x0b, 0x09, 0x00,
1119 0xf0, 0xa6, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00,
1120 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x80,
1121 0x3b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1122 0x54, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1125 0x01, 0x00, 0x00, 0x00, 0xc3, 0x30, 0x0d, 0x42,
1126 0xcf, 0xf3, 0x0c, 0x42, 0x0b, 0x00, 0x00, 0x00,
1127 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1128 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1131 0x54, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00,
1132 0x73, 0x00, 0x74, 0x00, 0x03, 0x00, 0x00, 0x00,
1133 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1134 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1135 0x08, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1136 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x80,
1137 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1139 0x14, 0x00, 0x00, 0x00
1142 static const unsigned char MF_LINETO_BITS
[] = {
1143 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1144 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1145 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1146 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1150 static const unsigned char EMF_LINETO_BITS
[] = {
1151 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1155 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1156 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1157 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1158 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1161 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1164 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1165 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1166 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1167 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1168 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1169 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1170 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1171 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1172 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1173 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1174 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1175 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1176 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1177 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1178 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1179 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1180 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1181 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1182 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1183 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1184 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1185 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1186 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1188 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1189 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1192 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS
[] = {
1193 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1195 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1197 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1198 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1199 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1200 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1203 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1205 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1206 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1207 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1208 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1209 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1210 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1211 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1212 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1213 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1214 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1216 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1217 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1218 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1219 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1220 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1221 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1222 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1223 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1224 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1225 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1226 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1227 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1228 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1230 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1231 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1234 static const unsigned char EMF_LINETO_MM_TEXT_BITS
[] = {
1235 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1240 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1241 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1242 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1244 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1245 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1248 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1249 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1250 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1251 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1252 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1253 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1254 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1255 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1256 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1257 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1258 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1259 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1261 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1263 0x14, 0x00, 0x00, 0x00
1266 static const unsigned char EMF_BITBLT
[] =
1268 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1273 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1274 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1275 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1278 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1281 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1282 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1284 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1286 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1293 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1294 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1295 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1296 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1309 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1310 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1318 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1322 static const unsigned char EMF_DCBRUSH_BITS
[] =
1324 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1325 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1326 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1327 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1328 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1329 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1330 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1331 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1334 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1336 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1337 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1338 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1339 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1340 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1341 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1342 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1344 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1345 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1346 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1349 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1350 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1351 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1352 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1353 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1354 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1355 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1356 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1357 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1358 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1359 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1360 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1361 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1362 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1363 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1364 0x14, 0x00, 0x00, 0x00
1367 static const unsigned char EMF_BEZIER_BITS
[] =
1369 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1373 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1374 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1375 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1376 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1378 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1379 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1382 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1383 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1384 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1385 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1386 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1387 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1388 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1389 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1390 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1391 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1392 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1393 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1394 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1395 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1396 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1397 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1398 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1399 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1400 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1401 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1402 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1403 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1404 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1405 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1407 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1408 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1409 0x14, 0x00, 0x00, 0x00
1412 /* For debugging or dumping the raw metafiles produced by
1413 * new test functions.
1415 static INT CALLBACK
mf_enum_proc(HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
,
1416 INT nobj
, LPARAM param
)
1418 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1419 hdc
, mr
->rdFunction
, mr
->rdSize
, (void *)param
);
1423 /* For debugging or dumping the raw metafiles produced by
1424 * new test functions.
1427 static void dump_mf_bits (const HMETAFILE mf
, const char *desc
)
1429 BYTE buf
[MF_BUFSIZE
];
1432 if (!winetest_debug
) return;
1434 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1435 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1437 printf ("MetaFile %s has bits:\n{\n ", desc
);
1438 for (i
=0; i
<mfsize
; i
++)
1440 printf ("0x%02x", buf
[i
]);
1443 else if (i
% 8 == 7)
1451 /* Compare the metafile produced by a test function with the
1452 * expected raw metafile data in "bits".
1453 * Return value is 0 for a perfect match,
1454 * -1 if lengths aren't equal,
1455 * otherwise returns the number of non-matching bytes.
1458 static int compare_mf_bits (const HMETAFILE mf
, const unsigned char *bits
, UINT bsize
,
1461 unsigned char buf
[MF_BUFSIZE
];
1465 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1466 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1467 if (mfsize
< MF_BUFSIZE
)
1468 ok (mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n",
1469 desc
, mfsize
, bsize
);
1471 ok (bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1472 desc
, mfsize
, bsize
);
1473 if (mfsize
!= bsize
)
1477 for (i
=0; i
<bsize
; i
++)
1479 if (buf
[i
] != bits
[i
])
1482 ok (diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1483 desc
, mfsize
, bsize
, diff
);
1488 static int compare_mf_disk_bits(LPCSTR name
, const BYTE
*bits
, UINT bsize
, const char *desc
)
1490 unsigned char buf
[MF_BUFSIZE
];
1491 DWORD mfsize
, rd_size
, i
;
1496 hfile
= CreateFileA(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1497 assert(hfile
!= INVALID_HANDLE_VALUE
);
1499 mfsize
= GetFileSize(hfile
, NULL
);
1500 assert(mfsize
<= MF_BUFSIZE
);
1502 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &rd_size
, NULL
);
1503 ok( ret
&& rd_size
== mfsize
, "ReadFile: error %d\n", GetLastError());
1507 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n", desc
, mfsize
, bsize
);
1509 if (mfsize
!= bsize
)
1513 for (i
=0; i
<bsize
; i
++)
1515 if (buf
[i
] != bits
[i
])
1518 ok(diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1519 desc
, mfsize
, bsize
, diff
);
1524 /* For debugging or dumping the raw EMFs produced by
1525 * new test functions.
1527 static void dump_emf_bits(const HENHMETAFILE mf
, const char *desc
)
1529 BYTE buf
[MF_BUFSIZE
];
1532 if (!winetest_debug
) return;
1534 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1535 ok (mfsize
> 0, "%s: GetEnhMetaFileBits failed\n", desc
);
1537 printf("EMF %s has bits:\n{\n ", desc
);
1538 for (i
= 0; i
< mfsize
; i
++)
1540 printf ("0x%02x", buf
[i
]);
1543 else if (i
% 8 == 7)
1551 static void dump_emf_records(const HENHMETAFILE mf
, const char *desc
)
1554 BYTE buf
[MF_BUFSIZE
];
1555 UINT mfsize
, offset
;
1557 if (!winetest_debug
) return;
1559 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1560 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1562 printf("EMF %s has records:\n", desc
);
1566 while(offset
< mfsize
)
1568 EMR
*emr
= (EMR
*)(emf
+ offset
);
1569 printf("emr->iType %d, emr->nSize %u\n", emr
->iType
, emr
->nSize
);
1570 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1571 offset
+= emr
->nSize
;
1575 static void dump_emf_record(const ENHMETARECORD
*emr
, const char *desc
)
1580 if (!winetest_debug
) return;
1582 printf ("%s: EMF record %u has bits:\n{\n", desc
, emr
->iType
);
1583 buf
= (const BYTE
*)emr
;
1584 for (i
= 0; i
< emr
->nSize
; i
++)
1586 printf ("0x%02x", buf
[i
]);
1587 if (i
== emr
->nSize
- 1)
1589 else if (i
% 8 == 7)
1597 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW
*eto
)
1599 trace("rclBounds %d,%d - %d,%d\n", eto
->rclBounds
.left
, eto
->rclBounds
.top
,
1600 eto
->rclBounds
.right
, eto
->rclBounds
.bottom
);
1601 trace("iGraphicsMode %u\n", eto
->iGraphicsMode
);
1602 trace("exScale: %f\n", eto
->exScale
);
1603 trace("eyScale: %f\n", eto
->eyScale
);
1604 trace("emrtext.ptlReference %d,%d\n", eto
->emrtext
.ptlReference
.x
, eto
->emrtext
.ptlReference
.y
);
1605 trace("emrtext.nChars %u\n", eto
->emrtext
.nChars
);
1606 trace("emrtext.offString %#x\n", eto
->emrtext
.offString
);
1607 trace("emrtext.fOptions %#x\n", eto
->emrtext
.fOptions
);
1608 trace("emrtext.rcl %d,%d - %d,%d\n", eto
->emrtext
.rcl
.left
, eto
->emrtext
.rcl
.top
,
1609 eto
->emrtext
.rcl
.right
, eto
->emrtext
.rcl
.bottom
);
1610 trace("emrtext.offDx %#x\n", eto
->emrtext
.offDx
);
1613 static BOOL
match_emf_record(const ENHMETARECORD
*emr1
, const ENHMETARECORD
*emr2
,
1614 const char *desc
, BOOL ignore_scaling
)
1618 ok(emr1
->iType
== emr2
->iType
, "%s: emr->iType %u != %u\n",
1619 desc
, emr1
->iType
, emr2
->iType
);
1621 ok(emr1
->nSize
== emr2
->nSize
, "%s: emr->nSize %u != %u\n",
1622 desc
, emr1
->nSize
, emr2
->nSize
);
1624 /* iType and nSize mismatches are fatal */
1625 if (emr1
->iType
!= emr2
->iType
|| emr1
->nSize
!= emr2
->nSize
) return FALSE
;
1627 /* contents of EMR_GDICOMMENT are not interesting */
1628 if (emr1
->iType
== EMR_GDICOMMENT
) return TRUE
;
1630 /* different Windows versions setup DC scaling differently when
1631 * converting an old style metafile to an EMF.
1633 if (ignore_scaling
&& (emr1
->iType
== EMR_SETWINDOWEXTEX
||
1634 emr1
->iType
== EMR_SETVIEWPORTEXTEX
))
1637 if (emr1
->iType
== EMR_EXTTEXTOUTW
|| emr1
->iType
== EMR_EXTTEXTOUTA
)
1639 EMREXTTEXTOUTW
*eto1
, *eto2
;
1641 eto1
= HeapAlloc(GetProcessHeap(), 0, emr1
->nSize
);
1642 memcpy(eto1
, emr1
, emr1
->nSize
);
1643 eto2
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1644 memcpy(eto2
, emr2
, emr2
->nSize
);
1646 /* different Windows versions setup DC scaling differently */
1647 eto1
->exScale
= eto1
->eyScale
= 0.0;
1648 eto2
->exScale
= eto2
->eyScale
= 0.0;
1650 diff
= memcmp(eto1
, eto2
, emr1
->nSize
);
1653 dump_EMREXTTEXTOUT(eto1
);
1654 dump_EMREXTTEXTOUT(eto2
);
1656 HeapFree(GetProcessHeap(), 0, eto1
);
1657 HeapFree(GetProcessHeap(), 0, eto2
);
1659 else if (emr1
->iType
== EMR_EXTSELECTCLIPRGN
&& !lstrcmpA(desc
, "emf_clipping"))
1661 /* We have to take care of NT4 differences here */
1662 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1665 ENHMETARECORD
*emr_nt4
;
1667 emr_nt4
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1668 memcpy(emr_nt4
, emr2
, emr2
->nSize
);
1669 /* Correct the nRgnSize field */
1670 emr_nt4
->dParm
[5] = sizeof(RECT
);
1672 diff
= memcmp(emr1
, emr_nt4
, emr1
->nSize
);
1674 win_skip("Catered for NT4 differences\n");
1676 HeapFree(GetProcessHeap(), 0, emr_nt4
);
1679 else if (emr1
->iType
== EMR_POLYBEZIERTO16
|| emr1
->iType
== EMR_POLYBEZIER16
)
1681 EMRPOLYBEZIER16
*eto1
, *eto2
;
1683 eto1
= (EMRPOLYBEZIER16
*)emr1
;
1684 eto2
= (EMRPOLYBEZIER16
*)emr2
;
1686 diff
= eto1
->cpts
!= eto2
->cpts
;
1688 diff
= memcmp(eto1
->apts
, eto2
->apts
, eto1
->cpts
* sizeof(POINTS
));
1690 else if (emr1
->iType
== EMR_POLYBEZIERTO
|| emr1
->iType
== EMR_POLYBEZIER
)
1692 EMRPOLYBEZIER
*eto1
, *eto2
;
1694 eto1
= (EMRPOLYBEZIER
*)emr1
;
1695 eto2
= (EMRPOLYBEZIER
*)emr2
;
1697 diff
= eto1
->cptl
!= eto2
->cptl
;
1699 diff
= memcmp(eto1
->aptl
, eto2
->aptl
, eto1
->cptl
* sizeof(POINTL
));
1702 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1704 ok(diff
== 0, "%s: contents of record %u don't match\n", desc
, emr1
->iType
);
1708 dump_emf_record(emr1
, "expected bits");
1709 dump_emf_record(emr2
, "actual bits");
1712 return diff
== 0; /* report all non-fatal record mismatches */
1715 /* Compare the EMF produced by a test function with the
1716 * expected raw EMF data in "bits".
1717 * Return value is 0 for a perfect match,
1718 * -1 if lengths aren't equal,
1719 * otherwise returns the number of non-matching bytes.
1721 static int compare_emf_bits(const HENHMETAFILE mf
, const unsigned char *bits
,
1722 UINT bsize
, const char *desc
,
1723 BOOL ignore_scaling
)
1725 unsigned char buf
[MF_BUFSIZE
];
1726 UINT mfsize
, offset1
, offset2
, diff_nt4
, diff_9x
;
1727 const ENHMETAHEADER
*emh1
, *emh2
;
1729 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1730 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1732 /* ENHMETAHEADER size could differ, depending on platform */
1733 diff_nt4
= sizeof(SIZEL
);
1734 diff_9x
= sizeof(SIZEL
) + 3 * sizeof(DWORD
);
1736 if (mfsize
< MF_BUFSIZE
)
1738 ok(mfsize
== bsize
||
1739 broken(mfsize
== bsize
- diff_nt4
) || /* NT4 */
1740 broken(mfsize
== bsize
- diff_9x
), /* Win9x/WinME */
1741 "%s: mfsize=%d, bsize=%d\n", desc
, mfsize
, bsize
);
1744 ok(bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1745 desc
, mfsize
, bsize
);
1747 /* basic things must match */
1748 emh1
= (const ENHMETAHEADER
*)bits
;
1749 emh2
= (const ENHMETAHEADER
*)buf
;
1750 ok(emh1
->iType
== EMR_HEADER
, "expected EMR_HEADER, got %u\n", emh1
->iType
);
1751 ok(emh1
->nSize
== sizeof(ENHMETAHEADER
), "expected sizeof(ENHMETAHEADER), got %u\n", emh1
->nSize
);
1752 ok(emh2
->nBytes
== mfsize
, "expected emh->nBytes %u, got %u\n", mfsize
, emh2
->nBytes
);
1753 ok(emh1
->dSignature
== ENHMETA_SIGNATURE
, "expected ENHMETA_SIGNATURE, got %u\n", emh1
->dSignature
);
1755 ok(emh1
->iType
== emh2
->iType
, "expected EMR_HEADER, got %u\n", emh2
->iType
);
1756 ok(emh1
->nSize
== emh2
->nSize
||
1757 broken(emh1
->nSize
- diff_nt4
== emh2
->nSize
) ||
1758 broken(emh1
->nSize
- diff_9x
== emh2
->nSize
),
1759 "expected nSize %u, got %u\n", emh1
->nSize
, emh2
->nSize
);
1760 ok(emh1
->dSignature
== emh2
->dSignature
, "expected dSignature %u, got %u\n", emh1
->dSignature
, emh2
->dSignature
);
1761 ok(emh1
->nBytes
== emh2
->nBytes
||
1762 broken(emh1
->nBytes
- diff_nt4
== emh2
->nBytes
) ||
1763 broken(emh1
->nBytes
- diff_9x
== emh2
->nBytes
),
1764 "expected nBytes %u, got %u\n", emh1
->nBytes
, emh2
->nBytes
);
1765 ok(emh1
->nRecords
== emh2
->nRecords
, "expected nRecords %u, got %u\n", emh1
->nRecords
, emh2
->nRecords
);
1767 offset1
= emh1
->nSize
;
1768 offset2
= emh2
->nSize
; /* Needed for Win9x/WinME/NT4 */
1769 while (offset1
< emh1
->nBytes
)
1771 const ENHMETARECORD
*emr1
= (const ENHMETARECORD
*)(bits
+ offset1
);
1772 const ENHMETARECORD
*emr2
= (const ENHMETARECORD
*)(buf
+ offset2
);
1774 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1775 desc
, emr1
->iType
, emr1
->nSize
, emr2
->iType
, emr2
->nSize
);
1777 if (!match_emf_record(emr1
, emr2
, desc
, ignore_scaling
)) return -1;
1779 /* We have already bailed out if iType or nSize don't match */
1780 offset1
+= emr1
->nSize
;
1781 offset2
+= emr2
->nSize
;
1787 /* tests blitting to an EMF */
1788 static void test_emf_BitBlt(void)
1790 HDC hdcDisplay
, hdcMetafile
, hdcBitmap
;
1791 HBITMAP hBitmap
, hOldBitmap
;
1792 HENHMETAFILE hMetafile
;
1794 BITMAPINFOHEADER bmih
=
1796 sizeof(BITMAPINFOHEADER
),
1797 BMP_DIM
,/* biWidth */
1798 BMP_DIM
,/* biHeight */
1800 24, /* biBitCount */
1801 BI_RGB
, /* biCompression */
1802 0, /* biXPelsPerMeter */
1803 0, /* biYPelsPerMeter */
1805 0, /* biClrImportant */
1810 hdcDisplay
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1811 ok( hdcDisplay
!= 0, "CreateDCA error %d\n", GetLastError() );
1813 hdcBitmap
= CreateCompatibleDC(hdcDisplay
);
1814 ok( hdcBitmap
!= 0, "CreateCompatibleDC failed\n" );
1815 bmih
.biXPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSX
), 100, 3937);
1816 bmih
.biYPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSY
), 100, 3937);
1817 hBitmap
= CreateDIBSection(hdcDisplay
, (const BITMAPINFO
*)&bmih
,
1818 DIB_RGB_COLORS
, &bits
, NULL
, 0);
1819 hOldBitmap
= SelectObject(hdcBitmap
, hBitmap
);
1821 hdcMetafile
= CreateEnhMetaFileA(hdcBitmap
, NULL
, NULL
, NULL
);
1822 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1824 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1825 ret
= BitBlt(hdcBitmap
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, BLACKNESS
);
1826 ok( ret
, "BitBlt(BLACKNESS) failed\n" );
1828 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, SRCCOPY
);
1829 ok( ret
, "BitBlt(SRCCOPY) failed\n" );
1830 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, WHITENESS
);
1831 ok( ret
, "BitBlt(WHITENESS) failed\n" );
1833 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1834 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1836 if(compare_emf_bits(hMetafile
, EMF_BITBLT
, sizeof(EMF_BITBLT
),
1837 "emf_BitBlt", FALSE
) != 0)
1839 dump_emf_bits(hMetafile
, "emf_BitBlt");
1840 dump_emf_records(hMetafile
, "emf_BitBlt");
1843 SelectObject(hdcBitmap
, hOldBitmap
);
1844 DeleteObject(hBitmap
);
1845 DeleteDC(hdcBitmap
);
1846 DeleteDC(hdcDisplay
);
1850 static void test_emf_DCBrush(void)
1853 HENHMETAFILE hMetafile
;
1859 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
1861 win_skip( "SetDCBrush/PenColor not supported\n" );
1865 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
1866 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1868 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
1869 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
1871 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
1872 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
1874 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
1875 ok( color
== 0xffffff, "SetDCBrushColor returned %x\n", color
);
1877 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
1878 ok( color
== 0, "SetDCPenColor returned %x\n", color
);
1880 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
1882 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
1883 ok( color
== 0x555555, "SetDCBrushColor returned %x\n", color
);
1885 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1886 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1888 if (compare_emf_bits (hMetafile
, EMF_DCBRUSH_BITS
, sizeof(EMF_DCBRUSH_BITS
),
1889 "emf_DC_Brush", FALSE
) != 0)
1891 dump_emf_bits(hMetafile
, "emf_DC_Brush");
1892 dump_emf_records(hMetafile
, "emf_DC_Brush");
1894 ret
= DeleteEnhMetaFile(hMetafile
);
1895 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
1896 ret
= DeleteObject(hBrush
);
1897 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1898 ret
= DeleteObject(hPen
);
1899 ok( ret
, "DeleteObject(HPEN) error %d\n", GetLastError());
1902 /* Test a blank metafile. May be used as a template for new tests. */
1904 static void test_mf_Blank(void)
1907 HMETAFILE hMetafile
;
1912 hdcMetafile
= CreateMetaFileA(NULL
);
1913 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1914 trace("hdcMetafile %p\n", hdcMetafile
);
1916 /* Tests on metafile initialization */
1917 caps
= GetDeviceCaps (hdcMetafile
, TECHNOLOGY
);
1918 ok (caps
== DT_METAFILE
,
1919 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps
);
1921 hMetafile
= CloseMetaFile(hdcMetafile
);
1922 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1923 type
= GetObjectType(hMetafile
);
1924 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1925 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1927 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1930 dump_mf_bits(hMetafile
, "mf_Blank");
1931 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1934 ret
= DeleteMetaFile(hMetafile
);
1935 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1938 static void test_CopyMetaFile(void)
1941 HMETAFILE hMetafile
, hmf_copy
;
1943 char temp_path
[MAX_PATH
];
1944 char mf_name
[MAX_PATH
];
1947 hdcMetafile
= CreateMetaFileA(NULL
);
1948 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1949 trace("hdcMetafile %p\n", hdcMetafile
);
1951 hMetafile
= CloseMetaFile(hdcMetafile
);
1952 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1953 type
= GetObjectType(hMetafile
);
1954 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1956 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1959 dump_mf_bits(hMetafile
, "mf_Blank");
1960 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1963 GetTempPathA(MAX_PATH
, temp_path
);
1964 GetTempFileNameA(temp_path
, "wmf", 0, mf_name
);
1966 hmf_copy
= CopyMetaFileA(hMetafile
, mf_name
);
1967 ok(hmf_copy
!= 0, "CopyMetaFile error %d\n", GetLastError());
1969 type
= GetObjectType(hmf_copy
);
1970 ok(type
== OBJ_METAFILE
, "CopyMetaFile created object with type %d\n", type
);
1972 ret
= DeleteMetaFile(hMetafile
);
1973 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1975 if (compare_mf_disk_bits(mf_name
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
), "mf_blank") != 0)
1977 dump_mf_bits(hmf_copy
, "mf_Blank");
1978 EnumMetaFile(0, hmf_copy
, mf_enum_proc
, 0);
1981 ret
= DeleteMetaFile(hmf_copy
);
1982 ok( ret
, "DeleteMetaFile(%p) error %d\n", hmf_copy
, GetLastError());
1984 DeleteFileA(mf_name
);
1987 static void test_SetMetaFileBits(void)
1995 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), MF_GRAPHICS_BITS
);
1996 trace("hmf %p\n", hmf
);
1997 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1998 type
= GetObjectType(hmf
);
1999 ok(type
== OBJ_METAFILE
, "SetMetaFileBitsEx created object with type %d\n", type
);
2001 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2003 dump_mf_bits(hmf
, "mf_Graphics");
2004 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2007 ret
= DeleteMetaFile(hmf
);
2008 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2010 /* NULL data crashes XP SP1 */
2011 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2013 /* Now with zero size */
2014 SetLastError(0xdeadbeef);
2015 hmf
= SetMetaFileBitsEx(0, MF_GRAPHICS_BITS
);
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 odd size */
2023 SetLastError(0xdeadbeef);
2024 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
) - 1, MF_GRAPHICS_BITS
);
2025 trace("hmf %p\n", hmf
);
2026 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2027 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2029 /* Now with zeroed out header fields */
2030 assert(sizeof(buf
) >= sizeof(MF_GRAPHICS_BITS
));
2031 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2032 mh
= (METAHEADER
*)buf
;
2033 /* corruption of any of the below fields leads to a failure */
2036 mh
->mtHeaderSize
= 0;
2037 SetLastError(0xdeadbeef);
2038 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2039 trace("hmf %p\n", hmf
);
2040 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2041 ok(GetLastError() == ERROR_INVALID_DATA
||
2042 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
2043 "wrong error %d\n", GetLastError());
2045 /* Now with corrupted mtSize field */
2046 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2047 mh
= (METAHEADER
*)buf
;
2048 /* corruption of mtSize doesn't lead to a failure */
2050 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2051 trace("hmf %p\n", hmf
);
2052 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2054 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2056 dump_mf_bits(hmf
, "mf_Graphics");
2057 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2060 ret
= DeleteMetaFile(hmf
);
2061 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2063 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2064 /* Now with zeroed out mtSize field */
2065 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2066 mh
= (METAHEADER
*)buf
;
2067 /* zeroing mtSize doesn't lead to a failure */
2069 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2070 trace("hmf %p\n", hmf
);
2071 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2073 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2075 dump_mf_bits(hmf
, "mf_Graphics");
2076 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2079 ret
= DeleteMetaFile(hmf
);
2080 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2084 /* Simple APIs from mfdrv/graphics.c
2087 static void test_mf_Graphics(void)
2090 HMETAFILE hMetafile
;
2094 hdcMetafile
= CreateMetaFileA(NULL
);
2095 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2096 trace("hdcMetafile %p\n", hdcMetafile
);
2098 ret
= MoveToEx(hdcMetafile
, 1, 1, NULL
);
2099 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2100 ret
= LineTo(hdcMetafile
, 2, 2);
2101 ok( ret
, "LineTo error %d.\n", GetLastError());
2102 ret
= MoveToEx(hdcMetafile
, 1, 1, &oldpoint
);
2103 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2105 /* oldpoint gets garbage under Win XP, so the following test would
2106 * work under Wine but fails under Windows:
2108 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2109 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2110 * oldpoint.x, oldpoint.y);
2113 ret
= Ellipse(hdcMetafile
, 0, 0, 2, 2);
2114 ok( ret
, "Ellipse error %d.\n", GetLastError());
2116 hMetafile
= CloseMetaFile(hdcMetafile
);
2117 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2118 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2120 if (compare_mf_bits (hMetafile
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
),
2121 "mf_Graphics") != 0)
2123 dump_mf_bits(hMetafile
, "mf_Graphics");
2124 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2127 ret
= DeleteMetaFile(hMetafile
);
2128 ok( ret
, "DeleteMetaFile(%p) error %d\n",
2129 hMetafile
, GetLastError());
2132 static void test_mf_PatternBrush(void)
2135 HMETAFILE hMetafile
;
2140 orig_lb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(LOGBRUSH
));
2142 orig_lb
->lbStyle
= BS_PATTERN
;
2143 orig_lb
->lbColor
= RGB(0, 0, 0);
2144 orig_lb
->lbHatch
= (ULONG_PTR
)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH
);
2145 ok((HBITMAP
)orig_lb
->lbHatch
!= NULL
, "CreateBitmap error %d.\n", GetLastError());
2147 hBrush
= CreateBrushIndirect (orig_lb
);
2148 ok(hBrush
!= 0, "CreateBrushIndirect error %d\n", GetLastError());
2150 hdcMetafile
= CreateMetaFileA(NULL
);
2151 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2152 trace("hdcMetafile %p\n", hdcMetafile
);
2154 hBrush
= SelectObject(hdcMetafile
, hBrush
);
2155 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2157 hMetafile
= CloseMetaFile(hdcMetafile
);
2158 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2159 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2161 if (compare_mf_bits (hMetafile
, MF_PATTERN_BRUSH_BITS
, sizeof(MF_PATTERN_BRUSH_BITS
),
2162 "mf_Pattern_Brush") != 0)
2164 dump_mf_bits(hMetafile
, "mf_Pattern_Brush");
2165 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2168 ret
= DeleteMetaFile(hMetafile
);
2169 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
2170 ret
= DeleteObject(hBrush
);
2171 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2172 ret
= DeleteObject((HBITMAP
)orig_lb
->lbHatch
);
2173 ok( ret
, "DeleteObject(HBITMAP) error %d\n",
2175 HeapFree (GetProcessHeap(), 0, orig_lb
);
2178 static void test_mf_DCBrush(void)
2181 HMETAFILE hMetafile
;
2187 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
2189 win_skip( "SetDCBrush/PenColor not supported\n" );
2193 hdcMetafile
= CreateMetaFileA(NULL
);
2194 ok( hdcMetafile
!= 0, "CreateMetaFileA failed\n" );
2196 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
2197 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2199 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
2200 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
2202 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
2203 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2205 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
2206 ok( color
== CLR_INVALID
, "SetDCPenColor returned %x\n", color
);
2208 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
2210 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
2211 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2213 hMetafile
= CloseMetaFile(hdcMetafile
);
2214 ok( hMetafile
!= 0, "CloseMetaFile failed\n" );
2216 if (compare_mf_bits(hMetafile
, MF_DCBRUSH_BITS
, sizeof(MF_DCBRUSH_BITS
), "mf_DCBrush") != 0)
2218 dump_mf_bits(hMetafile
, "mf_DCBrush");
2219 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2221 ret
= DeleteMetaFile(hMetafile
);
2222 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2225 static void test_mf_ExtTextOut_on_path(void)
2228 HMETAFILE hMetafile
;
2230 static const INT dx
[4] = { 3, 5, 8, 12 };
2232 hdcMetafile
= CreateMetaFileA(NULL
);
2233 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2234 trace("hdcMetafile %p\n", hdcMetafile
);
2236 ret
= BeginPath(hdcMetafile
);
2237 ok(!ret
, "BeginPath on metafile DC should fail\n");
2239 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2240 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2242 ret
= EndPath(hdcMetafile
);
2243 ok(!ret
, "EndPath on metafile DC should fail\n");
2245 hMetafile
= CloseMetaFile(hdcMetafile
);
2246 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2248 if (compare_mf_bits(hMetafile
, MF_TEXTOUT_ON_PATH_BITS
, sizeof(MF_TEXTOUT_ON_PATH_BITS
),
2249 "mf_TextOut_on_path") != 0)
2251 dump_mf_bits(hMetafile
, "mf_TextOut_on_path");
2252 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2255 ret
= DeleteMetaFile(hMetafile
);
2256 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2259 static void test_emf_ExtTextOut_on_path(void)
2262 HDC hdcDisplay
, hdcMetafile
;
2263 HENHMETAFILE hMetafile
;
2267 static const INT dx
[4] = { 3, 5, 8, 12 };
2269 /* Win9x doesn't play EMFs on invisible windows */
2270 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2271 0, 0, 200, 200, 0, 0, 0, NULL
);
2272 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2274 hdcDisplay
= GetDC(hwnd
);
2275 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
2277 /* with default font */
2278 ret
= BeginPath(hdcDisplay
);
2279 ok(ret
, "BeginPath error %d\n", GetLastError());
2281 ret
= ExtTextOutA(hdcDisplay
, 11, 22, 0, NULL
, "Test", 4, dx
);
2282 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2284 ret
= EndPath(hdcDisplay
);
2285 ok(ret
, "EndPath error %d\n", GetLastError());
2287 ret
= GetPath(hdcDisplay
, NULL
, NULL
, 0);
2288 ok(!ret
, "expected 0, got %d\n", ret
);
2290 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
2291 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2293 ret
= BeginPath(hdcMetafile
);
2294 ok(ret
, "BeginPath error %d\n", GetLastError());
2296 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2297 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2299 ret
= EndPath(hdcMetafile
);
2300 ok(ret
, "EndPath error %d\n", GetLastError());
2302 ret
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
2303 ok(!ret
, "expected 0, got %d\n", ret
);
2305 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2306 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2308 /* this doesn't succeed yet: EMF has correct size, all EMF records
2309 * are there, but their contents don't match for different reasons.
2311 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_ON_PATH_BITS
),
2312 "emf_TextOut_on_path", FALSE
) != 0)
2314 dump_emf_bits(hMetafile
, "emf_TextOut_on_path");
2315 dump_emf_records(hMetafile
, "emf_TextOut_on_path");
2318 ret
= DeleteEnhMetaFile(hMetafile
);
2319 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2321 /* with outline font */
2322 memset(&lf
, 0, sizeof(lf
));
2323 lf
.lfCharSet
= ANSI_CHARSET
;
2324 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
2325 lf
.lfWeight
= FW_DONTCARE
;
2327 lf
.lfQuality
= DEFAULT_QUALITY
;
2328 lstrcpyA(lf
.lfFaceName
, "Tahoma");
2329 hFont
= CreateFontIndirectA(&lf
);
2330 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
2331 hFont
= SelectObject(hdcDisplay
, hFont
);
2333 ret
= BeginPath(hdcDisplay
);
2334 ok(ret
, "BeginPath error %d\n", GetLastError());
2336 ret
= ExtTextOutA(hdcDisplay
, 11, 22, 0, NULL
, "Test", 4, dx
);
2337 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2339 ret
= EndPath(hdcDisplay
);
2340 ok(ret
, "EndPath error %d\n", GetLastError());
2342 ret
= GetPath(hdcDisplay
, NULL
, NULL
, 0);
2343 ok(ret
!= 0, "expected != 0\n");
2345 SelectObject(hdcDisplay
, hFont
);
2347 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
2348 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2350 hFont
= SelectObject(hdcMetafile
, hFont
);
2352 ret
= BeginPath(hdcMetafile
);
2353 ok(ret
, "BeginPath error %d\n", GetLastError());
2355 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2356 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2358 ret
= EndPath(hdcMetafile
);
2359 ok(ret
, "EndPath error %d\n", GetLastError());
2361 ret
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
2362 ok(!ret
, "expected 0, got %d\n", ret
);
2364 hFont
= SelectObject(hdcMetafile
, hFont
);
2365 DeleteObject(hFont
);
2367 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2368 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2370 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_OUTLINE_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_OUTLINE_ON_PATH_BITS
),
2371 "emf_TextOut_on_path", FALSE
) != 0)
2373 dump_emf_bits(hMetafile
, "emf_TextOut_outline_on_path");
2374 dump_emf_records(hMetafile
, "emf_TextOut_outline_on_path");
2377 ret
= DeleteEnhMetaFile(hMetafile
);
2378 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2380 ret
= ReleaseDC(hwnd
, hdcDisplay
);
2381 ok(ret
, "ReleaseDC error %d\n", GetLastError());
2382 DestroyWindow(hwnd
);
2385 static const unsigned char EMF_CLIPPING
[] =
2387 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2389 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2391 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2392 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2393 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2394 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2396 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2397 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2399 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2400 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2401 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2402 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2403 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2404 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2405 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2406 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2407 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2408 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2409 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2410 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2411 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2412 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2415 static void translate( POINT
*pt
, UINT count
, const XFORM
*xform
)
2419 FLOAT x
= (FLOAT
)pt
->x
;
2420 FLOAT y
= (FLOAT
)pt
->y
;
2421 pt
->x
= (LONG
)floor( x
* xform
->eM11
+ y
* xform
->eM21
+ xform
->eDx
+ 0.5 );
2422 pt
->y
= (LONG
)floor( x
* xform
->eM12
+ y
* xform
->eM22
+ xform
->eDy
+ 0.5 );
2427 /* Compare rectangles allowing rounding errors */
2428 static BOOL
is_equal_rect(const RECT
*rc1
, const RECT
*rc2
)
2430 return abs(rc1
->left
- rc2
->left
) <= 1 &&
2431 abs(rc1
->top
- rc2
->top
) <= 1 &&
2432 abs(rc1
->right
- rc2
->right
) <= 1 &&
2433 abs(rc1
->bottom
- rc2
->bottom
) <= 1;
2436 static int CALLBACK
clip_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2437 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
2439 if (emr
->iType
== EMR_EXTSELECTCLIPRGN
)
2441 const EMREXTSELECTCLIPRGN
*clip
= (const EMREXTSELECTCLIPRGN
*)emr
;
2445 char buf
[sizeof(RGNDATAHEADER
) + sizeof(RECT
)];
2447 const union _rgn
*rgn1
;
2449 RECT rect
, rc_transformed
;
2450 const RECT
*rc
= (const RECT
*)param
;
2456 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2457 clip
->cbRgnData
, clip
->iMode
);
2459 ok(clip
->iMode
== RGN_COPY
, "expected RGN_COPY, got %u\n", clip
->iMode
);
2460 ok(clip
->cbRgnData
>= sizeof(RGNDATAHEADER
) + sizeof(RECT
),
2461 "too small data block: %u bytes\n", clip
->cbRgnData
);
2462 if (clip
->cbRgnData
< sizeof(RGNDATAHEADER
) + sizeof(RECT
))
2465 rgn1
= (const union _rgn
*)clip
->RgnData
;
2467 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2468 rgn1
->data
.rdh
.dwSize
, rgn1
->data
.rdh
.iType
,
2469 rgn1
->data
.rdh
.nCount
, rgn1
->data
.rdh
.nRgnSize
,
2470 rgn1
->data
.rdh
.rcBound
.left
, rgn1
->data
.rdh
.rcBound
.top
,
2471 rgn1
->data
.rdh
.rcBound
.right
, rgn1
->data
.rdh
.rcBound
.bottom
);
2473 ok(EqualRect(&rgn1
->data
.rdh
.rcBound
, rc
), "rects don't match\n");
2475 rect
= *(const RECT
*)rgn1
->data
.Buffer
;
2476 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2477 ok(EqualRect(&rect
, rc
), "rects don't match\n");
2479 ok(rgn1
->data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn1
->data
.rdh
.dwSize
);
2480 ok(rgn1
->data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn1
->data
.rdh
.iType
);
2481 ok(rgn1
->data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn1
->data
.rdh
.nCount
);
2482 ok(rgn1
->data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2483 broken(rgn1
->data
.rdh
.nRgnSize
== 168), /* NT4 */
2484 "expected sizeof(RECT), got %u\n", rgn1
->data
.rdh
.nRgnSize
);
2486 hrgn
= CreateRectRgn(0, 0, 0, 0);
2488 memset(&xform
, 0, sizeof(xform
));
2489 SetLastError(0xdeadbeef);
2490 ret
= GetWorldTransform(hdc
, &xform
);
2491 is_win9x
= !ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
;
2493 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
2495 trace("xform.eM11 %f, xform.eM22 %f\n", xform
.eM11
, xform
.eM22
);
2497 ret
= GetClipRgn(hdc
, hrgn
);
2498 ok(ret
== 0, "GetClipRgn returned %d, expected 0\n", ret
);
2500 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
2502 ret
= GetClipRgn(hdc
, hrgn
);
2503 ok(ret
== 1, "GetClipRgn returned %d, expected 1\n", ret
);
2505 /* Win9x returns empty clipping region */
2506 if (is_win9x
) return 1;
2508 ret
= GetRegionData(hrgn
, 0, NULL
);
2509 ok(ret
== sizeof(rgn2
.data
.rdh
) + sizeof(RECT
), "expected sizeof(rgn), got %u\n", ret
);
2511 ret
= GetRegionData(hrgn
, sizeof(rgn2
), &rgn2
.data
);
2512 ok(ret
== sizeof(rgn2
), "expected sizeof(rgn2), got %u\n", ret
);
2514 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2515 rgn2
.data
.rdh
.dwSize
, rgn2
.data
.rdh
.iType
,
2516 rgn2
.data
.rdh
.nCount
, rgn2
.data
.rdh
.nRgnSize
,
2517 rgn2
.data
.rdh
.rcBound
.left
, rgn2
.data
.rdh
.rcBound
.top
,
2518 rgn2
.data
.rdh
.rcBound
.right
, rgn2
.data
.rdh
.rcBound
.bottom
);
2520 rect
= rgn2
.data
.rdh
.rcBound
;
2521 rc_transformed
= *rc
;
2522 translate((POINT
*)&rc_transformed
, 2, &xform
);
2523 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2524 rc_transformed
.right
, rc_transformed
.bottom
);
2525 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2527 rect
= *(const RECT
*)rgn2
.data
.Buffer
;
2528 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2529 rc_transformed
= *rc
;
2530 translate((POINT
*)&rc_transformed
, 2, &xform
);
2531 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2532 rc_transformed
.right
, rc_transformed
.bottom
);
2533 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2535 ok(rgn2
.data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn2
.data
.rdh
.dwSize
);
2536 ok(rgn2
.data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn2
.data
.rdh
.iType
);
2537 ok(rgn2
.data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn2
.data
.rdh
.nCount
);
2538 ok(rgn2
.data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2539 broken(rgn2
.data
.rdh
.nRgnSize
== 168), /* NT4 */
2540 "expected sizeof(RECT), got %u\n", rgn2
.data
.rdh
.nRgnSize
);
2547 static void test_emf_clipping(void)
2549 static const RECT rc
= { 0, 0, 100, 100 };
2550 RECT rc_clip
= { 100, 100, 1024, 1024 };
2556 RECT rc_res
, rc_sclip
;
2558 SetLastError(0xdeadbeef);
2559 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2560 ok(hdc
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2562 /* Need to write something to the emf, otherwise Windows won't play it back */
2565 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2566 ret
= SelectClipRgn(hdc
, hrgn
);
2567 ok(ret
== SIMPLEREGION
, "expected SIMPLEREGION, got %d\n", ret
);
2569 SetLastError(0xdeadbeef);
2570 hemf
= CloseEnhMetaFile(hdc
);
2571 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2573 if (compare_emf_bits(hemf
, EMF_CLIPPING
, sizeof(EMF_CLIPPING
),
2574 "emf_clipping", FALSE
) != 0)
2576 dump_emf_bits(hemf
, "emf_clipping");
2577 dump_emf_records(hemf
, "emf_clipping");
2582 /* Win9x doesn't play EMFs on invisible windows */
2583 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2584 0, 0, 200, 200, 0, 0, 0, NULL
);
2585 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2589 ret
= EnumEnhMetaFile(hdc
, hemf
, clip_emf_enum_proc
, &rc_clip
, &rc
);
2590 ok(ret
, "EnumEnhMetaFile error %d\n", GetLastError());
2592 DeleteEnhMetaFile(hemf
);
2593 ReleaseDC(hwnd
, hdc
);
2594 DestroyWindow(hwnd
);
2596 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2598 SetRect(&rc_sclip
, 100, 100, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2599 hrgn
= CreateRectRgn(rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
);
2600 SelectClipRgn(hdc
, hrgn
);
2601 SetRect(&rc_res
, -1, -1, -1, -1);
2602 ret
= GetClipBox(hdc
, &rc_res
);
2603 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2604 ok(EqualRect(&rc_res
, &rc_sclip
),
2605 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2606 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2607 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2609 OffsetRect(&rc_sclip
, -100, -100);
2610 ret
= OffsetClipRgn(hdc
, -100, -100);
2611 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2612 SetRect(&rc_res
, -1, -1, -1, -1);
2613 ret
= GetClipBox(hdc
, &rc_res
);
2614 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2615 ok(EqualRect(&rc_res
, &rc_sclip
),
2616 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2617 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2618 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2620 ret
= IntersectClipRect(hdc
, 0, 0, 100, 100);
2621 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2622 if (ret
== COMPLEXREGION
)
2624 /* XP returns COMPLEXREGION although region contains only 1 rect */
2625 ret
= GetClipRgn(hdc
, hrgn
);
2626 ok(ret
== 1, "expected 1, got %d\n", ret
);
2627 ret
= rgn_rect_count(hrgn
);
2628 ok(ret
== 1, "expected 1, got %d\n", ret
);
2630 SetRect(&rc_res
, -1, -1, -1, -1);
2631 ret
= GetClipBox(hdc
, &rc_res
);
2632 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2633 ok(EqualRect(&rc_res
, &rc
),
2634 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2635 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
2636 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2638 SetRect(&rc_sclip
, 0, 0, 100, 50);
2639 ret
= ExcludeClipRect(hdc
, 0, 50, 100, 100);
2640 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2641 if (ret
== COMPLEXREGION
)
2643 /* XP returns COMPLEXREGION although region contains only 1 rect */
2644 ret
= GetClipRgn(hdc
, hrgn
);
2645 ok(ret
== 1, "expected 1, got %d\n", ret
);
2646 ret
= rgn_rect_count(hrgn
);
2647 ok(ret
== 1, "expected 1, got %d\n", ret
);
2649 SetRect(&rc_res
, -1, -1, -1, -1);
2650 ret
= GetClipBox(hdc
, &rc_res
);
2651 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2652 ok(EqualRect(&rc_res
, &rc_sclip
),
2653 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2654 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2655 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2657 hemf
= CloseEnhMetaFile(hdc
);
2658 DeleteEnhMetaFile(hemf
);
2662 static const unsigned char MF_CLIP_BITS
[] = {
2664 0x01, 0x00, /* mtType */
2665 0x09, 0x00, /* mtHeaderSize */
2666 0x00, 0x03, /* mtVersion */
2667 0x32, 0x00, 0x00, 0x00, /* mtSize */
2668 0x01, 0x00, /* mtNoObjects */
2669 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2670 0x00, 0x00, /* reserved */
2672 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2673 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2674 0xff, 0x06, /* META_CREATEREGION */
2675 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2676 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2677 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2678 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2681 /* METARECORD for SelectObject */
2682 0x04, 0x00, 0x00, 0x00,
2683 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2687 0x04, 0x00, 0x00, 0x00,
2688 0xf0, 0x01, /* META_DELETEOBJECT */
2691 /* METARECORD for MoveTo(1,0x30) */
2692 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2693 0x14, 0x02, /* META_MOVETO */
2697 /* METARECORD for LineTo(0x20, 0x30) */
2698 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2699 0x13, 0x02, /* META_LINETO */
2704 0x03, 0x00, 0x00, 0x00,
2708 static int clip_mf_enum_proc_seen_selectclipregion
;
2709 static int clip_mf_enum_proc_seen_selectobject
;
2711 static int CALLBACK
clip_mf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2712 METARECORD
*mr
, int n_objs
, LPARAM param
)
2714 switch (mr
->rdFunction
) {
2715 case META_SELECTCLIPREGION
:
2716 clip_mf_enum_proc_seen_selectclipregion
++;
2718 case META_SELECTOBJECT
:
2719 clip_mf_enum_proc_seen_selectobject
++;
2725 static void test_mf_clipping(void)
2727 /* left top right bottom */
2728 static RECT rc_clip
= { 0x11, 0x22, 0x33, 0x44 };
2735 SetLastError(0xdeadbeef);
2736 hdc
= CreateMetaFileA(NULL
);
2737 ok(hdc
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2739 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2740 ret
= SelectClipRgn(hdc
, hrgn
);
2741 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2742 ok(ret
== NULLREGION
, "expected NULLREGION, got %d\n", ret
);
2744 /* Draw a line that starts off left of the clip region and ends inside it */
2745 MoveToEx(hdc
, 0x1, 0x30, NULL
);
2746 LineTo(hdc
, 0x20, 0x30);
2748 SetLastError(0xdeadbeef);
2749 hmf
= CloseMetaFile(hdc
);
2750 ok(hmf
!= 0, "CloseMetaFile error %d\n", GetLastError());
2752 if (compare_mf_bits(hmf
, MF_CLIP_BITS
, sizeof(MF_CLIP_BITS
),
2753 "mf_clipping") != 0)
2755 dump_mf_bits(hmf
, "mf_clipping");
2760 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2761 0, 0, 200, 200, 0, 0, 0, NULL
);
2762 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2766 ret
= EnumMetaFile(hdc
, hmf
, clip_mf_enum_proc
, (LPARAM
)&rc_clip
);
2767 ok(ret
, "EnumMetaFile error %d\n", GetLastError());
2769 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2770 ok(clip_mf_enum_proc_seen_selectclipregion
== 0,
2771 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion
);
2772 ok(clip_mf_enum_proc_seen_selectobject
== 1,
2773 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject
);
2775 DeleteMetaFile(hmf
);
2776 ReleaseDC(hwnd
, hdc
);
2777 DestroyWindow(hwnd
);
2780 static INT CALLBACK
EmfEnumProc(HDC hdc
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
, INT nObj
, LPARAM lpData
)
2782 LPMETAFILEPICT lpMFP
= (LPMETAFILEPICT
)lpData
;
2783 POINT mapping
[2] = { { 0, 0 }, { 10, 10 } };
2784 /* When using MM_TEXT Win9x does not update the mapping mode
2785 * until a record is played which actually outputs something */
2786 PlayEnhMetaFileRecord(hdc
, lpHTable
, lpEMFR
, nObj
);
2787 LPtoDP(hdc
, mapping
, 2);
2788 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2789 lpEMFR
->iType
, lpEMFR
->nSize
,
2790 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
);
2792 if (lpEMFR
->iType
== EMR_LINETO
)
2795 if (!lpMFP
|| lpMFP
->mm
== MM_TEXT
)
2799 x1
= (INT
)floor(10 * 100.0 / LINE_X
+ 0.5);
2800 y1
= (INT
)floor(10 * 100.0 / LINE_Y
+ 0.5);
2804 ok(lpMFP
->mm
== MM_ANISOTROPIC
, "mm=%d\n", lpMFP
->mm
);
2806 x0
= MulDiv(0, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2807 y0
= MulDiv(0, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2808 x1
= MulDiv(10, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2809 y1
= MulDiv(10, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2811 ok(mapping
[0].x
== x0
&& mapping
[0].y
== y0
&& mapping
[1].x
== x1
&& mapping
[1].y
== y1
,
2812 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2813 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
,
2819 static HENHMETAFILE
create_converted_emf(const METAFILEPICT
*mfp
)
2828 hdcMf
= CreateMetaFileA(NULL
);
2829 ok(hdcMf
!= NULL
, "CreateMetaFile failed with error %d\n", GetLastError());
2830 ret
= LineTo(hdcMf
, (INT
)LINE_X
, (INT
)LINE_Y
);
2831 ok(ret
, "LineTo failed with error %d\n", GetLastError());
2832 hmf
= CloseMetaFile(hdcMf
);
2833 ok(hmf
!= NULL
, "CloseMetaFile failed with error %d\n", GetLastError());
2835 if (compare_mf_bits (hmf
, MF_LINETO_BITS
, sizeof(MF_LINETO_BITS
), "mf_LineTo") != 0)
2837 dump_mf_bits(hmf
, "mf_LineTo");
2838 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2841 size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
2842 ok(size
, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2843 pBits
= HeapAlloc(GetProcessHeap(), 0, size
);
2844 GetMetaFileBitsEx(hmf
, size
, pBits
);
2845 DeleteMetaFile(hmf
);
2846 hemf
= SetWinMetaFileBits(size
, pBits
, NULL
, mfp
);
2847 HeapFree(GetProcessHeap(), 0, pBits
);
2851 static void test_mf_conversions(void)
2853 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2855 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2858 RECT rect
= { 0, 0, 100, 100 };
2859 mfp
.mm
= MM_ANISOTROPIC
;
2863 hemf
= create_converted_emf(&mfp
);
2865 if (compare_emf_bits(hemf
, EMF_LINETO_MM_ANISOTROPIC_BITS
, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS
),
2866 "emf_LineTo MM_ANISOTROPIC", TRUE
) != 0)
2868 dump_emf_bits(hemf
, "emf_LineTo MM_ANISOTROPIC");
2869 dump_emf_records(hemf
, "emf_LineTo MM_ANISOTROPIC");
2872 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2874 DeleteEnhMetaFile(hemf
);
2875 DeleteDC(hdcOffscreen
);
2878 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2880 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2883 RECT rect
= { 0, 0, 100, 100 };
2888 hemf
= create_converted_emf(&mfp
);
2890 if (compare_emf_bits(hemf
, EMF_LINETO_MM_TEXT_BITS
, sizeof(EMF_LINETO_MM_TEXT_BITS
),
2891 "emf_LineTo MM_TEXT", TRUE
) != 0)
2893 dump_emf_bits(hemf
, "emf_LineTo MM_TEXT");
2894 dump_emf_records(hemf
, "emf_LineTo MM_TEXT");
2897 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2899 DeleteEnhMetaFile(hemf
);
2900 DeleteDC(hdcOffscreen
);
2903 trace("Testing MF->EMF conversion (NULL mfp)\n");
2905 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2907 RECT rect
= { 0, 0, 100, 100 };
2908 hemf
= create_converted_emf(NULL
);
2910 if (compare_emf_bits(hemf
, EMF_LINETO_BITS
, sizeof(EMF_LINETO_BITS
),
2911 "emf_LineTo NULL", TRUE
) != 0)
2913 dump_emf_bits(hemf
, "emf_LineTo NULL");
2914 dump_emf_records(hemf
, "emf_LineTo NULL");
2917 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, NULL
, &rect
);
2919 DeleteEnhMetaFile(hemf
);
2920 DeleteDC(hdcOffscreen
);
2924 static BOOL
getConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
2925 LONG mm
, LONG xExt
, LONG yExt
,
2926 RECTL
* rclBounds
, RECTL
* rclFrame
)
2929 METAFILEPICT
* mfpPtr
= NULL
;
2931 ENHMETAHEADER header
;
2942 emf
= SetWinMetaFileBits(buffer_size
, buffer
, NULL
, mfpPtr
);
2943 ok(emf
!= NULL
, "SetWinMetaFileBits failed\n");
2944 if (!emf
) return FALSE
;
2945 res
= GetEnhMetaFileHeader(emf
, sizeof(header
), &header
);
2946 ok(res
!= 0, "GetEnhMetaHeader failed\n");
2947 DeleteEnhMetaFile(emf
);
2948 if (!res
) return FALSE
;
2950 *rclBounds
= header
.rclBounds
;
2951 *rclFrame
= header
.rclFrame
;
2955 static void checkConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
2956 LONG mm
, LONG xExt
, LONG yExt
,
2957 RECTL
* rclBoundsExpected
, RECTL
* rclFrameExpected
)
2959 RECTL rclBounds
, rclFrame
;
2961 if (getConvertedFrameAndBounds(buffer_size
, buffer
, mfpIsNull
, mm
, xExt
, yExt
, &rclBounds
, &rclFrame
))
2968 msg
= "mfp == NULL";
2972 const char * mm_str
;
2975 case MM_ANISOTROPIC
: mm_str
= "MM_ANISOTROPIC"; break;
2976 case MM_ISOTROPIC
: mm_str
= "MM_ISOTROPIC"; break;
2977 default: mm_str
= "Unexpected";
2979 sprintf(buf
, "mm=%s, xExt=%d, yExt=%d", mm_str
, xExt
, yExt
);
2983 ok(rclBounds
.left
== rclBoundsExpected
->left
, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected
->left
, rclBounds
.left
, msg
);
2984 ok(rclBounds
.top
== rclBoundsExpected
->top
, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected
->top
, rclBounds
.top
, msg
);
2985 ok(rclBounds
.right
== rclBoundsExpected
->right
, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected
->right
, rclBounds
.right
, msg
);
2986 ok(rclBounds
.bottom
== rclBoundsExpected
->bottom
, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected
->bottom
, rclBounds
.bottom
, msg
);
2987 ok(rclFrame
.left
== rclFrameExpected
->left
, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected
->left
, rclFrame
.left
, msg
);
2988 ok(rclFrame
.top
== rclFrameExpected
->top
, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected
->top
, rclFrame
.top
, msg
);
2989 ok(rclFrame
.right
== rclFrameExpected
->right
, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected
->right
, rclFrame
.right
, msg
);
2990 ok(rclFrame
.bottom
== rclFrameExpected
->bottom
, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected
->bottom
, rclFrame
.bottom
, msg
);
2994 static void test_SetWinMetaFileBits(void)
3002 RECTL rclBoundsAnisotropic
, rclFrameAnisotropic
;
3003 RECTL rclBoundsIsotropic
, rclFrameIsotropic
;
3004 RECTL rclBounds
, rclFrame
;
3008 wmfDC
= CreateMetaFileA(NULL
);
3009 ok(wmfDC
!= NULL
, "CreateMetaFile failed\n");
3012 SetWindowExtEx(wmfDC
, 100, 100, NULL
);
3013 rect
.left
= rect
.top
= 0;
3014 rect
.right
= rect
.bottom
= 50;
3015 FillRect(wmfDC
, &rect
, GetStockObject(BLACK_BRUSH
));
3016 wmf
= CloseMetaFile(wmfDC
);
3017 ok(wmf
!= NULL
, "Metafile creation failed\n");
3020 buffer_size
= GetMetaFileBitsEx(wmf
, 0, NULL
);
3021 ok(buffer_size
!= 0, "GetMetaFileBitsEx failed\n");
3022 if (buffer_size
== 0)
3024 DeleteMetaFile(wmf
);
3028 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
);
3029 ok(buffer
!= NULL
, "HeapAlloc failed\n");
3032 DeleteMetaFile(wmf
);
3036 res
= GetMetaFileBitsEx(wmf
, buffer_size
, buffer
);
3037 ok(res
== buffer_size
, "GetMetaFileBitsEx failed\n");
3038 DeleteMetaFile(wmf
);
3039 if (res
!= buffer_size
)
3041 HeapFree(GetProcessHeap(), 0, buffer
);
3045 /* Get the reference bounds and frame */
3046 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3047 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3049 ok(rclBoundsAnisotropic
.left
== 0 && rclBoundsAnisotropic
.top
== 0 &&
3050 rclBoundsIsotropic
.left
== 0 && rclBoundsIsotropic
.top
== 0,
3051 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3053 ok(rclBoundsAnisotropic
.right
>= rclBoundsIsotropic
.right
, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3054 ok(rclBoundsAnisotropic
.bottom
>= rclBoundsIsotropic
.bottom
, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3055 diffx
= rclBoundsIsotropic
.right
- rclBoundsIsotropic
.bottom
;
3056 if (diffx
< 0) diffx
= -diffx
;
3057 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3059 dc
= CreateCompatibleDC(NULL
);
3061 /* Allow 1 mm difference (rounding errors) */
3062 diffx
= rclBoundsAnisotropic
.right
- GetDeviceCaps(dc
, HORZRES
) / 2;
3063 diffy
= rclBoundsAnisotropic
.bottom
- GetDeviceCaps(dc
, VERTRES
) / 2;
3064 if (diffx
< 0) diffx
= -diffx
;
3065 if (diffy
< 0) diffy
= -diffy
;
3068 ok(diffx
<= 1 && diffy
<= 1,
3069 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3070 GetDeviceCaps(dc
, HORZRES
) / 2, GetDeviceCaps(dc
, VERTRES
) / 2, rclBoundsAnisotropic
.right
, rclBoundsAnisotropic
.bottom
);
3073 /* Allow 1 mm difference (rounding errors) */
3074 diffx
= rclFrameAnisotropic
.right
/ 100 - GetDeviceCaps(dc
, HORZSIZE
) / 2;
3075 diffy
= rclFrameAnisotropic
.bottom
/ 100 - GetDeviceCaps(dc
, VERTSIZE
) / 2;
3076 if (diffx
< 0) diffx
= -diffx
;
3077 if (diffy
< 0) diffy
= -diffy
;
3080 ok(diffx
<= 1 && diffy
<= 1,
3081 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3082 GetDeviceCaps(dc
, HORZSIZE
) / 2, GetDeviceCaps(dc
, VERTSIZE
) / 2, rclFrameAnisotropic
.right
/ 100, rclFrameAnisotropic
.bottom
/ 100);
3086 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3087 checkConvertedFrameAndBounds(buffer_size
, buffer
, TRUE
, 0, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3089 /* If xExt or yExt is zero or negative, the whole device surface is used */
3090 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3091 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3092 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3093 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3094 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3095 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3096 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3097 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3098 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3099 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3100 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3101 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3103 /* MSDN says that negative xExt and yExt values specify a ratio.
3104 Check that this is wrong and the whole device surface is used */
3105 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -1000, -100, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3106 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -1000, -100, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3108 /* Ordinary conversions */
3110 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3112 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3113 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3114 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0 && rclBounds
.right
> rclBounds
.bottom
,
3115 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3118 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3120 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3121 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3122 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0,
3123 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3125 /* Wine has a rounding error */
3126 diffx
= rclBounds
.right
- rclBounds
.bottom
;
3127 if (diffx
< 0) diffx
= -diffx
;
3128 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3131 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_HIMETRIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3133 ok(rclFrame
.right
- rclFrame
.left
!= 30000 && rclFrame
.bottom
- rclFrame
.top
!= 20000,
3134 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3137 HeapFree(GetProcessHeap(), 0, buffer
);
3140 static BOOL
near_match(int x
, int y
)
3142 int epsilon
= min(abs(x
), abs(y
));
3144 epsilon
= max(epsilon
/100, 2);
3146 if(x
< y
- epsilon
|| x
> y
+ epsilon
) return FALSE
;
3150 static void getwinmetafilebits(UINT mode
, int scale
, RECT
*rc
)
3153 HDC display_dc
, emf_dc
;
3154 ENHMETAHEADER
*enh_header
;
3155 UINT size
, emf_size
, i
;
3158 METAHEADER
*mh
= NULL
;
3160 INT horz_res
, vert_res
, horz_size
, vert_size
;
3161 INT curve_caps
, line_caps
, poly_caps
;
3163 display_dc
= GetDC(NULL
);
3164 ok(display_dc
!= NULL
, "display_dc is NULL\n");
3166 horz_res
= GetDeviceCaps(display_dc
, HORZRES
);
3167 vert_res
= GetDeviceCaps(display_dc
, VERTRES
);
3168 horz_size
= GetDeviceCaps(display_dc
, HORZSIZE
);
3169 vert_size
= GetDeviceCaps(display_dc
, VERTSIZE
);
3171 emf_dc
= CreateEnhMetaFileA(display_dc
, NULL
, rc
, NULL
);
3172 ok(emf_dc
!= NULL
, "emf_dc is NULL\n");
3174 curve_caps
= GetDeviceCaps(emf_dc
, CURVECAPS
);
3175 ok(curve_caps
== 511, "expect 511 got %d\n", curve_caps
);
3177 line_caps
= GetDeviceCaps(emf_dc
, LINECAPS
);
3178 ok(line_caps
== 254, "expect 254 got %d\n", line_caps
);
3180 poly_caps
= GetDeviceCaps(emf_dc
, POLYGONALCAPS
);
3181 ok(poly_caps
== 255, "expect 511 got %d\n", poly_caps
);
3183 for(i
= 0; i
< 3000; i
++) /* This is enough to take emf_size > 0xffff */
3184 Rectangle(emf_dc
, 0, 0, 1000, 20);
3185 emf
= CloseEnhMetaFile(emf_dc
);
3186 ok(emf
!= NULL
, "emf is NULL\n");
3188 emf_size
= GetEnhMetaFileBits(emf
, 0, NULL
);
3189 enh_header
= HeapAlloc(GetProcessHeap(), 0, emf_size
);
3190 emf_size
= GetEnhMetaFileBits(emf
, emf_size
, (BYTE
*)enh_header
);
3191 DeleteEnhMetaFile(emf
);
3192 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3193 have different resolutions */
3194 enh_header
->szlDevice
.cx
*= scale
;
3195 emf
= SetEnhMetaFileBits(emf_size
, (BYTE
*)enh_header
);
3196 ok(emf
!= NULL
, "emf is NULL\n");
3197 ok(EqualRect((RECT
*)&enh_header
->rclFrame
, rc
), "Frame rectangles differ\n");
3199 size
= GetWinMetaFileBits(emf
, 0, NULL
, mode
, display_dc
);
3201 broken(size
== 0), /* some versions of winxp fail for some reason */
3202 "GetWinMetaFileBits returns 0\n");
3204 mh
= HeapAlloc(GetProcessHeap(), 0, size
);
3205 GetWinMetaFileBits(emf
, size
, (BYTE
*)mh
, mode
, display_dc
);
3207 for(i
= 0; i
< size
/ 2; i
++) check
+= ((WORD
*)mh
)[i
];
3208 ok(check
== 0, "check %04x\n", check
);
3210 rec
= (METARECORD
*)(mh
+ 1);
3212 while(rec
->rdSize
&& rec
->rdFunction
)
3214 const DWORD chunk_size
= 0x2000;
3215 DWORD mfcomment_chunks
= (emf_size
+ chunk_size
- 1) / chunk_size
;
3217 if(rec_num
< mfcomment_chunks
)
3219 DWORD this_chunk_size
= chunk_size
;
3221 if(rec_num
== mfcomment_chunks
- 1)
3222 this_chunk_size
= emf_size
- rec_num
* chunk_size
;
3224 ok(rec
->rdSize
== (this_chunk_size
+ 44) / 2, "%04x: got %04x expected %04x\n", rec_num
, rec
->rdSize
, (this_chunk_size
+ 44) / 2);
3225 ok(rec
->rdFunction
== META_ESCAPE
, "%04x: got %04x\n", rec_num
, rec
->rdFunction
);
3226 if(rec
->rdSize
< (this_chunk_size
+ 44) / 2) break;
3227 ok(rec
->rdParm
[0] == MFCOMMENT
, "got %04x\n", rec
->rdParm
[0]);
3228 ok(rec
->rdParm
[1] == this_chunk_size
+ 34, "got %04x %x\n", rec
->rdParm
[1], emf_size
+ 34);
3229 ok(rec
->rdParm
[2] == 0x4d57, "got %04x\n", rec
->rdParm
[2]); /* WMFC */
3230 ok(rec
->rdParm
[3] == 0x4346, "got %04x\n", rec
->rdParm
[3]); /* " */
3231 ok(rec
->rdParm
[4] == 1, "got %04x\n", rec
->rdParm
[4]);
3232 ok(rec
->rdParm
[5] == 0, "got %04x\n", rec
->rdParm
[5]);
3233 ok(rec
->rdParm
[6] == 0, "got %04x\n", rec
->rdParm
[6]);
3234 ok(rec
->rdParm
[7] == 1, "got %04x\n", rec
->rdParm
[7]);
3235 /* parm[8] is the checksum, tested above */
3236 if(rec_num
> 0) ok(rec
->rdParm
[8] == 0, "got %04x\n", rec
->rdParm
[8]);
3237 ok(rec
->rdParm
[9] == 0, "got %04x\n", rec
->rdParm
[9]);
3238 ok(rec
->rdParm
[10] == 0, "got %04x\n", rec
->rdParm
[10]);
3239 ok(rec
->rdParm
[11] == mfcomment_chunks
, "got %04x\n", rec
->rdParm
[11]); /* num chunks */
3240 ok(rec
->rdParm
[12] == 0, "got %04x\n", rec
->rdParm
[12]);
3241 ok(rec
->rdParm
[13] == this_chunk_size
, "got %04x expected %04x\n", rec
->rdParm
[13], this_chunk_size
);
3242 ok(rec
->rdParm
[14] == 0, "got %04x\n", rec
->rdParm
[14]);
3243 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 */
3244 ok(*(DWORD
*)(rec
->rdParm
+ 17) == emf_size
, "got %08x emf_size %08x\n", *(DWORD
*)(rec
->rdParm
+ 17), emf_size
);
3245 ok(!memcmp(rec
->rdParm
+ 19, (char*)enh_header
+ rec_num
* chunk_size
, this_chunk_size
), "bits mismatch\n");
3248 else if(rec_num
== mfcomment_chunks
)
3250 ok(rec
->rdFunction
== META_SETMAPMODE
, "got %04x\n", rec
->rdFunction
);
3251 ok(rec
->rdParm
[0] == mode
, "got %04x\n", rec
->rdParm
[0]);
3253 else if(rec_num
== mfcomment_chunks
+ 1)
3256 ok(rec
->rdFunction
== META_SETWINDOWORG
, "got %04x\n", rec
->rdFunction
);
3261 case MM_ANISOTROPIC
:
3262 pt
.y
= MulDiv(rc
->top
, vert_res
, vert_size
* 100) + 1;
3263 pt
.x
= MulDiv(rc
->left
, horz_res
, horz_size
* 100);
3266 pt
.y
= MulDiv(-rc
->top
, 1, 10) + 1;
3267 pt
.x
= MulDiv( rc
->left
, 1, 10);
3270 pt
.y
= -rc
->top
+ 1;
3271 pt
.x
= (rc
->left
>= 0) ? rc
->left
: rc
->left
+ 1; /* strange but true */
3274 pt
.y
= MulDiv(-rc
->top
, 10, 254) + 1;
3275 pt
.x
= MulDiv( rc
->left
, 10, 254);
3278 pt
.y
= MulDiv(-rc
->top
, 100, 254) + 1;
3279 pt
.x
= MulDiv( rc
->left
, 100, 254);
3282 pt
.y
= MulDiv(-rc
->top
, 72 * 20, 2540) + 1;
3283 pt
.x
= MulDiv( rc
->left
, 72 * 20, 2540);
3288 ok(near_match((short)rec
->rdParm
[0], pt
.y
), "got %d expect %d\n", (short)rec
->rdParm
[0], pt
.y
);
3289 ok(near_match((short)rec
->rdParm
[1], pt
.x
), "got %d expect %d\n", (short)rec
->rdParm
[1], pt
.x
);
3291 if(rec_num
== mfcomment_chunks
+ 2)
3293 ok(rec
->rdFunction
== META_SETWINDOWEXT
, "got %04x\n", rec
->rdFunction
);
3294 ok(near_match((short)rec
->rdParm
[0], MulDiv(rc
->bottom
- rc
->top
, vert_res
, vert_size
* 100)),
3295 "got %d\n", (short)rec
->rdParm
[0]);
3296 ok(near_match((short)rec
->rdParm
[1], MulDiv(rc
->right
- rc
->left
, horz_res
, horz_size
* 100)),
3297 "got %d\n", (short)rec
->rdParm
[1]);
3301 rec
= (METARECORD
*)((WORD
*)rec
+ rec
->rdSize
);
3305 HeapFree(GetProcessHeap(), 0, mh
);
3306 HeapFree(GetProcessHeap(), 0, enh_header
);
3307 DeleteEnhMetaFile(emf
);
3309 ReleaseDC(NULL
, display_dc
);
3312 static void test_GetWinMetaFileBits(void)
3317 { 1000, 2000, 3000, 6000},
3318 {-1000, 2000, 3000, 6000},
3319 { 1000, -2000, 3000, 6000},
3320 { 1005, 2005, 3000, 6000},
3321 {-1005, -2005, 3000, 6000},
3322 {-1005, -2010, 3000, 6000},
3323 {-1005, 2010, 3000, 6000},
3329 for(mode
= MM_MIN
; mode
<= MM_MAX
; mode
++)
3332 for(rc
= frames
; rc
->right
- rc
->left
> 0; rc
++)
3334 getwinmetafilebits(mode
, 1, rc
);
3335 getwinmetafilebits(mode
, 2, rc
);
3340 static BOOL (WINAPI
*pGdiIsMetaPrintDC
)(HDC
);
3341 static BOOL (WINAPI
*pGdiIsMetaFileDC
)(HDC
);
3342 static BOOL (WINAPI
*pGdiIsPlayMetafileDC
)(HDC
);
3344 static void test_gdiis(void)
3346 RECT rect
= {0,0,100,100};
3347 HDC hdc
, hemfDC
, hmfDC
;
3351 /* resolve all the functions */
3352 hgdi32
= GetModuleHandleA("gdi32.dll");
3353 pGdiIsMetaPrintDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaPrintDC");
3354 pGdiIsMetaFileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaFileDC");
3355 pGdiIsPlayMetafileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsPlayMetafileDC");
3357 if(!pGdiIsMetaPrintDC
|| !pGdiIsMetaFileDC
|| !pGdiIsPlayMetafileDC
)
3359 win_skip("Needed GdiIs* functions are not available\n");
3363 /* try with nothing */
3364 ok(!pGdiIsMetaPrintDC(NULL
), "ismetaprint with NULL parameter\n");
3365 ok(!pGdiIsMetaFileDC(NULL
), "ismetafile with NULL parameter\n");
3366 ok(!pGdiIsPlayMetafileDC(NULL
), "isplaymetafile with NULL parameter\n");
3368 /* try with a metafile */
3369 hmfDC
= CreateMetaFileA(NULL
);
3370 ok(!pGdiIsMetaPrintDC(hmfDC
), "ismetaprint on metafile\n");
3371 ok(pGdiIsMetaFileDC(hmfDC
), "ismetafile on metafile\n");
3372 ok(!pGdiIsPlayMetafileDC(hmfDC
), "isplaymetafile on metafile\n");
3373 DeleteMetaFile(CloseMetaFile(hmfDC
));
3375 /* try with an enhanced metafile */
3377 hemfDC
= CreateEnhMetaFileW(hdc
, NULL
, &rect
, NULL
);
3378 ok(hemfDC
!= NULL
, "failed to create emf\n");
3380 ok(!pGdiIsMetaPrintDC(hemfDC
), "ismetaprint on emf\n");
3381 ok(pGdiIsMetaFileDC(hemfDC
), "ismetafile on emf\n");
3382 ok(!pGdiIsPlayMetafileDC(hemfDC
), "isplaymetafile on emf\n");
3384 hemf
= CloseEnhMetaFile(hemfDC
);
3385 ok(hemf
!= NULL
, "failed to close EMF\n");
3386 DeleteEnhMetaFile(hemf
);
3387 ReleaseDC(NULL
,hdc
);
3390 static void test_SetEnhMetaFileBits(void)
3396 memset(data
, 0xAA, sizeof(data
));
3397 SetLastError(0xdeadbeef);
3398 hemf
= SetEnhMetaFileBits(sizeof(data
), data
);
3399 ok(!hemf
, "SetEnhMetaFileBits should fail\n");
3400 ok(GetLastError() == ERROR_INVALID_DATA
||
3401 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x, WinMe */
3402 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3404 emh
= (ENHMETAHEADER
*)data
;
3405 memset(emh
, 0, sizeof(*emh
));
3407 emh
->iType
= EMR_HEADER
;
3408 emh
->nSize
= sizeof(*emh
);
3409 emh
->dSignature
= ENHMETA_SIGNATURE
;
3410 /* emh->nVersion = 0x10000; XP doesn't care about version */
3411 emh
->nBytes
= sizeof(*emh
);
3412 /* emh->nRecords = 1; XP doesn't care about records */
3413 emh
->nHandles
= 1; /* XP refuses to load a EMF if nHandles == 0 */
3415 SetLastError(0xdeadbeef);
3416 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3417 ok(hemf
!= 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3418 DeleteEnhMetaFile(hemf
);
3420 /* XP refuses to load unaligned EMF */
3422 SetLastError(0xdeadbeef);
3423 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3425 broken(hemf
!= NULL
), /* Win9x, WinMe */
3426 "SetEnhMetaFileBits should fail\n");
3427 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3428 DeleteEnhMetaFile(hemf
);
3430 emh
->dSignature
= 0;
3432 SetLastError(0xdeadbeef);
3433 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3435 broken(hemf
!= NULL
), /* Win9x, WinMe */
3436 "SetEnhMetaFileBits should fail\n");
3437 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3438 DeleteEnhMetaFile(hemf
);
3441 static void test_emf_polybezier(void)
3448 SetLastError(0xdeadbeef);
3449 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3450 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3452 pts
[0].x
= pts
[0].y
= 10;
3453 pts
[1].x
= pts
[1].y
= 20;
3454 pts
[2].x
= pts
[2].y
= 15;
3455 pts
[3].x
= pts
[3].y
= 25;
3456 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO16 */
3457 ok( ret
, "PolyBezierTo failed\n" );
3458 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER16 */
3459 ok( ret
, "PolyBezier failed\n" );
3461 pts
[0].x
= pts
[0].y
= 32769;
3462 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER */
3463 ok( ret
, "PolyBezier failed\n" );
3464 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO */
3465 ok( ret
, "PolyBezierTo failed\n" );
3467 hemf
= CloseEnhMetaFile(hdcMetafile
);
3468 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3470 if(compare_emf_bits(hemf
, EMF_BEZIER_BITS
, sizeof(EMF_BEZIER_BITS
),
3471 "emf_Bezier", FALSE
) != 0)
3473 dump_emf_bits(hemf
, "emf_Bezier");
3474 dump_emf_records(hemf
, "emf_Bezier");
3477 DeleteEnhMetaFile(hemf
);
3480 static const unsigned char EMF_PATH_BITS
[] =
3482 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3484 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3486 0xe6, 0xff, 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff,
3487 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3488 0xf8, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3489 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3491 0x80, 0x07, 0x00, 0x00, 0xd3, 0x03, 0x00, 0x00,
3492 0xfc, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
3493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3494 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
3495 0xd3, 0xf3, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3496 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3497 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3498 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3499 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3500 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3501 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3502 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3503 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3504 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3505 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3506 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3507 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3508 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3509 0x13, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3510 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3511 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3512 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3515 static void test_emf_GetPath(void)
3522 SetLastError(0xdeadbeef);
3523 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3524 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3526 BeginPath(hdcMetafile
);
3527 ret
= MoveToEx(hdcMetafile
, 50, 50, NULL
);
3528 ok( ret
, "MoveToEx error %d.\n", GetLastError());
3529 ret
= LineTo(hdcMetafile
, 50, 150);
3530 ok( ret
, "LineTo error %d.\n", GetLastError());
3531 ret
= LineTo(hdcMetafile
, 150, 150);
3532 ok( ret
, "LineTo error %d.\n", GetLastError());
3533 ret
= LineTo(hdcMetafile
, 150, 50);
3534 ok( ret
, "LineTo error %d.\n", GetLastError());
3535 ret
= LineTo(hdcMetafile
, 50, 50);
3536 ok( ret
, "LineTo error %d.\n", GetLastError());
3537 Rectangle(hdcMetafile
, 10, 10, 20, 20);
3538 EndPath(hdcMetafile
);
3540 size
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
3541 ok( size
== 9, "GetPath returned %d.\n", size
);
3543 hemf
= CloseEnhMetaFile(hdcMetafile
);
3544 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3546 if (compare_emf_bits(hemf
, EMF_PATH_BITS
, sizeof(EMF_PATH_BITS
), "test_emf_GetPath", FALSE
) != 0)
3548 dump_emf_bits(hemf
, "test_emf_GetPath");
3549 dump_emf_records(hemf
, "test_emf_GetPath");
3552 DeleteEnhMetaFile(hemf
);
3555 START_TEST(metafile
)
3557 init_function_pointers();
3559 /* For enhanced metafiles (enhmfdrv) */
3561 test_ExtTextOutScale();
3565 test_emf_ExtTextOut_on_path();
3566 test_emf_clipping();
3567 test_emf_polybezier();
3570 /* For win-format metafiles (mfdrv) */
3574 test_mf_PatternBrush();
3576 test_CopyMetaFile();
3577 test_SetMetaFileBits();
3578 test_mf_ExtTextOut_on_path();
3581 /* For metafile conversions */
3582 test_mf_conversions();
3583 test_SetWinMetaFileBits();
3584 test_GetWinMetaFileBits();
3587 test_SetEnhMetaFileBits();