gdi32/enhmfdrv: Always set ExtTextOut bounding rect if we're not inside path bracket.
[wine.git] / dlls / gdi32 / tests / metafile.c
blobebe7e021cab0a46daadee9f4eabfb541fce3b3c2
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 hFont = SelectObject(hdcMetafile, hFont);
244 ret = DeleteObject(hFont);
245 ok( ret, "DeleteObject error %d\n", GetLastError());
247 hMetafile = CloseEnhMetaFile(hdcMetafile);
248 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
250 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
252 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
253 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
255 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
256 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
257 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
258 SetROP2(hdcDisplay, R2_NOT);
259 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
260 SetPolyFillMode(hdcDisplay, WINDING);
261 SetStretchBltMode(hdcDisplay, HALFTONE);
263 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
264 SetBkMode(hdcDisplay, OPAQUE);
266 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
267 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
269 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
270 "text align %08x\n", GetTextAlign(hdcDisplay));
271 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
272 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
273 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
274 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
275 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
276 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
278 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
280 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
281 "A valid hdc has to require a valid rc\n");
283 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
284 "A null hdc does not require a valid rc\n");
286 ret = DeleteEnhMetaFile(hMetafile);
287 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
288 ret = ReleaseDC(hwnd, hdcDisplay);
289 ok( ret, "ReleaseDC error %d\n", GetLastError());
290 DestroyWindow(hwnd);
293 struct eto_scale_test_record
295 INT graphics_mode;
296 INT map_mode;
297 double ex_scale;
298 double ey_scale;
299 BOOL processed;
302 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
303 const ENHMETARECORD *emr, int n_objs, LPARAM param)
305 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
307 if (emr->iType == EMR_EXTTEXTOUTW)
309 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
310 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
311 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
312 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
313 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
314 test->processed = TRUE;
317 return 1;
320 static void test_ExtTextOutScale(void)
322 const RECT rc = { 0, 0, 100, 100 };
323 const WCHAR str[] = {'a',0 };
324 struct eto_scale_test_record test;
325 HDC hdcDisplay, hdcMetafile;
326 HENHMETAFILE hMetafile;
327 HWND hwnd;
328 SIZE wndext, vportext;
329 int horzSize, vertSize, horzRes, vertRes;
330 int ret;
331 int i;
333 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
334 0, 0, 200, 200, 0, 0, 0, NULL);
335 ok(hwnd != 0, "CreateWindowExA failed\n");
337 hdcDisplay = GetDC(hwnd);
338 ok(hdcDisplay != 0, "GetDC failed\n");
340 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
341 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
342 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
343 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
344 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
346 for (i = 0; i < 16; i++)
348 test.graphics_mode = i / 8 + 1;
349 test.map_mode = i % 8 + 1;
351 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
352 ok(ret, "SetGraphicsMode failed\n");
353 ret = SetMapMode(hdcDisplay, test.map_mode);
354 ok(ret, "SetMapMode failed\n");
356 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
358 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
359 ok(ret, "SetWindowExtEx failed\n");
360 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
361 ok(ret, "SetViewportExtEx failed\n");
364 ret = GetViewportExtEx(hdcDisplay, &vportext);
365 ok(ret, "GetViewportExtEx failed\n");
366 ret = GetWindowExtEx(hdcDisplay, &wndext);
367 ok(ret, "GetWindowExtEx failed\n");
369 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
370 test.graphics_mode, test.map_mode,
371 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
372 horzSize, horzRes, vertSize, vertRes);
374 if (test.graphics_mode == GM_COMPATIBLE)
376 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
377 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
378 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
379 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
381 else
383 test.ex_scale = 0.0;
384 test.ey_scale = 0.0;
387 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
388 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
390 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
391 ok(ret, "SetGraphicsMode failed\n");
392 ret = SetMapMode(hdcMetafile, test.map_mode);
393 ok(ret, "SetMapMode failed\n");
395 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
397 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
398 ok(ret, "SetWindowExtEx failed\n");
399 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
400 ok(ret, "SetViewportExtEx failed\n");
403 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
404 ok(ret, "ExtTextOutW failed\n");
406 hMetafile = CloseEnhMetaFile(hdcMetafile);
407 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
409 test.processed = 0;
410 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
411 ok(ret, "EnumEnhMetaFile failed\n");
412 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
414 ret = DeleteEnhMetaFile(hMetafile);
415 ok(ret, "DeleteEnhMetaFile failed\n");
418 ret = ReleaseDC(hwnd, hdcDisplay);
419 ok(ret, "ReleaseDC failed\n");
420 DestroyWindow(hwnd);
424 static void check_dc_state(HDC hdc, int restore_no,
425 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
426 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
428 BOOL ret;
429 XFORM xform;
430 POINT vp_org, win_org;
431 SIZE vp_size, win_size;
432 FLOAT xscale, yscale, edx, edy;
434 SetLastError(0xdeadbeef);
435 ret = GetWorldTransform(hdc, &xform);
436 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
437 ok(ret, "GetWorldTransform error %u\n", GetLastError());
439 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
441 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
442 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
444 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
445 trace("x scale %f\n", xscale);
446 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
447 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
449 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
450 trace("y scale %f\n", yscale);
451 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
452 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
454 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
455 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
456 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
457 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
459 return;
461 win9x_here:
463 GetWindowOrgEx(hdc, &win_org);
464 GetViewportOrgEx(hdc, &vp_org);
465 GetWindowExtEx(hdc, &win_size);
466 GetViewportExtEx(hdc, &vp_size);
468 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
469 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
471 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
472 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
474 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
475 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
477 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
478 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
481 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
482 const ENHMETARECORD *emr, int n_objs, LPARAM param)
484 BOOL ret;
485 XFORM xform;
486 POINT pt;
487 SIZE size;
488 static int save_state;
489 static int restore_no;
490 static int select_no;
492 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
493 hdc, emr->iType, emr->nSize, (void *)param);
495 SetLastError(0xdeadbeef);
496 ret = GetWorldTransform(hdc, &xform);
497 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
499 ret = GetWindowOrgEx(hdc, &pt);
500 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
501 trace("window org (%d,%d)\n", pt.x, pt.y);
502 ret = GetViewportOrgEx(hdc, &pt);
503 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
504 trace("vport org (%d,%d)\n", pt.x, pt.y);
505 ret = GetWindowExtEx(hdc, &size);
506 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
507 trace("window ext (%d,%d)\n", size.cx, size.cy);
508 ret = GetViewportExtEx(hdc, &size);
509 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
510 trace("vport ext (%d,%d)\n", size.cx, size.cy);
512 else
514 ok(ret, "GetWorldTransform error %u\n", GetLastError());
515 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
518 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
520 switch (emr->iType)
522 case EMR_HEADER:
524 static RECT exp_bounds = { 0, 0, 150, 150 };
525 RECT bounds;
526 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
528 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
529 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
530 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
531 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
532 emf->szlDevice.cx, emf->szlDevice.cy);
534 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
535 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
537 save_state = 0;
538 restore_no = 0;
539 select_no = 0;
540 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
541 break;
544 case EMR_LINETO:
546 const EMRLINETO *line = (const EMRLINETO *)emr;
547 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
548 break;
550 case EMR_SETWINDOWORGEX:
552 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
553 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
554 break;
556 case EMR_SETWINDOWEXTEX:
558 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
559 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
560 break;
562 case EMR_SETVIEWPORTORGEX:
564 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
565 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
566 break;
568 case EMR_SETVIEWPORTEXTEX:
570 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
571 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
572 break;
574 case EMR_SAVEDC:
575 save_state++;
576 trace("EMR_SAVEDC\n");
577 break;
579 case EMR_RESTOREDC:
581 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
582 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
584 switch(++restore_no)
586 case 1:
587 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
588 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
589 break;
590 case 2:
591 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
592 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
593 break;
594 case 3:
595 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
596 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
597 break;
599 ok(restore_no <= 3, "restore_no %d\n", restore_no);
600 save_state += restoredc->iRelative;
601 break;
603 case EMR_SELECTOBJECT:
605 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
606 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
607 select_no ++;
608 break;
610 case EMR_EOF:
611 ok(save_state == 0, "EOF save_state %d\n", save_state);
612 ok(select_no == 3, "Too many/few selects %i\n",select_no);
613 break;
616 SetLastError(0xdeadbeef);
617 ret = GetWorldTransform(hdc, &xform);
618 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
620 ret = GetWindowOrgEx(hdc, &pt);
621 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
622 trace("window org (%d,%d)\n", pt.x, pt.y);
623 ret = GetViewportOrgEx(hdc, &pt);
624 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
625 trace("vport org (%d,%d)\n", pt.x, pt.y);
626 ret = GetWindowExtEx(hdc, &size);
627 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
628 trace("window ext (%d,%d)\n", size.cx, size.cy);
629 ret = GetViewportExtEx(hdc, &size);
630 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
631 trace("vport ext (%d,%d)\n", size.cx, size.cy);
633 else
635 ok(ret, "GetWorldTransform error %u\n", GetLastError());
636 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
639 return 1;
642 static void test_SaveDC(void)
644 HDC hdcMetafile, hdcDisplay;
645 HENHMETAFILE hMetafile;
646 HWND hwnd;
647 int ret;
648 POINT pt;
649 SIZE size;
650 HFONT hFont,hFont2,hFontOld,hFontCheck;
651 static const RECT rc = { 0, 0, 150, 150 };
653 /* Win9x doesn't play EMFs on invisible windows */
654 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
655 0, 0, 200, 200, 0, 0, 0, NULL);
656 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
658 hdcDisplay = GetDC(hwnd);
659 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
661 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
662 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
664 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
666 /* Need to write something to the emf, otherwise Windows won't play it back */
667 LineTo(hdcMetafile, 150, 150);
669 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
670 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
671 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
672 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
674 /* Force Win9x to update DC state */
675 SetPixelV(hdcMetafile, 50, 50, 0);
677 ret = GetViewportOrgEx(hdcMetafile, &pt);
678 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
679 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
680 ret = GetViewportExtEx(hdcMetafile, &size);
681 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
682 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
683 ret = SaveDC(hdcMetafile);
684 ok(ret == 1, "ret = %d\n", ret);
686 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
687 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
688 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
689 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
691 /* Force Win9x to update DC state */
692 SetPixelV(hdcMetafile, 50, 50, 0);
694 ret = GetViewportOrgEx(hdcMetafile, &pt);
695 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
696 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
697 ret = GetViewportExtEx(hdcMetafile, &size);
698 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
699 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
700 ret = SaveDC(hdcMetafile);
701 ok(ret == 2, "ret = %d\n", ret);
703 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
704 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
705 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
706 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
707 SetPolyFillMode( hdcMetafile, ALTERNATE );
708 SetBkColor( hdcMetafile, 0 );
710 /* Force Win9x to update DC state */
711 SetPixelV(hdcMetafile, 50, 50, 0);
713 ret = GetViewportOrgEx(hdcMetafile, &pt);
714 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
715 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
716 ret = GetViewportExtEx(hdcMetafile, &size);
717 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
718 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
719 ret = SaveDC(hdcMetafile);
720 ok(ret == 3, "ret = %d\n", ret);
722 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
723 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
724 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
725 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
727 SetPolyFillMode( hdcMetafile, WINDING );
728 SetBkColor( hdcMetafile, 0x123456 );
729 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
730 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
732 /* Force Win9x to update DC state */
733 SetPixelV(hdcMetafile, 50, 50, 0);
735 ret = GetViewportOrgEx(hdcMetafile, &pt);
736 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
737 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
738 ret = GetViewportExtEx(hdcMetafile, &size);
739 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
740 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
741 ret = RestoreDC(hdcMetafile, -1);
742 ok(ret, "ret = %d\n", ret);
744 ret = GetViewportOrgEx(hdcMetafile, &pt);
745 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
746 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
747 ret = GetViewportExtEx(hdcMetafile, &size);
748 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
749 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
750 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
751 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
752 ret = SaveDC(hdcMetafile);
753 ok(ret == 3, "ret = %d\n", ret);
755 ret = GetViewportOrgEx(hdcMetafile, &pt);
756 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
757 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
758 ret = GetViewportExtEx(hdcMetafile, &size);
759 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
760 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
761 ret = RestoreDC(hdcMetafile, 1);
762 ok(ret, "ret = %d\n", ret);
763 ret = GetViewportOrgEx(hdcMetafile, &pt);
764 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
765 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
766 ret = GetViewportExtEx(hdcMetafile, &size);
767 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
768 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
770 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
771 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
772 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
773 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
775 /* Force Win9x to update DC state */
776 SetPixelV(hdcMetafile, 50, 50, 0);
778 ret = GetViewportOrgEx(hdcMetafile, &pt);
779 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
780 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
781 ret = GetViewportExtEx(hdcMetafile, &size);
782 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
783 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
784 ret = SaveDC(hdcMetafile);
785 ok(ret == 1, "ret = %d\n", ret);
787 ret = GetViewportOrgEx(hdcMetafile, &pt);
788 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
789 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
790 ret = GetViewportExtEx(hdcMetafile, &size);
791 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
792 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
793 ret = SaveDC(hdcMetafile);
794 ok(ret == 2, "ret = %d\n", ret);
796 memset(&orig_lf, 0, sizeof(orig_lf));
797 orig_lf.lfCharSet = ANSI_CHARSET;
798 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
799 orig_lf.lfWeight = FW_DONTCARE;
800 orig_lf.lfHeight = 7;
801 orig_lf.lfQuality = DEFAULT_QUALITY;
802 lstrcpyA(orig_lf.lfFaceName, "Arial");
803 hFont = CreateFontIndirectA(&orig_lf);
804 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
806 hFontOld = SelectObject(hdcMetafile, hFont);
808 hFont2 = CreateFontIndirectA(&orig_lf);
809 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
810 hFontCheck = SelectObject(hdcMetafile, hFont2);
811 ok(hFontCheck == hFont, "Font not selected\n");
813 /* Force Win9x to update DC state */
814 SetPixelV(hdcMetafile, 50, 50, 0);
816 ret = RestoreDC(hdcMetafile, 1);
817 ok(ret, "ret = %d\n", ret);
818 ret = GetViewportOrgEx(hdcMetafile, &pt);
819 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
820 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
821 ret = GetViewportExtEx(hdcMetafile, &size);
822 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
823 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
825 hFontCheck = SelectObject(hdcMetafile, hFontOld);
826 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
827 "Font not reverted with DC Restore\n");
829 ret = RestoreDC(hdcMetafile, -20);
830 ok(!ret, "ret = %d\n", ret);
831 ret = RestoreDC(hdcMetafile, 20);
832 ok(!ret, "ret = %d\n", ret);
834 hMetafile = CloseEnhMetaFile(hdcMetafile);
835 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
837 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
838 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
840 ret = DeleteObject(hFont);
841 ok( ret, "DeleteObject error %d\n", GetLastError());
842 ret = DeleteObject(hFont2);
843 ok( ret, "DeleteObject error %d\n", GetLastError());
844 ret = DeleteEnhMetaFile(hMetafile);
845 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
846 ret = ReleaseDC(hwnd, hdcDisplay);
847 ok( ret, "ReleaseDC error %d\n", GetLastError());
848 DestroyWindow(hwnd);
851 static void test_mf_SaveDC(void)
853 HDC hdcMetafile;
854 HMETAFILE hMetafile;
855 int ret;
856 POINT pt;
857 SIZE size;
858 HFONT hFont,hFont2,hFontOld,hFontCheck;
860 hdcMetafile = CreateMetaFileA(NULL);
861 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
863 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
864 ok (ret, "SetMapMode should not fail\n");
866 /* Need to write something to the emf, otherwise Windows won't play it back */
867 LineTo(hdcMetafile, 150, 150);
869 pt.x = pt.y = 5555;
870 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
871 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
872 pt.x = pt.y = 5555;
873 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
874 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
875 size.cx = size.cy = 5555;
876 SetWindowExtEx(hdcMetafile, 110, 110, &size );
877 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
878 size.cx = size.cy = 5555;
879 SetViewportExtEx(hdcMetafile, 120, 120, &size );
880 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
882 /* Force Win9x to update DC state */
883 SetPixelV(hdcMetafile, 50, 50, 0);
885 ret = GetViewportOrgEx(hdcMetafile, &pt);
886 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
887 ret = GetViewportExtEx(hdcMetafile, &size);
888 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
889 ret = SaveDC(hdcMetafile);
890 ok(ret == 1, "ret = %d\n", ret);
892 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
893 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
894 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
895 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
897 /* Force Win9x to update DC state */
898 SetPixelV(hdcMetafile, 50, 50, 0);
900 ret = SaveDC(hdcMetafile);
901 ok(ret == 1, "ret = %d\n", ret);
903 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
904 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
905 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
906 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
908 /* Force Win9x to update DC state */
909 SetPixelV(hdcMetafile, 50, 50, 0);
910 SetPolyFillMode( hdcMetafile, ALTERNATE );
911 SetBkColor( hdcMetafile, 0 );
913 ret = SaveDC(hdcMetafile);
914 ok(ret == 1, "ret = %d\n", ret);
916 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
917 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
918 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
919 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
921 SetPolyFillMode( hdcMetafile, WINDING );
922 SetBkColor( hdcMetafile, 0x123456 );
923 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
924 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
926 /* Force Win9x to update DC state */
927 SetPixelV(hdcMetafile, 50, 50, 0);
929 ret = RestoreDC(hdcMetafile, -1);
930 ok(ret, "ret = %d\n", ret);
932 ret = SaveDC(hdcMetafile);
933 ok(ret == 1, "ret = %d\n", ret);
935 ret = RestoreDC(hdcMetafile, 1);
936 ok(ret, "ret = %d\n", ret);
938 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
939 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
940 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
941 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
943 /* Force Win9x to update DC state */
944 SetPixelV(hdcMetafile, 50, 50, 0);
946 ret = SaveDC(hdcMetafile);
947 ok(ret == 1, "ret = %d\n", ret);
949 ret = SaveDC(hdcMetafile);
950 ok(ret == 1, "ret = %d\n", ret);
952 memset(&orig_lf, 0, sizeof(orig_lf));
953 orig_lf.lfCharSet = ANSI_CHARSET;
954 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
955 orig_lf.lfWeight = FW_DONTCARE;
956 orig_lf.lfHeight = 7;
957 orig_lf.lfQuality = DEFAULT_QUALITY;
958 lstrcpyA(orig_lf.lfFaceName, "Arial");
959 hFont = CreateFontIndirectA(&orig_lf);
960 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
962 hFontOld = SelectObject(hdcMetafile, hFont);
964 hFont2 = CreateFontIndirectA(&orig_lf);
965 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
966 hFontCheck = SelectObject(hdcMetafile, hFont2);
967 ok(hFontCheck == hFont, "Font not selected\n");
969 /* Force Win9x to update DC state */
970 SetPixelV(hdcMetafile, 50, 50, 0);
972 ret = RestoreDC(hdcMetafile, 1);
973 ok(ret, "ret = %d\n", ret);
975 hFontCheck = SelectObject(hdcMetafile, hFontOld);
976 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
978 /* restore level is ignored */
979 ret = RestoreDC(hdcMetafile, -20);
980 ok(ret, "ret = %d\n", ret);
981 ret = RestoreDC(hdcMetafile, 20);
982 ok(ret, "ret = %d\n", ret);
983 ret = RestoreDC(hdcMetafile, 0);
984 ok(ret, "ret = %d\n", ret);
986 hMetafile = CloseMetaFile(hdcMetafile);
987 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
989 ret = DeleteMetaFile(hMetafile);
990 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
991 ret = DeleteObject(hFont);
992 ok( ret, "DeleteObject error %d\n", GetLastError());
993 ret = DeleteObject(hFont2);
994 ok( ret, "DeleteObject error %d\n", GetLastError());
998 /* Win-format metafile (mfdrv) tests */
999 /* These tests compare the generated metafiles byte-by-byte */
1000 /* with the nominal results. */
1002 /* Maximum size of sample metafiles in bytes. */
1003 #define MF_BUFSIZE 1024
1005 /* 8x8 bitmap data for a pattern brush */
1006 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
1007 0x01, 0x00, 0x02, 0x00,
1008 0x03, 0x00, 0x04, 0x00,
1009 0x05, 0x00, 0x06, 0x00,
1010 0x07, 0x00, 0x08, 0x00
1013 /* Sample metafiles to be compared to the outputs of the
1014 * test functions.
1017 static const unsigned char MF_BLANK_BITS[] = {
1018 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1019 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1020 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 static const unsigned char MF_GRAPHICS_BITS[] = {
1024 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1025 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1026 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1027 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1028 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1029 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1030 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1031 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1032 0x00, 0x00, 0x00, 0x00
1035 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1036 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1037 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1038 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1039 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1040 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1041 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1045 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1046 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1047 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1048 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1049 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1050 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1051 0x00, 0x00
1054 static const unsigned char MF_DCBRUSH_BITS[] =
1056 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1057 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1058 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1059 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1060 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1061 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1063 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1064 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1065 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1066 0x00, 0x00, 0x00, 0x00
1069 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1071 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1073 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1074 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1075 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1076 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1077 0x00, 0x00
1080 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1082 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1084 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1086 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1087 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1088 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1089 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1091 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1092 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1095 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1096 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1097 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1099 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1101 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1102 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1105 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1106 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1107 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1108 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1109 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1110 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1112 0x14, 0x00, 0x00, 0x00
1115 static const unsigned char MF_LINETO_BITS[] = {
1116 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1117 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1118 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1119 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1120 0x00, 0x00
1123 static const unsigned char EMF_LINETO_BITS[] = {
1124 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1128 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1129 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1130 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1131 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1133 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1134 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1137 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1138 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1139 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1140 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1141 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1142 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1143 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1144 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1145 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1147 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1148 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1149 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1150 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1151 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1152 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1153 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1154 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1155 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1156 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1157 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1158 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1159 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1161 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1165 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1166 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1168 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1170 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1171 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1172 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1173 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1175 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1176 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1179 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1180 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1181 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1182 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1183 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1184 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1185 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1186 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1187 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1189 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1190 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1191 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1192 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1194 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1195 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1196 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1197 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1198 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1199 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1200 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1201 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1203 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1207 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1208 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1213 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1214 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1215 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1217 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1218 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1220 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1221 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1222 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1223 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1224 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1225 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1226 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1227 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1228 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1229 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1231 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1232 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1234 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1236 0x14, 0x00, 0x00, 0x00
1239 static const unsigned char EMF_BITBLT[] =
1241 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1246 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1247 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1248 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1251 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1254 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1255 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1257 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1259 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1266 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1267 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1268 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1269 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1283 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1291 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1293 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1295 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1297 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1300 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1301 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1302 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1303 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1304 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1305 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1315 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1316 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1317 0x14, 0x00, 0x00, 0x00
1320 static const unsigned char EMF_DCBRUSH_BITS[] =
1322 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1323 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1324 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1325 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1326 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1327 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1328 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1329 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1331 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1332 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1335 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1336 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1337 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1338 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1339 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1342 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1343 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1344 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1346 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1347 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1348 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1349 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1350 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1351 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1352 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1353 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1354 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1356 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1357 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1358 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1359 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1360 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1361 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1362 0x14, 0x00, 0x00, 0x00
1365 static const unsigned char EMF_BEZIER_BITS[] =
1367 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1369 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1372 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1373 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1374 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1376 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1377 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1380 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1381 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1383 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1384 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1385 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1386 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1387 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1388 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1389 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1390 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1391 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1392 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1393 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1394 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1395 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1396 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1397 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1398 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1399 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1400 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1401 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1402 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1403 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1404 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1405 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1407 0x14, 0x00, 0x00, 0x00
1410 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1412 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1413 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1414 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1415 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1416 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1417 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1418 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1419 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1421 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1422 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1424 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1425 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1426 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1427 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1428 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1429 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1430 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1432 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1433 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1435 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1437 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1438 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1439 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1440 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1441 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1443 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1444 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1445 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1446 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1447 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1448 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1449 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1450 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1451 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1452 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1453 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1454 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1455 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1456 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1457 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1458 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1459 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1460 0x14, 0x00, 0x00, 0x00
1463 static const unsigned char EMF_GRADIENTFILL_BITS[] =
1465 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1466 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1467 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1468 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1469 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1470 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1471 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1472 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1474 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1475 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1477 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1478 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1479 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1480 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1481 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1482 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1483 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1484 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1485 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1487 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1488 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1489 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1490 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1491 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1492 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1493 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1494 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1495 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1496 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1497 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1498 0x14, 0x00, 0x00, 0x00
1501 /* For debugging or dumping the raw metafiles produced by
1502 * new test functions.
1504 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1505 INT nobj, LPARAM param)
1507 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1508 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1509 return TRUE;
1512 /* For debugging or dumping the raw metafiles produced by
1513 * new test functions.
1516 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1518 BYTE buf[MF_BUFSIZE];
1519 UINT mfsize, i;
1521 if (!winetest_debug) return;
1523 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1524 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1526 printf ("MetaFile %s has bits:\n{\n ", desc);
1527 for (i=0; i<mfsize; i++)
1529 printf ("0x%02x", buf[i]);
1530 if (i == mfsize-1)
1531 printf ("\n");
1532 else if (i % 8 == 7)
1533 printf (",\n ");
1534 else
1535 printf (", ");
1537 printf ("};\n");
1540 /* Compare the metafile produced by a test function with the
1541 * expected raw metafile data in "bits".
1542 * Return value is 0 for a perfect match,
1543 * -1 if lengths aren't equal,
1544 * otherwise returns the number of non-matching bytes.
1547 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1548 const char *desc)
1550 unsigned char buf[MF_BUFSIZE];
1551 UINT mfsize, i;
1552 int diff;
1554 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1555 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1556 if (mfsize < MF_BUFSIZE)
1557 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1558 desc, mfsize, bsize);
1559 else
1560 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1561 desc, mfsize, bsize);
1562 if (mfsize != bsize)
1563 return -1;
1565 diff = 0;
1566 for (i=0; i<bsize; i++)
1568 if (buf[i] != bits[i])
1569 diff++;
1571 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1572 desc, mfsize, bsize, diff);
1574 return diff;
1577 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1579 unsigned char buf[MF_BUFSIZE];
1580 DWORD mfsize, rd_size, i;
1581 int diff;
1582 HANDLE hfile;
1583 BOOL ret;
1585 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1586 assert(hfile != INVALID_HANDLE_VALUE);
1588 mfsize = GetFileSize(hfile, NULL);
1589 assert(mfsize <= MF_BUFSIZE);
1591 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1592 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1594 CloseHandle(hfile);
1596 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1598 if (mfsize != bsize)
1599 return -1;
1601 diff = 0;
1602 for (i=0; i<bsize; i++)
1604 if (buf[i] != bits[i])
1605 diff++;
1607 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1608 desc, mfsize, bsize, diff);
1610 return diff;
1613 /* For debugging or dumping the raw EMFs produced by
1614 * new test functions.
1616 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1618 BYTE buf[MF_BUFSIZE];
1619 UINT mfsize, i;
1621 if (!winetest_debug) return;
1623 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1624 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1626 printf("EMF %s has bits:\n{\n ", desc);
1627 for (i = 0; i < mfsize; i++)
1629 printf ("0x%02x", buf[i]);
1630 if (i == mfsize-1)
1631 printf ("\n");
1632 else if (i % 8 == 7)
1633 printf (",\n ");
1634 else
1635 printf (", ");
1637 printf ("};\n");
1640 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1642 BYTE *emf;
1643 BYTE buf[MF_BUFSIZE];
1644 UINT mfsize, offset;
1646 if (!winetest_debug) return;
1648 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1649 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1651 printf("EMF %s has records:\n", desc);
1653 emf = buf;
1654 offset = 0;
1655 while(offset < mfsize)
1657 EMR *emr = (EMR *)(emf + offset);
1658 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1659 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1660 offset += emr->nSize;
1664 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1666 const BYTE *buf;
1667 DWORD i;
1669 if (!winetest_debug) return;
1671 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1672 buf = (const BYTE *)emr;
1673 for (i = 0; i < emr->nSize; i++)
1675 printf ("0x%02x", buf[i]);
1676 if (i == emr->nSize - 1)
1677 printf ("\n");
1678 else if (i % 8 == 7)
1679 printf (",\n");
1680 else
1681 printf (", ");
1683 printf ("};\n");
1686 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1688 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1689 eto->rclBounds.right, eto->rclBounds.bottom);
1690 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1691 trace("exScale: %f\n", eto->exScale);
1692 trace("eyScale: %f\n", eto->eyScale);
1693 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1694 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1695 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1696 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1697 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1698 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1699 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1702 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1703 const char *desc, BOOL ignore_scaling)
1705 int diff;
1707 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1708 desc, emr1->iType, emr2->iType);
1710 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1711 desc, emr1->nSize, emr2->nSize);
1713 /* iType and nSize mismatches are fatal */
1714 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1716 /* contents of EMR_GDICOMMENT are not interesting */
1717 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1719 /* different Windows versions setup DC scaling differently when
1720 * converting an old style metafile to an EMF.
1722 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1723 emr1->iType == EMR_SETVIEWPORTEXTEX))
1724 return TRUE;
1726 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1728 EMREXTTEXTOUTW *eto1, *eto2;
1730 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1731 memcpy(eto1, emr1, emr1->nSize);
1732 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1733 memcpy(eto2, emr2, emr2->nSize);
1735 /* different Windows versions setup DC scaling differently */
1736 eto1->exScale = eto1->eyScale = 0.0;
1737 eto2->exScale = eto2->eyScale = 0.0;
1739 diff = memcmp(eto1, eto2, emr1->nSize);
1740 if (diff)
1742 dump_EMREXTTEXTOUT(eto1);
1743 dump_EMREXTTEXTOUT(eto2);
1745 HeapFree(GetProcessHeap(), 0, eto1);
1746 HeapFree(GetProcessHeap(), 0, eto2);
1748 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1750 /* We have to take care of NT4 differences here */
1751 diff = memcmp(emr1, emr2, emr1->nSize);
1752 if (diff)
1754 ENHMETARECORD *emr_nt4;
1756 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1757 memcpy(emr_nt4, emr2, emr2->nSize);
1758 /* Correct the nRgnSize field */
1759 emr_nt4->dParm[5] = sizeof(RECT);
1761 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1762 if (!diff)
1763 win_skip("Catered for NT4 differences\n");
1765 HeapFree(GetProcessHeap(), 0, emr_nt4);
1768 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1770 EMRPOLYBEZIER16 *eto1, *eto2;
1772 eto1 = (EMRPOLYBEZIER16*)emr1;
1773 eto2 = (EMRPOLYBEZIER16*)emr2;
1775 diff = eto1->cpts != eto2->cpts;
1776 if(!diff)
1777 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1779 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1781 EMRPOLYBEZIER *eto1, *eto2;
1783 eto1 = (EMRPOLYBEZIER*)emr1;
1784 eto2 = (EMRPOLYBEZIER*)emr2;
1786 diff = eto1->cptl != eto2->cptl;
1787 if(!diff)
1788 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1790 else
1791 diff = memcmp(emr1, emr2, emr1->nSize);
1793 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1795 if (diff)
1797 dump_emf_record(emr1, "expected bits");
1798 dump_emf_record(emr2, "actual bits");
1801 return diff == 0; /* report all non-fatal record mismatches */
1804 /* Compare the EMF produced by a test function with the
1805 * expected raw EMF data in "bits".
1806 * Return value is 0 for a perfect match,
1807 * -1 if lengths aren't equal,
1808 * otherwise returns the number of non-matching bytes.
1810 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1811 UINT bsize, const char *desc,
1812 BOOL ignore_scaling)
1814 unsigned char buf[MF_BUFSIZE];
1815 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1816 const ENHMETAHEADER *emh1, *emh2;
1818 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1819 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1821 /* ENHMETAHEADER size could differ, depending on platform */
1822 diff_nt4 = sizeof(SIZEL);
1823 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1825 if (mfsize < MF_BUFSIZE)
1827 ok(mfsize == bsize ||
1828 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1829 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1830 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1832 else
1833 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1834 desc, mfsize, bsize);
1836 /* basic things must match */
1837 emh1 = (const ENHMETAHEADER *)bits;
1838 emh2 = (const ENHMETAHEADER *)buf;
1839 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1840 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1841 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1842 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1844 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1845 ok(emh1->nSize == emh2->nSize ||
1846 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1847 broken(emh1->nSize - diff_9x == emh2->nSize),
1848 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1849 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1850 ok(emh1->nBytes == emh2->nBytes ||
1851 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1852 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1853 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1854 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1856 offset1 = emh1->nSize;
1857 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1858 while (offset1 < emh1->nBytes)
1860 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1861 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1863 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1864 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1866 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1868 /* We have already bailed out if iType or nSize don't match */
1869 offset1 += emr1->nSize;
1870 offset2 += emr2->nSize;
1872 return 0;
1876 /* tests blitting to an EMF */
1877 static void test_emf_BitBlt(void)
1879 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1880 HBITMAP hBitmap, hOldBitmap;
1881 HENHMETAFILE hMetafile;
1882 #define BMP_DIM 4
1883 BITMAPINFOHEADER bmih =
1885 sizeof(BITMAPINFOHEADER),
1886 BMP_DIM,/* biWidth */
1887 BMP_DIM,/* biHeight */
1888 1, /* biPlanes */
1889 24, /* biBitCount */
1890 BI_RGB, /* biCompression */
1891 0, /* biXPelsPerMeter */
1892 0, /* biYPelsPerMeter */
1893 0, /* biClrUsed */
1894 0, /* biClrImportant */
1896 void *bits;
1897 XFORM xform;
1898 BOOL ret;
1900 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1901 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1903 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1904 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1905 ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
1906 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1907 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1908 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1909 DIB_RGB_COLORS, &bits, NULL, 0);
1910 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1912 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1913 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1915 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1916 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1917 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1919 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1920 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1921 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1922 ok( ret, "BitBlt(WHITENESS) failed\n" );
1924 ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
1925 ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
1926 ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
1927 ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
1928 ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
1929 memset(&xform, 0, sizeof(xform));
1930 xform.eM11 = 0.5;
1931 xform.eM22 = 1.0;
1932 ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
1934 ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
1935 ok( ret, "StretchBlt(SRCCOPY) failed\n" );
1937 hMetafile = CloseEnhMetaFile(hdcMetafile);
1938 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1940 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1941 "emf_BitBlt", FALSE) != 0)
1943 dump_emf_bits(hMetafile, "emf_BitBlt");
1944 dump_emf_records(hMetafile, "emf_BitBlt");
1947 SelectObject(hdcBitmap, hOldBitmap);
1948 DeleteObject(hBitmap);
1949 DeleteDC(hdcBitmap);
1950 DeleteDC(hdcDisplay);
1951 #undef BMP_DIM
1954 static void test_emf_DCBrush(void)
1956 HDC hdcMetafile;
1957 HENHMETAFILE hMetafile;
1958 HBRUSH hBrush;
1959 HPEN hPen;
1960 BOOL ret;
1961 COLORREF color;
1963 if (!pSetDCBrushColor || !pSetDCPenColor)
1965 win_skip( "SetDCBrush/PenColor not supported\n" );
1966 return;
1969 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1970 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1972 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1973 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1975 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1976 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1978 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1979 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1981 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1982 ok( color == 0, "SetDCPenColor returned %x\n", color );
1984 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1986 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1987 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1989 hMetafile = CloseEnhMetaFile(hdcMetafile);
1990 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1992 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1993 "emf_DC_Brush", FALSE ) != 0)
1995 dump_emf_bits(hMetafile, "emf_DC_Brush");
1996 dump_emf_records(hMetafile, "emf_DC_Brush");
1998 ret = DeleteEnhMetaFile(hMetafile);
1999 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2000 ret = DeleteObject(hBrush);
2001 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2002 ret = DeleteObject(hPen);
2003 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
2006 /* Test a blank metafile. May be used as a template for new tests. */
2008 static void test_mf_Blank(void)
2010 HDC hdcMetafile;
2011 HMETAFILE hMetafile;
2012 INT caps;
2013 BOOL ret;
2014 INT type;
2016 hdcMetafile = CreateMetaFileA(NULL);
2017 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2018 trace("hdcMetafile %p\n", hdcMetafile);
2020 /* Tests on metafile initialization */
2021 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
2022 ok (caps == DT_METAFILE,
2023 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
2025 hMetafile = CloseMetaFile(hdcMetafile);
2026 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2027 type = GetObjectType(hMetafile);
2028 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2029 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2031 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2032 "mf_blank") != 0)
2034 dump_mf_bits(hMetafile, "mf_Blank");
2035 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2038 ret = DeleteMetaFile(hMetafile);
2039 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2042 static void test_CopyMetaFile(void)
2044 HDC hdcMetafile;
2045 HMETAFILE hMetafile, hmf_copy;
2046 BOOL ret;
2047 char temp_path[MAX_PATH];
2048 char mf_name[MAX_PATH];
2049 INT type;
2051 hdcMetafile = CreateMetaFileA(NULL);
2052 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2053 trace("hdcMetafile %p\n", hdcMetafile);
2055 hMetafile = CloseMetaFile(hdcMetafile);
2056 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2057 type = GetObjectType(hMetafile);
2058 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2060 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2061 "mf_blank") != 0)
2063 dump_mf_bits(hMetafile, "mf_Blank");
2064 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2067 GetTempPathA(MAX_PATH, temp_path);
2068 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
2070 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
2071 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
2073 type = GetObjectType(hmf_copy);
2074 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
2076 ret = DeleteMetaFile(hMetafile);
2077 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2079 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
2081 dump_mf_bits(hmf_copy, "mf_Blank");
2082 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
2085 ret = DeleteMetaFile(hmf_copy);
2086 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
2088 DeleteFileA(mf_name);
2091 static void test_SetMetaFileBits(void)
2093 HMETAFILE hmf;
2094 INT type;
2095 BOOL ret;
2096 BYTE buf[256];
2097 METAHEADER *mh;
2099 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2100 trace("hmf %p\n", hmf);
2101 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2102 type = GetObjectType(hmf);
2103 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
2105 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2107 dump_mf_bits(hmf, "mf_Graphics");
2108 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2111 ret = DeleteMetaFile(hmf);
2112 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2114 /* NULL data crashes XP SP1 */
2115 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2117 /* Now with zero size */
2118 SetLastError(0xdeadbeef);
2119 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2120 trace("hmf %p\n", hmf);
2121 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2122 ok(GetLastError() == ERROR_INVALID_DATA ||
2123 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2124 "wrong error %d\n", GetLastError());
2126 /* Now with odd size */
2127 SetLastError(0xdeadbeef);
2128 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2129 trace("hmf %p\n", hmf);
2130 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2131 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2133 /* Now with zeroed out header fields */
2134 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2135 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2136 mh = (METAHEADER *)buf;
2137 /* corruption of any of the below fields leads to a failure */
2138 mh->mtType = 0;
2139 mh->mtVersion = 0;
2140 mh->mtHeaderSize = 0;
2141 SetLastError(0xdeadbeef);
2142 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2143 trace("hmf %p\n", hmf);
2144 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2145 ok(GetLastError() == ERROR_INVALID_DATA ||
2146 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2147 "wrong error %d\n", GetLastError());
2149 /* Now with corrupted mtSize field */
2150 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2151 mh = (METAHEADER *)buf;
2152 /* corruption of mtSize doesn't lead to a failure */
2153 mh->mtSize *= 2;
2154 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2155 trace("hmf %p\n", hmf);
2156 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2158 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2160 dump_mf_bits(hmf, "mf_Graphics");
2161 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2164 ret = DeleteMetaFile(hmf);
2165 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2167 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2168 /* Now with zeroed out mtSize field */
2169 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2170 mh = (METAHEADER *)buf;
2171 /* zeroing mtSize doesn't lead to a failure */
2172 mh->mtSize = 0;
2173 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2174 trace("hmf %p\n", hmf);
2175 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2177 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2179 dump_mf_bits(hmf, "mf_Graphics");
2180 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2183 ret = DeleteMetaFile(hmf);
2184 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2185 #endif
2188 /* Simple APIs from mfdrv/graphics.c
2191 static void test_mf_Graphics(void)
2193 HDC hdcMetafile;
2194 HMETAFILE hMetafile;
2195 POINT oldpoint;
2196 BOOL ret;
2198 hdcMetafile = CreateMetaFileA(NULL);
2199 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2200 trace("hdcMetafile %p\n", hdcMetafile);
2202 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2203 ok( ret, "MoveToEx error %d.\n", GetLastError());
2204 ret = LineTo(hdcMetafile, 2, 2);
2205 ok( ret, "LineTo error %d.\n", GetLastError());
2206 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2207 ok( ret, "MoveToEx error %d.\n", GetLastError());
2209 /* oldpoint gets garbage under Win XP, so the following test would
2210 * work under Wine but fails under Windows:
2212 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2213 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2214 * oldpoint.x, oldpoint.y);
2217 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2218 ok( ret, "Ellipse error %d.\n", GetLastError());
2220 hMetafile = CloseMetaFile(hdcMetafile);
2221 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2222 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2224 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2225 "mf_Graphics") != 0)
2227 dump_mf_bits(hMetafile, "mf_Graphics");
2228 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2231 ret = DeleteMetaFile(hMetafile);
2232 ok( ret, "DeleteMetaFile(%p) error %d\n",
2233 hMetafile, GetLastError());
2236 static void test_mf_PatternBrush(void)
2238 HDC hdcMetafile;
2239 HMETAFILE hMetafile;
2240 LOGBRUSH *orig_lb;
2241 HBRUSH hBrush;
2242 BOOL ret;
2244 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2246 orig_lb->lbStyle = BS_PATTERN;
2247 orig_lb->lbColor = RGB(0, 0, 0);
2248 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2249 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2251 hBrush = CreateBrushIndirect (orig_lb);
2252 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2254 hdcMetafile = CreateMetaFileA(NULL);
2255 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2256 trace("hdcMetafile %p\n", hdcMetafile);
2258 hBrush = SelectObject(hdcMetafile, hBrush);
2259 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2261 hMetafile = CloseMetaFile(hdcMetafile);
2262 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2263 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2265 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2266 "mf_Pattern_Brush") != 0)
2268 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2269 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2272 ret = DeleteMetaFile(hMetafile);
2273 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2274 ret = DeleteObject(hBrush);
2275 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2276 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2277 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2278 GetLastError());
2279 HeapFree (GetProcessHeap(), 0, orig_lb);
2282 static void test_mf_DCBrush(void)
2284 HDC hdcMetafile;
2285 HMETAFILE hMetafile;
2286 HBRUSH hBrush;
2287 HPEN hPen;
2288 BOOL ret;
2289 COLORREF color;
2291 if (!pSetDCBrushColor || !pSetDCPenColor)
2293 win_skip( "SetDCBrush/PenColor not supported\n" );
2294 return;
2297 hdcMetafile = CreateMetaFileA(NULL);
2298 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2300 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2301 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2303 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2304 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2306 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2307 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2309 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2310 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2312 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2314 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2315 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2317 hMetafile = CloseMetaFile(hdcMetafile);
2318 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2320 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2322 dump_mf_bits(hMetafile, "mf_DCBrush");
2323 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2325 ret = DeleteMetaFile(hMetafile);
2326 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2329 static void test_mf_ExtTextOut_on_path(void)
2331 HDC hdcMetafile;
2332 HMETAFILE hMetafile;
2333 BOOL ret;
2334 static const INT dx[4] = { 3, 5, 8, 12 };
2336 hdcMetafile = CreateMetaFileA(NULL);
2337 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2338 trace("hdcMetafile %p\n", hdcMetafile);
2340 ret = BeginPath(hdcMetafile);
2341 ok(!ret, "BeginPath on metafile DC should fail\n");
2343 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2344 ok(ret, "ExtTextOut error %d\n", GetLastError());
2346 ret = EndPath(hdcMetafile);
2347 ok(!ret, "EndPath on metafile DC should fail\n");
2349 hMetafile = CloseMetaFile(hdcMetafile);
2350 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2352 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2353 "mf_TextOut_on_path") != 0)
2355 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2356 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2359 ret = DeleteMetaFile(hMetafile);
2360 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2363 static void test_emf_ExtTextOut_on_path(void)
2365 HWND hwnd;
2366 HDC hdcDisplay, hdcMetafile;
2367 HENHMETAFILE hMetafile;
2368 BOOL ret;
2369 static const INT dx[4] = { 3, 5, 8, 12 };
2371 /* Win9x doesn't play EMFs on invisible windows */
2372 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2373 0, 0, 200, 200, 0, 0, 0, NULL);
2374 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2376 hdcDisplay = GetDC(hwnd);
2377 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2379 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2380 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2382 ret = BeginPath(hdcMetafile);
2383 ok(ret, "BeginPath error %d\n", GetLastError());
2385 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2386 ok(ret, "ExtTextOut error %d\n", GetLastError());
2388 ret = EndPath(hdcMetafile);
2389 ok(ret, "EndPath error %d\n", GetLastError());
2391 hMetafile = CloseEnhMetaFile(hdcMetafile);
2392 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2394 /* this doesn't succeed yet: EMF has correct size, all EMF records
2395 * are there, but their contents don't match for different reasons.
2397 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2398 "emf_TextOut_on_path", FALSE) != 0)
2400 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2401 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2404 ret = DeleteEnhMetaFile(hMetafile);
2405 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2406 ret = ReleaseDC(hwnd, hdcDisplay);
2407 ok(ret, "ReleaseDC error %d\n", GetLastError());
2408 DestroyWindow(hwnd);
2411 static const unsigned char EMF_CLIPPING[] =
2413 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2415 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2417 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2418 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2419 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2420 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2422 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2423 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2425 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2426 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2427 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2428 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2429 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2430 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2431 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2432 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2433 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2434 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2435 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2436 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2437 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2438 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2441 static void translate( POINT *pt, UINT count, const XFORM *xform )
2443 while (count--)
2445 FLOAT x = (FLOAT)pt->x;
2446 FLOAT y = (FLOAT)pt->y;
2447 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2448 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2449 pt++;
2453 /* Compare rectangles allowing rounding errors */
2454 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2456 return abs(rc1->left - rc2->left) <= 1 &&
2457 abs(rc1->top - rc2->top) <= 1 &&
2458 abs(rc1->right - rc2->right) <= 1 &&
2459 abs(rc1->bottom - rc2->bottom) <= 1;
2462 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2463 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2465 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2467 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2468 union _rgn
2470 RGNDATA data;
2471 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2473 const union _rgn *rgn1;
2474 union _rgn rgn2;
2475 RECT rect, rc_transformed;
2476 const RECT *rc = (const RECT *)param;
2477 HRGN hrgn;
2478 XFORM xform;
2479 INT ret;
2480 BOOL is_win9x;
2482 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2483 clip->cbRgnData, clip->iMode);
2485 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2486 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2487 "too small data block: %u bytes\n", clip->cbRgnData);
2488 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2489 return 0;
2491 rgn1 = (const union _rgn *)clip->RgnData;
2493 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2494 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2495 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2496 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2497 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2499 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2501 rect = *(const RECT *)rgn1->data.Buffer;
2502 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2503 ok(EqualRect(&rect, rc), "rects don't match\n");
2505 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2506 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2507 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2508 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2509 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2510 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2512 hrgn = CreateRectRgn(0, 0, 0, 0);
2514 memset(&xform, 0, sizeof(xform));
2515 SetLastError(0xdeadbeef);
2516 ret = GetWorldTransform(hdc, &xform);
2517 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2518 if (!is_win9x)
2519 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2521 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2523 ret = GetClipRgn(hdc, hrgn);
2524 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2526 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2528 ret = GetClipRgn(hdc, hrgn);
2529 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2531 /* Win9x returns empty clipping region */
2532 if (is_win9x) return 1;
2534 ret = GetRegionData(hrgn, 0, NULL);
2535 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2537 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2538 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2540 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2541 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2542 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2543 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2544 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2546 rect = rgn2.data.rdh.rcBound;
2547 rc_transformed = *rc;
2548 translate((POINT *)&rc_transformed, 2, &xform);
2549 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2550 rc_transformed.right, rc_transformed.bottom);
2551 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2553 rect = *(const RECT *)rgn2.data.Buffer;
2554 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2555 rc_transformed = *rc;
2556 translate((POINT *)&rc_transformed, 2, &xform);
2557 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2558 rc_transformed.right, rc_transformed.bottom);
2559 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2561 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2562 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2563 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2564 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2565 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2566 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2568 DeleteObject(hrgn);
2570 return 1;
2573 static void test_emf_clipping(void)
2575 static const RECT rc = { 0, 0, 100, 100 };
2576 RECT rc_clip = { 100, 100, 1024, 1024 };
2577 HWND hwnd;
2578 HDC hdc;
2579 HENHMETAFILE hemf;
2580 HRGN hrgn;
2581 INT ret;
2582 RECT rc_res, rc_sclip;
2584 SetLastError(0xdeadbeef);
2585 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2586 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2588 /* Need to write something to the emf, otherwise Windows won't play it back */
2589 LineTo(hdc, 1, 1);
2591 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2592 ret = SelectClipRgn(hdc, hrgn);
2593 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2595 SetLastError(0xdeadbeef);
2596 hemf = CloseEnhMetaFile(hdc);
2597 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2599 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2600 "emf_clipping", FALSE) != 0)
2602 dump_emf_bits(hemf, "emf_clipping");
2603 dump_emf_records(hemf, "emf_clipping");
2606 DeleteObject(hrgn);
2608 /* Win9x doesn't play EMFs on invisible windows */
2609 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2610 0, 0, 200, 200, 0, 0, 0, NULL);
2611 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2613 hdc = GetDC(hwnd);
2615 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2616 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2618 DeleteEnhMetaFile(hemf);
2619 ReleaseDC(hwnd, hdc);
2620 DestroyWindow(hwnd);
2622 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2624 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2625 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2626 SelectClipRgn(hdc, hrgn);
2627 SetRect(&rc_res, -1, -1, -1, -1);
2628 ret = GetClipBox(hdc, &rc_res);
2629 ok(ret == SIMPLEREGION, "got %d\n", ret);
2630 ok(EqualRect(&rc_res, &rc_sclip),
2631 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2632 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2633 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2635 OffsetRect(&rc_sclip, -100, -100);
2636 ret = OffsetClipRgn(hdc, -100, -100);
2637 ok(ret == SIMPLEREGION, "got %d\n", ret);
2638 SetRect(&rc_res, -1, -1, -1, -1);
2639 ret = GetClipBox(hdc, &rc_res);
2640 ok(ret == SIMPLEREGION, "got %d\n", ret);
2641 ok(EqualRect(&rc_res, &rc_sclip),
2642 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2643 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2644 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2646 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2647 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2648 if (ret == COMPLEXREGION)
2650 /* XP returns COMPLEXREGION although region contains only 1 rect */
2651 ret = GetClipRgn(hdc, hrgn);
2652 ok(ret == 1, "expected 1, got %d\n", ret);
2653 ret = rgn_rect_count(hrgn);
2654 ok(ret == 1, "expected 1, 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),
2660 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2661 rc.left, rc.top, rc.right, rc.bottom,
2662 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2664 SetRect(&rc_sclip, 0, 0, 100, 50);
2665 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2666 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2667 if (ret == COMPLEXREGION)
2669 /* XP returns COMPLEXREGION although region contains only 1 rect */
2670 ret = GetClipRgn(hdc, hrgn);
2671 ok(ret == 1, "expected 1, got %d\n", ret);
2672 ret = rgn_rect_count(hrgn);
2673 ok(ret == 1, "expected 1, got %d\n", ret);
2675 SetRect(&rc_res, -1, -1, -1, -1);
2676 ret = GetClipBox(hdc, &rc_res);
2677 ok(ret == SIMPLEREGION, "got %d\n", ret);
2678 ok(EqualRect(&rc_res, &rc_sclip),
2679 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2680 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2681 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2683 hemf = CloseEnhMetaFile(hdc);
2684 DeleteEnhMetaFile(hemf);
2685 DeleteObject(hrgn);
2688 static const unsigned char MF_CLIP_BITS[] = {
2689 /* METAHEADER */
2690 0x01, 0x00, /* mtType */
2691 0x09, 0x00, /* mtHeaderSize */
2692 0x00, 0x03, /* mtVersion */
2693 0x32, 0x00, 0x00, 0x00, /* mtSize */
2694 0x01, 0x00, /* mtNoObjects */
2695 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2696 0x00, 0x00, /* reserved */
2698 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2699 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2700 0xff, 0x06, /* META_CREATEREGION */
2701 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2702 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2703 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2704 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2705 0x02, 0x00,
2707 /* METARECORD for SelectObject */
2708 0x04, 0x00, 0x00, 0x00,
2709 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2710 0x00, 0x00,
2712 /* METARECORD */
2713 0x04, 0x00, 0x00, 0x00,
2714 0xf0, 0x01, /* META_DELETEOBJECT */
2715 0x00, 0x00,
2717 /* METARECORD for MoveTo(1,0x30) */
2718 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2719 0x14, 0x02, /* META_MOVETO */
2720 0x30, 0x00, /* y */
2721 0x01, 0x00, /* x */
2723 /* METARECORD for LineTo(0x20, 0x30) */
2724 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2725 0x13, 0x02, /* META_LINETO */
2726 0x30, 0x00, /* y */
2727 0x20, 0x00, /* x */
2729 /* EOF */
2730 0x03, 0x00, 0x00, 0x00,
2731 0x00, 0x00
2734 static int clip_mf_enum_proc_seen_selectclipregion;
2735 static int clip_mf_enum_proc_seen_selectobject;
2737 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2738 METARECORD *mr, int n_objs, LPARAM param)
2740 switch (mr->rdFunction) {
2741 case META_SELECTCLIPREGION:
2742 clip_mf_enum_proc_seen_selectclipregion++;
2743 break;
2744 case META_SELECTOBJECT:
2745 clip_mf_enum_proc_seen_selectobject++;
2746 break;
2748 return 1;
2751 static void test_mf_clipping(void)
2753 /* left top right bottom */
2754 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2755 HWND hwnd;
2756 HDC hdc;
2757 HMETAFILE hmf;
2758 HRGN hrgn;
2759 INT ret;
2761 SetLastError(0xdeadbeef);
2762 hdc = CreateMetaFileA(NULL);
2763 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2765 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2766 ret = SelectClipRgn(hdc, hrgn);
2767 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2768 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2770 /* Draw a line that starts off left of the clip region and ends inside it */
2771 MoveToEx(hdc, 0x1, 0x30, NULL);
2772 LineTo(hdc, 0x20, 0x30);
2774 SetLastError(0xdeadbeef);
2775 hmf = CloseMetaFile(hdc);
2776 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2778 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2779 "mf_clipping") != 0)
2781 dump_mf_bits(hmf, "mf_clipping");
2784 DeleteObject(hrgn);
2786 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2787 0, 0, 200, 200, 0, 0, 0, NULL);
2788 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2790 hdc = GetDC(hwnd);
2792 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2793 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2795 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2796 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2797 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2798 ok(clip_mf_enum_proc_seen_selectobject == 1,
2799 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2801 DeleteMetaFile(hmf);
2802 ReleaseDC(hwnd, hdc);
2803 DestroyWindow(hwnd);
2806 static const unsigned char MF_PATH_BITS[] =
2808 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2809 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2810 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2811 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2812 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2813 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2814 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2815 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2816 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2817 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2818 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2821 static void test_mf_GetPath(void)
2823 HDC hdc;
2824 HMETAFILE hmf;
2825 BOOL ret;
2826 int size;
2828 SetLastError(0xdeadbeef);
2829 hdc = CreateMetaFileA(NULL);
2830 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2832 BeginPath(hdc);
2833 ret = MoveToEx(hdc, 50, 50, NULL);
2834 ok( ret, "MoveToEx error %d.\n", GetLastError());
2835 ret = LineTo(hdc, 50, 150);
2836 ok( ret, "LineTo error %d.\n", GetLastError());
2837 ret = LineTo(hdc, 150, 150);
2838 ok( ret, "LineTo error %d.\n", GetLastError());
2839 ret = LineTo(hdc, 150, 50);
2840 ok( ret, "LineTo error %d.\n", GetLastError());
2841 ret = LineTo(hdc, 50, 50);
2842 ok( ret, "LineTo error %d.\n", GetLastError());
2843 Rectangle(hdc, 10, 10, 20, 20);
2844 EndPath(hdc);
2846 size = GetPath(hdc, NULL, NULL, 0);
2847 ok( size == -1, "GetPath returned %d.\n", size);
2849 hmf = CloseMetaFile(hdc);
2850 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2852 if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
2854 dump_mf_bits(hmf, "mf_GetPath");
2855 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2858 ret = DeleteMetaFile(hmf);
2859 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2862 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2864 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2865 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2866 /* When using MM_TEXT Win9x does not update the mapping mode
2867 * until a record is played which actually outputs something */
2868 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2869 LPtoDP(hdc, mapping, 2);
2870 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2871 lpEMFR->iType, lpEMFR->nSize,
2872 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2874 if (lpEMFR->iType == EMR_LINETO)
2876 INT x0, y0, x1, y1;
2877 if (!lpMFP || lpMFP->mm == MM_TEXT)
2879 x0 = 0;
2880 y0 = 0;
2881 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2882 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2884 else
2886 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2888 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2889 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2890 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2891 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2893 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2894 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2895 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2896 x0, y0, x1, y1);
2898 return TRUE;
2901 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2903 HDC hdcMf;
2904 HMETAFILE hmf;
2905 HENHMETAFILE hemf;
2906 BOOL ret;
2907 UINT size;
2908 LPBYTE pBits;
2910 hdcMf = CreateMetaFileA(NULL);
2911 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2912 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2913 ok(ret, "LineTo failed with error %d\n", GetLastError());
2914 hmf = CloseMetaFile(hdcMf);
2915 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2917 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2919 dump_mf_bits(hmf, "mf_LineTo");
2920 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2923 size = GetMetaFileBitsEx(hmf, 0, NULL);
2924 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2925 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2926 GetMetaFileBitsEx(hmf, size, pBits);
2927 DeleteMetaFile(hmf);
2928 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2929 HeapFree(GetProcessHeap(), 0, pBits);
2930 return hemf;
2933 static void test_mf_conversions(void)
2935 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2937 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2938 HENHMETAFILE hemf;
2939 METAFILEPICT mfp;
2940 RECT rect = { 0, 0, 100, 100 };
2941 mfp.mm = MM_ANISOTROPIC;
2942 mfp.xExt = 100;
2943 mfp.yExt = 100;
2944 mfp.hMF = NULL;
2945 hemf = create_converted_emf(&mfp);
2947 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2948 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2950 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2951 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2954 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2956 DeleteEnhMetaFile(hemf);
2957 DeleteDC(hdcOffscreen);
2960 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2962 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2963 HENHMETAFILE hemf;
2964 METAFILEPICT mfp;
2965 RECT rect = { 0, 0, 100, 100 };
2966 mfp.mm = MM_TEXT;
2967 mfp.xExt = 0;
2968 mfp.yExt = 0;
2969 mfp.hMF = NULL;
2970 hemf = create_converted_emf(&mfp);
2972 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2973 "emf_LineTo MM_TEXT", TRUE) != 0)
2975 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2976 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2979 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2981 DeleteEnhMetaFile(hemf);
2982 DeleteDC(hdcOffscreen);
2985 trace("Testing MF->EMF conversion (NULL mfp)\n");
2987 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2988 HENHMETAFILE hemf;
2989 RECT rect = { 0, 0, 100, 100 };
2990 hemf = create_converted_emf(NULL);
2992 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2993 "emf_LineTo NULL", TRUE) != 0)
2995 dump_emf_bits(hemf, "emf_LineTo NULL");
2996 dump_emf_records(hemf, "emf_LineTo NULL");
2999 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
3001 DeleteEnhMetaFile(hemf);
3002 DeleteDC(hdcOffscreen);
3006 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3007 LONG mm, LONG xExt, LONG yExt,
3008 RECTL * rclBounds, RECTL * rclFrame)
3010 METAFILEPICT mfp;
3011 METAFILEPICT * mfpPtr = NULL;
3012 HENHMETAFILE emf;
3013 ENHMETAHEADER header;
3014 UINT res;
3016 if (!mfpIsNull)
3018 mfp.mm = mm;
3019 mfp.xExt = xExt;
3020 mfp.yExt = yExt;
3021 mfpPtr = &mfp;
3024 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
3025 ok(emf != NULL, "SetWinMetaFileBits failed\n");
3026 if (!emf) return FALSE;
3027 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
3028 ok(res != 0, "GetEnhMetaHeader failed\n");
3029 DeleteEnhMetaFile(emf);
3030 if (!res) return FALSE;
3032 *rclBounds = header.rclBounds;
3033 *rclFrame = header.rclFrame;
3034 return TRUE;
3037 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3038 LONG mm, LONG xExt, LONG yExt,
3039 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
3041 RECTL rclBounds, rclFrame;
3043 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
3045 const char * msg;
3046 char buf[64];
3048 if (mfpIsNull)
3050 msg = "mfp == NULL";
3052 else
3054 const char * mm_str;
3055 switch (mm)
3057 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
3058 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
3059 default: mm_str = "Unexpected";
3061 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
3062 msg = buf;
3065 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
3066 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
3067 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
3068 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
3069 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
3070 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
3071 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
3072 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
3076 static void test_SetWinMetaFileBits(void)
3078 HMETAFILE wmf;
3079 HDC wmfDC;
3080 BYTE * buffer;
3081 UINT buffer_size;
3082 RECT rect;
3083 UINT res;
3084 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
3085 RECTL rclBoundsIsotropic, rclFrameIsotropic;
3086 RECTL rclBounds, rclFrame;
3087 HDC dc;
3088 LONG diffx, diffy;
3090 wmfDC = CreateMetaFileA(NULL);
3091 ok(wmfDC != NULL, "CreateMetaFile failed\n");
3092 if (!wmfDC) return;
3094 SetWindowExtEx(wmfDC, 100, 100, NULL);
3095 rect.left = rect.top = 0;
3096 rect.right = rect.bottom = 50;
3097 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
3098 wmf = CloseMetaFile(wmfDC);
3099 ok(wmf != NULL, "Metafile creation failed\n");
3100 if (!wmf) return;
3102 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
3103 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
3104 if (buffer_size == 0)
3106 DeleteMetaFile(wmf);
3107 return;
3110 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
3111 ok(buffer != NULL, "HeapAlloc failed\n");
3112 if (!buffer)
3114 DeleteMetaFile(wmf);
3115 return;
3118 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
3119 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3120 DeleteMetaFile(wmf);
3121 if (res != buffer_size)
3123 HeapFree(GetProcessHeap(), 0, buffer);
3124 return;
3127 /* Get the reference bounds and frame */
3128 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3129 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3131 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
3132 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
3133 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3135 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3136 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3137 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
3138 if (diffx < 0) diffx = -diffx;
3139 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3141 dc = CreateCompatibleDC(NULL);
3143 /* Allow 1 mm difference (rounding errors) */
3144 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
3145 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
3146 if (diffx < 0) diffx = -diffx;
3147 if (diffy < 0) diffy = -diffy;
3148 todo_wine
3150 ok(diffx <= 1 && diffy <= 1,
3151 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3152 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
3155 /* Allow 1 mm difference (rounding errors) */
3156 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
3157 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
3158 if (diffx < 0) diffx = -diffx;
3159 if (diffy < 0) diffy = -diffy;
3160 todo_wine
3162 ok(diffx <= 1 && diffy <= 1,
3163 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3164 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
3166 DeleteDC(dc);
3168 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3169 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3171 /* If xExt or yExt is zero or negative, the whole device surface is used */
3172 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3173 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3174 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3175 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3176 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3177 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3178 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3179 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3180 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3181 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3182 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3183 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3185 /* MSDN says that negative xExt and yExt values specify a ratio.
3186 Check that this is wrong and the whole device surface is used */
3187 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3188 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3190 /* Ordinary conversions */
3192 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3194 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3195 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3196 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3197 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3200 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3202 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3203 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3204 ok(rclBounds.left == 0 && rclBounds.top == 0,
3205 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3207 /* Wine has a rounding error */
3208 diffx = rclBounds.right - rclBounds.bottom;
3209 if (diffx < 0) diffx = -diffx;
3210 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3213 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3215 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3216 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3219 HeapFree(GetProcessHeap(), 0, buffer);
3222 static BOOL near_match(int x, int y)
3224 int epsilon = min(abs(x), abs(y));
3226 epsilon = max(epsilon/100, 2);
3228 if(x < y - epsilon || x > y + epsilon) return FALSE;
3229 return TRUE;
3232 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3234 HENHMETAFILE emf;
3235 HDC display_dc, emf_dc;
3236 ENHMETAHEADER *enh_header;
3237 UINT size, emf_size, i;
3238 WORD check = 0;
3239 DWORD rec_num = 0;
3240 METAHEADER *mh = NULL;
3241 METARECORD *rec;
3242 INT horz_res, vert_res, horz_size, vert_size;
3243 INT curve_caps, line_caps, poly_caps;
3245 display_dc = GetDC(NULL);
3246 ok(display_dc != NULL, "display_dc is NULL\n");
3248 horz_res = GetDeviceCaps(display_dc, HORZRES);
3249 vert_res = GetDeviceCaps(display_dc, VERTRES);
3250 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3251 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3253 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3254 ok(emf_dc != NULL, "emf_dc is NULL\n");
3256 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3257 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3259 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3260 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3262 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3263 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3265 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3266 Rectangle(emf_dc, 0, 0, 1000, 20);
3267 emf = CloseEnhMetaFile(emf_dc);
3268 ok(emf != NULL, "emf is NULL\n");
3270 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3271 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3272 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3273 DeleteEnhMetaFile(emf);
3274 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3275 have different resolutions */
3276 enh_header->szlDevice.cx *= scale;
3277 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3278 ok(emf != NULL, "emf is NULL\n");
3279 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3281 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3282 ok(size ||
3283 broken(size == 0), /* some versions of winxp fail for some reason */
3284 "GetWinMetaFileBits returns 0\n");
3285 if(!size) goto end;
3286 mh = HeapAlloc(GetProcessHeap(), 0, size);
3287 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3289 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3290 ok(check == 0, "check %04x\n", check);
3292 rec = (METARECORD*)(mh + 1);
3294 while(rec->rdSize && rec->rdFunction)
3296 const DWORD chunk_size = 0x2000;
3297 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3299 if(rec_num < mfcomment_chunks)
3301 DWORD this_chunk_size = chunk_size;
3303 if(rec_num == mfcomment_chunks - 1)
3304 this_chunk_size = emf_size - rec_num * chunk_size;
3306 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3307 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3308 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3309 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3310 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3311 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3312 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3313 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3314 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3315 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3316 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3317 /* parm[8] is the checksum, tested above */
3318 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3319 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3320 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3321 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3322 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3323 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3324 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3325 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 */
3326 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3327 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3330 else if(rec_num == mfcomment_chunks)
3332 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3333 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3335 else if(rec_num == mfcomment_chunks + 1)
3337 POINT pt;
3338 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3339 switch(mode)
3341 case MM_TEXT:
3342 case MM_ISOTROPIC:
3343 case MM_ANISOTROPIC:
3344 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3345 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3346 break;
3347 case MM_LOMETRIC:
3348 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3349 pt.x = MulDiv( rc->left, 1, 10);
3350 break;
3351 case MM_HIMETRIC:
3352 pt.y = -rc->top + 1;
3353 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3354 break;
3355 case MM_LOENGLISH:
3356 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3357 pt.x = MulDiv( rc->left, 10, 254);
3358 break;
3359 case MM_HIENGLISH:
3360 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3361 pt.x = MulDiv( rc->left, 100, 254);
3362 break;
3363 case MM_TWIPS:
3364 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3365 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3366 break;
3367 default:
3368 pt.x = pt.y = 0;
3370 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3371 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3373 if(rec_num == mfcomment_chunks + 2)
3375 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3376 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3377 "got %d\n", (short)rec->rdParm[0]);
3378 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3379 "got %d\n", (short)rec->rdParm[1]);
3382 rec_num++;
3383 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3386 end:
3387 HeapFree(GetProcessHeap(), 0, mh);
3388 HeapFree(GetProcessHeap(), 0, enh_header);
3389 DeleteEnhMetaFile(emf);
3391 ReleaseDC(NULL, display_dc);
3394 static void test_GetWinMetaFileBits(void)
3396 UINT mode;
3397 RECT frames[] =
3399 { 1000, 2000, 3000, 6000},
3400 {-1000, 2000, 3000, 6000},
3401 { 1000, -2000, 3000, 6000},
3402 { 1005, 2005, 3000, 6000},
3403 {-1005, -2005, 3000, 6000},
3404 {-1005, -2010, 3000, 6000},
3405 {-1005, 2010, 3000, 6000},
3406 { 0, 0, 1, 1},
3407 { -1, -1, 1, 1},
3408 { 0, 0, 0, 0}
3411 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3413 RECT *rc;
3414 for(rc = frames; rc->right - rc->left > 0; rc++)
3416 getwinmetafilebits(mode, 1, rc);
3417 getwinmetafilebits(mode, 2, rc);
3422 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3423 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3424 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3426 static void test_gdiis(void)
3428 RECT rect = {0,0,100,100};
3429 HDC hdc, hemfDC, hmfDC;
3430 HENHMETAFILE hemf;
3431 HMODULE hgdi32;
3433 /* resolve all the functions */
3434 hgdi32 = GetModuleHandleA("gdi32.dll");
3435 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3436 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3437 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3439 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3441 win_skip("Needed GdiIs* functions are not available\n");
3442 return;
3445 /* try with nothing */
3446 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3447 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3448 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3450 /* try with a metafile */
3451 hmfDC = CreateMetaFileA(NULL);
3452 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3453 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3454 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3455 DeleteMetaFile(CloseMetaFile(hmfDC));
3457 /* try with an enhanced metafile */
3458 hdc = GetDC(NULL);
3459 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3460 ok(hemfDC != NULL, "failed to create emf\n");
3462 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3463 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3464 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3466 hemf = CloseEnhMetaFile(hemfDC);
3467 ok(hemf != NULL, "failed to close EMF\n");
3468 DeleteEnhMetaFile(hemf);
3469 ReleaseDC(NULL,hdc);
3472 static void test_SetEnhMetaFileBits(void)
3474 BYTE data[256];
3475 HENHMETAFILE hemf;
3476 ENHMETAHEADER *emh;
3478 memset(data, 0xAA, sizeof(data));
3479 SetLastError(0xdeadbeef);
3480 hemf = SetEnhMetaFileBits(sizeof(data), data);
3481 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3482 ok(GetLastError() == ERROR_INVALID_DATA ||
3483 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3484 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3486 emh = (ENHMETAHEADER *)data;
3487 memset(emh, 0, sizeof(*emh));
3489 emh->iType = EMR_HEADER;
3490 emh->nSize = sizeof(*emh);
3491 emh->dSignature = ENHMETA_SIGNATURE;
3492 /* emh->nVersion = 0x10000; XP doesn't care about version */
3493 emh->nBytes = sizeof(*emh);
3494 /* emh->nRecords = 1; XP doesn't care about records */
3495 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3497 SetLastError(0xdeadbeef);
3498 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3499 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3500 DeleteEnhMetaFile(hemf);
3502 /* XP refuses to load unaligned EMF */
3503 emh->nBytes++;
3504 SetLastError(0xdeadbeef);
3505 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3506 ok(!hemf ||
3507 broken(hemf != NULL), /* Win9x, WinMe */
3508 "SetEnhMetaFileBits should fail\n");
3509 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3510 DeleteEnhMetaFile(hemf);
3512 emh->dSignature = 0;
3513 emh->nBytes--;
3514 SetLastError(0xdeadbeef);
3515 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3516 ok(!hemf ||
3517 broken(hemf != NULL), /* Win9x, WinMe */
3518 "SetEnhMetaFileBits should fail\n");
3519 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3520 DeleteEnhMetaFile(hemf);
3523 static void test_emf_polybezier(void)
3525 HDC hdcMetafile;
3526 HENHMETAFILE hemf;
3527 POINT pts[4];
3528 BOOL ret;
3530 SetLastError(0xdeadbeef);
3531 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3532 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3534 pts[0].x = pts[0].y = 10;
3535 pts[1].x = pts[1].y = 20;
3536 pts[2].x = pts[2].y = 15;
3537 pts[3].x = pts[3].y = 25;
3538 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3539 ok( ret, "PolyBezierTo failed\n" );
3540 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3541 ok( ret, "PolyBezier failed\n" );
3543 pts[0].x = pts[0].y = 32769;
3544 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3545 ok( ret, "PolyBezier failed\n" );
3546 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3547 ok( ret, "PolyBezierTo failed\n" );
3549 hemf = CloseEnhMetaFile(hdcMetafile);
3550 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3552 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3553 "emf_Bezier", FALSE) != 0)
3555 dump_emf_bits(hemf, "emf_Bezier");
3556 dump_emf_records(hemf, "emf_Bezier");
3559 DeleteEnhMetaFile(hemf);
3562 static const unsigned char EMF_PATH_BITS[] =
3564 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3566 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3568 0xe6, 0xff, 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff,
3569 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3570 0xf8, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3571 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3573 0x80, 0x07, 0x00, 0x00, 0xd3, 0x03, 0x00, 0x00,
3574 0xfc, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
3575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3576 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
3577 0xd3, 0xf3, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3578 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3579 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3580 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3581 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3582 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3583 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3584 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3585 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3586 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3587 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3588 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3589 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3590 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3591 0x13, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3592 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3593 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3594 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3597 static void test_emf_GetPath(void)
3599 HDC hdcMetafile;
3600 HENHMETAFILE hemf;
3601 BOOL ret;
3602 int size;
3604 SetLastError(0xdeadbeef);
3605 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3606 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3608 BeginPath(hdcMetafile);
3609 ret = MoveToEx(hdcMetafile, 50, 50, NULL);
3610 ok( ret, "MoveToEx error %d.\n", GetLastError());
3611 ret = LineTo(hdcMetafile, 50, 150);
3612 ok( ret, "LineTo error %d.\n", GetLastError());
3613 ret = LineTo(hdcMetafile, 150, 150);
3614 ok( ret, "LineTo error %d.\n", GetLastError());
3615 ret = LineTo(hdcMetafile, 150, 50);
3616 ok( ret, "LineTo error %d.\n", GetLastError());
3617 ret = LineTo(hdcMetafile, 50, 50);
3618 ok( ret, "LineTo error %d.\n", GetLastError());
3619 Rectangle(hdcMetafile, 10, 10, 20, 20);
3620 EndPath(hdcMetafile);
3622 size = GetPath(hdcMetafile, NULL, NULL, 0);
3623 todo_wine ok( size == 9, "GetPath returned %d.\n", size);
3625 hemf = CloseEnhMetaFile(hdcMetafile);
3626 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3628 if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_GetPath", FALSE) != 0)
3630 dump_emf_bits(hemf, "test_emf_GetPath");
3631 dump_emf_records(hemf, "test_emf_GetPath");
3634 DeleteEnhMetaFile(hemf);
3637 static void test_emf_PolyPolyline(void)
3639 HDC hdcMetafile;
3640 HENHMETAFILE hemf;
3641 POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3642 DWORD counts[2];
3643 BOOL ret;
3645 SetLastError(0xdeadbeef);
3646 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3647 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3649 ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
3650 ok( !ret, "PolyPolyline\n" );
3652 SetLastError( 0xdeadbeef );
3653 counts[0] = 0;
3654 counts[1] = 1;
3655 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3656 ok( !ret, "PolyPolyline\n" );
3657 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3659 SetLastError( 0xdeadbeef );
3660 counts[0] = 1;
3661 counts[1] = 1;
3662 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3663 ok( !ret, "PolyPolyline\n" );
3664 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3666 SetLastError( 0xdeadbeef );
3667 counts[0] = 2;
3668 counts[1] = 1;
3669 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3670 ok( !ret, "PolyPolyline\n" );
3671 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3673 counts[0] = 2;
3674 counts[1] = 2;
3675 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3676 ok( ret, "PolyPolyline\n" );
3678 hemf = CloseEnhMetaFile(hdcMetafile);
3679 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3681 if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
3682 "emf_PolyPolyline", FALSE) != 0)
3684 dump_emf_bits(hemf, "emf_PolyPolyline");
3685 dump_emf_records(hemf, "emf_PolyPolyline");
3688 DeleteEnhMetaFile(hemf);
3691 static void test_emf_GradientFill(void)
3693 HDC mf;
3694 HENHMETAFILE hemf;
3695 TRIVERTEX v[] =
3697 { 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
3698 { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
3699 { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
3700 { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
3701 { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
3703 GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
3704 BOOL ret;
3706 mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
3707 ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
3709 /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
3710 * means it allocates three mesh indices rather than two per
3711 * rectangle. This results in uninitialised values being written
3712 * to the EMF which is rather difficult to test against.
3714 * Note also that the final vertex here is not required, yet it is
3715 * written to the EMF, but is not considered in the bounds
3716 * calculation.
3718 ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
3719 GRADIENT_FILL_TRIANGLE );
3720 ok( ret, "GradientFill\n" );
3722 hemf = CloseEnhMetaFile( mf );
3723 ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
3725 if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
3726 "emf_GradientFill", FALSE ) != 0)
3728 dump_emf_bits( hemf, "emf_GradientFill" );
3729 dump_emf_records( hemf, "emf_GradientFill" );
3732 DeleteEnhMetaFile( hemf );
3735 START_TEST(metafile)
3737 init_function_pointers();
3739 /* For enhanced metafiles (enhmfdrv) */
3740 test_ExtTextOut();
3741 test_ExtTextOutScale();
3742 test_SaveDC();
3743 test_emf_BitBlt();
3744 test_emf_DCBrush();
3745 test_emf_ExtTextOut_on_path();
3746 test_emf_clipping();
3747 test_emf_polybezier();
3748 test_emf_GetPath();
3749 test_emf_PolyPolyline();
3750 test_emf_GradientFill();
3752 /* For win-format metafiles (mfdrv) */
3753 test_mf_SaveDC();
3754 test_mf_Blank();
3755 test_mf_Graphics();
3756 test_mf_PatternBrush();
3757 test_mf_DCBrush();
3758 test_CopyMetaFile();
3759 test_SetMetaFileBits();
3760 test_mf_ExtTextOut_on_path();
3761 test_mf_clipping();
3762 test_mf_GetPath();
3764 /* For metafile conversions */
3765 test_mf_conversions();
3766 test_SetWinMetaFileBits();
3767 test_GetWinMetaFileBits();
3769 test_gdiis();
3770 test_SetEnhMetaFileBits();