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 ok(!emr_ExtTextOutW
->rclBounds
.left
, "emr_ExtTextOutW->rclBounds.left = %d\n",
152 emr_ExtTextOutW
->rclBounds
.left
);
153 ok(emr_ExtTextOutW
->rclBounds
.right
!= -1, "emr_ExtTextOutW->rclBounds.right = %d\n",
154 emr_ExtTextOutW
->rclBounds
.right
);
155 ok(emr_ExtTextOutW
->rclBounds
.bottom
!= -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n",
156 emr_ExtTextOutW
->rclBounds
.bottom
);
158 for(i
= 0; i
< emr_ExtTextOutW
->emrtext
.nChars
; i
++)
160 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
161 n_record
, i
, dx
[i
], orig_dx
[i
]);
164 emr_processed
= TRUE
;
175 static void test_ExtTextOut(void)
178 HDC hdcDisplay
, hdcMetafile
;
179 HENHMETAFILE hMetafile
;
181 static const char text
[] = "Simple text to test ExtTextOut on metafiles";
183 static const RECT rc
= { 0, 0, 100, 100 };
186 assert(sizeof(dx
)/sizeof(dx
[0]) >= lstrlenA(text
));
188 /* Win9x doesn't play EMFs on invisible windows */
189 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
190 0, 0, 200, 200, 0, 0, 0, NULL
);
191 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
193 hdcDisplay
= GetDC(hwnd
);
194 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
196 trace("hdcDisplay %p\n", hdcDisplay
);
198 SetMapMode(hdcDisplay
, MM_TEXT
);
200 memset(&orig_lf
, 0, sizeof(orig_lf
));
202 orig_lf
.lfCharSet
= ANSI_CHARSET
;
203 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
204 orig_lf
.lfWeight
= FW_DONTCARE
;
205 orig_lf
.lfHeight
= 7;
206 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
207 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
208 hFont
= CreateFontIndirectA(&orig_lf
);
209 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
211 hFont
= SelectObject(hdcDisplay
, hFont
);
213 len
= lstrlenA(text
);
214 for (i
= 0; i
< len
; i
++)
216 ret
= GetCharWidthA(hdcDisplay
, text
[i
], text
[i
], &dx
[i
]);
217 ok( ret
, "GetCharWidthA error %d\n", GetLastError());
219 hFont
= SelectObject(hdcDisplay
, hFont
);
221 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
222 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
224 trace("hdcMetafile %p\n", hdcMetafile
);
226 ok(GetDeviceCaps(hdcMetafile
, TECHNOLOGY
) == DT_RASDISPLAY
,
227 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
229 hFont
= SelectObject(hdcMetafile
, hFont
);
231 /* 1. pass NULL lpDx */
232 ret
= ExtTextOutA(hdcMetafile
, 0, 0, 0, &rc
, text
, lstrlenA(text
), NULL
);
233 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
235 /* 2. pass custom lpDx */
236 ret
= ExtTextOutA(hdcMetafile
, 0, 20, 0, &rc
, text
, lstrlenA(text
), dx
);
237 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
239 /* 3. pass NULL lprc */
240 ret
= ExtTextOutA(hdcMetafile
, 0, 40, 0, NULL
, text
, lstrlenA(text
), NULL
);
241 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
243 /* 4. test with unmatched BeginPath/EndPath calls */
244 ret
= BeginPath(hdcMetafile
);
245 ok( ret
, "BeginPath error %d\n", GetLastError());
246 ret
= BeginPath(hdcMetafile
);
247 ok( ret
, "BeginPath error %d\n", GetLastError());
248 ret
= EndPath(hdcMetafile
);
249 ok( ret
, "BeginPath error %d\n", GetLastError());
250 ret
= ExtTextOutA(hdcMetafile
, 0, 60, 0, NULL
, text
, lstrlenA(text
), NULL
);
251 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
253 hFont
= SelectObject(hdcMetafile
, hFont
);
254 ret
= DeleteObject(hFont
);
255 ok( ret
, "DeleteObject error %d\n", GetLastError());
257 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
258 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
260 ok(!GetObjectType(hdcMetafile
), "CloseEnhMetaFile has to destroy metafile hdc\n");
262 ret
= PlayEnhMetaFile(hdcDisplay
, hMetafile
, &rc
);
263 ok( ret
, "PlayEnhMetaFile error %d\n", GetLastError());
265 SetTextAlign(hdcDisplay
, TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
);
266 SetBkColor(hdcDisplay
, RGB(0xff, 0, 0));
267 SetTextColor(hdcDisplay
, RGB(0, 0xff, 0));
268 SetROP2(hdcDisplay
, R2_NOT
);
269 SetArcDirection(hdcDisplay
, AD_CLOCKWISE
);
270 SetPolyFillMode(hdcDisplay
, WINDING
);
271 SetStretchBltMode(hdcDisplay
, HALFTONE
);
273 if(pSetRelAbs
) pSetRelAbs(hdcDisplay
, RELATIVE
);
274 SetBkMode(hdcDisplay
, OPAQUE
);
276 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, &rc
);
277 ok( ret
, "EnumEnhMetaFile error %d\n", GetLastError());
279 ok( GetTextAlign(hdcDisplay
) == (TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
),
280 "text align %08x\n", GetTextAlign(hdcDisplay
));
281 ok( GetBkColor(hdcDisplay
) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay
));
282 ok( GetTextColor(hdcDisplay
) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay
));
283 ok( GetROP2(hdcDisplay
) == R2_NOT
, "rop2 %d\n", GetROP2(hdcDisplay
));
284 ok( GetArcDirection(hdcDisplay
) == AD_CLOCKWISE
, "arc dir %d\n", GetArcDirection(hdcDisplay
));
285 ok( GetPolyFillMode(hdcDisplay
) == WINDING
, "poly fill %d\n", GetPolyFillMode(hdcDisplay
));
286 ok( GetStretchBltMode(hdcDisplay
) == HALFTONE
, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay
));
288 ok(emr_processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
290 ok(!EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
291 "A valid hdc has to require a valid rc\n");
293 ok(EnumEnhMetaFile(NULL
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
294 "A null hdc does not require a valid rc\n");
296 ret
= DeleteEnhMetaFile(hMetafile
);
297 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
298 ret
= ReleaseDC(hwnd
, hdcDisplay
);
299 ok( ret
, "ReleaseDC error %d\n", GetLastError());
303 struct eto_scale_test_record
312 static int CALLBACK
eto_scale_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
313 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
315 struct eto_scale_test_record
*test
= (struct eto_scale_test_record
*)param
;
317 if (emr
->iType
== EMR_EXTTEXTOUTW
)
319 const EMREXTTEXTOUTW
*pExtTextOutW
= (const EMREXTTEXTOUTW
*)emr
;
320 ok(fabs(test
->ex_scale
- pExtTextOutW
->exScale
) < 0.001,
321 "Got exScale %f, expected %f\n", pExtTextOutW
->exScale
, test
->ex_scale
);
322 ok(fabs(test
->ey_scale
- pExtTextOutW
->eyScale
) < 0.001,
323 "Got eyScale %f, expected %f\n", pExtTextOutW
->eyScale
, test
->ey_scale
);
324 test
->processed
= TRUE
;
330 static void test_ExtTextOutScale(void)
332 const RECT rc
= { 0, 0, 100, 100 };
333 const WCHAR str
[] = {'a',0 };
334 struct eto_scale_test_record test
;
335 HDC hdcDisplay
, hdcMetafile
;
336 HENHMETAFILE hMetafile
;
338 SIZE wndext
, vportext
;
339 int horzSize
, vertSize
, horzRes
, vertRes
;
343 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
344 0, 0, 200, 200, 0, 0, 0, NULL
);
345 ok(hwnd
!= 0, "CreateWindowExA failed\n");
347 hdcDisplay
= GetDC(hwnd
);
348 ok(hdcDisplay
!= 0, "GetDC failed\n");
350 horzSize
= GetDeviceCaps(hdcDisplay
, HORZSIZE
);
351 horzRes
= GetDeviceCaps(hdcDisplay
, HORZRES
);
352 vertSize
= GetDeviceCaps(hdcDisplay
, VERTSIZE
);
353 vertRes
= GetDeviceCaps(hdcDisplay
, VERTRES
);
354 ok(horzSize
&& horzRes
&& vertSize
&& vertRes
, "GetDeviceCaps failed\n");
356 for (i
= 0; i
< 16; i
++)
358 test
.graphics_mode
= i
/ 8 + 1;
359 test
.map_mode
= i
% 8 + 1;
361 ret
= SetGraphicsMode(hdcDisplay
, test
.graphics_mode
);
362 ok(ret
, "SetGraphicsMode failed\n");
363 ret
= SetMapMode(hdcDisplay
, test
.map_mode
);
364 ok(ret
, "SetMapMode failed\n");
366 if ((test
.map_mode
== MM_ISOTROPIC
) || (test
.map_mode
== MM_ANISOTROPIC
))
368 ret
= SetWindowExtEx(hdcDisplay
, 1, 1, NULL
);
369 ok(ret
, "SetWindowExtEx failed\n");
370 ret
= SetViewportExtEx(hdcDisplay
, -20, -10, NULL
);
371 ok(ret
, "SetViewportExtEx failed\n");
374 ret
= GetViewportExtEx(hdcDisplay
, &vportext
);
375 ok(ret
, "GetViewportExtEx failed\n");
376 ret
= GetWindowExtEx(hdcDisplay
, &wndext
);
377 ok(ret
, "GetWindowExtEx failed\n");
379 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
380 test
.graphics_mode
, test
.map_mode
,
381 wndext
.cx
, wndext
.cy
, vportext
.cx
, vportext
.cy
,
382 horzSize
, horzRes
, vertSize
, vertRes
);
384 if (test
.graphics_mode
== GM_COMPATIBLE
)
386 test
.ex_scale
= 100.0 * ((FLOAT
)horzSize
/ (FLOAT
)horzRes
) /
387 ((FLOAT
)wndext
.cx
/ (FLOAT
)vportext
.cx
);
388 test
.ey_scale
= 100.0 * ((FLOAT
)vertSize
/ (FLOAT
)vertRes
) /
389 ((FLOAT
)wndext
.cy
/ (FLOAT
)vportext
.cy
);
397 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
398 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n");
400 ret
= SetGraphicsMode(hdcMetafile
, test
.graphics_mode
);
401 ok(ret
, "SetGraphicsMode failed\n");
402 ret
= SetMapMode(hdcMetafile
, test
.map_mode
);
403 ok(ret
, "SetMapMode failed\n");
405 if ((test
.map_mode
== MM_ISOTROPIC
) || (test
.map_mode
== MM_ANISOTROPIC
))
407 ret
= SetWindowExtEx(hdcMetafile
, 1, 1, NULL
);
408 ok(ret
, "SetWindowExtEx failed\n");
409 ret
= SetViewportExtEx(hdcMetafile
, -20, -10, NULL
);
410 ok(ret
, "SetViewportExtEx failed\n");
413 ret
= ExtTextOutW(hdcMetafile
, 0, 0, 0, 0, str
, 1, NULL
);
414 ok(ret
, "ExtTextOutW failed\n");
416 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
417 ok(hMetafile
!= 0, "CloseEnhMetaFile failed\n");
420 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_scale_enum_proc
, &test
, &rc
);
421 ok(ret
, "EnumEnhMetaFile failed\n");
422 ok(test
.processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
424 ret
= DeleteEnhMetaFile(hMetafile
);
425 ok(ret
, "DeleteEnhMetaFile failed\n");
428 ret
= ReleaseDC(hwnd
, hdcDisplay
);
429 ok(ret
, "ReleaseDC failed\n");
434 static void check_dc_state(HDC hdc
, int restore_no
,
435 int wnd_org_x
, int wnd_org_y
, int wnd_ext_x
, int wnd_ext_y
,
436 int vp_org_x
, int vp_org_y
, int vp_ext_x
, int vp_ext_y
)
440 POINT vp_org
, win_org
;
441 SIZE vp_size
, win_size
;
442 FLOAT xscale
, yscale
, edx
, edy
;
444 SetLastError(0xdeadbeef);
445 ret
= GetWorldTransform(hdc
, &xform
);
446 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) goto win9x_here
;
447 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
449 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no
, xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
451 ok(xform
.eM12
== 0.0, "%d: expected eM12 0.0, got %f\n", restore_no
, xform
.eM12
);
452 ok(xform
.eM21
== 0.0, "%d: expected eM21 0.0, got %f\n", restore_no
, xform
.eM21
);
454 xscale
= (FLOAT
)vp_ext_x
/ (FLOAT
)wnd_ext_x
;
455 trace("x scale %f\n", xscale
);
456 ok(fabs(xscale
- xform
.eM11
) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
457 restore_no
, vp_ext_x
, wnd_ext_x
, xform
.eM11
);
459 yscale
= (FLOAT
)vp_ext_y
/ (FLOAT
)wnd_ext_y
;
460 trace("y scale %f\n", yscale
);
461 ok(fabs(yscale
- xform
.eM22
) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
462 restore_no
, vp_ext_y
, wnd_ext_y
, xform
.eM22
);
464 edx
= (FLOAT
)vp_org_x
- xform
.eM11
* (FLOAT
)wnd_org_x
;
465 ok(fabs(edx
- xform
.eDx
) < 0.01, "%d: edx %f != eDx %f\n", restore_no
, edx
, xform
.eDx
);
466 edy
= (FLOAT
)vp_org_y
- xform
.eM22
* (FLOAT
)wnd_org_y
;
467 ok(fabs(edy
- xform
.eDy
) < 0.01, "%d: edy %f != eDy %f\n", restore_no
, edy
, xform
.eDy
);
473 GetWindowOrgEx(hdc
, &win_org
);
474 GetViewportOrgEx(hdc
, &vp_org
);
475 GetWindowExtEx(hdc
, &win_size
);
476 GetViewportExtEx(hdc
, &vp_size
);
478 ok(wnd_org_x
== win_org
.x
, "%d: wnd_org_x: %d != %d\n", restore_no
, wnd_org_x
, win_org
.x
);
479 ok(wnd_org_y
== win_org
.y
, "%d: wnd_org_y: %d != %d\n", restore_no
, wnd_org_y
, win_org
.y
);
481 ok(vp_org_x
== vp_org
.x
, "%d: vport_org_x: %d != %d\n", restore_no
, vp_org_x
, vp_org
.x
);
482 ok(vp_org_y
== vp_org
.y
, "%d: vport_org_y: %d != %d\n", restore_no
, vp_org_y
, vp_org
.y
);
484 ok(wnd_ext_x
== win_size
.cx
, "%d: wnd_ext_x: %d != %d\n", restore_no
, wnd_ext_x
, win_size
.cx
);
485 ok(wnd_ext_y
== win_size
.cy
, "%d: wnd_ext_y: %d != %d\n", restore_no
, wnd_ext_y
, win_size
.cy
);
487 ok(vp_ext_x
== vp_size
.cx
, "%d: vport_ext_x: %d != %d\n", restore_no
, vp_ext_x
, vp_size
.cx
);
488 ok(vp_ext_y
== vp_size
.cy
, "%d: vport_ext_y: %d != %d\n", restore_no
, vp_ext_y
, vp_size
.cy
);
491 static int CALLBACK
savedc_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
492 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
498 static int save_state
;
499 static int restore_no
;
500 static int select_no
;
502 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
503 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
505 SetLastError(0xdeadbeef);
506 ret
= GetWorldTransform(hdc
, &xform
);
507 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
509 ret
= GetWindowOrgEx(hdc
, &pt
);
510 ok(ret
, "GetWindowOrgEx error %u\n", GetLastError());
511 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
512 ret
= GetViewportOrgEx(hdc
, &pt
);
513 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
514 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
515 ret
= GetWindowExtEx(hdc
, &size
);
516 ok(ret
, "GetWindowExtEx error %u\n", GetLastError());
517 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
518 ret
= GetViewportExtEx(hdc
, &size
);
519 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
520 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
524 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
525 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
528 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
534 static RECT exp_bounds
= { 0, 0, 150, 150 };
536 const ENHMETAHEADER
*emf
= (const ENHMETAHEADER
*)emr
;
538 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
539 emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
,
540 emf
->rclFrame
.left
, emf
->rclFrame
.top
, emf
->rclFrame
.right
, emf
->rclFrame
.bottom
);
541 trace("mm %d x %d, device %d x %d\n", emf
->szlMillimeters
.cx
, emf
->szlMillimeters
.cy
,
542 emf
->szlDevice
.cx
, emf
->szlDevice
.cy
);
544 SetRect(&bounds
, emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
);
545 ok(EqualRect(&bounds
, &exp_bounds
), "wrong bounds\n");
550 check_dc_state(hdc
, restore_no
, 0, 0, 1, 1, 0, 0, 1, 1);
556 const EMRLINETO
*line
= (const EMRLINETO
*)emr
;
557 trace("EMR_LINETO %d,%d\n", line
->ptl
.x
, line
->ptl
.x
);
560 case EMR_SETWINDOWORGEX
:
562 const EMRSETWINDOWORGEX
*org
= (const EMRSETWINDOWORGEX
*)emr
;
563 trace("EMR_SETWINDOWORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
566 case EMR_SETWINDOWEXTEX
:
568 const EMRSETWINDOWEXTEX
*ext
= (const EMRSETWINDOWEXTEX
*)emr
;
569 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
572 case EMR_SETVIEWPORTORGEX
:
574 const EMRSETVIEWPORTORGEX
*org
= (const EMRSETVIEWPORTORGEX
*)emr
;
575 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
578 case EMR_SETVIEWPORTEXTEX
:
580 const EMRSETVIEWPORTEXTEX
*ext
= (const EMRSETVIEWPORTEXTEX
*)emr
;
581 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
586 trace("EMR_SAVEDC\n");
591 const EMRRESTOREDC
*restoredc
= (const EMRRESTOREDC
*)emr
;
592 trace("EMR_RESTOREDC: %d\n", restoredc
->iRelative
);
597 ok(restoredc
->iRelative
== -1, "first restore %d\n", restoredc
->iRelative
);
598 check_dc_state(hdc
, restore_no
, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
601 ok(restoredc
->iRelative
== -3, "second restore %d\n", restoredc
->iRelative
);
602 check_dc_state(hdc
, restore_no
, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
605 ok(restoredc
->iRelative
== -2, "third restore %d\n", restoredc
->iRelative
);
606 check_dc_state(hdc
, restore_no
, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
609 ok(restore_no
<= 3, "restore_no %d\n", restore_no
);
610 save_state
+= restoredc
->iRelative
;
613 case EMR_SELECTOBJECT
:
615 const EMRSELECTOBJECT
*selectobj
= (const EMRSELECTOBJECT
*)emr
;
616 trace("EMR_SELECTOBJECT: %x\n",selectobj
->ihObject
);
621 ok(save_state
== 0, "EOF save_state %d\n", save_state
);
622 ok(select_no
== 3, "Too many/few selects %i\n",select_no
);
626 SetLastError(0xdeadbeef);
627 ret
= GetWorldTransform(hdc
, &xform
);
628 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
630 ret
= GetWindowOrgEx(hdc
, &pt
);
631 ok(ret
, "GetWindowOrgEx error %u\n", GetLastError());
632 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
633 ret
= GetViewportOrgEx(hdc
, &pt
);
634 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
635 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
636 ret
= GetWindowExtEx(hdc
, &size
);
637 ok(ret
, "GetWindowExtEx error %u\n", GetLastError());
638 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
639 ret
= GetViewportExtEx(hdc
, &size
);
640 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
641 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
645 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
646 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
652 static void test_SaveDC(void)
654 HDC hdcMetafile
, hdcDisplay
;
655 HENHMETAFILE hMetafile
;
660 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
661 static const RECT rc
= { 0, 0, 150, 150 };
663 /* Win9x doesn't play EMFs on invisible windows */
664 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
665 0, 0, 200, 200, 0, 0, 0, NULL
);
666 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
668 hdcDisplay
= GetDC(hwnd
);
669 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
671 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
672 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
674 SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
676 /* Need to write something to the emf, otherwise Windows won't play it back */
677 LineTo(hdcMetafile
, 150, 150);
679 SetWindowOrgEx(hdcMetafile
, 0, 0, NULL
);
680 SetViewportOrgEx(hdcMetafile
, 0, 0, NULL
);
681 SetWindowExtEx(hdcMetafile
, 110, 110, NULL
);
682 SetViewportExtEx(hdcMetafile
, 120, 120, NULL
);
684 /* Force Win9x to update DC state */
685 SetPixelV(hdcMetafile
, 50, 50, 0);
687 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
688 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
689 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
690 ret
= GetViewportExtEx(hdcMetafile
, &size
);
691 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
692 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
693 ret
= SaveDC(hdcMetafile
);
694 ok(ret
== 1, "ret = %d\n", ret
);
696 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
697 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
698 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
699 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
701 /* Force Win9x to update DC state */
702 SetPixelV(hdcMetafile
, 50, 50, 0);
704 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
705 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
706 ok(pt
.x
== 10,"Expecting ViewportOrg x of 10, got %i\n",pt
.x
);
707 ret
= GetViewportExtEx(hdcMetafile
, &size
);
708 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
709 ok(size
.cx
== 200,"Expecting ViewportExt cx of 200, got %i\n",size
.cx
);
710 ret
= SaveDC(hdcMetafile
);
711 ok(ret
== 2, "ret = %d\n", ret
);
713 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
714 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
715 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
716 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
717 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
718 SetBkColor( hdcMetafile
, 0 );
720 /* Force Win9x to update DC state */
721 SetPixelV(hdcMetafile
, 50, 50, 0);
723 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
724 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
725 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
726 ret
= GetViewportExtEx(hdcMetafile
, &size
);
727 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
728 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
729 ret
= SaveDC(hdcMetafile
);
730 ok(ret
== 3, "ret = %d\n", ret
);
732 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
733 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
734 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
735 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
737 SetPolyFillMode( hdcMetafile
, WINDING
);
738 SetBkColor( hdcMetafile
, 0x123456 );
739 ok( GetPolyFillMode( hdcMetafile
) == WINDING
, "PolyFillMode not restored\n" );
740 ok( GetBkColor( hdcMetafile
) == 0x123456, "Background color not restored\n" );
742 /* Force Win9x to update DC state */
743 SetPixelV(hdcMetafile
, 50, 50, 0);
745 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
746 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
747 ok(pt
.x
== 30,"Expecting ViewportOrg x of 30, got %i\n",pt
.x
);
748 ret
= GetViewportExtEx(hdcMetafile
, &size
);
749 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
750 ok(size
.cx
== 400,"Expecting ViewportExt cx of 400, got %i\n",size
.cx
);
751 ret
= RestoreDC(hdcMetafile
, -1);
752 ok(ret
, "ret = %d\n", ret
);
754 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
755 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
756 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
757 ret
= GetViewportExtEx(hdcMetafile
, &size
);
758 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
759 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
760 ok( GetPolyFillMode( hdcMetafile
) == ALTERNATE
, "PolyFillMode not restored\n" );
761 ok( GetBkColor( hdcMetafile
) == 0, "Background color not restored\n" );
762 ret
= SaveDC(hdcMetafile
);
763 ok(ret
== 3, "ret = %d\n", ret
);
765 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
766 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
767 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
768 ret
= GetViewportExtEx(hdcMetafile
, &size
);
769 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
770 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
771 ret
= RestoreDC(hdcMetafile
, 1);
772 ok(ret
, "ret = %d\n", ret
);
773 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
774 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
775 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
776 ret
= GetViewportExtEx(hdcMetafile
, &size
);
777 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
778 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
780 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
781 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
782 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
783 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
785 /* Force Win9x to update DC state */
786 SetPixelV(hdcMetafile
, 50, 50, 0);
788 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
789 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
790 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
791 ret
= GetViewportExtEx(hdcMetafile
, &size
);
792 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
793 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
794 ret
= SaveDC(hdcMetafile
);
795 ok(ret
== 1, "ret = %d\n", ret
);
797 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
798 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
799 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
800 ret
= GetViewportExtEx(hdcMetafile
, &size
);
801 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
802 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
803 ret
= SaveDC(hdcMetafile
);
804 ok(ret
== 2, "ret = %d\n", ret
);
806 memset(&orig_lf
, 0, sizeof(orig_lf
));
807 orig_lf
.lfCharSet
= ANSI_CHARSET
;
808 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
809 orig_lf
.lfWeight
= FW_DONTCARE
;
810 orig_lf
.lfHeight
= 7;
811 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
812 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
813 hFont
= CreateFontIndirectA(&orig_lf
);
814 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
816 hFontOld
= SelectObject(hdcMetafile
, hFont
);
818 hFont2
= CreateFontIndirectA(&orig_lf
);
819 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
820 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
821 ok(hFontCheck
== hFont
, "Font not selected\n");
823 /* Force Win9x to update DC state */
824 SetPixelV(hdcMetafile
, 50, 50, 0);
826 ret
= RestoreDC(hdcMetafile
, 1);
827 ok(ret
, "ret = %d\n", ret
);
828 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
829 ok(ret
, "GetViewportOrgEx error %u\n", GetLastError());
830 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
831 ret
= GetViewportExtEx(hdcMetafile
, &size
);
832 ok(ret
, "GetViewportExtEx error %u\n", GetLastError());
833 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
835 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
836 ok(hFontOld
== hFontCheck
&& hFontCheck
!= hFont
&& hFontCheck
!= hFont2
,
837 "Font not reverted with DC Restore\n");
839 ret
= RestoreDC(hdcMetafile
, -20);
840 ok(!ret
, "ret = %d\n", ret
);
841 ret
= RestoreDC(hdcMetafile
, 20);
842 ok(!ret
, "ret = %d\n", ret
);
844 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
845 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
847 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, savedc_emf_enum_proc
, 0, &rc
);
848 ok( ret
== 1, "EnumEnhMetaFile rets %d\n", ret
);
850 ret
= DeleteObject(hFont
);
851 ok( ret
, "DeleteObject error %d\n", GetLastError());
852 ret
= DeleteObject(hFont2
);
853 ok( ret
, "DeleteObject error %d\n", GetLastError());
854 ret
= DeleteEnhMetaFile(hMetafile
);
855 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
856 ret
= ReleaseDC(hwnd
, hdcDisplay
);
857 ok( ret
, "ReleaseDC error %d\n", GetLastError());
861 static void test_mf_SaveDC(void)
868 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
870 hdcMetafile
= CreateMetaFileA(NULL
);
871 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
873 ret
= SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
874 ok (ret
, "SetMapMode should not fail\n");
876 /* Need to write something to the emf, otherwise Windows won't play it back */
877 LineTo(hdcMetafile
, 150, 150);
880 SetWindowOrgEx(hdcMetafile
, 0, 0, &pt
);
881 ok( pt
.x
== 5555 && pt
.y
== 5555, "wrong origin %d,%d\n", pt
.x
, pt
.y
);
883 SetViewportOrgEx(hdcMetafile
, 0, 0, &pt
);
884 ok( pt
.x
== 5555 && pt
.y
== 5555, "wrong origin %d,%d\n", pt
.x
, pt
.y
);
885 size
.cx
= size
.cy
= 5555;
886 SetWindowExtEx(hdcMetafile
, 110, 110, &size
);
887 ok( size
.cx
== 5555 && size
.cy
== 5555, "wrong size %d,%d\n", size
.cx
, size
.cy
);
888 size
.cx
= size
.cy
= 5555;
889 SetViewportExtEx(hdcMetafile
, 120, 120, &size
);
890 ok( size
.cx
== 5555 && size
.cy
== 5555, "wrong size %d,%d\n", size
.cx
, size
.cy
);
892 /* Force Win9x to update DC state */
893 SetPixelV(hdcMetafile
, 50, 50, 0);
895 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
896 todo_wine
ok (!ret
, "GetViewportOrgEx should fail\n");
897 ret
= GetViewportExtEx(hdcMetafile
, &size
);
898 todo_wine
ok (!ret
, "GetViewportExtEx should fail\n");
899 ret
= SaveDC(hdcMetafile
);
900 ok(ret
== 1, "ret = %d\n", ret
);
902 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
903 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
904 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
905 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
907 /* Force Win9x to update DC state */
908 SetPixelV(hdcMetafile
, 50, 50, 0);
910 ret
= SaveDC(hdcMetafile
);
911 ok(ret
== 1, "ret = %d\n", ret
);
913 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
914 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
915 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
916 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
918 /* Force Win9x to update DC state */
919 SetPixelV(hdcMetafile
, 50, 50, 0);
920 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
921 SetBkColor( hdcMetafile
, 0 );
923 ret
= SaveDC(hdcMetafile
);
924 ok(ret
== 1, "ret = %d\n", ret
);
926 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
927 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
928 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
929 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
931 SetPolyFillMode( hdcMetafile
, WINDING
);
932 SetBkColor( hdcMetafile
, 0x123456 );
933 todo_wine
ok( !GetPolyFillMode( hdcMetafile
), "GetPolyFillMode succeeded\n" );
934 todo_wine
ok( GetBkColor( hdcMetafile
) == CLR_INVALID
, "GetBkColor succeeded\n" );
936 /* Force Win9x to update DC state */
937 SetPixelV(hdcMetafile
, 50, 50, 0);
939 ret
= RestoreDC(hdcMetafile
, -1);
940 ok(ret
, "ret = %d\n", ret
);
942 ret
= SaveDC(hdcMetafile
);
943 ok(ret
== 1, "ret = %d\n", ret
);
945 ret
= RestoreDC(hdcMetafile
, 1);
946 ok(ret
, "ret = %d\n", ret
);
948 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
949 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
950 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
951 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
953 /* Force Win9x to update DC state */
954 SetPixelV(hdcMetafile
, 50, 50, 0);
956 ret
= SaveDC(hdcMetafile
);
957 ok(ret
== 1, "ret = %d\n", ret
);
959 ret
= SaveDC(hdcMetafile
);
960 ok(ret
== 1, "ret = %d\n", ret
);
962 memset(&orig_lf
, 0, sizeof(orig_lf
));
963 orig_lf
.lfCharSet
= ANSI_CHARSET
;
964 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
965 orig_lf
.lfWeight
= FW_DONTCARE
;
966 orig_lf
.lfHeight
= 7;
967 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
968 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
969 hFont
= CreateFontIndirectA(&orig_lf
);
970 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
972 hFontOld
= SelectObject(hdcMetafile
, hFont
);
974 hFont2
= CreateFontIndirectA(&orig_lf
);
975 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
976 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
977 ok(hFontCheck
== hFont
, "Font not selected\n");
979 /* Force Win9x to update DC state */
980 SetPixelV(hdcMetafile
, 50, 50, 0);
982 ret
= RestoreDC(hdcMetafile
, 1);
983 ok(ret
, "ret = %d\n", ret
);
985 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
986 ok(hFontOld
!= hFontCheck
&& hFontCheck
== hFont2
, "Font incorrectly reverted with DC Restore\n");
988 /* restore level is ignored */
989 ret
= RestoreDC(hdcMetafile
, -20);
990 ok(ret
, "ret = %d\n", ret
);
991 ret
= RestoreDC(hdcMetafile
, 20);
992 ok(ret
, "ret = %d\n", ret
);
993 ret
= RestoreDC(hdcMetafile
, 0);
994 ok(ret
, "ret = %d\n", ret
);
996 hMetafile
= CloseMetaFile(hdcMetafile
);
997 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
999 ret
= DeleteMetaFile(hMetafile
);
1000 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
1001 ret
= DeleteObject(hFont
);
1002 ok( ret
, "DeleteObject error %d\n", GetLastError());
1003 ret
= DeleteObject(hFont2
);
1004 ok( ret
, "DeleteObject error %d\n", GetLastError());
1008 /* Win-format metafile (mfdrv) tests */
1009 /* These tests compare the generated metafiles byte-by-byte */
1010 /* with the nominal results. */
1012 /* Maximum size of sample metafiles in bytes. */
1013 #define MF_BUFSIZE 1024
1015 /* 8x8 bitmap data for a pattern brush */
1016 static const unsigned char SAMPLE_PATTERN_BRUSH
[] = {
1017 0x01, 0x00, 0x02, 0x00,
1018 0x03, 0x00, 0x04, 0x00,
1019 0x05, 0x00, 0x06, 0x00,
1020 0x07, 0x00, 0x08, 0x00
1023 /* Sample metafiles to be compared to the outputs of the
1027 static const unsigned char MF_BLANK_BITS
[] = {
1028 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1030 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1033 static const unsigned char MF_GRAPHICS_BITS
[] = {
1034 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1035 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1037 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1038 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1039 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1040 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1041 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1042 0x00, 0x00, 0x00, 0x00
1045 static const unsigned char MF_PATTERN_BRUSH_BITS
[] = {
1046 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1047 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1048 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1049 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1050 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1051 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1056 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1057 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1058 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1059 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1060 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1064 static const unsigned char MF_DCBRUSH_BITS
[] =
1066 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1067 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1068 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1069 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1070 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1071 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1074 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1075 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1076 0x00, 0x00, 0x00, 0x00
1079 static const unsigned char MF_TEXTOUT_ON_PATH_BITS
[] =
1081 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1084 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1085 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1086 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1090 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS
[] =
1092 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1097 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1098 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1099 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1102 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1105 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1106 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1107 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1109 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1111 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1112 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1115 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1116 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1117 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1118 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1119 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1120 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1122 0x14, 0x00, 0x00, 0x00
1125 static const unsigned char MF_LINETO_BITS
[] = {
1126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1133 static const unsigned char EMF_LINETO_BITS
[] = {
1134 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1139 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1140 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1141 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1144 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1147 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1148 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1149 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1150 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1151 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1152 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1154 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1155 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1157 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1158 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1161 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1162 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1163 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1164 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1165 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1166 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1167 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1168 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1169 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1170 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1171 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1175 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS
[] = {
1176 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1180 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1181 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1182 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1183 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1185 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1186 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1189 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1190 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1191 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1192 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1193 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1194 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1195 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1196 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1197 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1199 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1200 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1201 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1202 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1203 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1204 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1205 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1206 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1207 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1208 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1209 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1210 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1211 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1213 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1217 static const unsigned char EMF_LINETO_MM_TEXT_BITS
[] = {
1218 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1220 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1223 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1224 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1225 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1228 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1231 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1232 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1233 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1234 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1235 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1236 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1237 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1238 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1239 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1241 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1242 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1244 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1246 0x14, 0x00, 0x00, 0x00
1249 static const unsigned char EMF_BITBLT
[] =
1251 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1256 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1257 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1258 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1261 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1264 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1265 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1267 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1269 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1276 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1277 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1278 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1293 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1296 0x00, 0x00, 0x80, 0x3f, 0x00, 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, 0x4d, 0x00, 0x00, 0x00,
1301 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1303 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1305 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1311 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1312 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1313 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1314 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1315 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1316 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1325 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1326 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1327 0x14, 0x00, 0x00, 0x00
1330 static const unsigned char EMF_DCBRUSH_BITS
[] =
1332 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1333 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1334 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1335 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1336 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1337 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1338 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1339 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1341 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1342 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1345 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1346 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1347 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1348 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1349 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1350 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1351 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1352 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1353 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1354 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1357 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1358 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1359 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1360 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1361 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1362 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1363 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1365 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1366 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1367 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1368 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1369 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1370 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1372 0x14, 0x00, 0x00, 0x00
1375 static const unsigned char EMF_BEZIER_BITS
[] =
1377 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1382 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1383 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1384 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1386 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1387 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1389 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1390 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1391 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1393 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1394 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1395 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1396 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1397 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1398 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1399 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1400 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1401 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1402 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1403 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1404 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1405 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1407 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1408 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1409 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1410 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1411 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1412 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1413 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1414 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1415 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1416 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1417 0x14, 0x00, 0x00, 0x00
1420 static const unsigned char EMF_POLYPOLYLINE_BITS
[] =
1422 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1423 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1424 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1425 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1426 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1427 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1428 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1429 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1431 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1432 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1435 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1436 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1438 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1439 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1440 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1441 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1442 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1443 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1444 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1445 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1447 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1448 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1449 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1450 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1451 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1454 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1455 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1456 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1457 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1458 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1459 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1460 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1461 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1462 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1463 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1464 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1465 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1466 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1467 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1468 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1470 0x14, 0x00, 0x00, 0x00
1473 static const unsigned char EMF_GRADIENTFILL_BITS
[] =
1475 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1476 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1477 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1478 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1479 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1480 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1481 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1482 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1485 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1487 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1488 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1489 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1490 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1491 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1492 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1493 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1494 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1495 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1497 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1498 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1499 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1500 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1501 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1502 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1503 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1504 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1505 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1508 0x14, 0x00, 0x00, 0x00
1511 /* For debugging or dumping the raw metafiles produced by
1512 * new test functions.
1514 static INT CALLBACK
mf_enum_proc(HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
,
1515 INT nobj
, LPARAM param
)
1517 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1518 hdc
, mr
->rdFunction
, mr
->rdSize
, (void *)param
);
1522 /* For debugging or dumping the raw metafiles produced by
1523 * new test functions.
1526 static void dump_mf_bits (const HMETAFILE mf
, const char *desc
)
1528 BYTE buf
[MF_BUFSIZE
];
1531 if (!winetest_debug
) return;
1533 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1534 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1536 printf ("MetaFile %s has bits:\n{\n ", desc
);
1537 for (i
=0; i
<mfsize
; i
++)
1539 printf ("0x%02x", buf
[i
]);
1542 else if (i
% 8 == 7)
1550 /* Compare the metafile produced by a test function with the
1551 * expected raw metafile data in "bits".
1552 * Return value is 0 for a perfect match,
1553 * -1 if lengths aren't equal,
1554 * otherwise returns the number of non-matching bytes.
1557 static int compare_mf_bits (const HMETAFILE mf
, const unsigned char *bits
, UINT bsize
,
1560 unsigned char buf
[MF_BUFSIZE
];
1564 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1565 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1566 if (mfsize
< MF_BUFSIZE
)
1567 ok (mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n",
1568 desc
, mfsize
, bsize
);
1570 ok (bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1571 desc
, mfsize
, bsize
);
1572 if (mfsize
!= bsize
)
1576 for (i
=0; i
<bsize
; i
++)
1578 if (buf
[i
] != bits
[i
])
1581 ok (diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1582 desc
, mfsize
, bsize
, diff
);
1587 static int compare_mf_disk_bits(LPCSTR name
, const BYTE
*bits
, UINT bsize
, const char *desc
)
1589 unsigned char buf
[MF_BUFSIZE
];
1590 DWORD mfsize
, rd_size
, i
;
1595 hfile
= CreateFileA(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1596 assert(hfile
!= INVALID_HANDLE_VALUE
);
1598 mfsize
= GetFileSize(hfile
, NULL
);
1599 assert(mfsize
<= MF_BUFSIZE
);
1601 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &rd_size
, NULL
);
1602 ok( ret
&& rd_size
== mfsize
, "ReadFile: error %d\n", GetLastError());
1606 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n", desc
, mfsize
, bsize
);
1608 if (mfsize
!= bsize
)
1612 for (i
=0; i
<bsize
; i
++)
1614 if (buf
[i
] != bits
[i
])
1617 ok(diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1618 desc
, mfsize
, bsize
, diff
);
1623 /* For debugging or dumping the raw EMFs produced by
1624 * new test functions.
1626 static void dump_emf_bits(const HENHMETAFILE mf
, const char *desc
)
1628 BYTE buf
[MF_BUFSIZE
];
1631 if (!winetest_debug
) return;
1633 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1634 ok (mfsize
> 0, "%s: GetEnhMetaFileBits failed\n", desc
);
1636 printf("EMF %s has bits:\n{\n ", desc
);
1637 for (i
= 0; i
< mfsize
; i
++)
1639 printf ("0x%02x", buf
[i
]);
1642 else if (i
% 8 == 7)
1650 static void dump_emf_records(const HENHMETAFILE mf
, const char *desc
)
1653 BYTE buf
[MF_BUFSIZE
];
1654 UINT mfsize
, offset
;
1656 if (!winetest_debug
) return;
1658 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1659 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1661 printf("EMF %s has records:\n", desc
);
1665 while(offset
< mfsize
)
1667 EMR
*emr
= (EMR
*)(emf
+ offset
);
1668 printf("emr->iType %d, emr->nSize %u\n", emr
->iType
, emr
->nSize
);
1669 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1670 offset
+= emr
->nSize
;
1674 static void dump_emf_record(const ENHMETARECORD
*emr
, const char *desc
)
1679 if (!winetest_debug
) return;
1681 printf ("%s: EMF record %u has bits:\n{\n", desc
, emr
->iType
);
1682 buf
= (const BYTE
*)emr
;
1683 for (i
= 0; i
< emr
->nSize
; i
++)
1685 printf ("0x%02x", buf
[i
]);
1686 if (i
== emr
->nSize
- 1)
1688 else if (i
% 8 == 7)
1696 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW
*eto
)
1698 trace("rclBounds %d,%d - %d,%d\n", eto
->rclBounds
.left
, eto
->rclBounds
.top
,
1699 eto
->rclBounds
.right
, eto
->rclBounds
.bottom
);
1700 trace("iGraphicsMode %u\n", eto
->iGraphicsMode
);
1701 trace("exScale: %f\n", eto
->exScale
);
1702 trace("eyScale: %f\n", eto
->eyScale
);
1703 trace("emrtext.ptlReference %d,%d\n", eto
->emrtext
.ptlReference
.x
, eto
->emrtext
.ptlReference
.y
);
1704 trace("emrtext.nChars %u\n", eto
->emrtext
.nChars
);
1705 trace("emrtext.offString %#x\n", eto
->emrtext
.offString
);
1706 trace("emrtext.fOptions %#x\n", eto
->emrtext
.fOptions
);
1707 trace("emrtext.rcl %d,%d - %d,%d\n", eto
->emrtext
.rcl
.left
, eto
->emrtext
.rcl
.top
,
1708 eto
->emrtext
.rcl
.right
, eto
->emrtext
.rcl
.bottom
);
1709 trace("emrtext.offDx %#x\n", eto
->emrtext
.offDx
);
1712 static BOOL
match_emf_record(const ENHMETARECORD
*emr1
, const ENHMETARECORD
*emr2
,
1713 const char *desc
, BOOL ignore_scaling
)
1717 ok(emr1
->iType
== emr2
->iType
, "%s: emr->iType %u != %u\n",
1718 desc
, emr1
->iType
, emr2
->iType
);
1720 ok(emr1
->nSize
== emr2
->nSize
, "%s: emr->nSize %u != %u\n",
1721 desc
, emr1
->nSize
, emr2
->nSize
);
1723 /* iType and nSize mismatches are fatal */
1724 if (emr1
->iType
!= emr2
->iType
|| emr1
->nSize
!= emr2
->nSize
) return FALSE
;
1726 /* contents of EMR_GDICOMMENT are not interesting */
1727 if (emr1
->iType
== EMR_GDICOMMENT
) return TRUE
;
1729 /* different Windows versions setup DC scaling differently when
1730 * converting an old style metafile to an EMF.
1732 if (ignore_scaling
&& (emr1
->iType
== EMR_SETWINDOWEXTEX
||
1733 emr1
->iType
== EMR_SETVIEWPORTEXTEX
))
1736 if (emr1
->iType
== EMR_EXTTEXTOUTW
|| emr1
->iType
== EMR_EXTTEXTOUTA
)
1738 EMREXTTEXTOUTW
*eto1
, *eto2
;
1740 eto1
= HeapAlloc(GetProcessHeap(), 0, emr1
->nSize
);
1741 memcpy(eto1
, emr1
, emr1
->nSize
);
1742 eto2
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1743 memcpy(eto2
, emr2
, emr2
->nSize
);
1745 /* different Windows versions setup DC scaling differently */
1746 eto1
->exScale
= eto1
->eyScale
= 0.0;
1747 eto2
->exScale
= eto2
->eyScale
= 0.0;
1749 diff
= memcmp(eto1
, eto2
, emr1
->nSize
);
1752 dump_EMREXTTEXTOUT(eto1
);
1753 dump_EMREXTTEXTOUT(eto2
);
1755 HeapFree(GetProcessHeap(), 0, eto1
);
1756 HeapFree(GetProcessHeap(), 0, eto2
);
1758 else if (emr1
->iType
== EMR_EXTSELECTCLIPRGN
&& !lstrcmpA(desc
, "emf_clipping"))
1760 /* We have to take care of NT4 differences here */
1761 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1764 ENHMETARECORD
*emr_nt4
;
1766 emr_nt4
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1767 memcpy(emr_nt4
, emr2
, emr2
->nSize
);
1768 /* Correct the nRgnSize field */
1769 emr_nt4
->dParm
[5] = sizeof(RECT
);
1771 diff
= memcmp(emr1
, emr_nt4
, emr1
->nSize
);
1773 win_skip("Catered for NT4 differences\n");
1775 HeapFree(GetProcessHeap(), 0, emr_nt4
);
1778 else if (emr1
->iType
== EMR_POLYBEZIERTO16
|| emr1
->iType
== EMR_POLYBEZIER16
)
1780 EMRPOLYBEZIER16
*eto1
, *eto2
;
1782 eto1
= (EMRPOLYBEZIER16
*)emr1
;
1783 eto2
= (EMRPOLYBEZIER16
*)emr2
;
1785 diff
= eto1
->cpts
!= eto2
->cpts
;
1787 diff
= memcmp(eto1
->apts
, eto2
->apts
, eto1
->cpts
* sizeof(POINTS
));
1789 else if (emr1
->iType
== EMR_POLYBEZIERTO
|| emr1
->iType
== EMR_POLYBEZIER
)
1791 EMRPOLYBEZIER
*eto1
, *eto2
;
1793 eto1
= (EMRPOLYBEZIER
*)emr1
;
1794 eto2
= (EMRPOLYBEZIER
*)emr2
;
1796 diff
= eto1
->cptl
!= eto2
->cptl
;
1798 diff
= memcmp(eto1
->aptl
, eto2
->aptl
, eto1
->cptl
* sizeof(POINTL
));
1801 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1803 ok(diff
== 0, "%s: contents of record %u don't match\n", desc
, emr1
->iType
);
1807 dump_emf_record(emr1
, "expected bits");
1808 dump_emf_record(emr2
, "actual bits");
1811 return diff
== 0; /* report all non-fatal record mismatches */
1814 /* Compare the EMF produced by a test function with the
1815 * expected raw EMF data in "bits".
1816 * Return value is 0 for a perfect match,
1817 * -1 if lengths aren't equal,
1818 * otherwise returns the number of non-matching bytes.
1820 static int compare_emf_bits(const HENHMETAFILE mf
, const unsigned char *bits
,
1821 UINT bsize
, const char *desc
,
1822 BOOL ignore_scaling
)
1824 unsigned char buf
[MF_BUFSIZE
];
1825 UINT mfsize
, offset1
, offset2
, diff_nt4
, diff_9x
;
1826 const ENHMETAHEADER
*emh1
, *emh2
;
1828 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1829 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1831 /* ENHMETAHEADER size could differ, depending on platform */
1832 diff_nt4
= sizeof(SIZEL
);
1833 diff_9x
= sizeof(SIZEL
) + 3 * sizeof(DWORD
);
1835 if (mfsize
< MF_BUFSIZE
)
1837 ok(mfsize
== bsize
||
1838 broken(mfsize
== bsize
- diff_nt4
) || /* NT4 */
1839 broken(mfsize
== bsize
- diff_9x
), /* Win9x/WinME */
1840 "%s: mfsize=%d, bsize=%d\n", desc
, mfsize
, bsize
);
1843 ok(bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1844 desc
, mfsize
, bsize
);
1846 /* basic things must match */
1847 emh1
= (const ENHMETAHEADER
*)bits
;
1848 emh2
= (const ENHMETAHEADER
*)buf
;
1849 ok(emh1
->iType
== EMR_HEADER
, "expected EMR_HEADER, got %u\n", emh1
->iType
);
1850 ok(emh1
->nSize
== sizeof(ENHMETAHEADER
), "expected sizeof(ENHMETAHEADER), got %u\n", emh1
->nSize
);
1851 ok(emh2
->nBytes
== mfsize
, "expected emh->nBytes %u, got %u\n", mfsize
, emh2
->nBytes
);
1852 ok(emh1
->dSignature
== ENHMETA_SIGNATURE
, "expected ENHMETA_SIGNATURE, got %u\n", emh1
->dSignature
);
1854 ok(emh1
->iType
== emh2
->iType
, "expected EMR_HEADER, got %u\n", emh2
->iType
);
1855 ok(emh1
->nSize
== emh2
->nSize
||
1856 broken(emh1
->nSize
- diff_nt4
== emh2
->nSize
) ||
1857 broken(emh1
->nSize
- diff_9x
== emh2
->nSize
),
1858 "expected nSize %u, got %u\n", emh1
->nSize
, emh2
->nSize
);
1859 ok(emh1
->rclBounds
.left
== emh2
->rclBounds
.left
, "%s: expected rclBounds.left = %d, got %d\n",
1860 desc
, emh1
->rclBounds
.left
, emh2
->rclBounds
.left
);
1861 ok(emh1
->rclBounds
.top
== emh2
->rclBounds
.top
, "%s: expected rclBounds.top = %d, got %d\n",
1862 desc
, emh1
->rclBounds
.top
, emh2
->rclBounds
.top
);
1863 ok(emh1
->rclBounds
.right
== emh2
->rclBounds
.right
, "%s: expected rclBounds.right = %d, got %d\n",
1864 desc
, emh1
->rclBounds
.right
, emh2
->rclBounds
.right
);
1865 ok(emh1
->rclBounds
.bottom
== emh2
->rclBounds
.bottom
, "%s: expected rclBounds.bottom = %d, got %d\n",
1866 desc
, emh1
->rclBounds
.bottom
, emh2
->rclBounds
.bottom
);
1867 ok(emh1
->dSignature
== emh2
->dSignature
, "expected dSignature %u, got %u\n", emh1
->dSignature
, emh2
->dSignature
);
1868 ok(emh1
->nBytes
== emh2
->nBytes
||
1869 broken(emh1
->nBytes
- diff_nt4
== emh2
->nBytes
) ||
1870 broken(emh1
->nBytes
- diff_9x
== emh2
->nBytes
),
1871 "expected nBytes %u, got %u\n", emh1
->nBytes
, emh2
->nBytes
);
1872 ok(emh1
->nRecords
== emh2
->nRecords
, "expected nRecords %u, got %u\n", emh1
->nRecords
, emh2
->nRecords
);
1874 offset1
= emh1
->nSize
;
1875 offset2
= emh2
->nSize
; /* Needed for Win9x/WinME/NT4 */
1876 while (offset1
< emh1
->nBytes
)
1878 const ENHMETARECORD
*emr1
= (const ENHMETARECORD
*)(bits
+ offset1
);
1879 const ENHMETARECORD
*emr2
= (const ENHMETARECORD
*)(buf
+ offset2
);
1881 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1882 desc
, emr1
->iType
, emr1
->nSize
, emr2
->iType
, emr2
->nSize
);
1884 if (!match_emf_record(emr1
, emr2
, desc
, ignore_scaling
)) return -1;
1886 /* We have already bailed out if iType or nSize don't match */
1887 offset1
+= emr1
->nSize
;
1888 offset2
+= emr2
->nSize
;
1894 /* tests blitting to an EMF */
1895 static void test_emf_BitBlt(void)
1897 HDC hdcDisplay
, hdcMetafile
, hdcBitmap
;
1898 HBITMAP hBitmap
, hOldBitmap
;
1899 HENHMETAFILE hMetafile
;
1901 BITMAPINFOHEADER bmih
=
1903 sizeof(BITMAPINFOHEADER
),
1904 BMP_DIM
,/* biWidth */
1905 BMP_DIM
,/* biHeight */
1907 24, /* biBitCount */
1908 BI_RGB
, /* biCompression */
1909 0, /* biXPelsPerMeter */
1910 0, /* biYPelsPerMeter */
1912 0, /* biClrImportant */
1918 hdcDisplay
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1919 ok( hdcDisplay
!= 0, "CreateDCA error %d\n", GetLastError() );
1921 hdcBitmap
= CreateCompatibleDC(hdcDisplay
);
1922 ok( hdcBitmap
!= 0, "CreateCompatibleDC failed\n" );
1923 ok(SetGraphicsMode(hdcBitmap
, GM_ADVANCED
), "SetGraphicsMode failed\n");
1924 bmih
.biXPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSX
), 100, 3937);
1925 bmih
.biYPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSY
), 100, 3937);
1926 hBitmap
= CreateDIBSection(hdcDisplay
, (const BITMAPINFO
*)&bmih
,
1927 DIB_RGB_COLORS
, &bits
, NULL
, 0);
1928 hOldBitmap
= SelectObject(hdcBitmap
, hBitmap
);
1930 hdcMetafile
= CreateEnhMetaFileA(hdcBitmap
, NULL
, NULL
, NULL
);
1931 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1933 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1934 ret
= BitBlt(hdcBitmap
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, BLACKNESS
);
1935 ok( ret
, "BitBlt(BLACKNESS) failed\n" );
1937 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, SRCCOPY
);
1938 ok( ret
, "BitBlt(SRCCOPY) failed\n" );
1939 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, WHITENESS
);
1940 ok( ret
, "BitBlt(WHITENESS) failed\n" );
1942 ok(SetMapMode(hdcBitmap
, MM_ANISOTROPIC
), "SetMapMode failed\n");
1943 ok(SetWindowOrgEx(hdcBitmap
, 0, 0, NULL
), "SetWindowOrgEx failed\n");
1944 ok(SetWindowExtEx(hdcBitmap
, 400, 400, NULL
), "SetWindowExtEx failed\n");
1945 ok(SetViewportOrgEx(hdcBitmap
, 0, 0, NULL
), "SetViewportOrgEx failed\n");
1946 ok(SetViewportExtEx(hdcBitmap
, BMP_DIM
, BMP_DIM
, NULL
), "SetViewportExtEx failed\n");
1947 memset(&xform
, 0, sizeof(xform
));
1950 ok(SetWorldTransform(hdcBitmap
, &xform
), "SetWorldTransform failed\n");
1952 ret
= StretchBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, 400, 400, SRCCOPY
);
1953 ok( ret
, "StretchBlt(SRCCOPY) failed\n" );
1955 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1956 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1958 if(compare_emf_bits(hMetafile
, EMF_BITBLT
, sizeof(EMF_BITBLT
),
1959 "emf_BitBlt", FALSE
) != 0)
1961 dump_emf_bits(hMetafile
, "emf_BitBlt");
1962 dump_emf_records(hMetafile
, "emf_BitBlt");
1965 SelectObject(hdcBitmap
, hOldBitmap
);
1966 DeleteObject(hBitmap
);
1967 DeleteDC(hdcBitmap
);
1968 DeleteDC(hdcDisplay
);
1972 static void test_emf_DCBrush(void)
1975 HENHMETAFILE hMetafile
;
1981 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
1983 win_skip( "SetDCBrush/PenColor not supported\n" );
1987 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
1988 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1990 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
1991 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
1993 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
1994 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
1996 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
1997 ok( color
== 0xffffff, "SetDCBrushColor returned %x\n", color
);
1999 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
2000 ok( color
== 0, "SetDCPenColor returned %x\n", color
);
2002 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
2004 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
2005 ok( color
== 0x555555, "SetDCBrushColor returned %x\n", color
);
2007 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2008 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
2010 if (compare_emf_bits (hMetafile
, EMF_DCBRUSH_BITS
, sizeof(EMF_DCBRUSH_BITS
),
2011 "emf_DC_Brush", FALSE
) != 0)
2013 dump_emf_bits(hMetafile
, "emf_DC_Brush");
2014 dump_emf_records(hMetafile
, "emf_DC_Brush");
2016 ret
= DeleteEnhMetaFile(hMetafile
);
2017 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2018 ret
= DeleteObject(hBrush
);
2019 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2020 ret
= DeleteObject(hPen
);
2021 ok( ret
, "DeleteObject(HPEN) error %d\n", GetLastError());
2024 /* Test a blank metafile. May be used as a template for new tests. */
2026 static void test_mf_Blank(void)
2029 HMETAFILE hMetafile
;
2034 hdcMetafile
= CreateMetaFileA(NULL
);
2035 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2036 trace("hdcMetafile %p\n", hdcMetafile
);
2038 /* Tests on metafile initialization */
2039 caps
= GetDeviceCaps (hdcMetafile
, TECHNOLOGY
);
2040 ok (caps
== DT_METAFILE
,
2041 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps
);
2043 hMetafile
= CloseMetaFile(hdcMetafile
);
2044 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2045 type
= GetObjectType(hMetafile
);
2046 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
2047 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2049 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
2052 dump_mf_bits(hMetafile
, "mf_Blank");
2053 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2056 ret
= DeleteMetaFile(hMetafile
);
2057 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2060 static void test_CopyMetaFile(void)
2063 HMETAFILE hMetafile
, hmf_copy
;
2065 char temp_path
[MAX_PATH
];
2066 char mf_name
[MAX_PATH
];
2069 hdcMetafile
= CreateMetaFileA(NULL
);
2070 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2071 trace("hdcMetafile %p\n", hdcMetafile
);
2073 hMetafile
= CloseMetaFile(hdcMetafile
);
2074 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2075 type
= GetObjectType(hMetafile
);
2076 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
2078 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
2081 dump_mf_bits(hMetafile
, "mf_Blank");
2082 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2085 GetTempPathA(MAX_PATH
, temp_path
);
2086 GetTempFileNameA(temp_path
, "wmf", 0, mf_name
);
2088 hmf_copy
= CopyMetaFileA(hMetafile
, mf_name
);
2089 ok(hmf_copy
!= 0, "CopyMetaFile error %d\n", GetLastError());
2091 type
= GetObjectType(hmf_copy
);
2092 ok(type
== OBJ_METAFILE
, "CopyMetaFile created object with type %d\n", type
);
2094 ret
= DeleteMetaFile(hMetafile
);
2095 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2097 if (compare_mf_disk_bits(mf_name
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
), "mf_blank") != 0)
2099 dump_mf_bits(hmf_copy
, "mf_Blank");
2100 EnumMetaFile(0, hmf_copy
, mf_enum_proc
, 0);
2103 ret
= DeleteMetaFile(hmf_copy
);
2104 ok( ret
, "DeleteMetaFile(%p) error %d\n", hmf_copy
, GetLastError());
2106 DeleteFileA(mf_name
);
2109 static void test_SetMetaFileBits(void)
2117 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), MF_GRAPHICS_BITS
);
2118 trace("hmf %p\n", hmf
);
2119 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2120 type
= GetObjectType(hmf
);
2121 ok(type
== OBJ_METAFILE
, "SetMetaFileBitsEx created object with type %d\n", type
);
2123 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2125 dump_mf_bits(hmf
, "mf_Graphics");
2126 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2129 ret
= DeleteMetaFile(hmf
);
2130 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2132 /* NULL data crashes XP SP1 */
2133 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2135 /* Now with zero size */
2136 SetLastError(0xdeadbeef);
2137 hmf
= SetMetaFileBitsEx(0, MF_GRAPHICS_BITS
);
2138 trace("hmf %p\n", hmf
);
2139 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2140 ok(GetLastError() == ERROR_INVALID_DATA
||
2141 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
2142 "wrong error %d\n", GetLastError());
2144 /* Now with odd size */
2145 SetLastError(0xdeadbeef);
2146 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
) - 1, MF_GRAPHICS_BITS
);
2147 trace("hmf %p\n", hmf
);
2148 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2149 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2151 /* Now with zeroed out header fields */
2152 assert(sizeof(buf
) >= sizeof(MF_GRAPHICS_BITS
));
2153 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2154 mh
= (METAHEADER
*)buf
;
2155 /* corruption of any of the below fields leads to a failure */
2158 mh
->mtHeaderSize
= 0;
2159 SetLastError(0xdeadbeef);
2160 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2161 trace("hmf %p\n", hmf
);
2162 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2163 ok(GetLastError() == ERROR_INVALID_DATA
||
2164 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
2165 "wrong error %d\n", GetLastError());
2167 /* Now with corrupted mtSize field */
2168 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2169 mh
= (METAHEADER
*)buf
;
2170 /* corruption of mtSize doesn't lead to a failure */
2172 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2173 trace("hmf %p\n", hmf
);
2174 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2176 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2178 dump_mf_bits(hmf
, "mf_Graphics");
2179 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2182 ret
= DeleteMetaFile(hmf
);
2183 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2185 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2186 /* Now with zeroed out mtSize field */
2187 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2188 mh
= (METAHEADER
*)buf
;
2189 /* zeroing mtSize doesn't lead to a failure */
2191 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2192 trace("hmf %p\n", hmf
);
2193 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2195 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2197 dump_mf_bits(hmf
, "mf_Graphics");
2198 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2201 ret
= DeleteMetaFile(hmf
);
2202 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2206 /* Simple APIs from mfdrv/graphics.c
2209 static void test_mf_Graphics(void)
2212 HMETAFILE hMetafile
;
2216 hdcMetafile
= CreateMetaFileA(NULL
);
2217 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2218 trace("hdcMetafile %p\n", hdcMetafile
);
2220 ret
= MoveToEx(hdcMetafile
, 1, 1, NULL
);
2221 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2222 ret
= LineTo(hdcMetafile
, 2, 2);
2223 ok( ret
, "LineTo error %d.\n", GetLastError());
2224 ret
= MoveToEx(hdcMetafile
, 1, 1, &oldpoint
);
2225 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2227 /* oldpoint gets garbage under Win XP, so the following test would
2228 * work under Wine but fails under Windows:
2230 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2231 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2232 * oldpoint.x, oldpoint.y);
2235 ret
= Ellipse(hdcMetafile
, 0, 0, 2, 2);
2236 ok( ret
, "Ellipse error %d.\n", GetLastError());
2238 hMetafile
= CloseMetaFile(hdcMetafile
);
2239 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2240 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2242 if (compare_mf_bits (hMetafile
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
),
2243 "mf_Graphics") != 0)
2245 dump_mf_bits(hMetafile
, "mf_Graphics");
2246 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2249 ret
= DeleteMetaFile(hMetafile
);
2250 ok( ret
, "DeleteMetaFile(%p) error %d\n",
2251 hMetafile
, GetLastError());
2254 static void test_mf_PatternBrush(void)
2257 HMETAFILE hMetafile
;
2262 orig_lb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(LOGBRUSH
));
2264 orig_lb
->lbStyle
= BS_PATTERN
;
2265 orig_lb
->lbColor
= RGB(0, 0, 0);
2266 orig_lb
->lbHatch
= (ULONG_PTR
)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH
);
2267 ok((HBITMAP
)orig_lb
->lbHatch
!= NULL
, "CreateBitmap error %d.\n", GetLastError());
2269 hBrush
= CreateBrushIndirect (orig_lb
);
2270 ok(hBrush
!= 0, "CreateBrushIndirect error %d\n", GetLastError());
2272 hdcMetafile
= CreateMetaFileA(NULL
);
2273 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2274 trace("hdcMetafile %p\n", hdcMetafile
);
2276 hBrush
= SelectObject(hdcMetafile
, hBrush
);
2277 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2279 hMetafile
= CloseMetaFile(hdcMetafile
);
2280 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2281 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2283 if (compare_mf_bits (hMetafile
, MF_PATTERN_BRUSH_BITS
, sizeof(MF_PATTERN_BRUSH_BITS
),
2284 "mf_Pattern_Brush") != 0)
2286 dump_mf_bits(hMetafile
, "mf_Pattern_Brush");
2287 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2290 ret
= DeleteMetaFile(hMetafile
);
2291 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
2292 ret
= DeleteObject(hBrush
);
2293 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2294 ret
= DeleteObject((HBITMAP
)orig_lb
->lbHatch
);
2295 ok( ret
, "DeleteObject(HBITMAP) error %d\n",
2297 HeapFree (GetProcessHeap(), 0, orig_lb
);
2300 static void test_mf_DCBrush(void)
2303 HMETAFILE hMetafile
;
2309 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
2311 win_skip( "SetDCBrush/PenColor not supported\n" );
2315 hdcMetafile
= CreateMetaFileA(NULL
);
2316 ok( hdcMetafile
!= 0, "CreateMetaFileA failed\n" );
2318 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
2319 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2321 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
2322 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
2324 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
2325 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2327 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
2328 ok( color
== CLR_INVALID
, "SetDCPenColor returned %x\n", color
);
2330 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
2332 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
2333 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2335 hMetafile
= CloseMetaFile(hdcMetafile
);
2336 ok( hMetafile
!= 0, "CloseMetaFile failed\n" );
2338 if (compare_mf_bits(hMetafile
, MF_DCBRUSH_BITS
, sizeof(MF_DCBRUSH_BITS
), "mf_DCBrush") != 0)
2340 dump_mf_bits(hMetafile
, "mf_DCBrush");
2341 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2343 ret
= DeleteMetaFile(hMetafile
);
2344 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2347 static void test_mf_ExtTextOut_on_path(void)
2350 HMETAFILE hMetafile
;
2352 static const INT dx
[4] = { 3, 5, 8, 12 };
2354 hdcMetafile
= CreateMetaFileA(NULL
);
2355 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2356 trace("hdcMetafile %p\n", hdcMetafile
);
2358 ret
= BeginPath(hdcMetafile
);
2359 ok(!ret
, "BeginPath on metafile DC should fail\n");
2361 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2362 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2364 ret
= EndPath(hdcMetafile
);
2365 ok(!ret
, "EndPath on metafile DC should fail\n");
2367 hMetafile
= CloseMetaFile(hdcMetafile
);
2368 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2370 if (compare_mf_bits(hMetafile
, MF_TEXTOUT_ON_PATH_BITS
, sizeof(MF_TEXTOUT_ON_PATH_BITS
),
2371 "mf_TextOut_on_path") != 0)
2373 dump_mf_bits(hMetafile
, "mf_TextOut_on_path");
2374 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2377 ret
= DeleteMetaFile(hMetafile
);
2378 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2381 static void test_emf_ExtTextOut_on_path(void)
2384 HDC hdcDisplay
, hdcMetafile
;
2385 HENHMETAFILE hMetafile
;
2387 static const INT dx
[4] = { 3, 5, 8, 12 };
2389 /* Win9x doesn't play EMFs on invisible windows */
2390 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2391 0, 0, 200, 200, 0, 0, 0, NULL
);
2392 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2394 hdcDisplay
= GetDC(hwnd
);
2395 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
2397 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
2398 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2400 ret
= BeginPath(hdcMetafile
);
2401 ok(ret
, "BeginPath error %d\n", GetLastError());
2403 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2404 todo_wine
ok(ret
, "ExtTextOut error %d\n", GetLastError());
2406 ret
= EndPath(hdcMetafile
);
2407 ok(ret
, "EndPath error %d\n", GetLastError());
2409 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2410 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2412 /* this doesn't succeed yet: EMF has correct size, all EMF records
2413 * are there, but their contents don't match for different reasons.
2415 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_ON_PATH_BITS
),
2416 "emf_TextOut_on_path", FALSE
) != 0)
2418 dump_emf_bits(hMetafile
, "emf_TextOut_on_path");
2419 dump_emf_records(hMetafile
, "emf_TextOut_on_path");
2422 ret
= DeleteEnhMetaFile(hMetafile
);
2423 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2424 ret
= ReleaseDC(hwnd
, hdcDisplay
);
2425 ok(ret
, "ReleaseDC error %d\n", GetLastError());
2426 DestroyWindow(hwnd
);
2429 static const unsigned char EMF_CLIPPING
[] =
2431 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2433 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2435 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2436 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2437 0x04, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2438 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2440 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
2441 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
2442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2443 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
2444 0x30, 0xda, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2445 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2446 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2447 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2448 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2449 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2450 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2451 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2452 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2453 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2454 0x00, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
2455 0x08, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
2456 0x18, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2457 0x64, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00,
2458 0xff, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
2459 0x08, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
2460 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2461 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
2462 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2463 0x14, 0x00, 0x00, 0x00
2466 static void translate( POINT
*pt
, UINT count
, const XFORM
*xform
)
2470 FLOAT x
= (FLOAT
)pt
->x
;
2471 FLOAT y
= (FLOAT
)pt
->y
;
2472 pt
->x
= (LONG
)floor( x
* xform
->eM11
+ y
* xform
->eM21
+ xform
->eDx
+ 0.5 );
2473 pt
->y
= (LONG
)floor( x
* xform
->eM12
+ y
* xform
->eM22
+ xform
->eDy
+ 0.5 );
2478 /* Compare rectangles allowing rounding errors */
2479 static BOOL
is_equal_rect(const RECT
*rc1
, const RECT
*rc2
)
2481 return abs(rc1
->left
- rc2
->left
) <= 1 &&
2482 abs(rc1
->top
- rc2
->top
) <= 1 &&
2483 abs(rc1
->right
- rc2
->right
) <= 1 &&
2484 abs(rc1
->bottom
- rc2
->bottom
) <= 1;
2487 static int CALLBACK
clip_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2488 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
2490 if (emr
->iType
== EMR_EXTSELECTCLIPRGN
)
2492 const EMREXTSELECTCLIPRGN
*clip
= (const EMREXTSELECTCLIPRGN
*)emr
;
2496 char buf
[sizeof(RGNDATAHEADER
) + sizeof(RECT
)];
2498 const union _rgn
*rgn1
;
2500 RECT rect
, rc_transformed
;
2501 const RECT
*rc
= (const RECT
*)param
;
2507 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2508 clip
->cbRgnData
, clip
->iMode
);
2510 ok(clip
->iMode
== RGN_COPY
, "expected RGN_COPY, got %u\n", clip
->iMode
);
2511 ok(clip
->cbRgnData
>= sizeof(RGNDATAHEADER
) + sizeof(RECT
),
2512 "too small data block: %u bytes\n", clip
->cbRgnData
);
2513 if (clip
->cbRgnData
< sizeof(RGNDATAHEADER
) + sizeof(RECT
))
2516 rgn1
= (const union _rgn
*)clip
->RgnData
;
2518 trace("size %u, type %u, count %u, rgn size %u, bound %s\n",
2519 rgn1
->data
.rdh
.dwSize
, rgn1
->data
.rdh
.iType
,
2520 rgn1
->data
.rdh
.nCount
, rgn1
->data
.rdh
.nRgnSize
,
2521 wine_dbgstr_rect(&rgn1
->data
.rdh
.rcBound
));
2523 ok(EqualRect(&rgn1
->data
.rdh
.rcBound
, rc
), "rects don't match\n");
2525 rect
= *(const RECT
*)rgn1
->data
.Buffer
;
2526 trace("rect %s\n", wine_dbgstr_rect(&rect
));
2527 ok(EqualRect(&rect
, rc
), "rects don't match\n");
2529 ok(rgn1
->data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn1
->data
.rdh
.dwSize
);
2530 ok(rgn1
->data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn1
->data
.rdh
.iType
);
2531 ok(rgn1
->data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn1
->data
.rdh
.nCount
);
2532 ok(rgn1
->data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2533 broken(rgn1
->data
.rdh
.nRgnSize
== 168), /* NT4 */
2534 "expected sizeof(RECT), got %u\n", rgn1
->data
.rdh
.nRgnSize
);
2536 hrgn
= CreateRectRgn(0, 0, 0, 0);
2538 memset(&xform
, 0, sizeof(xform
));
2539 SetLastError(0xdeadbeef);
2540 ret
= GetWorldTransform(hdc
, &xform
);
2541 is_win9x
= !ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
;
2543 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
2545 trace("xform.eM11 %f, xform.eM22 %f\n", xform
.eM11
, xform
.eM22
);
2547 ret
= GetClipRgn(hdc
, hrgn
);
2548 ok(ret
== 0, "GetClipRgn returned %d, expected 0\n", ret
);
2550 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
2552 ret
= GetClipRgn(hdc
, hrgn
);
2553 ok(ret
== 1, "GetClipRgn returned %d, expected 1\n", ret
);
2555 /* Win9x returns empty clipping region */
2556 if (is_win9x
) return 1;
2558 ret
= GetRegionData(hrgn
, 0, NULL
);
2559 ok(ret
== sizeof(rgn2
.data
.rdh
) + sizeof(RECT
), "expected sizeof(rgn), got %u\n", ret
);
2561 ret
= GetRegionData(hrgn
, sizeof(rgn2
), &rgn2
.data
);
2562 ok(ret
== sizeof(rgn2
), "expected sizeof(rgn2), got %u\n", ret
);
2564 trace("size %u, type %u, count %u, rgn size %u, bound %s\n", rgn2
.data
.rdh
.dwSize
,
2565 rgn2
.data
.rdh
.iType
, rgn2
.data
.rdh
.nCount
, rgn2
.data
.rdh
.nRgnSize
,
2566 wine_dbgstr_rect(&rgn2
.data
.rdh
.rcBound
));
2568 rect
= rgn2
.data
.rdh
.rcBound
;
2569 rc_transformed
= *rc
;
2570 translate((POINT
*)&rc_transformed
, 2, &xform
);
2571 trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed
));
2572 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2574 rect
= *(const RECT
*)rgn2
.data
.Buffer
;
2575 trace("rect %s\n", wine_dbgstr_rect(&rect
));
2576 rc_transformed
= *rc
;
2577 translate((POINT
*)&rc_transformed
, 2, &xform
);
2578 trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed
));
2579 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2581 ok(rgn2
.data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn2
.data
.rdh
.dwSize
);
2582 ok(rgn2
.data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn2
.data
.rdh
.iType
);
2583 ok(rgn2
.data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn2
.data
.rdh
.nCount
);
2584 ok(rgn2
.data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2585 broken(rgn2
.data
.rdh
.nRgnSize
== 168), /* NT4 */
2586 "expected sizeof(RECT), got %u\n", rgn2
.data
.rdh
.nRgnSize
);
2593 static void test_emf_clipping(void)
2595 static const RECT rc
= { 0, 0, 100, 100 };
2596 RECT rc_clip
= { 100, 100, 1024, 1024 };
2602 RECT rc_res
, rc_sclip
;
2604 SetLastError(0xdeadbeef);
2605 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2606 ok(hdc
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2608 /* Need to write something to the emf, otherwise Windows won't play it back */
2611 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2612 ret
= SelectClipRgn(hdc
, hrgn
);
2613 ok(ret
== SIMPLEREGION
, "expected SIMPLEREGION, got %d\n", ret
);
2616 Rectangle(hdc
, rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2618 ret
= SelectClipPath(hdc
, RGN_AND
);
2619 ok(ret
, "SelectClipPath error %d\n", GetLastError());
2621 SetLastError(0xdeadbeef);
2622 hemf
= CloseEnhMetaFile(hdc
);
2623 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2625 if (compare_emf_bits(hemf
, EMF_CLIPPING
, sizeof(EMF_CLIPPING
),
2626 "emf_clipping", FALSE
) != 0)
2628 dump_emf_bits(hemf
, "emf_clipping");
2629 dump_emf_records(hemf
, "emf_clipping");
2634 /* Win9x doesn't play EMFs on invisible windows */
2635 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2636 0, 0, 200, 200, 0, 0, 0, NULL
);
2637 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2641 ret
= EnumEnhMetaFile(hdc
, hemf
, clip_emf_enum_proc
, &rc_clip
, &rc
);
2642 ok(ret
, "EnumEnhMetaFile error %d\n", GetLastError());
2644 DeleteEnhMetaFile(hemf
);
2645 ReleaseDC(hwnd
, hdc
);
2646 DestroyWindow(hwnd
);
2648 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2650 SetRect(&rc_sclip
, 100, 100, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2651 hrgn
= CreateRectRgn(rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
);
2652 SelectClipRgn(hdc
, hrgn
);
2653 SetRect(&rc_res
, -1, -1, -1, -1);
2654 ret
= GetClipBox(hdc
, &rc_res
);
2655 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2656 ok(EqualRect(&rc_res
, &rc_sclip
), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip
),
2657 wine_dbgstr_rect(&rc_res
));
2659 OffsetRect(&rc_sclip
, -100, -100);
2660 ret
= OffsetClipRgn(hdc
, -100, -100);
2661 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2662 SetRect(&rc_res
, -1, -1, -1, -1);
2663 ret
= GetClipBox(hdc
, &rc_res
);
2664 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2665 ok(EqualRect(&rc_res
, &rc_sclip
), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip
),
2666 wine_dbgstr_rect(&rc_res
));
2668 ret
= IntersectClipRect(hdc
, 0, 0, 100, 100);
2669 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2670 if (ret
== COMPLEXREGION
)
2672 /* XP returns COMPLEXREGION although region contains only 1 rect */
2673 ret
= GetClipRgn(hdc
, hrgn
);
2674 ok(ret
== 1, "expected 1, got %d\n", ret
);
2675 ret
= rgn_rect_count(hrgn
);
2676 ok(ret
== 1, "expected 1, got %d\n", ret
);
2678 SetRect(&rc_res
, -1, -1, -1, -1);
2679 ret
= GetClipBox(hdc
, &rc_res
);
2680 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2681 ok(EqualRect(&rc_res
, &rc
), "expected %s, got %s\n", wine_dbgstr_rect(&rc
),
2682 wine_dbgstr_rect(&rc_res
));
2684 SetRect(&rc_sclip
, 0, 0, 100, 50);
2685 ret
= ExcludeClipRect(hdc
, 0, 50, 100, 100);
2686 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2687 if (ret
== COMPLEXREGION
)
2689 /* XP returns COMPLEXREGION although region contains only 1 rect */
2690 ret
= GetClipRgn(hdc
, hrgn
);
2691 ok(ret
== 1, "expected 1, got %d\n", ret
);
2692 ret
= rgn_rect_count(hrgn
);
2693 ok(ret
== 1, "expected 1, got %d\n", ret
);
2695 SetRect(&rc_res
, -1, -1, -1, -1);
2696 ret
= GetClipBox(hdc
, &rc_res
);
2697 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2698 ok(EqualRect(&rc_res
, &rc_sclip
), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip
),
2699 wine_dbgstr_rect(&rc_res
));
2701 hemf
= CloseEnhMetaFile(hdc
);
2702 DeleteEnhMetaFile(hemf
);
2706 static const unsigned char MF_CLIP_BITS
[] = {
2708 0x01, 0x00, /* mtType */
2709 0x09, 0x00, /* mtHeaderSize */
2710 0x00, 0x03, /* mtVersion */
2711 0x32, 0x00, 0x00, 0x00, /* mtSize */
2712 0x01, 0x00, /* mtNoObjects */
2713 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2714 0x00, 0x00, /* reserved */
2716 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2717 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2718 0xff, 0x06, /* META_CREATEREGION */
2719 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2720 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2721 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2722 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2725 /* METARECORD for SelectObject */
2726 0x04, 0x00, 0x00, 0x00,
2727 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2731 0x04, 0x00, 0x00, 0x00,
2732 0xf0, 0x01, /* META_DELETEOBJECT */
2735 /* METARECORD for MoveTo(1,0x30) */
2736 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2737 0x14, 0x02, /* META_MOVETO */
2741 /* METARECORD for LineTo(0x20, 0x30) */
2742 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2743 0x13, 0x02, /* META_LINETO */
2748 0x03, 0x00, 0x00, 0x00,
2752 static int clip_mf_enum_proc_seen_selectclipregion
;
2753 static int clip_mf_enum_proc_seen_selectobject
;
2755 static int CALLBACK
clip_mf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2756 METARECORD
*mr
, int n_objs
, LPARAM param
)
2758 switch (mr
->rdFunction
) {
2759 case META_SELECTCLIPREGION
:
2760 clip_mf_enum_proc_seen_selectclipregion
++;
2762 case META_SELECTOBJECT
:
2763 clip_mf_enum_proc_seen_selectobject
++;
2769 static void test_mf_clipping(void)
2771 /* left top right bottom */
2772 static RECT rc_clip
= { 0x11, 0x22, 0x33, 0x44 };
2779 SetLastError(0xdeadbeef);
2780 hdc
= CreateMetaFileA(NULL
);
2781 ok(hdc
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2783 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2784 ret
= SelectClipRgn(hdc
, hrgn
);
2785 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2786 ok(ret
== NULLREGION
, "expected NULLREGION, got %d\n", ret
);
2788 /* Draw a line that starts off left of the clip region and ends inside it */
2789 MoveToEx(hdc
, 0x1, 0x30, NULL
);
2790 LineTo(hdc
, 0x20, 0x30);
2792 SetLastError(0xdeadbeef);
2793 hmf
= CloseMetaFile(hdc
);
2794 ok(hmf
!= 0, "CloseMetaFile error %d\n", GetLastError());
2796 if (compare_mf_bits(hmf
, MF_CLIP_BITS
, sizeof(MF_CLIP_BITS
),
2797 "mf_clipping") != 0)
2799 dump_mf_bits(hmf
, "mf_clipping");
2804 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2805 0, 0, 200, 200, 0, 0, 0, NULL
);
2806 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2810 ret
= EnumMetaFile(hdc
, hmf
, clip_mf_enum_proc
, (LPARAM
)&rc_clip
);
2811 ok(ret
, "EnumMetaFile error %d\n", GetLastError());
2813 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2814 ok(clip_mf_enum_proc_seen_selectclipregion
== 0,
2815 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion
);
2816 ok(clip_mf_enum_proc_seen_selectobject
== 1,
2817 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject
);
2819 DeleteMetaFile(hmf
);
2820 ReleaseDC(hwnd
, hdc
);
2821 DestroyWindow(hwnd
);
2824 static const unsigned char MF_PATH_BITS
[] =
2826 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2827 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2828 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2829 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2830 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2831 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2832 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2833 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2834 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2835 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2836 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2839 static void test_mf_GetPath(void)
2846 SetLastError(0xdeadbeef);
2847 hdc
= CreateMetaFileA(NULL
);
2848 ok(hdc
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2851 ret
= MoveToEx(hdc
, 50, 50, NULL
);
2852 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2853 ret
= LineTo(hdc
, 50, 150);
2854 ok( ret
, "LineTo error %d.\n", GetLastError());
2855 ret
= LineTo(hdc
, 150, 150);
2856 ok( ret
, "LineTo error %d.\n", GetLastError());
2857 ret
= LineTo(hdc
, 150, 50);
2858 ok( ret
, "LineTo error %d.\n", GetLastError());
2859 ret
= LineTo(hdc
, 50, 50);
2860 ok( ret
, "LineTo error %d.\n", GetLastError());
2861 Rectangle(hdc
, 10, 10, 20, 20);
2864 size
= GetPath(hdc
, NULL
, NULL
, 0);
2865 ok( size
== -1, "GetPath returned %d.\n", size
);
2867 hmf
= CloseMetaFile(hdc
);
2868 ok(hmf
!= 0, "CloseMetaFile error %d\n", GetLastError());
2870 if (compare_mf_bits (hmf
, MF_PATH_BITS
, sizeof(MF_PATH_BITS
), "mf_GetPath") != 0)
2872 dump_mf_bits(hmf
, "mf_GetPath");
2873 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2876 ret
= DeleteMetaFile(hmf
);
2877 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
2880 static INT CALLBACK
EmfEnumProc(HDC hdc
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
, INT nObj
, LPARAM lpData
)
2882 LPMETAFILEPICT lpMFP
= (LPMETAFILEPICT
)lpData
;
2883 POINT mapping
[2] = { { 0, 0 }, { 10, 10 } };
2884 /* When using MM_TEXT Win9x does not update the mapping mode
2885 * until a record is played which actually outputs something */
2886 PlayEnhMetaFileRecord(hdc
, lpHTable
, lpEMFR
, nObj
);
2887 LPtoDP(hdc
, mapping
, 2);
2888 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2889 lpEMFR
->iType
, lpEMFR
->nSize
,
2890 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
);
2892 if (lpEMFR
->iType
== EMR_LINETO
)
2895 if (!lpMFP
|| lpMFP
->mm
== MM_TEXT
)
2899 x1
= (INT
)floor(10 * 100.0 / LINE_X
+ 0.5);
2900 y1
= (INT
)floor(10 * 100.0 / LINE_Y
+ 0.5);
2904 ok(lpMFP
->mm
== MM_ANISOTROPIC
, "mm=%d\n", lpMFP
->mm
);
2906 x0
= MulDiv(0, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2907 y0
= MulDiv(0, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2908 x1
= MulDiv(10, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2909 y1
= MulDiv(10, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2911 ok(mapping
[0].x
== x0
&& mapping
[0].y
== y0
&& mapping
[1].x
== x1
&& mapping
[1].y
== y1
,
2912 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2913 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
,
2919 static HENHMETAFILE
create_converted_emf(const METAFILEPICT
*mfp
)
2928 hdcMf
= CreateMetaFileA(NULL
);
2929 ok(hdcMf
!= NULL
, "CreateMetaFile failed with error %d\n", GetLastError());
2930 ret
= LineTo(hdcMf
, (INT
)LINE_X
, (INT
)LINE_Y
);
2931 ok(ret
, "LineTo failed with error %d\n", GetLastError());
2932 hmf
= CloseMetaFile(hdcMf
);
2933 ok(hmf
!= NULL
, "CloseMetaFile failed with error %d\n", GetLastError());
2935 if (compare_mf_bits (hmf
, MF_LINETO_BITS
, sizeof(MF_LINETO_BITS
), "mf_LineTo") != 0)
2937 dump_mf_bits(hmf
, "mf_LineTo");
2938 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2941 size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
2942 ok(size
, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2943 pBits
= HeapAlloc(GetProcessHeap(), 0, size
);
2944 GetMetaFileBitsEx(hmf
, size
, pBits
);
2945 DeleteMetaFile(hmf
);
2946 hemf
= SetWinMetaFileBits(size
, pBits
, NULL
, mfp
);
2947 HeapFree(GetProcessHeap(), 0, pBits
);
2951 static void test_mf_conversions(void)
2953 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2955 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2958 RECT rect
= { 0, 0, 100, 100 };
2959 mfp
.mm
= MM_ANISOTROPIC
;
2963 hemf
= create_converted_emf(&mfp
);
2965 if (compare_emf_bits(hemf
, EMF_LINETO_MM_ANISOTROPIC_BITS
, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS
),
2966 "emf_LineTo MM_ANISOTROPIC", TRUE
) != 0)
2968 dump_emf_bits(hemf
, "emf_LineTo MM_ANISOTROPIC");
2969 dump_emf_records(hemf
, "emf_LineTo MM_ANISOTROPIC");
2972 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2974 DeleteEnhMetaFile(hemf
);
2975 DeleteDC(hdcOffscreen
);
2978 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2980 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2983 RECT rect
= { 0, 0, 100, 100 };
2988 hemf
= create_converted_emf(&mfp
);
2990 if (compare_emf_bits(hemf
, EMF_LINETO_MM_TEXT_BITS
, sizeof(EMF_LINETO_MM_TEXT_BITS
),
2991 "emf_LineTo MM_TEXT", TRUE
) != 0)
2993 dump_emf_bits(hemf
, "emf_LineTo MM_TEXT");
2994 dump_emf_records(hemf
, "emf_LineTo MM_TEXT");
2997 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2999 DeleteEnhMetaFile(hemf
);
3000 DeleteDC(hdcOffscreen
);
3003 trace("Testing MF->EMF conversion (NULL mfp)\n");
3005 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
3007 RECT rect
= { 0, 0, 100, 100 };
3008 hemf
= create_converted_emf(NULL
);
3010 if (compare_emf_bits(hemf
, EMF_LINETO_BITS
, sizeof(EMF_LINETO_BITS
),
3011 "emf_LineTo NULL", TRUE
) != 0)
3013 dump_emf_bits(hemf
, "emf_LineTo NULL");
3014 dump_emf_records(hemf
, "emf_LineTo NULL");
3017 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, NULL
, &rect
);
3019 DeleteEnhMetaFile(hemf
);
3020 DeleteDC(hdcOffscreen
);
3024 static BOOL
getConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
3025 LONG mm
, LONG xExt
, LONG yExt
,
3026 RECTL
* rclBounds
, RECTL
* rclFrame
)
3029 METAFILEPICT
* mfpPtr
= NULL
;
3031 ENHMETAHEADER header
;
3042 emf
= SetWinMetaFileBits(buffer_size
, buffer
, NULL
, mfpPtr
);
3043 ok(emf
!= NULL
, "SetWinMetaFileBits failed\n");
3044 if (!emf
) return FALSE
;
3045 res
= GetEnhMetaFileHeader(emf
, sizeof(header
), &header
);
3046 ok(res
!= 0, "GetEnhMetaHeader failed\n");
3047 DeleteEnhMetaFile(emf
);
3048 if (!res
) return FALSE
;
3050 *rclBounds
= header
.rclBounds
;
3051 *rclFrame
= header
.rclFrame
;
3055 static void checkConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
3056 LONG mm
, LONG xExt
, LONG yExt
,
3057 RECTL
* rclBoundsExpected
, RECTL
* rclFrameExpected
)
3059 RECTL rclBounds
, rclFrame
;
3061 if (getConvertedFrameAndBounds(buffer_size
, buffer
, mfpIsNull
, mm
, xExt
, yExt
, &rclBounds
, &rclFrame
))
3068 msg
= "mfp == NULL";
3072 const char * mm_str
;
3075 case MM_ANISOTROPIC
: mm_str
= "MM_ANISOTROPIC"; break;
3076 case MM_ISOTROPIC
: mm_str
= "MM_ISOTROPIC"; break;
3077 default: mm_str
= "Unexpected";
3079 sprintf(buf
, "mm=%s, xExt=%d, yExt=%d", mm_str
, xExt
, yExt
);
3083 ok(rclBounds
.left
== rclBoundsExpected
->left
, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected
->left
, rclBounds
.left
, msg
);
3084 ok(rclBounds
.top
== rclBoundsExpected
->top
, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected
->top
, rclBounds
.top
, msg
);
3085 ok(rclBounds
.right
== rclBoundsExpected
->right
, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected
->right
, rclBounds
.right
, msg
);
3086 ok(rclBounds
.bottom
== rclBoundsExpected
->bottom
, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected
->bottom
, rclBounds
.bottom
, msg
);
3087 ok(rclFrame
.left
== rclFrameExpected
->left
, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected
->left
, rclFrame
.left
, msg
);
3088 ok(rclFrame
.top
== rclFrameExpected
->top
, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected
->top
, rclFrame
.top
, msg
);
3089 ok(rclFrame
.right
== rclFrameExpected
->right
, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected
->right
, rclFrame
.right
, msg
);
3090 ok(rclFrame
.bottom
== rclFrameExpected
->bottom
, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected
->bottom
, rclFrame
.bottom
, msg
);
3094 static void test_SetWinMetaFileBits(void)
3102 RECTL rclBoundsAnisotropic
, rclFrameAnisotropic
;
3103 RECTL rclBoundsIsotropic
, rclFrameIsotropic
;
3104 RECTL rclBounds
, rclFrame
;
3108 wmfDC
= CreateMetaFileA(NULL
);
3109 ok(wmfDC
!= NULL
, "CreateMetaFile failed\n");
3112 SetWindowExtEx(wmfDC
, 100, 100, NULL
);
3113 SetRect(&rect
, 0, 0, 50, 50);
3114 FillRect(wmfDC
, &rect
, GetStockObject(BLACK_BRUSH
));
3115 wmf
= CloseMetaFile(wmfDC
);
3116 ok(wmf
!= NULL
, "Metafile creation failed\n");
3119 buffer_size
= GetMetaFileBitsEx(wmf
, 0, NULL
);
3120 ok(buffer_size
!= 0, "GetMetaFileBitsEx failed\n");
3121 if (buffer_size
== 0)
3123 DeleteMetaFile(wmf
);
3127 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
);
3128 ok(buffer
!= NULL
, "HeapAlloc failed\n");
3131 DeleteMetaFile(wmf
);
3135 res
= GetMetaFileBitsEx(wmf
, buffer_size
, buffer
);
3136 ok(res
== buffer_size
, "GetMetaFileBitsEx failed\n");
3137 DeleteMetaFile(wmf
);
3138 if (res
!= buffer_size
)
3140 HeapFree(GetProcessHeap(), 0, buffer
);
3144 /* Get the reference bounds and frame */
3145 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3146 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3148 ok(rclBoundsAnisotropic
.left
== 0 && rclBoundsAnisotropic
.top
== 0 &&
3149 rclBoundsIsotropic
.left
== 0 && rclBoundsIsotropic
.top
== 0,
3150 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3152 ok(rclBoundsAnisotropic
.right
>= rclBoundsIsotropic
.right
, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3153 ok(rclBoundsAnisotropic
.bottom
>= rclBoundsIsotropic
.bottom
, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3154 diffx
= rclBoundsIsotropic
.right
- rclBoundsIsotropic
.bottom
;
3155 if (diffx
< 0) diffx
= -diffx
;
3156 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3158 dc
= CreateCompatibleDC(NULL
);
3160 /* Allow 1 mm difference (rounding errors) */
3161 diffx
= rclBoundsAnisotropic
.right
- GetDeviceCaps(dc
, HORZRES
) / 2;
3162 diffy
= rclBoundsAnisotropic
.bottom
- GetDeviceCaps(dc
, VERTRES
) / 2;
3163 if (diffx
< 0) diffx
= -diffx
;
3164 if (diffy
< 0) diffy
= -diffy
;
3167 ok(diffx
<= 1 && diffy
<= 1,
3168 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3169 GetDeviceCaps(dc
, HORZRES
) / 2, GetDeviceCaps(dc
, VERTRES
) / 2, rclBoundsAnisotropic
.right
, rclBoundsAnisotropic
.bottom
);
3172 /* Allow 1 mm difference (rounding errors) */
3173 diffx
= rclFrameAnisotropic
.right
/ 100 - GetDeviceCaps(dc
, HORZSIZE
) / 2;
3174 diffy
= rclFrameAnisotropic
.bottom
/ 100 - GetDeviceCaps(dc
, VERTSIZE
) / 2;
3175 if (diffx
< 0) diffx
= -diffx
;
3176 if (diffy
< 0) diffy
= -diffy
;
3179 ok(diffx
<= 1 && diffy
<= 1,
3180 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3181 GetDeviceCaps(dc
, HORZSIZE
) / 2, GetDeviceCaps(dc
, VERTSIZE
) / 2, rclFrameAnisotropic
.right
/ 100, rclFrameAnisotropic
.bottom
/ 100);
3185 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3186 checkConvertedFrameAndBounds(buffer_size
, buffer
, TRUE
, 0, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3188 /* If xExt or yExt is zero or negative, the whole device surface is used */
3189 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3190 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3191 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3192 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3193 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3194 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3195 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3196 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3197 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3198 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3199 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3200 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3202 /* MSDN says that negative xExt and yExt values specify a ratio.
3203 Check that this is wrong and the whole device surface is used */
3204 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -1000, -100, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3205 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -1000, -100, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3207 /* Ordinary conversions */
3209 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3211 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3212 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3213 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0 && rclBounds
.right
> rclBounds
.bottom
,
3214 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3217 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3219 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3220 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3221 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0,
3222 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3224 /* Wine has a rounding error */
3225 diffx
= rclBounds
.right
- rclBounds
.bottom
;
3226 if (diffx
< 0) diffx
= -diffx
;
3227 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3230 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_HIMETRIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3232 ok(rclFrame
.right
- rclFrame
.left
!= 30000 && rclFrame
.bottom
- rclFrame
.top
!= 20000,
3233 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3236 HeapFree(GetProcessHeap(), 0, buffer
);
3239 static BOOL
near_match(int x
, int y
)
3241 int epsilon
= min(abs(x
), abs(y
));
3243 epsilon
= max(epsilon
/100, 2);
3245 if(x
< y
- epsilon
|| x
> y
+ epsilon
) return FALSE
;
3249 static void getwinmetafilebits(UINT mode
, int scale
, RECT
*rc
)
3251 HENHMETAFILE emf
, emf2
;
3252 HDC display_dc
, emf_dc
;
3253 ENHMETAHEADER
*enh_header
, *enh2_header
;
3254 UINT size
, emf_size
, i
, emf2_size
;
3257 METAHEADER
*mh
= NULL
;
3259 INT horz_res
, vert_res
, horz_size
, vert_size
;
3260 INT curve_caps
, line_caps
, poly_caps
;
3263 display_dc
= GetDC(NULL
);
3264 ok(display_dc
!= NULL
, "display_dc is NULL\n");
3266 horz_res
= GetDeviceCaps(display_dc
, HORZRES
);
3267 vert_res
= GetDeviceCaps(display_dc
, VERTRES
);
3268 horz_size
= GetDeviceCaps(display_dc
, HORZSIZE
);
3269 vert_size
= GetDeviceCaps(display_dc
, VERTSIZE
);
3271 emf_dc
= CreateEnhMetaFileA(display_dc
, NULL
, rc
, NULL
);
3272 ok(emf_dc
!= NULL
, "emf_dc is NULL\n");
3274 curve_caps
= GetDeviceCaps(emf_dc
, CURVECAPS
);
3275 ok(curve_caps
== 511, "expect 511 got %d\n", curve_caps
);
3277 line_caps
= GetDeviceCaps(emf_dc
, LINECAPS
);
3278 ok(line_caps
== 254, "expect 254 got %d\n", line_caps
);
3280 poly_caps
= GetDeviceCaps(emf_dc
, POLYGONALCAPS
);
3281 ok(poly_caps
== 255, "expect 511 got %d\n", poly_caps
);
3283 for(i
= 0; i
< 3000; i
++) /* This is enough to take emf_size > 0xffff */
3284 Rectangle(emf_dc
, 0, 0, 1000, 20);
3285 emf
= CloseEnhMetaFile(emf_dc
);
3286 ok(emf
!= NULL
, "emf is NULL\n");
3288 emf_size
= GetEnhMetaFileBits(emf
, 0, NULL
);
3289 enh_header
= HeapAlloc(GetProcessHeap(), 0, emf_size
);
3290 emf_size
= GetEnhMetaFileBits(emf
, emf_size
, (BYTE
*)enh_header
);
3291 DeleteEnhMetaFile(emf
);
3292 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3293 have different resolutions */
3294 enh_header
->szlDevice
.cx
*= scale
;
3295 emf
= SetEnhMetaFileBits(emf_size
, (BYTE
*)enh_header
);
3296 ok(emf
!= NULL
, "emf is NULL\n");
3297 ok(EqualRect((RECT
*)&enh_header
->rclFrame
, rc
), "Frame rectangles differ\n");
3299 size
= GetWinMetaFileBits(emf
, 0, NULL
, mode
, display_dc
);
3301 broken(size
== 0), /* some versions of winxp fail for some reason */
3302 "GetWinMetaFileBits returns 0\n");
3304 mh
= HeapAlloc(GetProcessHeap(), 0, size
);
3305 GetWinMetaFileBits(emf
, size
, (BYTE
*)mh
, mode
, display_dc
);
3307 for(i
= 0; i
< size
/ 2; i
++) check
+= ((WORD
*)mh
)[i
];
3308 ok(check
== 0, "check %04x\n", check
);
3310 rec
= (METARECORD
*)(mh
+ 1);
3312 while(rec
->rdSize
&& rec
->rdFunction
)
3314 const DWORD chunk_size
= 0x2000;
3315 DWORD mfcomment_chunks
= (emf_size
+ chunk_size
- 1) / chunk_size
;
3317 if(rec_num
< mfcomment_chunks
)
3319 DWORD this_chunk_size
= chunk_size
;
3321 if(rec_num
== mfcomment_chunks
- 1)
3322 this_chunk_size
= emf_size
- rec_num
* chunk_size
;
3324 ok(rec
->rdSize
== (this_chunk_size
+ 44) / 2, "%04x: got %04x expected %04x\n", rec_num
, rec
->rdSize
, (this_chunk_size
+ 44) / 2);
3325 ok(rec
->rdFunction
== META_ESCAPE
, "%04x: got %04x\n", rec_num
, rec
->rdFunction
);
3326 if(rec
->rdSize
< (this_chunk_size
+ 44) / 2) break;
3327 ok(rec
->rdParm
[0] == MFCOMMENT
, "got %04x\n", rec
->rdParm
[0]);
3328 ok(rec
->rdParm
[1] == this_chunk_size
+ 34, "got %04x %x\n", rec
->rdParm
[1], emf_size
+ 34);
3329 ok(rec
->rdParm
[2] == 0x4d57, "got %04x\n", rec
->rdParm
[2]); /* WMFC */
3330 ok(rec
->rdParm
[3] == 0x4346, "got %04x\n", rec
->rdParm
[3]); /* " */
3331 ok(rec
->rdParm
[4] == 1, "got %04x\n", rec
->rdParm
[4]);
3332 ok(rec
->rdParm
[5] == 0, "got %04x\n", rec
->rdParm
[5]);
3333 ok(rec
->rdParm
[6] == 0, "got %04x\n", rec
->rdParm
[6]);
3334 ok(rec
->rdParm
[7] == 1, "got %04x\n", rec
->rdParm
[7]);
3335 /* parm[8] is the checksum, tested above */
3336 if(rec_num
> 0) ok(rec
->rdParm
[8] == 0, "got %04x\n", rec
->rdParm
[8]);
3337 ok(rec
->rdParm
[9] == 0, "got %04x\n", rec
->rdParm
[9]);
3338 ok(rec
->rdParm
[10] == 0, "got %04x\n", rec
->rdParm
[10]);
3339 ok(rec
->rdParm
[11] == mfcomment_chunks
, "got %04x\n", rec
->rdParm
[11]); /* num chunks */
3340 ok(rec
->rdParm
[12] == 0, "got %04x\n", rec
->rdParm
[12]);
3341 ok(rec
->rdParm
[13] == this_chunk_size
, "got %04x expected %04x\n", rec
->rdParm
[13], this_chunk_size
);
3342 ok(rec
->rdParm
[14] == 0, "got %04x\n", rec
->rdParm
[14]);
3343 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 */
3344 ok(*(DWORD
*)(rec
->rdParm
+ 17) == emf_size
, "got %08x emf_size %08x\n", *(DWORD
*)(rec
->rdParm
+ 17), emf_size
);
3345 ok(!memcmp(rec
->rdParm
+ 19, (char*)enh_header
+ rec_num
* chunk_size
, this_chunk_size
), "bits mismatch\n");
3348 else if(rec_num
== mfcomment_chunks
)
3350 ok(rec
->rdFunction
== META_SETMAPMODE
, "got %04x\n", rec
->rdFunction
);
3351 ok(rec
->rdParm
[0] == mode
, "got %04x\n", rec
->rdParm
[0]);
3353 else if(rec_num
== mfcomment_chunks
+ 1)
3356 ok(rec
->rdFunction
== META_SETWINDOWORG
, "got %04x\n", rec
->rdFunction
);
3361 case MM_ANISOTROPIC
:
3362 pt
.y
= MulDiv(rc
->top
, vert_res
, vert_size
* 100) + 1;
3363 pt
.x
= MulDiv(rc
->left
, horz_res
, horz_size
* 100);
3366 pt
.y
= MulDiv(-rc
->top
, 1, 10) + 1;
3367 pt
.x
= MulDiv( rc
->left
, 1, 10);
3370 pt
.y
= -rc
->top
+ 1;
3371 pt
.x
= (rc
->left
>= 0) ? rc
->left
: rc
->left
+ 1; /* strange but true */
3374 pt
.y
= MulDiv(-rc
->top
, 10, 254) + 1;
3375 pt
.x
= MulDiv( rc
->left
, 10, 254);
3378 pt
.y
= MulDiv(-rc
->top
, 100, 254) + 1;
3379 pt
.x
= MulDiv( rc
->left
, 100, 254);
3382 pt
.y
= MulDiv(-rc
->top
, 72 * 20, 2540) + 1;
3383 pt
.x
= MulDiv( rc
->left
, 72 * 20, 2540);
3388 ok(near_match((short)rec
->rdParm
[0], pt
.y
), "got %d expect %d\n", (short)rec
->rdParm
[0], pt
.y
);
3389 ok(near_match((short)rec
->rdParm
[1], pt
.x
), "got %d expect %d\n", (short)rec
->rdParm
[1], pt
.x
);
3391 if(rec_num
== mfcomment_chunks
+ 2)
3393 ok(rec
->rdFunction
== META_SETWINDOWEXT
, "got %04x\n", rec
->rdFunction
);
3394 ok(near_match((short)rec
->rdParm
[0], MulDiv(rc
->bottom
- rc
->top
, vert_res
, vert_size
* 100)),
3395 "got %d\n", (short)rec
->rdParm
[0]);
3396 ok(near_match((short)rec
->rdParm
[1], MulDiv(rc
->right
- rc
->left
, horz_res
, horz_size
* 100)),
3397 "got %d\n", (short)rec
->rdParm
[1]);
3401 rec
= (METARECORD
*)((WORD
*)rec
+ rec
->rdSize
);
3404 /* Show that we get the original back when we do the reverse conversion.
3405 mfp is ignored in this case. */
3406 mfp
.mm
= MM_ISOTROPIC
;
3409 emf2
= SetWinMetaFileBits( size
, (BYTE
*)mh
, NULL
, &mfp
);
3410 ok( !!emf2
, "got NULL\n" );
3411 emf2_size
= GetEnhMetaFileBits( emf2
, 0, NULL
);
3412 enh2_header
= HeapAlloc( GetProcessHeap(), 0, emf2_size
);
3413 emf2_size
= GetEnhMetaFileBits( emf2
, emf2_size
, (BYTE
*)enh2_header
);
3414 ok( emf_size
== emf2_size
, "%d %d\n", emf_size
, emf2_size
);
3415 ok( !memcmp( enh_header
, enh2_header
, emf_size
), "mismatch\n" );
3416 HeapFree( GetProcessHeap(), 0, enh2_header
);
3417 DeleteEnhMetaFile( emf2
);
3420 HeapFree(GetProcessHeap(), 0, mh
);
3421 HeapFree(GetProcessHeap(), 0, enh_header
);
3422 DeleteEnhMetaFile(emf
);
3424 ReleaseDC(NULL
, display_dc
);
3427 static void test_GetWinMetaFileBits(void)
3432 { 1000, 2000, 3000, 6000},
3433 {-1000, 2000, 3000, 6000},
3434 { 1000, -2000, 3000, 6000},
3435 { 1005, 2005, 3000, 6000},
3436 {-1005, -2005, 3000, 6000},
3437 {-1005, -2010, 3000, 6000},
3438 {-1005, 2010, 3000, 6000},
3444 for(mode
= MM_MIN
; mode
<= MM_MAX
; mode
++)
3447 for(rc
= frames
; rc
->right
- rc
->left
> 0; rc
++)
3449 getwinmetafilebits(mode
, 1, rc
);
3450 getwinmetafilebits(mode
, 2, rc
);
3455 static BOOL (WINAPI
*pGdiIsMetaPrintDC
)(HDC
);
3456 static BOOL (WINAPI
*pGdiIsMetaFileDC
)(HDC
);
3457 static BOOL (WINAPI
*pGdiIsPlayMetafileDC
)(HDC
);
3459 static void test_gdiis(void)
3461 RECT rect
= {0,0,100,100};
3462 HDC hdc
, hemfDC
, hmfDC
;
3466 /* resolve all the functions */
3467 hgdi32
= GetModuleHandleA("gdi32.dll");
3468 pGdiIsMetaPrintDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaPrintDC");
3469 pGdiIsMetaFileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaFileDC");
3470 pGdiIsPlayMetafileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsPlayMetafileDC");
3472 if(!pGdiIsMetaPrintDC
|| !pGdiIsMetaFileDC
|| !pGdiIsPlayMetafileDC
)
3474 win_skip("Needed GdiIs* functions are not available\n");
3478 /* try with nothing */
3479 ok(!pGdiIsMetaPrintDC(NULL
), "ismetaprint with NULL parameter\n");
3480 ok(!pGdiIsMetaFileDC(NULL
), "ismetafile with NULL parameter\n");
3481 ok(!pGdiIsPlayMetafileDC(NULL
), "isplaymetafile with NULL parameter\n");
3483 /* try with a metafile */
3484 hmfDC
= CreateMetaFileA(NULL
);
3485 ok(!pGdiIsMetaPrintDC(hmfDC
), "ismetaprint on metafile\n");
3486 ok(pGdiIsMetaFileDC(hmfDC
), "ismetafile on metafile\n");
3487 ok(!pGdiIsPlayMetafileDC(hmfDC
), "isplaymetafile on metafile\n");
3488 DeleteMetaFile(CloseMetaFile(hmfDC
));
3490 /* try with an enhanced metafile */
3492 hemfDC
= CreateEnhMetaFileW(hdc
, NULL
, &rect
, NULL
);
3493 ok(hemfDC
!= NULL
, "failed to create emf\n");
3495 ok(!pGdiIsMetaPrintDC(hemfDC
), "ismetaprint on emf\n");
3496 ok(pGdiIsMetaFileDC(hemfDC
), "ismetafile on emf\n");
3497 ok(!pGdiIsPlayMetafileDC(hemfDC
), "isplaymetafile on emf\n");
3499 hemf
= CloseEnhMetaFile(hemfDC
);
3500 ok(hemf
!= NULL
, "failed to close EMF\n");
3501 DeleteEnhMetaFile(hemf
);
3502 ReleaseDC(NULL
,hdc
);
3505 static void test_SetEnhMetaFileBits(void)
3511 memset(data
, 0xAA, sizeof(data
));
3512 SetLastError(0xdeadbeef);
3513 hemf
= SetEnhMetaFileBits(sizeof(data
), data
);
3514 ok(!hemf
, "SetEnhMetaFileBits should fail\n");
3515 ok(GetLastError() == ERROR_INVALID_DATA
||
3516 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x, WinMe */
3517 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3519 emh
= (ENHMETAHEADER
*)data
;
3520 memset(emh
, 0, sizeof(*emh
));
3522 emh
->iType
= EMR_HEADER
;
3523 emh
->nSize
= sizeof(*emh
);
3524 emh
->dSignature
= ENHMETA_SIGNATURE
;
3525 /* emh->nVersion = 0x10000; XP doesn't care about version */
3526 emh
->nBytes
= sizeof(*emh
);
3527 /* emh->nRecords = 1; XP doesn't care about records */
3528 emh
->nHandles
= 1; /* XP refuses to load a EMF if nHandles == 0 */
3530 SetLastError(0xdeadbeef);
3531 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3532 ok(hemf
!= 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3533 DeleteEnhMetaFile(hemf
);
3535 /* XP refuses to load unaligned EMF */
3537 SetLastError(0xdeadbeef);
3538 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3540 broken(hemf
!= NULL
), /* Win9x, WinMe */
3541 "SetEnhMetaFileBits should fail\n");
3542 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3543 DeleteEnhMetaFile(hemf
);
3545 emh
->dSignature
= 0;
3547 SetLastError(0xdeadbeef);
3548 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3550 broken(hemf
!= NULL
), /* Win9x, WinMe */
3551 "SetEnhMetaFileBits should fail\n");
3552 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3553 DeleteEnhMetaFile(hemf
);
3556 static void test_emf_polybezier(void)
3563 SetLastError(0xdeadbeef);
3564 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3565 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3567 pts
[0].x
= pts
[0].y
= 10;
3568 pts
[1].x
= pts
[1].y
= 20;
3569 pts
[2].x
= pts
[2].y
= 15;
3570 pts
[3].x
= pts
[3].y
= 25;
3571 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO16 */
3572 ok( ret
, "PolyBezierTo failed\n" );
3573 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER16 */
3574 ok( ret
, "PolyBezier failed\n" );
3576 pts
[0].x
= pts
[0].y
= 32769;
3577 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER */
3578 ok( ret
, "PolyBezier failed\n" );
3579 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO */
3580 ok( ret
, "PolyBezierTo failed\n" );
3582 hemf
= CloseEnhMetaFile(hdcMetafile
);
3583 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3585 if(compare_emf_bits(hemf
, EMF_BEZIER_BITS
, sizeof(EMF_BEZIER_BITS
),
3586 "emf_Bezier", FALSE
) != 0)
3588 dump_emf_bits(hemf
, "emf_Bezier");
3589 dump_emf_records(hemf
, "emf_Bezier");
3592 DeleteEnhMetaFile(hemf
);
3595 static const unsigned char EMF_PATH_BITS
[] =
3597 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3598 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3599 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3600 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
3601 0x70, 0x17, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00,
3602 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3603 0xf8, 0x02, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3604 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3606 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3607 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3608 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3609 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3610 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3611 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3612 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3613 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3614 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3615 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3616 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3617 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3618 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3619 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3620 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3621 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3622 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3623 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3624 0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
3625 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3626 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3627 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3628 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3629 0x15, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
3630 0x28, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3631 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3632 0x1a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
3633 0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3634 0x17, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
3635 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3636 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3637 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3638 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3639 0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
3640 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3641 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3642 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3643 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3644 0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
3645 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3646 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3647 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3648 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3649 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3650 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3651 0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
3652 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3653 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3654 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
3655 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3656 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3657 0x59, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3659 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3660 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
3661 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00,
3662 0x14, 0x00, 0x14, 0x00, 0x5a, 0x00, 0x00, 0x00,
3663 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3664 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3665 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
3666 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3667 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
3668 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00,
3669 0x14, 0x00, 0x14, 0x00, 0x5c, 0x00, 0x00, 0x00,
3670 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3671 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3672 0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00,
3673 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3674 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3675 0x1e, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x14, 0x00,
3676 0x14, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x14, 0x00,
3677 0x14, 0x00, 0x0a, 0x00, 0x06, 0x02, 0x04, 0x04,
3678 0x04, 0x02, 0x03, 0x06, 0x02, 0x00, 0x00, 0x00,
3679 0x29, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
3680 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3681 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x42,
3682 0x00, 0x00, 0x34, 0x43, 0x3c, 0x00, 0x00, 0x00,
3683 0x08, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
3684 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3685 0x0a, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3686 0x96, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
3687 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3688 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3689 0xff, 0xff, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00,
3690 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3691 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3694 static const unsigned char EMF_EMPTY_PATH_BITS
[] =
3696 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3698 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3700 0xd8, 0xff, 0xff, 0xff, 0xd8, 0xff, 0xff, 0xff,
3701 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3702 0xc8, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
3703 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3704 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3705 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3706 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3708 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3709 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3710 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
3711 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
3712 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3713 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3714 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
3715 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
3716 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
3717 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
3718 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3719 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3720 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3723 static void test_emf_paths(void)
3725 POINT pts
[9] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}, {30, 30}, {40, 20}, {20, 30}, {20, 20}, {20, 10}};
3726 DWORD counts
[2] = {2, 2};
3727 BYTE types
[9] = { PT_MOVETO
, PT_LINETO
, PT_BEZIERTO
, PT_BEZIERTO
, PT_BEZIERTO
, PT_LINETO
,
3728 PT_LINETO
| PT_CLOSEFIGURE
, PT_MOVETO
, PT_LINETO
};
3734 SetLastError(0xdeadbeef);
3735 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3736 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3738 BeginPath(hdcMetafile
);
3739 ret
= MoveToEx(hdcMetafile
, 50, 50, NULL
);
3740 ok( ret
, "MoveToEx error %d.\n", GetLastError());
3741 ret
= LineTo(hdcMetafile
, 50, 150);
3742 ok( ret
, "LineTo error %d.\n", GetLastError());
3743 ret
= LineTo(hdcMetafile
, 150, 150);
3744 ok( ret
, "LineTo error %d.\n", GetLastError());
3745 ret
= LineTo(hdcMetafile
, 150, 50);
3746 ok( ret
, "LineTo error %d.\n", GetLastError());
3747 ret
= LineTo(hdcMetafile
, 50, 50);
3748 ok( ret
, "LineTo error %d.\n", GetLastError());
3749 Rectangle(hdcMetafile
, 10, 10, 20, 20);
3750 Arc(hdcMetafile
, 21, 21, 39, 29, 39, 29, 21, 21);
3751 ArcTo(hdcMetafile
, 23, 23, 37, 27, 37, 27, 23, 23);
3752 Chord(hdcMetafile
, 21, 21, 39, 29, 39, 29, 21, 21);
3753 Pie(hdcMetafile
, 21, 21, 39, 29, 39, 29, 21, 21);
3754 Ellipse(hdcMetafile
, 10, 10, 20, 20);
3755 RoundRect(hdcMetafile
, 10, 10, 20, 20, 3, 5);
3756 Polyline(hdcMetafile
, pts
, 4);
3757 PolylineTo(hdcMetafile
, pts
, 4);
3758 PolyPolyline(hdcMetafile
, pts
, counts
, 2);
3759 PolyDraw(hdcMetafile
, pts
, types
, 9);
3760 AngleArc(hdcMetafile
, 37, 36, 23, 90, 180);
3761 EndPath(hdcMetafile
);
3763 size
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
3764 ok( size
== 112, "GetPath returned %d.\n", size
);
3766 ret
= StrokeAndFillPath( hdcMetafile
);
3767 ok( ret
, "StrokeAndFillPath failed err %d\n", GetLastError() );
3768 ret
= StrokeAndFillPath( hdcMetafile
);
3769 ok( !ret
, "StrokeAndFillPath succeeded\n" );
3771 hemf
= CloseEnhMetaFile(hdcMetafile
);
3772 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3774 if (compare_emf_bits(hemf
, EMF_PATH_BITS
, sizeof(EMF_PATH_BITS
), "test_emf_paths", FALSE
) != 0)
3776 dump_emf_bits(hemf
, "test_emf_paths");
3777 dump_emf_records(hemf
, "test_emf_paths");
3780 DeleteEnhMetaFile(hemf
);
3782 SetLastError(0xdeadbeef);
3783 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3784 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3786 ret
= BeginPath(hdcMetafile
);
3787 ok( ret
, "BeginPath failed error %d\n", GetLastError() );
3788 ret
= CloseFigure(hdcMetafile
);
3789 ok( ret
, "CloseFigure failed error %d\n", GetLastError() );
3790 ret
= BeginPath(hdcMetafile
);
3791 ok( ret
, "BeginPath failed error %d\n", GetLastError() );
3792 ret
= EndPath(hdcMetafile
);
3793 ok( ret
, "EndPath failed error %d\n", GetLastError() );
3794 ret
= EndPath(hdcMetafile
);
3795 ok( !ret
, "EndPath succeeded\n" );
3796 ret
= CloseFigure(hdcMetafile
);
3797 ok( !ret
, "CloseFigure succeeded\n" );
3798 ret
= BeginPath(hdcMetafile
);
3799 ok( ret
, "BeginPath failed error %d\n", GetLastError() );
3800 ret
= AbortPath(hdcMetafile
);
3801 ok( ret
, "AbortPath failed error %d\n", GetLastError() );
3802 ret
= AbortPath(hdcMetafile
);
3803 ok( ret
, "AbortPath failed error %d\n", GetLastError() );
3805 hemf
= CloseEnhMetaFile(hdcMetafile
);
3806 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3808 if (compare_emf_bits(hemf
, EMF_EMPTY_PATH_BITS
, sizeof(EMF_EMPTY_PATH_BITS
), "empty path", FALSE
) != 0)
3810 dump_emf_bits(hemf
, "empty path");
3811 dump_emf_records(hemf
, "empty path");
3814 DeleteEnhMetaFile(hemf
);
3817 static void test_emf_PolyPolyline(void)
3821 POINT pts
[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3825 SetLastError(0xdeadbeef);
3826 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3827 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3829 ret
= PolyPolyline(hdcMetafile
, NULL
, NULL
, 0);
3830 ok( !ret
, "PolyPolyline\n" );
3832 SetLastError( 0xdeadbeef );
3835 ret
= PolyPolyline(hdcMetafile
, pts
, counts
, 2);
3836 ok( !ret
, "PolyPolyline\n" );
3837 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "gle %d\n", GetLastError() );
3839 SetLastError( 0xdeadbeef );
3842 ret
= PolyPolyline(hdcMetafile
, pts
, counts
, 2);
3843 ok( !ret
, "PolyPolyline\n" );
3844 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "gle %d\n", GetLastError() );
3846 SetLastError( 0xdeadbeef );
3849 ret
= PolyPolyline(hdcMetafile
, pts
, counts
, 2);
3850 ok( !ret
, "PolyPolyline\n" );
3851 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "gle %d\n", GetLastError() );
3855 ret
= PolyPolyline(hdcMetafile
, pts
, counts
, 2);
3856 ok( ret
, "PolyPolyline\n" );
3858 hemf
= CloseEnhMetaFile(hdcMetafile
);
3859 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3861 if(compare_emf_bits(hemf
, EMF_POLYPOLYLINE_BITS
, sizeof(EMF_POLYPOLYLINE_BITS
),
3862 "emf_PolyPolyline", FALSE
) != 0)
3864 dump_emf_bits(hemf
, "emf_PolyPolyline");
3865 dump_emf_records(hemf
, "emf_PolyPolyline");
3868 DeleteEnhMetaFile(hemf
);
3871 static void test_emf_GradientFill(void)
3877 { 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
3878 { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
3879 { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
3880 { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
3881 { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
3883 GRADIENT_TRIANGLE tri
[] = { { 0, 1, 2 }, { 3, 1, 0 } };
3886 mf
= CreateEnhMetaFileA( GetDC( 0 ), NULL
, NULL
, NULL
);
3887 ok( mf
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
3889 /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
3890 * means it allocates three mesh indices rather than two per
3891 * rectangle. This results in uninitialised values being written
3892 * to the EMF which is rather difficult to test against.
3894 * Note also that the final vertex here is not required, yet it is
3895 * written to the EMF, but is not considered in the bounds
3898 ret
= GdiGradientFill( mf
, v
, sizeof(v
) / sizeof(v
[0]), tri
, sizeof(tri
) / sizeof(tri
[0]),
3899 GRADIENT_FILL_TRIANGLE
);
3900 ok( ret
, "GradientFill\n" );
3902 hemf
= CloseEnhMetaFile( mf
);
3903 ok( hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError() );
3905 if (compare_emf_bits( hemf
, EMF_GRADIENTFILL_BITS
, sizeof(EMF_GRADIENTFILL_BITS
),
3906 "emf_GradientFill", FALSE
) != 0)
3908 dump_emf_bits( hemf
, "emf_GradientFill" );
3909 dump_emf_records( hemf
, "emf_GradientFill" );
3912 DeleteEnhMetaFile( hemf
);
3915 static void set_rotation_xform(XFORM
*out
, float rad
, int dx
, int dy
)
3917 out
->eM11
= cosf(rad
);
3918 out
->eM12
= -1.f
* sinf(rad
);
3919 out
->eM21
= sinf(rad
);
3920 out
->eM22
= cosf(rad
);
3925 struct emf_WorldTransform_test_data
3934 XFORM stored
; /* this is the "hidden" world transform used in PlayEnhMetaFileRecord */
3937 static BOOL
xform_eq(const XFORM
*a
, const XFORM
*b
)
3939 return fabs(a
->eM11
- b
->eM11
) < 0.001f
&&
3940 fabs(a
->eM12
- b
->eM12
) < 0.001f
&&
3941 fabs(a
->eM21
- b
->eM21
) < 0.001f
&&
3942 fabs(a
->eM22
- b
->eM22
) < 0.001f
&&
3943 fabs(a
->eDx
- b
->eDx
) < 0.001f
&&
3944 fabs(a
->eDy
- b
->eDy
) < 0.001f
;
3947 static INT CALLBACK
enum_emf_WorldTransform(HDC hdc
, HANDLETABLE
*ht
,
3948 const ENHMETARECORD
*emr
, INT nobj
, LPARAM param
)
3951 struct emf_WorldTransform_test_data
*test_data
= (struct emf_WorldTransform_test_data
*)param
;
3956 case EMR_SETWORLDTRANSFORM
:
3958 const EMRSETWORLDTRANSFORM
*lpXfrm
= (const EMRSETWORLDTRANSFORM
*)emr
;
3960 /* get scale factors with an identity world transform */
3961 GetWorldTransform(hdc
, &test_data
->scale
);
3963 /* play back record */
3964 ret
= PlayEnhMetaFileRecord(hdc
, ht
, emr
, nobj
);
3965 ok(ret
== TRUE
, "%s: PlayEnhMetaFileRecord failed\n", test_data
->name
);
3967 test_data
->stored
= lpXfrm
->xform
;
3968 CombineTransform(&test_data
->expected
, &test_data
->stored
, &test_data
->scale
);
3970 /* verify it is updated immediately */
3971 ret
= GetWorldTransform(hdc
, &xform
);
3972 ok(ret
== TRUE
, "%s: GetWorldTransform failed\n", test_data
->name
);
3973 ok(xform_eq(&xform
, &test_data
->expected
),
3974 "%s: After SWT playback, got wrong world transform: %f, %f; %f %f; %f %f; expected: %f, %f; %f %f; %f %f\n",
3976 xform
.eM11
, xform
.eM12
,
3977 xform
.eM21
, xform
.eM22
,
3978 xform
.eDx
, xform
.eDy
,
3979 test_data
->expected
.eM11
, test_data
->expected
.eM12
,
3980 test_data
->expected
.eM21
, test_data
->expected
.eM22
,
3981 test_data
->expected
.eDx
, test_data
->expected
.eDy
);
3986 case EMR_MODIFYWORLDTRANSFORM
:
3988 const EMRMODIFYWORLDTRANSFORM
*lpXfrm
= (const EMRMODIFYWORLDTRANSFORM
*)emr
;
3990 /* transform persists across calls */
3991 ret
= GetWorldTransform(hdc
, &xform
);
3992 ok(ret
== TRUE
, "%s: GetWorldTransform failed\n", test_data
->name
);
3993 ok(xform_eq(&xform
, &test_data
->expected
),
3994 "%s: On MWT entry, got wrong world transform: %f, %f; %f %f; %f %f; expected: %f, %f; %f %f; %f %f\n",
3996 xform
.eM11
, xform
.eM12
,
3997 xform
.eM21
, xform
.eM22
,
3998 xform
.eDx
, xform
.eDy
,
3999 test_data
->expected
.eM11
, test_data
->expected
.eM12
,
4000 test_data
->expected
.eM21
, test_data
->expected
.eM22
,
4001 test_data
->expected
.eDx
, test_data
->expected
.eDy
);
4003 if(test_data
->do_playback
)
4005 /* play back record */
4006 ret
= PlayEnhMetaFileRecord(hdc
, ht
, emr
, nobj
);
4007 ok(ret
== TRUE
, "%s: PlayEnhMetaFileRecord failed\n", test_data
->name
);
4009 if(lpXfrm
->iMode
== MWT_LEFTMULTIPLY
)
4011 /* left multiply does not discard direct modifications */
4012 CombineTransform(&test_data
->expected
, &lpXfrm
->xform
, &test_data
->expected
);
4014 /* and updates the stored matrix separately */
4015 CombineTransform(&test_data
->stored
, &lpXfrm
->xform
, &test_data
->stored
);
4018 else if(lpXfrm
->iMode
== MWT_RIGHTMULTIPLY
)
4020 /* but right multiply does discard */
4021 CombineTransform(&test_data
->stored
, &test_data
->stored
, &lpXfrm
->xform
);
4023 CombineTransform(&test_data
->expected
, &test_data
->stored
, &test_data
->scale
);
4026 /* verify it is updated immediately */
4027 ret
= GetWorldTransform(hdc
, &xform
);
4028 ok(ret
== TRUE
, "%s: GetWorldTransform failed\n", test_data
->name
);
4029 ok(xform_eq(&xform
, &test_data
->expected
),
4030 "%s: After MWT playback, got wrong world transform: %f, %f; %f %f; %f %f; expected: %f, %f; %f %f; %f %f\n",
4032 xform
.eM11
, xform
.eM12
,
4033 xform
.eM21
, xform
.eM22
,
4034 xform
.eDx
, xform
.eDy
,
4035 test_data
->expected
.eM11
, test_data
->expected
.eM12
,
4036 test_data
->expected
.eM21
, test_data
->expected
.eM22
,
4037 test_data
->expected
.eDx
, test_data
->expected
.eDy
);
4040 if(test_data
->do_modify
)
4042 /* modify directly */
4043 set_rotation_xform(&xform
, M_PI
/ 4.f
, 1, -1);
4044 ret
= ModifyWorldTransform(hdc
, &xform
, MWT_LEFTMULTIPLY
);
4045 ok(ret
== TRUE
, "%s: ModifyWorldTransform failed\n", test_data
->name
);
4047 /* the modified transform persists across callback calls */
4048 CombineTransform(&test_data
->expected
, &xform
, &test_data
->expected
);
4050 ret
= GetWorldTransform(hdc
, &xform
);
4051 ok(ret
== TRUE
, "%s: GetWorldTransform failed\n", test_data
->name
);
4052 ok(xform_eq(&xform
, &test_data
->expected
),
4053 "%s: After ModifyWT, got wrong world transform: %f, %f; %f %f; %f %f; expected: %f, %f; %f %f; %f %f\n",
4055 xform
.eM11
, xform
.eM12
,
4056 xform
.eM21
, xform
.eM22
,
4057 xform
.eDx
, xform
.eDy
,
4058 test_data
->expected
.eM11
, test_data
->expected
.eM12
,
4059 test_data
->expected
.eM21
, test_data
->expected
.eM22
,
4060 test_data
->expected
.eDx
, test_data
->expected
.eDy
);
4067 ret
= GetWorldTransform(hdc
, &xform
);
4068 ok(ret
== TRUE
, "%s: GetWorldTransform failed\n", test_data
->name
);
4069 ok(xform_eq(&xform
, &test_data
->expected
),
4070 "%s: Before LINETO playback, got wrong world transform: %f, %f; %f %f; %f %f; expected: %f, %f; %f %f; %f %f\n",
4072 xform
.eM11
, xform
.eM12
,
4073 xform
.eM21
, xform
.eM22
,
4074 xform
.eDx
, xform
.eDy
,
4075 test_data
->expected
.eM11
, test_data
->expected
.eM12
,
4076 test_data
->expected
.eM21
, test_data
->expected
.eM22
,
4077 test_data
->expected
.eDx
, test_data
->expected
.eDy
);
4079 ret
= PlayEnhMetaFileRecord(hdc
, ht
, emr
, nobj
);
4080 ok(ret
== TRUE
, "%s: PlayEnhMetaFileRecord failed\n", test_data
->name
);
4082 /* transform doesn't change during LINETO playback */
4083 ret
= GetWorldTransform(hdc
, &xform
);
4084 ok(ret
== TRUE
, "%s: GetWorldTransform failed\n", test_data
->name
);
4085 ok(xform_eq(&xform
, &test_data
->expected
),
4086 "%s: After LINETO playback, got wrong world transform: %f, %f; %f %f; %f %f; expected: %f, %f; %f %f; %f %f\n",
4088 xform
.eM11
, xform
.eM12
,
4089 xform
.eM21
, xform
.eM22
,
4090 xform
.eDx
, xform
.eDy
,
4091 test_data
->expected
.eM11
, test_data
->expected
.eM12
,
4092 test_data
->expected
.eM21
, test_data
->expected
.eM22
,
4093 test_data
->expected
.eDx
, test_data
->expected
.eDy
);
4098 PlayEnhMetaFileRecord(hdc
, ht
, emr
, nobj
);
4105 static void test_emf_WorldTransform(void)
4107 HDC hdcMetafile
, hdc
;
4112 RECT rect
= { 0, 0, 100, 100 };
4114 struct emf_WorldTransform_test_data test_data
[] = {
4115 { "normal", FALSE
, TRUE
},
4116 { "playback and modify", TRUE
, TRUE
},
4117 { "manual modify", TRUE
, FALSE
}
4120 for(i
= 0; i
< sizeof(test_data
) / sizeof(*test_data
); ++i
)
4122 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
4123 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
4125 ret
= SetGraphicsMode(hdcMetafile
, GM_ADVANCED
);
4126 ok(ret
== TRUE
, "SetGraphicsMode failed\n");
4128 set_rotation_xform(&xform
, M_PI
/ 4.f
, 2, 3);
4129 ret
= SetWorldTransform(hdcMetafile
, &xform
); /* EMR_SETWORLDTRANSFORM */
4130 ok(ret
== TRUE
, "SetWorldTransform failed\n");
4132 set_rotation_xform(&xform
, M_PI
/ 2.f
, -2, -3);
4133 ret
= ModifyWorldTransform(hdcMetafile
, &xform
, MWT_LEFTMULTIPLY
); /* EMR_MODIFYWORLDTRANSFORM */
4134 ok(ret
== TRUE
, "ModifyWorldTransform failed\n");
4136 set_rotation_xform(&xform
, M_PI
/ 3.f
, -2, 3);
4137 ret
= ModifyWorldTransform(hdcMetafile
, &xform
, MWT_LEFTMULTIPLY
); /* EMR_MODIFYWORLDTRANSFORM */
4138 ok(ret
== TRUE
, "ModifyWorldTransform failed\n");
4140 set_rotation_xform(&xform
, M_PI
, 2, -3);
4141 ret
= ModifyWorldTransform(hdcMetafile
, &xform
, MWT_RIGHTMULTIPLY
); /* EMR_MODIFYWORLDTRANSFORM */
4142 ok(ret
== TRUE
, "ModifyWorldTransform failed\n");
4144 ret
= LineTo(hdcMetafile
, 1, 1);
4145 ok(ret
== TRUE
, "LineTo failed\n");
4147 hemf
= CloseEnhMetaFile(hdcMetafile
);
4148 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
4150 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
4151 0, 0, 200, 200, 0, 0, 0, NULL
);
4152 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
4155 ok(hdc
!= 0, "GetDC failed\n");
4157 ret
= EnumEnhMetaFile(hdc
, hemf
, enum_emf_WorldTransform
, &test_data
[i
], &rect
);
4158 ok(ret
== TRUE
, "EnumEnhMetaFile failed: %u\n", GetLastError());
4160 ReleaseDC(hwnd
, hdc
);
4161 DestroyWindow(hwnd
);
4163 DeleteEnhMetaFile(hemf
);
4167 START_TEST(metafile
)
4169 init_function_pointers();
4171 /* For enhanced metafiles (enhmfdrv) */
4173 test_ExtTextOutScale();
4177 test_emf_ExtTextOut_on_path();
4178 test_emf_clipping();
4179 test_emf_polybezier();
4181 test_emf_PolyPolyline();
4182 test_emf_GradientFill();
4183 test_emf_WorldTransform();
4185 /* For win-format metafiles (mfdrv) */
4189 test_mf_PatternBrush();
4191 test_CopyMetaFile();
4192 test_SetMetaFileBits();
4193 test_mf_ExtTextOut_on_path();
4197 /* For metafile conversions */
4198 test_mf_conversions();
4199 test_SetWinMetaFileBits();
4200 test_GetWinMetaFileBits();
4203 test_SetEnhMetaFileBits();