gdi32: Implement ArcTo in enhanced metafiles.
[wine.git] / dlls / gdi32 / tests / metafile.c
blob4cf61a269319304a2f3ba02782d874220149b586
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 ok(!emr_ExtTextOutW->rclBounds.left, "emr_ExtTextOutW->rclBounds.left = %d\n",
152 emr_ExtTextOutW->rclBounds.left);
153 ok(emr_ExtTextOutW->rclBounds.right != -1, "emr_ExtTextOutW->rclBounds.right = %d\n",
154 emr_ExtTextOutW->rclBounds.right);
155 ok(emr_ExtTextOutW->rclBounds.bottom != -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n",
156 emr_ExtTextOutW->rclBounds.bottom);
158 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
160 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
161 n_record, i, dx[i], orig_dx[i]);
163 n_record++;
164 emr_processed = TRUE;
165 break;
168 default:
169 break;
172 return 1;
175 static void test_ExtTextOut(void)
177 HWND hwnd;
178 HDC hdcDisplay, hdcMetafile;
179 HENHMETAFILE hMetafile;
180 HFONT hFont;
181 static const char text[] = "Simple text to test ExtTextOut on metafiles";
182 INT i, len, dx[256];
183 static const RECT rc = { 0, 0, 100, 100 };
184 BOOL ret;
186 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
188 /* Win9x doesn't play EMFs on invisible windows */
189 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
190 0, 0, 200, 200, 0, 0, 0, NULL);
191 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
193 hdcDisplay = GetDC(hwnd);
194 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
196 trace("hdcDisplay %p\n", hdcDisplay);
198 SetMapMode(hdcDisplay, MM_TEXT);
200 memset(&orig_lf, 0, sizeof(orig_lf));
202 orig_lf.lfCharSet = ANSI_CHARSET;
203 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
204 orig_lf.lfWeight = FW_DONTCARE;
205 orig_lf.lfHeight = 7;
206 orig_lf.lfQuality = DEFAULT_QUALITY;
207 lstrcpyA(orig_lf.lfFaceName, "Arial");
208 hFont = CreateFontIndirectA(&orig_lf);
209 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
211 hFont = SelectObject(hdcDisplay, hFont);
213 len = lstrlenA(text);
214 for (i = 0; i < len; i++)
216 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
217 ok( ret, "GetCharWidthA error %d\n", GetLastError());
219 hFont = SelectObject(hdcDisplay, hFont);
221 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
222 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
224 trace("hdcMetafile %p\n", hdcMetafile);
226 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
227 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
229 hFont = SelectObject(hdcMetafile, hFont);
231 /* 1. pass NULL lpDx */
232 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
233 ok( ret, "ExtTextOutA error %d\n", GetLastError());
235 /* 2. pass custom lpDx */
236 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
237 ok( ret, "ExtTextOutA error %d\n", GetLastError());
239 /* 3. pass NULL lprc */
240 ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL);
241 ok( ret, "ExtTextOutA error %d\n", GetLastError());
243 /* 4. test with unmatched BeginPath/EndPath calls */
244 ret = BeginPath(hdcMetafile);
245 ok( ret, "BeginPath error %d\n", GetLastError());
246 ret = BeginPath(hdcMetafile);
247 ok( ret, "BeginPath error %d\n", GetLastError());
248 ret = EndPath(hdcMetafile);
249 ok( ret, "BeginPath error %d\n", GetLastError());
250 ret = ExtTextOutA(hdcMetafile, 0, 60, 0, NULL, text, lstrlenA(text), NULL);
251 ok( ret, "ExtTextOutA error %d\n", GetLastError());
253 hFont = SelectObject(hdcMetafile, hFont);
254 ret = DeleteObject(hFont);
255 ok( ret, "DeleteObject error %d\n", GetLastError());
257 hMetafile = CloseEnhMetaFile(hdcMetafile);
258 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
260 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
262 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
263 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
265 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
266 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
267 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
268 SetROP2(hdcDisplay, R2_NOT);
269 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
270 SetPolyFillMode(hdcDisplay, WINDING);
271 SetStretchBltMode(hdcDisplay, HALFTONE);
273 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
274 SetBkMode(hdcDisplay, OPAQUE);
276 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
277 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
279 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
280 "text align %08x\n", GetTextAlign(hdcDisplay));
281 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
282 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
283 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
284 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
285 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
286 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
288 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
290 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
291 "A valid hdc has to require a valid rc\n");
293 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
294 "A null hdc does not require a valid rc\n");
296 ret = DeleteEnhMetaFile(hMetafile);
297 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
298 ret = ReleaseDC(hwnd, hdcDisplay);
299 ok( ret, "ReleaseDC error %d\n", GetLastError());
300 DestroyWindow(hwnd);
303 struct eto_scale_test_record
305 INT graphics_mode;
306 INT map_mode;
307 double ex_scale;
308 double ey_scale;
309 BOOL processed;
312 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
313 const ENHMETARECORD *emr, int n_objs, LPARAM param)
315 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
317 if (emr->iType == EMR_EXTTEXTOUTW)
319 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
320 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
321 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
322 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
323 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
324 test->processed = TRUE;
327 return 1;
330 static void test_ExtTextOutScale(void)
332 const RECT rc = { 0, 0, 100, 100 };
333 const WCHAR str[] = {'a',0 };
334 struct eto_scale_test_record test;
335 HDC hdcDisplay, hdcMetafile;
336 HENHMETAFILE hMetafile;
337 HWND hwnd;
338 SIZE wndext, vportext;
339 int horzSize, vertSize, horzRes, vertRes;
340 int ret;
341 int i;
343 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
344 0, 0, 200, 200, 0, 0, 0, NULL);
345 ok(hwnd != 0, "CreateWindowExA failed\n");
347 hdcDisplay = GetDC(hwnd);
348 ok(hdcDisplay != 0, "GetDC failed\n");
350 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
351 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
352 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
353 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
354 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
356 for (i = 0; i < 16; i++)
358 test.graphics_mode = i / 8 + 1;
359 test.map_mode = i % 8 + 1;
361 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
362 ok(ret, "SetGraphicsMode failed\n");
363 ret = SetMapMode(hdcDisplay, test.map_mode);
364 ok(ret, "SetMapMode failed\n");
366 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
368 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
369 ok(ret, "SetWindowExtEx failed\n");
370 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
371 ok(ret, "SetViewportExtEx failed\n");
374 ret = GetViewportExtEx(hdcDisplay, &vportext);
375 ok(ret, "GetViewportExtEx failed\n");
376 ret = GetWindowExtEx(hdcDisplay, &wndext);
377 ok(ret, "GetWindowExtEx failed\n");
379 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
380 test.graphics_mode, test.map_mode,
381 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
382 horzSize, horzRes, vertSize, vertRes);
384 if (test.graphics_mode == GM_COMPATIBLE)
386 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
387 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
388 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
389 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
391 else
393 test.ex_scale = 0.0;
394 test.ey_scale = 0.0;
397 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
398 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
400 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
401 ok(ret, "SetGraphicsMode failed\n");
402 ret = SetMapMode(hdcMetafile, test.map_mode);
403 ok(ret, "SetMapMode failed\n");
405 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
407 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
408 ok(ret, "SetWindowExtEx failed\n");
409 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
410 ok(ret, "SetViewportExtEx failed\n");
413 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
414 ok(ret, "ExtTextOutW failed\n");
416 hMetafile = CloseEnhMetaFile(hdcMetafile);
417 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
419 test.processed = 0;
420 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
421 ok(ret, "EnumEnhMetaFile failed\n");
422 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
424 ret = DeleteEnhMetaFile(hMetafile);
425 ok(ret, "DeleteEnhMetaFile failed\n");
428 ret = ReleaseDC(hwnd, hdcDisplay);
429 ok(ret, "ReleaseDC failed\n");
430 DestroyWindow(hwnd);
434 static void check_dc_state(HDC hdc, int restore_no,
435 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
436 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
438 BOOL ret;
439 XFORM xform;
440 POINT vp_org, win_org;
441 SIZE vp_size, win_size;
442 FLOAT xscale, yscale, edx, edy;
444 SetLastError(0xdeadbeef);
445 ret = GetWorldTransform(hdc, &xform);
446 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
447 ok(ret, "GetWorldTransform error %u\n", GetLastError());
449 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
451 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
452 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
454 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
455 trace("x scale %f\n", xscale);
456 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
457 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
459 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
460 trace("y scale %f\n", yscale);
461 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
462 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
464 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
465 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
466 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
467 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
469 return;
471 win9x_here:
473 GetWindowOrgEx(hdc, &win_org);
474 GetViewportOrgEx(hdc, &vp_org);
475 GetWindowExtEx(hdc, &win_size);
476 GetViewportExtEx(hdc, &vp_size);
478 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
479 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
481 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
482 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
484 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
485 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
487 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
488 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
491 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
492 const ENHMETARECORD *emr, int n_objs, LPARAM param)
494 BOOL ret;
495 XFORM xform;
496 POINT pt;
497 SIZE size;
498 static int save_state;
499 static int restore_no;
500 static int select_no;
502 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
503 hdc, emr->iType, emr->nSize, (void *)param);
505 SetLastError(0xdeadbeef);
506 ret = GetWorldTransform(hdc, &xform);
507 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
509 ret = GetWindowOrgEx(hdc, &pt);
510 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
511 trace("window org (%d,%d)\n", pt.x, pt.y);
512 ret = GetViewportOrgEx(hdc, &pt);
513 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
514 trace("vport org (%d,%d)\n", pt.x, pt.y);
515 ret = GetWindowExtEx(hdc, &size);
516 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
517 trace("window ext (%d,%d)\n", size.cx, size.cy);
518 ret = GetViewportExtEx(hdc, &size);
519 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
520 trace("vport ext (%d,%d)\n", size.cx, size.cy);
522 else
524 ok(ret, "GetWorldTransform error %u\n", GetLastError());
525 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
528 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
530 switch (emr->iType)
532 case EMR_HEADER:
534 static RECT exp_bounds = { 0, 0, 150, 150 };
535 RECT bounds;
536 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
538 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
539 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
540 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
541 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
542 emf->szlDevice.cx, emf->szlDevice.cy);
544 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
545 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
547 save_state = 0;
548 restore_no = 0;
549 select_no = 0;
550 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
551 break;
554 case EMR_LINETO:
556 const EMRLINETO *line = (const EMRLINETO *)emr;
557 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
558 break;
560 case EMR_SETWINDOWORGEX:
562 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
563 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
564 break;
566 case EMR_SETWINDOWEXTEX:
568 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
569 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
570 break;
572 case EMR_SETVIEWPORTORGEX:
574 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
575 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
576 break;
578 case EMR_SETVIEWPORTEXTEX:
580 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
581 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
582 break;
584 case EMR_SAVEDC:
585 save_state++;
586 trace("EMR_SAVEDC\n");
587 break;
589 case EMR_RESTOREDC:
591 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
592 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
594 switch(++restore_no)
596 case 1:
597 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
598 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
599 break;
600 case 2:
601 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
602 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
603 break;
604 case 3:
605 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
606 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
607 break;
609 ok(restore_no <= 3, "restore_no %d\n", restore_no);
610 save_state += restoredc->iRelative;
611 break;
613 case EMR_SELECTOBJECT:
615 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
616 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
617 select_no ++;
618 break;
620 case EMR_EOF:
621 ok(save_state == 0, "EOF save_state %d\n", save_state);
622 ok(select_no == 3, "Too many/few selects %i\n",select_no);
623 break;
626 SetLastError(0xdeadbeef);
627 ret = GetWorldTransform(hdc, &xform);
628 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
630 ret = GetWindowOrgEx(hdc, &pt);
631 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
632 trace("window org (%d,%d)\n", pt.x, pt.y);
633 ret = GetViewportOrgEx(hdc, &pt);
634 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
635 trace("vport org (%d,%d)\n", pt.x, pt.y);
636 ret = GetWindowExtEx(hdc, &size);
637 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
638 trace("window ext (%d,%d)\n", size.cx, size.cy);
639 ret = GetViewportExtEx(hdc, &size);
640 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
641 trace("vport ext (%d,%d)\n", size.cx, size.cy);
643 else
645 ok(ret, "GetWorldTransform error %u\n", GetLastError());
646 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
649 return 1;
652 static void test_SaveDC(void)
654 HDC hdcMetafile, hdcDisplay;
655 HENHMETAFILE hMetafile;
656 HWND hwnd;
657 int ret;
658 POINT pt;
659 SIZE size;
660 HFONT hFont,hFont2,hFontOld,hFontCheck;
661 static const RECT rc = { 0, 0, 150, 150 };
663 /* Win9x doesn't play EMFs on invisible windows */
664 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
665 0, 0, 200, 200, 0, 0, 0, NULL);
666 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
668 hdcDisplay = GetDC(hwnd);
669 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
671 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
672 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
674 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
676 /* Need to write something to the emf, otherwise Windows won't play it back */
677 LineTo(hdcMetafile, 150, 150);
679 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
680 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
681 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
682 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
684 /* Force Win9x to update DC state */
685 SetPixelV(hdcMetafile, 50, 50, 0);
687 ret = GetViewportOrgEx(hdcMetafile, &pt);
688 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
689 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
690 ret = GetViewportExtEx(hdcMetafile, &size);
691 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
692 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
693 ret = SaveDC(hdcMetafile);
694 ok(ret == 1, "ret = %d\n", ret);
696 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
697 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
698 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
699 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
701 /* Force Win9x to update DC state */
702 SetPixelV(hdcMetafile, 50, 50, 0);
704 ret = GetViewportOrgEx(hdcMetafile, &pt);
705 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
706 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
707 ret = GetViewportExtEx(hdcMetafile, &size);
708 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
709 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
710 ret = SaveDC(hdcMetafile);
711 ok(ret == 2, "ret = %d\n", ret);
713 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
714 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
715 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
716 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
717 SetPolyFillMode( hdcMetafile, ALTERNATE );
718 SetBkColor( hdcMetafile, 0 );
720 /* Force Win9x to update DC state */
721 SetPixelV(hdcMetafile, 50, 50, 0);
723 ret = GetViewportOrgEx(hdcMetafile, &pt);
724 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
725 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
726 ret = GetViewportExtEx(hdcMetafile, &size);
727 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
728 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
729 ret = SaveDC(hdcMetafile);
730 ok(ret == 3, "ret = %d\n", ret);
732 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
733 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
734 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
735 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
737 SetPolyFillMode( hdcMetafile, WINDING );
738 SetBkColor( hdcMetafile, 0x123456 );
739 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
740 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
742 /* Force Win9x to update DC state */
743 SetPixelV(hdcMetafile, 50, 50, 0);
745 ret = GetViewportOrgEx(hdcMetafile, &pt);
746 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
747 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
748 ret = GetViewportExtEx(hdcMetafile, &size);
749 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
750 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
751 ret = RestoreDC(hdcMetafile, -1);
752 ok(ret, "ret = %d\n", ret);
754 ret = GetViewportOrgEx(hdcMetafile, &pt);
755 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
756 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
757 ret = GetViewportExtEx(hdcMetafile, &size);
758 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
759 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
760 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
761 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
762 ret = SaveDC(hdcMetafile);
763 ok(ret == 3, "ret = %d\n", ret);
765 ret = GetViewportOrgEx(hdcMetafile, &pt);
766 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
767 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
768 ret = GetViewportExtEx(hdcMetafile, &size);
769 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
770 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
771 ret = RestoreDC(hdcMetafile, 1);
772 ok(ret, "ret = %d\n", ret);
773 ret = GetViewportOrgEx(hdcMetafile, &pt);
774 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
775 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
776 ret = GetViewportExtEx(hdcMetafile, &size);
777 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
778 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
780 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
781 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
782 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
783 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
785 /* Force Win9x to update DC state */
786 SetPixelV(hdcMetafile, 50, 50, 0);
788 ret = GetViewportOrgEx(hdcMetafile, &pt);
789 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
790 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
791 ret = GetViewportExtEx(hdcMetafile, &size);
792 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
793 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
794 ret = SaveDC(hdcMetafile);
795 ok(ret == 1, "ret = %d\n", ret);
797 ret = GetViewportOrgEx(hdcMetafile, &pt);
798 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
799 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
800 ret = GetViewportExtEx(hdcMetafile, &size);
801 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
802 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
803 ret = SaveDC(hdcMetafile);
804 ok(ret == 2, "ret = %d\n", ret);
806 memset(&orig_lf, 0, sizeof(orig_lf));
807 orig_lf.lfCharSet = ANSI_CHARSET;
808 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
809 orig_lf.lfWeight = FW_DONTCARE;
810 orig_lf.lfHeight = 7;
811 orig_lf.lfQuality = DEFAULT_QUALITY;
812 lstrcpyA(orig_lf.lfFaceName, "Arial");
813 hFont = CreateFontIndirectA(&orig_lf);
814 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
816 hFontOld = SelectObject(hdcMetafile, hFont);
818 hFont2 = CreateFontIndirectA(&orig_lf);
819 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
820 hFontCheck = SelectObject(hdcMetafile, hFont2);
821 ok(hFontCheck == hFont, "Font not selected\n");
823 /* Force Win9x to update DC state */
824 SetPixelV(hdcMetafile, 50, 50, 0);
826 ret = RestoreDC(hdcMetafile, 1);
827 ok(ret, "ret = %d\n", ret);
828 ret = GetViewportOrgEx(hdcMetafile, &pt);
829 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
830 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
831 ret = GetViewportExtEx(hdcMetafile, &size);
832 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
833 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
835 hFontCheck = SelectObject(hdcMetafile, hFontOld);
836 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
837 "Font not reverted with DC Restore\n");
839 ret = RestoreDC(hdcMetafile, -20);
840 ok(!ret, "ret = %d\n", ret);
841 ret = RestoreDC(hdcMetafile, 20);
842 ok(!ret, "ret = %d\n", ret);
844 hMetafile = CloseEnhMetaFile(hdcMetafile);
845 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
847 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
848 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
850 ret = DeleteObject(hFont);
851 ok( ret, "DeleteObject error %d\n", GetLastError());
852 ret = DeleteObject(hFont2);
853 ok( ret, "DeleteObject error %d\n", GetLastError());
854 ret = DeleteEnhMetaFile(hMetafile);
855 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
856 ret = ReleaseDC(hwnd, hdcDisplay);
857 ok( ret, "ReleaseDC error %d\n", GetLastError());
858 DestroyWindow(hwnd);
861 static void test_mf_SaveDC(void)
863 HDC hdcMetafile;
864 HMETAFILE hMetafile;
865 int ret;
866 POINT pt;
867 SIZE size;
868 HFONT hFont,hFont2,hFontOld,hFontCheck;
870 hdcMetafile = CreateMetaFileA(NULL);
871 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
873 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
874 ok (ret, "SetMapMode should not fail\n");
876 /* Need to write something to the emf, otherwise Windows won't play it back */
877 LineTo(hdcMetafile, 150, 150);
879 pt.x = pt.y = 5555;
880 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
881 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
882 pt.x = pt.y = 5555;
883 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
884 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
885 size.cx = size.cy = 5555;
886 SetWindowExtEx(hdcMetafile, 110, 110, &size );
887 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
888 size.cx = size.cy = 5555;
889 SetViewportExtEx(hdcMetafile, 120, 120, &size );
890 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
892 /* Force Win9x to update DC state */
893 SetPixelV(hdcMetafile, 50, 50, 0);
895 ret = GetViewportOrgEx(hdcMetafile, &pt);
896 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
897 ret = GetViewportExtEx(hdcMetafile, &size);
898 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
899 ret = SaveDC(hdcMetafile);
900 ok(ret == 1, "ret = %d\n", ret);
902 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
903 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
904 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
905 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
907 /* Force Win9x to update DC state */
908 SetPixelV(hdcMetafile, 50, 50, 0);
910 ret = SaveDC(hdcMetafile);
911 ok(ret == 1, "ret = %d\n", ret);
913 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
914 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
915 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
916 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
918 /* Force Win9x to update DC state */
919 SetPixelV(hdcMetafile, 50, 50, 0);
920 SetPolyFillMode( hdcMetafile, ALTERNATE );
921 SetBkColor( hdcMetafile, 0 );
923 ret = SaveDC(hdcMetafile);
924 ok(ret == 1, "ret = %d\n", ret);
926 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
927 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
928 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
929 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
931 SetPolyFillMode( hdcMetafile, WINDING );
932 SetBkColor( hdcMetafile, 0x123456 );
933 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
934 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
936 /* Force Win9x to update DC state */
937 SetPixelV(hdcMetafile, 50, 50, 0);
939 ret = RestoreDC(hdcMetafile, -1);
940 ok(ret, "ret = %d\n", ret);
942 ret = SaveDC(hdcMetafile);
943 ok(ret == 1, "ret = %d\n", ret);
945 ret = RestoreDC(hdcMetafile, 1);
946 ok(ret, "ret = %d\n", ret);
948 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
949 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
950 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
951 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
953 /* Force Win9x to update DC state */
954 SetPixelV(hdcMetafile, 50, 50, 0);
956 ret = SaveDC(hdcMetafile);
957 ok(ret == 1, "ret = %d\n", ret);
959 ret = SaveDC(hdcMetafile);
960 ok(ret == 1, "ret = %d\n", ret);
962 memset(&orig_lf, 0, sizeof(orig_lf));
963 orig_lf.lfCharSet = ANSI_CHARSET;
964 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
965 orig_lf.lfWeight = FW_DONTCARE;
966 orig_lf.lfHeight = 7;
967 orig_lf.lfQuality = DEFAULT_QUALITY;
968 lstrcpyA(orig_lf.lfFaceName, "Arial");
969 hFont = CreateFontIndirectA(&orig_lf);
970 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
972 hFontOld = SelectObject(hdcMetafile, hFont);
974 hFont2 = CreateFontIndirectA(&orig_lf);
975 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
976 hFontCheck = SelectObject(hdcMetafile, hFont2);
977 ok(hFontCheck == hFont, "Font not selected\n");
979 /* Force Win9x to update DC state */
980 SetPixelV(hdcMetafile, 50, 50, 0);
982 ret = RestoreDC(hdcMetafile, 1);
983 ok(ret, "ret = %d\n", ret);
985 hFontCheck = SelectObject(hdcMetafile, hFontOld);
986 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
988 /* restore level is ignored */
989 ret = RestoreDC(hdcMetafile, -20);
990 ok(ret, "ret = %d\n", ret);
991 ret = RestoreDC(hdcMetafile, 20);
992 ok(ret, "ret = %d\n", ret);
993 ret = RestoreDC(hdcMetafile, 0);
994 ok(ret, "ret = %d\n", ret);
996 hMetafile = CloseMetaFile(hdcMetafile);
997 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
999 ret = DeleteMetaFile(hMetafile);
1000 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1001 ret = DeleteObject(hFont);
1002 ok( ret, "DeleteObject error %d\n", GetLastError());
1003 ret = DeleteObject(hFont2);
1004 ok( ret, "DeleteObject error %d\n", GetLastError());
1008 /* Win-format metafile (mfdrv) tests */
1009 /* These tests compare the generated metafiles byte-by-byte */
1010 /* with the nominal results. */
1012 /* Maximum size of sample metafiles in bytes. */
1013 #define MF_BUFSIZE 1024
1015 /* 8x8 bitmap data for a pattern brush */
1016 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
1017 0x01, 0x00, 0x02, 0x00,
1018 0x03, 0x00, 0x04, 0x00,
1019 0x05, 0x00, 0x06, 0x00,
1020 0x07, 0x00, 0x08, 0x00
1023 /* Sample metafiles to be compared to the outputs of the
1024 * test functions.
1027 static const unsigned char MF_BLANK_BITS[] = {
1028 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1030 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1033 static const unsigned char MF_GRAPHICS_BITS[] = {
1034 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1035 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1037 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1038 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1039 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1040 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1041 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1042 0x00, 0x00, 0x00, 0x00
1045 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1046 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1047 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1048 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1049 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1050 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1051 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1056 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1057 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1058 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1059 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1060 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1061 0x00, 0x00
1064 static const unsigned char MF_DCBRUSH_BITS[] =
1066 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1067 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1068 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1069 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1070 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1071 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1074 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1075 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1076 0x00, 0x00, 0x00, 0x00
1079 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1081 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1084 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1085 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1086 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1087 0x00, 0x00
1090 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1092 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1097 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1098 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1099 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1102 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1105 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1106 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1107 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1109 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1111 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1112 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1115 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1116 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1117 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1118 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1119 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1120 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1122 0x14, 0x00, 0x00, 0x00
1125 static const unsigned char MF_LINETO_BITS[] = {
1126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1130 0x00, 0x00
1133 static const unsigned char EMF_LINETO_BITS[] = {
1134 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1139 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1140 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1141 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1144 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1147 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1148 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1149 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1150 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1151 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1152 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1154 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1155 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1157 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1158 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1161 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1162 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1163 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1164 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1165 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1166 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1167 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1168 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1169 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1170 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1171 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1175 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1176 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1180 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1181 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1182 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1183 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1185 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1186 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1189 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1190 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1191 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1192 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1193 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1194 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1195 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1196 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1197 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1199 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1200 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1201 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1202 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1203 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1204 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1205 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1206 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1207 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1208 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1209 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1210 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1211 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1213 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1217 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1218 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1220 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1223 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1224 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1225 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1228 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1231 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1232 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1233 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1234 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1235 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1236 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1237 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1238 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1239 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1241 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1242 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1244 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1246 0x14, 0x00, 0x00, 0x00
1249 static const unsigned char EMF_BITBLT[] =
1251 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1256 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1257 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1258 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1261 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1264 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1265 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1267 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1269 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1276 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1277 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1278 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1293 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1296 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1301 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1303 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1305 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1311 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1312 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1313 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1314 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1315 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1316 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1325 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1326 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1327 0x14, 0x00, 0x00, 0x00
1330 static const unsigned char EMF_DCBRUSH_BITS[] =
1332 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1333 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1334 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1335 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1336 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1337 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1338 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1339 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1341 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1342 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1345 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1346 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1347 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1348 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1349 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1350 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1351 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1352 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1353 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1354 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1357 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1358 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1359 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1360 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1361 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1362 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1363 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1365 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1366 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1367 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1368 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1369 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1370 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1372 0x14, 0x00, 0x00, 0x00
1375 static const unsigned char EMF_BEZIER_BITS[] =
1377 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1382 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1383 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1384 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1386 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1387 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1389 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1390 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1391 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1393 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1394 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1395 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1396 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1397 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1398 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1399 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1400 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1401 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1402 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1403 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1404 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1405 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1407 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1408 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1409 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1410 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1411 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1412 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1413 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1414 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1415 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1416 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1417 0x14, 0x00, 0x00, 0x00
1420 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1422 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1423 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1424 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1425 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1426 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1427 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1428 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1429 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1431 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1432 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1435 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1436 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1438 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1439 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1440 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1441 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1442 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1443 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1444 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1445 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1447 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1448 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1449 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1450 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1451 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1454 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1455 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1456 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1457 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1458 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1459 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1460 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1461 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1462 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1463 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1464 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1465 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1466 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1467 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1468 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1470 0x14, 0x00, 0x00, 0x00
1473 static const unsigned char EMF_GRADIENTFILL_BITS[] =
1475 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1476 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1477 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1478 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1479 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1480 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1481 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1482 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1485 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1487 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1488 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1489 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1490 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1491 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1492 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1493 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1494 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1495 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1497 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1498 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1499 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1500 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1501 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1502 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1503 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1504 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1505 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1508 0x14, 0x00, 0x00, 0x00
1511 /* For debugging or dumping the raw metafiles produced by
1512 * new test functions.
1514 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1515 INT nobj, LPARAM param)
1517 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1518 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1519 return TRUE;
1522 /* For debugging or dumping the raw metafiles produced by
1523 * new test functions.
1526 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1528 BYTE buf[MF_BUFSIZE];
1529 UINT mfsize, i;
1531 if (!winetest_debug) return;
1533 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1534 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1536 printf ("MetaFile %s has bits:\n{\n ", desc);
1537 for (i=0; i<mfsize; i++)
1539 printf ("0x%02x", buf[i]);
1540 if (i == mfsize-1)
1541 printf ("\n");
1542 else if (i % 8 == 7)
1543 printf (",\n ");
1544 else
1545 printf (", ");
1547 printf ("};\n");
1550 /* Compare the metafile produced by a test function with the
1551 * expected raw metafile data in "bits".
1552 * Return value is 0 for a perfect match,
1553 * -1 if lengths aren't equal,
1554 * otherwise returns the number of non-matching bytes.
1557 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1558 const char *desc)
1560 unsigned char buf[MF_BUFSIZE];
1561 UINT mfsize, i;
1562 int diff;
1564 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1565 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1566 if (mfsize < MF_BUFSIZE)
1567 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1568 desc, mfsize, bsize);
1569 else
1570 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1571 desc, mfsize, bsize);
1572 if (mfsize != bsize)
1573 return -1;
1575 diff = 0;
1576 for (i=0; i<bsize; i++)
1578 if (buf[i] != bits[i])
1579 diff++;
1581 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1582 desc, mfsize, bsize, diff);
1584 return diff;
1587 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1589 unsigned char buf[MF_BUFSIZE];
1590 DWORD mfsize, rd_size, i;
1591 int diff;
1592 HANDLE hfile;
1593 BOOL ret;
1595 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1596 assert(hfile != INVALID_HANDLE_VALUE);
1598 mfsize = GetFileSize(hfile, NULL);
1599 assert(mfsize <= MF_BUFSIZE);
1601 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1602 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1604 CloseHandle(hfile);
1606 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1608 if (mfsize != bsize)
1609 return -1;
1611 diff = 0;
1612 for (i=0; i<bsize; i++)
1614 if (buf[i] != bits[i])
1615 diff++;
1617 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1618 desc, mfsize, bsize, diff);
1620 return diff;
1623 /* For debugging or dumping the raw EMFs produced by
1624 * new test functions.
1626 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1628 BYTE buf[MF_BUFSIZE];
1629 UINT mfsize, i;
1631 if (!winetest_debug) return;
1633 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1634 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1636 printf("EMF %s has bits:\n{\n ", desc);
1637 for (i = 0; i < mfsize; i++)
1639 printf ("0x%02x", buf[i]);
1640 if (i == mfsize-1)
1641 printf ("\n");
1642 else if (i % 8 == 7)
1643 printf (",\n ");
1644 else
1645 printf (", ");
1647 printf ("};\n");
1650 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1652 BYTE *emf;
1653 BYTE buf[MF_BUFSIZE];
1654 UINT mfsize, offset;
1656 if (!winetest_debug) return;
1658 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1659 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1661 printf("EMF %s has records:\n", desc);
1663 emf = buf;
1664 offset = 0;
1665 while(offset < mfsize)
1667 EMR *emr = (EMR *)(emf + offset);
1668 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1669 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1670 offset += emr->nSize;
1674 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1676 const BYTE *buf;
1677 DWORD i;
1679 if (!winetest_debug) return;
1681 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1682 buf = (const BYTE *)emr;
1683 for (i = 0; i < emr->nSize; i++)
1685 printf ("0x%02x", buf[i]);
1686 if (i == emr->nSize - 1)
1687 printf ("\n");
1688 else if (i % 8 == 7)
1689 printf (",\n");
1690 else
1691 printf (", ");
1693 printf ("};\n");
1696 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1698 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1699 eto->rclBounds.right, eto->rclBounds.bottom);
1700 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1701 trace("exScale: %f\n", eto->exScale);
1702 trace("eyScale: %f\n", eto->eyScale);
1703 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1704 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1705 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1706 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1707 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1708 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1709 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1712 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1713 const char *desc, BOOL ignore_scaling)
1715 int diff;
1717 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1718 desc, emr1->iType, emr2->iType);
1720 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1721 desc, emr1->nSize, emr2->nSize);
1723 /* iType and nSize mismatches are fatal */
1724 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1726 /* contents of EMR_GDICOMMENT are not interesting */
1727 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1729 /* different Windows versions setup DC scaling differently when
1730 * converting an old style metafile to an EMF.
1732 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1733 emr1->iType == EMR_SETVIEWPORTEXTEX))
1734 return TRUE;
1736 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1738 EMREXTTEXTOUTW *eto1, *eto2;
1740 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1741 memcpy(eto1, emr1, emr1->nSize);
1742 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1743 memcpy(eto2, emr2, emr2->nSize);
1745 /* different Windows versions setup DC scaling differently */
1746 eto1->exScale = eto1->eyScale = 0.0;
1747 eto2->exScale = eto2->eyScale = 0.0;
1749 diff = memcmp(eto1, eto2, emr1->nSize);
1750 if (diff)
1752 dump_EMREXTTEXTOUT(eto1);
1753 dump_EMREXTTEXTOUT(eto2);
1755 HeapFree(GetProcessHeap(), 0, eto1);
1756 HeapFree(GetProcessHeap(), 0, eto2);
1758 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1760 /* We have to take care of NT4 differences here */
1761 diff = memcmp(emr1, emr2, emr1->nSize);
1762 if (diff)
1764 ENHMETARECORD *emr_nt4;
1766 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1767 memcpy(emr_nt4, emr2, emr2->nSize);
1768 /* Correct the nRgnSize field */
1769 emr_nt4->dParm[5] = sizeof(RECT);
1771 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1772 if (!diff)
1773 win_skip("Catered for NT4 differences\n");
1775 HeapFree(GetProcessHeap(), 0, emr_nt4);
1778 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1780 EMRPOLYBEZIER16 *eto1, *eto2;
1782 eto1 = (EMRPOLYBEZIER16*)emr1;
1783 eto2 = (EMRPOLYBEZIER16*)emr2;
1785 diff = eto1->cpts != eto2->cpts;
1786 if(!diff)
1787 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1789 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1791 EMRPOLYBEZIER *eto1, *eto2;
1793 eto1 = (EMRPOLYBEZIER*)emr1;
1794 eto2 = (EMRPOLYBEZIER*)emr2;
1796 diff = eto1->cptl != eto2->cptl;
1797 if(!diff)
1798 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1800 else
1801 diff = memcmp(emr1, emr2, emr1->nSize);
1803 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1805 if (diff)
1807 dump_emf_record(emr1, "expected bits");
1808 dump_emf_record(emr2, "actual bits");
1811 return diff == 0; /* report all non-fatal record mismatches */
1814 /* Compare the EMF produced by a test function with the
1815 * expected raw EMF data in "bits".
1816 * Return value is 0 for a perfect match,
1817 * -1 if lengths aren't equal,
1818 * otherwise returns the number of non-matching bytes.
1820 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1821 UINT bsize, const char *desc,
1822 BOOL ignore_scaling)
1824 unsigned char buf[MF_BUFSIZE];
1825 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1826 const ENHMETAHEADER *emh1, *emh2;
1828 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1829 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1831 /* ENHMETAHEADER size could differ, depending on platform */
1832 diff_nt4 = sizeof(SIZEL);
1833 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1835 if (mfsize < MF_BUFSIZE)
1837 ok(mfsize == bsize ||
1838 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1839 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1840 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1842 else
1843 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1844 desc, mfsize, bsize);
1846 /* basic things must match */
1847 emh1 = (const ENHMETAHEADER *)bits;
1848 emh2 = (const ENHMETAHEADER *)buf;
1849 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1850 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1851 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1852 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1854 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1855 ok(emh1->nSize == emh2->nSize ||
1856 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1857 broken(emh1->nSize - diff_9x == emh2->nSize),
1858 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1859 ok(emh1->rclBounds.left == emh2->rclBounds.left, "%s: expected rclBounds.left = %d, got %d\n",
1860 desc, emh1->rclBounds.left, emh2->rclBounds.left);
1861 ok(emh1->rclBounds.top == emh2->rclBounds.top, "%s: expected rclBounds.top = %d, got %d\n",
1862 desc, emh1->rclBounds.top, emh2->rclBounds.top);
1863 ok(emh1->rclBounds.right == emh2->rclBounds.right, "%s: expected rclBounds.right = %d, got %d\n",
1864 desc, emh1->rclBounds.right, emh2->rclBounds.right);
1865 ok(emh1->rclBounds.bottom == emh2->rclBounds.bottom, "%s: expected rclBounds.bottom = %d, got %d\n",
1866 desc, emh1->rclBounds.bottom, emh2->rclBounds.bottom);
1867 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1868 ok(emh1->nBytes == emh2->nBytes ||
1869 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1870 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1871 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1872 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1874 offset1 = emh1->nSize;
1875 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1876 while (offset1 < emh1->nBytes)
1878 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1879 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1881 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1882 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1884 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1886 /* We have already bailed out if iType or nSize don't match */
1887 offset1 += emr1->nSize;
1888 offset2 += emr2->nSize;
1890 return 0;
1894 /* tests blitting to an EMF */
1895 static void test_emf_BitBlt(void)
1897 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1898 HBITMAP hBitmap, hOldBitmap;
1899 HENHMETAFILE hMetafile;
1900 #define BMP_DIM 4
1901 BITMAPINFOHEADER bmih =
1903 sizeof(BITMAPINFOHEADER),
1904 BMP_DIM,/* biWidth */
1905 BMP_DIM,/* biHeight */
1906 1, /* biPlanes */
1907 24, /* biBitCount */
1908 BI_RGB, /* biCompression */
1909 0, /* biXPelsPerMeter */
1910 0, /* biYPelsPerMeter */
1911 0, /* biClrUsed */
1912 0, /* biClrImportant */
1914 void *bits;
1915 XFORM xform;
1916 BOOL ret;
1918 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1919 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1921 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1922 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1923 ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
1924 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1925 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1926 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1927 DIB_RGB_COLORS, &bits, NULL, 0);
1928 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1930 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1931 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1933 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1934 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1935 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1937 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1938 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1939 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1940 ok( ret, "BitBlt(WHITENESS) failed\n" );
1942 ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
1943 ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
1944 ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
1945 ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
1946 ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
1947 memset(&xform, 0, sizeof(xform));
1948 xform.eM11 = 0.5;
1949 xform.eM22 = 1.0;
1950 ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
1952 ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
1953 ok( ret, "StretchBlt(SRCCOPY) failed\n" );
1955 hMetafile = CloseEnhMetaFile(hdcMetafile);
1956 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1958 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1959 "emf_BitBlt", FALSE) != 0)
1961 dump_emf_bits(hMetafile, "emf_BitBlt");
1962 dump_emf_records(hMetafile, "emf_BitBlt");
1965 SelectObject(hdcBitmap, hOldBitmap);
1966 DeleteObject(hBitmap);
1967 DeleteDC(hdcBitmap);
1968 DeleteDC(hdcDisplay);
1969 #undef BMP_DIM
1972 static void test_emf_DCBrush(void)
1974 HDC hdcMetafile;
1975 HENHMETAFILE hMetafile;
1976 HBRUSH hBrush;
1977 HPEN hPen;
1978 BOOL ret;
1979 COLORREF color;
1981 if (!pSetDCBrushColor || !pSetDCPenColor)
1983 win_skip( "SetDCBrush/PenColor not supported\n" );
1984 return;
1987 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1988 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1990 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1991 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1993 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1994 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1996 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1997 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1999 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2000 ok( color == 0, "SetDCPenColor returned %x\n", color );
2002 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2004 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2005 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
2007 hMetafile = CloseEnhMetaFile(hdcMetafile);
2008 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
2010 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
2011 "emf_DC_Brush", FALSE ) != 0)
2013 dump_emf_bits(hMetafile, "emf_DC_Brush");
2014 dump_emf_records(hMetafile, "emf_DC_Brush");
2016 ret = DeleteEnhMetaFile(hMetafile);
2017 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2018 ret = DeleteObject(hBrush);
2019 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2020 ret = DeleteObject(hPen);
2021 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
2024 /* Test a blank metafile. May be used as a template for new tests. */
2026 static void test_mf_Blank(void)
2028 HDC hdcMetafile;
2029 HMETAFILE hMetafile;
2030 INT caps;
2031 BOOL ret;
2032 INT type;
2034 hdcMetafile = CreateMetaFileA(NULL);
2035 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2036 trace("hdcMetafile %p\n", hdcMetafile);
2038 /* Tests on metafile initialization */
2039 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
2040 ok (caps == DT_METAFILE,
2041 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
2043 hMetafile = CloseMetaFile(hdcMetafile);
2044 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2045 type = GetObjectType(hMetafile);
2046 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2047 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2049 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2050 "mf_blank") != 0)
2052 dump_mf_bits(hMetafile, "mf_Blank");
2053 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2056 ret = DeleteMetaFile(hMetafile);
2057 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2060 static void test_CopyMetaFile(void)
2062 HDC hdcMetafile;
2063 HMETAFILE hMetafile, hmf_copy;
2064 BOOL ret;
2065 char temp_path[MAX_PATH];
2066 char mf_name[MAX_PATH];
2067 INT type;
2069 hdcMetafile = CreateMetaFileA(NULL);
2070 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2071 trace("hdcMetafile %p\n", hdcMetafile);
2073 hMetafile = CloseMetaFile(hdcMetafile);
2074 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2075 type = GetObjectType(hMetafile);
2076 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2078 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2079 "mf_blank") != 0)
2081 dump_mf_bits(hMetafile, "mf_Blank");
2082 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2085 GetTempPathA(MAX_PATH, temp_path);
2086 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
2088 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
2089 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
2091 type = GetObjectType(hmf_copy);
2092 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
2094 ret = DeleteMetaFile(hMetafile);
2095 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2097 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
2099 dump_mf_bits(hmf_copy, "mf_Blank");
2100 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
2103 ret = DeleteMetaFile(hmf_copy);
2104 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
2106 DeleteFileA(mf_name);
2109 static void test_SetMetaFileBits(void)
2111 HMETAFILE hmf;
2112 INT type;
2113 BOOL ret;
2114 BYTE buf[256];
2115 METAHEADER *mh;
2117 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2118 trace("hmf %p\n", hmf);
2119 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2120 type = GetObjectType(hmf);
2121 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
2123 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2125 dump_mf_bits(hmf, "mf_Graphics");
2126 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2129 ret = DeleteMetaFile(hmf);
2130 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2132 /* NULL data crashes XP SP1 */
2133 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2135 /* Now with zero size */
2136 SetLastError(0xdeadbeef);
2137 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2138 trace("hmf %p\n", hmf);
2139 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2140 ok(GetLastError() == ERROR_INVALID_DATA ||
2141 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2142 "wrong error %d\n", GetLastError());
2144 /* Now with odd size */
2145 SetLastError(0xdeadbeef);
2146 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2147 trace("hmf %p\n", hmf);
2148 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2149 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2151 /* Now with zeroed out header fields */
2152 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2153 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2154 mh = (METAHEADER *)buf;
2155 /* corruption of any of the below fields leads to a failure */
2156 mh->mtType = 0;
2157 mh->mtVersion = 0;
2158 mh->mtHeaderSize = 0;
2159 SetLastError(0xdeadbeef);
2160 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2161 trace("hmf %p\n", hmf);
2162 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2163 ok(GetLastError() == ERROR_INVALID_DATA ||
2164 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2165 "wrong error %d\n", GetLastError());
2167 /* Now with corrupted mtSize field */
2168 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2169 mh = (METAHEADER *)buf;
2170 /* corruption of mtSize doesn't lead to a failure */
2171 mh->mtSize *= 2;
2172 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2173 trace("hmf %p\n", hmf);
2174 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2176 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2178 dump_mf_bits(hmf, "mf_Graphics");
2179 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2182 ret = DeleteMetaFile(hmf);
2183 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2185 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2186 /* Now with zeroed out mtSize field */
2187 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2188 mh = (METAHEADER *)buf;
2189 /* zeroing mtSize doesn't lead to a failure */
2190 mh->mtSize = 0;
2191 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2192 trace("hmf %p\n", hmf);
2193 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2195 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2197 dump_mf_bits(hmf, "mf_Graphics");
2198 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2201 ret = DeleteMetaFile(hmf);
2202 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2203 #endif
2206 /* Simple APIs from mfdrv/graphics.c
2209 static void test_mf_Graphics(void)
2211 HDC hdcMetafile;
2212 HMETAFILE hMetafile;
2213 POINT oldpoint;
2214 BOOL ret;
2216 hdcMetafile = CreateMetaFileA(NULL);
2217 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2218 trace("hdcMetafile %p\n", hdcMetafile);
2220 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2221 ok( ret, "MoveToEx error %d.\n", GetLastError());
2222 ret = LineTo(hdcMetafile, 2, 2);
2223 ok( ret, "LineTo error %d.\n", GetLastError());
2224 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2225 ok( ret, "MoveToEx error %d.\n", GetLastError());
2227 /* oldpoint gets garbage under Win XP, so the following test would
2228 * work under Wine but fails under Windows:
2230 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2231 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2232 * oldpoint.x, oldpoint.y);
2235 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2236 ok( ret, "Ellipse error %d.\n", GetLastError());
2238 hMetafile = CloseMetaFile(hdcMetafile);
2239 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2240 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2242 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2243 "mf_Graphics") != 0)
2245 dump_mf_bits(hMetafile, "mf_Graphics");
2246 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2249 ret = DeleteMetaFile(hMetafile);
2250 ok( ret, "DeleteMetaFile(%p) error %d\n",
2251 hMetafile, GetLastError());
2254 static void test_mf_PatternBrush(void)
2256 HDC hdcMetafile;
2257 HMETAFILE hMetafile;
2258 LOGBRUSH *orig_lb;
2259 HBRUSH hBrush;
2260 BOOL ret;
2262 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2264 orig_lb->lbStyle = BS_PATTERN;
2265 orig_lb->lbColor = RGB(0, 0, 0);
2266 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2267 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2269 hBrush = CreateBrushIndirect (orig_lb);
2270 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2272 hdcMetafile = CreateMetaFileA(NULL);
2273 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2274 trace("hdcMetafile %p\n", hdcMetafile);
2276 hBrush = SelectObject(hdcMetafile, hBrush);
2277 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2279 hMetafile = CloseMetaFile(hdcMetafile);
2280 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2281 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2283 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2284 "mf_Pattern_Brush") != 0)
2286 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2287 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2290 ret = DeleteMetaFile(hMetafile);
2291 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2292 ret = DeleteObject(hBrush);
2293 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2294 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2295 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2296 GetLastError());
2297 HeapFree (GetProcessHeap(), 0, orig_lb);
2300 static void test_mf_DCBrush(void)
2302 HDC hdcMetafile;
2303 HMETAFILE hMetafile;
2304 HBRUSH hBrush;
2305 HPEN hPen;
2306 BOOL ret;
2307 COLORREF color;
2309 if (!pSetDCBrushColor || !pSetDCPenColor)
2311 win_skip( "SetDCBrush/PenColor not supported\n" );
2312 return;
2315 hdcMetafile = CreateMetaFileA(NULL);
2316 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2318 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2319 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2321 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2322 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2324 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2325 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2327 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2328 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2330 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2332 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2333 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2335 hMetafile = CloseMetaFile(hdcMetafile);
2336 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2338 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2340 dump_mf_bits(hMetafile, "mf_DCBrush");
2341 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2343 ret = DeleteMetaFile(hMetafile);
2344 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2347 static void test_mf_ExtTextOut_on_path(void)
2349 HDC hdcMetafile;
2350 HMETAFILE hMetafile;
2351 BOOL ret;
2352 static const INT dx[4] = { 3, 5, 8, 12 };
2354 hdcMetafile = CreateMetaFileA(NULL);
2355 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2356 trace("hdcMetafile %p\n", hdcMetafile);
2358 ret = BeginPath(hdcMetafile);
2359 ok(!ret, "BeginPath on metafile DC should fail\n");
2361 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2362 ok(ret, "ExtTextOut error %d\n", GetLastError());
2364 ret = EndPath(hdcMetafile);
2365 ok(!ret, "EndPath on metafile DC should fail\n");
2367 hMetafile = CloseMetaFile(hdcMetafile);
2368 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2370 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2371 "mf_TextOut_on_path") != 0)
2373 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2374 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2377 ret = DeleteMetaFile(hMetafile);
2378 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2381 static void test_emf_ExtTextOut_on_path(void)
2383 HWND hwnd;
2384 HDC hdcDisplay, hdcMetafile;
2385 HENHMETAFILE hMetafile;
2386 BOOL ret;
2387 static const INT dx[4] = { 3, 5, 8, 12 };
2389 /* Win9x doesn't play EMFs on invisible windows */
2390 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2391 0, 0, 200, 200, 0, 0, 0, NULL);
2392 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2394 hdcDisplay = GetDC(hwnd);
2395 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2397 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2398 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2400 ret = BeginPath(hdcMetafile);
2401 ok(ret, "BeginPath error %d\n", GetLastError());
2403 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2404 ok(ret, "ExtTextOut error %d\n", GetLastError());
2406 ret = EndPath(hdcMetafile);
2407 ok(ret, "EndPath error %d\n", GetLastError());
2409 hMetafile = CloseEnhMetaFile(hdcMetafile);
2410 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2412 /* this doesn't succeed yet: EMF has correct size, all EMF records
2413 * are there, but their contents don't match for different reasons.
2415 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2416 "emf_TextOut_on_path", FALSE) != 0)
2418 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2419 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2422 ret = DeleteEnhMetaFile(hMetafile);
2423 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2424 ret = ReleaseDC(hwnd, hdcDisplay);
2425 ok(ret, "ReleaseDC error %d\n", GetLastError());
2426 DestroyWindow(hwnd);
2429 static const unsigned char EMF_CLIPPING[] =
2431 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2433 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2435 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2436 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2437 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2438 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2440 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2441 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2443 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2444 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2445 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2446 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2447 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2448 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2449 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2450 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2451 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2452 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2453 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2454 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2455 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2456 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2459 static void translate( POINT *pt, UINT count, const XFORM *xform )
2461 while (count--)
2463 FLOAT x = (FLOAT)pt->x;
2464 FLOAT y = (FLOAT)pt->y;
2465 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2466 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2467 pt++;
2471 /* Compare rectangles allowing rounding errors */
2472 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2474 return abs(rc1->left - rc2->left) <= 1 &&
2475 abs(rc1->top - rc2->top) <= 1 &&
2476 abs(rc1->right - rc2->right) <= 1 &&
2477 abs(rc1->bottom - rc2->bottom) <= 1;
2480 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2481 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2483 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2485 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2486 union _rgn
2488 RGNDATA data;
2489 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2491 const union _rgn *rgn1;
2492 union _rgn rgn2;
2493 RECT rect, rc_transformed;
2494 const RECT *rc = (const RECT *)param;
2495 HRGN hrgn;
2496 XFORM xform;
2497 INT ret;
2498 BOOL is_win9x;
2500 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2501 clip->cbRgnData, clip->iMode);
2503 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2504 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2505 "too small data block: %u bytes\n", clip->cbRgnData);
2506 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2507 return 0;
2509 rgn1 = (const union _rgn *)clip->RgnData;
2511 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2512 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2513 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2514 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2515 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2517 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2519 rect = *(const RECT *)rgn1->data.Buffer;
2520 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2521 ok(EqualRect(&rect, rc), "rects don't match\n");
2523 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2524 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2525 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2526 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2527 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2528 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2530 hrgn = CreateRectRgn(0, 0, 0, 0);
2532 memset(&xform, 0, sizeof(xform));
2533 SetLastError(0xdeadbeef);
2534 ret = GetWorldTransform(hdc, &xform);
2535 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2536 if (!is_win9x)
2537 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2539 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2541 ret = GetClipRgn(hdc, hrgn);
2542 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2544 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2546 ret = GetClipRgn(hdc, hrgn);
2547 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2549 /* Win9x returns empty clipping region */
2550 if (is_win9x) return 1;
2552 ret = GetRegionData(hrgn, 0, NULL);
2553 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2555 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2556 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2558 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2559 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2560 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2561 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2562 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2564 rect = rgn2.data.rdh.rcBound;
2565 rc_transformed = *rc;
2566 translate((POINT *)&rc_transformed, 2, &xform);
2567 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2568 rc_transformed.right, rc_transformed.bottom);
2569 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2571 rect = *(const RECT *)rgn2.data.Buffer;
2572 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2573 rc_transformed = *rc;
2574 translate((POINT *)&rc_transformed, 2, &xform);
2575 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2576 rc_transformed.right, rc_transformed.bottom);
2577 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2579 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2580 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2581 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2582 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2583 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2584 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2586 DeleteObject(hrgn);
2588 return 1;
2591 static void test_emf_clipping(void)
2593 static const RECT rc = { 0, 0, 100, 100 };
2594 RECT rc_clip = { 100, 100, 1024, 1024 };
2595 HWND hwnd;
2596 HDC hdc;
2597 HENHMETAFILE hemf;
2598 HRGN hrgn;
2599 INT ret;
2600 RECT rc_res, rc_sclip;
2602 SetLastError(0xdeadbeef);
2603 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2604 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2606 /* Need to write something to the emf, otherwise Windows won't play it back */
2607 LineTo(hdc, 1, 1);
2609 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2610 ret = SelectClipRgn(hdc, hrgn);
2611 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2613 SetLastError(0xdeadbeef);
2614 hemf = CloseEnhMetaFile(hdc);
2615 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2617 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2618 "emf_clipping", FALSE) != 0)
2620 dump_emf_bits(hemf, "emf_clipping");
2621 dump_emf_records(hemf, "emf_clipping");
2624 DeleteObject(hrgn);
2626 /* Win9x doesn't play EMFs on invisible windows */
2627 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2628 0, 0, 200, 200, 0, 0, 0, NULL);
2629 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2631 hdc = GetDC(hwnd);
2633 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2634 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2636 DeleteEnhMetaFile(hemf);
2637 ReleaseDC(hwnd, hdc);
2638 DestroyWindow(hwnd);
2640 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2642 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2643 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2644 SelectClipRgn(hdc, hrgn);
2645 SetRect(&rc_res, -1, -1, -1, -1);
2646 ret = GetClipBox(hdc, &rc_res);
2647 ok(ret == SIMPLEREGION, "got %d\n", ret);
2648 ok(EqualRect(&rc_res, &rc_sclip),
2649 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2650 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2651 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2653 OffsetRect(&rc_sclip, -100, -100);
2654 ret = OffsetClipRgn(hdc, -100, -100);
2655 ok(ret == SIMPLEREGION, "got %d\n", ret);
2656 SetRect(&rc_res, -1, -1, -1, -1);
2657 ret = GetClipBox(hdc, &rc_res);
2658 ok(ret == SIMPLEREGION, "got %d\n", ret);
2659 ok(EqualRect(&rc_res, &rc_sclip),
2660 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2661 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2662 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2664 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2665 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2666 if (ret == COMPLEXREGION)
2668 /* XP returns COMPLEXREGION although region contains only 1 rect */
2669 ret = GetClipRgn(hdc, hrgn);
2670 ok(ret == 1, "expected 1, got %d\n", ret);
2671 ret = rgn_rect_count(hrgn);
2672 ok(ret == 1, "expected 1, got %d\n", ret);
2674 SetRect(&rc_res, -1, -1, -1, -1);
2675 ret = GetClipBox(hdc, &rc_res);
2676 ok(ret == SIMPLEREGION, "got %d\n", ret);
2677 ok(EqualRect(&rc_res, &rc),
2678 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2679 rc.left, rc.top, rc.right, rc.bottom,
2680 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2682 SetRect(&rc_sclip, 0, 0, 100, 50);
2683 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2684 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2685 if (ret == COMPLEXREGION)
2687 /* XP returns COMPLEXREGION although region contains only 1 rect */
2688 ret = GetClipRgn(hdc, hrgn);
2689 ok(ret == 1, "expected 1, got %d\n", ret);
2690 ret = rgn_rect_count(hrgn);
2691 ok(ret == 1, "expected 1, got %d\n", ret);
2693 SetRect(&rc_res, -1, -1, -1, -1);
2694 ret = GetClipBox(hdc, &rc_res);
2695 ok(ret == SIMPLEREGION, "got %d\n", ret);
2696 ok(EqualRect(&rc_res, &rc_sclip),
2697 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2698 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2699 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2701 hemf = CloseEnhMetaFile(hdc);
2702 DeleteEnhMetaFile(hemf);
2703 DeleteObject(hrgn);
2706 static const unsigned char MF_CLIP_BITS[] = {
2707 /* METAHEADER */
2708 0x01, 0x00, /* mtType */
2709 0x09, 0x00, /* mtHeaderSize */
2710 0x00, 0x03, /* mtVersion */
2711 0x32, 0x00, 0x00, 0x00, /* mtSize */
2712 0x01, 0x00, /* mtNoObjects */
2713 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2714 0x00, 0x00, /* reserved */
2716 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2717 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2718 0xff, 0x06, /* META_CREATEREGION */
2719 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2720 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2721 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2722 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2723 0x02, 0x00,
2725 /* METARECORD for SelectObject */
2726 0x04, 0x00, 0x00, 0x00,
2727 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2728 0x00, 0x00,
2730 /* METARECORD */
2731 0x04, 0x00, 0x00, 0x00,
2732 0xf0, 0x01, /* META_DELETEOBJECT */
2733 0x00, 0x00,
2735 /* METARECORD for MoveTo(1,0x30) */
2736 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2737 0x14, 0x02, /* META_MOVETO */
2738 0x30, 0x00, /* y */
2739 0x01, 0x00, /* x */
2741 /* METARECORD for LineTo(0x20, 0x30) */
2742 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2743 0x13, 0x02, /* META_LINETO */
2744 0x30, 0x00, /* y */
2745 0x20, 0x00, /* x */
2747 /* EOF */
2748 0x03, 0x00, 0x00, 0x00,
2749 0x00, 0x00
2752 static int clip_mf_enum_proc_seen_selectclipregion;
2753 static int clip_mf_enum_proc_seen_selectobject;
2755 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2756 METARECORD *mr, int n_objs, LPARAM param)
2758 switch (mr->rdFunction) {
2759 case META_SELECTCLIPREGION:
2760 clip_mf_enum_proc_seen_selectclipregion++;
2761 break;
2762 case META_SELECTOBJECT:
2763 clip_mf_enum_proc_seen_selectobject++;
2764 break;
2766 return 1;
2769 static void test_mf_clipping(void)
2771 /* left top right bottom */
2772 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2773 HWND hwnd;
2774 HDC hdc;
2775 HMETAFILE hmf;
2776 HRGN hrgn;
2777 INT ret;
2779 SetLastError(0xdeadbeef);
2780 hdc = CreateMetaFileA(NULL);
2781 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2783 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2784 ret = SelectClipRgn(hdc, hrgn);
2785 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2786 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2788 /* Draw a line that starts off left of the clip region and ends inside it */
2789 MoveToEx(hdc, 0x1, 0x30, NULL);
2790 LineTo(hdc, 0x20, 0x30);
2792 SetLastError(0xdeadbeef);
2793 hmf = CloseMetaFile(hdc);
2794 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2796 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2797 "mf_clipping") != 0)
2799 dump_mf_bits(hmf, "mf_clipping");
2802 DeleteObject(hrgn);
2804 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2805 0, 0, 200, 200, 0, 0, 0, NULL);
2806 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2808 hdc = GetDC(hwnd);
2810 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2811 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2813 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2814 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2815 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2816 ok(clip_mf_enum_proc_seen_selectobject == 1,
2817 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2819 DeleteMetaFile(hmf);
2820 ReleaseDC(hwnd, hdc);
2821 DestroyWindow(hwnd);
2824 static const unsigned char MF_PATH_BITS[] =
2826 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2827 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2828 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2829 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2830 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2831 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2832 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2833 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2834 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2835 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2836 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2839 static void test_mf_GetPath(void)
2841 HDC hdc;
2842 HMETAFILE hmf;
2843 BOOL ret;
2844 int size;
2846 SetLastError(0xdeadbeef);
2847 hdc = CreateMetaFileA(NULL);
2848 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2850 BeginPath(hdc);
2851 ret = MoveToEx(hdc, 50, 50, NULL);
2852 ok( ret, "MoveToEx error %d.\n", GetLastError());
2853 ret = LineTo(hdc, 50, 150);
2854 ok( ret, "LineTo error %d.\n", GetLastError());
2855 ret = LineTo(hdc, 150, 150);
2856 ok( ret, "LineTo error %d.\n", GetLastError());
2857 ret = LineTo(hdc, 150, 50);
2858 ok( ret, "LineTo error %d.\n", GetLastError());
2859 ret = LineTo(hdc, 50, 50);
2860 ok( ret, "LineTo error %d.\n", GetLastError());
2861 Rectangle(hdc, 10, 10, 20, 20);
2862 EndPath(hdc);
2864 size = GetPath(hdc, NULL, NULL, 0);
2865 ok( size == -1, "GetPath returned %d.\n", size);
2867 hmf = CloseMetaFile(hdc);
2868 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2870 if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
2872 dump_mf_bits(hmf, "mf_GetPath");
2873 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2876 ret = DeleteMetaFile(hmf);
2877 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2880 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2882 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2883 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2884 /* When using MM_TEXT Win9x does not update the mapping mode
2885 * until a record is played which actually outputs something */
2886 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2887 LPtoDP(hdc, mapping, 2);
2888 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2889 lpEMFR->iType, lpEMFR->nSize,
2890 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2892 if (lpEMFR->iType == EMR_LINETO)
2894 INT x0, y0, x1, y1;
2895 if (!lpMFP || lpMFP->mm == MM_TEXT)
2897 x0 = 0;
2898 y0 = 0;
2899 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2900 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2902 else
2904 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2906 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2907 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2908 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2909 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2911 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2912 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2913 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2914 x0, y0, x1, y1);
2916 return TRUE;
2919 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2921 HDC hdcMf;
2922 HMETAFILE hmf;
2923 HENHMETAFILE hemf;
2924 BOOL ret;
2925 UINT size;
2926 LPBYTE pBits;
2928 hdcMf = CreateMetaFileA(NULL);
2929 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2930 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2931 ok(ret, "LineTo failed with error %d\n", GetLastError());
2932 hmf = CloseMetaFile(hdcMf);
2933 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2935 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2937 dump_mf_bits(hmf, "mf_LineTo");
2938 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2941 size = GetMetaFileBitsEx(hmf, 0, NULL);
2942 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2943 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2944 GetMetaFileBitsEx(hmf, size, pBits);
2945 DeleteMetaFile(hmf);
2946 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2947 HeapFree(GetProcessHeap(), 0, pBits);
2948 return hemf;
2951 static void test_mf_conversions(void)
2953 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2955 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2956 HENHMETAFILE hemf;
2957 METAFILEPICT mfp;
2958 RECT rect = { 0, 0, 100, 100 };
2959 mfp.mm = MM_ANISOTROPIC;
2960 mfp.xExt = 100;
2961 mfp.yExt = 100;
2962 mfp.hMF = NULL;
2963 hemf = create_converted_emf(&mfp);
2965 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2966 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2968 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2969 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2972 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2974 DeleteEnhMetaFile(hemf);
2975 DeleteDC(hdcOffscreen);
2978 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2980 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2981 HENHMETAFILE hemf;
2982 METAFILEPICT mfp;
2983 RECT rect = { 0, 0, 100, 100 };
2984 mfp.mm = MM_TEXT;
2985 mfp.xExt = 0;
2986 mfp.yExt = 0;
2987 mfp.hMF = NULL;
2988 hemf = create_converted_emf(&mfp);
2990 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2991 "emf_LineTo MM_TEXT", TRUE) != 0)
2993 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2994 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2997 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2999 DeleteEnhMetaFile(hemf);
3000 DeleteDC(hdcOffscreen);
3003 trace("Testing MF->EMF conversion (NULL mfp)\n");
3005 HDC hdcOffscreen = CreateCompatibleDC(NULL);
3006 HENHMETAFILE hemf;
3007 RECT rect = { 0, 0, 100, 100 };
3008 hemf = create_converted_emf(NULL);
3010 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
3011 "emf_LineTo NULL", TRUE) != 0)
3013 dump_emf_bits(hemf, "emf_LineTo NULL");
3014 dump_emf_records(hemf, "emf_LineTo NULL");
3017 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
3019 DeleteEnhMetaFile(hemf);
3020 DeleteDC(hdcOffscreen);
3024 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3025 LONG mm, LONG xExt, LONG yExt,
3026 RECTL * rclBounds, RECTL * rclFrame)
3028 METAFILEPICT mfp;
3029 METAFILEPICT * mfpPtr = NULL;
3030 HENHMETAFILE emf;
3031 ENHMETAHEADER header;
3032 UINT res;
3034 if (!mfpIsNull)
3036 mfp.mm = mm;
3037 mfp.xExt = xExt;
3038 mfp.yExt = yExt;
3039 mfpPtr = &mfp;
3042 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
3043 ok(emf != NULL, "SetWinMetaFileBits failed\n");
3044 if (!emf) return FALSE;
3045 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
3046 ok(res != 0, "GetEnhMetaHeader failed\n");
3047 DeleteEnhMetaFile(emf);
3048 if (!res) return FALSE;
3050 *rclBounds = header.rclBounds;
3051 *rclFrame = header.rclFrame;
3052 return TRUE;
3055 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3056 LONG mm, LONG xExt, LONG yExt,
3057 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
3059 RECTL rclBounds, rclFrame;
3061 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
3063 const char * msg;
3064 char buf[64];
3066 if (mfpIsNull)
3068 msg = "mfp == NULL";
3070 else
3072 const char * mm_str;
3073 switch (mm)
3075 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
3076 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
3077 default: mm_str = "Unexpected";
3079 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
3080 msg = buf;
3083 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
3084 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
3085 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
3086 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
3087 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
3088 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
3089 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
3090 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
3094 static void test_SetWinMetaFileBits(void)
3096 HMETAFILE wmf;
3097 HDC wmfDC;
3098 BYTE * buffer;
3099 UINT buffer_size;
3100 RECT rect;
3101 UINT res;
3102 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
3103 RECTL rclBoundsIsotropic, rclFrameIsotropic;
3104 RECTL rclBounds, rclFrame;
3105 HDC dc;
3106 LONG diffx, diffy;
3108 wmfDC = CreateMetaFileA(NULL);
3109 ok(wmfDC != NULL, "CreateMetaFile failed\n");
3110 if (!wmfDC) return;
3112 SetWindowExtEx(wmfDC, 100, 100, NULL);
3113 rect.left = rect.top = 0;
3114 rect.right = rect.bottom = 50;
3115 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
3116 wmf = CloseMetaFile(wmfDC);
3117 ok(wmf != NULL, "Metafile creation failed\n");
3118 if (!wmf) return;
3120 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
3121 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
3122 if (buffer_size == 0)
3124 DeleteMetaFile(wmf);
3125 return;
3128 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
3129 ok(buffer != NULL, "HeapAlloc failed\n");
3130 if (!buffer)
3132 DeleteMetaFile(wmf);
3133 return;
3136 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
3137 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3138 DeleteMetaFile(wmf);
3139 if (res != buffer_size)
3141 HeapFree(GetProcessHeap(), 0, buffer);
3142 return;
3145 /* Get the reference bounds and frame */
3146 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3147 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3149 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
3150 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
3151 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3153 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3154 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3155 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
3156 if (diffx < 0) diffx = -diffx;
3157 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3159 dc = CreateCompatibleDC(NULL);
3161 /* Allow 1 mm difference (rounding errors) */
3162 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
3163 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
3164 if (diffx < 0) diffx = -diffx;
3165 if (diffy < 0) diffy = -diffy;
3166 todo_wine
3168 ok(diffx <= 1 && diffy <= 1,
3169 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3170 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
3173 /* Allow 1 mm difference (rounding errors) */
3174 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
3175 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
3176 if (diffx < 0) diffx = -diffx;
3177 if (diffy < 0) diffy = -diffy;
3178 todo_wine
3180 ok(diffx <= 1 && diffy <= 1,
3181 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3182 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
3184 DeleteDC(dc);
3186 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3187 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3189 /* If xExt or yExt is zero or negative, the whole device surface is used */
3190 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3191 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3192 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3193 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3194 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3195 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3196 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3197 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3198 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3199 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3200 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3201 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3203 /* MSDN says that negative xExt and yExt values specify a ratio.
3204 Check that this is wrong and the whole device surface is used */
3205 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3206 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3208 /* Ordinary conversions */
3210 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3212 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3213 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3214 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3215 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3218 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3220 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3221 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3222 ok(rclBounds.left == 0 && rclBounds.top == 0,
3223 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3225 /* Wine has a rounding error */
3226 diffx = rclBounds.right - rclBounds.bottom;
3227 if (diffx < 0) diffx = -diffx;
3228 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3231 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3233 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3234 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3237 HeapFree(GetProcessHeap(), 0, buffer);
3240 static BOOL near_match(int x, int y)
3242 int epsilon = min(abs(x), abs(y));
3244 epsilon = max(epsilon/100, 2);
3246 if(x < y - epsilon || x > y + epsilon) return FALSE;
3247 return TRUE;
3250 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3252 HENHMETAFILE emf, emf2;
3253 HDC display_dc, emf_dc;
3254 ENHMETAHEADER *enh_header, *enh2_header;
3255 UINT size, emf_size, i, emf2_size;
3256 WORD check = 0;
3257 DWORD rec_num = 0;
3258 METAHEADER *mh = NULL;
3259 METARECORD *rec;
3260 INT horz_res, vert_res, horz_size, vert_size;
3261 INT curve_caps, line_caps, poly_caps;
3262 METAFILEPICT mfp;
3264 display_dc = GetDC(NULL);
3265 ok(display_dc != NULL, "display_dc is NULL\n");
3267 horz_res = GetDeviceCaps(display_dc, HORZRES);
3268 vert_res = GetDeviceCaps(display_dc, VERTRES);
3269 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3270 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3272 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3273 ok(emf_dc != NULL, "emf_dc is NULL\n");
3275 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3276 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3278 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3279 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3281 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3282 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3284 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3285 Rectangle(emf_dc, 0, 0, 1000, 20);
3286 emf = CloseEnhMetaFile(emf_dc);
3287 ok(emf != NULL, "emf is NULL\n");
3289 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3290 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3291 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3292 DeleteEnhMetaFile(emf);
3293 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3294 have different resolutions */
3295 enh_header->szlDevice.cx *= scale;
3296 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3297 ok(emf != NULL, "emf is NULL\n");
3298 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3300 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3301 ok(size ||
3302 broken(size == 0), /* some versions of winxp fail for some reason */
3303 "GetWinMetaFileBits returns 0\n");
3304 if(!size) goto end;
3305 mh = HeapAlloc(GetProcessHeap(), 0, size);
3306 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3308 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3309 ok(check == 0, "check %04x\n", check);
3311 rec = (METARECORD*)(mh + 1);
3313 while(rec->rdSize && rec->rdFunction)
3315 const DWORD chunk_size = 0x2000;
3316 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3318 if(rec_num < mfcomment_chunks)
3320 DWORD this_chunk_size = chunk_size;
3322 if(rec_num == mfcomment_chunks - 1)
3323 this_chunk_size = emf_size - rec_num * chunk_size;
3325 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3326 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3327 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3328 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3329 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3330 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3331 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3332 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3333 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3334 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3335 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3336 /* parm[8] is the checksum, tested above */
3337 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3338 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3339 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3340 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3341 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3342 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3343 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3344 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 */
3345 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3346 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3349 else if(rec_num == mfcomment_chunks)
3351 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3352 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3354 else if(rec_num == mfcomment_chunks + 1)
3356 POINT pt;
3357 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3358 switch(mode)
3360 case MM_TEXT:
3361 case MM_ISOTROPIC:
3362 case MM_ANISOTROPIC:
3363 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3364 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3365 break;
3366 case MM_LOMETRIC:
3367 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3368 pt.x = MulDiv( rc->left, 1, 10);
3369 break;
3370 case MM_HIMETRIC:
3371 pt.y = -rc->top + 1;
3372 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3373 break;
3374 case MM_LOENGLISH:
3375 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3376 pt.x = MulDiv( rc->left, 10, 254);
3377 break;
3378 case MM_HIENGLISH:
3379 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3380 pt.x = MulDiv( rc->left, 100, 254);
3381 break;
3382 case MM_TWIPS:
3383 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3384 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3385 break;
3386 default:
3387 pt.x = pt.y = 0;
3389 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3390 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3392 if(rec_num == mfcomment_chunks + 2)
3394 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3395 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3396 "got %d\n", (short)rec->rdParm[0]);
3397 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3398 "got %d\n", (short)rec->rdParm[1]);
3401 rec_num++;
3402 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3405 /* Show that we get the original back when we do the reverse conversion.
3406 mfp is ignored in this case. */
3407 mfp.mm = MM_ISOTROPIC;
3408 mfp.xExt = 0xcafe;
3409 mfp.yExt = 0xbeef;
3410 emf2 = SetWinMetaFileBits( size, (BYTE*)mh, NULL, &mfp );
3411 ok( !!emf2, "got NULL\n" );
3412 emf2_size = GetEnhMetaFileBits( emf2, 0, NULL );
3413 enh2_header = HeapAlloc( GetProcessHeap(), 0, emf2_size );
3414 emf2_size = GetEnhMetaFileBits( emf2, emf2_size, (BYTE*)enh2_header );
3415 ok( emf_size == emf2_size, "%d %d\n", emf_size, emf2_size );
3416 ok( !memcmp( enh_header, enh2_header, emf_size ), "mismatch\n" );
3417 HeapFree( GetProcessHeap(), 0, enh2_header );
3418 DeleteEnhMetaFile( emf2 );
3420 end:
3421 HeapFree(GetProcessHeap(), 0, mh);
3422 HeapFree(GetProcessHeap(), 0, enh_header);
3423 DeleteEnhMetaFile(emf);
3425 ReleaseDC(NULL, display_dc);
3428 static void test_GetWinMetaFileBits(void)
3430 UINT mode;
3431 RECT frames[] =
3433 { 1000, 2000, 3000, 6000},
3434 {-1000, 2000, 3000, 6000},
3435 { 1000, -2000, 3000, 6000},
3436 { 1005, 2005, 3000, 6000},
3437 {-1005, -2005, 3000, 6000},
3438 {-1005, -2010, 3000, 6000},
3439 {-1005, 2010, 3000, 6000},
3440 { 0, 0, 1, 1},
3441 { -1, -1, 1, 1},
3442 { 0, 0, 0, 0}
3445 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3447 RECT *rc;
3448 for(rc = frames; rc->right - rc->left > 0; rc++)
3450 getwinmetafilebits(mode, 1, rc);
3451 getwinmetafilebits(mode, 2, rc);
3456 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3457 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3458 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3460 static void test_gdiis(void)
3462 RECT rect = {0,0,100,100};
3463 HDC hdc, hemfDC, hmfDC;
3464 HENHMETAFILE hemf;
3465 HMODULE hgdi32;
3467 /* resolve all the functions */
3468 hgdi32 = GetModuleHandleA("gdi32.dll");
3469 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3470 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3471 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3473 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3475 win_skip("Needed GdiIs* functions are not available\n");
3476 return;
3479 /* try with nothing */
3480 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3481 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3482 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3484 /* try with a metafile */
3485 hmfDC = CreateMetaFileA(NULL);
3486 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3487 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3488 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3489 DeleteMetaFile(CloseMetaFile(hmfDC));
3491 /* try with an enhanced metafile */
3492 hdc = GetDC(NULL);
3493 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3494 ok(hemfDC != NULL, "failed to create emf\n");
3496 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3497 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3498 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3500 hemf = CloseEnhMetaFile(hemfDC);
3501 ok(hemf != NULL, "failed to close EMF\n");
3502 DeleteEnhMetaFile(hemf);
3503 ReleaseDC(NULL,hdc);
3506 static void test_SetEnhMetaFileBits(void)
3508 BYTE data[256];
3509 HENHMETAFILE hemf;
3510 ENHMETAHEADER *emh;
3512 memset(data, 0xAA, sizeof(data));
3513 SetLastError(0xdeadbeef);
3514 hemf = SetEnhMetaFileBits(sizeof(data), data);
3515 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3516 ok(GetLastError() == ERROR_INVALID_DATA ||
3517 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3518 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3520 emh = (ENHMETAHEADER *)data;
3521 memset(emh, 0, sizeof(*emh));
3523 emh->iType = EMR_HEADER;
3524 emh->nSize = sizeof(*emh);
3525 emh->dSignature = ENHMETA_SIGNATURE;
3526 /* emh->nVersion = 0x10000; XP doesn't care about version */
3527 emh->nBytes = sizeof(*emh);
3528 /* emh->nRecords = 1; XP doesn't care about records */
3529 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3531 SetLastError(0xdeadbeef);
3532 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3533 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3534 DeleteEnhMetaFile(hemf);
3536 /* XP refuses to load unaligned EMF */
3537 emh->nBytes++;
3538 SetLastError(0xdeadbeef);
3539 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3540 ok(!hemf ||
3541 broken(hemf != NULL), /* Win9x, WinMe */
3542 "SetEnhMetaFileBits should fail\n");
3543 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3544 DeleteEnhMetaFile(hemf);
3546 emh->dSignature = 0;
3547 emh->nBytes--;
3548 SetLastError(0xdeadbeef);
3549 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3550 ok(!hemf ||
3551 broken(hemf != NULL), /* Win9x, WinMe */
3552 "SetEnhMetaFileBits should fail\n");
3553 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3554 DeleteEnhMetaFile(hemf);
3557 static void test_emf_polybezier(void)
3559 HDC hdcMetafile;
3560 HENHMETAFILE hemf;
3561 POINT pts[4];
3562 BOOL ret;
3564 SetLastError(0xdeadbeef);
3565 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3566 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3568 pts[0].x = pts[0].y = 10;
3569 pts[1].x = pts[1].y = 20;
3570 pts[2].x = pts[2].y = 15;
3571 pts[3].x = pts[3].y = 25;
3572 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3573 ok( ret, "PolyBezierTo failed\n" );
3574 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3575 ok( ret, "PolyBezier failed\n" );
3577 pts[0].x = pts[0].y = 32769;
3578 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3579 ok( ret, "PolyBezier failed\n" );
3580 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3581 ok( ret, "PolyBezierTo failed\n" );
3583 hemf = CloseEnhMetaFile(hdcMetafile);
3584 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3586 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3587 "emf_Bezier", FALSE) != 0)
3589 dump_emf_bits(hemf, "emf_Bezier");
3590 dump_emf_records(hemf, "emf_Bezier");
3593 DeleteEnhMetaFile(hemf);
3596 static const unsigned char EMF_PATH_BITS[] =
3598 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3600 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3602 0xd8, 0xff, 0xff, 0xff, 0xd8, 0xff, 0xff, 0xff,
3603 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3604 0x34, 0x02, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
3605 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3607 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3608 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3610 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3611 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3612 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3613 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3614 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3615 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3616 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3617 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3618 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3619 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3620 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3621 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3622 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3623 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3624 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3625 0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
3626 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3627 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3628 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3629 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3630 0x15, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
3631 0x28, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3632 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3633 0x1a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
3634 0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3635 0x17, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
3636 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3637 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3638 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3639 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3640 0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
3641 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3642 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3643 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3644 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3645 0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
3646 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3647 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3648 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3649 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3650 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3651 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3652 0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
3653 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3654 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3655 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
3656 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3657 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3658 0x5a, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
3659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3660 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3661 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
3662 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3663 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3664 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3665 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
3666 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
3667 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
3668 0x14, 0x00, 0x00, 0x00
3671 static void test_emf_GetPath(void)
3673 POINT pts[4] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}};
3674 DWORD counts[2] = {2, 2};
3675 HDC hdcMetafile;
3676 HENHMETAFILE hemf;
3677 BOOL ret;
3678 int size;
3680 SetLastError(0xdeadbeef);
3681 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3682 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3684 BeginPath(hdcMetafile);
3685 ret = MoveToEx(hdcMetafile, 50, 50, NULL);
3686 ok( ret, "MoveToEx error %d.\n", GetLastError());
3687 ret = LineTo(hdcMetafile, 50, 150);
3688 ok( ret, "LineTo error %d.\n", GetLastError());
3689 ret = LineTo(hdcMetafile, 150, 150);
3690 ok( ret, "LineTo error %d.\n", GetLastError());
3691 ret = LineTo(hdcMetafile, 150, 50);
3692 ok( ret, "LineTo error %d.\n", GetLastError());
3693 ret = LineTo(hdcMetafile, 50, 50);
3694 ok( ret, "LineTo error %d.\n", GetLastError());
3695 Rectangle(hdcMetafile, 10, 10, 20, 20);
3696 Arc(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3697 ArcTo(hdcMetafile, 23, 23, 37, 27, 37, 27, 23, 23);
3698 Chord(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3699 Pie(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3700 Ellipse(hdcMetafile, 10, 10, 20, 20);
3701 RoundRect(hdcMetafile, 10, 10, 20, 20, 3, 5);
3702 Polyline(hdcMetafile, pts, 4);
3703 PolyPolyline(hdcMetafile, pts, counts, 2);
3704 EndPath(hdcMetafile);
3706 size = GetPath(hdcMetafile, NULL, NULL, 0);
3707 todo_wine ok( size == 88, "GetPath returned %d.\n", size);
3709 hemf = CloseEnhMetaFile(hdcMetafile);
3710 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3712 if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_GetPath", FALSE) != 0)
3714 dump_emf_bits(hemf, "test_emf_GetPath");
3715 dump_emf_records(hemf, "test_emf_GetPath");
3718 DeleteEnhMetaFile(hemf);
3721 static void test_emf_PolyPolyline(void)
3723 HDC hdcMetafile;
3724 HENHMETAFILE hemf;
3725 POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3726 DWORD counts[2];
3727 BOOL ret;
3729 SetLastError(0xdeadbeef);
3730 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3731 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3733 ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
3734 ok( !ret, "PolyPolyline\n" );
3736 SetLastError( 0xdeadbeef );
3737 counts[0] = 0;
3738 counts[1] = 1;
3739 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3740 ok( !ret, "PolyPolyline\n" );
3741 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3743 SetLastError( 0xdeadbeef );
3744 counts[0] = 1;
3745 counts[1] = 1;
3746 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3747 ok( !ret, "PolyPolyline\n" );
3748 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3750 SetLastError( 0xdeadbeef );
3751 counts[0] = 2;
3752 counts[1] = 1;
3753 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3754 ok( !ret, "PolyPolyline\n" );
3755 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3757 counts[0] = 2;
3758 counts[1] = 2;
3759 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3760 ok( ret, "PolyPolyline\n" );
3762 hemf = CloseEnhMetaFile(hdcMetafile);
3763 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3765 if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
3766 "emf_PolyPolyline", FALSE) != 0)
3768 dump_emf_bits(hemf, "emf_PolyPolyline");
3769 dump_emf_records(hemf, "emf_PolyPolyline");
3772 DeleteEnhMetaFile(hemf);
3775 static void test_emf_GradientFill(void)
3777 HDC mf;
3778 HENHMETAFILE hemf;
3779 TRIVERTEX v[] =
3781 { 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
3782 { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
3783 { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
3784 { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
3785 { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
3787 GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
3788 BOOL ret;
3790 mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
3791 ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
3793 /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
3794 * means it allocates three mesh indices rather than two per
3795 * rectangle. This results in uninitialised values being written
3796 * to the EMF which is rather difficult to test against.
3798 * Note also that the final vertex here is not required, yet it is
3799 * written to the EMF, but is not considered in the bounds
3800 * calculation.
3802 ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
3803 GRADIENT_FILL_TRIANGLE );
3804 ok( ret, "GradientFill\n" );
3806 hemf = CloseEnhMetaFile( mf );
3807 ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
3809 if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
3810 "emf_GradientFill", FALSE ) != 0)
3812 dump_emf_bits( hemf, "emf_GradientFill" );
3813 dump_emf_records( hemf, "emf_GradientFill" );
3816 DeleteEnhMetaFile( hemf );
3819 START_TEST(metafile)
3821 init_function_pointers();
3823 /* For enhanced metafiles (enhmfdrv) */
3824 test_ExtTextOut();
3825 test_ExtTextOutScale();
3826 test_SaveDC();
3827 test_emf_BitBlt();
3828 test_emf_DCBrush();
3829 test_emf_ExtTextOut_on_path();
3830 test_emf_clipping();
3831 test_emf_polybezier();
3832 test_emf_GetPath();
3833 test_emf_PolyPolyline();
3834 test_emf_GradientFill();
3836 /* For win-format metafiles (mfdrv) */
3837 test_mf_SaveDC();
3838 test_mf_Blank();
3839 test_mf_Graphics();
3840 test_mf_PatternBrush();
3841 test_mf_DCBrush();
3842 test_CopyMetaFile();
3843 test_SetMetaFileBits();
3844 test_mf_ExtTextOut_on_path();
3845 test_mf_clipping();
3846 test_mf_GetPath();
3848 /* For metafile conversions */
3849 test_mf_conversions();
3850 test_SetWinMetaFileBits();
3851 test_GetWinMetaFileBits();
3853 test_gdiis();
3854 test_SetEnhMetaFileBits();