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 EMF_TEXTOUT_OUTLINE_ON_PATH_BITS
[] =
1127 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff,
1132 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1133 0x0c, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1134 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x90, 0x06, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00,
1137 0x51, 0x02, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1139 0x00, 0x00, 0x00, 0x00, 0x1a, 0x0b, 0x09, 0x00,
1140 0xf0, 0xa6, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00,
1141 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x80,
1142 0x3b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1143 0x54, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1146 0x01, 0x00, 0x00, 0x00, 0xc3, 0x30, 0x0d, 0x42,
1147 0xcf, 0xf3, 0x0c, 0x42, 0x0b, 0x00, 0x00, 0x00,
1148 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1149 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1152 0x54, 0x00, 0x00, 0x00, 0x54, 0x00, 0x65, 0x00,
1153 0x73, 0x00, 0x74, 0x00, 0x03, 0x00, 0x00, 0x00,
1154 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1155 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1156 0x08, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1157 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x80,
1158 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1159 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1160 0x14, 0x00, 0x00, 0x00
1163 static const unsigned char MF_LINETO_BITS
[] = {
1164 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1165 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1166 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1167 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1171 static const unsigned char EMF_LINETO_BITS
[] = {
1172 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1177 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1178 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1179 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1181 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1182 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1185 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1186 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1187 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1188 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1189 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1190 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1191 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1192 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1193 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1194 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1195 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1196 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1197 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1198 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1199 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1200 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1201 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1202 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1203 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1204 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1205 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1206 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1207 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1208 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1209 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1213 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS
[] = {
1214 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1216 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1219 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1220 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1221 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1223 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1224 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1227 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1228 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1229 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1230 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1231 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1232 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1234 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1235 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1237 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1238 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1239 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1240 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1241 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1242 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1243 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1244 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1245 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1246 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1247 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1248 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1249 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1251 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1252 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1255 static const unsigned char EMF_LINETO_MM_TEXT_BITS
[] = {
1256 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1261 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1262 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1263 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1266 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1269 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1270 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1271 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1272 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1273 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1274 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1275 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1276 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1277 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1278 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1279 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1280 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1282 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1284 0x14, 0x00, 0x00, 0x00
1287 static const unsigned char EMF_BITBLT
[] =
1289 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1294 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1295 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1296 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1299 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1301 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1302 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1303 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1305 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1307 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1309 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1312 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1313 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1314 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1315 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1316 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x30, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1326 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1328 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1331 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1338 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1339 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1341 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1342 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1343 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1346 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1349 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1350 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1351 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1352 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1353 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1354 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1363 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1365 0x14, 0x00, 0x00, 0x00
1368 static const unsigned char EMF_DCBRUSH_BITS
[] =
1370 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1371 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1372 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1373 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1374 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1375 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1376 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1377 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1380 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1383 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1384 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1385 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1386 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1387 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1389 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1390 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1391 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1392 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1394 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1395 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1396 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1397 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1398 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1399 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1400 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1401 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1402 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1403 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1404 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1405 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1406 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1407 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1408 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1409 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1410 0x14, 0x00, 0x00, 0x00
1413 static const unsigned char EMF_BEZIER_BITS
[] =
1415 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1417 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1419 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1420 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1421 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1422 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1424 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1425 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1427 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1428 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1429 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1431 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1432 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1433 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1434 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1435 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1436 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1437 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1438 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1439 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1440 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1441 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1442 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1443 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1444 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1445 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1446 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1447 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1448 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1449 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1450 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1451 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1452 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1453 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1454 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1455 0x14, 0x00, 0x00, 0x00
1458 static const unsigned char EMF_POLYPOLYLINE_BITS
[] =
1460 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1461 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1462 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1463 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1464 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1465 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1466 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1467 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1470 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1473 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1474 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1475 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1476 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1477 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1478 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1479 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1480 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1481 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1482 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1483 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1486 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1487 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1488 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1489 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1491 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1492 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1493 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1494 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1495 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1496 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1497 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1498 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1499 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1500 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1501 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1502 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1503 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1504 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1505 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 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 static const unsigned char EMF_GRADIENTFILL_BITS
[] =
1513 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1514 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1515 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1516 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1517 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1518 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1519 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1520 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1522 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1523 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1525 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1526 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1527 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1528 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1529 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1530 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1531 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1532 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1533 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1534 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1535 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1536 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1537 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1538 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1539 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1540 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1541 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1542 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1543 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1544 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1545 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1546 0x14, 0x00, 0x00, 0x00
1549 /* For debugging or dumping the raw metafiles produced by
1550 * new test functions.
1552 static INT CALLBACK
mf_enum_proc(HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
,
1553 INT nobj
, LPARAM param
)
1555 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1556 hdc
, mr
->rdFunction
, mr
->rdSize
, (void *)param
);
1560 /* For debugging or dumping the raw metafiles produced by
1561 * new test functions.
1564 static void dump_mf_bits (const HMETAFILE mf
, const char *desc
)
1566 BYTE buf
[MF_BUFSIZE
];
1569 if (!winetest_debug
) return;
1571 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1572 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1574 printf ("MetaFile %s has bits:\n{\n ", desc
);
1575 for (i
=0; i
<mfsize
; i
++)
1577 printf ("0x%02x", buf
[i
]);
1580 else if (i
% 8 == 7)
1588 /* Compare the metafile produced by a test function with the
1589 * expected raw metafile data in "bits".
1590 * Return value is 0 for a perfect match,
1591 * -1 if lengths aren't equal,
1592 * otherwise returns the number of non-matching bytes.
1595 static int compare_mf_bits (const HMETAFILE mf
, const unsigned char *bits
, UINT bsize
,
1598 unsigned char buf
[MF_BUFSIZE
];
1602 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1603 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1604 if (mfsize
< MF_BUFSIZE
)
1605 ok (mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n",
1606 desc
, mfsize
, bsize
);
1608 ok (bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1609 desc
, mfsize
, bsize
);
1610 if (mfsize
!= bsize
)
1614 for (i
=0; i
<bsize
; i
++)
1616 if (buf
[i
] != bits
[i
])
1619 ok (diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1620 desc
, mfsize
, bsize
, diff
);
1625 static int compare_mf_disk_bits(LPCSTR name
, const BYTE
*bits
, UINT bsize
, const char *desc
)
1627 unsigned char buf
[MF_BUFSIZE
];
1628 DWORD mfsize
, rd_size
, i
;
1633 hfile
= CreateFileA(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1634 assert(hfile
!= INVALID_HANDLE_VALUE
);
1636 mfsize
= GetFileSize(hfile
, NULL
);
1637 assert(mfsize
<= MF_BUFSIZE
);
1639 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &rd_size
, NULL
);
1640 ok( ret
&& rd_size
== mfsize
, "ReadFile: error %d\n", GetLastError());
1644 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n", desc
, mfsize
, bsize
);
1646 if (mfsize
!= bsize
)
1650 for (i
=0; i
<bsize
; i
++)
1652 if (buf
[i
] != bits
[i
])
1655 ok(diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1656 desc
, mfsize
, bsize
, diff
);
1661 /* For debugging or dumping the raw EMFs produced by
1662 * new test functions.
1664 static void dump_emf_bits(const HENHMETAFILE mf
, const char *desc
)
1666 BYTE buf
[MF_BUFSIZE
];
1669 if (!winetest_debug
) return;
1671 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1672 ok (mfsize
> 0, "%s: GetEnhMetaFileBits failed\n", desc
);
1674 printf("EMF %s has bits:\n{\n ", desc
);
1675 for (i
= 0; i
< mfsize
; i
++)
1677 printf ("0x%02x", buf
[i
]);
1680 else if (i
% 8 == 7)
1688 static void dump_emf_records(const HENHMETAFILE mf
, const char *desc
)
1691 BYTE buf
[MF_BUFSIZE
];
1692 UINT mfsize
, offset
;
1694 if (!winetest_debug
) return;
1696 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1697 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1699 printf("EMF %s has records:\n", desc
);
1703 while(offset
< mfsize
)
1705 EMR
*emr
= (EMR
*)(emf
+ offset
);
1706 printf("emr->iType %d, emr->nSize %u\n", emr
->iType
, emr
->nSize
);
1707 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1708 offset
+= emr
->nSize
;
1712 static void dump_emf_record(const ENHMETARECORD
*emr
, const char *desc
)
1717 if (!winetest_debug
) return;
1719 printf ("%s: EMF record %u has bits:\n{\n", desc
, emr
->iType
);
1720 buf
= (const BYTE
*)emr
;
1721 for (i
= 0; i
< emr
->nSize
; i
++)
1723 printf ("0x%02x", buf
[i
]);
1724 if (i
== emr
->nSize
- 1)
1726 else if (i
% 8 == 7)
1734 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW
*eto
)
1736 trace("rclBounds %d,%d - %d,%d\n", eto
->rclBounds
.left
, eto
->rclBounds
.top
,
1737 eto
->rclBounds
.right
, eto
->rclBounds
.bottom
);
1738 trace("iGraphicsMode %u\n", eto
->iGraphicsMode
);
1739 trace("exScale: %f\n", eto
->exScale
);
1740 trace("eyScale: %f\n", eto
->eyScale
);
1741 trace("emrtext.ptlReference %d,%d\n", eto
->emrtext
.ptlReference
.x
, eto
->emrtext
.ptlReference
.y
);
1742 trace("emrtext.nChars %u\n", eto
->emrtext
.nChars
);
1743 trace("emrtext.offString %#x\n", eto
->emrtext
.offString
);
1744 trace("emrtext.fOptions %#x\n", eto
->emrtext
.fOptions
);
1745 trace("emrtext.rcl %d,%d - %d,%d\n", eto
->emrtext
.rcl
.left
, eto
->emrtext
.rcl
.top
,
1746 eto
->emrtext
.rcl
.right
, eto
->emrtext
.rcl
.bottom
);
1747 trace("emrtext.offDx %#x\n", eto
->emrtext
.offDx
);
1750 static BOOL
match_emf_record(const ENHMETARECORD
*emr1
, const ENHMETARECORD
*emr2
,
1751 const char *desc
, BOOL ignore_scaling
)
1755 ok(emr1
->iType
== emr2
->iType
, "%s: emr->iType %u != %u\n",
1756 desc
, emr1
->iType
, emr2
->iType
);
1758 ok(emr1
->nSize
== emr2
->nSize
, "%s: emr->nSize %u != %u\n",
1759 desc
, emr1
->nSize
, emr2
->nSize
);
1761 /* iType and nSize mismatches are fatal */
1762 if (emr1
->iType
!= emr2
->iType
|| emr1
->nSize
!= emr2
->nSize
) return FALSE
;
1764 /* contents of EMR_GDICOMMENT are not interesting */
1765 if (emr1
->iType
== EMR_GDICOMMENT
) return TRUE
;
1767 /* different Windows versions setup DC scaling differently when
1768 * converting an old style metafile to an EMF.
1770 if (ignore_scaling
&& (emr1
->iType
== EMR_SETWINDOWEXTEX
||
1771 emr1
->iType
== EMR_SETVIEWPORTEXTEX
))
1774 if (emr1
->iType
== EMR_EXTTEXTOUTW
|| emr1
->iType
== EMR_EXTTEXTOUTA
)
1776 EMREXTTEXTOUTW
*eto1
, *eto2
;
1778 eto1
= HeapAlloc(GetProcessHeap(), 0, emr1
->nSize
);
1779 memcpy(eto1
, emr1
, emr1
->nSize
);
1780 eto2
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1781 memcpy(eto2
, emr2
, emr2
->nSize
);
1783 /* different Windows versions setup DC scaling differently */
1784 eto1
->exScale
= eto1
->eyScale
= 0.0;
1785 eto2
->exScale
= eto2
->eyScale
= 0.0;
1787 diff
= memcmp(eto1
, eto2
, emr1
->nSize
);
1790 dump_EMREXTTEXTOUT(eto1
);
1791 dump_EMREXTTEXTOUT(eto2
);
1793 HeapFree(GetProcessHeap(), 0, eto1
);
1794 HeapFree(GetProcessHeap(), 0, eto2
);
1796 else if (emr1
->iType
== EMR_EXTSELECTCLIPRGN
&& !lstrcmpA(desc
, "emf_clipping"))
1798 /* We have to take care of NT4 differences here */
1799 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1802 ENHMETARECORD
*emr_nt4
;
1804 emr_nt4
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1805 memcpy(emr_nt4
, emr2
, emr2
->nSize
);
1806 /* Correct the nRgnSize field */
1807 emr_nt4
->dParm
[5] = sizeof(RECT
);
1809 diff
= memcmp(emr1
, emr_nt4
, emr1
->nSize
);
1811 win_skip("Catered for NT4 differences\n");
1813 HeapFree(GetProcessHeap(), 0, emr_nt4
);
1816 else if (emr1
->iType
== EMR_POLYBEZIERTO16
|| emr1
->iType
== EMR_POLYBEZIER16
)
1818 EMRPOLYBEZIER16
*eto1
, *eto2
;
1820 eto1
= (EMRPOLYBEZIER16
*)emr1
;
1821 eto2
= (EMRPOLYBEZIER16
*)emr2
;
1823 diff
= eto1
->cpts
!= eto2
->cpts
;
1825 diff
= memcmp(eto1
->apts
, eto2
->apts
, eto1
->cpts
* sizeof(POINTS
));
1827 else if (emr1
->iType
== EMR_POLYBEZIERTO
|| emr1
->iType
== EMR_POLYBEZIER
)
1829 EMRPOLYBEZIER
*eto1
, *eto2
;
1831 eto1
= (EMRPOLYBEZIER
*)emr1
;
1832 eto2
= (EMRPOLYBEZIER
*)emr2
;
1834 diff
= eto1
->cptl
!= eto2
->cptl
;
1836 diff
= memcmp(eto1
->aptl
, eto2
->aptl
, eto1
->cptl
* sizeof(POINTL
));
1839 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1841 ok(diff
== 0, "%s: contents of record %u don't match\n", desc
, emr1
->iType
);
1845 dump_emf_record(emr1
, "expected bits");
1846 dump_emf_record(emr2
, "actual bits");
1849 return diff
== 0; /* report all non-fatal record mismatches */
1852 /* Compare the EMF produced by a test function with the
1853 * expected raw EMF data in "bits".
1854 * Return value is 0 for a perfect match,
1855 * -1 if lengths aren't equal,
1856 * otherwise returns the number of non-matching bytes.
1858 static int compare_emf_bits(const HENHMETAFILE mf
, const unsigned char *bits
,
1859 UINT bsize
, const char *desc
,
1860 BOOL ignore_scaling
)
1862 unsigned char buf
[MF_BUFSIZE
];
1863 UINT mfsize
, offset1
, offset2
, diff_nt4
, diff_9x
;
1864 const ENHMETAHEADER
*emh1
, *emh2
;
1866 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1867 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1869 /* ENHMETAHEADER size could differ, depending on platform */
1870 diff_nt4
= sizeof(SIZEL
);
1871 diff_9x
= sizeof(SIZEL
) + 3 * sizeof(DWORD
);
1873 if (mfsize
< MF_BUFSIZE
)
1875 ok(mfsize
== bsize
||
1876 broken(mfsize
== bsize
- diff_nt4
) || /* NT4 */
1877 broken(mfsize
== bsize
- diff_9x
), /* Win9x/WinME */
1878 "%s: mfsize=%d, bsize=%d\n", desc
, mfsize
, bsize
);
1881 ok(bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1882 desc
, mfsize
, bsize
);
1884 /* basic things must match */
1885 emh1
= (const ENHMETAHEADER
*)bits
;
1886 emh2
= (const ENHMETAHEADER
*)buf
;
1887 ok(emh1
->iType
== EMR_HEADER
, "expected EMR_HEADER, got %u\n", emh1
->iType
);
1888 ok(emh1
->nSize
== sizeof(ENHMETAHEADER
), "expected sizeof(ENHMETAHEADER), got %u\n", emh1
->nSize
);
1889 ok(emh2
->nBytes
== mfsize
, "expected emh->nBytes %u, got %u\n", mfsize
, emh2
->nBytes
);
1890 ok(emh1
->dSignature
== ENHMETA_SIGNATURE
, "expected ENHMETA_SIGNATURE, got %u\n", emh1
->dSignature
);
1892 ok(emh1
->iType
== emh2
->iType
, "expected EMR_HEADER, got %u\n", emh2
->iType
);
1893 ok(emh1
->nSize
== emh2
->nSize
||
1894 broken(emh1
->nSize
- diff_nt4
== emh2
->nSize
) ||
1895 broken(emh1
->nSize
- diff_9x
== emh2
->nSize
),
1896 "expected nSize %u, got %u\n", emh1
->nSize
, emh2
->nSize
);
1897 ok(emh1
->rclBounds
.left
== emh2
->rclBounds
.left
, "%s: expected rclBounds.left = %d, got %d\n",
1898 desc
, emh1
->rclBounds
.left
, emh2
->rclBounds
.left
);
1899 ok(emh1
->rclBounds
.top
== emh2
->rclBounds
.top
, "%s: expected rclBounds.top = %d, got %d\n",
1900 desc
, emh1
->rclBounds
.top
, emh2
->rclBounds
.top
);
1901 ok(emh1
->rclBounds
.right
== emh2
->rclBounds
.right
, "%s: expected rclBounds.right = %d, got %d\n",
1902 desc
, emh1
->rclBounds
.right
, emh2
->rclBounds
.right
);
1903 ok(emh1
->rclBounds
.bottom
== emh2
->rclBounds
.bottom
, "%s: expected rclBounds.bottom = %d, got %d\n",
1904 desc
, emh1
->rclBounds
.bottom
, emh2
->rclBounds
.bottom
);
1905 ok(emh1
->dSignature
== emh2
->dSignature
, "expected dSignature %u, got %u\n", emh1
->dSignature
, emh2
->dSignature
);
1906 ok(emh1
->nBytes
== emh2
->nBytes
||
1907 broken(emh1
->nBytes
- diff_nt4
== emh2
->nBytes
) ||
1908 broken(emh1
->nBytes
- diff_9x
== emh2
->nBytes
),
1909 "expected nBytes %u, got %u\n", emh1
->nBytes
, emh2
->nBytes
);
1910 ok(emh1
->nRecords
== emh2
->nRecords
, "expected nRecords %u, got %u\n", emh1
->nRecords
, emh2
->nRecords
);
1912 offset1
= emh1
->nSize
;
1913 offset2
= emh2
->nSize
; /* Needed for Win9x/WinME/NT4 */
1914 while (offset1
< emh1
->nBytes
)
1916 const ENHMETARECORD
*emr1
= (const ENHMETARECORD
*)(bits
+ offset1
);
1917 const ENHMETARECORD
*emr2
= (const ENHMETARECORD
*)(buf
+ offset2
);
1919 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1920 desc
, emr1
->iType
, emr1
->nSize
, emr2
->iType
, emr2
->nSize
);
1922 if (!match_emf_record(emr1
, emr2
, desc
, ignore_scaling
)) return -1;
1924 /* We have already bailed out if iType or nSize don't match */
1925 offset1
+= emr1
->nSize
;
1926 offset2
+= emr2
->nSize
;
1932 /* tests blitting to an EMF */
1933 static void test_emf_BitBlt(void)
1935 HDC hdcDisplay
, hdcMetafile
, hdcBitmap
;
1936 HBITMAP hBitmap
, hOldBitmap
;
1937 HENHMETAFILE hMetafile
;
1939 BITMAPINFOHEADER bmih
=
1941 sizeof(BITMAPINFOHEADER
),
1942 BMP_DIM
,/* biWidth */
1943 BMP_DIM
,/* biHeight */
1945 24, /* biBitCount */
1946 BI_RGB
, /* biCompression */
1947 0, /* biXPelsPerMeter */
1948 0, /* biYPelsPerMeter */
1950 0, /* biClrImportant */
1956 hdcDisplay
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1957 ok( hdcDisplay
!= 0, "CreateDCA error %d\n", GetLastError() );
1959 hdcBitmap
= CreateCompatibleDC(hdcDisplay
);
1960 ok( hdcBitmap
!= 0, "CreateCompatibleDC failed\n" );
1961 ok(SetGraphicsMode(hdcBitmap
, GM_ADVANCED
), "SetGraphicsMode failed\n");
1962 bmih
.biXPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSX
), 100, 3937);
1963 bmih
.biYPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSY
), 100, 3937);
1964 hBitmap
= CreateDIBSection(hdcDisplay
, (const BITMAPINFO
*)&bmih
,
1965 DIB_RGB_COLORS
, &bits
, NULL
, 0);
1966 hOldBitmap
= SelectObject(hdcBitmap
, hBitmap
);
1968 hdcMetafile
= CreateEnhMetaFileA(hdcBitmap
, NULL
, NULL
, NULL
);
1969 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1971 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1972 ret
= BitBlt(hdcBitmap
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, BLACKNESS
);
1973 ok( ret
, "BitBlt(BLACKNESS) failed\n" );
1975 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, SRCCOPY
);
1976 ok( ret
, "BitBlt(SRCCOPY) failed\n" );
1977 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, WHITENESS
);
1978 ok( ret
, "BitBlt(WHITENESS) failed\n" );
1980 ok(SetMapMode(hdcBitmap
, MM_ANISOTROPIC
), "SetMapMode failed\n");
1981 ok(SetWindowOrgEx(hdcBitmap
, 0, 0, NULL
), "SetWindowOrgEx failed\n");
1982 ok(SetWindowExtEx(hdcBitmap
, 400, 400, NULL
), "SetWindowExtEx failed\n");
1983 ok(SetViewportOrgEx(hdcBitmap
, 0, 0, NULL
), "SetViewportOrgEx failed\n");
1984 ok(SetViewportExtEx(hdcBitmap
, BMP_DIM
, BMP_DIM
, NULL
), "SetViewportExtEx failed\n");
1985 memset(&xform
, 0, sizeof(xform
));
1988 ok(SetWorldTransform(hdcBitmap
, &xform
), "SetWorldTransform failed\n");
1990 ret
= StretchBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, 400, 400, SRCCOPY
);
1991 ok( ret
, "StretchBlt(SRCCOPY) failed\n" );
1993 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1994 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1996 if(compare_emf_bits(hMetafile
, EMF_BITBLT
, sizeof(EMF_BITBLT
),
1997 "emf_BitBlt", FALSE
) != 0)
1999 dump_emf_bits(hMetafile
, "emf_BitBlt");
2000 dump_emf_records(hMetafile
, "emf_BitBlt");
2003 SelectObject(hdcBitmap
, hOldBitmap
);
2004 DeleteObject(hBitmap
);
2005 DeleteDC(hdcBitmap
);
2006 DeleteDC(hdcDisplay
);
2010 static void test_emf_DCBrush(void)
2013 HENHMETAFILE hMetafile
;
2019 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
2021 win_skip( "SetDCBrush/PenColor not supported\n" );
2025 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
2026 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
2028 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
2029 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2031 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
2032 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
2034 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
2035 ok( color
== 0xffffff, "SetDCBrushColor returned %x\n", color
);
2037 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
2038 ok( color
== 0, "SetDCPenColor returned %x\n", color
);
2040 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
2042 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
2043 ok( color
== 0x555555, "SetDCBrushColor returned %x\n", color
);
2045 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2046 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
2048 if (compare_emf_bits (hMetafile
, EMF_DCBRUSH_BITS
, sizeof(EMF_DCBRUSH_BITS
),
2049 "emf_DC_Brush", FALSE
) != 0)
2051 dump_emf_bits(hMetafile
, "emf_DC_Brush");
2052 dump_emf_records(hMetafile
, "emf_DC_Brush");
2054 ret
= DeleteEnhMetaFile(hMetafile
);
2055 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2056 ret
= DeleteObject(hBrush
);
2057 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2058 ret
= DeleteObject(hPen
);
2059 ok( ret
, "DeleteObject(HPEN) error %d\n", GetLastError());
2062 /* Test a blank metafile. May be used as a template for new tests. */
2064 static void test_mf_Blank(void)
2067 HMETAFILE hMetafile
;
2072 hdcMetafile
= CreateMetaFileA(NULL
);
2073 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2074 trace("hdcMetafile %p\n", hdcMetafile
);
2076 /* Tests on metafile initialization */
2077 caps
= GetDeviceCaps (hdcMetafile
, TECHNOLOGY
);
2078 ok (caps
== DT_METAFILE
,
2079 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps
);
2081 hMetafile
= CloseMetaFile(hdcMetafile
);
2082 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2083 type
= GetObjectType(hMetafile
);
2084 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
2085 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2087 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
2090 dump_mf_bits(hMetafile
, "mf_Blank");
2091 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2094 ret
= DeleteMetaFile(hMetafile
);
2095 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2098 static void test_CopyMetaFile(void)
2101 HMETAFILE hMetafile
, hmf_copy
;
2103 char temp_path
[MAX_PATH
];
2104 char mf_name
[MAX_PATH
];
2107 hdcMetafile
= CreateMetaFileA(NULL
);
2108 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2109 trace("hdcMetafile %p\n", hdcMetafile
);
2111 hMetafile
= CloseMetaFile(hdcMetafile
);
2112 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2113 type
= GetObjectType(hMetafile
);
2114 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
2116 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
2119 dump_mf_bits(hMetafile
, "mf_Blank");
2120 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2123 GetTempPathA(MAX_PATH
, temp_path
);
2124 GetTempFileNameA(temp_path
, "wmf", 0, mf_name
);
2126 hmf_copy
= CopyMetaFileA(hMetafile
, mf_name
);
2127 ok(hmf_copy
!= 0, "CopyMetaFile error %d\n", GetLastError());
2129 type
= GetObjectType(hmf_copy
);
2130 ok(type
== OBJ_METAFILE
, "CopyMetaFile created object with type %d\n", type
);
2132 ret
= DeleteMetaFile(hMetafile
);
2133 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2135 if (compare_mf_disk_bits(mf_name
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
), "mf_blank") != 0)
2137 dump_mf_bits(hmf_copy
, "mf_Blank");
2138 EnumMetaFile(0, hmf_copy
, mf_enum_proc
, 0);
2141 ret
= DeleteMetaFile(hmf_copy
);
2142 ok( ret
, "DeleteMetaFile(%p) error %d\n", hmf_copy
, GetLastError());
2144 DeleteFileA(mf_name
);
2147 static void test_SetMetaFileBits(void)
2155 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), MF_GRAPHICS_BITS
);
2156 trace("hmf %p\n", hmf
);
2157 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2158 type
= GetObjectType(hmf
);
2159 ok(type
== OBJ_METAFILE
, "SetMetaFileBitsEx created object with type %d\n", type
);
2161 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2163 dump_mf_bits(hmf
, "mf_Graphics");
2164 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2167 ret
= DeleteMetaFile(hmf
);
2168 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2170 /* NULL data crashes XP SP1 */
2171 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2173 /* Now with zero size */
2174 SetLastError(0xdeadbeef);
2175 hmf
= SetMetaFileBitsEx(0, MF_GRAPHICS_BITS
);
2176 trace("hmf %p\n", hmf
);
2177 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2178 ok(GetLastError() == ERROR_INVALID_DATA
||
2179 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
2180 "wrong error %d\n", GetLastError());
2182 /* Now with odd size */
2183 SetLastError(0xdeadbeef);
2184 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
) - 1, MF_GRAPHICS_BITS
);
2185 trace("hmf %p\n", hmf
);
2186 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2187 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2189 /* Now with zeroed out header fields */
2190 assert(sizeof(buf
) >= sizeof(MF_GRAPHICS_BITS
));
2191 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2192 mh
= (METAHEADER
*)buf
;
2193 /* corruption of any of the below fields leads to a failure */
2196 mh
->mtHeaderSize
= 0;
2197 SetLastError(0xdeadbeef);
2198 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2199 trace("hmf %p\n", hmf
);
2200 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
2201 ok(GetLastError() == ERROR_INVALID_DATA
||
2202 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
2203 "wrong error %d\n", GetLastError());
2205 /* Now with corrupted mtSize field */
2206 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2207 mh
= (METAHEADER
*)buf
;
2208 /* corruption of mtSize doesn't lead to a failure */
2210 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2211 trace("hmf %p\n", hmf
);
2212 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2214 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2216 dump_mf_bits(hmf
, "mf_Graphics");
2217 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2220 ret
= DeleteMetaFile(hmf
);
2221 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2223 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2224 /* Now with zeroed out mtSize field */
2225 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
2226 mh
= (METAHEADER
*)buf
;
2227 /* zeroing mtSize doesn't lead to a failure */
2229 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
2230 trace("hmf %p\n", hmf
);
2231 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2233 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
2235 dump_mf_bits(hmf
, "mf_Graphics");
2236 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2239 ret
= DeleteMetaFile(hmf
);
2240 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
2244 /* Simple APIs from mfdrv/graphics.c
2247 static void test_mf_Graphics(void)
2250 HMETAFILE hMetafile
;
2254 hdcMetafile
= CreateMetaFileA(NULL
);
2255 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2256 trace("hdcMetafile %p\n", hdcMetafile
);
2258 ret
= MoveToEx(hdcMetafile
, 1, 1, NULL
);
2259 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2260 ret
= LineTo(hdcMetafile
, 2, 2);
2261 ok( ret
, "LineTo error %d.\n", GetLastError());
2262 ret
= MoveToEx(hdcMetafile
, 1, 1, &oldpoint
);
2263 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2265 /* oldpoint gets garbage under Win XP, so the following test would
2266 * work under Wine but fails under Windows:
2268 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2269 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2270 * oldpoint.x, oldpoint.y);
2273 ret
= Ellipse(hdcMetafile
, 0, 0, 2, 2);
2274 ok( ret
, "Ellipse error %d.\n", GetLastError());
2276 hMetafile
= CloseMetaFile(hdcMetafile
);
2277 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2278 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2280 if (compare_mf_bits (hMetafile
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
),
2281 "mf_Graphics") != 0)
2283 dump_mf_bits(hMetafile
, "mf_Graphics");
2284 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2287 ret
= DeleteMetaFile(hMetafile
);
2288 ok( ret
, "DeleteMetaFile(%p) error %d\n",
2289 hMetafile
, GetLastError());
2292 static void test_mf_PatternBrush(void)
2295 HMETAFILE hMetafile
;
2300 orig_lb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(LOGBRUSH
));
2302 orig_lb
->lbStyle
= BS_PATTERN
;
2303 orig_lb
->lbColor
= RGB(0, 0, 0);
2304 orig_lb
->lbHatch
= (ULONG_PTR
)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH
);
2305 ok((HBITMAP
)orig_lb
->lbHatch
!= NULL
, "CreateBitmap error %d.\n", GetLastError());
2307 hBrush
= CreateBrushIndirect (orig_lb
);
2308 ok(hBrush
!= 0, "CreateBrushIndirect error %d\n", GetLastError());
2310 hdcMetafile
= CreateMetaFileA(NULL
);
2311 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2312 trace("hdcMetafile %p\n", hdcMetafile
);
2314 hBrush
= SelectObject(hdcMetafile
, hBrush
);
2315 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2317 hMetafile
= CloseMetaFile(hdcMetafile
);
2318 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2319 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
2321 if (compare_mf_bits (hMetafile
, MF_PATTERN_BRUSH_BITS
, sizeof(MF_PATTERN_BRUSH_BITS
),
2322 "mf_Pattern_Brush") != 0)
2324 dump_mf_bits(hMetafile
, "mf_Pattern_Brush");
2325 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2328 ret
= DeleteMetaFile(hMetafile
);
2329 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
2330 ret
= DeleteObject(hBrush
);
2331 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2332 ret
= DeleteObject((HBITMAP
)orig_lb
->lbHatch
);
2333 ok( ret
, "DeleteObject(HBITMAP) error %d\n",
2335 HeapFree (GetProcessHeap(), 0, orig_lb
);
2338 static void test_mf_DCBrush(void)
2341 HMETAFILE hMetafile
;
2347 if (!pSetDCBrushColor
|| !pSetDCPenColor
)
2349 win_skip( "SetDCBrush/PenColor not supported\n" );
2353 hdcMetafile
= CreateMetaFileA(NULL
);
2354 ok( hdcMetafile
!= 0, "CreateMetaFileA failed\n" );
2356 hBrush
= SelectObject(hdcMetafile
, GetStockObject(DC_BRUSH
));
2357 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
2359 hPen
= SelectObject(hdcMetafile
, GetStockObject(DC_PEN
));
2360 ok(hPen
!= 0, "SelectObject error %d.\n", GetLastError());
2362 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x55,0x55,0x55) );
2363 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2365 color
= pSetDCPenColor( hdcMetafile
, RGB(0x33,0x44,0x55) );
2366 ok( color
== CLR_INVALID
, "SetDCPenColor returned %x\n", color
);
2368 Rectangle( hdcMetafile
, 10, 10, 20, 20 );
2370 color
= pSetDCBrushColor( hdcMetafile
, RGB(0x12,0x34,0x56) );
2371 ok( color
== CLR_INVALID
, "SetDCBrushColor returned %x\n", color
);
2373 hMetafile
= CloseMetaFile(hdcMetafile
);
2374 ok( hMetafile
!= 0, "CloseMetaFile failed\n" );
2376 if (compare_mf_bits(hMetafile
, MF_DCBRUSH_BITS
, sizeof(MF_DCBRUSH_BITS
), "mf_DCBrush") != 0)
2378 dump_mf_bits(hMetafile
, "mf_DCBrush");
2379 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2381 ret
= DeleteMetaFile(hMetafile
);
2382 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2385 static void test_mf_ExtTextOut_on_path(void)
2388 HMETAFILE hMetafile
;
2390 static const INT dx
[4] = { 3, 5, 8, 12 };
2392 hdcMetafile
= CreateMetaFileA(NULL
);
2393 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2394 trace("hdcMetafile %p\n", hdcMetafile
);
2396 ret
= BeginPath(hdcMetafile
);
2397 ok(!ret
, "BeginPath on metafile DC should fail\n");
2399 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2400 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2402 ret
= EndPath(hdcMetafile
);
2403 ok(!ret
, "EndPath on metafile DC should fail\n");
2405 hMetafile
= CloseMetaFile(hdcMetafile
);
2406 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
2408 if (compare_mf_bits(hMetafile
, MF_TEXTOUT_ON_PATH_BITS
, sizeof(MF_TEXTOUT_ON_PATH_BITS
),
2409 "mf_TextOut_on_path") != 0)
2411 dump_mf_bits(hMetafile
, "mf_TextOut_on_path");
2412 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
2415 ret
= DeleteMetaFile(hMetafile
);
2416 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
2419 static void test_emf_ExtTextOut_on_path(void)
2422 HDC hdcDisplay
, hdcMetafile
;
2423 HENHMETAFILE hMetafile
;
2427 static const INT dx
[4] = { 3, 5, 8, 12 };
2429 /* Win9x doesn't play EMFs on invisible windows */
2430 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2431 0, 0, 200, 200, 0, 0, 0, NULL
);
2432 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2434 hdcDisplay
= GetDC(hwnd
);
2435 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
2437 /* with default font */
2438 ret
= BeginPath(hdcDisplay
);
2439 ok(ret
, "BeginPath error %d\n", GetLastError());
2441 ret
= ExtTextOutA(hdcDisplay
, 11, 22, 0, NULL
, "Test", 4, dx
);
2442 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2444 ret
= EndPath(hdcDisplay
);
2445 ok(ret
, "EndPath error %d\n", GetLastError());
2447 ret
= GetPath(hdcDisplay
, NULL
, NULL
, 0);
2448 ok(!ret
, "expected 0, got %d\n", ret
);
2450 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
2451 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2453 ret
= BeginPath(hdcMetafile
);
2454 ok(ret
, "BeginPath error %d\n", GetLastError());
2456 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2457 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2459 ret
= EndPath(hdcMetafile
);
2460 ok(ret
, "EndPath error %d\n", GetLastError());
2462 ret
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
2463 ok(!ret
, "expected 0, got %d\n", ret
);
2465 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2466 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2468 /* this doesn't succeed yet: EMF has correct size, all EMF records
2469 * are there, but their contents don't match for different reasons.
2471 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_ON_PATH_BITS
),
2472 "emf_TextOut_on_path", FALSE
) != 0)
2474 dump_emf_bits(hMetafile
, "emf_TextOut_on_path");
2475 dump_emf_records(hMetafile
, "emf_TextOut_on_path");
2478 ret
= DeleteEnhMetaFile(hMetafile
);
2479 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2481 /* with outline font */
2482 memset(&lf
, 0, sizeof(lf
));
2483 lf
.lfCharSet
= ANSI_CHARSET
;
2484 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
2485 lf
.lfWeight
= FW_DONTCARE
;
2487 lf
.lfQuality
= DEFAULT_QUALITY
;
2488 lstrcpyA(lf
.lfFaceName
, "Tahoma");
2489 hFont
= CreateFontIndirectA(&lf
);
2490 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
2491 hFont
= SelectObject(hdcDisplay
, hFont
);
2493 ret
= BeginPath(hdcDisplay
);
2494 ok(ret
, "BeginPath error %d\n", GetLastError());
2496 ret
= ExtTextOutA(hdcDisplay
, 11, 22, 0, NULL
, "Test", 4, dx
);
2497 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2499 ret
= EndPath(hdcDisplay
);
2500 ok(ret
, "EndPath error %d\n", GetLastError());
2502 ret
= GetPath(hdcDisplay
, NULL
, NULL
, 0);
2503 ok(ret
!= 0, "expected != 0\n");
2505 SelectObject(hdcDisplay
, hFont
);
2507 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
2508 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2510 hFont
= SelectObject(hdcMetafile
, hFont
);
2512 ret
= BeginPath(hdcMetafile
);
2513 ok(ret
, "BeginPath error %d\n", GetLastError());
2515 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
2516 ok(ret
, "ExtTextOut error %d\n", GetLastError());
2518 ret
= EndPath(hdcMetafile
);
2519 ok(ret
, "EndPath error %d\n", GetLastError());
2521 ret
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
2522 ok(!ret
, "expected 0, got %d\n", ret
);
2524 hFont
= SelectObject(hdcMetafile
, hFont
);
2525 DeleteObject(hFont
);
2527 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
2528 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2530 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_OUTLINE_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_OUTLINE_ON_PATH_BITS
),
2531 "emf_TextOut_on_path", FALSE
) != 0)
2533 dump_emf_bits(hMetafile
, "emf_TextOut_outline_on_path");
2534 dump_emf_records(hMetafile
, "emf_TextOut_outline_on_path");
2537 ret
= DeleteEnhMetaFile(hMetafile
);
2538 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
2540 ret
= ReleaseDC(hwnd
, hdcDisplay
);
2541 ok(ret
, "ReleaseDC error %d\n", GetLastError());
2542 DestroyWindow(hwnd
);
2545 static const unsigned char EMF_CLIPPING
[] =
2547 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2549 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2551 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2552 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2553 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2554 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2556 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2557 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2559 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2560 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2561 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2562 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2563 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2564 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2565 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2566 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2567 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2568 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2569 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2570 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2571 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2572 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2575 static void translate( POINT
*pt
, UINT count
, const XFORM
*xform
)
2579 FLOAT x
= (FLOAT
)pt
->x
;
2580 FLOAT y
= (FLOAT
)pt
->y
;
2581 pt
->x
= (LONG
)floor( x
* xform
->eM11
+ y
* xform
->eM21
+ xform
->eDx
+ 0.5 );
2582 pt
->y
= (LONG
)floor( x
* xform
->eM12
+ y
* xform
->eM22
+ xform
->eDy
+ 0.5 );
2587 /* Compare rectangles allowing rounding errors */
2588 static BOOL
is_equal_rect(const RECT
*rc1
, const RECT
*rc2
)
2590 return abs(rc1
->left
- rc2
->left
) <= 1 &&
2591 abs(rc1
->top
- rc2
->top
) <= 1 &&
2592 abs(rc1
->right
- rc2
->right
) <= 1 &&
2593 abs(rc1
->bottom
- rc2
->bottom
) <= 1;
2596 static int CALLBACK
clip_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2597 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
2599 if (emr
->iType
== EMR_EXTSELECTCLIPRGN
)
2601 const EMREXTSELECTCLIPRGN
*clip
= (const EMREXTSELECTCLIPRGN
*)emr
;
2605 char buf
[sizeof(RGNDATAHEADER
) + sizeof(RECT
)];
2607 const union _rgn
*rgn1
;
2609 RECT rect
, rc_transformed
;
2610 const RECT
*rc
= (const RECT
*)param
;
2616 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2617 clip
->cbRgnData
, clip
->iMode
);
2619 ok(clip
->iMode
== RGN_COPY
, "expected RGN_COPY, got %u\n", clip
->iMode
);
2620 ok(clip
->cbRgnData
>= sizeof(RGNDATAHEADER
) + sizeof(RECT
),
2621 "too small data block: %u bytes\n", clip
->cbRgnData
);
2622 if (clip
->cbRgnData
< sizeof(RGNDATAHEADER
) + sizeof(RECT
))
2625 rgn1
= (const union _rgn
*)clip
->RgnData
;
2627 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2628 rgn1
->data
.rdh
.dwSize
, rgn1
->data
.rdh
.iType
,
2629 rgn1
->data
.rdh
.nCount
, rgn1
->data
.rdh
.nRgnSize
,
2630 rgn1
->data
.rdh
.rcBound
.left
, rgn1
->data
.rdh
.rcBound
.top
,
2631 rgn1
->data
.rdh
.rcBound
.right
, rgn1
->data
.rdh
.rcBound
.bottom
);
2633 ok(EqualRect(&rgn1
->data
.rdh
.rcBound
, rc
), "rects don't match\n");
2635 rect
= *(const RECT
*)rgn1
->data
.Buffer
;
2636 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2637 ok(EqualRect(&rect
, rc
), "rects don't match\n");
2639 ok(rgn1
->data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn1
->data
.rdh
.dwSize
);
2640 ok(rgn1
->data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn1
->data
.rdh
.iType
);
2641 ok(rgn1
->data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn1
->data
.rdh
.nCount
);
2642 ok(rgn1
->data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2643 broken(rgn1
->data
.rdh
.nRgnSize
== 168), /* NT4 */
2644 "expected sizeof(RECT), got %u\n", rgn1
->data
.rdh
.nRgnSize
);
2646 hrgn
= CreateRectRgn(0, 0, 0, 0);
2648 memset(&xform
, 0, sizeof(xform
));
2649 SetLastError(0xdeadbeef);
2650 ret
= GetWorldTransform(hdc
, &xform
);
2651 is_win9x
= !ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
;
2653 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
2655 trace("xform.eM11 %f, xform.eM22 %f\n", xform
.eM11
, xform
.eM22
);
2657 ret
= GetClipRgn(hdc
, hrgn
);
2658 ok(ret
== 0, "GetClipRgn returned %d, expected 0\n", ret
);
2660 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
2662 ret
= GetClipRgn(hdc
, hrgn
);
2663 ok(ret
== 1, "GetClipRgn returned %d, expected 1\n", ret
);
2665 /* Win9x returns empty clipping region */
2666 if (is_win9x
) return 1;
2668 ret
= GetRegionData(hrgn
, 0, NULL
);
2669 ok(ret
== sizeof(rgn2
.data
.rdh
) + sizeof(RECT
), "expected sizeof(rgn), got %u\n", ret
);
2671 ret
= GetRegionData(hrgn
, sizeof(rgn2
), &rgn2
.data
);
2672 ok(ret
== sizeof(rgn2
), "expected sizeof(rgn2), got %u\n", ret
);
2674 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2675 rgn2
.data
.rdh
.dwSize
, rgn2
.data
.rdh
.iType
,
2676 rgn2
.data
.rdh
.nCount
, rgn2
.data
.rdh
.nRgnSize
,
2677 rgn2
.data
.rdh
.rcBound
.left
, rgn2
.data
.rdh
.rcBound
.top
,
2678 rgn2
.data
.rdh
.rcBound
.right
, rgn2
.data
.rdh
.rcBound
.bottom
);
2680 rect
= rgn2
.data
.rdh
.rcBound
;
2681 rc_transformed
= *rc
;
2682 translate((POINT
*)&rc_transformed
, 2, &xform
);
2683 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2684 rc_transformed
.right
, rc_transformed
.bottom
);
2685 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2687 rect
= *(const RECT
*)rgn2
.data
.Buffer
;
2688 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2689 rc_transformed
= *rc
;
2690 translate((POINT
*)&rc_transformed
, 2, &xform
);
2691 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2692 rc_transformed
.right
, rc_transformed
.bottom
);
2693 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2695 ok(rgn2
.data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn2
.data
.rdh
.dwSize
);
2696 ok(rgn2
.data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn2
.data
.rdh
.iType
);
2697 ok(rgn2
.data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn2
.data
.rdh
.nCount
);
2698 ok(rgn2
.data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2699 broken(rgn2
.data
.rdh
.nRgnSize
== 168), /* NT4 */
2700 "expected sizeof(RECT), got %u\n", rgn2
.data
.rdh
.nRgnSize
);
2707 static void test_emf_clipping(void)
2709 static const RECT rc
= { 0, 0, 100, 100 };
2710 RECT rc_clip
= { 100, 100, 1024, 1024 };
2716 RECT rc_res
, rc_sclip
;
2718 SetLastError(0xdeadbeef);
2719 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2720 ok(hdc
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2722 /* Need to write something to the emf, otherwise Windows won't play it back */
2725 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2726 ret
= SelectClipRgn(hdc
, hrgn
);
2727 ok(ret
== SIMPLEREGION
, "expected SIMPLEREGION, got %d\n", ret
);
2729 SetLastError(0xdeadbeef);
2730 hemf
= CloseEnhMetaFile(hdc
);
2731 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2733 if (compare_emf_bits(hemf
, EMF_CLIPPING
, sizeof(EMF_CLIPPING
),
2734 "emf_clipping", FALSE
) != 0)
2736 dump_emf_bits(hemf
, "emf_clipping");
2737 dump_emf_records(hemf
, "emf_clipping");
2742 /* Win9x doesn't play EMFs on invisible windows */
2743 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2744 0, 0, 200, 200, 0, 0, 0, NULL
);
2745 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2749 ret
= EnumEnhMetaFile(hdc
, hemf
, clip_emf_enum_proc
, &rc_clip
, &rc
);
2750 ok(ret
, "EnumEnhMetaFile error %d\n", GetLastError());
2752 DeleteEnhMetaFile(hemf
);
2753 ReleaseDC(hwnd
, hdc
);
2754 DestroyWindow(hwnd
);
2756 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2758 SetRect(&rc_sclip
, 100, 100, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2759 hrgn
= CreateRectRgn(rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
);
2760 SelectClipRgn(hdc
, hrgn
);
2761 SetRect(&rc_res
, -1, -1, -1, -1);
2762 ret
= GetClipBox(hdc
, &rc_res
);
2763 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2764 ok(EqualRect(&rc_res
, &rc_sclip
),
2765 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2766 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2767 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2769 OffsetRect(&rc_sclip
, -100, -100);
2770 ret
= OffsetClipRgn(hdc
, -100, -100);
2771 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2772 SetRect(&rc_res
, -1, -1, -1, -1);
2773 ret
= GetClipBox(hdc
, &rc_res
);
2774 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2775 ok(EqualRect(&rc_res
, &rc_sclip
),
2776 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2777 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2778 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2780 ret
= IntersectClipRect(hdc
, 0, 0, 100, 100);
2781 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2782 if (ret
== COMPLEXREGION
)
2784 /* XP returns COMPLEXREGION although region contains only 1 rect */
2785 ret
= GetClipRgn(hdc
, hrgn
);
2786 ok(ret
== 1, "expected 1, got %d\n", ret
);
2787 ret
= rgn_rect_count(hrgn
);
2788 ok(ret
== 1, "expected 1, got %d\n", ret
);
2790 SetRect(&rc_res
, -1, -1, -1, -1);
2791 ret
= GetClipBox(hdc
, &rc_res
);
2792 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2793 ok(EqualRect(&rc_res
, &rc
),
2794 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2795 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
2796 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2798 SetRect(&rc_sclip
, 0, 0, 100, 50);
2799 ret
= ExcludeClipRect(hdc
, 0, 50, 100, 100);
2800 ok(ret
== SIMPLEREGION
|| broken(ret
== COMPLEXREGION
) /* XP */, "got %d\n", ret
);
2801 if (ret
== COMPLEXREGION
)
2803 /* XP returns COMPLEXREGION although region contains only 1 rect */
2804 ret
= GetClipRgn(hdc
, hrgn
);
2805 ok(ret
== 1, "expected 1, got %d\n", ret
);
2806 ret
= rgn_rect_count(hrgn
);
2807 ok(ret
== 1, "expected 1, got %d\n", ret
);
2809 SetRect(&rc_res
, -1, -1, -1, -1);
2810 ret
= GetClipBox(hdc
, &rc_res
);
2811 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2812 ok(EqualRect(&rc_res
, &rc_sclip
),
2813 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2814 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2815 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2817 hemf
= CloseEnhMetaFile(hdc
);
2818 DeleteEnhMetaFile(hemf
);
2822 static const unsigned char MF_CLIP_BITS
[] = {
2824 0x01, 0x00, /* mtType */
2825 0x09, 0x00, /* mtHeaderSize */
2826 0x00, 0x03, /* mtVersion */
2827 0x32, 0x00, 0x00, 0x00, /* mtSize */
2828 0x01, 0x00, /* mtNoObjects */
2829 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2830 0x00, 0x00, /* reserved */
2832 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2833 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2834 0xff, 0x06, /* META_CREATEREGION */
2835 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2836 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2837 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2838 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2841 /* METARECORD for SelectObject */
2842 0x04, 0x00, 0x00, 0x00,
2843 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2847 0x04, 0x00, 0x00, 0x00,
2848 0xf0, 0x01, /* META_DELETEOBJECT */
2851 /* METARECORD for MoveTo(1,0x30) */
2852 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2853 0x14, 0x02, /* META_MOVETO */
2857 /* METARECORD for LineTo(0x20, 0x30) */
2858 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2859 0x13, 0x02, /* META_LINETO */
2864 0x03, 0x00, 0x00, 0x00,
2868 static int clip_mf_enum_proc_seen_selectclipregion
;
2869 static int clip_mf_enum_proc_seen_selectobject
;
2871 static int CALLBACK
clip_mf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
2872 METARECORD
*mr
, int n_objs
, LPARAM param
)
2874 switch (mr
->rdFunction
) {
2875 case META_SELECTCLIPREGION
:
2876 clip_mf_enum_proc_seen_selectclipregion
++;
2878 case META_SELECTOBJECT
:
2879 clip_mf_enum_proc_seen_selectobject
++;
2885 static void test_mf_clipping(void)
2887 /* left top right bottom */
2888 static RECT rc_clip
= { 0x11, 0x22, 0x33, 0x44 };
2895 SetLastError(0xdeadbeef);
2896 hdc
= CreateMetaFileA(NULL
);
2897 ok(hdc
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2899 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2900 ret
= SelectClipRgn(hdc
, hrgn
);
2901 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2902 ok(ret
== NULLREGION
, "expected NULLREGION, got %d\n", ret
);
2904 /* Draw a line that starts off left of the clip region and ends inside it */
2905 MoveToEx(hdc
, 0x1, 0x30, NULL
);
2906 LineTo(hdc
, 0x20, 0x30);
2908 SetLastError(0xdeadbeef);
2909 hmf
= CloseMetaFile(hdc
);
2910 ok(hmf
!= 0, "CloseMetaFile error %d\n", GetLastError());
2912 if (compare_mf_bits(hmf
, MF_CLIP_BITS
, sizeof(MF_CLIP_BITS
),
2913 "mf_clipping") != 0)
2915 dump_mf_bits(hmf
, "mf_clipping");
2920 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2921 0, 0, 200, 200, 0, 0, 0, NULL
);
2922 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2926 ret
= EnumMetaFile(hdc
, hmf
, clip_mf_enum_proc
, (LPARAM
)&rc_clip
);
2927 ok(ret
, "EnumMetaFile error %d\n", GetLastError());
2929 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2930 ok(clip_mf_enum_proc_seen_selectclipregion
== 0,
2931 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion
);
2932 ok(clip_mf_enum_proc_seen_selectobject
== 1,
2933 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject
);
2935 DeleteMetaFile(hmf
);
2936 ReleaseDC(hwnd
, hdc
);
2937 DestroyWindow(hwnd
);
2940 static const unsigned char MF_PATH_BITS
[] =
2942 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2943 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2944 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2945 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2946 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2947 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2948 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2949 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2950 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2951 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2952 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2955 static void test_mf_GetPath(void)
2962 SetLastError(0xdeadbeef);
2963 hdc
= CreateMetaFileA(NULL
);
2964 ok(hdc
!= 0, "CreateMetaFileA error %d\n", GetLastError());
2966 ret
= BeginPath(hdc
);
2967 ok(!ret
, "BeginPath on metafile DC should fail\n");
2968 ret
= MoveToEx(hdc
, 50, 50, NULL
);
2969 ok( ret
, "MoveToEx error %d.\n", GetLastError());
2970 ret
= LineTo(hdc
, 50, 150);
2971 ok( ret
, "LineTo error %d.\n", GetLastError());
2972 ret
= LineTo(hdc
, 150, 150);
2973 ok( ret
, "LineTo error %d.\n", GetLastError());
2974 ret
= LineTo(hdc
, 150, 50);
2975 ok( ret
, "LineTo error %d.\n", GetLastError());
2976 ret
= LineTo(hdc
, 50, 50);
2977 ok( ret
, "LineTo error %d.\n", GetLastError());
2978 Rectangle(hdc
, 10, 10, 20, 20);
2981 size
= GetPath(hdc
, NULL
, NULL
, 0);
2982 ok( size
== -1, "GetPath returned %d.\n", size
);
2984 hmf
= CloseMetaFile(hdc
);
2985 ok(hmf
!= 0, "CloseMetaFile error %d\n", GetLastError());
2987 if (compare_mf_bits (hmf
, MF_PATH_BITS
, sizeof(MF_PATH_BITS
), "mf_GetPath") != 0)
2989 dump_mf_bits(hmf
, "mf_GetPath");
2990 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2993 ret
= DeleteMetaFile(hmf
);
2994 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
2997 static INT CALLBACK
EmfEnumProc(HDC hdc
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
, INT nObj
, LPARAM lpData
)
2999 LPMETAFILEPICT lpMFP
= (LPMETAFILEPICT
)lpData
;
3000 POINT mapping
[2] = { { 0, 0 }, { 10, 10 } };
3001 /* When using MM_TEXT Win9x does not update the mapping mode
3002 * until a record is played which actually outputs something */
3003 PlayEnhMetaFileRecord(hdc
, lpHTable
, lpEMFR
, nObj
);
3004 LPtoDP(hdc
, mapping
, 2);
3005 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
3006 lpEMFR
->iType
, lpEMFR
->nSize
,
3007 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
);
3009 if (lpEMFR
->iType
== EMR_LINETO
)
3012 if (!lpMFP
|| lpMFP
->mm
== MM_TEXT
)
3016 x1
= (INT
)floor(10 * 100.0 / LINE_X
+ 0.5);
3017 y1
= (INT
)floor(10 * 100.0 / LINE_Y
+ 0.5);
3021 ok(lpMFP
->mm
== MM_ANISOTROPIC
, "mm=%d\n", lpMFP
->mm
);
3023 x0
= MulDiv(0, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
3024 y0
= MulDiv(0, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
3025 x1
= MulDiv(10, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
3026 y1
= MulDiv(10, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
3028 ok(mapping
[0].x
== x0
&& mapping
[0].y
== y0
&& mapping
[1].x
== x1
&& mapping
[1].y
== y1
,
3029 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
3030 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
,
3036 static HENHMETAFILE
create_converted_emf(const METAFILEPICT
*mfp
)
3045 hdcMf
= CreateMetaFileA(NULL
);
3046 ok(hdcMf
!= NULL
, "CreateMetaFile failed with error %d\n", GetLastError());
3047 ret
= LineTo(hdcMf
, (INT
)LINE_X
, (INT
)LINE_Y
);
3048 ok(ret
, "LineTo failed with error %d\n", GetLastError());
3049 hmf
= CloseMetaFile(hdcMf
);
3050 ok(hmf
!= NULL
, "CloseMetaFile failed with error %d\n", GetLastError());
3052 if (compare_mf_bits (hmf
, MF_LINETO_BITS
, sizeof(MF_LINETO_BITS
), "mf_LineTo") != 0)
3054 dump_mf_bits(hmf
, "mf_LineTo");
3055 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
3058 size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
3059 ok(size
, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
3060 pBits
= HeapAlloc(GetProcessHeap(), 0, size
);
3061 GetMetaFileBitsEx(hmf
, size
, pBits
);
3062 DeleteMetaFile(hmf
);
3063 hemf
= SetWinMetaFileBits(size
, pBits
, NULL
, mfp
);
3064 HeapFree(GetProcessHeap(), 0, pBits
);
3068 static void test_mf_conversions(void)
3070 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
3072 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
3075 RECT rect
= { 0, 0, 100, 100 };
3076 mfp
.mm
= MM_ANISOTROPIC
;
3080 hemf
= create_converted_emf(&mfp
);
3082 if (compare_emf_bits(hemf
, EMF_LINETO_MM_ANISOTROPIC_BITS
, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS
),
3083 "emf_LineTo MM_ANISOTROPIC", TRUE
) != 0)
3085 dump_emf_bits(hemf
, "emf_LineTo MM_ANISOTROPIC");
3086 dump_emf_records(hemf
, "emf_LineTo MM_ANISOTROPIC");
3089 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
3091 DeleteEnhMetaFile(hemf
);
3092 DeleteDC(hdcOffscreen
);
3095 trace("Testing MF->EMF conversion (MM_TEXT)\n");
3097 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
3100 RECT rect
= { 0, 0, 100, 100 };
3105 hemf
= create_converted_emf(&mfp
);
3107 if (compare_emf_bits(hemf
, EMF_LINETO_MM_TEXT_BITS
, sizeof(EMF_LINETO_MM_TEXT_BITS
),
3108 "emf_LineTo MM_TEXT", TRUE
) != 0)
3110 dump_emf_bits(hemf
, "emf_LineTo MM_TEXT");
3111 dump_emf_records(hemf
, "emf_LineTo MM_TEXT");
3114 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
3116 DeleteEnhMetaFile(hemf
);
3117 DeleteDC(hdcOffscreen
);
3120 trace("Testing MF->EMF conversion (NULL mfp)\n");
3122 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
3124 RECT rect
= { 0, 0, 100, 100 };
3125 hemf
= create_converted_emf(NULL
);
3127 if (compare_emf_bits(hemf
, EMF_LINETO_BITS
, sizeof(EMF_LINETO_BITS
),
3128 "emf_LineTo NULL", TRUE
) != 0)
3130 dump_emf_bits(hemf
, "emf_LineTo NULL");
3131 dump_emf_records(hemf
, "emf_LineTo NULL");
3134 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, NULL
, &rect
);
3136 DeleteEnhMetaFile(hemf
);
3137 DeleteDC(hdcOffscreen
);
3141 static BOOL
getConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
3142 LONG mm
, LONG xExt
, LONG yExt
,
3143 RECTL
* rclBounds
, RECTL
* rclFrame
)
3146 METAFILEPICT
* mfpPtr
= NULL
;
3148 ENHMETAHEADER header
;
3159 emf
= SetWinMetaFileBits(buffer_size
, buffer
, NULL
, mfpPtr
);
3160 ok(emf
!= NULL
, "SetWinMetaFileBits failed\n");
3161 if (!emf
) return FALSE
;
3162 res
= GetEnhMetaFileHeader(emf
, sizeof(header
), &header
);
3163 ok(res
!= 0, "GetEnhMetaHeader failed\n");
3164 DeleteEnhMetaFile(emf
);
3165 if (!res
) return FALSE
;
3167 *rclBounds
= header
.rclBounds
;
3168 *rclFrame
= header
.rclFrame
;
3172 static void checkConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
3173 LONG mm
, LONG xExt
, LONG yExt
,
3174 RECTL
* rclBoundsExpected
, RECTL
* rclFrameExpected
)
3176 RECTL rclBounds
, rclFrame
;
3178 if (getConvertedFrameAndBounds(buffer_size
, buffer
, mfpIsNull
, mm
, xExt
, yExt
, &rclBounds
, &rclFrame
))
3185 msg
= "mfp == NULL";
3189 const char * mm_str
;
3192 case MM_ANISOTROPIC
: mm_str
= "MM_ANISOTROPIC"; break;
3193 case MM_ISOTROPIC
: mm_str
= "MM_ISOTROPIC"; break;
3194 default: mm_str
= "Unexpected";
3196 sprintf(buf
, "mm=%s, xExt=%d, yExt=%d", mm_str
, xExt
, yExt
);
3200 ok(rclBounds
.left
== rclBoundsExpected
->left
, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected
->left
, rclBounds
.left
, msg
);
3201 ok(rclBounds
.top
== rclBoundsExpected
->top
, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected
->top
, rclBounds
.top
, msg
);
3202 ok(rclBounds
.right
== rclBoundsExpected
->right
, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected
->right
, rclBounds
.right
, msg
);
3203 ok(rclBounds
.bottom
== rclBoundsExpected
->bottom
, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected
->bottom
, rclBounds
.bottom
, msg
);
3204 ok(rclFrame
.left
== rclFrameExpected
->left
, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected
->left
, rclFrame
.left
, msg
);
3205 ok(rclFrame
.top
== rclFrameExpected
->top
, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected
->top
, rclFrame
.top
, msg
);
3206 ok(rclFrame
.right
== rclFrameExpected
->right
, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected
->right
, rclFrame
.right
, msg
);
3207 ok(rclFrame
.bottom
== rclFrameExpected
->bottom
, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected
->bottom
, rclFrame
.bottom
, msg
);
3211 static void test_SetWinMetaFileBits(void)
3219 RECTL rclBoundsAnisotropic
, rclFrameAnisotropic
;
3220 RECTL rclBoundsIsotropic
, rclFrameIsotropic
;
3221 RECTL rclBounds
, rclFrame
;
3225 wmfDC
= CreateMetaFileA(NULL
);
3226 ok(wmfDC
!= NULL
, "CreateMetaFile failed\n");
3229 SetWindowExtEx(wmfDC
, 100, 100, NULL
);
3230 rect
.left
= rect
.top
= 0;
3231 rect
.right
= rect
.bottom
= 50;
3232 FillRect(wmfDC
, &rect
, GetStockObject(BLACK_BRUSH
));
3233 wmf
= CloseMetaFile(wmfDC
);
3234 ok(wmf
!= NULL
, "Metafile creation failed\n");
3237 buffer_size
= GetMetaFileBitsEx(wmf
, 0, NULL
);
3238 ok(buffer_size
!= 0, "GetMetaFileBitsEx failed\n");
3239 if (buffer_size
== 0)
3241 DeleteMetaFile(wmf
);
3245 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
);
3246 ok(buffer
!= NULL
, "HeapAlloc failed\n");
3249 DeleteMetaFile(wmf
);
3253 res
= GetMetaFileBitsEx(wmf
, buffer_size
, buffer
);
3254 ok(res
== buffer_size
, "GetMetaFileBitsEx failed\n");
3255 DeleteMetaFile(wmf
);
3256 if (res
!= buffer_size
)
3258 HeapFree(GetProcessHeap(), 0, buffer
);
3262 /* Get the reference bounds and frame */
3263 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3264 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3266 ok(rclBoundsAnisotropic
.left
== 0 && rclBoundsAnisotropic
.top
== 0 &&
3267 rclBoundsIsotropic
.left
== 0 && rclBoundsIsotropic
.top
== 0,
3268 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3270 ok(rclBoundsAnisotropic
.right
>= rclBoundsIsotropic
.right
, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3271 ok(rclBoundsAnisotropic
.bottom
>= rclBoundsIsotropic
.bottom
, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3272 diffx
= rclBoundsIsotropic
.right
- rclBoundsIsotropic
.bottom
;
3273 if (diffx
< 0) diffx
= -diffx
;
3274 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3276 dc
= CreateCompatibleDC(NULL
);
3278 /* Allow 1 mm difference (rounding errors) */
3279 diffx
= rclBoundsAnisotropic
.right
- GetDeviceCaps(dc
, HORZRES
) / 2;
3280 diffy
= rclBoundsAnisotropic
.bottom
- GetDeviceCaps(dc
, VERTRES
) / 2;
3281 if (diffx
< 0) diffx
= -diffx
;
3282 if (diffy
< 0) diffy
= -diffy
;
3285 ok(diffx
<= 1 && diffy
<= 1,
3286 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3287 GetDeviceCaps(dc
, HORZRES
) / 2, GetDeviceCaps(dc
, VERTRES
) / 2, rclBoundsAnisotropic
.right
, rclBoundsAnisotropic
.bottom
);
3290 /* Allow 1 mm difference (rounding errors) */
3291 diffx
= rclFrameAnisotropic
.right
/ 100 - GetDeviceCaps(dc
, HORZSIZE
) / 2;
3292 diffy
= rclFrameAnisotropic
.bottom
/ 100 - GetDeviceCaps(dc
, VERTSIZE
) / 2;
3293 if (diffx
< 0) diffx
= -diffx
;
3294 if (diffy
< 0) diffy
= -diffy
;
3297 ok(diffx
<= 1 && diffy
<= 1,
3298 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3299 GetDeviceCaps(dc
, HORZSIZE
) / 2, GetDeviceCaps(dc
, VERTSIZE
) / 2, rclFrameAnisotropic
.right
/ 100, rclFrameAnisotropic
.bottom
/ 100);
3303 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3304 checkConvertedFrameAndBounds(buffer_size
, buffer
, TRUE
, 0, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3306 /* If xExt or yExt is zero or negative, the whole device surface is used */
3307 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3308 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3309 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3310 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3311 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3312 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3313 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3314 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3315 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3316 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3317 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3318 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3320 /* MSDN says that negative xExt and yExt values specify a ratio.
3321 Check that this is wrong and the whole device surface is used */
3322 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -1000, -100, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
3323 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -1000, -100, &rclBoundsIsotropic
, &rclFrameIsotropic
);
3325 /* Ordinary conversions */
3327 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3329 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3330 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3331 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0 && rclBounds
.right
> rclBounds
.bottom
,
3332 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3335 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3337 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
3338 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3339 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0,
3340 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3342 /* Wine has a rounding error */
3343 diffx
= rclBounds
.right
- rclBounds
.bottom
;
3344 if (diffx
< 0) diffx
= -diffx
;
3345 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3348 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_HIMETRIC
, 30000, 20000, &rclBounds
, &rclFrame
))
3350 ok(rclFrame
.right
- rclFrame
.left
!= 30000 && rclFrame
.bottom
- rclFrame
.top
!= 20000,
3351 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3354 HeapFree(GetProcessHeap(), 0, buffer
);
3357 static BOOL
near_match(int x
, int y
)
3359 int epsilon
= min(abs(x
), abs(y
));
3361 epsilon
= max(epsilon
/100, 2);
3363 if(x
< y
- epsilon
|| x
> y
+ epsilon
) return FALSE
;
3367 static void getwinmetafilebits(UINT mode
, int scale
, RECT
*rc
)
3370 HDC display_dc
, emf_dc
;
3371 ENHMETAHEADER
*enh_header
;
3372 UINT size
, emf_size
, i
;
3375 METAHEADER
*mh
= NULL
;
3377 INT horz_res
, vert_res
, horz_size
, vert_size
;
3378 INT curve_caps
, line_caps
, poly_caps
;
3380 display_dc
= GetDC(NULL
);
3381 ok(display_dc
!= NULL
, "display_dc is NULL\n");
3383 horz_res
= GetDeviceCaps(display_dc
, HORZRES
);
3384 vert_res
= GetDeviceCaps(display_dc
, VERTRES
);
3385 horz_size
= GetDeviceCaps(display_dc
, HORZSIZE
);
3386 vert_size
= GetDeviceCaps(display_dc
, VERTSIZE
);
3388 emf_dc
= CreateEnhMetaFileA(display_dc
, NULL
, rc
, NULL
);
3389 ok(emf_dc
!= NULL
, "emf_dc is NULL\n");
3391 curve_caps
= GetDeviceCaps(emf_dc
, CURVECAPS
);
3392 ok(curve_caps
== 511, "expect 511 got %d\n", curve_caps
);
3394 line_caps
= GetDeviceCaps(emf_dc
, LINECAPS
);
3395 ok(line_caps
== 254, "expect 254 got %d\n", line_caps
);
3397 poly_caps
= GetDeviceCaps(emf_dc
, POLYGONALCAPS
);
3398 ok(poly_caps
== 255, "expect 511 got %d\n", poly_caps
);
3400 for(i
= 0; i
< 3000; i
++) /* This is enough to take emf_size > 0xffff */
3401 Rectangle(emf_dc
, 0, 0, 1000, 20);
3402 emf
= CloseEnhMetaFile(emf_dc
);
3403 ok(emf
!= NULL
, "emf is NULL\n");
3405 emf_size
= GetEnhMetaFileBits(emf
, 0, NULL
);
3406 enh_header
= HeapAlloc(GetProcessHeap(), 0, emf_size
);
3407 emf_size
= GetEnhMetaFileBits(emf
, emf_size
, (BYTE
*)enh_header
);
3408 DeleteEnhMetaFile(emf
);
3409 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3410 have different resolutions */
3411 enh_header
->szlDevice
.cx
*= scale
;
3412 emf
= SetEnhMetaFileBits(emf_size
, (BYTE
*)enh_header
);
3413 ok(emf
!= NULL
, "emf is NULL\n");
3414 ok(EqualRect((RECT
*)&enh_header
->rclFrame
, rc
), "Frame rectangles differ\n");
3416 size
= GetWinMetaFileBits(emf
, 0, NULL
, mode
, display_dc
);
3418 broken(size
== 0), /* some versions of winxp fail for some reason */
3419 "GetWinMetaFileBits returns 0\n");
3421 mh
= HeapAlloc(GetProcessHeap(), 0, size
);
3422 GetWinMetaFileBits(emf
, size
, (BYTE
*)mh
, mode
, display_dc
);
3424 for(i
= 0; i
< size
/ 2; i
++) check
+= ((WORD
*)mh
)[i
];
3425 ok(check
== 0, "check %04x\n", check
);
3427 rec
= (METARECORD
*)(mh
+ 1);
3429 while(rec
->rdSize
&& rec
->rdFunction
)
3431 const DWORD chunk_size
= 0x2000;
3432 DWORD mfcomment_chunks
= (emf_size
+ chunk_size
- 1) / chunk_size
;
3434 if(rec_num
< mfcomment_chunks
)
3436 DWORD this_chunk_size
= chunk_size
;
3438 if(rec_num
== mfcomment_chunks
- 1)
3439 this_chunk_size
= emf_size
- rec_num
* chunk_size
;
3441 ok(rec
->rdSize
== (this_chunk_size
+ 44) / 2, "%04x: got %04x expected %04x\n", rec_num
, rec
->rdSize
, (this_chunk_size
+ 44) / 2);
3442 ok(rec
->rdFunction
== META_ESCAPE
, "%04x: got %04x\n", rec_num
, rec
->rdFunction
);
3443 if(rec
->rdSize
< (this_chunk_size
+ 44) / 2) break;
3444 ok(rec
->rdParm
[0] == MFCOMMENT
, "got %04x\n", rec
->rdParm
[0]);
3445 ok(rec
->rdParm
[1] == this_chunk_size
+ 34, "got %04x %x\n", rec
->rdParm
[1], emf_size
+ 34);
3446 ok(rec
->rdParm
[2] == 0x4d57, "got %04x\n", rec
->rdParm
[2]); /* WMFC */
3447 ok(rec
->rdParm
[3] == 0x4346, "got %04x\n", rec
->rdParm
[3]); /* " */
3448 ok(rec
->rdParm
[4] == 1, "got %04x\n", rec
->rdParm
[4]);
3449 ok(rec
->rdParm
[5] == 0, "got %04x\n", rec
->rdParm
[5]);
3450 ok(rec
->rdParm
[6] == 0, "got %04x\n", rec
->rdParm
[6]);
3451 ok(rec
->rdParm
[7] == 1, "got %04x\n", rec
->rdParm
[7]);
3452 /* parm[8] is the checksum, tested above */
3453 if(rec_num
> 0) ok(rec
->rdParm
[8] == 0, "got %04x\n", rec
->rdParm
[8]);
3454 ok(rec
->rdParm
[9] == 0, "got %04x\n", rec
->rdParm
[9]);
3455 ok(rec
->rdParm
[10] == 0, "got %04x\n", rec
->rdParm
[10]);
3456 ok(rec
->rdParm
[11] == mfcomment_chunks
, "got %04x\n", rec
->rdParm
[11]); /* num chunks */
3457 ok(rec
->rdParm
[12] == 0, "got %04x\n", rec
->rdParm
[12]);
3458 ok(rec
->rdParm
[13] == this_chunk_size
, "got %04x expected %04x\n", rec
->rdParm
[13], this_chunk_size
);
3459 ok(rec
->rdParm
[14] == 0, "got %04x\n", rec
->rdParm
[14]);
3460 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 */
3461 ok(*(DWORD
*)(rec
->rdParm
+ 17) == emf_size
, "got %08x emf_size %08x\n", *(DWORD
*)(rec
->rdParm
+ 17), emf_size
);
3462 ok(!memcmp(rec
->rdParm
+ 19, (char*)enh_header
+ rec_num
* chunk_size
, this_chunk_size
), "bits mismatch\n");
3465 else if(rec_num
== mfcomment_chunks
)
3467 ok(rec
->rdFunction
== META_SETMAPMODE
, "got %04x\n", rec
->rdFunction
);
3468 ok(rec
->rdParm
[0] == mode
, "got %04x\n", rec
->rdParm
[0]);
3470 else if(rec_num
== mfcomment_chunks
+ 1)
3473 ok(rec
->rdFunction
== META_SETWINDOWORG
, "got %04x\n", rec
->rdFunction
);
3478 case MM_ANISOTROPIC
:
3479 pt
.y
= MulDiv(rc
->top
, vert_res
, vert_size
* 100) + 1;
3480 pt
.x
= MulDiv(rc
->left
, horz_res
, horz_size
* 100);
3483 pt
.y
= MulDiv(-rc
->top
, 1, 10) + 1;
3484 pt
.x
= MulDiv( rc
->left
, 1, 10);
3487 pt
.y
= -rc
->top
+ 1;
3488 pt
.x
= (rc
->left
>= 0) ? rc
->left
: rc
->left
+ 1; /* strange but true */
3491 pt
.y
= MulDiv(-rc
->top
, 10, 254) + 1;
3492 pt
.x
= MulDiv( rc
->left
, 10, 254);
3495 pt
.y
= MulDiv(-rc
->top
, 100, 254) + 1;
3496 pt
.x
= MulDiv( rc
->left
, 100, 254);
3499 pt
.y
= MulDiv(-rc
->top
, 72 * 20, 2540) + 1;
3500 pt
.x
= MulDiv( rc
->left
, 72 * 20, 2540);
3505 ok(near_match((short)rec
->rdParm
[0], pt
.y
), "got %d expect %d\n", (short)rec
->rdParm
[0], pt
.y
);
3506 ok(near_match((short)rec
->rdParm
[1], pt
.x
), "got %d expect %d\n", (short)rec
->rdParm
[1], pt
.x
);
3508 if(rec_num
== mfcomment_chunks
+ 2)
3510 ok(rec
->rdFunction
== META_SETWINDOWEXT
, "got %04x\n", rec
->rdFunction
);
3511 ok(near_match((short)rec
->rdParm
[0], MulDiv(rc
->bottom
- rc
->top
, vert_res
, vert_size
* 100)),
3512 "got %d\n", (short)rec
->rdParm
[0]);
3513 ok(near_match((short)rec
->rdParm
[1], MulDiv(rc
->right
- rc
->left
, horz_res
, horz_size
* 100)),
3514 "got %d\n", (short)rec
->rdParm
[1]);
3518 rec
= (METARECORD
*)((WORD
*)rec
+ rec
->rdSize
);
3522 HeapFree(GetProcessHeap(), 0, mh
);
3523 HeapFree(GetProcessHeap(), 0, enh_header
);
3524 DeleteEnhMetaFile(emf
);
3526 ReleaseDC(NULL
, display_dc
);
3529 static void test_GetWinMetaFileBits(void)
3534 { 1000, 2000, 3000, 6000},
3535 {-1000, 2000, 3000, 6000},
3536 { 1000, -2000, 3000, 6000},
3537 { 1005, 2005, 3000, 6000},
3538 {-1005, -2005, 3000, 6000},
3539 {-1005, -2010, 3000, 6000},
3540 {-1005, 2010, 3000, 6000},
3546 for(mode
= MM_MIN
; mode
<= MM_MAX
; mode
++)
3549 for(rc
= frames
; rc
->right
- rc
->left
> 0; rc
++)
3551 getwinmetafilebits(mode
, 1, rc
);
3552 getwinmetafilebits(mode
, 2, rc
);
3557 static BOOL (WINAPI
*pGdiIsMetaPrintDC
)(HDC
);
3558 static BOOL (WINAPI
*pGdiIsMetaFileDC
)(HDC
);
3559 static BOOL (WINAPI
*pGdiIsPlayMetafileDC
)(HDC
);
3561 static void test_gdiis(void)
3563 RECT rect
= {0,0,100,100};
3564 HDC hdc
, hemfDC
, hmfDC
;
3568 /* resolve all the functions */
3569 hgdi32
= GetModuleHandleA("gdi32.dll");
3570 pGdiIsMetaPrintDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaPrintDC");
3571 pGdiIsMetaFileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaFileDC");
3572 pGdiIsPlayMetafileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsPlayMetafileDC");
3574 if(!pGdiIsMetaPrintDC
|| !pGdiIsMetaFileDC
|| !pGdiIsPlayMetafileDC
)
3576 win_skip("Needed GdiIs* functions are not available\n");
3580 /* try with nothing */
3581 ok(!pGdiIsMetaPrintDC(NULL
), "ismetaprint with NULL parameter\n");
3582 ok(!pGdiIsMetaFileDC(NULL
), "ismetafile with NULL parameter\n");
3583 ok(!pGdiIsPlayMetafileDC(NULL
), "isplaymetafile with NULL parameter\n");
3585 /* try with a metafile */
3586 hmfDC
= CreateMetaFileA(NULL
);
3587 ok(!pGdiIsMetaPrintDC(hmfDC
), "ismetaprint on metafile\n");
3588 ok(pGdiIsMetaFileDC(hmfDC
), "ismetafile on metafile\n");
3589 ok(!pGdiIsPlayMetafileDC(hmfDC
), "isplaymetafile on metafile\n");
3590 DeleteMetaFile(CloseMetaFile(hmfDC
));
3592 /* try with an enhanced metafile */
3594 hemfDC
= CreateEnhMetaFileW(hdc
, NULL
, &rect
, NULL
);
3595 ok(hemfDC
!= NULL
, "failed to create emf\n");
3597 ok(!pGdiIsMetaPrintDC(hemfDC
), "ismetaprint on emf\n");
3598 ok(pGdiIsMetaFileDC(hemfDC
), "ismetafile on emf\n");
3599 ok(!pGdiIsPlayMetafileDC(hemfDC
), "isplaymetafile on emf\n");
3601 hemf
= CloseEnhMetaFile(hemfDC
);
3602 ok(hemf
!= NULL
, "failed to close EMF\n");
3603 DeleteEnhMetaFile(hemf
);
3604 ReleaseDC(NULL
,hdc
);
3607 static void test_SetEnhMetaFileBits(void)
3613 memset(data
, 0xAA, sizeof(data
));
3614 SetLastError(0xdeadbeef);
3615 hemf
= SetEnhMetaFileBits(sizeof(data
), data
);
3616 ok(!hemf
, "SetEnhMetaFileBits should fail\n");
3617 ok(GetLastError() == ERROR_INVALID_DATA
||
3618 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x, WinMe */
3619 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3621 emh
= (ENHMETAHEADER
*)data
;
3622 memset(emh
, 0, sizeof(*emh
));
3624 emh
->iType
= EMR_HEADER
;
3625 emh
->nSize
= sizeof(*emh
);
3626 emh
->dSignature
= ENHMETA_SIGNATURE
;
3627 /* emh->nVersion = 0x10000; XP doesn't care about version */
3628 emh
->nBytes
= sizeof(*emh
);
3629 /* emh->nRecords = 1; XP doesn't care about records */
3630 emh
->nHandles
= 1; /* XP refuses to load a EMF if nHandles == 0 */
3632 SetLastError(0xdeadbeef);
3633 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3634 ok(hemf
!= 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3635 DeleteEnhMetaFile(hemf
);
3637 /* XP refuses to load unaligned EMF */
3639 SetLastError(0xdeadbeef);
3640 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3642 broken(hemf
!= NULL
), /* Win9x, WinMe */
3643 "SetEnhMetaFileBits should fail\n");
3644 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3645 DeleteEnhMetaFile(hemf
);
3647 emh
->dSignature
= 0;
3649 SetLastError(0xdeadbeef);
3650 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
3652 broken(hemf
!= NULL
), /* Win9x, WinMe */
3653 "SetEnhMetaFileBits should fail\n");
3654 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3655 DeleteEnhMetaFile(hemf
);
3658 static void test_emf_polybezier(void)
3665 SetLastError(0xdeadbeef);
3666 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3667 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3669 pts
[0].x
= pts
[0].y
= 10;
3670 pts
[1].x
= pts
[1].y
= 20;
3671 pts
[2].x
= pts
[2].y
= 15;
3672 pts
[3].x
= pts
[3].y
= 25;
3673 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO16 */
3674 ok( ret
, "PolyBezierTo failed\n" );
3675 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER16 */
3676 ok( ret
, "PolyBezier failed\n" );
3678 pts
[0].x
= pts
[0].y
= 32769;
3679 ret
= PolyBezier(hdcMetafile
, pts
, 4); /* EMR_POLYBEZIER */
3680 ok( ret
, "PolyBezier failed\n" );
3681 ret
= PolyBezierTo(hdcMetafile
, pts
, 3); /* EMR_POLYBEZIERTO */
3682 ok( ret
, "PolyBezierTo failed\n" );
3684 hemf
= CloseEnhMetaFile(hdcMetafile
);
3685 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3687 if(compare_emf_bits(hemf
, EMF_BEZIER_BITS
, sizeof(EMF_BEZIER_BITS
),
3688 "emf_Bezier", FALSE
) != 0)
3690 dump_emf_bits(hemf
, "emf_Bezier");
3691 dump_emf_records(hemf
, "emf_Bezier");
3694 DeleteEnhMetaFile(hemf
);
3697 static const unsigned char EMF_PATH_BITS
[] =
3699 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3700 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3701 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3703 0xef, 0xff, 0xff, 0xff, 0xea, 0xff, 0xff, 0xff,
3704 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3705 0x0c, 0x02, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
3706 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3707 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3708 0x80, 0x07, 0x00, 0x00, 0x3e, 0x04, 0x00, 0x00,
3709 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3711 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3712 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3713 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3714 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3715 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3716 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3717 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3718 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3719 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3720 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3721 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3722 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3723 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3724 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3725 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3726 0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
3727 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3728 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3729 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3730 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3731 0x15, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
3732 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3733 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3734 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3735 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3736 0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
3737 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3738 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3739 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3740 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3741 0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
3742 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3743 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3744 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3745 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3746 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3747 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3748 0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
3749 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3750 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3751 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
3752 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3753 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3754 0x5a, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
3755 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3756 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3757 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3758 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3759 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3760 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3761 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3762 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
3763 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3764 0x14, 0x00, 0x00, 0x00
3767 static void test_emf_GetPath(void)
3769 POINT pts
[4] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}};
3770 DWORD counts
[2] = {2, 2};
3776 SetLastError(0xdeadbeef);
3777 hdcMetafile
= CreateEnhMetaFileA(GetDC(0), NULL
, NULL
, NULL
);
3778 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3780 ret
= BeginPath(hdcMetafile
);
3781 ok(ret
, "BeginPath error %d\n", GetLastError());
3782 ret
= MoveToEx(hdcMetafile
, 50, 50, NULL
);
3783 ok( ret
, "MoveToEx error %d.\n", GetLastError());
3784 ret
= LineTo(hdcMetafile
, 50, 150);
3785 ok( ret
, "LineTo error %d.\n", GetLastError());
3786 ret
= LineTo(hdcMetafile
, 150, 150);
3787 ok( ret
, "LineTo error %d.\n", GetLastError());
3788 ret
= LineTo(hdcMetafile
, 150, 50);
3789 ok( ret
, "LineTo error %d.\n", GetLastError());
3790 ret
= LineTo(hdcMetafile
, 50, 50);
3791 ok( ret
, "LineTo error %d.\n", GetLastError());
3792 Rectangle(hdcMetafile
, 10, 10, 20, 20);
3793 Arc(hdcMetafile
, 21, 21, 39, 29, 39, 29, 21, 21);
3794 Chord(hdcMetafile
, 21, 21, 39, 29, 39, 29, 21, 21);
3795 Pie(hdcMetafile
, 21, 21, 39, 29, 39, 29, 21, 21);
3796 Ellipse(hdcMetafile
, 10, 10, 20, 20);
3797 RoundRect(hdcMetafile
, 10, 10, 20, 20, 3, 5);
3798 Polyline(hdcMetafile
, pts
, 4);
3799 PolyPolyline(hdcMetafile
, pts
, counts
, 2);
3800 EndPath(hdcMetafile
);
3802 size
= GetPath(hdcMetafile
, NULL
, NULL
, 0);
3803 todo_wine
ok( size
== 77, "GetPath returned %d.\n", size
);
3805 hemf
= CloseEnhMetaFile(hdcMetafile
);
3806 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
3808 if (compare_emf_bits(hemf
, EMF_PATH_BITS
, sizeof(EMF_PATH_BITS
), "test_emf_GetPath", FALSE
) != 0)
3810 dump_emf_bits(hemf
, "test_emf_GetPath");
3811 dump_emf_records(hemf
, "test_emf_GetPath");
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 START_TEST(metafile
)
3917 init_function_pointers();
3919 /* For enhanced metafiles (enhmfdrv) */
3921 test_ExtTextOutScale();
3925 test_emf_ExtTextOut_on_path();
3926 test_emf_clipping();
3927 test_emf_polybezier();
3929 test_emf_PolyPolyline();
3930 test_emf_GradientFill();
3932 /* For win-format metafiles (mfdrv) */
3936 test_mf_PatternBrush();
3938 test_CopyMetaFile();
3939 test_SetMetaFileBits();
3940 test_mf_ExtTextOut_on_path();
3944 /* For metafile conversions */
3945 test_mf_conversions();
3946 test_SetWinMetaFileBits();
3947 test_GetWinMetaFileBits();
3950 test_SetEnhMetaFileBits();