gdi32/tests: Add tests for EMF PolyPolyline record creation.
[wine.git] / dlls / gdi32 / tests / metafile.c
blob5b3bd9fbb607d75d7ba2fa5b3c685f7e0ef49496
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 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1376 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1377 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1378 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1379 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1380 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1381 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1382 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1383 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1386 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1389 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1390 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1391 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1392 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1393 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1394 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1395 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1396 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1397 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1398 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1399 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1401 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1402 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1403 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1404 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1405 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1407 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1408 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1409 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1410 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1411 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1412 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1413 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1414 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1415 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1416 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1417 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1418 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1419 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1420 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1421 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1422 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1423 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1424 0x14, 0x00, 0x00, 0x00
1427 /* For debugging or dumping the raw metafiles produced by
1428 * new test functions.
1430 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1431 INT nobj, LPARAM param)
1433 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1434 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1435 return TRUE;
1438 /* For debugging or dumping the raw metafiles produced by
1439 * new test functions.
1442 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1444 BYTE buf[MF_BUFSIZE];
1445 UINT mfsize, i;
1447 if (!winetest_debug) return;
1449 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1450 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1452 printf ("MetaFile %s has bits:\n{\n ", desc);
1453 for (i=0; i<mfsize; i++)
1455 printf ("0x%02x", buf[i]);
1456 if (i == mfsize-1)
1457 printf ("\n");
1458 else if (i % 8 == 7)
1459 printf (",\n ");
1460 else
1461 printf (", ");
1463 printf ("};\n");
1466 /* Compare the metafile produced by a test function with the
1467 * expected raw metafile data in "bits".
1468 * Return value is 0 for a perfect match,
1469 * -1 if lengths aren't equal,
1470 * otherwise returns the number of non-matching bytes.
1473 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1474 const char *desc)
1476 unsigned char buf[MF_BUFSIZE];
1477 UINT mfsize, i;
1478 int diff;
1480 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1481 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1482 if (mfsize < MF_BUFSIZE)
1483 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1484 desc, mfsize, bsize);
1485 else
1486 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1487 desc, mfsize, bsize);
1488 if (mfsize != bsize)
1489 return -1;
1491 diff = 0;
1492 for (i=0; i<bsize; i++)
1494 if (buf[i] != bits[i])
1495 diff++;
1497 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1498 desc, mfsize, bsize, diff);
1500 return diff;
1503 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1505 unsigned char buf[MF_BUFSIZE];
1506 DWORD mfsize, rd_size, i;
1507 int diff;
1508 HANDLE hfile;
1509 BOOL ret;
1511 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1512 assert(hfile != INVALID_HANDLE_VALUE);
1514 mfsize = GetFileSize(hfile, NULL);
1515 assert(mfsize <= MF_BUFSIZE);
1517 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1518 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1520 CloseHandle(hfile);
1522 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1524 if (mfsize != bsize)
1525 return -1;
1527 diff = 0;
1528 for (i=0; i<bsize; i++)
1530 if (buf[i] != bits[i])
1531 diff++;
1533 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1534 desc, mfsize, bsize, diff);
1536 return diff;
1539 /* For debugging or dumping the raw EMFs produced by
1540 * new test functions.
1542 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1544 BYTE buf[MF_BUFSIZE];
1545 UINT mfsize, i;
1547 if (!winetest_debug) return;
1549 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1550 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1552 printf("EMF %s has bits:\n{\n ", desc);
1553 for (i = 0; i < mfsize; i++)
1555 printf ("0x%02x", buf[i]);
1556 if (i == mfsize-1)
1557 printf ("\n");
1558 else if (i % 8 == 7)
1559 printf (",\n ");
1560 else
1561 printf (", ");
1563 printf ("};\n");
1566 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1568 BYTE *emf;
1569 BYTE buf[MF_BUFSIZE];
1570 UINT mfsize, offset;
1572 if (!winetest_debug) return;
1574 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1575 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1577 printf("EMF %s has records:\n", desc);
1579 emf = buf;
1580 offset = 0;
1581 while(offset < mfsize)
1583 EMR *emr = (EMR *)(emf + offset);
1584 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1585 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1586 offset += emr->nSize;
1590 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1592 const BYTE *buf;
1593 DWORD i;
1595 if (!winetest_debug) return;
1597 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1598 buf = (const BYTE *)emr;
1599 for (i = 0; i < emr->nSize; i++)
1601 printf ("0x%02x", buf[i]);
1602 if (i == emr->nSize - 1)
1603 printf ("\n");
1604 else if (i % 8 == 7)
1605 printf (",\n");
1606 else
1607 printf (", ");
1609 printf ("};\n");
1612 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1614 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1615 eto->rclBounds.right, eto->rclBounds.bottom);
1616 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1617 trace("exScale: %f\n", eto->exScale);
1618 trace("eyScale: %f\n", eto->eyScale);
1619 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1620 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1621 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1622 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1623 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1624 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1625 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1628 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1629 const char *desc, BOOL ignore_scaling)
1631 int diff;
1633 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1634 desc, emr1->iType, emr2->iType);
1636 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1637 desc, emr1->nSize, emr2->nSize);
1639 /* iType and nSize mismatches are fatal */
1640 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1642 /* contents of EMR_GDICOMMENT are not interesting */
1643 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1645 /* different Windows versions setup DC scaling differently when
1646 * converting an old style metafile to an EMF.
1648 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1649 emr1->iType == EMR_SETVIEWPORTEXTEX))
1650 return TRUE;
1652 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1654 EMREXTTEXTOUTW *eto1, *eto2;
1656 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1657 memcpy(eto1, emr1, emr1->nSize);
1658 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1659 memcpy(eto2, emr2, emr2->nSize);
1661 /* different Windows versions setup DC scaling differently */
1662 eto1->exScale = eto1->eyScale = 0.0;
1663 eto2->exScale = eto2->eyScale = 0.0;
1665 diff = memcmp(eto1, eto2, emr1->nSize);
1666 if (diff)
1668 dump_EMREXTTEXTOUT(eto1);
1669 dump_EMREXTTEXTOUT(eto2);
1671 HeapFree(GetProcessHeap(), 0, eto1);
1672 HeapFree(GetProcessHeap(), 0, eto2);
1674 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1676 /* We have to take care of NT4 differences here */
1677 diff = memcmp(emr1, emr2, emr1->nSize);
1678 if (diff)
1680 ENHMETARECORD *emr_nt4;
1682 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1683 memcpy(emr_nt4, emr2, emr2->nSize);
1684 /* Correct the nRgnSize field */
1685 emr_nt4->dParm[5] = sizeof(RECT);
1687 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1688 if (!diff)
1689 win_skip("Catered for NT4 differences\n");
1691 HeapFree(GetProcessHeap(), 0, emr_nt4);
1694 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1696 EMRPOLYBEZIER16 *eto1, *eto2;
1698 eto1 = (EMRPOLYBEZIER16*)emr1;
1699 eto2 = (EMRPOLYBEZIER16*)emr2;
1701 diff = eto1->cpts != eto2->cpts;
1702 if(!diff)
1703 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1705 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1707 EMRPOLYBEZIER *eto1, *eto2;
1709 eto1 = (EMRPOLYBEZIER*)emr1;
1710 eto2 = (EMRPOLYBEZIER*)emr2;
1712 diff = eto1->cptl != eto2->cptl;
1713 if(!diff)
1714 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1716 else
1717 diff = memcmp(emr1, emr2, emr1->nSize);
1719 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1721 if (diff)
1723 dump_emf_record(emr1, "expected bits");
1724 dump_emf_record(emr2, "actual bits");
1727 return diff == 0; /* report all non-fatal record mismatches */
1730 /* Compare the EMF produced by a test function with the
1731 * expected raw EMF data in "bits".
1732 * Return value is 0 for a perfect match,
1733 * -1 if lengths aren't equal,
1734 * otherwise returns the number of non-matching bytes.
1736 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1737 UINT bsize, const char *desc,
1738 BOOL ignore_scaling)
1740 unsigned char buf[MF_BUFSIZE];
1741 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1742 const ENHMETAHEADER *emh1, *emh2;
1744 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1745 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1747 /* ENHMETAHEADER size could differ, depending on platform */
1748 diff_nt4 = sizeof(SIZEL);
1749 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1751 if (mfsize < MF_BUFSIZE)
1753 ok(mfsize == bsize ||
1754 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1755 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1756 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1758 else
1759 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1760 desc, mfsize, bsize);
1762 /* basic things must match */
1763 emh1 = (const ENHMETAHEADER *)bits;
1764 emh2 = (const ENHMETAHEADER *)buf;
1765 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1766 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1767 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1768 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1770 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1771 ok(emh1->nSize == emh2->nSize ||
1772 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1773 broken(emh1->nSize - diff_9x == emh2->nSize),
1774 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1775 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1776 ok(emh1->nBytes == emh2->nBytes ||
1777 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1778 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1779 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1780 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1782 offset1 = emh1->nSize;
1783 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1784 while (offset1 < emh1->nBytes)
1786 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1787 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1789 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1790 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1792 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1794 /* We have already bailed out if iType or nSize don't match */
1795 offset1 += emr1->nSize;
1796 offset2 += emr2->nSize;
1798 return 0;
1802 /* tests blitting to an EMF */
1803 static void test_emf_BitBlt(void)
1805 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1806 HBITMAP hBitmap, hOldBitmap;
1807 HENHMETAFILE hMetafile;
1808 #define BMP_DIM 4
1809 BITMAPINFOHEADER bmih =
1811 sizeof(BITMAPINFOHEADER),
1812 BMP_DIM,/* biWidth */
1813 BMP_DIM,/* biHeight */
1814 1, /* biPlanes */
1815 24, /* biBitCount */
1816 BI_RGB, /* biCompression */
1817 0, /* biXPelsPerMeter */
1818 0, /* biYPelsPerMeter */
1819 0, /* biClrUsed */
1820 0, /* biClrImportant */
1822 void *bits;
1823 BOOL ret;
1825 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1826 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1828 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1829 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1830 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1831 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1832 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1833 DIB_RGB_COLORS, &bits, NULL, 0);
1834 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1836 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1837 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1839 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1840 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1841 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1843 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1844 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1845 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1846 ok( ret, "BitBlt(WHITENESS) failed\n" );
1848 hMetafile = CloseEnhMetaFile(hdcMetafile);
1849 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1851 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1852 "emf_BitBlt", FALSE) != 0)
1854 dump_emf_bits(hMetafile, "emf_BitBlt");
1855 dump_emf_records(hMetafile, "emf_BitBlt");
1858 SelectObject(hdcBitmap, hOldBitmap);
1859 DeleteObject(hBitmap);
1860 DeleteDC(hdcBitmap);
1861 DeleteDC(hdcDisplay);
1862 #undef BMP_DIM
1865 static void test_emf_DCBrush(void)
1867 HDC hdcMetafile;
1868 HENHMETAFILE hMetafile;
1869 HBRUSH hBrush;
1870 HPEN hPen;
1871 BOOL ret;
1872 COLORREF color;
1874 if (!pSetDCBrushColor || !pSetDCPenColor)
1876 win_skip( "SetDCBrush/PenColor not supported\n" );
1877 return;
1880 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1881 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1883 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1884 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1886 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1887 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1889 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1890 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1892 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1893 ok( color == 0, "SetDCPenColor returned %x\n", color );
1895 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1897 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1898 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1900 hMetafile = CloseEnhMetaFile(hdcMetafile);
1901 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1903 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1904 "emf_DC_Brush", FALSE ) != 0)
1906 dump_emf_bits(hMetafile, "emf_DC_Brush");
1907 dump_emf_records(hMetafile, "emf_DC_Brush");
1909 ret = DeleteEnhMetaFile(hMetafile);
1910 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1911 ret = DeleteObject(hBrush);
1912 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1913 ret = DeleteObject(hPen);
1914 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1917 /* Test a blank metafile. May be used as a template for new tests. */
1919 static void test_mf_Blank(void)
1921 HDC hdcMetafile;
1922 HMETAFILE hMetafile;
1923 INT caps;
1924 BOOL ret;
1925 INT type;
1927 hdcMetafile = CreateMetaFileA(NULL);
1928 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1929 trace("hdcMetafile %p\n", hdcMetafile);
1931 /* Tests on metafile initialization */
1932 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1933 ok (caps == DT_METAFILE,
1934 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1936 hMetafile = CloseMetaFile(hdcMetafile);
1937 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1938 type = GetObjectType(hMetafile);
1939 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1940 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1942 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1943 "mf_blank") != 0)
1945 dump_mf_bits(hMetafile, "mf_Blank");
1946 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1949 ret = DeleteMetaFile(hMetafile);
1950 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1953 static void test_CopyMetaFile(void)
1955 HDC hdcMetafile;
1956 HMETAFILE hMetafile, hmf_copy;
1957 BOOL ret;
1958 char temp_path[MAX_PATH];
1959 char mf_name[MAX_PATH];
1960 INT type;
1962 hdcMetafile = CreateMetaFileA(NULL);
1963 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1964 trace("hdcMetafile %p\n", hdcMetafile);
1966 hMetafile = CloseMetaFile(hdcMetafile);
1967 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1968 type = GetObjectType(hMetafile);
1969 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1971 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1972 "mf_blank") != 0)
1974 dump_mf_bits(hMetafile, "mf_Blank");
1975 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1978 GetTempPathA(MAX_PATH, temp_path);
1979 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1981 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1982 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1984 type = GetObjectType(hmf_copy);
1985 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1987 ret = DeleteMetaFile(hMetafile);
1988 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1990 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1992 dump_mf_bits(hmf_copy, "mf_Blank");
1993 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1996 ret = DeleteMetaFile(hmf_copy);
1997 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1999 DeleteFileA(mf_name);
2002 static void test_SetMetaFileBits(void)
2004 HMETAFILE hmf;
2005 INT type;
2006 BOOL ret;
2007 BYTE buf[256];
2008 METAHEADER *mh;
2010 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2011 trace("hmf %p\n", hmf);
2012 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2013 type = GetObjectType(hmf);
2014 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
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 /* NULL data crashes XP SP1 */
2026 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2028 /* Now with zero size */
2029 SetLastError(0xdeadbeef);
2030 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2031 trace("hmf %p\n", hmf);
2032 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2033 ok(GetLastError() == ERROR_INVALID_DATA ||
2034 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2035 "wrong error %d\n", GetLastError());
2037 /* Now with odd size */
2038 SetLastError(0xdeadbeef);
2039 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2040 trace("hmf %p\n", hmf);
2041 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2042 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2044 /* Now with zeroed out header fields */
2045 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2046 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2047 mh = (METAHEADER *)buf;
2048 /* corruption of any of the below fields leads to a failure */
2049 mh->mtType = 0;
2050 mh->mtVersion = 0;
2051 mh->mtHeaderSize = 0;
2052 SetLastError(0xdeadbeef);
2053 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2054 trace("hmf %p\n", hmf);
2055 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2056 ok(GetLastError() == ERROR_INVALID_DATA ||
2057 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2058 "wrong error %d\n", GetLastError());
2060 /* Now with corrupted mtSize field */
2061 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2062 mh = (METAHEADER *)buf;
2063 /* corruption of mtSize doesn't lead to a failure */
2064 mh->mtSize *= 2;
2065 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2066 trace("hmf %p\n", hmf);
2067 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2069 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2071 dump_mf_bits(hmf, "mf_Graphics");
2072 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2075 ret = DeleteMetaFile(hmf);
2076 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2078 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2079 /* Now with zeroed out mtSize field */
2080 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2081 mh = (METAHEADER *)buf;
2082 /* zeroing mtSize doesn't lead to a failure */
2083 mh->mtSize = 0;
2084 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2085 trace("hmf %p\n", hmf);
2086 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2088 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2090 dump_mf_bits(hmf, "mf_Graphics");
2091 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2094 ret = DeleteMetaFile(hmf);
2095 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2096 #endif
2099 /* Simple APIs from mfdrv/graphics.c
2102 static void test_mf_Graphics(void)
2104 HDC hdcMetafile;
2105 HMETAFILE hMetafile;
2106 POINT oldpoint;
2107 BOOL ret;
2109 hdcMetafile = CreateMetaFileA(NULL);
2110 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2111 trace("hdcMetafile %p\n", hdcMetafile);
2113 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2114 ok( ret, "MoveToEx error %d.\n", GetLastError());
2115 ret = LineTo(hdcMetafile, 2, 2);
2116 ok( ret, "LineTo error %d.\n", GetLastError());
2117 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2118 ok( ret, "MoveToEx error %d.\n", GetLastError());
2120 /* oldpoint gets garbage under Win XP, so the following test would
2121 * work under Wine but fails under Windows:
2123 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2124 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2125 * oldpoint.x, oldpoint.y);
2128 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2129 ok( ret, "Ellipse error %d.\n", GetLastError());
2131 hMetafile = CloseMetaFile(hdcMetafile);
2132 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2133 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2135 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2136 "mf_Graphics") != 0)
2138 dump_mf_bits(hMetafile, "mf_Graphics");
2139 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2142 ret = DeleteMetaFile(hMetafile);
2143 ok( ret, "DeleteMetaFile(%p) error %d\n",
2144 hMetafile, GetLastError());
2147 static void test_mf_PatternBrush(void)
2149 HDC hdcMetafile;
2150 HMETAFILE hMetafile;
2151 LOGBRUSH *orig_lb;
2152 HBRUSH hBrush;
2153 BOOL ret;
2155 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2157 orig_lb->lbStyle = BS_PATTERN;
2158 orig_lb->lbColor = RGB(0, 0, 0);
2159 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2160 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2162 hBrush = CreateBrushIndirect (orig_lb);
2163 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2165 hdcMetafile = CreateMetaFileA(NULL);
2166 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2167 trace("hdcMetafile %p\n", hdcMetafile);
2169 hBrush = SelectObject(hdcMetafile, hBrush);
2170 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2172 hMetafile = CloseMetaFile(hdcMetafile);
2173 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2174 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2176 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2177 "mf_Pattern_Brush") != 0)
2179 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2180 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2183 ret = DeleteMetaFile(hMetafile);
2184 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2185 ret = DeleteObject(hBrush);
2186 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2187 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2188 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2189 GetLastError());
2190 HeapFree (GetProcessHeap(), 0, orig_lb);
2193 static void test_mf_DCBrush(void)
2195 HDC hdcMetafile;
2196 HMETAFILE hMetafile;
2197 HBRUSH hBrush;
2198 HPEN hPen;
2199 BOOL ret;
2200 COLORREF color;
2202 if (!pSetDCBrushColor || !pSetDCPenColor)
2204 win_skip( "SetDCBrush/PenColor not supported\n" );
2205 return;
2208 hdcMetafile = CreateMetaFileA(NULL);
2209 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2211 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2212 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2214 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2215 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2217 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2218 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2220 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2221 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2223 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2225 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2226 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2228 hMetafile = CloseMetaFile(hdcMetafile);
2229 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2231 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2233 dump_mf_bits(hMetafile, "mf_DCBrush");
2234 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2236 ret = DeleteMetaFile(hMetafile);
2237 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2240 static void test_mf_ExtTextOut_on_path(void)
2242 HDC hdcMetafile;
2243 HMETAFILE hMetafile;
2244 BOOL ret;
2245 static const INT dx[4] = { 3, 5, 8, 12 };
2247 hdcMetafile = CreateMetaFileA(NULL);
2248 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2249 trace("hdcMetafile %p\n", hdcMetafile);
2251 ret = BeginPath(hdcMetafile);
2252 ok(!ret, "BeginPath on metafile DC should fail\n");
2254 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2255 ok(ret, "ExtTextOut error %d\n", GetLastError());
2257 ret = EndPath(hdcMetafile);
2258 ok(!ret, "EndPath on metafile DC should fail\n");
2260 hMetafile = CloseMetaFile(hdcMetafile);
2261 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2263 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2264 "mf_TextOut_on_path") != 0)
2266 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2267 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2270 ret = DeleteMetaFile(hMetafile);
2271 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2274 static void test_emf_ExtTextOut_on_path(void)
2276 HWND hwnd;
2277 HDC hdcDisplay, hdcMetafile;
2278 HENHMETAFILE hMetafile;
2279 BOOL ret;
2280 static const INT dx[4] = { 3, 5, 8, 12 };
2282 /* Win9x doesn't play EMFs on invisible windows */
2283 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2284 0, 0, 200, 200, 0, 0, 0, NULL);
2285 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2287 hdcDisplay = GetDC(hwnd);
2288 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2290 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2291 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2293 ret = BeginPath(hdcMetafile);
2294 ok(ret, "BeginPath error %d\n", GetLastError());
2296 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2297 ok(ret, "ExtTextOut error %d\n", GetLastError());
2299 ret = EndPath(hdcMetafile);
2300 ok(ret, "EndPath error %d\n", GetLastError());
2302 hMetafile = CloseEnhMetaFile(hdcMetafile);
2303 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2305 /* this doesn't succeed yet: EMF has correct size, all EMF records
2306 * are there, but their contents don't match for different reasons.
2308 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2309 "emf_TextOut_on_path", FALSE) != 0)
2311 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2312 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2315 ret = DeleteEnhMetaFile(hMetafile);
2316 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2317 ret = ReleaseDC(hwnd, hdcDisplay);
2318 ok(ret, "ReleaseDC error %d\n", GetLastError());
2319 DestroyWindow(hwnd);
2322 static const unsigned char EMF_CLIPPING[] =
2324 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2326 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2328 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2329 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2330 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2331 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2333 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2334 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2336 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2337 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2338 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2339 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2340 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2341 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2342 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2343 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2344 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2345 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2346 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2347 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2348 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2349 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2352 static void translate( POINT *pt, UINT count, const XFORM *xform )
2354 while (count--)
2356 FLOAT x = (FLOAT)pt->x;
2357 FLOAT y = (FLOAT)pt->y;
2358 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2359 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2360 pt++;
2364 /* Compare rectangles allowing rounding errors */
2365 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2367 return abs(rc1->left - rc2->left) <= 1 &&
2368 abs(rc1->top - rc2->top) <= 1 &&
2369 abs(rc1->right - rc2->right) <= 1 &&
2370 abs(rc1->bottom - rc2->bottom) <= 1;
2373 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2374 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2376 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2378 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2379 union _rgn
2381 RGNDATA data;
2382 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2384 const union _rgn *rgn1;
2385 union _rgn rgn2;
2386 RECT rect, rc_transformed;
2387 const RECT *rc = (const RECT *)param;
2388 HRGN hrgn;
2389 XFORM xform;
2390 INT ret;
2391 BOOL is_win9x;
2393 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2394 clip->cbRgnData, clip->iMode);
2396 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2397 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2398 "too small data block: %u bytes\n", clip->cbRgnData);
2399 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2400 return 0;
2402 rgn1 = (const union _rgn *)clip->RgnData;
2404 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2405 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2406 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2407 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2408 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2410 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2412 rect = *(const RECT *)rgn1->data.Buffer;
2413 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2414 ok(EqualRect(&rect, rc), "rects don't match\n");
2416 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2417 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2418 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2419 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2420 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2421 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2423 hrgn = CreateRectRgn(0, 0, 0, 0);
2425 memset(&xform, 0, sizeof(xform));
2426 SetLastError(0xdeadbeef);
2427 ret = GetWorldTransform(hdc, &xform);
2428 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2429 if (!is_win9x)
2430 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2432 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2434 ret = GetClipRgn(hdc, hrgn);
2435 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2437 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2439 ret = GetClipRgn(hdc, hrgn);
2440 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2442 /* Win9x returns empty clipping region */
2443 if (is_win9x) return 1;
2445 ret = GetRegionData(hrgn, 0, NULL);
2446 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2448 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2449 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2451 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2452 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2453 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2454 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2455 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2457 rect = rgn2.data.rdh.rcBound;
2458 rc_transformed = *rc;
2459 translate((POINT *)&rc_transformed, 2, &xform);
2460 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2461 rc_transformed.right, rc_transformed.bottom);
2462 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2464 rect = *(const RECT *)rgn2.data.Buffer;
2465 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2466 rc_transformed = *rc;
2467 translate((POINT *)&rc_transformed, 2, &xform);
2468 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2469 rc_transformed.right, rc_transformed.bottom);
2470 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2472 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2473 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2474 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2475 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2476 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2477 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2479 DeleteObject(hrgn);
2481 return 1;
2484 static void test_emf_clipping(void)
2486 static const RECT rc = { 0, 0, 100, 100 };
2487 RECT rc_clip = { 100, 100, 1024, 1024 };
2488 HWND hwnd;
2489 HDC hdc;
2490 HENHMETAFILE hemf;
2491 HRGN hrgn;
2492 INT ret;
2493 RECT rc_res, rc_sclip;
2495 SetLastError(0xdeadbeef);
2496 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2497 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2499 /* Need to write something to the emf, otherwise Windows won't play it back */
2500 LineTo(hdc, 1, 1);
2502 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2503 ret = SelectClipRgn(hdc, hrgn);
2504 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2506 SetLastError(0xdeadbeef);
2507 hemf = CloseEnhMetaFile(hdc);
2508 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2510 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2511 "emf_clipping", FALSE) != 0)
2513 dump_emf_bits(hemf, "emf_clipping");
2514 dump_emf_records(hemf, "emf_clipping");
2517 DeleteObject(hrgn);
2519 /* Win9x doesn't play EMFs on invisible windows */
2520 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2521 0, 0, 200, 200, 0, 0, 0, NULL);
2522 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2524 hdc = GetDC(hwnd);
2526 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2527 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2529 DeleteEnhMetaFile(hemf);
2530 ReleaseDC(hwnd, hdc);
2531 DestroyWindow(hwnd);
2533 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2535 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2536 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2537 SelectClipRgn(hdc, hrgn);
2538 SetRect(&rc_res, -1, -1, -1, -1);
2539 ret = GetClipBox(hdc, &rc_res);
2540 ok(ret == SIMPLEREGION, "got %d\n", ret);
2541 ok(EqualRect(&rc_res, &rc_sclip),
2542 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2543 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2544 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2546 OffsetRect(&rc_sclip, -100, -100);
2547 ret = OffsetClipRgn(hdc, -100, -100);
2548 ok(ret == SIMPLEREGION, "got %d\n", ret);
2549 SetRect(&rc_res, -1, -1, -1, -1);
2550 ret = GetClipBox(hdc, &rc_res);
2551 ok(ret == SIMPLEREGION, "got %d\n", ret);
2552 ok(EqualRect(&rc_res, &rc_sclip),
2553 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2554 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2555 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2557 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2558 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2559 if (ret == COMPLEXREGION)
2561 /* XP returns COMPLEXREGION although region contains only 1 rect */
2562 ret = GetClipRgn(hdc, hrgn);
2563 ok(ret == 1, "expected 1, got %d\n", ret);
2564 ret = rgn_rect_count(hrgn);
2565 ok(ret == 1, "expected 1, got %d\n", ret);
2567 SetRect(&rc_res, -1, -1, -1, -1);
2568 ret = GetClipBox(hdc, &rc_res);
2569 ok(ret == SIMPLEREGION, "got %d\n", ret);
2570 ok(EqualRect(&rc_res, &rc),
2571 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2572 rc.left, rc.top, rc.right, rc.bottom,
2573 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2575 SetRect(&rc_sclip, 0, 0, 100, 50);
2576 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2577 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2578 if (ret == COMPLEXREGION)
2580 /* XP returns COMPLEXREGION although region contains only 1 rect */
2581 ret = GetClipRgn(hdc, hrgn);
2582 ok(ret == 1, "expected 1, got %d\n", ret);
2583 ret = rgn_rect_count(hrgn);
2584 ok(ret == 1, "expected 1, got %d\n", ret);
2586 SetRect(&rc_res, -1, -1, -1, -1);
2587 ret = GetClipBox(hdc, &rc_res);
2588 ok(ret == SIMPLEREGION, "got %d\n", ret);
2589 ok(EqualRect(&rc_res, &rc_sclip),
2590 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2591 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2592 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2594 hemf = CloseEnhMetaFile(hdc);
2595 DeleteEnhMetaFile(hemf);
2596 DeleteObject(hrgn);
2599 static const unsigned char MF_CLIP_BITS[] = {
2600 /* METAHEADER */
2601 0x01, 0x00, /* mtType */
2602 0x09, 0x00, /* mtHeaderSize */
2603 0x00, 0x03, /* mtVersion */
2604 0x32, 0x00, 0x00, 0x00, /* mtSize */
2605 0x01, 0x00, /* mtNoObjects */
2606 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2607 0x00, 0x00, /* reserved */
2609 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2610 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2611 0xff, 0x06, /* META_CREATEREGION */
2612 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2613 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2614 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2615 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2616 0x02, 0x00,
2618 /* METARECORD for SelectObject */
2619 0x04, 0x00, 0x00, 0x00,
2620 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2621 0x00, 0x00,
2623 /* METARECORD */
2624 0x04, 0x00, 0x00, 0x00,
2625 0xf0, 0x01, /* META_DELETEOBJECT */
2626 0x00, 0x00,
2628 /* METARECORD for MoveTo(1,0x30) */
2629 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2630 0x14, 0x02, /* META_MOVETO */
2631 0x30, 0x00, /* y */
2632 0x01, 0x00, /* x */
2634 /* METARECORD for LineTo(0x20, 0x30) */
2635 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2636 0x13, 0x02, /* META_LINETO */
2637 0x30, 0x00, /* y */
2638 0x20, 0x00, /* x */
2640 /* EOF */
2641 0x03, 0x00, 0x00, 0x00,
2642 0x00, 0x00
2645 static int clip_mf_enum_proc_seen_selectclipregion;
2646 static int clip_mf_enum_proc_seen_selectobject;
2648 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2649 METARECORD *mr, int n_objs, LPARAM param)
2651 switch (mr->rdFunction) {
2652 case META_SELECTCLIPREGION:
2653 clip_mf_enum_proc_seen_selectclipregion++;
2654 break;
2655 case META_SELECTOBJECT:
2656 clip_mf_enum_proc_seen_selectobject++;
2657 break;
2659 return 1;
2662 static void test_mf_clipping(void)
2664 /* left top right bottom */
2665 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2666 HWND hwnd;
2667 HDC hdc;
2668 HMETAFILE hmf;
2669 HRGN hrgn;
2670 INT ret;
2672 SetLastError(0xdeadbeef);
2673 hdc = CreateMetaFileA(NULL);
2674 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2676 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2677 ret = SelectClipRgn(hdc, hrgn);
2678 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2679 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2681 /* Draw a line that starts off left of the clip region and ends inside it */
2682 MoveToEx(hdc, 0x1, 0x30, NULL);
2683 LineTo(hdc, 0x20, 0x30);
2685 SetLastError(0xdeadbeef);
2686 hmf = CloseMetaFile(hdc);
2687 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2689 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2690 "mf_clipping") != 0)
2692 dump_mf_bits(hmf, "mf_clipping");
2695 DeleteObject(hrgn);
2697 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2698 0, 0, 200, 200, 0, 0, 0, NULL);
2699 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2701 hdc = GetDC(hwnd);
2703 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2704 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2706 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2707 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2708 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2709 ok(clip_mf_enum_proc_seen_selectobject == 1,
2710 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2712 DeleteMetaFile(hmf);
2713 ReleaseDC(hwnd, hdc);
2714 DestroyWindow(hwnd);
2717 static const unsigned char MF_PATH_BITS[] =
2719 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2720 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2721 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2722 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2723 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2724 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2725 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2726 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2727 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2728 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2729 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2732 static void test_mf_GetPath(void)
2734 HDC hdc;
2735 HMETAFILE hmf;
2736 BOOL ret;
2737 int size;
2739 SetLastError(0xdeadbeef);
2740 hdc = CreateMetaFileA(NULL);
2741 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2743 BeginPath(hdc);
2744 ret = MoveToEx(hdc, 50, 50, NULL);
2745 ok( ret, "MoveToEx error %d.\n", GetLastError());
2746 ret = LineTo(hdc, 50, 150);
2747 ok( ret, "LineTo error %d.\n", GetLastError());
2748 ret = LineTo(hdc, 150, 150);
2749 ok( ret, "LineTo error %d.\n", GetLastError());
2750 ret = LineTo(hdc, 150, 50);
2751 ok( ret, "LineTo error %d.\n", GetLastError());
2752 ret = LineTo(hdc, 50, 50);
2753 ok( ret, "LineTo error %d.\n", GetLastError());
2754 Rectangle(hdc, 10, 10, 20, 20);
2755 EndPath(hdc);
2757 size = GetPath(hdc, NULL, NULL, 0);
2758 ok( size == -1, "GetPath returned %d.\n", size);
2760 hmf = CloseMetaFile(hdc);
2761 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2763 if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
2765 dump_mf_bits(hmf, "mf_GetPath");
2766 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2769 ret = DeleteMetaFile(hmf);
2770 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2773 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2775 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2776 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2777 /* When using MM_TEXT Win9x does not update the mapping mode
2778 * until a record is played which actually outputs something */
2779 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2780 LPtoDP(hdc, mapping, 2);
2781 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2782 lpEMFR->iType, lpEMFR->nSize,
2783 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2785 if (lpEMFR->iType == EMR_LINETO)
2787 INT x0, y0, x1, y1;
2788 if (!lpMFP || lpMFP->mm == MM_TEXT)
2790 x0 = 0;
2791 y0 = 0;
2792 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2793 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2795 else
2797 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2799 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2800 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2801 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2802 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2804 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2805 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2806 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2807 x0, y0, x1, y1);
2809 return TRUE;
2812 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2814 HDC hdcMf;
2815 HMETAFILE hmf;
2816 HENHMETAFILE hemf;
2817 BOOL ret;
2818 UINT size;
2819 LPBYTE pBits;
2821 hdcMf = CreateMetaFileA(NULL);
2822 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2823 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2824 ok(ret, "LineTo failed with error %d\n", GetLastError());
2825 hmf = CloseMetaFile(hdcMf);
2826 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2828 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2830 dump_mf_bits(hmf, "mf_LineTo");
2831 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2834 size = GetMetaFileBitsEx(hmf, 0, NULL);
2835 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2836 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2837 GetMetaFileBitsEx(hmf, size, pBits);
2838 DeleteMetaFile(hmf);
2839 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2840 HeapFree(GetProcessHeap(), 0, pBits);
2841 return hemf;
2844 static void test_mf_conversions(void)
2846 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2848 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2849 HENHMETAFILE hemf;
2850 METAFILEPICT mfp;
2851 RECT rect = { 0, 0, 100, 100 };
2852 mfp.mm = MM_ANISOTROPIC;
2853 mfp.xExt = 100;
2854 mfp.yExt = 100;
2855 mfp.hMF = NULL;
2856 hemf = create_converted_emf(&mfp);
2858 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2859 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2861 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2862 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2865 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2867 DeleteEnhMetaFile(hemf);
2868 DeleteDC(hdcOffscreen);
2871 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2873 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2874 HENHMETAFILE hemf;
2875 METAFILEPICT mfp;
2876 RECT rect = { 0, 0, 100, 100 };
2877 mfp.mm = MM_TEXT;
2878 mfp.xExt = 0;
2879 mfp.yExt = 0;
2880 mfp.hMF = NULL;
2881 hemf = create_converted_emf(&mfp);
2883 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2884 "emf_LineTo MM_TEXT", TRUE) != 0)
2886 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2887 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2890 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2892 DeleteEnhMetaFile(hemf);
2893 DeleteDC(hdcOffscreen);
2896 trace("Testing MF->EMF conversion (NULL mfp)\n");
2898 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2899 HENHMETAFILE hemf;
2900 RECT rect = { 0, 0, 100, 100 };
2901 hemf = create_converted_emf(NULL);
2903 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2904 "emf_LineTo NULL", TRUE) != 0)
2906 dump_emf_bits(hemf, "emf_LineTo NULL");
2907 dump_emf_records(hemf, "emf_LineTo NULL");
2910 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2912 DeleteEnhMetaFile(hemf);
2913 DeleteDC(hdcOffscreen);
2917 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2918 LONG mm, LONG xExt, LONG yExt,
2919 RECTL * rclBounds, RECTL * rclFrame)
2921 METAFILEPICT mfp;
2922 METAFILEPICT * mfpPtr = NULL;
2923 HENHMETAFILE emf;
2924 ENHMETAHEADER header;
2925 UINT res;
2927 if (!mfpIsNull)
2929 mfp.mm = mm;
2930 mfp.xExt = xExt;
2931 mfp.yExt = yExt;
2932 mfpPtr = &mfp;
2935 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2936 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2937 if (!emf) return FALSE;
2938 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2939 ok(res != 0, "GetEnhMetaHeader failed\n");
2940 DeleteEnhMetaFile(emf);
2941 if (!res) return FALSE;
2943 *rclBounds = header.rclBounds;
2944 *rclFrame = header.rclFrame;
2945 return TRUE;
2948 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2949 LONG mm, LONG xExt, LONG yExt,
2950 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2952 RECTL rclBounds, rclFrame;
2954 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2956 const char * msg;
2957 char buf[64];
2959 if (mfpIsNull)
2961 msg = "mfp == NULL";
2963 else
2965 const char * mm_str;
2966 switch (mm)
2968 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2969 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2970 default: mm_str = "Unexpected";
2972 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2973 msg = buf;
2976 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2977 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2978 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2979 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2980 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2981 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2982 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2983 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2987 static void test_SetWinMetaFileBits(void)
2989 HMETAFILE wmf;
2990 HDC wmfDC;
2991 BYTE * buffer;
2992 UINT buffer_size;
2993 RECT rect;
2994 UINT res;
2995 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2996 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2997 RECTL rclBounds, rclFrame;
2998 HDC dc;
2999 LONG diffx, diffy;
3001 wmfDC = CreateMetaFileA(NULL);
3002 ok(wmfDC != NULL, "CreateMetaFile failed\n");
3003 if (!wmfDC) return;
3005 SetWindowExtEx(wmfDC, 100, 100, NULL);
3006 rect.left = rect.top = 0;
3007 rect.right = rect.bottom = 50;
3008 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
3009 wmf = CloseMetaFile(wmfDC);
3010 ok(wmf != NULL, "Metafile creation failed\n");
3011 if (!wmf) return;
3013 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
3014 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
3015 if (buffer_size == 0)
3017 DeleteMetaFile(wmf);
3018 return;
3021 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
3022 ok(buffer != NULL, "HeapAlloc failed\n");
3023 if (!buffer)
3025 DeleteMetaFile(wmf);
3026 return;
3029 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
3030 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3031 DeleteMetaFile(wmf);
3032 if (res != buffer_size)
3034 HeapFree(GetProcessHeap(), 0, buffer);
3035 return;
3038 /* Get the reference bounds and frame */
3039 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3040 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3042 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
3043 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
3044 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3046 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3047 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3048 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
3049 if (diffx < 0) diffx = -diffx;
3050 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3052 dc = CreateCompatibleDC(NULL);
3054 /* Allow 1 mm difference (rounding errors) */
3055 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
3056 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
3057 if (diffx < 0) diffx = -diffx;
3058 if (diffy < 0) diffy = -diffy;
3059 todo_wine
3061 ok(diffx <= 1 && diffy <= 1,
3062 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3063 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
3066 /* Allow 1 mm difference (rounding errors) */
3067 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
3068 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
3069 if (diffx < 0) diffx = -diffx;
3070 if (diffy < 0) diffy = -diffy;
3071 todo_wine
3073 ok(diffx <= 1 && diffy <= 1,
3074 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3075 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
3077 DeleteDC(dc);
3079 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3080 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3082 /* If xExt or yExt is zero or negative, the whole device surface is used */
3083 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3084 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3085 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3086 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3087 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3088 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3089 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3090 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3091 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3092 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3093 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3094 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3096 /* MSDN says that negative xExt and yExt values specify a ratio.
3097 Check that this is wrong and the whole device surface is used */
3098 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3099 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3101 /* Ordinary conversions */
3103 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3105 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3106 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3107 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3108 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3111 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3113 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3114 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3115 ok(rclBounds.left == 0 && rclBounds.top == 0,
3116 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3118 /* Wine has a rounding error */
3119 diffx = rclBounds.right - rclBounds.bottom;
3120 if (diffx < 0) diffx = -diffx;
3121 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3124 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3126 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3127 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3130 HeapFree(GetProcessHeap(), 0, buffer);
3133 static BOOL near_match(int x, int y)
3135 int epsilon = min(abs(x), abs(y));
3137 epsilon = max(epsilon/100, 2);
3139 if(x < y - epsilon || x > y + epsilon) return FALSE;
3140 return TRUE;
3143 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3145 HENHMETAFILE emf;
3146 HDC display_dc, emf_dc;
3147 ENHMETAHEADER *enh_header;
3148 UINT size, emf_size, i;
3149 WORD check = 0;
3150 DWORD rec_num = 0;
3151 METAHEADER *mh = NULL;
3152 METARECORD *rec;
3153 INT horz_res, vert_res, horz_size, vert_size;
3154 INT curve_caps, line_caps, poly_caps;
3156 display_dc = GetDC(NULL);
3157 ok(display_dc != NULL, "display_dc is NULL\n");
3159 horz_res = GetDeviceCaps(display_dc, HORZRES);
3160 vert_res = GetDeviceCaps(display_dc, VERTRES);
3161 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3162 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3164 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3165 ok(emf_dc != NULL, "emf_dc is NULL\n");
3167 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3168 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3170 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3171 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3173 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3174 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3176 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3177 Rectangle(emf_dc, 0, 0, 1000, 20);
3178 emf = CloseEnhMetaFile(emf_dc);
3179 ok(emf != NULL, "emf is NULL\n");
3181 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3182 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3183 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3184 DeleteEnhMetaFile(emf);
3185 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3186 have different resolutions */
3187 enh_header->szlDevice.cx *= scale;
3188 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3189 ok(emf != NULL, "emf is NULL\n");
3190 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3192 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3193 ok(size ||
3194 broken(size == 0), /* some versions of winxp fail for some reason */
3195 "GetWinMetaFileBits returns 0\n");
3196 if(!size) goto end;
3197 mh = HeapAlloc(GetProcessHeap(), 0, size);
3198 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3200 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3201 ok(check == 0, "check %04x\n", check);
3203 rec = (METARECORD*)(mh + 1);
3205 while(rec->rdSize && rec->rdFunction)
3207 const DWORD chunk_size = 0x2000;
3208 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3210 if(rec_num < mfcomment_chunks)
3212 DWORD this_chunk_size = chunk_size;
3214 if(rec_num == mfcomment_chunks - 1)
3215 this_chunk_size = emf_size - rec_num * chunk_size;
3217 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3218 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3219 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3220 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3221 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3222 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3223 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3224 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3225 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3226 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3227 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3228 /* parm[8] is the checksum, tested above */
3229 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3230 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3231 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3232 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3233 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3234 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3235 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3236 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 */
3237 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3238 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3241 else if(rec_num == mfcomment_chunks)
3243 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3244 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3246 else if(rec_num == mfcomment_chunks + 1)
3248 POINT pt;
3249 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3250 switch(mode)
3252 case MM_TEXT:
3253 case MM_ISOTROPIC:
3254 case MM_ANISOTROPIC:
3255 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3256 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3257 break;
3258 case MM_LOMETRIC:
3259 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3260 pt.x = MulDiv( rc->left, 1, 10);
3261 break;
3262 case MM_HIMETRIC:
3263 pt.y = -rc->top + 1;
3264 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3265 break;
3266 case MM_LOENGLISH:
3267 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3268 pt.x = MulDiv( rc->left, 10, 254);
3269 break;
3270 case MM_HIENGLISH:
3271 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3272 pt.x = MulDiv( rc->left, 100, 254);
3273 break;
3274 case MM_TWIPS:
3275 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3276 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3277 break;
3278 default:
3279 pt.x = pt.y = 0;
3281 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3282 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3284 if(rec_num == mfcomment_chunks + 2)
3286 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3287 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3288 "got %d\n", (short)rec->rdParm[0]);
3289 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3290 "got %d\n", (short)rec->rdParm[1]);
3293 rec_num++;
3294 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3297 end:
3298 HeapFree(GetProcessHeap(), 0, mh);
3299 HeapFree(GetProcessHeap(), 0, enh_header);
3300 DeleteEnhMetaFile(emf);
3302 ReleaseDC(NULL, display_dc);
3305 static void test_GetWinMetaFileBits(void)
3307 UINT mode;
3308 RECT frames[] =
3310 { 1000, 2000, 3000, 6000},
3311 {-1000, 2000, 3000, 6000},
3312 { 1000, -2000, 3000, 6000},
3313 { 1005, 2005, 3000, 6000},
3314 {-1005, -2005, 3000, 6000},
3315 {-1005, -2010, 3000, 6000},
3316 {-1005, 2010, 3000, 6000},
3317 { 0, 0, 1, 1},
3318 { -1, -1, 1, 1},
3319 { 0, 0, 0, 0}
3322 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3324 RECT *rc;
3325 for(rc = frames; rc->right - rc->left > 0; rc++)
3327 getwinmetafilebits(mode, 1, rc);
3328 getwinmetafilebits(mode, 2, rc);
3333 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3334 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3335 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3337 static void test_gdiis(void)
3339 RECT rect = {0,0,100,100};
3340 HDC hdc, hemfDC, hmfDC;
3341 HENHMETAFILE hemf;
3342 HMODULE hgdi32;
3344 /* resolve all the functions */
3345 hgdi32 = GetModuleHandleA("gdi32.dll");
3346 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3347 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3348 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3350 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3352 win_skip("Needed GdiIs* functions are not available\n");
3353 return;
3356 /* try with nothing */
3357 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3358 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3359 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3361 /* try with a metafile */
3362 hmfDC = CreateMetaFileA(NULL);
3363 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3364 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3365 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3366 DeleteMetaFile(CloseMetaFile(hmfDC));
3368 /* try with an enhanced metafile */
3369 hdc = GetDC(NULL);
3370 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3371 ok(hemfDC != NULL, "failed to create emf\n");
3373 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3374 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3375 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3377 hemf = CloseEnhMetaFile(hemfDC);
3378 ok(hemf != NULL, "failed to close EMF\n");
3379 DeleteEnhMetaFile(hemf);
3380 ReleaseDC(NULL,hdc);
3383 static void test_SetEnhMetaFileBits(void)
3385 BYTE data[256];
3386 HENHMETAFILE hemf;
3387 ENHMETAHEADER *emh;
3389 memset(data, 0xAA, sizeof(data));
3390 SetLastError(0xdeadbeef);
3391 hemf = SetEnhMetaFileBits(sizeof(data), data);
3392 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3393 ok(GetLastError() == ERROR_INVALID_DATA ||
3394 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3395 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3397 emh = (ENHMETAHEADER *)data;
3398 memset(emh, 0, sizeof(*emh));
3400 emh->iType = EMR_HEADER;
3401 emh->nSize = sizeof(*emh);
3402 emh->dSignature = ENHMETA_SIGNATURE;
3403 /* emh->nVersion = 0x10000; XP doesn't care about version */
3404 emh->nBytes = sizeof(*emh);
3405 /* emh->nRecords = 1; XP doesn't care about records */
3406 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3408 SetLastError(0xdeadbeef);
3409 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3410 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3411 DeleteEnhMetaFile(hemf);
3413 /* XP refuses to load unaligned EMF */
3414 emh->nBytes++;
3415 SetLastError(0xdeadbeef);
3416 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3417 ok(!hemf ||
3418 broken(hemf != NULL), /* Win9x, WinMe */
3419 "SetEnhMetaFileBits should fail\n");
3420 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3421 DeleteEnhMetaFile(hemf);
3423 emh->dSignature = 0;
3424 emh->nBytes--;
3425 SetLastError(0xdeadbeef);
3426 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3427 ok(!hemf ||
3428 broken(hemf != NULL), /* Win9x, WinMe */
3429 "SetEnhMetaFileBits should fail\n");
3430 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3431 DeleteEnhMetaFile(hemf);
3434 static void test_emf_polybezier(void)
3436 HDC hdcMetafile;
3437 HENHMETAFILE hemf;
3438 POINT pts[4];
3439 BOOL ret;
3441 SetLastError(0xdeadbeef);
3442 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3443 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3445 pts[0].x = pts[0].y = 10;
3446 pts[1].x = pts[1].y = 20;
3447 pts[2].x = pts[2].y = 15;
3448 pts[3].x = pts[3].y = 25;
3449 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3450 ok( ret, "PolyBezierTo failed\n" );
3451 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3452 ok( ret, "PolyBezier failed\n" );
3454 pts[0].x = pts[0].y = 32769;
3455 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3456 ok( ret, "PolyBezier failed\n" );
3457 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3458 ok( ret, "PolyBezierTo failed\n" );
3460 hemf = CloseEnhMetaFile(hdcMetafile);
3461 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3463 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3464 "emf_Bezier", FALSE) != 0)
3466 dump_emf_bits(hemf, "emf_Bezier");
3467 dump_emf_records(hemf, "emf_Bezier");
3470 DeleteEnhMetaFile(hemf);
3473 static const unsigned char EMF_PATH_BITS[] =
3475 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3477 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3479 0xe6, 0xff, 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff,
3480 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3481 0xf8, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3482 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3484 0x80, 0x07, 0x00, 0x00, 0xd3, 0x03, 0x00, 0x00,
3485 0xfc, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
3486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3487 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
3488 0xd3, 0xf3, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3489 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3490 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3491 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3492 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3493 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3494 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3495 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3496 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3497 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3498 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3499 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3500 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3501 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3502 0x13, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3503 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3504 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3505 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3508 static void test_emf_GetPath(void)
3510 HDC hdcMetafile;
3511 HENHMETAFILE hemf;
3512 BOOL ret;
3513 int size;
3515 SetLastError(0xdeadbeef);
3516 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3517 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3519 BeginPath(hdcMetafile);
3520 ret = MoveToEx(hdcMetafile, 50, 50, NULL);
3521 ok( ret, "MoveToEx error %d.\n", GetLastError());
3522 ret = LineTo(hdcMetafile, 50, 150);
3523 ok( ret, "LineTo error %d.\n", GetLastError());
3524 ret = LineTo(hdcMetafile, 150, 150);
3525 ok( ret, "LineTo error %d.\n", GetLastError());
3526 ret = LineTo(hdcMetafile, 150, 50);
3527 ok( ret, "LineTo error %d.\n", GetLastError());
3528 ret = LineTo(hdcMetafile, 50, 50);
3529 ok( ret, "LineTo error %d.\n", GetLastError());
3530 Rectangle(hdcMetafile, 10, 10, 20, 20);
3531 EndPath(hdcMetafile);
3533 size = GetPath(hdcMetafile, NULL, NULL, 0);
3534 todo_wine ok( size == 9, "GetPath returned %d.\n", size);
3536 hemf = CloseEnhMetaFile(hdcMetafile);
3537 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3539 if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_GetPath", FALSE) != 0)
3541 dump_emf_bits(hemf, "test_emf_GetPath");
3542 dump_emf_records(hemf, "test_emf_GetPath");
3545 DeleteEnhMetaFile(hemf);
3548 static void test_emf_PolyPolyline(void)
3550 HDC hdcMetafile;
3551 HENHMETAFILE hemf;
3552 POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3553 DWORD counts[2];
3554 BOOL ret;
3556 SetLastError(0xdeadbeef);
3557 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3558 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3560 ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
3561 ok( !ret, "PolyPolyline\n" );
3563 SetLastError( 0xdeadbeef );
3564 counts[0] = 0;
3565 counts[1] = 1;
3566 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3567 ok( !ret, "PolyPolyline\n" );
3568 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3570 SetLastError( 0xdeadbeef );
3571 counts[0] = 1;
3572 counts[1] = 1;
3573 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3574 ok( !ret, "PolyPolyline\n" );
3575 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3577 SetLastError( 0xdeadbeef );
3578 counts[0] = 2;
3579 counts[1] = 1;
3580 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3581 ok( !ret, "PolyPolyline\n" );
3582 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3584 counts[0] = 2;
3585 counts[1] = 2;
3586 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3587 ok( ret, "PolyPolyline\n" );
3589 hemf = CloseEnhMetaFile(hdcMetafile);
3590 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3592 if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
3593 "emf_PolyPolyline", FALSE) != 0)
3595 dump_emf_bits(hemf, "emf_PolyPolyline");
3596 dump_emf_records(hemf, "emf_PolyPolyline");
3599 DeleteEnhMetaFile(hemf);
3602 START_TEST(metafile)
3604 init_function_pointers();
3606 /* For enhanced metafiles (enhmfdrv) */
3607 test_ExtTextOut();
3608 test_ExtTextOutScale();
3609 test_SaveDC();
3610 test_emf_BitBlt();
3611 test_emf_DCBrush();
3612 test_emf_ExtTextOut_on_path();
3613 test_emf_clipping();
3614 test_emf_polybezier();
3615 test_emf_GetPath();
3616 test_emf_PolyPolyline();
3618 /* For win-format metafiles (mfdrv) */
3619 test_mf_SaveDC();
3620 test_mf_Blank();
3621 test_mf_Graphics();
3622 test_mf_PatternBrush();
3623 test_mf_DCBrush();
3624 test_CopyMetaFile();
3625 test_SetMetaFileBits();
3626 test_mf_ExtTextOut_on_path();
3627 test_mf_clipping();
3628 test_mf_GetPath();
3630 /* For metafile conversions */
3631 test_mf_conversions();
3632 test_SetWinMetaFileBits();
3633 test_GetWinMetaFileBits();
3635 test_gdiis();
3636 test_SetEnhMetaFileBits();