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
;
334 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
335 hdc
, emr
->iType
, emr
->nSize
, (void *)param
);
338 SetLastError(0xdeadbeef);
339 ret
= GetWorldTransform(hdc
, &xform
);
340 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
342 ok(GetWindowOrgEx(hdc
, &pt
), "GetWindowOrgEx error %u\n", GetLastError());
343 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
344 ok(GetViewportOrgEx(hdc
, &pt
), "GetViewportOrgEx error %u\n", GetLastError());
345 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
346 ok(GetWindowExtEx(hdc
, &size
), "GetWindowExtEx error %u\n", GetLastError());
347 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
348 ok(GetViewportExtEx(hdc
, &size
), "GetViewportExtEx error %u\n", GetLastError());
349 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
353 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
354 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
357 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
363 static RECT exp_bounds
= { 0, 0, 150, 150 };
365 const ENHMETAHEADER
*emf
= (const ENHMETAHEADER
*)emr
;
367 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
368 emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
,
369 emf
->rclFrame
.left
, emf
->rclFrame
.top
, emf
->rclFrame
.right
, emf
->rclFrame
.bottom
);
370 trace("mm %d x %d, device %d x %d\n", emf
->szlMillimeters
.cx
, emf
->szlMillimeters
.cy
,
371 emf
->szlDevice
.cx
, emf
->szlDevice
.cy
);
373 SetRect(&bounds
, emf
->rclBounds
.left
, emf
->rclBounds
.top
, emf
->rclBounds
.right
, emf
->rclBounds
.bottom
);
374 ok(EqualRect(&bounds
, &exp_bounds
), "wrong bounds\n");
378 check_dc_state(hdc
, restore_no
, 0, 0, 1, 1, 0, 0, 1, 1);
384 const EMRLINETO
*line
= (const EMRLINETO
*)emr
;
385 trace("EMR_LINETO %d,%d\n", line
->ptl
.x
, line
->ptl
.x
);
388 case EMR_SETWINDOWORGEX
:
390 const EMRSETWINDOWORGEX
*org
= (const EMRSETWINDOWORGEX
*)emr
;
391 trace("EMR_SETWINDOWORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
394 case EMR_SETWINDOWEXTEX
:
396 const EMRSETWINDOWEXTEX
*ext
= (const EMRSETWINDOWEXTEX
*)emr
;
397 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
400 case EMR_SETVIEWPORTORGEX
:
402 const EMRSETVIEWPORTORGEX
*org
= (const EMRSETVIEWPORTORGEX
*)emr
;
403 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org
->ptlOrigin
.x
, org
->ptlOrigin
.y
);
406 case EMR_SETVIEWPORTEXTEX
:
408 const EMRSETVIEWPORTEXTEX
*ext
= (const EMRSETVIEWPORTEXTEX
*)emr
;
409 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext
->szlExtent
.cx
, ext
->szlExtent
.cy
);
414 trace("EMR_SAVEDC\n");
419 const EMRRESTOREDC
*restoredc
= (const EMRRESTOREDC
*)emr
;
420 trace("EMR_RESTOREDC: %d\n", restoredc
->iRelative
);
425 ok(restoredc
->iRelative
== -1, "first restore %d\n", restoredc
->iRelative
);
426 check_dc_state(hdc
, restore_no
, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
429 ok(restoredc
->iRelative
== -3, "second restore %d\n", restoredc
->iRelative
);
430 check_dc_state(hdc
, restore_no
, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
433 ok(restoredc
->iRelative
== -2, "third restore %d\n", restoredc
->iRelative
);
434 check_dc_state(hdc
, restore_no
, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
437 ok(restore_no
<= 3, "restore_no %d\n", restore_no
);
438 save_state
+= restoredc
->iRelative
;
442 ok(save_state
== 0, "EOF save_state %d\n", save_state
);
447 SetLastError(0xdeadbeef);
448 ret
= GetWorldTransform(hdc
, &xform
);
449 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
451 ok(GetWindowOrgEx(hdc
, &pt
), "GetWindowOrgEx error %u\n", GetLastError());
452 trace("window org (%d,%d)\n", pt
.x
, pt
.y
);
453 ok(GetViewportOrgEx(hdc
, &pt
), "GetViewportOrgEx error %u\n", GetLastError());
454 trace("vport org (%d,%d)\n", pt
.x
, pt
.y
);
455 ok(GetWindowExtEx(hdc
, &size
), "GetWindowExtEx error %u\n", GetLastError());
456 trace("window ext (%d,%d)\n", size
.cx
, size
.cy
);
457 ok(GetViewportExtEx(hdc
, &size
), "GetViewportExtEx error %u\n", GetLastError());
458 trace("vport ext (%d,%d)\n", size
.cx
, size
.cy
);
462 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
463 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform
.eM11
, xform
.eM22
, xform
.eDx
, xform
.eDy
);
469 static void test_SaveDC(void)
471 HDC hdcMetafile
, hdcDisplay
;
472 HENHMETAFILE hMetafile
;
475 static const RECT rc
= { 0, 0, 150, 150 };
477 /* Win9x doesn't play EMFs on invisible windows */
478 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
479 0, 0, 200, 200, 0, 0, 0, NULL
);
480 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
482 hdcDisplay
= GetDC(hwnd
);
483 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
485 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
486 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
488 SetMapMode(hdcMetafile
, MM_ANISOTROPIC
);
490 /* Need to write something to the emf, otherwise Windows won't play it back */
491 LineTo(hdcMetafile
, 150, 150);
493 SetWindowOrgEx(hdcMetafile
, 0, 0, NULL
);
494 SetViewportOrgEx(hdcMetafile
, 0, 0, NULL
);
495 SetWindowExtEx(hdcMetafile
, 110, 110, NULL
);
496 SetViewportExtEx(hdcMetafile
, 120, 120, NULL
);
498 /* Force Win9x to update DC state */
499 SetPixelV(hdcMetafile
, 50, 50, 0);
501 ret
= SaveDC(hdcMetafile
);
502 ok(ret
== 1, "ret = %d\n", ret
);
504 SetWindowOrgEx(hdcMetafile
, -1, -1, NULL
);
505 SetViewportOrgEx(hdcMetafile
, 10, 10, NULL
);
506 SetWindowExtEx(hdcMetafile
, 150, 150, NULL
);
507 SetViewportExtEx(hdcMetafile
, 200, 200, NULL
);
509 /* Force Win9x to update DC state */
510 SetPixelV(hdcMetafile
, 50, 50, 0);
512 ret
= SaveDC(hdcMetafile
);
513 ok(ret
== 2, "ret = %d\n", ret
);
515 SetWindowOrgEx(hdcMetafile
, -2, -2, NULL
);
516 SetViewportOrgEx(hdcMetafile
, 20, 20, NULL
);
517 SetWindowExtEx(hdcMetafile
, 120, 120, NULL
);
518 SetViewportExtEx(hdcMetafile
, 300, 300, NULL
);
520 /* Force Win9x to update DC state */
521 SetPixelV(hdcMetafile
, 50, 50, 0);
523 ret
= SaveDC(hdcMetafile
);
524 ok(ret
== 3, "ret = %d\n", ret
);
526 SetWindowOrgEx(hdcMetafile
, -3, -3, NULL
);
527 SetViewportOrgEx(hdcMetafile
, 30, 30, NULL
);
528 SetWindowExtEx(hdcMetafile
, 200, 200, NULL
);
529 SetViewportExtEx(hdcMetafile
, 400, 400, NULL
);
531 /* Force Win9x to update DC state */
532 SetPixelV(hdcMetafile
, 50, 50, 0);
534 ret
= RestoreDC(hdcMetafile
, -1);
535 ok(ret
, "ret = %d\n", ret
);
537 ret
= SaveDC(hdcMetafile
);
538 ok(ret
== 3, "ret = %d\n", ret
);
540 ret
= RestoreDC(hdcMetafile
, 1);
541 ok(ret
, "ret = %d\n", ret
);
543 SetWindowOrgEx(hdcMetafile
, -4, -4, NULL
);
544 SetViewportOrgEx(hdcMetafile
, 40, 40, NULL
);
545 SetWindowExtEx(hdcMetafile
, 500, 500, NULL
);
546 SetViewportExtEx(hdcMetafile
, 50, 50, NULL
);
548 /* Force Win9x to update DC state */
549 SetPixelV(hdcMetafile
, 50, 50, 0);
551 ret
= SaveDC(hdcMetafile
);
552 ok(ret
== 1, "ret = %d\n", ret
);
554 ret
= SaveDC(hdcMetafile
);
555 ok(ret
== 2, "ret = %d\n", ret
);
557 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
558 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
560 ret
= EnumEnhMetaFile(hdcDisplay
, hMetafile
, savedc_emf_enum_proc
, 0, &rc
);
561 ok( ret
== 1, "EnumEnhMetaFile rets %d\n", ret
);
563 ret
= DeleteEnhMetaFile(hMetafile
);
564 ok( ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
565 ret
= ReleaseDC(hwnd
, hdcDisplay
);
566 ok( ret
, "ReleaseDC error %d\n", GetLastError());
570 /* Win-format metafile (mfdrv) tests */
571 /* These tests compare the generated metafiles byte-by-byte */
572 /* with the nominal results. */
574 /* Maximum size of sample metafiles in bytes. */
575 #define MF_BUFSIZE 512
577 /* 8x8 bitmap data for a pattern brush */
578 static const unsigned char SAMPLE_PATTERN_BRUSH
[] = {
579 0x01, 0x00, 0x02, 0x00,
580 0x03, 0x00, 0x04, 0x00,
581 0x05, 0x00, 0x06, 0x00,
582 0x07, 0x00, 0x08, 0x00
585 /* Sample metafiles to be compared to the outputs of the
589 static const unsigned char MF_BLANK_BITS
[] = {
590 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
595 static const unsigned char MF_GRAPHICS_BITS
[] = {
596 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
599 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
600 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
601 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
602 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
603 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
604 0x00, 0x00, 0x00, 0x00
607 static const unsigned char MF_PATTERN_BRUSH_BITS
[] = {
608 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
609 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
611 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
612 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
613 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
618 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
619 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
620 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
621 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
622 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
626 static const unsigned char MF_TEXTOUT_ON_PATH_BITS
[] =
628 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
631 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
632 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
633 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
637 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS
[] =
639 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
644 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
645 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
646 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
649 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
652 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
653 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
654 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
656 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
658 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
659 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
662 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
663 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
664 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
665 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
666 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
667 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
669 0x14, 0x00, 0x00, 0x00
672 static const unsigned char MF_LINETO_BITS
[] = {
673 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
676 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
680 static const unsigned char EMF_LINETO_BITS
[] = {
681 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
686 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
687 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
688 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
691 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
694 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
695 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
696 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
697 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
698 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
699 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
702 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
704 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
705 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
706 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
707 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
708 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
709 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
710 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
711 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
712 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
713 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
714 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
715 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
716 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
718 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
722 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS
[] = {
723 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
728 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
729 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
730 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
733 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
736 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
737 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
738 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
739 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
740 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
741 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
744 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
746 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
747 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
748 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
749 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
750 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
751 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
752 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
753 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
754 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
755 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
756 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
757 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
758 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
760 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
764 static const unsigned char EMF_LINETO_MM_TEXT_BITS
[] = {
765 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
770 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
771 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
772 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
775 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
778 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
779 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
780 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
781 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
782 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
783 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
784 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
785 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
786 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
788 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
789 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
791 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
793 0x14, 0x00, 0x00, 0x00
796 /* For debugging or dumping the raw metafiles produced by
797 * new test functions.
799 static INT CALLBACK
mf_enum_proc(HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
,
800 INT nobj
, LPARAM param
)
802 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
803 hdc
, mr
->rdFunction
, mr
->rdSize
, (void *)param
);
807 /* For debugging or dumping the raw metafiles produced by
808 * new test functions.
811 static void dump_mf_bits (const HMETAFILE mf
, const char *desc
)
813 BYTE buf
[MF_BUFSIZE
];
816 if (!winetest_debug
) return;
818 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
819 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
821 printf ("MetaFile %s has bits:\n{\n ", desc
);
822 for (i
=0; i
<mfsize
; i
++)
824 printf ("0x%02x", buf
[i
]);
835 /* Compare the metafile produced by a test function with the
836 * expected raw metafile data in "bits".
837 * Return value is 0 for a perfect match,
838 * -1 if lengths aren't equal,
839 * otherwise returns the number of non-matching bytes.
842 static int compare_mf_bits (const HMETAFILE mf
, const unsigned char *bits
, UINT bsize
,
845 unsigned char buf
[MF_BUFSIZE
];
849 mfsize
= GetMetaFileBitsEx (mf
, MF_BUFSIZE
, buf
);
850 ok (mfsize
> 0, "%s: GetMetaFileBitsEx failed.\n", desc
);
851 if (mfsize
< MF_BUFSIZE
)
852 ok (mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n",
853 desc
, mfsize
, bsize
);
855 ok (bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
856 desc
, mfsize
, bsize
);
861 for (i
=0; i
<bsize
; i
++)
863 if (buf
[i
] != bits
[i
])
866 ok (diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
867 desc
, mfsize
, bsize
, diff
);
872 static int compare_mf_disk_bits(LPCSTR name
, const BYTE
*bits
, UINT bsize
, const char *desc
)
874 unsigned char buf
[MF_BUFSIZE
];
875 DWORD mfsize
, rd_size
, i
;
880 hfile
= CreateFileA(name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
881 assert(hfile
!= INVALID_HANDLE_VALUE
);
883 mfsize
= GetFileSize(hfile
, NULL
);
884 assert(mfsize
<= MF_BUFSIZE
);
886 ret
= ReadFile(hfile
, buf
, sizeof(buf
), &rd_size
, NULL
);
887 ok( ret
&& rd_size
== mfsize
, "ReadFile: error %d\n", GetLastError());
891 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d.\n", desc
, mfsize
, bsize
);
897 for (i
=0; i
<bsize
; i
++)
899 if (buf
[i
] != bits
[i
])
902 ok(diff
== 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
903 desc
, mfsize
, bsize
, diff
);
908 /* For debugging or dumping the raw EMFs produced by
909 * new test functions.
911 static void dump_emf_bits(const HENHMETAFILE mf
, const char *desc
)
913 BYTE buf
[MF_BUFSIZE
];
916 if (!winetest_debug
) return;
918 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
919 ok (mfsize
> 0, "%s: GetEnhMetaFileBits failed\n", desc
);
921 printf("EMF %s has bits:\n{\n ", desc
);
922 for (i
= 0; i
< mfsize
; i
++)
924 printf ("0x%02x", buf
[i
]);
935 static void dump_emf_records(const HENHMETAFILE mf
, const char *desc
)
938 BYTE buf
[MF_BUFSIZE
];
941 if (!winetest_debug
) return;
943 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
944 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
946 printf("EMF %s has records:\n", desc
);
950 while(offset
< mfsize
)
952 EMR
*emr
= (EMR
*)(emf
+ offset
);
953 printf("emr->iType %d, emr->nSize %u\n", emr
->iType
, emr
->nSize
);
954 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
955 offset
+= emr
->nSize
;
959 static void dump_emf_record(const ENHMETARECORD
*emr
, const char *desc
)
964 if (!winetest_debug
) return;
966 printf ("%s: EMF record %u has bits:\n{\n", desc
, emr
->iType
);
967 buf
= (const BYTE
*)emr
;
968 for (i
= 0; i
< emr
->nSize
; i
++)
970 printf ("0x%02x", buf
[i
]);
971 if (i
== emr
->nSize
- 1)
981 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW
*eto
)
983 trace("rclBounds %d,%d - %d,%d\n", eto
->rclBounds
.left
, eto
->rclBounds
.top
,
984 eto
->rclBounds
.right
, eto
->rclBounds
.bottom
);
985 trace("iGraphicsMode %u\n", eto
->iGraphicsMode
);
986 trace("exScale: %f\n", eto
->exScale
);
987 trace("eyScale: %f\n", eto
->eyScale
);
988 trace("emrtext.ptlReference %d,%d\n", eto
->emrtext
.ptlReference
.x
, eto
->emrtext
.ptlReference
.y
);
989 trace("emrtext.nChars %u\n", eto
->emrtext
.nChars
);
990 trace("emrtext.offString %#x\n", eto
->emrtext
.offString
);
991 trace("emrtext.fOptions %#x\n", eto
->emrtext
.fOptions
);
992 trace("emrtext.rcl %d,%d - %d,%d\n", eto
->emrtext
.rcl
.left
, eto
->emrtext
.rcl
.top
,
993 eto
->emrtext
.rcl
.right
, eto
->emrtext
.rcl
.bottom
);
994 trace("emrtext.offDx %#x\n", eto
->emrtext
.offDx
);
997 static BOOL
match_emf_record(const ENHMETARECORD
*emr1
, const ENHMETARECORD
*emr2
,
998 const char *desc
, BOOL ignore_scaling
)
1002 ok(emr1
->iType
== emr2
->iType
, "%s: emr->iType %u != %u\n",
1003 desc
, emr1
->iType
, emr2
->iType
);
1005 ok(emr1
->nSize
== emr2
->nSize
, "%s: emr->nSize %u != %u\n",
1006 desc
, emr1
->nSize
, emr2
->nSize
);
1008 /* iType and nSize mismatches are fatal */
1009 if (emr1
->iType
!= emr2
->iType
|| emr1
->nSize
!= emr2
->nSize
) return FALSE
;
1011 /* contents of EMR_GDICOMMENT are not interesting */
1012 if (emr1
->iType
== EMR_GDICOMMENT
) return TRUE
;
1014 /* different Windows versions setup DC scaling differently when
1015 * converting an old style metafile to an EMF.
1017 if (ignore_scaling
&& (emr1
->iType
== EMR_SETWINDOWEXTEX
||
1018 emr1
->iType
== EMR_SETVIEWPORTEXTEX
))
1021 if (emr1
->iType
== EMR_EXTTEXTOUTW
|| emr1
->iType
== EMR_EXTTEXTOUTA
)
1023 EMREXTTEXTOUTW
*eto1
, *eto2
;
1025 eto1
= HeapAlloc(GetProcessHeap(), 0, emr1
->nSize
);
1026 memcpy(eto1
, emr1
, emr1
->nSize
);
1027 eto2
= HeapAlloc(GetProcessHeap(), 0, emr2
->nSize
);
1028 memcpy(eto2
, emr2
, emr2
->nSize
);
1030 /* different Windows versions setup DC scaling differently */
1031 eto1
->exScale
= eto1
->eyScale
= 0.0;
1032 eto2
->exScale
= eto2
->eyScale
= 0.0;
1034 diff
= memcmp(eto1
, eto2
, emr1
->nSize
);
1037 dump_EMREXTTEXTOUT(eto1
);
1038 dump_EMREXTTEXTOUT(eto2
);
1040 HeapFree(GetProcessHeap(), 0, eto1
);
1041 HeapFree(GetProcessHeap(), 0, eto2
);
1044 diff
= memcmp(emr1
, emr2
, emr1
->nSize
);
1046 ok(diff
== 0, "%s: contents of record %u don't match\n", desc
, emr1
->iType
);
1050 dump_emf_record(emr1
, "expected bits");
1051 dump_emf_record(emr2
, "actual bits");
1054 return diff
== 0; /* report all non-fatal record mismatches */
1057 /* Compare the EMF produced by a test function with the
1058 * expected raw EMF data in "bits".
1059 * Return value is 0 for a perfect match,
1060 * -1 if lengths aren't equal,
1061 * otherwise returns the number of non-matching bytes.
1063 static int compare_emf_bits(const HENHMETAFILE mf
, const unsigned char *bits
,
1064 UINT bsize
, const char *desc
,
1065 BOOL ignore_scaling
)
1067 unsigned char buf
[MF_BUFSIZE
];
1068 UINT mfsize
, offset
;
1069 const ENHMETAHEADER
*emh1
, *emh2
;
1071 mfsize
= GetEnhMetaFileBits(mf
, MF_BUFSIZE
, buf
);
1072 ok (mfsize
> 0, "%s: GetEnhMetaFileBits error %d\n", desc
, GetLastError());
1074 if (mfsize
< MF_BUFSIZE
)
1076 ok(mfsize
== bsize
, "%s: mfsize=%d, bsize=%d\n", desc
, mfsize
, bsize
);
1079 ok(bsize
>= MF_BUFSIZE
, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1080 desc
, mfsize
, bsize
);
1082 /* basic things must match */
1083 emh1
= (const ENHMETAHEADER
*)bits
;
1084 emh2
= (const ENHMETAHEADER
*)buf
;
1085 ok(emh1
->iType
== EMR_HEADER
, "expected EMR_HEADER, got %u\n", emh1
->iType
);
1086 ok(emh1
->nSize
== sizeof(ENHMETAHEADER
), "expected sizeof(ENHMETAHEADER), got %u\n", emh1
->nSize
);
1087 ok(emh2
->nBytes
== mfsize
, "expected emh->nBytes %u, got %u\n", mfsize
, emh2
->nBytes
);
1088 ok(emh1
->dSignature
== ENHMETA_SIGNATURE
, "expected ENHMETA_SIGNATURE, got %u\n", emh1
->dSignature
);
1090 ok(emh1
->iType
== emh2
->iType
, "expected EMR_HEADER, got %u\n", emh2
->iType
);
1091 ok(emh1
->nSize
== emh2
->nSize
, "expected nSize %u, got %u\n", emh1
->nSize
, emh2
->nSize
);
1092 ok(emh1
->dSignature
== emh2
->dSignature
, "expected dSignature %u, got %u\n", emh1
->dSignature
, emh2
->dSignature
);
1093 ok(emh1
->nBytes
== emh2
->nBytes
, "expected nBytes %u, got %u\n", emh1
->nBytes
, emh2
->nBytes
);
1094 ok(emh1
->nRecords
== emh2
->nRecords
, "expected nBytes %u, got %u\n", emh1
->nRecords
, emh2
->nRecords
);
1096 offset
= emh1
->nSize
;
1097 while (offset
< emh1
->nBytes
)
1099 const ENHMETARECORD
*emr1
= (const ENHMETARECORD
*)(bits
+ offset
);
1100 const ENHMETARECORD
*emr2
= (const ENHMETARECORD
*)(buf
+ offset
);
1102 trace("EMF record %u, size %u/record %u, size %u\n",
1103 emr1
->iType
, emr1
->nSize
, emr2
->iType
, emr2
->nSize
);
1105 if (!match_emf_record(emr1
, emr2
, desc
, ignore_scaling
)) return -1;
1107 offset
+= emr1
->nSize
;
1112 /* Test a blank metafile. May be used as a template for new tests. */
1114 static void test_mf_Blank(void)
1117 HMETAFILE hMetafile
;
1122 hdcMetafile
= CreateMetaFileA(NULL
);
1123 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1124 trace("hdcMetafile %p\n", hdcMetafile
);
1126 /* Tests on metafile initialization */
1127 caps
= GetDeviceCaps (hdcMetafile
, TECHNOLOGY
);
1128 ok (caps
== DT_METAFILE
,
1129 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps
);
1131 hMetafile
= CloseMetaFile(hdcMetafile
);
1132 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1133 type
= GetObjectType(hMetafile
);
1134 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1135 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1137 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1140 dump_mf_bits(hMetafile
, "mf_Blank");
1141 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1144 ret
= DeleteMetaFile(hMetafile
);
1145 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1148 static void test_CopyMetaFile(void)
1151 HMETAFILE hMetafile
, hmf_copy
;
1153 char temp_path
[MAX_PATH
];
1154 char mf_name
[MAX_PATH
];
1157 hdcMetafile
= CreateMetaFileA(NULL
);
1158 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1159 trace("hdcMetafile %p\n", hdcMetafile
);
1161 hMetafile
= CloseMetaFile(hdcMetafile
);
1162 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1163 type
= GetObjectType(hMetafile
);
1164 ok(type
== OBJ_METAFILE
, "CloseMetaFile created object with type %d\n", type
);
1166 if (compare_mf_bits (hMetafile
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
),
1169 dump_mf_bits(hMetafile
, "mf_Blank");
1170 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1173 GetTempPathA(MAX_PATH
, temp_path
);
1174 GetTempFileNameA(temp_path
, "wmf", 0, mf_name
);
1176 hmf_copy
= CopyMetaFileA(hMetafile
, mf_name
);
1177 ok(hmf_copy
!= 0, "CopyMetaFile error %d\n", GetLastError());
1179 type
= GetObjectType(hmf_copy
);
1180 ok(type
== OBJ_METAFILE
, "CopyMetaFile created object with type %d\n", type
);
1182 ret
= DeleteMetaFile(hMetafile
);
1183 ok( ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1185 if (compare_mf_disk_bits(mf_name
, MF_BLANK_BITS
, sizeof(MF_BLANK_BITS
), "mf_blank") != 0)
1187 dump_mf_bits(hMetafile
, "mf_Blank");
1188 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1191 ret
= DeleteMetaFile(hmf_copy
);
1192 ok( ret
, "DeleteMetaFile(%p) error %d\n", hmf_copy
, GetLastError());
1194 DeleteFileA(mf_name
);
1197 static void test_SetMetaFileBits(void)
1205 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), MF_GRAPHICS_BITS
);
1206 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1207 type
= GetObjectType(hmf
);
1208 ok(type
== OBJ_METAFILE
, "SetMetaFileBitsEx created object with type %d\n", type
);
1210 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1212 dump_mf_bits(hmf
, "mf_Graphics");
1213 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1216 ret
= DeleteMetaFile(hmf
);
1217 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1219 /* NULL data crashes XP SP1 */
1220 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1222 /* Now with not zero size */
1223 SetLastError(0xdeadbeef);
1224 hmf
= SetMetaFileBitsEx(0, MF_GRAPHICS_BITS
);
1225 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1226 ok(GetLastError() == ERROR_INVALID_DATA
, "wrong error %d\n", GetLastError());
1228 /* Now with not even size */
1229 SetLastError(0xdeadbeef);
1230 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
) - 1, MF_GRAPHICS_BITS
);
1231 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1232 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1234 /* Now with zeroed out or faked some header fields */
1235 assert(sizeof(buf
) >= sizeof(MF_GRAPHICS_BITS
));
1236 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
1237 mh
= (METAHEADER
*)buf
;
1238 /* corruption of any of the below fields leads to a failure */
1241 mh
->mtHeaderSize
= 0;
1242 SetLastError(0xdeadbeef);
1243 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
1244 ok(!hmf
, "SetMetaFileBitsEx should fail\n");
1245 ok(GetLastError() == ERROR_INVALID_DATA
, "wrong error %d\n", GetLastError());
1247 /* Now with corrupted mtSize field */
1248 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
1249 mh
= (METAHEADER
*)buf
;
1250 /* corruption of mtSize doesn't lead to a failure */
1252 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
1253 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1255 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1257 dump_mf_bits(hmf
, "mf_Graphics");
1258 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1261 ret
= DeleteMetaFile(hmf
);
1262 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1264 /* Now with zeroed out mtSize field */
1265 memcpy(buf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
));
1266 mh
= (METAHEADER
*)buf
;
1267 /* zeroing mtSize doesn't lead to a failure */
1269 hmf
= SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS
), buf
);
1270 ok(hmf
!= 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1272 if (compare_mf_bits(hmf
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
), "mf_Graphics") != 0)
1274 dump_mf_bits(hmf
, "mf_Graphics");
1275 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1278 ret
= DeleteMetaFile(hmf
);
1279 ok(ret
, "DeleteMetaFile(%p) error %d\n", hmf
, GetLastError());
1282 /* Simple APIs from mfdrv/graphics.c
1285 static void test_mf_Graphics(void)
1288 HMETAFILE hMetafile
;
1292 hdcMetafile
= CreateMetaFileA(NULL
);
1293 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1294 trace("hdcMetafile %p\n", hdcMetafile
);
1296 ret
= MoveToEx(hdcMetafile
, 1, 1, NULL
);
1297 ok( ret
, "MoveToEx error %d.\n", GetLastError());
1298 ret
= LineTo(hdcMetafile
, 2, 2);
1299 ok( ret
, "LineTo error %d.\n", GetLastError());
1300 ret
= MoveToEx(hdcMetafile
, 1, 1, &oldpoint
);
1301 ok( ret
, "MoveToEx error %d.\n", GetLastError());
1303 /* oldpoint gets garbage under Win XP, so the following test would
1304 * work under Wine but fails under Windows:
1306 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1307 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1308 * oldpoint.x, oldpoint.y);
1311 ret
= Ellipse(hdcMetafile
, 0, 0, 2, 2);
1312 ok( ret
, "Ellipse error %d.\n", GetLastError());
1314 hMetafile
= CloseMetaFile(hdcMetafile
);
1315 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1316 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1318 if (compare_mf_bits (hMetafile
, MF_GRAPHICS_BITS
, sizeof(MF_GRAPHICS_BITS
),
1319 "mf_Graphics") != 0)
1321 dump_mf_bits(hMetafile
, "mf_Graphics");
1322 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1325 ret
= DeleteMetaFile(hMetafile
);
1326 ok( ret
, "DeleteMetaFile(%p) error %d\n",
1327 hMetafile
, GetLastError());
1330 static void test_mf_PatternBrush(void)
1333 HMETAFILE hMetafile
;
1338 orig_lb
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(LOGBRUSH
));
1340 orig_lb
->lbStyle
= BS_PATTERN
;
1341 orig_lb
->lbColor
= RGB(0, 0, 0);
1342 orig_lb
->lbHatch
= (ULONG_PTR
)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH
);
1343 ok((HBITMAP
)orig_lb
->lbHatch
!= NULL
, "CreateBitmap error %d.\n", GetLastError());
1345 hBrush
= CreateBrushIndirect (orig_lb
);
1346 ok(hBrush
!= 0, "CreateBrushIndirect error %d\n", GetLastError());
1348 hdcMetafile
= CreateMetaFileA(NULL
);
1349 ok(hdcMetafile
!= 0, "CreateMetaFileA error %d\n", GetLastError());
1350 trace("hdcMetafile %p\n", hdcMetafile
);
1352 hBrush
= SelectObject(hdcMetafile
, hBrush
);
1353 ok(hBrush
!= 0, "SelectObject error %d.\n", GetLastError());
1355 hMetafile
= CloseMetaFile(hdcMetafile
);
1356 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1357 ok(!GetObjectType(hdcMetafile
), "CloseMetaFile has to destroy metafile hdc\n");
1359 if (compare_mf_bits (hMetafile
, MF_PATTERN_BRUSH_BITS
, sizeof(MF_PATTERN_BRUSH_BITS
),
1360 "mf_Pattern_Brush") != 0)
1362 dump_mf_bits(hMetafile
, "mf_Pattern_Brush");
1363 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1366 ret
= DeleteMetaFile(hMetafile
);
1367 ok( ret
, "DeleteMetaFile error %d\n", GetLastError());
1368 ret
= DeleteObject(hBrush
);
1369 ok( ret
, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1370 ret
= DeleteObject((HBITMAP
)orig_lb
->lbHatch
);
1371 ok( ret
, "DeleteObject(HBITMAP) error %d\n",
1373 HeapFree (GetProcessHeap(), 0, orig_lb
);
1376 static void test_mf_ExtTextOut_on_path(void)
1379 HMETAFILE hMetafile
;
1381 static const INT dx
[4] = { 3, 5, 8, 12 };
1383 hdcMetafile
= CreateMetaFileA(NULL
);
1384 ok(hdcMetafile
!= 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1385 trace("hdcMetafile %p\n", hdcMetafile
);
1387 ret
= BeginPath(hdcMetafile
);
1388 ok(!ret
, "BeginPath on metafile DC should fail\n");
1390 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
1391 ok(ret
, "ExtTextOut error %d\n", GetLastError());
1393 ret
= EndPath(hdcMetafile
);
1394 ok(!ret
, "EndPath on metafile DC should fail\n");
1396 hMetafile
= CloseMetaFile(hdcMetafile
);
1397 ok(hMetafile
!= 0, "CloseMetaFile error %d\n", GetLastError());
1399 if (compare_mf_bits(hMetafile
, MF_TEXTOUT_ON_PATH_BITS
, sizeof(MF_TEXTOUT_ON_PATH_BITS
),
1400 "mf_TextOut_on_path") != 0)
1402 dump_mf_bits(hMetafile
, "mf_TextOut_on_path");
1403 EnumMetaFile(0, hMetafile
, mf_enum_proc
, 0);
1406 ret
= DeleteMetaFile(hMetafile
);
1407 ok(ret
, "DeleteMetaFile(%p) error %d\n", hMetafile
, GetLastError());
1410 static void test_emf_ExtTextOut_on_path(void)
1413 HDC hdcDisplay
, hdcMetafile
;
1414 HENHMETAFILE hMetafile
;
1416 static const INT dx
[4] = { 3, 5, 8, 12 };
1418 /* Win9x doesn't play EMFs on invisible windows */
1419 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
1420 0, 0, 200, 200, 0, 0, 0, NULL
);
1421 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
1423 hdcDisplay
= GetDC(hwnd
);
1424 ok(hdcDisplay
!= 0, "GetDC error %d\n", GetLastError());
1426 hdcMetafile
= CreateEnhMetaFileA(hdcDisplay
, NULL
, NULL
, NULL
);
1427 ok(hdcMetafile
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1429 ret
= BeginPath(hdcMetafile
);
1430 ok(ret
, "BeginPath error %d\n", GetLastError());
1432 ret
= ExtTextOutA(hdcMetafile
, 11, 22, 0, NULL
, "Test", 4, dx
);
1433 ok(ret
, "ExtTextOut error %d\n", GetLastError());
1435 ret
= EndPath(hdcMetafile
);
1436 ok(ret
, "EndPath error %d\n", GetLastError());
1438 hMetafile
= CloseEnhMetaFile(hdcMetafile
);
1439 ok(hMetafile
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
1441 /* this doesn't succeed yet: EMF has correct size, all EMF records
1442 * are there, but their contents don't match for different reasons.
1444 if (compare_emf_bits(hMetafile
, EMF_TEXTOUT_ON_PATH_BITS
, sizeof(EMF_TEXTOUT_ON_PATH_BITS
),
1445 "emf_TextOut_on_path", FALSE
) != 0)
1447 dump_emf_bits(hMetafile
, "emf_TextOut_on_path");
1448 dump_emf_records(hMetafile
, "emf_TextOut_on_path");
1451 ret
= DeleteEnhMetaFile(hMetafile
);
1452 ok(ret
, "DeleteEnhMetaFile error %d\n", GetLastError());
1453 ret
= ReleaseDC(hwnd
, hdcDisplay
);
1454 ok(ret
, "ReleaseDC error %d\n", GetLastError());
1455 DestroyWindow(hwnd
);
1458 static const unsigned char EMF_CLIPPING
[] =
1460 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1461 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1462 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1464 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1465 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1466 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1467 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1470 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1473 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1474 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1475 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1476 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1477 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1478 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1479 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1480 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1481 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1482 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1483 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1484 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1488 static void translate( POINT
*pt
, UINT count
, const XFORM
*xform
)
1492 FLOAT x
= (FLOAT
)pt
->x
;
1493 FLOAT y
= (FLOAT
)pt
->y
;
1494 pt
->x
= (LONG
)floor( x
* xform
->eM11
+ y
* xform
->eM21
+ xform
->eDx
+ 0.5 );
1495 pt
->y
= (LONG
)floor( x
* xform
->eM12
+ y
* xform
->eM22
+ xform
->eDy
+ 0.5 );
1500 /* Compare rectangles allowing rounding errors */
1501 static BOOL
is_equal_rect(const RECT
*rc1
, const RECT
*rc2
)
1503 return abs(rc1
->left
- rc2
->left
) <= 1 &&
1504 abs(rc1
->top
- rc2
->top
) <= 1 &&
1505 abs(rc1
->right
- rc2
->right
) <= 1 &&
1506 abs(rc1
->bottom
- rc2
->bottom
) <= 1;
1509 static int CALLBACK
clip_emf_enum_proc(HDC hdc
, HANDLETABLE
*handle_table
,
1510 const ENHMETARECORD
*emr
, int n_objs
, LPARAM param
)
1512 if (emr
->iType
== EMR_EXTSELECTCLIPRGN
)
1514 const EMREXTSELECTCLIPRGN
*clip
= (const EMREXTSELECTCLIPRGN
*)emr
;
1518 char buf
[sizeof(RGNDATAHEADER
) + sizeof(RECT
)];
1520 const union _rgn
*rgn1
;
1522 RECT rect
, rc_transformed
;
1523 const RECT
*rc
= (const RECT
*)param
;
1529 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1530 clip
->cbRgnData
, clip
->iMode
);
1532 ok(clip
->iMode
== RGN_COPY
, "expected RGN_COPY, got %u\n", clip
->iMode
);
1533 ok(clip
->cbRgnData
>= sizeof(RGNDATAHEADER
) + sizeof(RECT
),
1534 "too small data block: %u bytes\n", clip
->cbRgnData
);
1535 if (clip
->cbRgnData
< sizeof(RGNDATAHEADER
) + sizeof(RECT
))
1538 rgn1
= (const union _rgn
*)clip
->RgnData
;
1540 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1541 rgn1
->data
.rdh
.dwSize
, rgn1
->data
.rdh
.iType
,
1542 rgn1
->data
.rdh
.nCount
, rgn1
->data
.rdh
.nRgnSize
,
1543 rgn1
->data
.rdh
.rcBound
.left
, rgn1
->data
.rdh
.rcBound
.top
,
1544 rgn1
->data
.rdh
.rcBound
.right
, rgn1
->data
.rdh
.rcBound
.bottom
);
1546 ok(EqualRect(&rgn1
->data
.rdh
.rcBound
, rc
), "rects don't match\n");
1548 rect
= *(const RECT
*)rgn1
->data
.Buffer
;
1549 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1550 ok(EqualRect(&rect
, rc
), "rects don't match\n");
1552 ok(rgn1
->data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn1
->data
.rdh
.dwSize
);
1553 ok(rgn1
->data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn1
->data
.rdh
.iType
);
1554 ok(rgn1
->data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn1
->data
.rdh
.nCount
);
1555 ok(rgn1
->data
.rdh
.nRgnSize
== sizeof(RECT
), "expected sizeof(RECT), got %u\n", rgn1
->data
.rdh
.nRgnSize
);
1557 hrgn
= CreateRectRgn(0, 0, 0, 0);
1559 memset(&xform
, 0, sizeof(xform
));
1560 SetLastError(0xdeadbeef);
1561 ret
= GetWorldTransform(hdc
, &xform
);
1562 is_win9x
= !ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
;
1564 ok(ret
, "GetWorldTransform error %u\n", GetLastError());
1566 trace("xform.eM11 %f, xform.eM22 %f\n", xform
.eM11
, xform
.eM22
);
1568 ret
= GetClipRgn(hdc
, hrgn
);
1569 ok(ret
== 0, "GetClipRgn returned %d, expected 0\n", ret
);
1571 PlayEnhMetaFileRecord(hdc
, handle_table
, emr
, n_objs
);
1573 ret
= GetClipRgn(hdc
, hrgn
);
1574 ok(ret
== 1, "GetClipRgn returned %d, expected 0\n", ret
);
1576 /* Win9x returns empty clipping region */
1577 if (is_win9x
) return 1;
1579 ret
= GetRegionData(hrgn
, 0, NULL
);
1580 ok(ret
== sizeof(rgn2
.data
.rdh
) + sizeof(RECT
), "expected sizeof(rgn), got %u\n", ret
);
1582 ret
= GetRegionData(hrgn
, sizeof(rgn2
), &rgn2
.data
);
1584 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1585 rgn2
.data
.rdh
.dwSize
, rgn2
.data
.rdh
.iType
,
1586 rgn2
.data
.rdh
.nCount
, rgn2
.data
.rdh
.nRgnSize
,
1587 rgn2
.data
.rdh
.rcBound
.left
, rgn2
.data
.rdh
.rcBound
.top
,
1588 rgn2
.data
.rdh
.rcBound
.right
, rgn2
.data
.rdh
.rcBound
.bottom
);
1590 rect
= rgn2
.data
.rdh
.rcBound
;
1591 rc_transformed
= *rc
;
1592 translate((POINT
*)&rc_transformed
, 2, &xform
);
1593 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
1594 rc_transformed
.right
, rc_transformed
.bottom
);
1595 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
1597 rect
= *(const RECT
*)rgn2
.data
.Buffer
;
1598 trace("rect (%d,%d-%d,%d)\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
1599 rc_transformed
= *rc
;
1600 translate((POINT
*)&rc_transformed
, 2, &xform
);
1601 trace("transformed (%d,%d-%d,%d)\n", rc_transformed
.left
, rc_transformed
.top
,
1602 rc_transformed
.right
, rc_transformed
.bottom
);
1603 ok(is_equal_rect(&rect
, &rc_transformed
), "rects don't match\n");
1605 ok(rgn2
.data
.rdh
.dwSize
== sizeof(rgn1
->data
.rdh
), "expected sizeof(rdh), got %u\n", rgn2
.data
.rdh
.dwSize
);
1606 ok(rgn2
.data
.rdh
.iType
== RDH_RECTANGLES
, "expected RDH_RECTANGLES, got %u\n", rgn2
.data
.rdh
.iType
);
1607 ok(rgn2
.data
.rdh
.nCount
== 1, "expected 1, got %u\n", rgn2
.data
.rdh
.nCount
);
1608 ok(rgn2
.data
.rdh
.nRgnSize
== sizeof(RECT
), "expected sizeof(RECT), got %u\n", rgn2
.data
.rdh
.nRgnSize
);
1615 static void test_emf_clipping(void)
1617 static const RECT rc
= { 0, 0, 100, 100 };
1618 RECT rc_clip
= { 100, 100, 1024, 1024 };
1625 SetLastError(0xdeadbeef);
1626 hdc
= CreateEnhMetaFileA(0, NULL
, NULL
, NULL
);
1627 ok(hdc
!= 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1629 /* Need to write something to the emf, otherwise Windows won't play it back */
1632 hrgn
= CreateRectRgn(rc_clip
.left
, rc_clip
.top
, rc_clip
.right
, rc_clip
.bottom
);
1633 ret
= SelectClipRgn(hdc
, hrgn
);
1634 ok(ret
== SIMPLEREGION
, "expected SIMPLEREGION, got %d\n", ret
);
1636 SetLastError(0xdeadbeef);
1637 hemf
= CloseEnhMetaFile(hdc
);
1638 ok(hemf
!= 0, "CloseEnhMetaFile error %d\n", GetLastError());
1640 if (compare_emf_bits(hemf
, EMF_CLIPPING
, sizeof(EMF_CLIPPING
),
1641 "emf_clipping", FALSE
) != 0)
1643 dump_emf_bits(hemf
, "emf_clipping");
1644 dump_emf_records(hemf
, "emf_clipping");
1649 /* Win9x doesn't play EMFs on invisible windows */
1650 hwnd
= CreateWindowExA(0, "static", NULL
, WS_POPUP
| WS_VISIBLE
,
1651 0, 0, 200, 200, 0, 0, 0, NULL
);
1652 ok(hwnd
!= 0, "CreateWindowExA error %d\n", GetLastError());
1656 ret
= EnumEnhMetaFile(hdc
, hemf
, clip_emf_enum_proc
, &rc_clip
, &rc
);
1657 ok(ret
, "EnumEnhMetaFile error %d\n", GetLastError());
1659 DeleteEnhMetaFile(hemf
);
1660 ReleaseDC(hwnd
, hdc
);
1661 DestroyWindow(hwnd
);
1664 static INT CALLBACK
EmfEnumProc(HDC hdc
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
, INT nObj
, LPARAM lpData
)
1666 LPMETAFILEPICT lpMFP
= (LPMETAFILEPICT
)lpData
;
1667 POINT mapping
[2] = { { 0, 0 }, { 10, 10 } };
1668 /* When using MM_TEXT Win9x does not update the mapping mode
1669 * until a record is played which actually outputs something */
1670 PlayEnhMetaFileRecord(hdc
, lpHTable
, lpEMFR
, nObj
);
1671 LPtoDP(hdc
, mapping
, 2);
1672 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1673 lpEMFR
->iType
, lpEMFR
->nSize
,
1674 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
);
1676 if (lpEMFR
->iType
== EMR_LINETO
)
1679 if (!lpMFP
|| lpMFP
->mm
== MM_TEXT
)
1683 x1
= (INT
)floor(10 * 100.0 / LINE_X
+ 0.5);
1684 y1
= (INT
)floor(10 * 100.0 / LINE_Y
+ 0.5);
1688 ok(lpMFP
->mm
== MM_ANISOTROPIC
, "mm=%d\n", lpMFP
->mm
);
1690 x0
= MulDiv(0, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
1691 y0
= MulDiv(0, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
1692 x1
= MulDiv(10, GetDeviceCaps(hdc
, HORZSIZE
) * 100, GetDeviceCaps(hdc
, HORZRES
));
1693 y1
= MulDiv(10, GetDeviceCaps(hdc
, VERTSIZE
) * 100, GetDeviceCaps(hdc
, VERTRES
));
1695 ok(mapping
[0].x
== x0
&& mapping
[0].y
== y0
&& mapping
[1].x
== x1
&& mapping
[1].y
== y1
,
1696 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1697 mapping
[0].x
, mapping
[0].y
, mapping
[1].x
, mapping
[1].y
,
1703 static HENHMETAFILE
create_converted_emf(const METAFILEPICT
*mfp
)
1712 hdcMf
= CreateMetaFile(NULL
);
1713 ok(hdcMf
!= NULL
, "CreateMetaFile failed with error %d\n", GetLastError());
1714 ret
= LineTo(hdcMf
, (INT
)LINE_X
, (INT
)LINE_Y
);
1715 ok(ret
, "LineTo failed with error %d\n", GetLastError());
1716 hmf
= CloseMetaFile(hdcMf
);
1717 ok(hmf
!= NULL
, "CloseMetaFile failed with error %d\n", GetLastError());
1719 if (compare_mf_bits (hmf
, MF_LINETO_BITS
, sizeof(MF_LINETO_BITS
), "mf_LineTo") != 0)
1721 dump_mf_bits(hmf
, "mf_LineTo");
1722 EnumMetaFile(0, hmf
, mf_enum_proc
, 0);
1725 size
= GetMetaFileBitsEx(hmf
, 0, NULL
);
1726 ok(size
, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1727 pBits
= HeapAlloc(GetProcessHeap(), 0, size
);
1728 GetMetaFileBitsEx(hmf
, size
, pBits
);
1729 DeleteMetaFile(hmf
);
1730 hemf
= SetWinMetaFileBits(size
, pBits
, NULL
, mfp
);
1731 HeapFree(GetProcessHeap(), 0, pBits
);
1735 static void test_mf_conversions(void)
1737 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1739 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
1742 RECT rect
= { 0, 0, 100, 100 };
1743 mfp
.mm
= MM_ANISOTROPIC
;
1747 hemf
= create_converted_emf(&mfp
);
1749 if (compare_emf_bits(hemf
, EMF_LINETO_MM_ANISOTROPIC_BITS
, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS
),
1750 "emf_LineTo MM_ANISOTROPIC", TRUE
) != 0)
1752 dump_emf_bits(hemf
, "emf_LineTo MM_ANISOTROPIC");
1753 dump_emf_records(hemf
, "emf_LineTo MM_ANISOTROPIC");
1756 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
1758 DeleteEnhMetaFile(hemf
);
1759 DeleteDC(hdcOffscreen
);
1762 trace("Testing MF->EMF conversion (MM_TEXT)\n");
1764 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
1767 RECT rect
= { 0, 0, 100, 100 };
1772 hemf
= create_converted_emf(&mfp
);
1774 if (compare_emf_bits(hemf
, EMF_LINETO_MM_TEXT_BITS
, sizeof(EMF_LINETO_MM_TEXT_BITS
),
1775 "emf_LineTo MM_TEXT", TRUE
) != 0)
1777 dump_emf_bits(hemf
, "emf_LineTo MM_TEXT");
1778 dump_emf_records(hemf
, "emf_LineTo MM_TEXT");
1781 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, &mfp
, &rect
);
1783 DeleteEnhMetaFile(hemf
);
1784 DeleteDC(hdcOffscreen
);
1787 trace("Testing MF->EMF conversion (NULL mfp)\n");
1789 HDC hdcOffscreen
= CreateCompatibleDC(NULL
);
1791 RECT rect
= { 0, 0, 100, 100 };
1792 hemf
= create_converted_emf(NULL
);
1794 if (compare_emf_bits(hemf
, EMF_LINETO_BITS
, sizeof(EMF_LINETO_BITS
),
1795 "emf_LineTo NULL", TRUE
) != 0)
1797 dump_emf_bits(hemf
, "emf_LineTo NULL");
1798 dump_emf_records(hemf
, "emf_LineTo NULL");
1801 EnumEnhMetaFile(hdcOffscreen
, hemf
, EmfEnumProc
, NULL
, &rect
);
1803 DeleteEnhMetaFile(hemf
);
1804 DeleteDC(hdcOffscreen
);
1808 static BOOL
getConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
1809 LONG mm
, LONG xExt
, LONG yExt
,
1810 RECTL
* rclBounds
, RECTL
* rclFrame
)
1813 METAFILEPICT
* mfpPtr
= NULL
;
1815 ENHMETAHEADER header
;
1826 emf
= SetWinMetaFileBits(buffer_size
, buffer
, NULL
, mfpPtr
);
1827 ok(emf
!= NULL
, "SetWinMetaFileBits failed\n");
1828 if (!emf
) return FALSE
;
1829 res
= GetEnhMetaFileHeader(emf
, sizeof(header
), &header
);
1830 ok(res
!= 0, "GetEnhMetaHeader failed\n");
1831 DeleteEnhMetaFile(emf
);
1832 if (!res
) return FALSE
;
1834 *rclBounds
= header
.rclBounds
;
1835 *rclFrame
= header
.rclFrame
;
1839 static void checkConvertedFrameAndBounds(UINT buffer_size
, BYTE
* buffer
, BOOL mfpIsNull
,
1840 LONG mm
, LONG xExt
, LONG yExt
,
1841 RECTL
* rclBoundsExpected
, RECTL
* rclFrameExpected
)
1843 RECTL rclBounds
, rclFrame
;
1845 if (getConvertedFrameAndBounds(buffer_size
, buffer
, mfpIsNull
, mm
, xExt
, yExt
, &rclBounds
, &rclFrame
))
1852 msg
= "mfp == NULL";
1856 const char * mm_str
;
1859 case MM_ANISOTROPIC
: mm_str
= "MM_ANISOTROPIC"; break;
1860 case MM_ISOTROPIC
: mm_str
= "MM_ISOTROPIC"; break;
1861 default: mm_str
= "Unexpected";
1863 sprintf(buf
, "mm=%s, xExt=%d, yExt=%d", mm_str
, xExt
, yExt
);
1867 ok(rclBounds
.left
== rclBoundsExpected
->left
, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected
->left
, rclBounds
.left
, msg
);
1868 ok(rclBounds
.top
== rclBoundsExpected
->top
, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected
->top
, rclBounds
.top
, msg
);
1869 ok(rclBounds
.right
== rclBoundsExpected
->right
, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected
->right
, rclBounds
.right
, msg
);
1870 ok(rclBounds
.bottom
== rclBoundsExpected
->bottom
, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected
->bottom
, rclBounds
.bottom
, msg
);
1871 ok(rclFrame
.left
== rclFrameExpected
->left
, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected
->left
, rclFrame
.left
, msg
);
1872 ok(rclFrame
.top
== rclFrameExpected
->top
, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected
->top
, rclFrame
.top
, msg
);
1873 ok(rclFrame
.right
== rclFrameExpected
->right
, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected
->right
, rclFrame
.right
, msg
);
1874 ok(rclFrame
.bottom
== rclFrameExpected
->bottom
, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected
->bottom
, rclFrame
.bottom
, msg
);
1878 static void test_SetWinMetaFileBits(void)
1886 RECTL rclBoundsAnisotropic
, rclFrameAnisotropic
;
1887 RECTL rclBoundsIsotropic
, rclFrameIsotropic
;
1888 RECTL rclBounds
, rclFrame
;
1892 wmfDC
= CreateMetaFile(NULL
);
1893 ok(wmfDC
!= NULL
, "CreateMetaFile failed\n");
1896 SetWindowExtEx(wmfDC
, 100, 100, NULL
);
1897 rect
.left
= rect
.top
= 0;
1898 rect
.right
= rect
.bottom
= 50;
1899 FillRect(wmfDC
, &rect
, GetStockObject(BLACK_BRUSH
));
1900 wmf
= CloseMetaFile(wmfDC
);
1901 ok(wmf
!= NULL
, "Metafile creation failed\n");
1904 buffer_size
= GetMetaFileBitsEx(wmf
, 0, NULL
);
1905 ok(buffer_size
!= 0, "GetMetaFileBitsEx failed\n");
1906 if (buffer_size
== 0)
1908 DeleteMetaFile(wmf
);
1912 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_size
);
1913 ok(buffer
!= NULL
, "HeapAlloc failed\n");
1916 DeleteMetaFile(wmf
);
1920 res
= GetMetaFileBitsEx(wmf
, buffer_size
, buffer
);
1921 ok(res
== buffer_size
, "GetMetaFileBitsEx failed\n");
1922 DeleteMetaFile(wmf
);
1923 if (res
!= buffer_size
)
1925 HeapFree(GetProcessHeap(), 0, buffer
);
1929 /* Get the reference bounds and frame */
1930 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1931 getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1933 ok(rclBoundsAnisotropic
.left
== 0 && rclBoundsAnisotropic
.top
== 0 &&
1934 rclBoundsIsotropic
.left
== 0 && rclBoundsIsotropic
.top
== 0,
1935 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1937 ok(rclBoundsAnisotropic
.right
>= rclBoundsIsotropic
.right
, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1938 ok(rclBoundsAnisotropic
.bottom
>= rclBoundsIsotropic
.bottom
, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1939 diffx
= rclBoundsIsotropic
.right
- rclBoundsIsotropic
.bottom
;
1940 if (diffx
< 0) diffx
= -diffx
;
1941 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1943 dc
= CreateCompatibleDC(NULL
);
1945 /* Allow 1 mm difference (rounding errors) */
1946 diffx
= rclBoundsAnisotropic
.right
- GetDeviceCaps(dc
, HORZRES
) / 2;
1947 diffy
= rclBoundsAnisotropic
.bottom
- GetDeviceCaps(dc
, VERTRES
) / 2;
1948 if (diffx
< 0) diffx
= -diffx
;
1949 if (diffy
< 0) diffy
= -diffy
;
1952 ok(diffx
<= 1 && diffy
<= 1,
1953 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1954 GetDeviceCaps(dc
, HORZRES
) / 2, GetDeviceCaps(dc
, VERTRES
) / 2, rclBoundsAnisotropic
.right
, rclBoundsAnisotropic
.bottom
);
1957 /* Allow 1 mm difference (rounding errors) */
1958 diffx
= rclFrameAnisotropic
.right
/ 100 - GetDeviceCaps(dc
, HORZSIZE
) / 2;
1959 diffy
= rclFrameAnisotropic
.bottom
/ 100 - GetDeviceCaps(dc
, VERTSIZE
) / 2;
1960 if (diffx
< 0) diffx
= -diffx
;
1961 if (diffy
< 0) diffy
= -diffy
;
1964 ok(diffx
<= 1 && diffy
<= 1,
1965 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1966 GetDeviceCaps(dc
, HORZSIZE
) / 2, GetDeviceCaps(dc
, VERTSIZE
) / 2, rclFrameAnisotropic
.right
/ 100, rclFrameAnisotropic
.bottom
/ 100);
1970 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1971 checkConvertedFrameAndBounds(buffer_size
, buffer
, TRUE
, 0, 0, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1973 /* If xExt or yExt is zero or negative, the whole device surface is used */
1974 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1975 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1976 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1977 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1978 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 0, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1979 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 0, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1980 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 0, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1981 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 0, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1982 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -10000, 10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1983 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -10000, 10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1984 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 10000, -10000, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1985 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 10000, -10000, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1987 /* MSDN says that negative xExt and yExt values specify a ratio.
1988 Check that this is wrong and the whole device surface is used */
1989 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, -1000, -100, &rclBoundsAnisotropic
, &rclFrameAnisotropic
);
1990 checkConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, -1000, -100, &rclBoundsIsotropic
, &rclFrameIsotropic
);
1992 /* Ordinary conversions */
1994 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ANISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
1996 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
1997 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
1998 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0 && rclBounds
.right
> rclBounds
.bottom
,
1999 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2002 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_ISOTROPIC
, 30000, 20000, &rclBounds
, &rclFrame
))
2004 ok(rclFrame
.left
== 0 && rclFrame
.top
== 0 && rclFrame
.right
== 30000 && rclFrame
.bottom
== 20000,
2005 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2006 ok(rclBounds
.left
== 0 && rclBounds
.top
== 0,
2007 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2009 /* Wine has a rounding error */
2010 diffx
= rclBounds
.right
- rclBounds
.bottom
;
2011 if (diffx
< 0) diffx
= -diffx
;
2012 ok(diffx
<= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2015 if (getConvertedFrameAndBounds(buffer_size
, buffer
, FALSE
, MM_HIMETRIC
, 30000, 20000, &rclBounds
, &rclFrame
))
2017 ok(rclFrame
.right
- rclFrame
.left
!= 30000 && rclFrame
.bottom
- rclFrame
.top
!= 20000,
2018 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2021 HeapFree(GetProcessHeap(), 0, buffer
);
2024 static BOOL (WINAPI
*pGdiIsMetaPrintDC
)(HDC
);
2025 static BOOL (WINAPI
*pGdiIsMetaFileDC
)(HDC
);
2026 static BOOL (WINAPI
*pGdiIsPlayMetafileDC
)(HDC
);
2028 static void test_gdiis(void)
2030 RECT rect
= {0,0,100,100};
2031 HDC hdc
, hemfDC
, hmfDC
;
2035 /* resolve all the functions */
2036 hgdi32
= GetModuleHandle("gdi32");
2037 pGdiIsMetaPrintDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaPrintDC");
2038 pGdiIsMetaFileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsMetaFileDC");
2039 pGdiIsPlayMetafileDC
= (void*) GetProcAddress(hgdi32
, "GdiIsPlayMetafileDC");
2041 if(!pGdiIsMetaPrintDC
|| !pGdiIsMetaFileDC
|| !pGdiIsPlayMetafileDC
)
2043 win_skip("Needed GdiIs* functions are not available\n");
2047 /* try with nothing */
2048 ok(!pGdiIsMetaPrintDC(NULL
), "ismetaprint with NULL parameter\n");
2049 ok(!pGdiIsMetaFileDC(NULL
), "ismetafile with NULL parameter\n");
2050 ok(!pGdiIsPlayMetafileDC(NULL
), "isplaymetafile with NULL parameter\n");
2052 /* try with a metafile */
2053 hmfDC
= CreateMetaFile(NULL
);
2054 ok(!pGdiIsMetaPrintDC(hmfDC
), "ismetaprint on metafile\n");
2055 ok(pGdiIsMetaFileDC(hmfDC
), "ismetafile on metafile\n");
2056 ok(!pGdiIsPlayMetafileDC(hmfDC
), "isplaymetafile on metafile\n");
2057 DeleteMetaFile(CloseMetaFile(hmfDC
));
2059 /* try with an enhanced metafile */
2061 hemfDC
= CreateEnhMetaFileW(hdc
, NULL
, &rect
, NULL
);
2062 ok(hemfDC
!= NULL
, "failed to create emf\n");
2064 ok(!pGdiIsMetaPrintDC(hemfDC
), "ismetaprint on emf\n");
2065 ok(pGdiIsMetaFileDC(hemfDC
), "ismetafile on emf\n");
2066 ok(!pGdiIsPlayMetafileDC(hemfDC
), "isplaymetafile on emf\n");
2068 hemf
= CloseEnhMetaFile(hemfDC
);
2069 ok(hemf
!= NULL
, "failed to close EMF\n");
2070 DeleteEnhMetaFile(hemf
);
2071 ReleaseDC(NULL
,hdc
);
2074 static void test_SetEnhMetaFileBits(void)
2080 memset(data
, 0xAA, sizeof(data
));
2081 SetLastError(0xdeadbeef);
2082 hemf
= SetEnhMetaFileBits(sizeof(data
), data
);
2083 ok(!hemf
, "SetEnhMetaFileBits should fail\n");
2084 ok(GetLastError() == ERROR_INVALID_DATA
||
2085 GetLastError() == ERROR_INVALID_PARAMETER
, /* Win9x, WinMe */
2086 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2088 emh
= (ENHMETAHEADER
*)data
;
2089 memset(emh
, 0, sizeof(*emh
));
2091 emh
->iType
= EMR_HEADER
;
2092 emh
->nSize
= sizeof(*emh
);
2093 emh
->dSignature
= ENHMETA_SIGNATURE
;
2094 /* emh->nVersion = 0x10000; XP doesn't care about version */
2095 emh
->nBytes
= sizeof(*emh
);
2096 /* emh->nRecords = 1; XP doesn't care about records */
2097 emh
->nHandles
= 1; /* XP refuses to load a EMF if nHandles == 0 */
2099 SetLastError(0xdeadbeef);
2100 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
2101 ok(hemf
!= 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2102 DeleteEnhMetaFile(hemf
);
2104 /* XP refuses to load unaligned EMF */
2106 SetLastError(0xdeadbeef);
2107 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
2109 broken(hemf
!= NULL
), /* Win9x, WinMe */
2110 "SetEnhMetaFileBits should fail\n");
2112 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2113 DeleteEnhMetaFile(hemf
);
2115 emh
->dSignature
= 0;
2117 SetLastError(0xdeadbeef);
2118 hemf
= SetEnhMetaFileBits(emh
->nBytes
, data
);
2120 broken(hemf
!= NULL
), /* Win9x, WinMe */
2121 "SetEnhMetaFileBits should fail\n");
2123 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2124 DeleteEnhMetaFile(hemf
);
2127 START_TEST(metafile
)
2129 init_function_pointers();
2131 /* For enhanced metafiles (enhmfdrv) */
2135 /* For win-format metafiles (mfdrv) */
2138 test_mf_PatternBrush();
2139 test_CopyMetaFile();
2140 test_SetMetaFileBits();
2141 test_mf_ExtTextOut_on_path();
2142 test_emf_ExtTextOut_on_path();
2143 test_emf_clipping();
2145 /* For metafile conversions */
2146 test_mf_conversions();
2147 test_SetWinMetaFileBits();
2150 test_SetEnhMetaFileBits();