gdi32/tests: Add a test for GetGlyphOutline with an insufficient buffer.
[wine/multimedia.git] / dlls / gdi32 / tests / metafile.c
blob1b0d34bb5f2eb6a2d60581832b0faef300db1215
1 /*
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
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.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 */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
40 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
41 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
43 #define GDI_GET_PROC(func) \
44 p ## func = (void *)GetProcAddress(hGDI, #func); \
45 if(!p ## func) \
46 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
48 static void init_function_pointers(void)
50 HMODULE hGDI;
52 pGetRelAbs = NULL;
53 pSetRelAbs = NULL;
55 hGDI = GetModuleHandleA("gdi32.dll");
56 assert(hGDI);
57 GDI_GET_PROC(GetRelAbs);
58 GDI_GET_PROC(SetRelAbs);
59 GDI_GET_PROC(SetDCBrushColor);
60 GDI_GET_PROC(SetDCPenColor);
63 static DWORD rgn_rect_count(HRGN hrgn)
65 DWORD size;
66 RGNDATA *data;
68 if (!hrgn) return 0;
69 if (!(size = GetRegionData(hrgn, 0, NULL))) return 0;
70 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0;
71 GetRegionData(hrgn, size, data);
72 size = data->rdh.nCount;
73 HeapFree(GetProcessHeap(), 0, data);
74 return size;
77 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
78 const ENHMETARECORD *emr, int n_objs, LPARAM param)
80 static int n_record;
81 DWORD i;
82 const INT *dx;
83 INT *orig_dx = (INT *)param;
84 LOGFONTA device_lf;
85 INT ret;
87 if(!hdc) return 1;
89 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
91 switch (emr->iType)
93 case EMR_HEADER:
94 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
95 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
96 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
97 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
98 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
99 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
100 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
102 /* GetBkMode, GetRelAbs do not get reset to the default value */
103 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
104 if(pSetRelAbs && pGetRelAbs)
105 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
107 n_record = 0;
108 break;
110 case EMR_EXTTEXTOUTA:
112 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
113 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
115 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
116 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
118 /* compare up to lfOutPrecision, other values are not interesting,
119 * and in fact sometimes arbitrary adapted by Win9x.
121 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
122 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
124 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
126 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
127 n_record, i, dx[i], orig_dx[i]);
129 n_record++;
130 emr_processed = TRUE;
131 break;
134 case EMR_EXTTEXTOUTW:
136 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
137 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
139 SetLastError(0xdeadbeef);
140 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
141 ok( ret == sizeof(device_lf) ||
142 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
143 "GetObjectA error %d\n", GetLastError());
145 /* compare up to lfOutPrecision, other values are not interesting,
146 * and in fact sometimes arbitrary adapted by Win9x.
148 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
149 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
151 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
153 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
154 n_record, i, dx[i], orig_dx[i]);
156 n_record++;
157 emr_processed = TRUE;
158 break;
161 default:
162 break;
165 return 1;
168 static void test_ExtTextOut(void)
170 HWND hwnd;
171 HDC hdcDisplay, hdcMetafile;
172 HENHMETAFILE hMetafile;
173 HFONT hFont;
174 static const char text[] = "Simple text to test ExtTextOut on metafiles";
175 INT i, len, dx[256];
176 static const RECT rc = { 0, 0, 100, 100 };
177 BOOL ret;
179 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
181 /* Win9x doesn't play EMFs on invisible windows */
182 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
183 0, 0, 200, 200, 0, 0, 0, NULL);
184 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
186 hdcDisplay = GetDC(hwnd);
187 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
189 trace("hdcDisplay %p\n", hdcDisplay);
191 SetMapMode(hdcDisplay, MM_TEXT);
193 memset(&orig_lf, 0, sizeof(orig_lf));
195 orig_lf.lfCharSet = ANSI_CHARSET;
196 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
197 orig_lf.lfWeight = FW_DONTCARE;
198 orig_lf.lfHeight = 7;
199 orig_lf.lfQuality = DEFAULT_QUALITY;
200 lstrcpyA(orig_lf.lfFaceName, "Arial");
201 hFont = CreateFontIndirectA(&orig_lf);
202 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
204 hFont = SelectObject(hdcDisplay, hFont);
206 len = lstrlenA(text);
207 for (i = 0; i < len; i++)
209 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
210 ok( ret, "GetCharWidthA error %d\n", GetLastError());
212 hFont = SelectObject(hdcDisplay, hFont);
214 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
215 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
217 trace("hdcMetafile %p\n", hdcMetafile);
219 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
220 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
222 hFont = SelectObject(hdcMetafile, hFont);
224 /* 1. pass NULL lpDx */
225 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
226 ok( ret, "ExtTextOutA error %d\n", GetLastError());
228 /* 2. pass custom lpDx */
229 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
230 ok( ret, "ExtTextOutA error %d\n", GetLastError());
232 hFont = SelectObject(hdcMetafile, hFont);
233 ret = DeleteObject(hFont);
234 ok( ret, "DeleteObject error %d\n", GetLastError());
236 hMetafile = CloseEnhMetaFile(hdcMetafile);
237 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
239 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
241 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
242 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
244 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
245 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
246 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
247 SetROP2(hdcDisplay, R2_NOT);
248 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
249 SetPolyFillMode(hdcDisplay, WINDING);
250 SetStretchBltMode(hdcDisplay, HALFTONE);
252 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
253 SetBkMode(hdcDisplay, OPAQUE);
255 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
256 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
258 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
259 "text align %08x\n", GetTextAlign(hdcDisplay));
260 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
261 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
262 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
263 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
264 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
265 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
267 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
269 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
270 "A valid hdc has to require a valid rc\n");
272 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
273 "A null hdc does not require a valid rc\n");
275 ret = DeleteEnhMetaFile(hMetafile);
276 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
277 ret = ReleaseDC(hwnd, hdcDisplay);
278 ok( ret, "ReleaseDC error %d\n", GetLastError());
279 DestroyWindow(hwnd);
282 struct eto_scale_test_record
284 INT graphics_mode;
285 INT map_mode;
286 double ex_scale;
287 double ey_scale;
288 BOOL processed;
291 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
292 const ENHMETARECORD *emr, int n_objs, LPARAM param)
294 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
296 if (emr->iType == EMR_EXTTEXTOUTW)
298 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
299 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
300 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
301 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
302 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
303 test->processed = TRUE;
306 return 1;
309 static void test_ExtTextOutScale(void)
311 const RECT rc = { 0, 0, 100, 100 };
312 const WCHAR str[] = {'a',0 };
313 struct eto_scale_test_record test;
314 HDC hdcDisplay, hdcMetafile;
315 HENHMETAFILE hMetafile;
316 HWND hwnd;
317 SIZE wndext, vportext;
318 int horzSize, vertSize, horzRes, vertRes;
319 int ret;
320 int i;
322 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
323 0, 0, 200, 200, 0, 0, 0, NULL);
324 ok(hwnd != 0, "CreateWindowExA failed\n");
326 hdcDisplay = GetDC(hwnd);
327 ok(hdcDisplay != 0, "GetDC failed\n");
329 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
330 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
331 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
332 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
333 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
335 for (i = 0; i < 16; i++)
337 test.graphics_mode = i / 8 + 1;
338 test.map_mode = i % 8 + 1;
340 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
341 ok(ret, "SetGraphicsMode failed\n");
342 ret = SetMapMode(hdcDisplay, test.map_mode);
343 ok(ret, "SetMapMode failed\n");
345 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
347 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
348 ok(ret, "SetWindowExtEx failed\n");
349 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
350 ok(ret, "SetViewportExtEx failed\n");
353 ret = GetViewportExtEx(hdcDisplay, &vportext);
354 ok(ret, "GetViewportExtEx failed\n");
355 ret = GetWindowExtEx(hdcDisplay, &wndext);
356 ok(ret, "GetWindowExtEx failed\n");
358 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
359 test.graphics_mode, test.map_mode,
360 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
361 horzSize, horzRes, vertSize, vertRes);
363 if (test.graphics_mode == GM_COMPATIBLE)
365 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
366 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
367 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
368 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
370 else
372 test.ex_scale = 0.0;
373 test.ey_scale = 0.0;
376 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
377 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
379 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
380 ok(ret, "SetGraphicsMode failed\n");
381 ret = SetMapMode(hdcMetafile, test.map_mode);
382 ok(ret, "SetMapMode failed\n");
384 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
386 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
387 ok(ret, "SetWindowExtEx failed\n");
388 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
389 ok(ret, "SetViewportExtEx failed\n");
392 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
393 ok(ret, "ExtTextOutW failed\n");
395 hMetafile = CloseEnhMetaFile(hdcMetafile);
396 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
398 test.processed = 0;
399 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
400 ok(ret, "EnumEnhMetaFile failed\n");
401 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
403 ret = DeleteEnhMetaFile(hMetafile);
404 ok(ret, "DeleteEnhMetaFile failed\n");
407 ret = ReleaseDC(hwnd, hdcDisplay);
408 ok(ret, "ReleaseDC failed\n");
409 DestroyWindow(hwnd);
413 static void check_dc_state(HDC hdc, int restore_no,
414 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
415 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
417 BOOL ret;
418 XFORM xform;
419 POINT vp_org, win_org;
420 SIZE vp_size, win_size;
421 FLOAT xscale, yscale, edx, edy;
423 SetLastError(0xdeadbeef);
424 ret = GetWorldTransform(hdc, &xform);
425 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
426 ok(ret, "GetWorldTransform error %u\n", GetLastError());
428 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
430 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
431 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
433 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
434 trace("x scale %f\n", xscale);
435 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
436 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
438 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
439 trace("y scale %f\n", yscale);
440 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
441 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
443 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
444 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
445 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
446 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
448 return;
450 win9x_here:
452 GetWindowOrgEx(hdc, &win_org);
453 GetViewportOrgEx(hdc, &vp_org);
454 GetWindowExtEx(hdc, &win_size);
455 GetViewportExtEx(hdc, &vp_size);
457 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
458 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
460 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
461 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
463 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
464 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
466 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
467 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
470 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
471 const ENHMETARECORD *emr, int n_objs, LPARAM param)
473 BOOL ret;
474 XFORM xform;
475 POINT pt;
476 SIZE size;
477 static int save_state;
478 static int restore_no;
479 static int select_no;
481 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
482 hdc, emr->iType, emr->nSize, (void *)param);
484 SetLastError(0xdeadbeef);
485 ret = GetWorldTransform(hdc, &xform);
486 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
488 ret = GetWindowOrgEx(hdc, &pt);
489 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
490 trace("window org (%d,%d)\n", pt.x, pt.y);
491 ret = GetViewportOrgEx(hdc, &pt);
492 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
493 trace("vport org (%d,%d)\n", pt.x, pt.y);
494 ret = GetWindowExtEx(hdc, &size);
495 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
496 trace("window ext (%d,%d)\n", size.cx, size.cy);
497 ret = GetViewportExtEx(hdc, &size);
498 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
499 trace("vport ext (%d,%d)\n", size.cx, size.cy);
501 else
503 ok(ret, "GetWorldTransform error %u\n", GetLastError());
504 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
507 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
509 switch (emr->iType)
511 case EMR_HEADER:
513 static RECT exp_bounds = { 0, 0, 150, 150 };
514 RECT bounds;
515 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
517 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
518 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
519 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
520 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
521 emf->szlDevice.cx, emf->szlDevice.cy);
523 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
524 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
526 save_state = 0;
527 restore_no = 0;
528 select_no = 0;
529 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
530 break;
533 case EMR_LINETO:
535 const EMRLINETO *line = (const EMRLINETO *)emr;
536 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
537 break;
539 case EMR_SETWINDOWORGEX:
541 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
542 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
543 break;
545 case EMR_SETWINDOWEXTEX:
547 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
548 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
549 break;
551 case EMR_SETVIEWPORTORGEX:
553 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
554 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
555 break;
557 case EMR_SETVIEWPORTEXTEX:
559 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
560 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
561 break;
563 case EMR_SAVEDC:
564 save_state++;
565 trace("EMR_SAVEDC\n");
566 break;
568 case EMR_RESTOREDC:
570 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
571 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
573 switch(++restore_no)
575 case 1:
576 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
577 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
578 break;
579 case 2:
580 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
581 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
582 break;
583 case 3:
584 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
585 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
586 break;
588 ok(restore_no <= 3, "restore_no %d\n", restore_no);
589 save_state += restoredc->iRelative;
590 break;
592 case EMR_SELECTOBJECT:
594 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
595 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
596 select_no ++;
597 break;
599 case EMR_EOF:
600 ok(save_state == 0, "EOF save_state %d\n", save_state);
601 ok(select_no == 3, "Too many/few selects %i\n",select_no);
602 break;
605 SetLastError(0xdeadbeef);
606 ret = GetWorldTransform(hdc, &xform);
607 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
609 ret = GetWindowOrgEx(hdc, &pt);
610 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
611 trace("window org (%d,%d)\n", pt.x, pt.y);
612 ret = GetViewportOrgEx(hdc, &pt);
613 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
614 trace("vport org (%d,%d)\n", pt.x, pt.y);
615 ret = GetWindowExtEx(hdc, &size);
616 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
617 trace("window ext (%d,%d)\n", size.cx, size.cy);
618 ret = GetViewportExtEx(hdc, &size);
619 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
620 trace("vport ext (%d,%d)\n", size.cx, size.cy);
622 else
624 ok(ret, "GetWorldTransform error %u\n", GetLastError());
625 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
628 return 1;
631 static void test_SaveDC(void)
633 HDC hdcMetafile, hdcDisplay;
634 HENHMETAFILE hMetafile;
635 HWND hwnd;
636 int ret;
637 POINT pt;
638 SIZE size;
639 HFONT hFont,hFont2,hFontOld,hFontCheck;
640 static const RECT rc = { 0, 0, 150, 150 };
642 /* Win9x doesn't play EMFs on invisible windows */
643 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
644 0, 0, 200, 200, 0, 0, 0, NULL);
645 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
647 hdcDisplay = GetDC(hwnd);
648 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
650 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
651 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
653 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
655 /* Need to write something to the emf, otherwise Windows won't play it back */
656 LineTo(hdcMetafile, 150, 150);
658 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
659 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
660 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
661 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
663 /* Force Win9x to update DC state */
664 SetPixelV(hdcMetafile, 50, 50, 0);
666 ret = GetViewportOrgEx(hdcMetafile, &pt);
667 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
668 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
669 ret = GetViewportExtEx(hdcMetafile, &size);
670 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
671 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
672 ret = SaveDC(hdcMetafile);
673 ok(ret == 1, "ret = %d\n", ret);
675 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
676 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
677 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
678 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
680 /* Force Win9x to update DC state */
681 SetPixelV(hdcMetafile, 50, 50, 0);
683 ret = GetViewportOrgEx(hdcMetafile, &pt);
684 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
685 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
686 ret = GetViewportExtEx(hdcMetafile, &size);
687 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
688 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
689 ret = SaveDC(hdcMetafile);
690 ok(ret == 2, "ret = %d\n", ret);
692 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
693 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
694 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
695 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
696 SetPolyFillMode( hdcMetafile, ALTERNATE );
697 SetBkColor( hdcMetafile, 0 );
699 /* Force Win9x to update DC state */
700 SetPixelV(hdcMetafile, 50, 50, 0);
702 ret = GetViewportOrgEx(hdcMetafile, &pt);
703 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
704 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
705 ret = GetViewportExtEx(hdcMetafile, &size);
706 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
707 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
708 ret = SaveDC(hdcMetafile);
709 ok(ret == 3, "ret = %d\n", ret);
711 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
712 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
713 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
714 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
716 SetPolyFillMode( hdcMetafile, WINDING );
717 SetBkColor( hdcMetafile, 0x123456 );
718 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
719 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
721 /* Force Win9x to update DC state */
722 SetPixelV(hdcMetafile, 50, 50, 0);
724 ret = GetViewportOrgEx(hdcMetafile, &pt);
725 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
726 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
727 ret = GetViewportExtEx(hdcMetafile, &size);
728 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
729 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
730 ret = RestoreDC(hdcMetafile, -1);
731 ok(ret, "ret = %d\n", ret);
733 ret = GetViewportOrgEx(hdcMetafile, &pt);
734 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
735 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
736 ret = GetViewportExtEx(hdcMetafile, &size);
737 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
738 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
739 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
740 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
741 ret = SaveDC(hdcMetafile);
742 ok(ret == 3, "ret = %d\n", ret);
744 ret = GetViewportOrgEx(hdcMetafile, &pt);
745 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
746 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
747 ret = GetViewportExtEx(hdcMetafile, &size);
748 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
749 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
750 ret = RestoreDC(hdcMetafile, 1);
751 ok(ret, "ret = %d\n", ret);
752 ret = GetViewportOrgEx(hdcMetafile, &pt);
753 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
754 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
755 ret = GetViewportExtEx(hdcMetafile, &size);
756 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
757 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
759 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
760 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
761 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
762 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
764 /* Force Win9x to update DC state */
765 SetPixelV(hdcMetafile, 50, 50, 0);
767 ret = GetViewportOrgEx(hdcMetafile, &pt);
768 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
769 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
770 ret = GetViewportExtEx(hdcMetafile, &size);
771 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
772 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
773 ret = SaveDC(hdcMetafile);
774 ok(ret == 1, "ret = %d\n", ret);
776 ret = GetViewportOrgEx(hdcMetafile, &pt);
777 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
778 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
779 ret = GetViewportExtEx(hdcMetafile, &size);
780 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
781 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
782 ret = SaveDC(hdcMetafile);
783 ok(ret == 2, "ret = %d\n", ret);
785 memset(&orig_lf, 0, sizeof(orig_lf));
786 orig_lf.lfCharSet = ANSI_CHARSET;
787 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
788 orig_lf.lfWeight = FW_DONTCARE;
789 orig_lf.lfHeight = 7;
790 orig_lf.lfQuality = DEFAULT_QUALITY;
791 lstrcpyA(orig_lf.lfFaceName, "Arial");
792 hFont = CreateFontIndirectA(&orig_lf);
793 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
795 hFontOld = SelectObject(hdcMetafile, hFont);
797 hFont2 = CreateFontIndirectA(&orig_lf);
798 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
799 hFontCheck = SelectObject(hdcMetafile, hFont2);
800 ok(hFontCheck == hFont, "Font not selected\n");
802 /* Force Win9x to update DC state */
803 SetPixelV(hdcMetafile, 50, 50, 0);
805 ret = RestoreDC(hdcMetafile, 1);
806 ok(ret, "ret = %d\n", ret);
807 ret = GetViewportOrgEx(hdcMetafile, &pt);
808 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
809 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
810 ret = GetViewportExtEx(hdcMetafile, &size);
811 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
812 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
814 hFontCheck = SelectObject(hdcMetafile, hFontOld);
815 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
816 "Font not reverted with DC Restore\n");
818 ret = RestoreDC(hdcMetafile, -20);
819 ok(!ret, "ret = %d\n", ret);
820 ret = RestoreDC(hdcMetafile, 20);
821 ok(!ret, "ret = %d\n", ret);
823 hMetafile = CloseEnhMetaFile(hdcMetafile);
824 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
826 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
827 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
829 ret = DeleteObject(hFont);
830 ok( ret, "DeleteObject error %d\n", GetLastError());
831 ret = DeleteObject(hFont2);
832 ok( ret, "DeleteObject error %d\n", GetLastError());
833 ret = DeleteEnhMetaFile(hMetafile);
834 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
835 ret = ReleaseDC(hwnd, hdcDisplay);
836 ok( ret, "ReleaseDC error %d\n", GetLastError());
837 DestroyWindow(hwnd);
840 static void test_mf_SaveDC(void)
842 HDC hdcMetafile;
843 HMETAFILE hMetafile;
844 int ret;
845 POINT pt;
846 SIZE size;
847 HFONT hFont,hFont2,hFontOld,hFontCheck;
849 hdcMetafile = CreateMetaFileA(NULL);
850 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
852 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
853 ok (ret, "SetMapMode should not fail\n");
855 /* Need to write something to the emf, otherwise Windows won't play it back */
856 LineTo(hdcMetafile, 150, 150);
858 pt.x = pt.y = 5555;
859 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
860 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
861 pt.x = pt.y = 5555;
862 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
863 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
864 size.cx = size.cy = 5555;
865 SetWindowExtEx(hdcMetafile, 110, 110, &size );
866 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
867 size.cx = size.cy = 5555;
868 SetViewportExtEx(hdcMetafile, 120, 120, &size );
869 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
871 /* Force Win9x to update DC state */
872 SetPixelV(hdcMetafile, 50, 50, 0);
874 ret = GetViewportOrgEx(hdcMetafile, &pt);
875 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
876 ret = GetViewportExtEx(hdcMetafile, &size);
877 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
878 ret = SaveDC(hdcMetafile);
879 ok(ret == 1, "ret = %d\n", ret);
881 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
882 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
883 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
884 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
886 /* Force Win9x to update DC state */
887 SetPixelV(hdcMetafile, 50, 50, 0);
889 ret = SaveDC(hdcMetafile);
890 ok(ret == 1, "ret = %d\n", ret);
892 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
893 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
894 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
895 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
897 /* Force Win9x to update DC state */
898 SetPixelV(hdcMetafile, 50, 50, 0);
899 SetPolyFillMode( hdcMetafile, ALTERNATE );
900 SetBkColor( hdcMetafile, 0 );
902 ret = SaveDC(hdcMetafile);
903 ok(ret == 1, "ret = %d\n", ret);
905 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
906 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
907 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
908 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
910 SetPolyFillMode( hdcMetafile, WINDING );
911 SetBkColor( hdcMetafile, 0x123456 );
912 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
913 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
915 /* Force Win9x to update DC state */
916 SetPixelV(hdcMetafile, 50, 50, 0);
918 ret = RestoreDC(hdcMetafile, -1);
919 ok(ret, "ret = %d\n", ret);
921 ret = SaveDC(hdcMetafile);
922 ok(ret == 1, "ret = %d\n", ret);
924 ret = RestoreDC(hdcMetafile, 1);
925 ok(ret, "ret = %d\n", ret);
927 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
928 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
929 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
930 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
932 /* Force Win9x to update DC state */
933 SetPixelV(hdcMetafile, 50, 50, 0);
935 ret = SaveDC(hdcMetafile);
936 ok(ret == 1, "ret = %d\n", ret);
938 ret = SaveDC(hdcMetafile);
939 ok(ret == 1, "ret = %d\n", ret);
941 memset(&orig_lf, 0, sizeof(orig_lf));
942 orig_lf.lfCharSet = ANSI_CHARSET;
943 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
944 orig_lf.lfWeight = FW_DONTCARE;
945 orig_lf.lfHeight = 7;
946 orig_lf.lfQuality = DEFAULT_QUALITY;
947 lstrcpyA(orig_lf.lfFaceName, "Arial");
948 hFont = CreateFontIndirectA(&orig_lf);
949 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
951 hFontOld = SelectObject(hdcMetafile, hFont);
953 hFont2 = CreateFontIndirectA(&orig_lf);
954 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
955 hFontCheck = SelectObject(hdcMetafile, hFont2);
956 ok(hFontCheck == hFont, "Font not selected\n");
958 /* Force Win9x to update DC state */
959 SetPixelV(hdcMetafile, 50, 50, 0);
961 ret = RestoreDC(hdcMetafile, 1);
962 ok(ret, "ret = %d\n", ret);
964 hFontCheck = SelectObject(hdcMetafile, hFontOld);
965 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
967 /* restore level is ignored */
968 ret = RestoreDC(hdcMetafile, -20);
969 ok(ret, "ret = %d\n", ret);
970 ret = RestoreDC(hdcMetafile, 20);
971 ok(ret, "ret = %d\n", ret);
972 ret = RestoreDC(hdcMetafile, 0);
973 ok(ret, "ret = %d\n", ret);
975 hMetafile = CloseMetaFile(hdcMetafile);
976 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
978 ret = DeleteMetaFile(hMetafile);
979 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
980 ret = DeleteObject(hFont);
981 ok( ret, "DeleteObject error %d\n", GetLastError());
982 ret = DeleteObject(hFont2);
983 ok( ret, "DeleteObject error %d\n", GetLastError());
987 /* Win-format metafile (mfdrv) tests */
988 /* These tests compare the generated metafiles byte-by-byte */
989 /* with the nominal results. */
991 /* Maximum size of sample metafiles in bytes. */
992 #define MF_BUFSIZE 512
994 /* 8x8 bitmap data for a pattern brush */
995 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
996 0x01, 0x00, 0x02, 0x00,
997 0x03, 0x00, 0x04, 0x00,
998 0x05, 0x00, 0x06, 0x00,
999 0x07, 0x00, 0x08, 0x00
1002 /* Sample metafiles to be compared to the outputs of the
1003 * test functions.
1006 static const unsigned char MF_BLANK_BITS[] = {
1007 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1012 static const unsigned char MF_GRAPHICS_BITS[] = {
1013 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1016 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1017 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1018 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1019 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1020 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1021 0x00, 0x00, 0x00, 0x00
1024 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1025 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1026 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1028 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1029 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1030 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1031 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1032 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1033 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1035 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1036 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1037 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1038 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1039 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1040 0x00, 0x00
1043 static const unsigned char MF_DCBRUSH_BITS[] =
1045 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1046 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1047 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1048 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1049 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1050 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1053 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1054 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1055 0x00, 0x00, 0x00, 0x00
1058 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1060 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1062 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1063 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1064 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1065 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1066 0x00, 0x00
1069 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1071 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1076 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1077 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1078 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1081 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1084 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1085 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1086 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1088 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1089 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1090 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1091 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1094 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1095 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1096 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1097 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1098 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1099 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1101 0x14, 0x00, 0x00, 0x00
1104 static const unsigned char MF_LINETO_BITS[] = {
1105 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1106 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1107 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1108 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1109 0x00, 0x00
1112 static const unsigned char EMF_LINETO_BITS[] = {
1113 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1115 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1118 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1119 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1120 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1123 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1126 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1127 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1128 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1129 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1130 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1131 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1132 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1133 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1134 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1136 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1137 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1138 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1139 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1140 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1141 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1142 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1143 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1144 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1145 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1146 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1147 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1148 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1149 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1150 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1151 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1154 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1155 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1157 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1160 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1161 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1162 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1165 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1168 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1169 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1170 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1171 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1172 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1173 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1174 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1175 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1176 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1178 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1179 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1180 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1181 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1182 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1183 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1184 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1185 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1186 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1187 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1188 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1189 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1190 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1191 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1192 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1193 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1196 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1197 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1199 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1202 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1203 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1204 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1207 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1210 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1211 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1212 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1213 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1214 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1215 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1216 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1217 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1218 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1220 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1221 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1223 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1224 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1225 0x14, 0x00, 0x00, 0x00
1228 static const unsigned char EMF_BITBLT[] =
1230 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1232 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1235 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1236 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1237 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1240 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1243 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1244 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1246 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1248 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1254 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1255 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1256 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1257 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1267 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1269 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1272 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1280 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1284 static const unsigned char EMF_DCBRUSH_BITS[] =
1286 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1287 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1288 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1289 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1290 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1291 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1292 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1293 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1295 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1296 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1299 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1300 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1301 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1302 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1303 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1305 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1306 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1307 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1308 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1311 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1312 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1313 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1314 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1315 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1316 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1317 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1320 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1321 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1322 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1323 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1324 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1325 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1326 0x14, 0x00, 0x00, 0x00
1329 static const unsigned char EMF_BEZIER_BITS[] =
1331 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1336 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1337 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1338 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1341 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1344 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1345 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1346 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1347 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1348 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1349 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1350 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1351 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1352 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1353 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1354 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1355 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1356 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1357 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1358 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1359 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1360 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1361 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1362 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1363 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1364 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1365 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1366 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1367 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1368 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1369 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1371 0x14, 0x00, 0x00, 0x00
1374 /* For debugging or dumping the raw metafiles produced by
1375 * new test functions.
1377 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1378 INT nobj, LPARAM param)
1380 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1381 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1382 return TRUE;
1385 /* For debugging or dumping the raw metafiles produced by
1386 * new test functions.
1389 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1391 BYTE buf[MF_BUFSIZE];
1392 UINT mfsize, i;
1394 if (!winetest_debug) return;
1396 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1397 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1399 printf ("MetaFile %s has bits:\n{\n ", desc);
1400 for (i=0; i<mfsize; i++)
1402 printf ("0x%02x", buf[i]);
1403 if (i == mfsize-1)
1404 printf ("\n");
1405 else if (i % 8 == 7)
1406 printf (",\n ");
1407 else
1408 printf (", ");
1410 printf ("};\n");
1413 /* Compare the metafile produced by a test function with the
1414 * expected raw metafile data in "bits".
1415 * Return value is 0 for a perfect match,
1416 * -1 if lengths aren't equal,
1417 * otherwise returns the number of non-matching bytes.
1420 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1421 const char *desc)
1423 unsigned char buf[MF_BUFSIZE];
1424 UINT mfsize, i;
1425 int diff;
1427 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1428 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1429 if (mfsize < MF_BUFSIZE)
1430 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1431 desc, mfsize, bsize);
1432 else
1433 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1434 desc, mfsize, bsize);
1435 if (mfsize != bsize)
1436 return -1;
1438 diff = 0;
1439 for (i=0; i<bsize; i++)
1441 if (buf[i] != bits[i])
1442 diff++;
1444 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1445 desc, mfsize, bsize, diff);
1447 return diff;
1450 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1452 unsigned char buf[MF_BUFSIZE];
1453 DWORD mfsize, rd_size, i;
1454 int diff;
1455 HANDLE hfile;
1456 BOOL ret;
1458 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1459 assert(hfile != INVALID_HANDLE_VALUE);
1461 mfsize = GetFileSize(hfile, NULL);
1462 assert(mfsize <= MF_BUFSIZE);
1464 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1465 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1467 CloseHandle(hfile);
1469 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1471 if (mfsize != bsize)
1472 return -1;
1474 diff = 0;
1475 for (i=0; i<bsize; i++)
1477 if (buf[i] != bits[i])
1478 diff++;
1480 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1481 desc, mfsize, bsize, diff);
1483 return diff;
1486 /* For debugging or dumping the raw EMFs produced by
1487 * new test functions.
1489 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1491 BYTE buf[MF_BUFSIZE];
1492 UINT mfsize, i;
1494 if (!winetest_debug) return;
1496 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1497 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1499 printf("EMF %s has bits:\n{\n ", desc);
1500 for (i = 0; i < mfsize; i++)
1502 printf ("0x%02x", buf[i]);
1503 if (i == mfsize-1)
1504 printf ("\n");
1505 else if (i % 8 == 7)
1506 printf (",\n ");
1507 else
1508 printf (", ");
1510 printf ("};\n");
1513 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1515 BYTE *emf;
1516 BYTE buf[MF_BUFSIZE];
1517 UINT mfsize, offset;
1519 if (!winetest_debug) return;
1521 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1522 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1524 printf("EMF %s has records:\n", desc);
1526 emf = buf;
1527 offset = 0;
1528 while(offset < mfsize)
1530 EMR *emr = (EMR *)(emf + offset);
1531 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1532 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1533 offset += emr->nSize;
1537 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1539 const BYTE *buf;
1540 DWORD i;
1542 if (!winetest_debug) return;
1544 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1545 buf = (const BYTE *)emr;
1546 for (i = 0; i < emr->nSize; i++)
1548 printf ("0x%02x", buf[i]);
1549 if (i == emr->nSize - 1)
1550 printf ("\n");
1551 else if (i % 8 == 7)
1552 printf (",\n");
1553 else
1554 printf (", ");
1556 printf ("};\n");
1559 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1561 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1562 eto->rclBounds.right, eto->rclBounds.bottom);
1563 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1564 trace("exScale: %f\n", eto->exScale);
1565 trace("eyScale: %f\n", eto->eyScale);
1566 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1567 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1568 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1569 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1570 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1571 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1572 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1575 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1576 const char *desc, BOOL ignore_scaling)
1578 int diff;
1580 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1581 desc, emr1->iType, emr2->iType);
1583 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1584 desc, emr1->nSize, emr2->nSize);
1586 /* iType and nSize mismatches are fatal */
1587 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1589 /* contents of EMR_GDICOMMENT are not interesting */
1590 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1592 /* different Windows versions setup DC scaling differently when
1593 * converting an old style metafile to an EMF.
1595 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1596 emr1->iType == EMR_SETVIEWPORTEXTEX))
1597 return TRUE;
1599 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1601 EMREXTTEXTOUTW *eto1, *eto2;
1603 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1604 memcpy(eto1, emr1, emr1->nSize);
1605 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1606 memcpy(eto2, emr2, emr2->nSize);
1608 /* different Windows versions setup DC scaling differently */
1609 eto1->exScale = eto1->eyScale = 0.0;
1610 eto2->exScale = eto2->eyScale = 0.0;
1612 diff = memcmp(eto1, eto2, emr1->nSize);
1613 if (diff)
1615 dump_EMREXTTEXTOUT(eto1);
1616 dump_EMREXTTEXTOUT(eto2);
1618 HeapFree(GetProcessHeap(), 0, eto1);
1619 HeapFree(GetProcessHeap(), 0, eto2);
1621 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1623 /* We have to take care of NT4 differences here */
1624 diff = memcmp(emr1, emr2, emr1->nSize);
1625 if (diff)
1627 ENHMETARECORD *emr_nt4;
1629 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1630 memcpy(emr_nt4, emr2, emr2->nSize);
1631 /* Correct the nRgnSize field */
1632 emr_nt4->dParm[5] = sizeof(RECT);
1634 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1635 if (!diff)
1636 win_skip("Catered for NT4 differences\n");
1638 HeapFree(GetProcessHeap(), 0, emr_nt4);
1641 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1643 EMRPOLYBEZIER16 *eto1, *eto2;
1645 eto1 = (EMRPOLYBEZIER16*)emr1;
1646 eto2 = (EMRPOLYBEZIER16*)emr2;
1648 diff = eto1->cpts != eto2->cpts;
1649 if(!diff)
1650 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1652 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1654 EMRPOLYBEZIER *eto1, *eto2;
1656 eto1 = (EMRPOLYBEZIER*)emr1;
1657 eto2 = (EMRPOLYBEZIER*)emr2;
1659 diff = eto1->cptl != eto2->cptl;
1660 if(!diff)
1661 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1663 else
1664 diff = memcmp(emr1, emr2, emr1->nSize);
1666 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1668 if (diff)
1670 dump_emf_record(emr1, "expected bits");
1671 dump_emf_record(emr2, "actual bits");
1674 return diff == 0; /* report all non-fatal record mismatches */
1677 /* Compare the EMF produced by a test function with the
1678 * expected raw EMF data in "bits".
1679 * Return value is 0 for a perfect match,
1680 * -1 if lengths aren't equal,
1681 * otherwise returns the number of non-matching bytes.
1683 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1684 UINT bsize, const char *desc,
1685 BOOL ignore_scaling)
1687 unsigned char buf[MF_BUFSIZE];
1688 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1689 const ENHMETAHEADER *emh1, *emh2;
1691 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1692 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1694 /* ENHMETAHEADER size could differ, depending on platform */
1695 diff_nt4 = sizeof(SIZEL);
1696 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1698 if (mfsize < MF_BUFSIZE)
1700 ok(mfsize == bsize ||
1701 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1702 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1703 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1705 else
1706 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1707 desc, mfsize, bsize);
1709 /* basic things must match */
1710 emh1 = (const ENHMETAHEADER *)bits;
1711 emh2 = (const ENHMETAHEADER *)buf;
1712 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1713 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1714 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1715 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1717 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1718 ok(emh1->nSize == emh2->nSize ||
1719 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1720 broken(emh1->nSize - diff_9x == emh2->nSize),
1721 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1722 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1723 ok(emh1->nBytes == emh2->nBytes ||
1724 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1725 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1726 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1727 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1729 offset1 = emh1->nSize;
1730 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1731 while (offset1 < emh1->nBytes)
1733 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1734 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1736 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1737 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1739 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1741 /* We have already bailed out if iType or nSize don't match */
1742 offset1 += emr1->nSize;
1743 offset2 += emr2->nSize;
1745 return 0;
1749 /* tests blitting to an EMF */
1750 static void test_emf_BitBlt(void)
1752 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1753 HBITMAP hBitmap, hOldBitmap;
1754 HENHMETAFILE hMetafile;
1755 #define BMP_DIM 4
1756 BITMAPINFOHEADER bmih =
1758 sizeof(BITMAPINFOHEADER),
1759 BMP_DIM,/* biWidth */
1760 BMP_DIM,/* biHeight */
1761 1, /* biPlanes */
1762 24, /* biBitCount */
1763 BI_RGB, /* biCompression */
1764 0, /* biXPelsPerMeter */
1765 0, /* biYPelsPerMeter */
1766 0, /* biClrUsed */
1767 0, /* biClrImportant */
1769 void *bits;
1770 BOOL ret;
1772 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1773 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1775 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1776 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1777 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1778 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1779 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1780 DIB_RGB_COLORS, &bits, NULL, 0);
1781 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1783 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1784 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1786 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1787 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1788 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1790 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1791 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1792 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1793 ok( ret, "BitBlt(WHITENESS) failed\n" );
1795 hMetafile = CloseEnhMetaFile(hdcMetafile);
1796 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1798 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1799 "emf_BitBlt", FALSE) != 0)
1801 dump_emf_bits(hMetafile, "emf_BitBlt");
1802 dump_emf_records(hMetafile, "emf_BitBlt");
1805 SelectObject(hdcBitmap, hOldBitmap);
1806 DeleteObject(hBitmap);
1807 DeleteDC(hdcBitmap);
1808 DeleteDC(hdcDisplay);
1809 #undef BMP_DIM
1812 static void test_emf_DCBrush(void)
1814 HDC hdcMetafile;
1815 HENHMETAFILE hMetafile;
1816 HBRUSH hBrush;
1817 HPEN hPen;
1818 BOOL ret;
1819 COLORREF color;
1821 if (!pSetDCBrushColor || !pSetDCPenColor)
1823 win_skip( "SetDCBrush/PenColor not supported\n" );
1824 return;
1827 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1828 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1830 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1831 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1833 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1834 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1836 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1837 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1839 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1840 ok( color == 0, "SetDCPenColor returned %x\n", color );
1842 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1844 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1845 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1847 hMetafile = CloseEnhMetaFile(hdcMetafile);
1848 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1850 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1851 "emf_DC_Brush", FALSE ) != 0)
1853 dump_emf_bits(hMetafile, "emf_DC_Brush");
1854 dump_emf_records(hMetafile, "emf_DC_Brush");
1856 ret = DeleteEnhMetaFile(hMetafile);
1857 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1858 ret = DeleteObject(hBrush);
1859 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1860 ret = DeleteObject(hPen);
1861 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1864 /* Test a blank metafile. May be used as a template for new tests. */
1866 static void test_mf_Blank(void)
1868 HDC hdcMetafile;
1869 HMETAFILE hMetafile;
1870 INT caps;
1871 BOOL ret;
1872 INT type;
1874 hdcMetafile = CreateMetaFileA(NULL);
1875 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1876 trace("hdcMetafile %p\n", hdcMetafile);
1878 /* Tests on metafile initialization */
1879 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1880 ok (caps == DT_METAFILE,
1881 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1883 hMetafile = CloseMetaFile(hdcMetafile);
1884 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1885 type = GetObjectType(hMetafile);
1886 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1887 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1889 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1890 "mf_blank") != 0)
1892 dump_mf_bits(hMetafile, "mf_Blank");
1893 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1896 ret = DeleteMetaFile(hMetafile);
1897 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1900 static void test_CopyMetaFile(void)
1902 HDC hdcMetafile;
1903 HMETAFILE hMetafile, hmf_copy;
1904 BOOL ret;
1905 char temp_path[MAX_PATH];
1906 char mf_name[MAX_PATH];
1907 INT type;
1909 hdcMetafile = CreateMetaFileA(NULL);
1910 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1911 trace("hdcMetafile %p\n", hdcMetafile);
1913 hMetafile = CloseMetaFile(hdcMetafile);
1914 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1915 type = GetObjectType(hMetafile);
1916 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1918 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1919 "mf_blank") != 0)
1921 dump_mf_bits(hMetafile, "mf_Blank");
1922 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1925 GetTempPathA(MAX_PATH, temp_path);
1926 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1928 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1929 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1931 type = GetObjectType(hmf_copy);
1932 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1934 ret = DeleteMetaFile(hMetafile);
1935 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1937 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1939 dump_mf_bits(hmf_copy, "mf_Blank");
1940 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1943 ret = DeleteMetaFile(hmf_copy);
1944 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1946 DeleteFileA(mf_name);
1949 static void test_SetMetaFileBits(void)
1951 HMETAFILE hmf;
1952 INT type;
1953 BOOL ret;
1954 BYTE buf[256];
1955 METAHEADER *mh;
1957 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1958 trace("hmf %p\n", hmf);
1959 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1960 type = GetObjectType(hmf);
1961 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1963 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1965 dump_mf_bits(hmf, "mf_Graphics");
1966 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1969 ret = DeleteMetaFile(hmf);
1970 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1972 /* NULL data crashes XP SP1 */
1973 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1975 /* Now with zero size */
1976 SetLastError(0xdeadbeef);
1977 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1978 trace("hmf %p\n", hmf);
1979 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1980 ok(GetLastError() == ERROR_INVALID_DATA ||
1981 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1982 "wrong error %d\n", GetLastError());
1984 /* Now with odd size */
1985 SetLastError(0xdeadbeef);
1986 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1987 trace("hmf %p\n", hmf);
1988 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1989 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1991 /* Now with zeroed out header fields */
1992 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1993 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1994 mh = (METAHEADER *)buf;
1995 /* corruption of any of the below fields leads to a failure */
1996 mh->mtType = 0;
1997 mh->mtVersion = 0;
1998 mh->mtHeaderSize = 0;
1999 SetLastError(0xdeadbeef);
2000 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2001 trace("hmf %p\n", hmf);
2002 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2003 ok(GetLastError() == ERROR_INVALID_DATA ||
2004 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2005 "wrong error %d\n", GetLastError());
2007 /* Now with corrupted mtSize field */
2008 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2009 mh = (METAHEADER *)buf;
2010 /* corruption of mtSize doesn't lead to a failure */
2011 mh->mtSize *= 2;
2012 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2013 trace("hmf %p\n", hmf);
2014 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2016 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2018 dump_mf_bits(hmf, "mf_Graphics");
2019 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2022 ret = DeleteMetaFile(hmf);
2023 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2025 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2026 /* Now with zeroed out mtSize field */
2027 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2028 mh = (METAHEADER *)buf;
2029 /* zeroing mtSize doesn't lead to a failure */
2030 mh->mtSize = 0;
2031 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2032 trace("hmf %p\n", hmf);
2033 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2035 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2037 dump_mf_bits(hmf, "mf_Graphics");
2038 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2041 ret = DeleteMetaFile(hmf);
2042 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2043 #endif
2046 /* Simple APIs from mfdrv/graphics.c
2049 static void test_mf_Graphics(void)
2051 HDC hdcMetafile;
2052 HMETAFILE hMetafile;
2053 POINT oldpoint;
2054 BOOL ret;
2056 hdcMetafile = CreateMetaFileA(NULL);
2057 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2058 trace("hdcMetafile %p\n", hdcMetafile);
2060 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2061 ok( ret, "MoveToEx error %d.\n", GetLastError());
2062 ret = LineTo(hdcMetafile, 2, 2);
2063 ok( ret, "LineTo error %d.\n", GetLastError());
2064 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2065 ok( ret, "MoveToEx error %d.\n", GetLastError());
2067 /* oldpoint gets garbage under Win XP, so the following test would
2068 * work under Wine but fails under Windows:
2070 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2071 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2072 * oldpoint.x, oldpoint.y);
2075 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2076 ok( ret, "Ellipse error %d.\n", GetLastError());
2078 hMetafile = CloseMetaFile(hdcMetafile);
2079 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2080 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2082 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2083 "mf_Graphics") != 0)
2085 dump_mf_bits(hMetafile, "mf_Graphics");
2086 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2089 ret = DeleteMetaFile(hMetafile);
2090 ok( ret, "DeleteMetaFile(%p) error %d\n",
2091 hMetafile, GetLastError());
2094 static void test_mf_PatternBrush(void)
2096 HDC hdcMetafile;
2097 HMETAFILE hMetafile;
2098 LOGBRUSH *orig_lb;
2099 HBRUSH hBrush;
2100 BOOL ret;
2102 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2104 orig_lb->lbStyle = BS_PATTERN;
2105 orig_lb->lbColor = RGB(0, 0, 0);
2106 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2107 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2109 hBrush = CreateBrushIndirect (orig_lb);
2110 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2112 hdcMetafile = CreateMetaFileA(NULL);
2113 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2114 trace("hdcMetafile %p\n", hdcMetafile);
2116 hBrush = SelectObject(hdcMetafile, hBrush);
2117 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2119 hMetafile = CloseMetaFile(hdcMetafile);
2120 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2121 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2123 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2124 "mf_Pattern_Brush") != 0)
2126 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2127 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2130 ret = DeleteMetaFile(hMetafile);
2131 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2132 ret = DeleteObject(hBrush);
2133 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2134 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2135 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2136 GetLastError());
2137 HeapFree (GetProcessHeap(), 0, orig_lb);
2140 static void test_mf_DCBrush(void)
2142 HDC hdcMetafile;
2143 HMETAFILE hMetafile;
2144 HBRUSH hBrush;
2145 HPEN hPen;
2146 BOOL ret;
2147 COLORREF color;
2149 if (!pSetDCBrushColor || !pSetDCPenColor)
2151 win_skip( "SetDCBrush/PenColor not supported\n" );
2152 return;
2155 hdcMetafile = CreateMetaFileA(NULL);
2156 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2158 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2159 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2161 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2162 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2164 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2165 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2167 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2168 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2170 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2172 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2173 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2175 hMetafile = CloseMetaFile(hdcMetafile);
2176 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2178 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2180 dump_mf_bits(hMetafile, "mf_DCBrush");
2181 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2183 ret = DeleteMetaFile(hMetafile);
2184 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2187 static void test_mf_ExtTextOut_on_path(void)
2189 HDC hdcMetafile;
2190 HMETAFILE hMetafile;
2191 BOOL ret;
2192 static const INT dx[4] = { 3, 5, 8, 12 };
2194 hdcMetafile = CreateMetaFileA(NULL);
2195 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2196 trace("hdcMetafile %p\n", hdcMetafile);
2198 ret = BeginPath(hdcMetafile);
2199 ok(!ret, "BeginPath on metafile DC should fail\n");
2201 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2202 ok(ret, "ExtTextOut error %d\n", GetLastError());
2204 ret = EndPath(hdcMetafile);
2205 ok(!ret, "EndPath on metafile DC should fail\n");
2207 hMetafile = CloseMetaFile(hdcMetafile);
2208 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2210 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2211 "mf_TextOut_on_path") != 0)
2213 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2214 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2217 ret = DeleteMetaFile(hMetafile);
2218 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2221 static void test_emf_ExtTextOut_on_path(void)
2223 HWND hwnd;
2224 HDC hdcDisplay, hdcMetafile;
2225 HENHMETAFILE hMetafile;
2226 BOOL ret;
2227 static const INT dx[4] = { 3, 5, 8, 12 };
2229 /* Win9x doesn't play EMFs on invisible windows */
2230 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2231 0, 0, 200, 200, 0, 0, 0, NULL);
2232 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2234 hdcDisplay = GetDC(hwnd);
2235 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2237 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2238 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2240 ret = BeginPath(hdcMetafile);
2241 ok(ret, "BeginPath error %d\n", GetLastError());
2243 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2244 ok(ret, "ExtTextOut error %d\n", GetLastError());
2246 ret = EndPath(hdcMetafile);
2247 ok(ret, "EndPath error %d\n", GetLastError());
2249 hMetafile = CloseEnhMetaFile(hdcMetafile);
2250 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2252 /* this doesn't succeed yet: EMF has correct size, all EMF records
2253 * are there, but their contents don't match for different reasons.
2255 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2256 "emf_TextOut_on_path", FALSE) != 0)
2258 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2259 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2262 ret = DeleteEnhMetaFile(hMetafile);
2263 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2264 ret = ReleaseDC(hwnd, hdcDisplay);
2265 ok(ret, "ReleaseDC error %d\n", GetLastError());
2266 DestroyWindow(hwnd);
2269 static const unsigned char EMF_CLIPPING[] =
2271 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2273 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2275 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2276 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2277 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2278 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2280 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2281 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2283 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2284 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2285 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2286 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2287 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2288 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2289 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2290 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2291 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2292 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2293 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2294 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2295 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2296 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2299 static void translate( POINT *pt, UINT count, const XFORM *xform )
2301 while (count--)
2303 FLOAT x = (FLOAT)pt->x;
2304 FLOAT y = (FLOAT)pt->y;
2305 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2306 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2307 pt++;
2311 /* Compare rectangles allowing rounding errors */
2312 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2314 return abs(rc1->left - rc2->left) <= 1 &&
2315 abs(rc1->top - rc2->top) <= 1 &&
2316 abs(rc1->right - rc2->right) <= 1 &&
2317 abs(rc1->bottom - rc2->bottom) <= 1;
2320 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2321 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2323 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2325 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2326 union _rgn
2328 RGNDATA data;
2329 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2331 const union _rgn *rgn1;
2332 union _rgn rgn2;
2333 RECT rect, rc_transformed;
2334 const RECT *rc = (const RECT *)param;
2335 HRGN hrgn;
2336 XFORM xform;
2337 INT ret;
2338 BOOL is_win9x;
2340 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2341 clip->cbRgnData, clip->iMode);
2343 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2344 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2345 "too small data block: %u bytes\n", clip->cbRgnData);
2346 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2347 return 0;
2349 rgn1 = (const union _rgn *)clip->RgnData;
2351 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2352 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2353 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2354 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2355 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2357 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2359 rect = *(const RECT *)rgn1->data.Buffer;
2360 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2361 ok(EqualRect(&rect, rc), "rects don't match\n");
2363 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2364 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2365 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2366 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2367 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2368 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2370 hrgn = CreateRectRgn(0, 0, 0, 0);
2372 memset(&xform, 0, sizeof(xform));
2373 SetLastError(0xdeadbeef);
2374 ret = GetWorldTransform(hdc, &xform);
2375 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2376 if (!is_win9x)
2377 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2379 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2381 ret = GetClipRgn(hdc, hrgn);
2382 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2384 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2386 ret = GetClipRgn(hdc, hrgn);
2387 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2389 /* Win9x returns empty clipping region */
2390 if (is_win9x) return 1;
2392 ret = GetRegionData(hrgn, 0, NULL);
2393 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2395 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2396 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2398 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2399 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2400 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2401 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2402 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2404 rect = rgn2.data.rdh.rcBound;
2405 rc_transformed = *rc;
2406 translate((POINT *)&rc_transformed, 2, &xform);
2407 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2408 rc_transformed.right, rc_transformed.bottom);
2409 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2411 rect = *(const RECT *)rgn2.data.Buffer;
2412 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2413 rc_transformed = *rc;
2414 translate((POINT *)&rc_transformed, 2, &xform);
2415 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2416 rc_transformed.right, rc_transformed.bottom);
2417 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2419 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2420 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2421 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2422 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2423 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2424 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2426 DeleteObject(hrgn);
2428 return 1;
2431 static void test_emf_clipping(void)
2433 static const RECT rc = { 0, 0, 100, 100 };
2434 RECT rc_clip = { 100, 100, 1024, 1024 };
2435 HWND hwnd;
2436 HDC hdc;
2437 HENHMETAFILE hemf;
2438 HRGN hrgn;
2439 INT ret;
2440 RECT rc_res, rc_sclip;
2442 SetLastError(0xdeadbeef);
2443 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2444 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2446 /* Need to write something to the emf, otherwise Windows won't play it back */
2447 LineTo(hdc, 1, 1);
2449 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2450 ret = SelectClipRgn(hdc, hrgn);
2451 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2453 SetLastError(0xdeadbeef);
2454 hemf = CloseEnhMetaFile(hdc);
2455 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2457 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2458 "emf_clipping", FALSE) != 0)
2460 dump_emf_bits(hemf, "emf_clipping");
2461 dump_emf_records(hemf, "emf_clipping");
2464 DeleteObject(hrgn);
2466 /* Win9x doesn't play EMFs on invisible windows */
2467 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2468 0, 0, 200, 200, 0, 0, 0, NULL);
2469 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2471 hdc = GetDC(hwnd);
2473 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2474 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2476 DeleteEnhMetaFile(hemf);
2477 ReleaseDC(hwnd, hdc);
2478 DestroyWindow(hwnd);
2480 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2482 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2483 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2484 SelectClipRgn(hdc, hrgn);
2485 SetRect(&rc_res, -1, -1, -1, -1);
2486 ret = GetClipBox(hdc, &rc_res);
2487 ok(ret == SIMPLEREGION, "got %d\n", ret);
2488 ok(EqualRect(&rc_res, &rc_sclip),
2489 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2490 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2491 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2493 OffsetRect(&rc_sclip, -100, -100);
2494 ret = OffsetClipRgn(hdc, -100, -100);
2495 ok(ret == SIMPLEREGION, "got %d\n", ret);
2496 SetRect(&rc_res, -1, -1, -1, -1);
2497 ret = GetClipBox(hdc, &rc_res);
2498 ok(ret == SIMPLEREGION, "got %d\n", ret);
2499 ok(EqualRect(&rc_res, &rc_sclip),
2500 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2501 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2502 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2504 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2505 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2506 if (ret == COMPLEXREGION)
2508 /* XP returns COMPLEXREGION although region contains only 1 rect */
2509 ret = GetClipRgn(hdc, hrgn);
2510 ok(ret == 1, "expected 1, got %d\n", ret);
2511 ret = rgn_rect_count(hrgn);
2512 ok(ret == 1, "expected 1, got %d\n", ret);
2514 SetRect(&rc_res, -1, -1, -1, -1);
2515 ret = GetClipBox(hdc, &rc_res);
2516 ok(ret == SIMPLEREGION, "got %d\n", ret);
2517 ok(EqualRect(&rc_res, &rc),
2518 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2519 rc.left, rc.top, rc.right, rc.bottom,
2520 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2522 SetRect(&rc_sclip, 0, 0, 100, 50);
2523 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2524 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2525 if (ret == COMPLEXREGION)
2527 /* XP returns COMPLEXREGION although region contains only 1 rect */
2528 ret = GetClipRgn(hdc, hrgn);
2529 ok(ret == 1, "expected 1, got %d\n", ret);
2530 ret = rgn_rect_count(hrgn);
2531 ok(ret == 1, "expected 1, got %d\n", ret);
2533 SetRect(&rc_res, -1, -1, -1, -1);
2534 ret = GetClipBox(hdc, &rc_res);
2535 ok(ret == SIMPLEREGION, "got %d\n", ret);
2536 ok(EqualRect(&rc_res, &rc_sclip),
2537 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2538 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2539 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2541 hemf = CloseEnhMetaFile(hdc);
2542 DeleteEnhMetaFile(hemf);
2543 DeleteObject(hrgn);
2546 static const unsigned char MF_CLIP_BITS[] = {
2547 /* METAHEADER */
2548 0x01, 0x00, /* mtType */
2549 0x09, 0x00, /* mtHeaderSize */
2550 0x00, 0x03, /* mtVersion */
2551 0x32, 0x00, 0x00, 0x00, /* mtSize */
2552 0x01, 0x00, /* mtNoObjects */
2553 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2554 0x00, 0x00, /* reserved */
2556 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2557 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2558 0xff, 0x06, /* META_CREATEREGION */
2559 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2560 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2561 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2562 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2563 0x02, 0x00,
2565 /* METARECORD for SelectObject */
2566 0x04, 0x00, 0x00, 0x00,
2567 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2568 0x00, 0x00,
2570 /* METARECORD */
2571 0x04, 0x00, 0x00, 0x00,
2572 0xf0, 0x01, /* META_DELETEOBJECT */
2573 0x00, 0x00,
2575 /* METARECORD for MoveTo(1,0x30) */
2576 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2577 0x14, 0x02, /* META_MOVETO */
2578 0x30, 0x00, /* y */
2579 0x01, 0x00, /* x */
2581 /* METARECORD for LineTo(0x20, 0x30) */
2582 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2583 0x13, 0x02, /* META_LINETO */
2584 0x30, 0x00, /* y */
2585 0x20, 0x00, /* x */
2587 /* EOF */
2588 0x03, 0x00, 0x00, 0x00,
2589 0x00, 0x00
2592 static int clip_mf_enum_proc_seen_selectclipregion;
2593 static int clip_mf_enum_proc_seen_selectobject;
2595 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2596 METARECORD *mr, int n_objs, LPARAM param)
2598 switch (mr->rdFunction) {
2599 case META_SELECTCLIPREGION:
2600 clip_mf_enum_proc_seen_selectclipregion++;
2601 break;
2602 case META_SELECTOBJECT:
2603 clip_mf_enum_proc_seen_selectobject++;
2604 break;
2606 return 1;
2609 static void test_mf_clipping(void)
2611 /* left top right bottom */
2612 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2613 HWND hwnd;
2614 HDC hdc;
2615 HMETAFILE hmf;
2616 HRGN hrgn;
2617 INT ret;
2619 SetLastError(0xdeadbeef);
2620 hdc = CreateMetaFileA(NULL);
2621 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2623 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2624 ret = SelectClipRgn(hdc, hrgn);
2625 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2626 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2628 /* Draw a line that starts off left of the clip region and ends inside it */
2629 MoveToEx(hdc, 0x1, 0x30, NULL);
2630 LineTo(hdc, 0x20, 0x30);
2632 SetLastError(0xdeadbeef);
2633 hmf = CloseMetaFile(hdc);
2634 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2636 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2637 "mf_clipping") != 0)
2639 dump_mf_bits(hmf, "mf_clipping");
2642 DeleteObject(hrgn);
2644 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2645 0, 0, 200, 200, 0, 0, 0, NULL);
2646 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2648 hdc = GetDC(hwnd);
2650 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2651 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2653 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2654 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2655 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2656 ok(clip_mf_enum_proc_seen_selectobject == 1,
2657 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2659 DeleteMetaFile(hmf);
2660 ReleaseDC(hwnd, hdc);
2661 DestroyWindow(hwnd);
2664 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2666 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2667 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2668 /* When using MM_TEXT Win9x does not update the mapping mode
2669 * until a record is played which actually outputs something */
2670 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2671 LPtoDP(hdc, mapping, 2);
2672 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2673 lpEMFR->iType, lpEMFR->nSize,
2674 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2676 if (lpEMFR->iType == EMR_LINETO)
2678 INT x0, y0, x1, y1;
2679 if (!lpMFP || lpMFP->mm == MM_TEXT)
2681 x0 = 0;
2682 y0 = 0;
2683 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2684 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2686 else
2688 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2690 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2691 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2692 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2693 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2695 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2696 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2697 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2698 x0, y0, x1, y1);
2700 return TRUE;
2703 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2705 HDC hdcMf;
2706 HMETAFILE hmf;
2707 HENHMETAFILE hemf;
2708 BOOL ret;
2709 UINT size;
2710 LPBYTE pBits;
2712 hdcMf = CreateMetaFileA(NULL);
2713 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2714 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2715 ok(ret, "LineTo failed with error %d\n", GetLastError());
2716 hmf = CloseMetaFile(hdcMf);
2717 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2719 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2721 dump_mf_bits(hmf, "mf_LineTo");
2722 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2725 size = GetMetaFileBitsEx(hmf, 0, NULL);
2726 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2727 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2728 GetMetaFileBitsEx(hmf, size, pBits);
2729 DeleteMetaFile(hmf);
2730 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2731 HeapFree(GetProcessHeap(), 0, pBits);
2732 return hemf;
2735 static void test_mf_conversions(void)
2737 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2739 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2740 HENHMETAFILE hemf;
2741 METAFILEPICT mfp;
2742 RECT rect = { 0, 0, 100, 100 };
2743 mfp.mm = MM_ANISOTROPIC;
2744 mfp.xExt = 100;
2745 mfp.yExt = 100;
2746 mfp.hMF = NULL;
2747 hemf = create_converted_emf(&mfp);
2749 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2750 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2752 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2753 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2756 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2758 DeleteEnhMetaFile(hemf);
2759 DeleteDC(hdcOffscreen);
2762 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2764 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2765 HENHMETAFILE hemf;
2766 METAFILEPICT mfp;
2767 RECT rect = { 0, 0, 100, 100 };
2768 mfp.mm = MM_TEXT;
2769 mfp.xExt = 0;
2770 mfp.yExt = 0;
2771 mfp.hMF = NULL;
2772 hemf = create_converted_emf(&mfp);
2774 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2775 "emf_LineTo MM_TEXT", TRUE) != 0)
2777 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2778 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2781 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2783 DeleteEnhMetaFile(hemf);
2784 DeleteDC(hdcOffscreen);
2787 trace("Testing MF->EMF conversion (NULL mfp)\n");
2789 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2790 HENHMETAFILE hemf;
2791 RECT rect = { 0, 0, 100, 100 };
2792 hemf = create_converted_emf(NULL);
2794 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2795 "emf_LineTo NULL", TRUE) != 0)
2797 dump_emf_bits(hemf, "emf_LineTo NULL");
2798 dump_emf_records(hemf, "emf_LineTo NULL");
2801 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2803 DeleteEnhMetaFile(hemf);
2804 DeleteDC(hdcOffscreen);
2808 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2809 LONG mm, LONG xExt, LONG yExt,
2810 RECTL * rclBounds, RECTL * rclFrame)
2812 METAFILEPICT mfp;
2813 METAFILEPICT * mfpPtr = NULL;
2814 HENHMETAFILE emf;
2815 ENHMETAHEADER header;
2816 UINT res;
2818 if (!mfpIsNull)
2820 mfp.mm = mm;
2821 mfp.xExt = xExt;
2822 mfp.yExt = yExt;
2823 mfpPtr = &mfp;
2826 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2827 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2828 if (!emf) return FALSE;
2829 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2830 ok(res != 0, "GetEnhMetaHeader failed\n");
2831 DeleteEnhMetaFile(emf);
2832 if (!res) return FALSE;
2834 *rclBounds = header.rclBounds;
2835 *rclFrame = header.rclFrame;
2836 return TRUE;
2839 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2840 LONG mm, LONG xExt, LONG yExt,
2841 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2843 RECTL rclBounds, rclFrame;
2845 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2847 const char * msg;
2848 char buf[64];
2850 if (mfpIsNull)
2852 msg = "mfp == NULL";
2854 else
2856 const char * mm_str;
2857 switch (mm)
2859 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2860 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2861 default: mm_str = "Unexpected";
2863 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2864 msg = buf;
2867 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2868 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2869 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2870 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2871 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2872 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2873 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2874 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2878 static void test_SetWinMetaFileBits(void)
2880 HMETAFILE wmf;
2881 HDC wmfDC;
2882 BYTE * buffer;
2883 UINT buffer_size;
2884 RECT rect;
2885 UINT res;
2886 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2887 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2888 RECTL rclBounds, rclFrame;
2889 HDC dc;
2890 LONG diffx, diffy;
2892 wmfDC = CreateMetaFileA(NULL);
2893 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2894 if (!wmfDC) return;
2896 SetWindowExtEx(wmfDC, 100, 100, NULL);
2897 rect.left = rect.top = 0;
2898 rect.right = rect.bottom = 50;
2899 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2900 wmf = CloseMetaFile(wmfDC);
2901 ok(wmf != NULL, "Metafile creation failed\n");
2902 if (!wmf) return;
2904 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2905 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2906 if (buffer_size == 0)
2908 DeleteMetaFile(wmf);
2909 return;
2912 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2913 ok(buffer != NULL, "HeapAlloc failed\n");
2914 if (!buffer)
2916 DeleteMetaFile(wmf);
2917 return;
2920 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2921 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2922 DeleteMetaFile(wmf);
2923 if (res != buffer_size)
2925 HeapFree(GetProcessHeap(), 0, buffer);
2926 return;
2929 /* Get the reference bounds and frame */
2930 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2931 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2933 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2934 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2935 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2937 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2938 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2939 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2940 if (diffx < 0) diffx = -diffx;
2941 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2943 dc = CreateCompatibleDC(NULL);
2945 /* Allow 1 mm difference (rounding errors) */
2946 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2947 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2948 if (diffx < 0) diffx = -diffx;
2949 if (diffy < 0) diffy = -diffy;
2950 todo_wine
2952 ok(diffx <= 1 && diffy <= 1,
2953 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2954 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2957 /* Allow 1 mm difference (rounding errors) */
2958 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2959 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2960 if (diffx < 0) diffx = -diffx;
2961 if (diffy < 0) diffy = -diffy;
2962 todo_wine
2964 ok(diffx <= 1 && diffy <= 1,
2965 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2966 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2968 DeleteDC(dc);
2970 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2971 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2973 /* If xExt or yExt is zero or negative, the whole device surface is used */
2974 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2975 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2976 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2977 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2978 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2979 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2980 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2981 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2982 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2983 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2984 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2985 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2987 /* MSDN says that negative xExt and yExt values specify a ratio.
2988 Check that this is wrong and the whole device surface is used */
2989 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2990 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2992 /* Ordinary conversions */
2994 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2996 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2997 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2998 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2999 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3002 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3004 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3005 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3006 ok(rclBounds.left == 0 && rclBounds.top == 0,
3007 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3009 /* Wine has a rounding error */
3010 diffx = rclBounds.right - rclBounds.bottom;
3011 if (diffx < 0) diffx = -diffx;
3012 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3015 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3017 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3018 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3021 HeapFree(GetProcessHeap(), 0, buffer);
3024 static BOOL near_match(int x, int y)
3026 int epsilon = min(abs(x), abs(y));
3028 epsilon = max(epsilon/100, 2);
3030 if(x < y - epsilon || x > y + epsilon) return FALSE;
3031 return TRUE;
3034 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3036 HENHMETAFILE emf;
3037 HDC display_dc, emf_dc;
3038 ENHMETAHEADER *enh_header;
3039 UINT size, emf_size, i;
3040 WORD check = 0;
3041 DWORD rec_num = 0;
3042 METAHEADER *mh = NULL;
3043 METARECORD *rec;
3044 INT horz_res, vert_res, horz_size, vert_size;
3045 INT curve_caps, line_caps, poly_caps;
3047 display_dc = GetDC(NULL);
3048 ok(display_dc != NULL, "display_dc is NULL\n");
3050 horz_res = GetDeviceCaps(display_dc, HORZRES);
3051 vert_res = GetDeviceCaps(display_dc, VERTRES);
3052 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3053 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3055 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3056 ok(emf_dc != NULL, "emf_dc is NULL\n");
3058 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3059 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3061 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3062 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3064 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3065 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3067 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3068 Rectangle(emf_dc, 0, 0, 1000, 20);
3069 emf = CloseEnhMetaFile(emf_dc);
3070 ok(emf != NULL, "emf is NULL\n");
3072 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3073 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3074 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3075 DeleteEnhMetaFile(emf);
3076 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3077 have different resolutions */
3078 enh_header->szlDevice.cx *= scale;
3079 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3080 ok(emf != NULL, "emf is NULL\n");
3081 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3083 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3084 ok(size ||
3085 broken(size == 0), /* some versions of winxp fail for some reason */
3086 "GetWinMetaFileBits returns 0\n");
3087 if(!size) goto end;
3088 mh = HeapAlloc(GetProcessHeap(), 0, size);
3089 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3091 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3092 ok(check == 0, "check %04x\n", check);
3094 rec = (METARECORD*)(mh + 1);
3096 while(rec->rdSize && rec->rdFunction)
3098 const DWORD chunk_size = 0x2000;
3099 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3101 if(rec_num < mfcomment_chunks)
3103 DWORD this_chunk_size = chunk_size;
3105 if(rec_num == mfcomment_chunks - 1)
3106 this_chunk_size = emf_size - rec_num * chunk_size;
3108 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3109 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3110 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3111 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3112 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3113 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3114 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3115 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3116 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3117 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3118 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3119 /* parm[8] is the checksum, tested above */
3120 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3121 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3122 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3123 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3124 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3125 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3126 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3127 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 */
3128 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3129 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3132 else if(rec_num == mfcomment_chunks)
3134 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3135 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3137 else if(rec_num == mfcomment_chunks + 1)
3139 POINT pt;
3140 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3141 switch(mode)
3143 case MM_TEXT:
3144 case MM_ISOTROPIC:
3145 case MM_ANISOTROPIC:
3146 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3147 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3148 break;
3149 case MM_LOMETRIC:
3150 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3151 pt.x = MulDiv( rc->left, 1, 10);
3152 break;
3153 case MM_HIMETRIC:
3154 pt.y = -rc->top + 1;
3155 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3156 break;
3157 case MM_LOENGLISH:
3158 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3159 pt.x = MulDiv( rc->left, 10, 254);
3160 break;
3161 case MM_HIENGLISH:
3162 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3163 pt.x = MulDiv( rc->left, 100, 254);
3164 break;
3165 case MM_TWIPS:
3166 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3167 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3168 break;
3169 default:
3170 pt.x = pt.y = 0;
3172 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3173 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3175 if(rec_num == mfcomment_chunks + 2)
3177 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3178 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3179 "got %d\n", (short)rec->rdParm[0]);
3180 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3181 "got %d\n", (short)rec->rdParm[1]);
3184 rec_num++;
3185 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3188 end:
3189 HeapFree(GetProcessHeap(), 0, mh);
3190 HeapFree(GetProcessHeap(), 0, enh_header);
3191 DeleteEnhMetaFile(emf);
3193 ReleaseDC(NULL, display_dc);
3196 static void test_GetWinMetaFileBits(void)
3198 UINT mode;
3199 RECT frames[] =
3201 { 1000, 2000, 3000, 6000},
3202 {-1000, 2000, 3000, 6000},
3203 { 1000, -2000, 3000, 6000},
3204 { 1005, 2005, 3000, 6000},
3205 {-1005, -2005, 3000, 6000},
3206 {-1005, -2010, 3000, 6000},
3207 {-1005, 2010, 3000, 6000},
3208 { 0, 0, 1, 1},
3209 { -1, -1, 1, 1},
3210 { 0, 0, 0, 0}
3213 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3215 RECT *rc;
3216 for(rc = frames; rc->right - rc->left > 0; rc++)
3218 getwinmetafilebits(mode, 1, rc);
3219 getwinmetafilebits(mode, 2, rc);
3224 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3225 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3226 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3228 static void test_gdiis(void)
3230 RECT rect = {0,0,100,100};
3231 HDC hdc, hemfDC, hmfDC;
3232 HENHMETAFILE hemf;
3233 HMODULE hgdi32;
3235 /* resolve all the functions */
3236 hgdi32 = GetModuleHandleA("gdi32.dll");
3237 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3238 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3239 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3241 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3243 win_skip("Needed GdiIs* functions are not available\n");
3244 return;
3247 /* try with nothing */
3248 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3249 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3250 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3252 /* try with a metafile */
3253 hmfDC = CreateMetaFileA(NULL);
3254 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3255 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3256 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3257 DeleteMetaFile(CloseMetaFile(hmfDC));
3259 /* try with an enhanced metafile */
3260 hdc = GetDC(NULL);
3261 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3262 ok(hemfDC != NULL, "failed to create emf\n");
3264 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3265 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3266 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3268 hemf = CloseEnhMetaFile(hemfDC);
3269 ok(hemf != NULL, "failed to close EMF\n");
3270 DeleteEnhMetaFile(hemf);
3271 ReleaseDC(NULL,hdc);
3274 static void test_SetEnhMetaFileBits(void)
3276 BYTE data[256];
3277 HENHMETAFILE hemf;
3278 ENHMETAHEADER *emh;
3280 memset(data, 0xAA, sizeof(data));
3281 SetLastError(0xdeadbeef);
3282 hemf = SetEnhMetaFileBits(sizeof(data), data);
3283 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3284 ok(GetLastError() == ERROR_INVALID_DATA ||
3285 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3286 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3288 emh = (ENHMETAHEADER *)data;
3289 memset(emh, 0, sizeof(*emh));
3291 emh->iType = EMR_HEADER;
3292 emh->nSize = sizeof(*emh);
3293 emh->dSignature = ENHMETA_SIGNATURE;
3294 /* emh->nVersion = 0x10000; XP doesn't care about version */
3295 emh->nBytes = sizeof(*emh);
3296 /* emh->nRecords = 1; XP doesn't care about records */
3297 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3299 SetLastError(0xdeadbeef);
3300 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3301 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3302 DeleteEnhMetaFile(hemf);
3304 /* XP refuses to load unaligned EMF */
3305 emh->nBytes++;
3306 SetLastError(0xdeadbeef);
3307 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3308 ok(!hemf ||
3309 broken(hemf != NULL), /* Win9x, WinMe */
3310 "SetEnhMetaFileBits should fail\n");
3311 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3312 DeleteEnhMetaFile(hemf);
3314 emh->dSignature = 0;
3315 emh->nBytes--;
3316 SetLastError(0xdeadbeef);
3317 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3318 ok(!hemf ||
3319 broken(hemf != NULL), /* Win9x, WinMe */
3320 "SetEnhMetaFileBits should fail\n");
3321 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3322 DeleteEnhMetaFile(hemf);
3325 static void test_emf_polybezier(void)
3327 HDC hdcMetafile;
3328 HENHMETAFILE hemf;
3329 POINT pts[4];
3330 BOOL ret;
3332 SetLastError(0xdeadbeef);
3333 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3334 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3336 pts[0].x = pts[0].y = 10;
3337 pts[1].x = pts[1].y = 20;
3338 pts[2].x = pts[2].y = 15;
3339 pts[3].x = pts[3].y = 25;
3340 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3341 ok( ret, "PolyBezierTo failed\n" );
3342 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3343 ok( ret, "PolyBezier failed\n" );
3345 pts[0].x = pts[0].y = 32769;
3346 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3347 ok( ret, "PolyBezier failed\n" );
3348 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3349 ok( ret, "PolyBezierTo failed\n" );
3351 hemf = CloseEnhMetaFile(hdcMetafile);
3352 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3354 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3355 "emf_Bezier", FALSE) != 0)
3357 dump_emf_bits(hemf, "emf_Bezier");
3358 dump_emf_records(hemf, "emf_Bezier");
3361 DeleteEnhMetaFile(hemf);
3364 START_TEST(metafile)
3366 init_function_pointers();
3368 /* For enhanced metafiles (enhmfdrv) */
3369 test_ExtTextOut();
3370 test_ExtTextOutScale();
3371 test_SaveDC();
3372 test_emf_BitBlt();
3373 test_emf_DCBrush();
3374 test_emf_ExtTextOut_on_path();
3375 test_emf_clipping();
3376 test_emf_polybezier();
3378 /* For win-format metafiles (mfdrv) */
3379 test_mf_SaveDC();
3380 test_mf_Blank();
3381 test_mf_Graphics();
3382 test_mf_PatternBrush();
3383 test_mf_DCBrush();
3384 test_CopyMetaFile();
3385 test_SetMetaFileBits();
3386 test_mf_ExtTextOut_on_path();
3387 test_mf_clipping();
3389 /* For metafile conversions */
3390 test_mf_conversions();
3391 test_SetWinMetaFileBits();
3392 test_GetWinMetaFileBits();
3394 test_gdiis();
3395 test_SetEnhMetaFileBits();