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
);
41 #define GDI_GET_PROC(func) \
42 p ## func = (void *)GetProcAddress(hGDI, #func); \
44 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
46 static void init_function_pointers(void)
53 hGDI
= GetModuleHandleA("gdi32.dll");
55 GDI_GET_PROC(GetRelAbs
);
56 GDI_GET_PROC(SetRelAbs
);
59 static int CALLBACK
eto_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
60 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
65 INT
*orig_dx
= (INT
*)param
;
69 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
74 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
79 ok(GetTextAlign(hdc
) == 0, "text align %08x\n", GetTextAlign(hdc
));
80 ok(GetBkColor(hdc
) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc
));
81 ok(GetTextColor(hdc
) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc
));
82 ok(GetROP2(hdc
) == R2_COPYPEN
, "rop %d\n", GetROP2(hdc
));
83 ok(GetArcDirection(hdc
) == AD_COUNTERCLOCKWISE
, "arc dir %d\n", GetArcDirection(hdc
));
84 ok(GetPolyFillMode(hdc
) == ALTERNATE
, "poly fill %d\n", GetPolyFillMode(hdc
));
85 ok(GetStretchBltMode(hdc
) == BLACKONWHITE
, "stretchblt mode %d\n", GetStretchBltMode(hdc
));
87 /* GetBkMode, GetRelAbs do not get reset to the default value */
88 ok(GetBkMode(hdc
) == OPAQUE
, "bk mode %d\n", GetBkMode(hdc
));
89 if(pSetRelAbs
&& pGetRelAbs
)
90 ok(pGetRelAbs(hdc
, 0) == RELATIVE
, "relabs %d\n", pGetRelAbs(hdc
, 0));
97 const EMREXTTEXTOUTA
*emr_ExtTextOutA
= (const EMREXTTEXTOUTA
*)emr
;
98 dx
= (const INT
*)((const char *)emr
+ emr_ExtTextOutA
->emrtext
.offDx
);
100 ret
= GetObjectA(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(device_lf
), &device_lf
);
101 ok( ret
== sizeof(device_lf
), "GetObjectA error %d\n", GetLastError());
103 /* compare up to lfOutPrecision, other values are not interesting,
104 * and in fact sometimes arbitrary adapted by Win9x.
106 ok(!memcmp(&orig_lf
, &device_lf
, FIELD_OFFSET(LOGFONTA
, lfOutPrecision
)), "fonts don't match\n");
107 ok(!lstrcmpA(orig_lf
.lfFaceName
, device_lf
.lfFaceName
), "font names don't match\n");
109 for(i
= 0; i
< emr_ExtTextOutA
->emrtext
.nChars
; i
++)
111 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
112 n_record
, i
, dx
[i
], orig_dx
[i
]);
115 emr_processed
= TRUE
;
119 case EMR_EXTTEXTOUTW
:
121 const EMREXTTEXTOUTW
*emr_ExtTextOutW
= (const EMREXTTEXTOUTW
*)emr
;
122 dx
= (const INT
*)((const char *)emr
+ emr_ExtTextOutW
->emrtext
.offDx
);
124 SetLastError(0xdeadbeef);
125 ret
= GetObjectA(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(device_lf
), &device_lf
);
126 ok( ret
== sizeof(device_lf
) ||
127 broken(ret
== (sizeof(device_lf
) - LF_FACESIZE
+ strlen(device_lf
.lfFaceName
) + 1)), /* NT4 */
128 "GetObjectA error %d\n", GetLastError());
130 /* compare up to lfOutPrecision, other values are not interesting,
131 * and in fact sometimes arbitrary adapted by Win9x.
133 ok(!memcmp(&orig_lf
, &device_lf
, FIELD_OFFSET(LOGFONTA
, lfOutPrecision
)), "fonts don't match\n");
134 ok(!lstrcmpA(orig_lf
.lfFaceName
, device_lf
.lfFaceName
), "font names don't match\n");
136 for(i
= 0; i
< emr_ExtTextOutW
->emrtext
.nChars
; i
++)
138 ok(orig_dx
[i
] == dx
[i
], "pass %d: dx[%d] (%d) didn't match %d\n",
139 n_record
, i
, dx
[i
], orig_dx
[i
]);
142 emr_processed
= TRUE
;
153 static void test_ExtTextOut(void)
156 HDC hdcDisplay
, hdcMetafile
;
157 HENHMETAFILE hMetafile
;
159 static const char text
[] = "Simple text to test ExtTextOut on metafiles";
161 static const RECT rc
= { 0, 0, 100, 100 };
164 assert(sizeof(dx
)/sizeof(dx
[0]) >= lstrlenA(text
));
166 /* Win9x doesn't play EMFs on invisible windows */
167 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
168 0, 0, 200, 200, 0, 0, 0, NULL
);
169 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
171 hdcDisplay
= GetDC(hwnd
);
172 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
174 trace("hdcDisplay %p\n", hdcDisplay
);
176 SetMapMode(hdcDisplay
, MM_TEXT
);
178 memset(&orig_lf
, 0, sizeof(orig_lf
));
180 orig_lf
.lfCharSet
= ANSI_CHARSET
;
181 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
182 orig_lf
.lfWeight
= FW_DONTCARE
;
183 orig_lf
.lfHeight
= 7;
184 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
185 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
186 hFont
= CreateFontIndirectA(&orig_lf
);
187 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
189 hFont
= SelectObject(hdcDisplay
, hFont
);
191 len
= lstrlenA(text
);
192 for (i
= 0; i
< len
; i
++)
194 ret
= GetCharWidthA(hdcDisplay
, text
[i
], text
[i
], &dx
[i
]);
195 ok( ret
, "GetCharWidthA error %d\n", GetLastError());
197 hFont
= SelectObject(hdcDisplay
, hFont
);
199 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
200 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
202 trace("hdcMetafile %p\n", hdcMetafile
);
204 ok(GetDeviceCaps(hdcMetafile
, TECHNOLOGY
) == DT_RASDISPLAY
,
205 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
207 hFont
= SelectObject(hdcMetafile
, hFont
);
209 /* 1. pass NULL lpDx */
210 ret
= ExtTextOutA(hdcMetafile
, 0, 0, 0, &rc
, text
, lstrlenA(text
), NULL
);
211 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
213 /* 2. pass custom lpDx */
214 ret
= ExtTextOutA(hdcMetafile
, 0, 20, 0, &rc
, text
, lstrlenA(text
), dx
);
215 ok( ret
, "ExtTextOutA error %d\n", GetLastError());
217 hFont
= SelectObject(hdcMetafile
, hFont
);
218 ret
= DeleteObject(hFont
);
219 ok( ret
, "DeleteObject error %d\n", GetLastError());
221 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
222 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
224 ok(!GetObjectType(hdcMetafile
), "CloseEnhMetaFile has to destroy metafile hdc\n");
226 ret
= PlayEnhMetaFile(hdcDisplay
, hMetafile
, &rc
);
227 ok( ret
, "PlayEnhMetaFile error %d\n", GetLastError());
229 SetTextAlign(hdcDisplay
, TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
);
230 SetBkColor(hdcDisplay
, RGB(0xff, 0, 0));
231 SetTextColor(hdcDisplay
, RGB(0, 0xff, 0));
232 SetROP2(hdcDisplay
, R2_NOT
);
233 SetArcDirection(hdcDisplay
, AD_CLOCKWISE
);
234 SetPolyFillMode(hdcDisplay
, WINDING
);
235 SetStretchBltMode(hdcDisplay
, HALFTONE
);
237 if(pSetRelAbs
) pSetRelAbs(hdcDisplay
, RELATIVE
);
238 SetBkMode(hdcDisplay
, OPAQUE
);
240 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, &rc
);
241 ok( ret
, "EnumEnhMetaFile error %d\n", GetLastError());
243 ok( GetTextAlign(hdcDisplay
) == (TA_UPDATECP
| TA_CENTER
| TA_BASELINE
| TA_RTLREADING
),
244 "text align %08x\n", GetTextAlign(hdcDisplay
));
245 ok( GetBkColor(hdcDisplay
) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay
));
246 ok( GetTextColor(hdcDisplay
) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay
));
247 ok( GetROP2(hdcDisplay
) == R2_NOT
, "rop2 %d\n", GetROP2(hdcDisplay
));
248 ok( GetArcDirection(hdcDisplay
) == AD_CLOCKWISE
, "arc dir %d\n", GetArcDirection(hdcDisplay
));
249 ok( GetPolyFillMode(hdcDisplay
) == WINDING
, "poly fill %d\n", GetPolyFillMode(hdcDisplay
));
250 ok( GetStretchBltMode(hdcDisplay
) == HALFTONE
, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay
));
252 ok(emr_processed
, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
254 ok(!EnumEnhMetaFile(hdcDisplay
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
255 "A valid hdc has to require a valid rc\n");
257 ok(EnumEnhMetaFile(NULL
, hMetafile
, eto_emf_enum_proc
, dx
, NULL
),
258 "A null hdc does not require a valid rc\n");
260 ret
= DeleteEnhMetaFile(hMetafile
);
261 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
262 ret
= ReleaseDC(hwnd
, hdcDisplay
);
263 ok( ret
, "ReleaseDC error %d\n", GetLastError());
267 static void check_dc_state(HDC hdc
, int restore_no
,
268 int wnd_org_x
, int wnd_org_y
, int wnd_ext_x
, int wnd_ext_y
,
269 int vp_org_x
, int vp_org_y
, int vp_ext_x
, int vp_ext_y
)
273 POINT vp_org
, win_org
;
274 SIZE vp_size
, win_size
;
275 FLOAT xscale
, yscale
, edx
, edy
;
277 SetLastError(0xdeadbeef);
278 ret
= GetWorldTransform(hdc
, &xform
);
279 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) goto win9x_here
;
280 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
282 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no
, xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
284 ok(xform
.eM12
== 0.0, "%d: expected eM12 0.0, got %f\n", restore_no
, xform
.eM12
);
285 ok(xform
.eM21
== 0.0, "%d: expected eM21 0.0, got %f\n", restore_no
, xform
.eM21
);
287 xscale
= (FLOAT
)vp_ext_x
/ (FLOAT
)wnd_ext_x
;
288 trace("x scale %f\n", xscale
);
289 ok(fabs(xscale
- xform
.eM11
) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
290 restore_no
, vp_ext_x
, wnd_ext_x
, xform
.eM11
);
292 yscale
= (FLOAT
)vp_ext_y
/ (FLOAT
)wnd_ext_y
;
293 trace("y scale %f\n", yscale
);
294 ok(fabs(yscale
- xform
.eM22
) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
295 restore_no
, vp_ext_y
, wnd_ext_y
, xform
.eM22
);
297 edx
= (FLOAT
)vp_org_x
- xform
.eM11
* (FLOAT
)wnd_org_x
;
298 ok(fabs(edx
- xform
.eDx
) < 0.01, "%d: edx %f != eDx %f\n", restore_no
, edx
, xform
.eDx
);
299 edy
= (FLOAT
)vp_org_y
- xform
.eM22
* (FLOAT
)wnd_org_y
;
300 ok(fabs(edy
- xform
.eDy
) < 0.01, "%d: edy %f != eDy %f\n", restore_no
, edy
, xform
.eDy
);
306 GetWindowOrgEx(hdc
, &win_org
);
307 GetViewportOrgEx(hdc
, &vp_org
);
308 GetWindowExtEx(hdc
, &win_size
);
309 GetViewportExtEx(hdc
, &vp_size
);
311 ok(wnd_org_x
== win_org
.x
, "%d: wnd_org_x: %d != %d\n", restore_no
, wnd_org_x
, win_org
.x
);
312 ok(wnd_org_y
== win_org
.y
, "%d: wnd_org_y: %d != %d\n", restore_no
, wnd_org_y
, win_org
.y
);
314 ok(vp_org_x
== vp_org
.x
, "%d: vport_org_x: %d != %d\n", restore_no
, vp_org_x
, vp_org
.x
);
315 ok(vp_org_y
== vp_org
.y
, "%d: vport_org_y: %d != %d\n", restore_no
, vp_org_y
, vp_org
.y
);
317 ok(wnd_ext_x
== win_size
.cx
, "%d: wnd_ext_x: %d != %d\n", restore_no
, wnd_ext_x
, win_size
.cx
);
318 ok(wnd_ext_y
== win_size
.cy
, "%d: wnd_ext_y: %d != %d\n", restore_no
, wnd_ext_y
, win_size
.cy
);
320 ok(vp_ext_x
== vp_size
.cx
, "%d: vport_ext_x: %d != %d\n", restore_no
, vp_ext_x
, vp_size
.cx
);
321 ok(vp_ext_y
== vp_size
.cy
, "%d: vport_ext_y: %d != %d\n", restore_no
, vp_ext_y
, vp_size
.cy
);
324 static int CALLBACK
savedc_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
325 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
331 static int save_state
;
332 static int restore_no
;
333 static int select_no
;
335 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
336 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
339 SetLastError(0xdeadbeef);
340 ret
= GetWorldTransform(hdc
, &xform
);
341 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
343 ok(GetWindowOrgEx(hdc
, &pt
), "GetWindowOrgEx error %u\n", GetLastError());
344 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
345 ok(GetViewportOrgEx(hdc
, &pt
), "GetViewportOrgEx error %u\n", GetLastError());
346 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
347 ok(GetWindowExtEx(hdc
, &size
), "GetWindowExtEx error %u\n", GetLastError());
348 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
349 ok(GetViewportExtEx(hdc
, &size
), "GetViewportExtEx error %u\n", GetLastError());
350 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
354 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
355 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
358 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
364 static RECT exp_bounds
= { 0, 0, 150, 150 };
366 const ENHMETAHEADER
*emf
= (const ENHMETAHEADER
*)emr
;
368 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
369 emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
,
370 emf
->rclFrame
.left
, emf
->rclFrame
.top
, emf
->rclFrame
.right
, emf
->rclFrame
.bottom
);
371 trace("mm %d x %d, device %d x %d\n", emf
->szlMillimeters
.cx
, emf
->szlMillimeters
.cy
,
372 emf
->szlDevice
.cx
, emf
->szlDevice
.cy
);
374 SetRect(&bounds
, emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
);
375 ok(EqualRect(&bounds
, &exp_bounds
), "wrong bounds\n");
380 check_dc_state(hdc
, restore_no
, 0, 0, 1, 1, 0, 0, 1, 1);
386 const EMRLINETO
*line
= (const EMRLINETO
*)emr
;
387 trace("EMR_LINETO %d,%d\n", line
->ptl
.x
, line
->ptl
.x
);
390 case EMR_SETWINDOWORGEX
:
392 const EMRSETWINDOWORGEX
*org
= (const EMRSETWINDOWORGEX
*)emr
;
393 trace("EMR_SETWINDOWORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
396 case EMR_SETWINDOWEXTEX
:
398 const EMRSETWINDOWEXTEX
*ext
= (const EMRSETWINDOWEXTEX
*)emr
;
399 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
402 case EMR_SETVIEWPORTORGEX
:
404 const EMRSETVIEWPORTORGEX
*org
= (const EMRSETVIEWPORTORGEX
*)emr
;
405 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
408 case EMR_SETVIEWPORTEXTEX
:
410 const EMRSETVIEWPORTEXTEX
*ext
= (const EMRSETVIEWPORTEXTEX
*)emr
;
411 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
416 trace("EMR_SAVEDC\n");
421 const EMRRESTOREDC
*restoredc
= (const EMRRESTOREDC
*)emr
;
422 trace("EMR_RESTOREDC: %d\n", restoredc
->iRelative
);
427 ok(restoredc
->iRelative
== -1, "first restore %d\n", restoredc
->iRelative
);
428 check_dc_state(hdc
, restore_no
, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
431 ok(restoredc
->iRelative
== -3, "second restore %d\n", restoredc
->iRelative
);
432 check_dc_state(hdc
, restore_no
, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
435 ok(restoredc
->iRelative
== -2, "third restore %d\n", restoredc
->iRelative
);
436 check_dc_state(hdc
, restore_no
, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
439 ok(restore_no
<= 3, "restore_no %d\n", restore_no
);
440 save_state
+= restoredc
->iRelative
;
443 case EMR_SELECTOBJECT
:
445 const EMRSELECTOBJECT
*selectobj
= (const EMRSELECTOBJECT
*)emr
;
446 trace("EMR_SELECTOBJECT: %x\n",selectobj
->ihObject
);
451 ok(save_state
== 0, "EOF save_state %d\n", save_state
);
452 ok(select_no
== 3, "Too many/few selects %i\n",select_no
);
457 SetLastError(0xdeadbeef);
458 ret
= GetWorldTransform(hdc
, &xform
);
459 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
461 ok(GetWindowOrgEx(hdc
, &pt
), "GetWindowOrgEx error %u\n", GetLastError());
462 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
463 ok(GetViewportOrgEx(hdc
, &pt
), "GetViewportOrgEx error %u\n", GetLastError());
464 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
465 ok(GetWindowExtEx(hdc
, &size
), "GetWindowExtEx error %u\n", GetLastError());
466 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
467 ok(GetViewportExtEx(hdc
, &size
), "GetViewportExtEx error %u\n", GetLastError());
468 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
472 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
473 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
479 static void test_SaveDC(void)
481 HDC hdcMetafile
, hdcDisplay
;
482 HENHMETAFILE hMetafile
;
487 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
488 static const RECT rc
= { 0, 0, 150, 150 };
490 /* Win9x doesn't play EMFs on invisible windows */
491 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
492 0, 0, 200, 200, 0, 0, 0, NULL
);
493 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
495 hdcDisplay
= GetDC(hwnd
);
496 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
498 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
499 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
501 SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
503 /* Need to write something to the emf, otherwise Windows won't play it back */
504 LineTo(hdcMetafile
, 150, 150);
506 SetWindowOrgEx(hdcMetafile
, 0, 0, NULL
);
507 SetViewportOrgEx(hdcMetafile
, 0, 0, NULL
);
508 SetWindowExtEx(hdcMetafile
, 110, 110, NULL
);
509 SetViewportExtEx(hdcMetafile
, 120, 120, NULL
);
511 /* Force Win9x to update DC state */
512 SetPixelV(hdcMetafile
, 50, 50, 0);
514 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
515 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
516 ret
= GetViewportExtEx(hdcMetafile
, &size
);
517 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
518 ret
= SaveDC(hdcMetafile
);
519 ok(ret
== 1, "ret = %d\n", ret
);
521 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
522 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
523 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
524 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
526 /* Force Win9x to update DC state */
527 SetPixelV(hdcMetafile
, 50, 50, 0);
529 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
530 ok(pt
.x
== 10,"Expecting ViewportOrg x of 10, got %i\n",pt
.x
);
531 ret
= GetViewportExtEx(hdcMetafile
, &size
);
532 ok(size
.cx
== 200,"Expecting ViewportExt cx of 200, got %i\n",size
.cx
);
533 ret
= SaveDC(hdcMetafile
);
534 ok(ret
== 2, "ret = %d\n", ret
);
536 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
537 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
538 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
539 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
540 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
541 SetBkColor( hdcMetafile
, 0 );
543 /* Force Win9x to update DC state */
544 SetPixelV(hdcMetafile
, 50, 50, 0);
546 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
547 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
548 ret
= GetViewportExtEx(hdcMetafile
, &size
);
549 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
550 ret
= SaveDC(hdcMetafile
);
551 ok(ret
== 3, "ret = %d\n", ret
);
553 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
554 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
555 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
556 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
558 SetPolyFillMode( hdcMetafile
, WINDING
);
559 SetBkColor( hdcMetafile
, 0x123456 );
560 ok( GetPolyFillMode( hdcMetafile
) == WINDING
, "PolyFillMode not restored\n" );
561 ok( GetBkColor( hdcMetafile
) == 0x123456, "Background color not restored\n" );
563 /* Force Win9x to update DC state */
564 SetPixelV(hdcMetafile
, 50, 50, 0);
566 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
567 ok(pt
.x
== 30,"Expecting ViewportOrg x of 30, got %i\n",pt
.x
);
568 ret
= GetViewportExtEx(hdcMetafile
, &size
);
569 ok(size
.cx
== 400,"Expecting ViewportExt cx of 400, got %i\n",size
.cx
);
570 ret
= RestoreDC(hdcMetafile
, -1);
571 ok(ret
, "ret = %d\n", ret
);
573 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
574 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
575 ret
= GetViewportExtEx(hdcMetafile
, &size
);
576 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
577 ok( GetPolyFillMode( hdcMetafile
) == ALTERNATE
, "PolyFillMode not restored\n" );
578 ok( GetBkColor( hdcMetafile
) == 0, "Background color not restored\n" );
579 ret
= SaveDC(hdcMetafile
);
580 ok(ret
== 3, "ret = %d\n", ret
);
582 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
583 ok(pt
.x
== 20,"Expecting ViewportOrg x of 20, got %i\n",pt
.x
);
584 ret
= GetViewportExtEx(hdcMetafile
, &size
);
585 ok(size
.cx
== 300,"Expecting ViewportExt cx of 300, got %i\n",size
.cx
);
586 ret
= RestoreDC(hdcMetafile
, 1);
587 ok(ret
, "ret = %d\n", ret
);
588 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
589 ok(pt
.x
== 0,"Expecting ViewportOrg x of 0, got %i\n",pt
.x
);
590 ret
= GetViewportExtEx(hdcMetafile
, &size
);
591 ok(size
.cx
== 120,"Expecting ViewportExt cx of 120, got %i\n",size
.cx
);
593 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
594 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
595 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
596 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
598 /* Force Win9x to update DC state */
599 SetPixelV(hdcMetafile
, 50, 50, 0);
601 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
602 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
603 ret
= GetViewportExtEx(hdcMetafile
, &size
);
604 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
605 ret
= SaveDC(hdcMetafile
);
606 ok(ret
== 1, "ret = %d\n", ret
);
608 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
609 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
610 ret
= GetViewportExtEx(hdcMetafile
, &size
);
611 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
612 ret
= SaveDC(hdcMetafile
);
613 ok(ret
== 2, "ret = %d\n", ret
);
615 memset(&orig_lf
, 0, sizeof(orig_lf
));
616 orig_lf
.lfCharSet
= ANSI_CHARSET
;
617 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
618 orig_lf
.lfWeight
= FW_DONTCARE
;
619 orig_lf
.lfHeight
= 7;
620 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
621 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
622 hFont
= CreateFontIndirectA(&orig_lf
);
623 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
625 hFontOld
= SelectObject(hdcMetafile
, hFont
);
627 hFont2
= CreateFontIndirectA(&orig_lf
);
628 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
629 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
630 ok(hFontCheck
== hFont
, "Font not selected\n");
632 /* Force Win9x to update DC state */
633 SetPixelV(hdcMetafile
, 50, 50, 0);
635 ret
= RestoreDC(hdcMetafile
, 1);
636 ok(ret
, "ret = %d\n", ret
);
637 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
638 ok(pt
.x
== 40,"Expecting ViewportOrg x of 40, got %i\n",pt
.x
);
639 ret
= GetViewportExtEx(hdcMetafile
, &size
);
640 ok(size
.cx
== 50,"Expecting ViewportExt cx of 50, got %i\n",size
.cx
);
642 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
643 ok(hFontOld
== hFontCheck
&& hFontCheck
!= hFont
&& hFontCheck
!= hFont2
,
644 "Font not reverted with DC Restore\n");
646 ret
= RestoreDC(hdcMetafile
, -20);
647 ok(!ret
, "ret = %d\n", ret
);
648 ret
= RestoreDC(hdcMetafile
, 20);
649 ok(!ret
, "ret = %d\n", ret
);
651 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
652 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
654 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, savedc_emf_enum_proc
, 0, &rc
);
655 ok( ret
== 1, "EnumEnhMetaFile rets %d\n", ret
);
657 ret
= DeleteObject(hFont
);
658 ok( ret
, "DeleteObject error %d\n", GetLastError());
659 ret
= DeleteObject(hFont2
);
660 ok( ret
, "DeleteObject error %d\n", GetLastError());
661 ret
= DeleteEnhMetaFile(hMetafile
);
662 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
663 ret
= ReleaseDC(hwnd
, hdcDisplay
);
664 ok( ret
, "ReleaseDC error %d\n", GetLastError());
668 static void test_mf_SaveDC(void)
675 HFONT hFont
,hFont2
,hFontOld
,hFontCheck
;
677 hdcMetafile
= CreateMetaFileA(NULL
);
678 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
680 ret
= SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
681 ok (ret
, "SetMapMode should not fail\n");
683 /* Need to write something to the emf, otherwise Windows won't play it back */
684 LineTo(hdcMetafile
, 150, 150);
686 SetWindowOrgEx(hdcMetafile
, 0, 0, NULL
);
687 SetViewportOrgEx(hdcMetafile
, 0, 0, NULL
);
688 SetWindowExtEx(hdcMetafile
, 110, 110, NULL
);
689 SetViewportExtEx(hdcMetafile
, 120, 120, NULL
);
691 /* Force Win9x to update DC state */
692 SetPixelV(hdcMetafile
, 50, 50, 0);
694 ret
= GetViewportOrgEx(hdcMetafile
, &pt
);
695 todo_wine
ok (!ret
, "GetViewportOrgEx should fail\n");
696 ret
= GetViewportExtEx(hdcMetafile
, &size
);
697 todo_wine
ok (!ret
, "GetViewportExtEx should fail\n");
698 ret
= SaveDC(hdcMetafile
);
699 ok(ret
== 1, "ret = %d\n", ret
);
701 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
702 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
703 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
704 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
706 /* Force Win9x to update DC state */
707 SetPixelV(hdcMetafile
, 50, 50, 0);
709 ret
= SaveDC(hdcMetafile
);
710 ok(ret
== 1, "ret = %d\n", ret
);
712 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
713 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
714 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
715 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
717 /* Force Win9x to update DC state */
718 SetPixelV(hdcMetafile
, 50, 50, 0);
719 SetPolyFillMode( hdcMetafile
, ALTERNATE
);
720 SetBkColor( hdcMetafile
, 0 );
722 ret
= SaveDC(hdcMetafile
);
723 ok(ret
== 1, "ret = %d\n", ret
);
725 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
726 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
727 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
728 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
730 SetPolyFillMode( hdcMetafile
, WINDING
);
731 SetBkColor( hdcMetafile
, 0x123456 );
732 todo_wine
ok( !GetPolyFillMode( hdcMetafile
), "GetPolyFillMode succeeded\n" );
733 todo_wine
ok( GetBkColor( hdcMetafile
) == CLR_INVALID
, "GetBkColor succeeded\n" );
735 /* Force Win9x to update DC state */
736 SetPixelV(hdcMetafile
, 50, 50, 0);
738 ret
= RestoreDC(hdcMetafile
, -1);
739 ok(ret
, "ret = %d\n", ret
);
741 ret
= SaveDC(hdcMetafile
);
742 ok(ret
== 1, "ret = %d\n", ret
);
744 ret
= RestoreDC(hdcMetafile
, 1);
745 ok(ret
, "ret = %d\n", ret
);
747 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
748 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
749 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
750 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
752 /* Force Win9x to update DC state */
753 SetPixelV(hdcMetafile
, 50, 50, 0);
755 ret
= SaveDC(hdcMetafile
);
756 ok(ret
== 1, "ret = %d\n", ret
);
758 ret
= SaveDC(hdcMetafile
);
759 ok(ret
== 1, "ret = %d\n", ret
);
761 memset(&orig_lf
, 0, sizeof(orig_lf
));
762 orig_lf
.lfCharSet
= ANSI_CHARSET
;
763 orig_lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
764 orig_lf
.lfWeight
= FW_DONTCARE
;
765 orig_lf
.lfHeight
= 7;
766 orig_lf
.lfQuality
= DEFAULT_QUALITY
;
767 lstrcpyA(orig_lf
.lfFaceName
, "Arial");
768 hFont
= CreateFontIndirectA(&orig_lf
);
769 ok(hFont
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
771 hFontOld
= SelectObject(hdcMetafile
, hFont
);
773 hFont2
= CreateFontIndirectA(&orig_lf
);
774 ok(hFont2
!= 0, "CreateFontIndirectA error %d\n", GetLastError());
775 hFontCheck
= SelectObject(hdcMetafile
, hFont2
);
776 ok(hFontCheck
== hFont
, "Font not selected\n");
778 /* Force Win9x to update DC state */
779 SetPixelV(hdcMetafile
, 50, 50, 0);
781 ret
= RestoreDC(hdcMetafile
, 1);
782 ok(ret
, "ret = %d\n", ret
);
784 hFontCheck
= SelectObject(hdcMetafile
, hFontOld
);
785 ok(hFontOld
!= hFontCheck
&& hFontCheck
== hFont2
, "Font incorrectly reverted with DC Restore\n");
787 /* restore level is ignored */
788 ret
= RestoreDC(hdcMetafile
, -20);
789 ok(ret
, "ret = %d\n", ret
);
790 ret
= RestoreDC(hdcMetafile
, 20);
791 ok(ret
, "ret = %d\n", ret
);
792 ret
= RestoreDC(hdcMetafile
, 0);
793 ok(ret
, "ret = %d\n", ret
);
795 hMetafile
= CloseMetaFile(hdcMetafile
);
796 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
798 ret
= DeleteMetaFile(hMetafile
);
799 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
800 ret
= DeleteObject(hFont
);
801 ok( ret
, "DeleteObject error %d\n", GetLastError());
802 ret
= DeleteObject(hFont2
);
803 ok( ret
, "DeleteObject error %d\n", GetLastError());
807 /* Win-format metafile (mfdrv) tests */
808 /* These tests compare the generated metafiles byte-by-byte */
809 /* with the nominal results. */
811 /* Maximum size of sample metafiles in bytes. */
812 #define MF_BUFSIZE 512
814 /* 8x8 bitmap data for a pattern brush */
815 static const unsigned char SAMPLE_PATTERN_BRUSH
[] = {
816 0x01, 0x00, 0x02, 0x00,
817 0x03, 0x00, 0x04, 0x00,
818 0x05, 0x00, 0x06, 0x00,
819 0x07, 0x00, 0x08, 0x00
822 /* Sample metafiles to be compared to the outputs of the
826 static const unsigned char MF_BLANK_BITS
[] = {
827 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
832 static const unsigned char MF_GRAPHICS_BITS
[] = {
833 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
836 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
837 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
838 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
839 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
840 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
841 0x00, 0x00, 0x00, 0x00
844 static const unsigned char MF_PATTERN_BRUSH_BITS
[] = {
845 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
846 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
848 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
849 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
850 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
854 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
855 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
856 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
857 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
858 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
859 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
863 static const unsigned char MF_TEXTOUT_ON_PATH_BITS
[] =
865 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
868 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
869 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
870 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
874 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS
[] =
876 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
881 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
882 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
883 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
886 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
889 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
890 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
891 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
893 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
894 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
895 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
896 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
899 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
900 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
901 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
902 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
903 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
904 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
906 0x14, 0x00, 0x00, 0x00
909 static const unsigned char MF_LINETO_BITS
[] = {
910 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
911 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
913 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
917 static const unsigned char EMF_LINETO_BITS
[] = {
918 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
923 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
924 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
925 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
928 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
930 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
931 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
932 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
933 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
934 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
935 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
936 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
937 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
938 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
939 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
941 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
942 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
943 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
944 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
945 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
946 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
947 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
948 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
949 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
950 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
951 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
952 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
953 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
955 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
959 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS
[] = {
960 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
965 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
966 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
967 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
970 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
972 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
973 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
974 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
975 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
976 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
977 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
978 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
979 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
981 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
983 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
984 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
985 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
986 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
987 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
988 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
989 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
990 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
991 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
992 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
993 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
994 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
995 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
997 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
998 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1001 static const unsigned char EMF_LINETO_MM_TEXT_BITS
[] = {
1002 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1007 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1008 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1009 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1012 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1015 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1016 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1017 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1018 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1019 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1020 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1021 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1022 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1023 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1025 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1026 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1028 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1030 0x14, 0x00, 0x00, 0x00
1033 static const unsigned char EMF_BITBLT
[] =
1035 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1037 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1038 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1039 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1040 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1041 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1042 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1044 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1045 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1048 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1049 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1050 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1051 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1053 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1056 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1058 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1059 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1060 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1061 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1062 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1063 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1065 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1069 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1071 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1072 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1073 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1074 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1076 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1077 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1084 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1085 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1086 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1090 /* For debugging or dumping the raw metafiles produced by
1091 * new test functions.
1093 static INT CALLBACK
mf_enum_proc(HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
,
1094 INT nobj
, LPARAM param
)
1096 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1097 hdc
, mr
->rdFunction
, mr
->rdSize
, (void *)param
);
1101 /* For debugging or dumping the raw metafiles produced by
1102 * new test functions.
1105 static void dump_mf_bits (const HMETAFILE mf
, const char *desc
)
1107 BYTE buf
[MF_BUFSIZE
];
1110 if (!winetest_debug
) return;
1112 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1113 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1115 printf ("MetaFile %s has bits:\n{\n ", desc
);
1116 for (i
=0; i
<mfsize
; i
++)
1118 printf ("0x%02x", buf
[i
]);
1121 else if (i
% 8 == 7)
1129 /* Compare the metafile produced by a test function with the
1130 * expected raw metafile data in "bits".
1131 * Return value is 0 for a perfect match,
1132 * -1 if lengths aren't equal,
1133 * otherwise returns the number of non-matching bytes.
1136 static int compare_mf_bits (const HMETAFILE mf
, const unsigned char *bits
, UINT bsize
,
1139 unsigned char buf
[MF_BUFSIZE
];
1143 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
1144 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
1145 if (mfsize
< MF_BUFSIZE
)
1146 ok (mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n",
1147 desc
, mfsize
, bsize
);
1149 ok (bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1150 desc
, mfsize
, bsize
);
1151 if (mfsize
!= bsize
)
1155 for (i
=0; i
<bsize
; i
++)
1157 if (buf
[i
] != bits
[i
])
1160 ok (diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1161 desc
, mfsize
, bsize
, diff
);
1166 static int compare_mf_disk_bits(LPCSTR name
, const BYTE
*bits
, UINT bsize
, const char *desc
)
1168 unsigned char buf
[MF_BUFSIZE
];
1169 DWORD mfsize
, rd_size
, i
;
1174 hfile
= CreateFileA(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
1175 assert(hfile
!= INVALID_HANDLE_VALUE
);
1177 mfsize
= GetFileSize(hfile
, NULL
);
1178 assert(mfsize
<= MF_BUFSIZE
);
1180 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &rd_size
, NULL
);
1181 ok( ret
&& rd_size
== mfsize
, "ReadFile: error %d\n", GetLastError());
1185 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n", desc
, mfsize
, bsize
);
1187 if (mfsize
!= bsize
)
1191 for (i
=0; i
<bsize
; i
++)
1193 if (buf
[i
] != bits
[i
])
1196 ok(diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1197 desc
, mfsize
, bsize
, diff
);
1202 /* For debugging or dumping the raw EMFs produced by
1203 * new test functions.
1205 static void dump_emf_bits(const HENHMETAFILE mf
, const char *desc
)
1207 BYTE buf
[MF_BUFSIZE
];
1210 if (!winetest_debug
) return;
1212 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1213 ok (mfsize
> 0, "%s: GetEnhMetaFileBits failed\n", desc
);
1215 printf("EMF %s has bits:\n{\n ", desc
);
1216 for (i
= 0; i
< mfsize
; i
++)
1218 printf ("0x%02x", buf
[i
]);
1221 else if (i
% 8 == 7)
1229 static void dump_emf_records(const HENHMETAFILE mf
, const char *desc
)
1232 BYTE buf
[MF_BUFSIZE
];
1233 UINT mfsize
, offset
;
1235 if (!winetest_debug
) return;
1237 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1238 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1240 printf("EMF %s has records:\n", desc
);
1244 while(offset
< mfsize
)
1246 EMR
*emr
= (EMR
*)(emf
+ offset
);
1247 printf("emr->iType %d, emr->nSize %u\n", emr
->iType
, emr
->nSize
);
1248 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1249 offset
+= emr
->nSize
;
1253 static void dump_emf_record(const ENHMETARECORD
*emr
, const char *desc
)
1258 if (!winetest_debug
) return;
1260 printf ("%s: EMF record %u has bits:\n{\n", desc
, emr
->iType
);
1261 buf
= (const BYTE
*)emr
;
1262 for (i
= 0; i
< emr
->nSize
; i
++)
1264 printf ("0x%02x", buf
[i
]);
1265 if (i
== emr
->nSize
- 1)
1267 else if (i
% 8 == 7)
1275 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW
*eto
)
1277 trace("rclBounds %d,%d - %d,%d\n", eto
->rclBounds
.left
, eto
->rclBounds
.top
,
1278 eto
->rclBounds
.right
, eto
->rclBounds
.bottom
);
1279 trace("iGraphicsMode %u\n", eto
->iGraphicsMode
);
1280 trace("exScale: %f\n", eto
->exScale
);
1281 trace("eyScale: %f\n", eto
->eyScale
);
1282 trace("emrtext.ptlReference %d,%d\n", eto
->emrtext
.ptlReference
.x
, eto
->emrtext
.ptlReference
.y
);
1283 trace("emrtext.nChars %u\n", eto
->emrtext
.nChars
);
1284 trace("emrtext.offString %#x\n", eto
->emrtext
.offString
);
1285 trace("emrtext.fOptions %#x\n", eto
->emrtext
.fOptions
);
1286 trace("emrtext.rcl %d,%d - %d,%d\n", eto
->emrtext
.rcl
.left
, eto
->emrtext
.rcl
.top
,
1287 eto
->emrtext
.rcl
.right
, eto
->emrtext
.rcl
.bottom
);
1288 trace("emrtext.offDx %#x\n", eto
->emrtext
.offDx
);
1291 static BOOL
match_emf_record(const ENHMETARECORD
*emr1
, const ENHMETARECORD
*emr2
,
1292 const char *desc
, BOOL ignore_scaling
)
1296 ok(emr1
->iType
== emr2
->iType
, "%s: emr->iType %u != %u\n",
1297 desc
, emr1
->iType
, emr2
->iType
);
1299 ok(emr1
->nSize
== emr2
->nSize
, "%s: emr->nSize %u != %u\n",
1300 desc
, emr1
->nSize
, emr2
->nSize
);
1302 /* iType and nSize mismatches are fatal */
1303 if (emr1
->iType
!= emr2
->iType
|| emr1
->nSize
!= emr2
->nSize
) return FALSE
;
1305 /* contents of EMR_GDICOMMENT are not interesting */
1306 if (emr1
->iType
== EMR_GDICOMMENT
) return TRUE
;
1308 /* different Windows versions setup DC scaling differently when
1309 * converting an old style metafile to an EMF.
1311 if (ignore_scaling
&& (emr1
->iType
== EMR_SETWINDOWEXTEX
||
1312 emr1
->iType
== EMR_SETVIEWPORTEXTEX
))
1315 if (emr1
->iType
== EMR_EXTTEXTOUTW
|| emr1
->iType
== EMR_EXTTEXTOUTA
)
1317 EMREXTTEXTOUTW
*eto1
, *eto2
;
1319 eto1
= HeapAlloc(GetProcessHeap(), 0, emr1
->nSize
);
1320 memcpy(eto1
, emr1
, emr1
->nSize
);
1321 eto2
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1322 memcpy(eto2
, emr2
, emr2
->nSize
);
1324 /* different Windows versions setup DC scaling differently */
1325 eto1
->exScale
= eto1
->eyScale
= 0.0;
1326 eto2
->exScale
= eto2
->eyScale
= 0.0;
1328 diff
= memcmp(eto1
, eto2
, emr1
->nSize
);
1331 dump_EMREXTTEXTOUT(eto1
);
1332 dump_EMREXTTEXTOUT(eto2
);
1334 HeapFree(GetProcessHeap(), 0, eto1
);
1335 HeapFree(GetProcessHeap(), 0, eto2
);
1337 else if (emr1
->iType
== EMR_EXTSELECTCLIPRGN
&& !lstrcmpA(desc
, "emf_clipping"))
1339 /* We have to take care of NT4 differences here */
1340 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1343 ENHMETARECORD
*emr_nt4
;
1345 emr_nt4
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1346 memcpy(emr_nt4
, emr2
, emr2
->nSize
);
1347 /* Correct the nRgnSize field */
1348 emr_nt4
->dParm
[5] = sizeof(RECT
);
1350 diff
= memcmp(emr1
, emr_nt4
, emr1
->nSize
);
1352 win_skip("Catered for NT4 differences\n");
1354 HeapFree(GetProcessHeap(), 0, emr_nt4
);
1358 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1360 ok(diff
== 0, "%s: contents of record %u don't match\n", desc
, emr1
->iType
);
1364 dump_emf_record(emr1
, "expected bits");
1365 dump_emf_record(emr2
, "actual bits");
1368 return diff
== 0; /* report all non-fatal record mismatches */
1371 /* Compare the EMF produced by a test function with the
1372 * expected raw EMF data in "bits".
1373 * Return value is 0 for a perfect match,
1374 * -1 if lengths aren't equal,
1375 * otherwise returns the number of non-matching bytes.
1377 static int compare_emf_bits(const HENHMETAFILE mf
, const unsigned char *bits
,
1378 UINT bsize
, const char *desc
,
1379 BOOL ignore_scaling
)
1381 unsigned char buf
[MF_BUFSIZE
];
1382 UINT mfsize
, offset1
, offset2
, diff_nt4
, diff_9x
;
1383 const ENHMETAHEADER
*emh1
, *emh2
;
1385 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1386 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1388 /* ENHMETAHEADER size could differ, depending on platform */
1389 diff_nt4
= sizeof(SIZEL
);
1390 diff_9x
= sizeof(SIZEL
) + 3 * sizeof(DWORD
);
1392 if (mfsize
< MF_BUFSIZE
)
1394 ok(mfsize
== bsize
||
1395 broken(mfsize
== bsize
- diff_nt4
) || /* NT4 */
1396 broken(mfsize
== bsize
- diff_9x
), /* Win9x/WinME */
1397 "%s: mfsize=%d, bsize=%d\n", desc
, mfsize
, bsize
);
1400 ok(bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1401 desc
, mfsize
, bsize
);
1403 /* basic things must match */
1404 emh1
= (const ENHMETAHEADER
*)bits
;
1405 emh2
= (const ENHMETAHEADER
*)buf
;
1406 ok(emh1
->iType
== EMR_HEADER
, "expected EMR_HEADER, got %u\n", emh1
->iType
);
1407 ok(emh1
->nSize
== sizeof(ENHMETAHEADER
), "expected sizeof(ENHMETAHEADER), got %u\n", emh1
->nSize
);
1408 ok(emh2
->nBytes
== mfsize
, "expected emh->nBytes %u, got %u\n", mfsize
, emh2
->nBytes
);
1409 ok(emh1
->dSignature
== ENHMETA_SIGNATURE
, "expected ENHMETA_SIGNATURE, got %u\n", emh1
->dSignature
);
1411 ok(emh1
->iType
== emh2
->iType
, "expected EMR_HEADER, got %u\n", emh2
->iType
);
1412 ok(emh1
->nSize
== emh2
->nSize
||
1413 broken(emh1
->nSize
- diff_nt4
== emh2
->nSize
) ||
1414 broken(emh1
->nSize
- diff_9x
== emh2
->nSize
),
1415 "expected nSize %u, got %u\n", emh1
->nSize
, emh2
->nSize
);
1416 ok(emh1
->dSignature
== emh2
->dSignature
, "expected dSignature %u, got %u\n", emh1
->dSignature
, emh2
->dSignature
);
1417 ok(emh1
->nBytes
== emh2
->nBytes
||
1418 broken(emh1
->nBytes
- diff_nt4
== emh2
->nBytes
) ||
1419 broken(emh1
->nBytes
- diff_9x
== emh2
->nBytes
),
1420 "expected nBytes %u, got %u\n", emh1
->nBytes
, emh2
->nBytes
);
1421 ok(emh1
->nRecords
== emh2
->nRecords
, "expected nRecords %u, got %u\n", emh1
->nRecords
, emh2
->nRecords
);
1423 offset1
= emh1
->nSize
;
1424 offset2
= emh2
->nSize
; /* Needed for Win9x/WinME/NT4 */
1425 while (offset1
< emh1
->nBytes
)
1427 const ENHMETARECORD
*emr1
= (const ENHMETARECORD
*)(bits
+ offset1
);
1428 const ENHMETARECORD
*emr2
= (const ENHMETARECORD
*)(buf
+ offset2
);
1430 skip("skipping match_emf_record(), bug 5392\n");
1431 // trace("%s: EMF record %u, size %u/record %u, size %u\n",
1432 // desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1434 // if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1436 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1437 desc
, emr1
->iType
, emr1
->nSize
, emr2
->iType
, emr2
->nSize
);
1439 if (!match_emf_record(emr1
, emr2
, desc
, ignore_scaling
)) return -1;
1441 /* We have already bailed out if iType or nSize don't match */
1442 offset1
+= emr1
->nSize
;
1443 offset2
+= emr2
->nSize
;
1449 /* tests blitting to an EMF */
1450 static void test_emf_BitBlt(void)
1452 HDC hdcDisplay
, hdcMetafile
, hdcBitmap
;
1453 HBITMAP hBitmap
, hOldBitmap
;
1454 HENHMETAFILE hMetafile
;
1456 BITMAPINFOHEADER bmih
=
1458 sizeof(BITMAPINFOHEADER
),
1459 BMP_DIM
,/* biWidth */
1460 BMP_DIM
,/* biHeight */
1462 24, /* biBitCount */
1463 BI_RGB
, /* biCompression */
1464 0, /* biXPelsPerMeter */
1465 0, /* biYPelsPerMeter */
1467 0, /* biClrImportant */
1472 hdcDisplay
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1473 ok( hdcDisplay
!= 0, "CreateDCA error %d\n", GetLastError() );
1475 hdcBitmap
= CreateCompatibleDC(hdcDisplay
);
1476 ok( hdcBitmap
!= 0, "CreateCompatibleDC failed\n" );
1477 bmih
.biXPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSX
), 100, 3937);
1478 bmih
.biYPelsPerMeter
= MulDiv(GetDeviceCaps(hdcDisplay
, LOGPIXELSY
), 100, 3937);
1479 hBitmap
= CreateDIBSection(hdcDisplay
, (const BITMAPINFO
*)&bmih
,
1480 DIB_RGB_COLORS
, &bits
, NULL
, 0);
1481 hOldBitmap
= SelectObject(hdcBitmap
, hBitmap
);
1483 hdcMetafile
= CreateEnhMetaFileA(hdcBitmap
, NULL
, NULL
, NULL
);
1484 ok( hdcMetafile
!= 0, "CreateEnhMetaFileA failed\n" );
1486 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1487 ret
= BitBlt(hdcBitmap
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, BLACKNESS
);
1488 ok( ret
, "BitBlt(BLACKNESS) failed\n" );
1490 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, hdcBitmap
, 0, 0, SRCCOPY
);
1491 ok( ret
, "BitBlt(SRCCOPY) failed\n" );
1492 ret
= BitBlt(hdcMetafile
, 0, 0, BMP_DIM
, BMP_DIM
, 0, 0, 0, WHITENESS
);
1493 ok( ret
, "BitBlt(WHITENESS) failed\n" );
1495 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1496 ok( hMetafile
!= 0, "CloseEnhMetaFile failed\n" );
1498 if(compare_emf_bits(hMetafile
, EMF_BITBLT
, sizeof(EMF_BITBLT
),
1499 "emf_BitBlt", FALSE
) != 0)
1501 dump_emf_bits(hMetafile
, "emf_BitBlt");
1502 dump_emf_records(hMetafile
, "emf_BitBlt");
1505 SelectObject(hdcBitmap
, hOldBitmap
);
1506 DeleteObject(hBitmap
);
1507 DeleteDC(hdcBitmap
);
1508 DeleteDC(hdcDisplay
);
1512 /* Test a blank metafile. May be used as a template for new tests. */
1514 static void test_mf_Blank(void)
1517 HMETAFILE hMetafile
;
1522 hdcMetafile
= CreateMetaFileA(NULL
);
1523 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1524 trace("hdcMetafile %p\n", hdcMetafile
);
1526 /* Tests on metafile initialization */
1527 caps
= GetDeviceCaps (hdcMetafile
, TECHNOLOGY
);
1528 ok (caps
== DT_METAFILE
,
1529 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps
);
1531 hMetafile
= CloseMetaFile(hdcMetafile
);
1532 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1533 type
= GetObjectType(hMetafile
);
1534 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1535 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1537 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1540 dump_mf_bits(hMetafile
, "mf_Blank");
1541 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1544 ret
= DeleteMetaFile(hMetafile
);
1545 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1548 static void test_CopyMetaFile(void)
1551 HMETAFILE hMetafile
, hmf_copy
;
1553 char temp_path
[MAX_PATH
];
1554 char mf_name
[MAX_PATH
];
1557 hdcMetafile
= CreateMetaFileA(NULL
);
1558 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1559 trace("hdcMetafile %p\n", hdcMetafile
);
1561 hMetafile
= CloseMetaFile(hdcMetafile
);
1562 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1563 type
= GetObjectType(hMetafile
);
1564 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1566 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1569 dump_mf_bits(hMetafile
, "mf_Blank");
1570 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1573 GetTempPathA(MAX_PATH
, temp_path
);
1574 GetTempFileNameA(temp_path
, "wmf", 0, mf_name
);
1576 hmf_copy
= CopyMetaFileA(hMetafile
, mf_name
);
1577 ok(hmf_copy
!= 0, "CopyMetaFile error %d\n", GetLastError());
1579 type
= GetObjectType(hmf_copy
);
1580 ok(type
== OBJ_METAFILE
, "CopyMetaFile created object with type %d\n", type
);
1582 ret
= DeleteMetaFile(hMetafile
);
1583 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1585 if (compare_mf_disk_bits(mf_name
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
), "mf_blank") != 0)
1587 dump_mf_bits(hmf_copy
, "mf_Blank");
1588 EnumMetaFile(0, hmf_copy
, mf_enum_proc
, 0);
1591 ret
= DeleteMetaFile(hmf_copy
);
1592 ok( ret
, "DeleteMetaFile(%p) error %d\n", hmf_copy
, GetLastError());
1594 DeleteFileA(mf_name
);
1597 static void test_SetMetaFileBits(void)
1605 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), MF_GRAPHICS_BITS
);
1606 trace("hmf %p\n", hmf
);
1607 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1608 type
= GetObjectType(hmf
);
1609 ok(type
== OBJ_METAFILE
, "SetMetaFileBitsEx created object with type %d\n", type
);
1611 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1613 dump_mf_bits(hmf
, "mf_Graphics");
1614 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1617 ret
= DeleteMetaFile(hmf
);
1618 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1620 /* NULL data crashes XP SP1 */
1621 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1623 /* Now with zero size */
1624 SetLastError(0xdeadbeef);
1625 hmf
= SetMetaFileBitsEx(0, MF_GRAPHICS_BITS
);
1626 trace("hmf %p\n", hmf
);
1627 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1628 ok(GetLastError() == ERROR_INVALID_DATA
||
1629 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
1630 "wrong error %d\n", GetLastError());
1632 /* Now with odd size */
1633 SetLastError(0xdeadbeef);
1634 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
) - 1, MF_GRAPHICS_BITS
);
1635 trace("hmf %p\n", hmf
);
1636 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1637 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1639 /* Now with zeroed out header fields */
1640 assert(sizeof(buf
) >= sizeof(MF_GRAPHICS_BITS
));
1641 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
1642 mh
= (METAHEADER
*)buf
;
1643 /* corruption of any of the below fields leads to a failure */
1646 mh
->mtHeaderSize
= 0;
1647 SetLastError(0xdeadbeef);
1648 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
1649 trace("hmf %p\n", hmf
);
1650 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1651 ok(GetLastError() == ERROR_INVALID_DATA
||
1652 broken(GetLastError() == ERROR_INVALID_PARAMETER
), /* Win9x */
1653 "wrong error %d\n", GetLastError());
1655 /* Now with corrupted mtSize field */
1656 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
1657 mh
= (METAHEADER
*)buf
;
1658 /* corruption of mtSize doesn't lead to a failure */
1660 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
1661 trace("hmf %p\n", hmf
);
1662 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1664 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1666 dump_mf_bits(hmf
, "mf_Graphics");
1667 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1670 ret
= DeleteMetaFile(hmf
);
1671 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1673 /* Now with zeroed out mtSize field */
1674 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
1675 mh
= (METAHEADER
*)buf
;
1676 /* zeroing mtSize doesn't lead to a failure */
1678 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
1679 trace("hmf %p\n", hmf
);
1680 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1682 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1684 dump_mf_bits(hmf
, "mf_Graphics");
1685 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1688 ret
= DeleteMetaFile(hmf
);
1689 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1692 /* Simple APIs from mfdrv/graphics.c
1695 static void test_mf_Graphics(void)
1698 HMETAFILE hMetafile
;
1702 hdcMetafile
= CreateMetaFileA(NULL
);
1703 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1704 trace("hdcMetafile %p\n", hdcMetafile
);
1706 ret
= MoveToEx(hdcMetafile
, 1, 1, NULL
);
1707 ok( ret
, "MoveToEx error %d.\n", GetLastError());
1708 ret
= LineTo(hdcMetafile
, 2, 2);
1709 ok( ret
, "LineTo error %d.\n", GetLastError());
1710 ret
= MoveToEx(hdcMetafile
, 1, 1, &oldpoint
);
1711 ok( ret
, "MoveToEx error %d.\n", GetLastError());
1713 /* oldpoint gets garbage under Win XP, so the following test would
1714 * work under Wine but fails under Windows:
1716 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1717 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1718 * oldpoint.x, oldpoint.y);
1721 ret
= Ellipse(hdcMetafile
, 0, 0, 2, 2);
1722 ok( ret
, "Ellipse error %d.\n", GetLastError());
1724 hMetafile
= CloseMetaFile(hdcMetafile
);
1725 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1726 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1728 if (compare_mf_bits (hMetafile
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
),
1729 "mf_Graphics") != 0)
1731 dump_mf_bits(hMetafile
, "mf_Graphics");
1732 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1735 ret
= DeleteMetaFile(hMetafile
);
1736 ok( ret
, "DeleteMetaFile(%p) error %d\n",
1737 hMetafile
, GetLastError());
1740 static void test_mf_PatternBrush(void)
1743 HMETAFILE hMetafile
;
1748 orig_lb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(LOGBRUSH
));
1750 orig_lb
->lbStyle
= BS_PATTERN
;
1751 orig_lb
->lbColor
= RGB(0, 0, 0);
1752 orig_lb
->lbHatch
= (ULONG_PTR
)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH
);
1753 ok((HBITMAP
)orig_lb
->lbHatch
!= NULL
, "CreateBitmap error %d.\n", GetLastError());
1755 hBrush
= CreateBrushIndirect (orig_lb
);
1756 ok(hBrush
!= 0, "CreateBrushIndirect error %d\n", GetLastError());
1758 hdcMetafile
= CreateMetaFileA(NULL
);
1759 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
1760 trace("hdcMetafile %p\n", hdcMetafile
);
1762 hBrush
= SelectObject(hdcMetafile
, hBrush
);
1763 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
1765 hMetafile
= CloseMetaFile(hdcMetafile
);
1766 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1767 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1769 if (compare_mf_bits (hMetafile
, MF_PATTERN_BRUSH_BITS
, sizeof(MF_PATTERN_BRUSH_BITS
),
1770 "mf_Pattern_Brush") != 0)
1772 dump_mf_bits(hMetafile
, "mf_Pattern_Brush");
1773 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1776 ret
= DeleteMetaFile(hMetafile
);
1777 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
1778 ret
= DeleteObject(hBrush
);
1779 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1780 ret
= DeleteObject((HBITMAP
)orig_lb
->lbHatch
);
1781 ok( ret
, "DeleteObject(HBITMAP) error %d\n",
1783 HeapFree (GetProcessHeap(), 0, orig_lb
);
1786 static void test_mf_ExtTextOut_on_path(void)
1789 HMETAFILE hMetafile
;
1791 static const INT dx
[4] = { 3, 5, 8, 12 };
1793 hdcMetafile
= CreateMetaFileA(NULL
);
1794 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1795 trace("hdcMetafile %p\n", hdcMetafile
);
1797 ret
= BeginPath(hdcMetafile
);
1798 ok(!ret
, "BeginPath on metafile DC should fail\n");
1800 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
1801 ok(ret
, "ExtTextOut error %d\n", GetLastError());
1803 ret
= EndPath(hdcMetafile
);
1804 ok(!ret
, "EndPath on metafile DC should fail\n");
1806 hMetafile
= CloseMetaFile(hdcMetafile
);
1807 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1809 if (compare_mf_bits(hMetafile
, MF_TEXTOUT_ON_PATH_BITS
, sizeof(MF_TEXTOUT_ON_PATH_BITS
),
1810 "mf_TextOut_on_path") != 0)
1812 dump_mf_bits(hMetafile
, "mf_TextOut_on_path");
1813 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1816 ret
= DeleteMetaFile(hMetafile
);
1817 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1820 static void test_emf_ExtTextOut_on_path(void)
1823 HDC hdcDisplay
, hdcMetafile
;
1824 HENHMETAFILE hMetafile
;
1826 static const INT dx
[4] = { 3, 5, 8, 12 };
1828 /* Win9x doesn't play EMFs on invisible windows */
1829 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
1830 0, 0, 200, 200, 0, 0, 0, NULL
);
1831 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
1833 hdcDisplay
= GetDC(hwnd
);
1834 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
1836 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
1837 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1839 ret
= BeginPath(hdcMetafile
);
1840 ok(ret
, "BeginPath error %d\n", GetLastError());
1842 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
1843 ok(ret
, "ExtTextOut error %d\n", GetLastError());
1845 ret
= EndPath(hdcMetafile
);
1846 ok(ret
, "EndPath error %d\n", GetLastError());
1848 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1849 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
1851 /* this doesn't succeed yet: EMF has correct size, all EMF records
1852 * are there, but their contents don't match for different reasons.
1854 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_ON_PATH_BITS
),
1855 "emf_TextOut_on_path", FALSE
) != 0)
1857 dump_emf_bits(hMetafile
, "emf_TextOut_on_path");
1858 dump_emf_records(hMetafile
, "emf_TextOut_on_path");
1861 ret
= DeleteEnhMetaFile(hMetafile
);
1862 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
1863 ret
= ReleaseDC(hwnd
, hdcDisplay
);
1864 ok(ret
, "ReleaseDC error %d\n", GetLastError());
1865 DestroyWindow(hwnd
);
1868 static const unsigned char EMF_CLIPPING
[] =
1870 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1871 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1872 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1874 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1875 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1876 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1877 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1879 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1880 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1883 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1884 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1885 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1886 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1887 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1888 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1889 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1890 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1891 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1892 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1893 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1894 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1895 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1898 static void translate( POINT
*pt
, UINT count
, const XFORM
*xform
)
1902 FLOAT x
= (FLOAT
)pt
->x
;
1903 FLOAT y
= (FLOAT
)pt
->y
;
1904 pt
->x
= (LONG
)floor( x
* xform
->eM11
+ y
* xform
->eM21
+ xform
->eDx
+ 0.5 );
1905 pt
->y
= (LONG
)floor( x
* xform
->eM12
+ y
* xform
->eM22
+ xform
->eDy
+ 0.5 );
1910 /* Compare rectangles allowing rounding errors */
1911 static BOOL
is_equal_rect(const RECT
*rc1
, const RECT
*rc2
)
1913 return abs(rc1
->left
- rc2
->left
) <= 1 &&
1914 abs(rc1
->top
- rc2
->top
) <= 1 &&
1915 abs(rc1
->right
- rc2
->right
) <= 1 &&
1916 abs(rc1
->bottom
- rc2
->bottom
) <= 1;
1919 static int CALLBACK
clip_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
1920 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
1922 if (emr
->iType
== EMR_EXTSELECTCLIPRGN
)
1924 const EMREXTSELECTCLIPRGN
*clip
= (const EMREXTSELECTCLIPRGN
*)emr
;
1928 char buf
[sizeof(RGNDATAHEADER
) + sizeof(RECT
)];
1930 const union _rgn
*rgn1
;
1932 RECT rect
, rc_transformed
;
1933 const RECT
*rc
= (const RECT
*)param
;
1939 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1940 clip
->cbRgnData
, clip
->iMode
);
1942 ok(clip
->iMode
== RGN_COPY
, "expected RGN_COPY, got %u\n", clip
->iMode
);
1943 ok(clip
->cbRgnData
>= sizeof(RGNDATAHEADER
) + sizeof(RECT
),
1944 "too small data block: %u bytes\n", clip
->cbRgnData
);
1945 if (clip
->cbRgnData
< sizeof(RGNDATAHEADER
) + sizeof(RECT
))
1948 rgn1
= (const union _rgn
*)clip
->RgnData
;
1950 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1951 rgn1
->data
.rdh
.dwSize
, rgn1
->data
.rdh
.iType
,
1952 rgn1
->data
.rdh
.nCount
, rgn1
->data
.rdh
.nRgnSize
,
1953 rgn1
->data
.rdh
.rcBound
.left
, rgn1
->data
.rdh
.rcBound
.top
,
1954 rgn1
->data
.rdh
.rcBound
.right
, rgn1
->data
.rdh
.rcBound
.bottom
);
1956 ok(EqualRect(&rgn1
->data
.rdh
.rcBound
, rc
), "rects don't match\n");
1958 rect
= *(const RECT
*)rgn1
->data
.Buffer
;
1959 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1960 ok(EqualRect(&rect
, rc
), "rects don't match\n");
1962 ok(rgn1
->data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn1
->data
.rdh
.dwSize
);
1963 ok(rgn1
->data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn1
->data
.rdh
.iType
);
1964 ok(rgn1
->data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn1
->data
.rdh
.nCount
);
1965 ok(rgn1
->data
.rdh
.nRgnSize
== sizeof(RECT
) ||
1966 broken(rgn1
->data
.rdh
.nRgnSize
== 168), /* NT4 */
1967 "expected sizeof(RECT), got %u\n", rgn1
->data
.rdh
.nRgnSize
);
1969 hrgn
= CreateRectRgn(0, 0, 0, 0);
1971 memset(&xform
, 0, sizeof(xform
));
1972 SetLastError(0xdeadbeef);
1973 ret
= GetWorldTransform(hdc
, &xform
);
1974 is_win9x
= !ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
;
1976 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
1978 trace("xform.eM11 %f, xform.eM22 %f\n", xform
.eM11
, xform
.eM22
);
1980 ret
= GetClipRgn(hdc
, hrgn
);
1981 ok(ret
== 0, "GetClipRgn returned %d, expected 0\n", ret
);
1983 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
1985 ret
= GetClipRgn(hdc
, hrgn
);
1986 ok(ret
== 1, "GetClipRgn returned %d, expected 1\n", ret
);
1988 /* Win9x returns empty clipping region */
1989 if (is_win9x
) return 1;
1991 ret
= GetRegionData(hrgn
, 0, NULL
);
1992 ok(ret
== sizeof(rgn2
.data
.rdh
) + sizeof(RECT
), "expected sizeof(rgn), got %u\n", ret
);
1994 ret
= GetRegionData(hrgn
, sizeof(rgn2
), &rgn2
.data
);
1996 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1997 rgn2
.data
.rdh
.dwSize
, rgn2
.data
.rdh
.iType
,
1998 rgn2
.data
.rdh
.nCount
, rgn2
.data
.rdh
.nRgnSize
,
1999 rgn2
.data
.rdh
.rcBound
.left
, rgn2
.data
.rdh
.rcBound
.top
,
2000 rgn2
.data
.rdh
.rcBound
.right
, rgn2
.data
.rdh
.rcBound
.bottom
);
2002 rect
= rgn2
.data
.rdh
.rcBound
;
2003 rc_transformed
= *rc
;
2004 translate((POINT
*)&rc_transformed
, 2, &xform
);
2005 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2006 rc_transformed
.right
, rc_transformed
.bottom
);
2007 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2009 rect
= *(const RECT
*)rgn2
.data
.Buffer
;
2010 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2011 rc_transformed
= *rc
;
2012 translate((POINT
*)&rc_transformed
, 2, &xform
);
2013 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
2014 rc_transformed
.right
, rc_transformed
.bottom
);
2015 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
2017 ok(rgn2
.data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn2
.data
.rdh
.dwSize
);
2018 ok(rgn2
.data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn2
.data
.rdh
.iType
);
2019 ok(rgn2
.data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn2
.data
.rdh
.nCount
);
2020 ok(rgn2
.data
.rdh
.nRgnSize
== sizeof(RECT
) ||
2021 broken(rgn2
.data
.rdh
.nRgnSize
== 168), /* NT4 */
2022 "expected sizeof(RECT), got %u\n", rgn2
.data
.rdh
.nRgnSize
);
2029 static void test_emf_clipping(void)
2031 static const RECT rc
= { 0, 0, 100, 100 };
2032 RECT rc_clip
= { 100, 100, 1024, 1024 };
2038 RECT rc_res
, rc_sclip
;
2040 SetLastError(0xdeadbeef);
2041 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2042 ok(hdc
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2044 /* Need to write something to the emf, otherwise Windows won't play it back */
2047 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
2048 ret
= SelectClipRgn(hdc
, hrgn
);
2049 ok(ret
== SIMPLEREGION
, "expected SIMPLEREGION, got %d\n", ret
);
2051 SetLastError(0xdeadbeef);
2052 hemf
= CloseEnhMetaFile(hdc
);
2053 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
2055 if (compare_emf_bits(hemf
, EMF_CLIPPING
, sizeof(EMF_CLIPPING
),
2056 "emf_clipping", FALSE
) != 0)
2058 dump_emf_bits(hemf
, "emf_clipping");
2059 dump_emf_records(hemf
, "emf_clipping");
2064 /* Win9x doesn't play EMFs on invisible windows */
2065 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
2066 0, 0, 200, 200, 0, 0, 0, NULL
);
2067 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
2071 ret
= EnumEnhMetaFile(hdc
, hemf
, clip_emf_enum_proc
, &rc_clip
, &rc
);
2072 ok(ret
, "EnumEnhMetaFile error %d\n", GetLastError());
2074 DeleteEnhMetaFile(hemf
);
2075 ReleaseDC(hwnd
, hdc
);
2076 DestroyWindow(hwnd
);
2078 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
2080 SetRect(&rc_sclip
, 100, 100, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
2081 hrgn
= CreateRectRgn(rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
);
2082 SelectClipRgn(hdc
, hrgn
);
2083 ret
= GetClipBox(hdc
, &rc_res
);
2085 ok(ret
== SIMPLEREGION
, "got %d\n", ret
);
2086 if(ret
== SIMPLEREGION
)
2087 ok(EqualRect(&rc_res
, &rc_sclip
),
2088 "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2089 rc_sclip
.left
, rc_sclip
.top
, rc_sclip
.right
, rc_sclip
.bottom
,
2090 rc_res
.left
, rc_res
.top
, rc_res
.right
, rc_res
.bottom
);
2092 hemf
= CloseEnhMetaFile(hdc
);
2093 DeleteEnhMetaFile(hemf
);
2098 static INT CALLBACK
EmfEnumProc(HDC hdc
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
, INT nObj
, LPARAM lpData
)
2100 LPMETAFILEPICT lpMFP
= (LPMETAFILEPICT
)lpData
;
2101 POINT mapping
[2] = { { 0, 0 }, { 10, 10 } };
2102 /* When using MM_TEXT Win9x does not update the mapping mode
2103 * until a record is played which actually outputs something */
2104 PlayEnhMetaFileRecord(hdc
, lpHTable
, lpEMFR
, nObj
);
2105 LPtoDP(hdc
, mapping
, 2);
2106 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2107 lpEMFR
->iType
, lpEMFR
->nSize
,
2108 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
);
2110 if (lpEMFR
->iType
== EMR_LINETO
)
2113 if (!lpMFP
|| lpMFP
->mm
== MM_TEXT
)
2117 x1
= (INT
)floor(10 * 100.0 / LINE_X
+ 0.5);
2118 y1
= (INT
)floor(10 * 100.0 / LINE_Y
+ 0.5);
2122 ok(lpMFP
->mm
== MM_ANISOTROPIC
, "mm=%d\n", lpMFP
->mm
);
2124 x0
= MulDiv(0, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2125 y0
= MulDiv(0, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2126 x1
= MulDiv(10, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
2127 y1
= MulDiv(10, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
2129 ok(mapping
[0].x
== x0
&& mapping
[0].y
== y0
&& mapping
[1].x
== x1
&& mapping
[1].y
== y1
,
2130 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2131 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
,
2137 static HENHMETAFILE
create_converted_emf(const METAFILEPICT
*mfp
)
2146 hdcMf
= CreateMetaFile(NULL
);
2147 ok(hdcMf
!= NULL
, "CreateMetaFile failed with error %d\n", GetLastError());
2148 ret
= LineTo(hdcMf
, (INT
)LINE_X
, (INT
)LINE_Y
);
2149 ok(ret
, "LineTo failed with error %d\n", GetLastError());
2150 hmf
= CloseMetaFile(hdcMf
);
2151 ok(hmf
!= NULL
, "CloseMetaFile failed with error %d\n", GetLastError());
2153 if (compare_mf_bits (hmf
, MF_LINETO_BITS
, sizeof(MF_LINETO_BITS
), "mf_LineTo") != 0)
2155 dump_mf_bits(hmf
, "mf_LineTo");
2156 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
2159 size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
2160 ok(size
, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2161 pBits
= HeapAlloc(GetProcessHeap(), 0, size
);
2162 GetMetaFileBitsEx(hmf
, size
, pBits
);
2163 DeleteMetaFile(hmf
);
2164 hemf
= SetWinMetaFileBits(size
, pBits
, NULL
, mfp
);
2165 HeapFree(GetProcessHeap(), 0, pBits
);
2169 static void test_mf_conversions(void)
2171 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2173 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2176 RECT rect
= { 0, 0, 100, 100 };
2177 mfp
.mm
= MM_ANISOTROPIC
;
2181 hemf
= create_converted_emf(&mfp
);
2183 if (compare_emf_bits(hemf
, EMF_LINETO_MM_ANISOTROPIC_BITS
, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS
),
2184 "emf_LineTo MM_ANISOTROPIC", TRUE
) != 0)
2186 dump_emf_bits(hemf
, "emf_LineTo MM_ANISOTROPIC");
2187 dump_emf_records(hemf
, "emf_LineTo MM_ANISOTROPIC");
2190 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2192 DeleteEnhMetaFile(hemf
);
2193 DeleteDC(hdcOffscreen
);
2196 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2198 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2201 RECT rect
= { 0, 0, 100, 100 };
2206 hemf
= create_converted_emf(&mfp
);
2208 if (compare_emf_bits(hemf
, EMF_LINETO_MM_TEXT_BITS
, sizeof(EMF_LINETO_MM_TEXT_BITS
),
2209 "emf_LineTo MM_TEXT", TRUE
) != 0)
2211 dump_emf_bits(hemf
, "emf_LineTo MM_TEXT");
2212 dump_emf_records(hemf
, "emf_LineTo MM_TEXT");
2215 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
2217 DeleteEnhMetaFile(hemf
);
2218 DeleteDC(hdcOffscreen
);
2221 trace("Testing MF->EMF conversion (NULL mfp)\n");
2223 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
2225 RECT rect
= { 0, 0, 100, 100 };
2226 hemf
= create_converted_emf(NULL
);
2228 if (compare_emf_bits(hemf
, EMF_LINETO_BITS
, sizeof(EMF_LINETO_BITS
),
2229 "emf_LineTo NULL", TRUE
) != 0)
2231 dump_emf_bits(hemf
, "emf_LineTo NULL");
2232 dump_emf_records(hemf
, "emf_LineTo NULL");
2235 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, NULL
, &rect
);
2237 DeleteEnhMetaFile(hemf
);
2238 DeleteDC(hdcOffscreen
);
2242 static BOOL
getConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
2243 LONG mm
, LONG xExt
, LONG yExt
,
2244 RECTL
* rclBounds
, RECTL
* rclFrame
)
2247 METAFILEPICT
* mfpPtr
= NULL
;
2249 ENHMETAHEADER header
;
2260 emf
= SetWinMetaFileBits(buffer_size
, buffer
, NULL
, mfpPtr
);
2261 ok(emf
!= NULL
, "SetWinMetaFileBits failed\n");
2262 if (!emf
) return FALSE
;
2263 res
= GetEnhMetaFileHeader(emf
, sizeof(header
), &header
);
2264 ok(res
!= 0, "GetEnhMetaHeader failed\n");
2265 DeleteEnhMetaFile(emf
);
2266 if (!res
) return FALSE
;
2268 *rclBounds
= header
.rclBounds
;
2269 *rclFrame
= header
.rclFrame
;
2273 static void checkConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
2274 LONG mm
, LONG xExt
, LONG yExt
,
2275 RECTL
* rclBoundsExpected
, RECTL
* rclFrameExpected
)
2277 RECTL rclBounds
, rclFrame
;
2279 if (getConvertedFrameAndBounds(buffer_size
, buffer
, mfpIsNull
, mm
, xExt
, yExt
, &rclBounds
, &rclFrame
))
2286 msg
= "mfp == NULL";
2290 const char * mm_str
;
2293 case MM_ANISOTROPIC
: mm_str
= "MM_ANISOTROPIC"; break;
2294 case MM_ISOTROPIC
: mm_str
= "MM_ISOTROPIC"; break;
2295 default: mm_str
= "Unexpected";
2297 sprintf(buf
, "mm=%s, xExt=%d, yExt=%d", mm_str
, xExt
, yExt
);
2301 ok(rclBounds
.left
== rclBoundsExpected
->left
, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected
->left
, rclBounds
.left
, msg
);
2302 ok(rclBounds
.top
== rclBoundsExpected
->top
, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected
->top
, rclBounds
.top
, msg
);
2303 ok(rclBounds
.right
== rclBoundsExpected
->right
, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected
->right
, rclBounds
.right
, msg
);
2304 ok(rclBounds
.bottom
== rclBoundsExpected
->bottom
, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected
->bottom
, rclBounds
.bottom
, msg
);
2305 ok(rclFrame
.left
== rclFrameExpected
->left
, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected
->left
, rclFrame
.left
, msg
);
2306 ok(rclFrame
.top
== rclFrameExpected
->top
, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected
->top
, rclFrame
.top
, msg
);
2307 ok(rclFrame
.right
== rclFrameExpected
->right
, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected
->right
, rclFrame
.right
, msg
);
2308 ok(rclFrame
.bottom
== rclFrameExpected
->bottom
, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected
->bottom
, rclFrame
.bottom
, msg
);
2312 static void test_SetWinMetaFileBits(void)
2320 RECTL rclBoundsAnisotropic
, rclFrameAnisotropic
;
2321 RECTL rclBoundsIsotropic
, rclFrameIsotropic
;
2322 RECTL rclBounds
, rclFrame
;
2326 wmfDC
= CreateMetaFile(NULL
);
2327 ok(wmfDC
!= NULL
, "CreateMetaFile failed\n");
2330 SetWindowExtEx(wmfDC
, 100, 100, NULL
);
2331 rect
.left
= rect
.top
= 0;
2332 rect
.right
= rect
.bottom
= 50;
2333 FillRect(wmfDC
, &rect
, GetStockObject(BLACK_BRUSH
));
2334 wmf
= CloseMetaFile(wmfDC
);
2335 ok(wmf
!= NULL
, "Metafile creation failed\n");
2338 buffer_size
= GetMetaFileBitsEx(wmf
, 0, NULL
);
2339 ok(buffer_size
!= 0, "GetMetaFileBitsEx failed\n");
2340 if (buffer_size
== 0)
2342 DeleteMetaFile(wmf
);
2346 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
);
2347 ok(buffer
!= NULL
, "HeapAlloc failed\n");
2350 DeleteMetaFile(wmf
);
2354 res
= GetMetaFileBitsEx(wmf
, buffer_size
, buffer
);
2355 ok(res
== buffer_size
, "GetMetaFileBitsEx failed\n");
2356 DeleteMetaFile(wmf
);
2357 if (res
!= buffer_size
)
2359 HeapFree(GetProcessHeap(), 0, buffer
);
2363 /* Get the reference bounds and frame */
2364 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2365 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2367 ok(rclBoundsAnisotropic
.left
== 0 && rclBoundsAnisotropic
.top
== 0 &&
2368 rclBoundsIsotropic
.left
== 0 && rclBoundsIsotropic
.top
== 0,
2369 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2371 ok(rclBoundsAnisotropic
.right
>= rclBoundsIsotropic
.right
, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2372 ok(rclBoundsAnisotropic
.bottom
>= rclBoundsIsotropic
.bottom
, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2373 diffx
= rclBoundsIsotropic
.right
- rclBoundsIsotropic
.bottom
;
2374 if (diffx
< 0) diffx
= -diffx
;
2375 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2377 dc
= CreateCompatibleDC(NULL
);
2379 /* Allow 1 mm difference (rounding errors) */
2380 diffx
= rclBoundsAnisotropic
.right
- GetDeviceCaps(dc
, HORZRES
) / 2;
2381 diffy
= rclBoundsAnisotropic
.bottom
- GetDeviceCaps(dc
, VERTRES
) / 2;
2382 if (diffx
< 0) diffx
= -diffx
;
2383 if (diffy
< 0) diffy
= -diffy
;
2386 ok(diffx
<= 1 && diffy
<= 1,
2387 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2388 GetDeviceCaps(dc
, HORZRES
) / 2, GetDeviceCaps(dc
, VERTRES
) / 2, rclBoundsAnisotropic
.right
, rclBoundsAnisotropic
.bottom
);
2391 /* Allow 1 mm difference (rounding errors) */
2392 diffx
= rclFrameAnisotropic
.right
/ 100 - GetDeviceCaps(dc
, HORZSIZE
) / 2;
2393 diffy
= rclFrameAnisotropic
.bottom
/ 100 - GetDeviceCaps(dc
, VERTSIZE
) / 2;
2394 if (diffx
< 0) diffx
= -diffx
;
2395 if (diffy
< 0) diffy
= -diffy
;
2398 ok(diffx
<= 1 && diffy
<= 1,
2399 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2400 GetDeviceCaps(dc
, HORZSIZE
) / 2, GetDeviceCaps(dc
, VERTSIZE
) / 2, rclFrameAnisotropic
.right
/ 100, rclFrameAnisotropic
.bottom
/ 100);
2404 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2405 checkConvertedFrameAndBounds(buffer_size
, buffer
, TRUE
, 0, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2407 /* If xExt or yExt is zero or negative, the whole device surface is used */
2408 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2409 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2410 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2411 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2412 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2413 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2414 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2415 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2416 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2417 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2418 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2419 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2421 /* MSDN says that negative xExt and yExt values specify a ratio.
2422 Check that this is wrong and the whole device surface is used */
2423 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -1000, -100, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
2424 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -1000, -100, &rclBoundsIsotropic
, &rclFrameIsotropic
);
2426 /* Ordinary conversions */
2428 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
2430 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
2431 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2432 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0 && rclBounds
.right
> rclBounds
.bottom
,
2433 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2436 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
2438 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
2439 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2440 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0,
2441 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2443 /* Wine has a rounding error */
2444 diffx
= rclBounds
.right
- rclBounds
.bottom
;
2445 if (diffx
< 0) diffx
= -diffx
;
2446 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2449 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_HIMETRIC
, 30000, 20000, &rclBounds
, &rclFrame
))
2451 ok(rclFrame
.right
- rclFrame
.left
!= 30000 && rclFrame
.bottom
- rclFrame
.top
!= 20000,
2452 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2455 HeapFree(GetProcessHeap(), 0, buffer
);
2458 static BOOL
near_match(int x
, int y
)
2460 int epsilon
= min(abs(x
), abs(y
));
2462 epsilon
= max(epsilon
/100, 2);
2464 if(x
< y
- epsilon
|| x
> y
+ epsilon
) return FALSE
;
2468 static void getwinmetafilebits(UINT mode
, int scale
, RECT
*rc
)
2471 HDC display_dc
, emf_dc
;
2472 ENHMETAHEADER
*enh_header
;
2473 UINT size
, emf_size
, i
;
2476 METAHEADER
*mh
= NULL
;
2478 INT horz_res
, vert_res
, horz_size
, vert_size
;
2480 display_dc
= GetDC(NULL
);
2481 ok(display_dc
!= NULL
, "display_dc is NULL\n");
2483 horz_res
= GetDeviceCaps(display_dc
, HORZRES
);
2484 vert_res
= GetDeviceCaps(display_dc
, VERTRES
);
2485 horz_size
= GetDeviceCaps(display_dc
, HORZSIZE
);
2486 vert_size
= GetDeviceCaps(display_dc
, VERTSIZE
);
2488 emf_dc
= CreateEnhMetaFileA(display_dc
, NULL
, rc
, NULL
);
2489 ok(emf_dc
!= NULL
, "emf_dc is NULL\n");
2490 for(i
= 0; i
< 3000; i
++) /* This is enough to take emf_size > 0xffff */
2491 Rectangle(emf_dc
, 0, 0, 1000, 20);
2492 emf
= CloseEnhMetaFile(emf_dc
);
2493 ok(emf
!= NULL
, "emf is NULL\n");
2495 emf_size
= GetEnhMetaFileBits(emf
, 0, NULL
);
2496 enh_header
= HeapAlloc(GetProcessHeap(), 0, emf_size
);
2497 emf_size
= GetEnhMetaFileBits(emf
, emf_size
, (BYTE
*)enh_header
);
2498 DeleteEnhMetaFile(emf
);
2499 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2500 have different resolutions */
2501 enh_header
->szlDevice
.cx
*= scale
;
2502 emf
= SetEnhMetaFileBits(emf_size
, (BYTE
*)enh_header
);
2503 ok(emf
!= NULL
, "emf is NULL\n");
2504 ok(EqualRect((RECT
*)&enh_header
->rclFrame
, rc
), "Frame rectangles differ\n");
2506 size
= GetWinMetaFileBits(emf
, 0, NULL
, mode
, display_dc
);
2508 broken(size
== 0), /* some versions of winxp fail for some reason */
2509 "GetWinMetaFileBits returns 0\n");
2511 mh
= HeapAlloc(GetProcessHeap(), 0, size
);
2512 GetWinMetaFileBits(emf
, size
, (BYTE
*)mh
, mode
, display_dc
);
2514 for(i
= 0; i
< size
/ 2; i
++) check
+= ((WORD
*)mh
)[i
];
2515 ok(check
== 0, "check %04x\n", check
);
2517 rec
= (METARECORD
*)(mh
+ 1);
2519 while(rec
->rdSize
&& rec
->rdFunction
)
2521 const DWORD chunk_size
= 0x2000;
2522 DWORD mfcomment_chunks
= (emf_size
+ chunk_size
- 1) / chunk_size
;
2524 if(rec_num
< mfcomment_chunks
)
2526 DWORD this_chunk_size
= chunk_size
;
2528 if(rec_num
== mfcomment_chunks
- 1)
2529 this_chunk_size
= emf_size
- rec_num
* chunk_size
;
2531 ok(rec
->rdSize
== (this_chunk_size
+ 44) / 2, "%04x: got %04x expected %04x\n", rec_num
, rec
->rdSize
, (this_chunk_size
+ 44) / 2);
2532 ok(rec
->rdFunction
== META_ESCAPE
, "%04x: got %04x\n", rec_num
, rec
->rdFunction
);
2533 if(rec
->rdSize
< (this_chunk_size
+ 44) / 2) break;
2534 ok(rec
->rdParm
[0] == MFCOMMENT
, "got %04x\n", rec
->rdParm
[0]);
2535 ok(rec
->rdParm
[1] == this_chunk_size
+ 34, "got %04x %x\n", rec
->rdParm
[1], emf_size
+ 34);
2536 ok(rec
->rdParm
[2] == 0x4d57, "got %04x\n", rec
->rdParm
[2]); /* WMFC */
2537 ok(rec
->rdParm
[3] == 0x4346, "got %04x\n", rec
->rdParm
[3]); /* " */
2538 ok(rec
->rdParm
[4] == 1, "got %04x\n", rec
->rdParm
[4]);
2539 ok(rec
->rdParm
[5] == 0, "got %04x\n", rec
->rdParm
[5]);
2540 ok(rec
->rdParm
[6] == 0, "got %04x\n", rec
->rdParm
[6]);
2541 ok(rec
->rdParm
[7] == 1, "got %04x\n", rec
->rdParm
[7]);
2542 /* parm[8] is the checksum, tested above */
2543 if(rec_num
> 0) ok(rec
->rdParm
[8] == 0, "got %04x\n", rec
->rdParm
[8]);
2544 ok(rec
->rdParm
[9] == 0, "got %04x\n", rec
->rdParm
[9]);
2545 ok(rec
->rdParm
[10] == 0, "got %04x\n", rec
->rdParm
[10]);
2546 ok(rec
->rdParm
[11] == mfcomment_chunks
, "got %04x\n", rec
->rdParm
[11]); /* num chunks */
2547 ok(rec
->rdParm
[12] == 0, "got %04x\n", rec
->rdParm
[12]);
2548 ok(rec
->rdParm
[13] == this_chunk_size
, "got %04x expected %04x\n", rec
->rdParm
[13], this_chunk_size
);
2549 ok(rec
->rdParm
[14] == 0, "got %04x\n", rec
->rdParm
[14]);
2550 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 */
2551 ok(*(DWORD
*)(rec
->rdParm
+ 17) == emf_size
, "got %08x emf_size %08x\n", *(DWORD
*)(rec
->rdParm
+ 17), emf_size
);
2552 ok(!memcmp(rec
->rdParm
+ 19, (char*)enh_header
+ rec_num
* chunk_size
, this_chunk_size
), "bits mismatch\n");
2555 else if(rec_num
== mfcomment_chunks
)
2557 ok(rec
->rdFunction
== META_SETMAPMODE
, "got %04x\n", rec
->rdFunction
);
2558 ok(rec
->rdParm
[0] == mode
, "got %04x\n", rec
->rdParm
[0]);
2560 else if(rec_num
== mfcomment_chunks
+ 1)
2563 ok(rec
->rdFunction
== META_SETWINDOWORG
, "got %04x\n", rec
->rdFunction
);
2568 case MM_ANISOTROPIC
:
2569 pt
.y
= MulDiv(rc
->top
, vert_res
, vert_size
* 100) + 1;
2570 pt
.x
= MulDiv(rc
->left
, horz_res
, horz_size
* 100);
2573 pt
.y
= MulDiv(-rc
->top
, 1, 10) + 1;
2574 pt
.x
= MulDiv( rc
->left
, 1, 10);
2577 pt
.y
= -rc
->top
+ 1;
2578 pt
.x
= (rc
->left
>= 0) ? rc
->left
: rc
->left
+ 1; /* strange but true */
2581 pt
.y
= MulDiv(-rc
->top
, 10, 254) + 1;
2582 pt
.x
= MulDiv( rc
->left
, 10, 254);
2585 pt
.y
= MulDiv(-rc
->top
, 100, 254) + 1;
2586 pt
.x
= MulDiv( rc
->left
, 100, 254);
2589 pt
.y
= MulDiv(-rc
->top
, 72 * 20, 2540) + 1;
2590 pt
.x
= MulDiv( rc
->left
, 72 * 20, 2540);
2595 ok(near_match((short)rec
->rdParm
[0], pt
.y
), "got %d expect %d\n", (short)rec
->rdParm
[0], pt
.y
);
2596 ok(near_match((short)rec
->rdParm
[1], pt
.x
), "got %d expect %d\n", (short)rec
->rdParm
[1], pt
.x
);
2598 if(rec_num
== mfcomment_chunks
+ 2)
2600 ok(rec
->rdFunction
== META_SETWINDOWEXT
, "got %04x\n", rec
->rdFunction
);
2601 ok(near_match((short)rec
->rdParm
[0], MulDiv(rc
->bottom
- rc
->top
, vert_res
, vert_size
* 100)),
2602 "got %d\n", (short)rec
->rdParm
[0]);
2603 ok(near_match((short)rec
->rdParm
[1], MulDiv(rc
->right
- rc
->left
, horz_res
, horz_size
* 100)),
2604 "got %d\n", (short)rec
->rdParm
[1]);
2608 rec
= (METARECORD
*)((WORD
*)rec
+ rec
->rdSize
);
2612 HeapFree(GetProcessHeap(), 0, mh
);
2613 HeapFree(GetProcessHeap(), 0, enh_header
);
2614 DeleteEnhMetaFile(emf
);
2616 ReleaseDC(NULL
, display_dc
);
2619 static void test_GetWinMetaFileBits(void)
2624 { 1000, 2000, 3000, 6000},
2625 {-1000, 2000, 3000, 6000},
2626 { 1000, -2000, 3000, 6000},
2627 { 1005, 2005, 3000, 6000},
2628 {-1005, -2005, 3000, 6000},
2629 {-1005, -2010, 3000, 6000},
2630 {-1005, 2010, 3000, 6000},
2636 for(mode
= MM_MIN
; mode
<= MM_MAX
; mode
++)
2639 trace("mode %d\n", mode
);
2641 for(rc
= frames
; rc
->right
- rc
->left
> 0; rc
++)
2643 trace("frame %d,%d - %d,%d\n", rc
->left
, rc
->top
, rc
->right
, rc
->bottom
);
2644 getwinmetafilebits(mode
, 1, rc
);
2645 getwinmetafilebits(mode
, 2, rc
);
2650 static BOOL (WINAPI
*pGdiIsMetaPrintDC
)(HDC
);
2651 static BOOL (WINAPI
*pGdiIsMetaFileDC
)(HDC
);
2652 static BOOL (WINAPI
*pGdiIsPlayMetafileDC
)(HDC
);
2654 static void test_gdiis(void)
2656 RECT rect
= {0,0,100,100};
2657 HDC hdc
, hemfDC
, hmfDC
;
2661 /* resolve all the functions */
2662 hgdi32
= GetModuleHandle("gdi32");
2663 pGdiIsMetaPrintDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaPrintDC");
2664 pGdiIsMetaFileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaFileDC");
2665 pGdiIsPlayMetafileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsPlayMetafileDC");
2667 if(!pGdiIsMetaPrintDC
|| !pGdiIsMetaFileDC
|| !pGdiIsPlayMetafileDC
)
2669 win_skip("Needed GdiIs* functions are not available\n");
2673 /* try with nothing */
2674 ok(!pGdiIsMetaPrintDC(NULL
), "ismetaprint with NULL parameter\n");
2675 ok(!pGdiIsMetaFileDC(NULL
), "ismetafile with NULL parameter\n");
2676 ok(!pGdiIsPlayMetafileDC(NULL
), "isplaymetafile with NULL parameter\n");
2678 /* try with a metafile */
2679 hmfDC
= CreateMetaFile(NULL
);
2680 ok(!pGdiIsMetaPrintDC(hmfDC
), "ismetaprint on metafile\n");
2681 ok(pGdiIsMetaFileDC(hmfDC
), "ismetafile on metafile\n");
2682 ok(!pGdiIsPlayMetafileDC(hmfDC
), "isplaymetafile on metafile\n");
2683 DeleteMetaFile(CloseMetaFile(hmfDC
));
2685 /* try with an enhanced metafile */
2687 hemfDC
= CreateEnhMetaFileW(hdc
, NULL
, &rect
, NULL
);
2688 ok(hemfDC
!= NULL
, "failed to create emf\n");
2690 ok(!pGdiIsMetaPrintDC(hemfDC
), "ismetaprint on emf\n");
2691 ok(pGdiIsMetaFileDC(hemfDC
), "ismetafile on emf\n");
2692 ok(!pGdiIsPlayMetafileDC(hemfDC
), "isplaymetafile on emf\n");
2694 hemf
= CloseEnhMetaFile(hemfDC
);
2695 ok(hemf
!= NULL
, "failed to close EMF\n");
2696 DeleteEnhMetaFile(hemf
);
2697 ReleaseDC(NULL
,hdc
);
2700 static void test_SetEnhMetaFileBits(void)
2706 memset(data
, 0xAA, sizeof(data
));
2707 SetLastError(0xdeadbeef);
2708 hemf
= SetEnhMetaFileBits(sizeof(data
), data
);
2709 ok(!hemf
, "SetEnhMetaFileBits should fail\n");
2710 ok(GetLastError() == ERROR_INVALID_DATA
||
2711 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x, WinMe */
2712 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2714 emh
= (ENHMETAHEADER
*)data
;
2715 memset(emh
, 0, sizeof(*emh
));
2717 emh
->iType
= EMR_HEADER
;
2718 emh
->nSize
= sizeof(*emh
);
2719 emh
->dSignature
= ENHMETA_SIGNATURE
;
2720 /* emh->nVersion = 0x10000; XP doesn't care about version */
2721 emh
->nBytes
= sizeof(*emh
);
2722 /* emh->nRecords = 1; XP doesn't care about records */
2723 emh
->nHandles
= 1; /* XP refuses to load a EMF if nHandles == 0 */
2725 SetLastError(0xdeadbeef);
2726 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
2727 ok(hemf
!= 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2728 DeleteEnhMetaFile(hemf
);
2730 /* XP refuses to load unaligned EMF */
2732 SetLastError(0xdeadbeef);
2733 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
2735 broken(hemf
!= NULL
), /* Win9x, WinMe */
2736 "SetEnhMetaFileBits should fail\n");
2737 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2738 DeleteEnhMetaFile(hemf
);
2740 emh
->dSignature
= 0;
2742 SetLastError(0xdeadbeef);
2743 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
2745 broken(hemf
!= NULL
), /* Win9x, WinMe */
2746 "SetEnhMetaFileBits should fail\n");
2747 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2748 DeleteEnhMetaFile(hemf
);
2751 START_TEST(metafile
)
2753 init_function_pointers();
2755 /* For enhanced metafiles (enhmfdrv) */
2760 /* For win-format metafiles (mfdrv) */
2764 test_mf_PatternBrush();
2765 test_CopyMetaFile();
2766 test_SetMetaFileBits();
2767 test_mf_ExtTextOut_on_path();
2768 test_emf_ExtTextOut_on_path();
2769 test_emf_clipping();
2771 /* For metafile conversions */
2772 test_mf_conversions();
2773 test_SetWinMetaFileBits();
2774 test_GetWinMetaFileBits();
2777 test_SetEnhMetaFileBits();