kernel32: Add GetConsoleFontInfo stub.
[wine.git] / dlls / gdi32 / tests / metafile.c
blobc77112d99f7e4188ca2d8f4fe36eadf3aff7c49a
1 /*
2 * Unit tests for metafile functions
4 * Copyright (c) 2002 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
40 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
41 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
43 #define GDI_GET_PROC(func) \
44 p ## func = (void *)GetProcAddress(hGDI, #func); \
45 if(!p ## func) \
46 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
48 static void init_function_pointers(void)
50 HMODULE hGDI;
52 pGetRelAbs = NULL;
53 pSetRelAbs = NULL;
55 hGDI = GetModuleHandleA("gdi32.dll");
56 assert(hGDI);
57 GDI_GET_PROC(GetRelAbs);
58 GDI_GET_PROC(SetRelAbs);
59 GDI_GET_PROC(SetDCBrushColor);
60 GDI_GET_PROC(SetDCPenColor);
63 static DWORD rgn_rect_count(HRGN hrgn)
65 DWORD size;
66 RGNDATA *data;
68 if (!hrgn) return 0;
69 if (!(size = GetRegionData(hrgn, 0, NULL))) return 0;
70 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0;
71 GetRegionData(hrgn, size, data);
72 size = data->rdh.nCount;
73 HeapFree(GetProcessHeap(), 0, data);
74 return size;
77 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
78 const ENHMETARECORD *emr, int n_objs, LPARAM param)
80 static int n_record;
81 DWORD i;
82 const INT *dx;
83 INT *orig_dx = (INT *)param;
84 LOGFONTA device_lf;
85 INT ret;
87 if(!hdc) return 1;
89 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
91 switch (emr->iType)
93 case EMR_HEADER:
94 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
95 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
96 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
97 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
98 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
99 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
100 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
102 /* GetBkMode, GetRelAbs do not get reset to the default value */
103 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
104 if(pSetRelAbs && pGetRelAbs)
105 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
107 n_record = 0;
108 break;
110 case EMR_EXTTEXTOUTA:
112 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
113 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
115 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
116 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
118 /* compare up to lfOutPrecision, other values are not interesting,
119 * and in fact sometimes arbitrary adapted by Win9x.
121 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
122 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
124 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
126 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
127 n_record, i, dx[i], orig_dx[i]);
129 n_record++;
130 emr_processed = TRUE;
131 break;
134 case EMR_EXTTEXTOUTW:
136 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
137 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
139 SetLastError(0xdeadbeef);
140 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
141 ok( ret == sizeof(device_lf) ||
142 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
143 "GetObjectA error %d\n", GetLastError());
145 /* compare up to lfOutPrecision, other values are not interesting,
146 * and in fact sometimes arbitrary adapted by Win9x.
148 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
149 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
151 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
153 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
154 n_record, i, dx[i], orig_dx[i]);
156 n_record++;
157 emr_processed = TRUE;
158 break;
161 default:
162 break;
165 return 1;
168 static void test_ExtTextOut(void)
170 HWND hwnd;
171 HDC hdcDisplay, hdcMetafile;
172 HENHMETAFILE hMetafile;
173 HFONT hFont;
174 static const char text[] = "Simple text to test ExtTextOut on metafiles";
175 INT i, len, dx[256];
176 static const RECT rc = { 0, 0, 100, 100 };
177 BOOL ret;
179 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
181 /* Win9x doesn't play EMFs on invisible windows */
182 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
183 0, 0, 200, 200, 0, 0, 0, NULL);
184 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
186 hdcDisplay = GetDC(hwnd);
187 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
189 trace("hdcDisplay %p\n", hdcDisplay);
191 SetMapMode(hdcDisplay, MM_TEXT);
193 memset(&orig_lf, 0, sizeof(orig_lf));
195 orig_lf.lfCharSet = ANSI_CHARSET;
196 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
197 orig_lf.lfWeight = FW_DONTCARE;
198 orig_lf.lfHeight = 7;
199 orig_lf.lfQuality = DEFAULT_QUALITY;
200 lstrcpyA(orig_lf.lfFaceName, "Arial");
201 hFont = CreateFontIndirectA(&orig_lf);
202 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
204 hFont = SelectObject(hdcDisplay, hFont);
206 len = lstrlenA(text);
207 for (i = 0; i < len; i++)
209 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
210 ok( ret, "GetCharWidthA error %d\n", GetLastError());
212 hFont = SelectObject(hdcDisplay, hFont);
214 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
215 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
217 trace("hdcMetafile %p\n", hdcMetafile);
219 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
220 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
222 hFont = SelectObject(hdcMetafile, hFont);
224 /* 1. pass NULL lpDx */
225 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
226 ok( ret, "ExtTextOutA error %d\n", GetLastError());
228 /* 2. pass custom lpDx */
229 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
230 ok( ret, "ExtTextOutA error %d\n", GetLastError());
232 hFont = SelectObject(hdcMetafile, hFont);
233 ret = DeleteObject(hFont);
234 ok( ret, "DeleteObject error %d\n", GetLastError());
236 hMetafile = CloseEnhMetaFile(hdcMetafile);
237 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
239 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
241 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
242 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
244 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
245 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
246 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
247 SetROP2(hdcDisplay, R2_NOT);
248 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
249 SetPolyFillMode(hdcDisplay, WINDING);
250 SetStretchBltMode(hdcDisplay, HALFTONE);
252 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
253 SetBkMode(hdcDisplay, OPAQUE);
255 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
256 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
258 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
259 "text align %08x\n", GetTextAlign(hdcDisplay));
260 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
261 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
262 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
263 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
264 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
265 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
267 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
269 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
270 "A valid hdc has to require a valid rc\n");
272 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
273 "A null hdc does not require a valid rc\n");
275 ret = DeleteEnhMetaFile(hMetafile);
276 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
277 ret = ReleaseDC(hwnd, hdcDisplay);
278 ok( ret, "ReleaseDC error %d\n", GetLastError());
279 DestroyWindow(hwnd);
282 struct eto_scale_test_record
284 INT graphics_mode;
285 INT map_mode;
286 double ex_scale;
287 double ey_scale;
288 BOOL processed;
291 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
292 const ENHMETARECORD *emr, int n_objs, LPARAM param)
294 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
296 if (emr->iType == EMR_EXTTEXTOUTW)
298 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
299 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
300 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
301 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
302 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
303 test->processed = TRUE;
306 return 1;
309 static void test_ExtTextOutScale(void)
311 const RECT rc = { 0, 0, 100, 100 };
312 const WCHAR str[] = {'a',0 };
313 struct eto_scale_test_record test;
314 HDC hdcDisplay, hdcMetafile;
315 HENHMETAFILE hMetafile;
316 HWND hwnd;
317 SIZE wndext, vportext;
318 int horzSize, vertSize, horzRes, vertRes;
319 int ret;
320 int i;
322 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
323 0, 0, 200, 200, 0, 0, 0, NULL);
324 ok(hwnd != 0, "CreateWindowExA failed\n");
326 hdcDisplay = GetDC(hwnd);
327 ok(hdcDisplay != 0, "GetDC failed\n");
329 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
330 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
331 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
332 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
333 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
335 for (i = 0; i < 16; i++)
337 test.graphics_mode = i / 8 + 1;
338 test.map_mode = i % 8 + 1;
340 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
341 ok(ret, "SetGraphicsMode failed\n");
342 ret = SetMapMode(hdcDisplay, test.map_mode);
343 ok(ret, "SetMapMode failed\n");
345 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
347 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
348 ok(ret, "SetWindowExtEx failed\n");
349 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
350 ok(ret, "SetViewportExtEx failed\n");
353 ret = GetViewportExtEx(hdcDisplay, &vportext);
354 ok(ret, "GetViewportExtEx failed\n");
355 ret = GetWindowExtEx(hdcDisplay, &wndext);
356 ok(ret, "GetWindowExtEx failed\n");
358 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
359 test.graphics_mode, test.map_mode,
360 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
361 horzSize, horzRes, vertSize, vertRes);
363 if (test.graphics_mode == GM_COMPATIBLE)
365 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
366 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
367 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
368 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
370 else
372 test.ex_scale = 0.0;
373 test.ey_scale = 0.0;
376 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
377 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
379 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
380 ok(ret, "SetGraphicsMode failed\n");
381 ret = SetMapMode(hdcMetafile, test.map_mode);
382 ok(ret, "SetMapMode failed\n");
384 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
386 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
387 ok(ret, "SetWindowExtEx failed\n");
388 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
389 ok(ret, "SetViewportExtEx failed\n");
392 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
393 ok(ret, "ExtTextOutW failed\n");
395 hMetafile = CloseEnhMetaFile(hdcMetafile);
396 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
398 test.processed = 0;
399 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
400 ok(ret, "EnumEnhMetaFile failed\n");
401 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
403 ret = DeleteEnhMetaFile(hMetafile);
404 ok(ret, "DeleteEnhMetaFile failed\n");
407 ret = ReleaseDC(hwnd, hdcDisplay);
408 ok(ret, "ReleaseDC failed\n");
409 DestroyWindow(hwnd);
413 static void check_dc_state(HDC hdc, int restore_no,
414 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
415 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
417 BOOL ret;
418 XFORM xform;
419 POINT vp_org, win_org;
420 SIZE vp_size, win_size;
421 FLOAT xscale, yscale, edx, edy;
423 SetLastError(0xdeadbeef);
424 ret = GetWorldTransform(hdc, &xform);
425 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
426 ok(ret, "GetWorldTransform error %u\n", GetLastError());
428 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
430 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
431 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
433 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
434 trace("x scale %f\n", xscale);
435 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
436 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
438 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
439 trace("y scale %f\n", yscale);
440 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
441 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
443 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
444 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
445 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
446 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
448 return;
450 win9x_here:
452 GetWindowOrgEx(hdc, &win_org);
453 GetViewportOrgEx(hdc, &vp_org);
454 GetWindowExtEx(hdc, &win_size);
455 GetViewportExtEx(hdc, &vp_size);
457 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
458 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
460 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
461 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
463 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
464 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
466 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
467 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
470 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
471 const ENHMETARECORD *emr, int n_objs, LPARAM param)
473 BOOL ret;
474 XFORM xform;
475 POINT pt;
476 SIZE size;
477 static int save_state;
478 static int restore_no;
479 static int select_no;
481 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
482 hdc, emr->iType, emr->nSize, (void *)param);
484 SetLastError(0xdeadbeef);
485 ret = GetWorldTransform(hdc, &xform);
486 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
488 ret = GetWindowOrgEx(hdc, &pt);
489 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
490 trace("window org (%d,%d)\n", pt.x, pt.y);
491 ret = GetViewportOrgEx(hdc, &pt);
492 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
493 trace("vport org (%d,%d)\n", pt.x, pt.y);
494 ret = GetWindowExtEx(hdc, &size);
495 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
496 trace("window ext (%d,%d)\n", size.cx, size.cy);
497 ret = GetViewportExtEx(hdc, &size);
498 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
499 trace("vport ext (%d,%d)\n", size.cx, size.cy);
501 else
503 ok(ret, "GetWorldTransform error %u\n", GetLastError());
504 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
507 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
509 switch (emr->iType)
511 case EMR_HEADER:
513 static RECT exp_bounds = { 0, 0, 150, 150 };
514 RECT bounds;
515 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
517 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
518 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
519 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
520 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
521 emf->szlDevice.cx, emf->szlDevice.cy);
523 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
524 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
526 save_state = 0;
527 restore_no = 0;
528 select_no = 0;
529 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
530 break;
533 case EMR_LINETO:
535 const EMRLINETO *line = (const EMRLINETO *)emr;
536 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
537 break;
539 case EMR_SETWINDOWORGEX:
541 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
542 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
543 break;
545 case EMR_SETWINDOWEXTEX:
547 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
548 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
549 break;
551 case EMR_SETVIEWPORTORGEX:
553 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
554 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
555 break;
557 case EMR_SETVIEWPORTEXTEX:
559 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
560 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
561 break;
563 case EMR_SAVEDC:
564 save_state++;
565 trace("EMR_SAVEDC\n");
566 break;
568 case EMR_RESTOREDC:
570 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
571 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
573 switch(++restore_no)
575 case 1:
576 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
577 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
578 break;
579 case 2:
580 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
581 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
582 break;
583 case 3:
584 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
585 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
586 break;
588 ok(restore_no <= 3, "restore_no %d\n", restore_no);
589 save_state += restoredc->iRelative;
590 break;
592 case EMR_SELECTOBJECT:
594 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
595 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
596 select_no ++;
597 break;
599 case EMR_EOF:
600 ok(save_state == 0, "EOF save_state %d\n", save_state);
601 ok(select_no == 3, "Too many/few selects %i\n",select_no);
602 break;
605 SetLastError(0xdeadbeef);
606 ret = GetWorldTransform(hdc, &xform);
607 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
609 ret = GetWindowOrgEx(hdc, &pt);
610 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
611 trace("window org (%d,%d)\n", pt.x, pt.y);
612 ret = GetViewportOrgEx(hdc, &pt);
613 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
614 trace("vport org (%d,%d)\n", pt.x, pt.y);
615 ret = GetWindowExtEx(hdc, &size);
616 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
617 trace("window ext (%d,%d)\n", size.cx, size.cy);
618 ret = GetViewportExtEx(hdc, &size);
619 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
620 trace("vport ext (%d,%d)\n", size.cx, size.cy);
622 else
624 ok(ret, "GetWorldTransform error %u\n", GetLastError());
625 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
628 return 1;
631 static void test_SaveDC(void)
633 HDC hdcMetafile, hdcDisplay;
634 HENHMETAFILE hMetafile;
635 HWND hwnd;
636 int ret;
637 POINT pt;
638 SIZE size;
639 HFONT hFont,hFont2,hFontOld,hFontCheck;
640 static const RECT rc = { 0, 0, 150, 150 };
642 /* Win9x doesn't play EMFs on invisible windows */
643 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
644 0, 0, 200, 200, 0, 0, 0, NULL);
645 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
647 hdcDisplay = GetDC(hwnd);
648 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
650 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
651 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
653 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
655 /* Need to write something to the emf, otherwise Windows won't play it back */
656 LineTo(hdcMetafile, 150, 150);
658 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
659 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
660 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
661 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
663 /* Force Win9x to update DC state */
664 SetPixelV(hdcMetafile, 50, 50, 0);
666 ret = GetViewportOrgEx(hdcMetafile, &pt);
667 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
668 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
669 ret = GetViewportExtEx(hdcMetafile, &size);
670 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
671 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
672 ret = SaveDC(hdcMetafile);
673 ok(ret == 1, "ret = %d\n", ret);
675 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
676 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
677 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
678 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
680 /* Force Win9x to update DC state */
681 SetPixelV(hdcMetafile, 50, 50, 0);
683 ret = GetViewportOrgEx(hdcMetafile, &pt);
684 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
685 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
686 ret = GetViewportExtEx(hdcMetafile, &size);
687 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
688 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
689 ret = SaveDC(hdcMetafile);
690 ok(ret == 2, "ret = %d\n", ret);
692 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
693 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
694 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
695 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
696 SetPolyFillMode( hdcMetafile, ALTERNATE );
697 SetBkColor( hdcMetafile, 0 );
699 /* Force Win9x to update DC state */
700 SetPixelV(hdcMetafile, 50, 50, 0);
702 ret = GetViewportOrgEx(hdcMetafile, &pt);
703 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
704 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
705 ret = GetViewportExtEx(hdcMetafile, &size);
706 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
707 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
708 ret = SaveDC(hdcMetafile);
709 ok(ret == 3, "ret = %d\n", ret);
711 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
712 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
713 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
714 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
716 SetPolyFillMode( hdcMetafile, WINDING );
717 SetBkColor( hdcMetafile, 0x123456 );
718 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
719 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
721 /* Force Win9x to update DC state */
722 SetPixelV(hdcMetafile, 50, 50, 0);
724 ret = GetViewportOrgEx(hdcMetafile, &pt);
725 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
726 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
727 ret = GetViewportExtEx(hdcMetafile, &size);
728 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
729 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
730 ret = RestoreDC(hdcMetafile, -1);
731 ok(ret, "ret = %d\n", ret);
733 ret = GetViewportOrgEx(hdcMetafile, &pt);
734 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
735 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
736 ret = GetViewportExtEx(hdcMetafile, &size);
737 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
738 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
739 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
740 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
741 ret = SaveDC(hdcMetafile);
742 ok(ret == 3, "ret = %d\n", ret);
744 ret = GetViewportOrgEx(hdcMetafile, &pt);
745 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
746 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
747 ret = GetViewportExtEx(hdcMetafile, &size);
748 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
749 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
750 ret = RestoreDC(hdcMetafile, 1);
751 ok(ret, "ret = %d\n", ret);
752 ret = GetViewportOrgEx(hdcMetafile, &pt);
753 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
754 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
755 ret = GetViewportExtEx(hdcMetafile, &size);
756 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
757 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
759 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
760 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
761 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
762 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
764 /* Force Win9x to update DC state */
765 SetPixelV(hdcMetafile, 50, 50, 0);
767 ret = GetViewportOrgEx(hdcMetafile, &pt);
768 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
769 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
770 ret = GetViewportExtEx(hdcMetafile, &size);
771 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
772 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
773 ret = SaveDC(hdcMetafile);
774 ok(ret == 1, "ret = %d\n", ret);
776 ret = GetViewportOrgEx(hdcMetafile, &pt);
777 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
778 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
779 ret = GetViewportExtEx(hdcMetafile, &size);
780 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
781 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
782 ret = SaveDC(hdcMetafile);
783 ok(ret == 2, "ret = %d\n", ret);
785 memset(&orig_lf, 0, sizeof(orig_lf));
786 orig_lf.lfCharSet = ANSI_CHARSET;
787 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
788 orig_lf.lfWeight = FW_DONTCARE;
789 orig_lf.lfHeight = 7;
790 orig_lf.lfQuality = DEFAULT_QUALITY;
791 lstrcpyA(orig_lf.lfFaceName, "Arial");
792 hFont = CreateFontIndirectA(&orig_lf);
793 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
795 hFontOld = SelectObject(hdcMetafile, hFont);
797 hFont2 = CreateFontIndirectA(&orig_lf);
798 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
799 hFontCheck = SelectObject(hdcMetafile, hFont2);
800 ok(hFontCheck == hFont, "Font not selected\n");
802 /* Force Win9x to update DC state */
803 SetPixelV(hdcMetafile, 50, 50, 0);
805 ret = RestoreDC(hdcMetafile, 1);
806 ok(ret, "ret = %d\n", ret);
807 ret = GetViewportOrgEx(hdcMetafile, &pt);
808 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
809 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
810 ret = GetViewportExtEx(hdcMetafile, &size);
811 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
812 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
814 hFontCheck = SelectObject(hdcMetafile, hFontOld);
815 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
816 "Font not reverted with DC Restore\n");
818 ret = RestoreDC(hdcMetafile, -20);
819 ok(!ret, "ret = %d\n", ret);
820 ret = RestoreDC(hdcMetafile, 20);
821 ok(!ret, "ret = %d\n", ret);
823 hMetafile = CloseEnhMetaFile(hdcMetafile);
824 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
826 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
827 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
829 ret = DeleteObject(hFont);
830 ok( ret, "DeleteObject error %d\n", GetLastError());
831 ret = DeleteObject(hFont2);
832 ok( ret, "DeleteObject error %d\n", GetLastError());
833 ret = DeleteEnhMetaFile(hMetafile);
834 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
835 ret = ReleaseDC(hwnd, hdcDisplay);
836 ok( ret, "ReleaseDC error %d\n", GetLastError());
837 DestroyWindow(hwnd);
840 static void test_mf_SaveDC(void)
842 HDC hdcMetafile;
843 HMETAFILE hMetafile;
844 int ret;
845 POINT pt;
846 SIZE size;
847 HFONT hFont,hFont2,hFontOld,hFontCheck;
849 hdcMetafile = CreateMetaFileA(NULL);
850 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
852 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
853 ok (ret, "SetMapMode should not fail\n");
855 /* Need to write something to the emf, otherwise Windows won't play it back */
856 LineTo(hdcMetafile, 150, 150);
858 pt.x = pt.y = 5555;
859 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
860 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
861 pt.x = pt.y = 5555;
862 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
863 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
864 size.cx = size.cy = 5555;
865 SetWindowExtEx(hdcMetafile, 110, 110, &size );
866 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
867 size.cx = size.cy = 5555;
868 SetViewportExtEx(hdcMetafile, 120, 120, &size );
869 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
871 /* Force Win9x to update DC state */
872 SetPixelV(hdcMetafile, 50, 50, 0);
874 ret = GetViewportOrgEx(hdcMetafile, &pt);
875 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
876 ret = GetViewportExtEx(hdcMetafile, &size);
877 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
878 ret = SaveDC(hdcMetafile);
879 ok(ret == 1, "ret = %d\n", ret);
881 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
882 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
883 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
884 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
886 /* Force Win9x to update DC state */
887 SetPixelV(hdcMetafile, 50, 50, 0);
889 ret = SaveDC(hdcMetafile);
890 ok(ret == 1, "ret = %d\n", ret);
892 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
893 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
894 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
895 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
897 /* Force Win9x to update DC state */
898 SetPixelV(hdcMetafile, 50, 50, 0);
899 SetPolyFillMode( hdcMetafile, ALTERNATE );
900 SetBkColor( hdcMetafile, 0 );
902 ret = SaveDC(hdcMetafile);
903 ok(ret == 1, "ret = %d\n", ret);
905 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
906 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
907 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
908 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
910 SetPolyFillMode( hdcMetafile, WINDING );
911 SetBkColor( hdcMetafile, 0x123456 );
912 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
913 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
915 /* Force Win9x to update DC state */
916 SetPixelV(hdcMetafile, 50, 50, 0);
918 ret = RestoreDC(hdcMetafile, -1);
919 ok(ret, "ret = %d\n", ret);
921 ret = SaveDC(hdcMetafile);
922 ok(ret == 1, "ret = %d\n", ret);
924 ret = RestoreDC(hdcMetafile, 1);
925 ok(ret, "ret = %d\n", ret);
927 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
928 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
929 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
930 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
932 /* Force Win9x to update DC state */
933 SetPixelV(hdcMetafile, 50, 50, 0);
935 ret = SaveDC(hdcMetafile);
936 ok(ret == 1, "ret = %d\n", ret);
938 ret = SaveDC(hdcMetafile);
939 ok(ret == 1, "ret = %d\n", ret);
941 memset(&orig_lf, 0, sizeof(orig_lf));
942 orig_lf.lfCharSet = ANSI_CHARSET;
943 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
944 orig_lf.lfWeight = FW_DONTCARE;
945 orig_lf.lfHeight = 7;
946 orig_lf.lfQuality = DEFAULT_QUALITY;
947 lstrcpyA(orig_lf.lfFaceName, "Arial");
948 hFont = CreateFontIndirectA(&orig_lf);
949 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
951 hFontOld = SelectObject(hdcMetafile, hFont);
953 hFont2 = CreateFontIndirectA(&orig_lf);
954 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
955 hFontCheck = SelectObject(hdcMetafile, hFont2);
956 ok(hFontCheck == hFont, "Font not selected\n");
958 /* Force Win9x to update DC state */
959 SetPixelV(hdcMetafile, 50, 50, 0);
961 ret = RestoreDC(hdcMetafile, 1);
962 ok(ret, "ret = %d\n", ret);
964 hFontCheck = SelectObject(hdcMetafile, hFontOld);
965 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
967 /* restore level is ignored */
968 ret = RestoreDC(hdcMetafile, -20);
969 ok(ret, "ret = %d\n", ret);
970 ret = RestoreDC(hdcMetafile, 20);
971 ok(ret, "ret = %d\n", ret);
972 ret = RestoreDC(hdcMetafile, 0);
973 ok(ret, "ret = %d\n", ret);
975 hMetafile = CloseMetaFile(hdcMetafile);
976 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
978 ret = DeleteMetaFile(hMetafile);
979 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
980 ret = DeleteObject(hFont);
981 ok( ret, "DeleteObject error %d\n", GetLastError());
982 ret = DeleteObject(hFont2);
983 ok( ret, "DeleteObject error %d\n", GetLastError());
987 /* Win-format metafile (mfdrv) tests */
988 /* These tests compare the generated metafiles byte-by-byte */
989 /* with the nominal results. */
991 /* Maximum size of sample metafiles in bytes. */
992 #define MF_BUFSIZE 1024
994 /* 8x8 bitmap data for a pattern brush */
995 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
996 0x01, 0x00, 0x02, 0x00,
997 0x03, 0x00, 0x04, 0x00,
998 0x05, 0x00, 0x06, 0x00,
999 0x07, 0x00, 0x08, 0x00
1002 /* Sample metafiles to be compared to the outputs of the
1003 * test functions.
1006 static const unsigned char MF_BLANK_BITS[] = {
1007 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1008 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1009 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1012 static const unsigned char MF_GRAPHICS_BITS[] = {
1013 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1016 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1017 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1018 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1019 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1020 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1021 0x00, 0x00, 0x00, 0x00
1024 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1025 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1026 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1028 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1029 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1030 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1031 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1032 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1033 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1035 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1036 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1037 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1038 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1039 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1040 0x00, 0x00
1043 static const unsigned char MF_DCBRUSH_BITS[] =
1045 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1046 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1047 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1048 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1049 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1050 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1053 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1054 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1055 0x00, 0x00, 0x00, 0x00
1058 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1060 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1062 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1063 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1064 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1065 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1066 0x00, 0x00
1069 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1071 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1076 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1077 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1078 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1081 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1084 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1085 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1086 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1088 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1089 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1090 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1091 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1094 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1095 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1096 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1097 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1098 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1099 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1101 0x14, 0x00, 0x00, 0x00
1104 static const unsigned char MF_LINETO_BITS[] = {
1105 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1106 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1107 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1108 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1109 0x00, 0x00
1112 static const unsigned char EMF_LINETO_BITS[] = {
1113 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1115 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1118 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1119 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1120 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1123 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1126 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1127 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1128 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1129 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1130 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1131 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1132 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1133 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1134 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1136 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1137 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1138 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1139 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1140 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1141 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1142 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1143 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1144 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1145 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1146 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1147 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1148 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1149 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1150 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1151 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1154 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1155 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1157 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1160 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1161 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1162 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1165 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1168 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1169 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1170 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1171 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1172 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1173 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1174 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1175 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1176 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1178 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1179 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1180 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1181 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1182 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1183 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1184 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1185 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1186 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1187 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1188 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1189 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1190 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1191 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1192 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1193 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1196 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1197 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1199 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1202 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1203 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1204 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1207 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1210 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1211 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1212 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1213 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1214 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1215 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1216 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1217 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1218 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1220 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1221 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1223 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1224 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1225 0x14, 0x00, 0x00, 0x00
1228 static const unsigned char EMF_BITBLT[] =
1230 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1232 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1235 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1236 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1237 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1240 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1243 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1244 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1246 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1248 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1254 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1255 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1256 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1257 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1267 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1269 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1272 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1280 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1282 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1284 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1291 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1292 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1293 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1294 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1295 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1305 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1306 0x14, 0x00, 0x00, 0x00
1309 static const unsigned char EMF_DCBRUSH_BITS[] =
1311 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1312 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1313 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1314 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1315 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1316 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1317 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1318 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1321 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1323 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1324 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1325 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1326 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1327 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1328 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1329 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1330 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1331 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1332 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1333 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1336 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1337 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1338 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1339 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1340 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1341 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1342 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1345 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1346 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1347 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1348 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1349 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1350 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1351 0x14, 0x00, 0x00, 0x00
1354 static const unsigned char EMF_BEZIER_BITS[] =
1356 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1358 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1360 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1361 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1362 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1363 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1365 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1366 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1368 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1369 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1370 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1372 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1373 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1374 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1375 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1376 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1377 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1378 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1379 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1380 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1381 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1382 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1383 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1384 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1385 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1386 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1387 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1388 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1389 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1390 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1391 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1392 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1393 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1394 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1395 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1396 0x14, 0x00, 0x00, 0x00
1399 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1401 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1402 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1403 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1404 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1405 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1406 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1407 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1408 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1410 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1411 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1413 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1414 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1415 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1416 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1417 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1418 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1419 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1420 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1421 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1422 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1424 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1426 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1427 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1428 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1429 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1430 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1432 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1433 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1434 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1435 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1436 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1437 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1438 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1439 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1440 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1441 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1442 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1443 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1444 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1445 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1446 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1447 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1448 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1449 0x14, 0x00, 0x00, 0x00
1452 static const unsigned char EMF_GRADIENTFILL_BITS[] =
1454 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1455 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1456 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1457 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1458 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1459 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1460 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1461 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1463 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1464 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1467 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1468 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1469 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1470 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1471 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1472 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1473 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1474 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1475 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1476 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1477 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1478 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1479 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1480 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1481 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1482 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1483 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1484 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1487 0x14, 0x00, 0x00, 0x00
1490 /* For debugging or dumping the raw metafiles produced by
1491 * new test functions.
1493 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1494 INT nobj, LPARAM param)
1496 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1497 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1498 return TRUE;
1501 /* For debugging or dumping the raw metafiles produced by
1502 * new test functions.
1505 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1507 BYTE buf[MF_BUFSIZE];
1508 UINT mfsize, i;
1510 if (!winetest_debug) return;
1512 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1513 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1515 printf ("MetaFile %s has bits:\n{\n ", desc);
1516 for (i=0; i<mfsize; i++)
1518 printf ("0x%02x", buf[i]);
1519 if (i == mfsize-1)
1520 printf ("\n");
1521 else if (i % 8 == 7)
1522 printf (",\n ");
1523 else
1524 printf (", ");
1526 printf ("};\n");
1529 /* Compare the metafile produced by a test function with the
1530 * expected raw metafile data in "bits".
1531 * Return value is 0 for a perfect match,
1532 * -1 if lengths aren't equal,
1533 * otherwise returns the number of non-matching bytes.
1536 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1537 const char *desc)
1539 unsigned char buf[MF_BUFSIZE];
1540 UINT mfsize, i;
1541 int diff;
1543 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1544 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1545 if (mfsize < MF_BUFSIZE)
1546 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1547 desc, mfsize, bsize);
1548 else
1549 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1550 desc, mfsize, bsize);
1551 if (mfsize != bsize)
1552 return -1;
1554 diff = 0;
1555 for (i=0; i<bsize; i++)
1557 if (buf[i] != bits[i])
1558 diff++;
1560 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1561 desc, mfsize, bsize, diff);
1563 return diff;
1566 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1568 unsigned char buf[MF_BUFSIZE];
1569 DWORD mfsize, rd_size, i;
1570 int diff;
1571 HANDLE hfile;
1572 BOOL ret;
1574 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1575 assert(hfile != INVALID_HANDLE_VALUE);
1577 mfsize = GetFileSize(hfile, NULL);
1578 assert(mfsize <= MF_BUFSIZE);
1580 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1581 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1583 CloseHandle(hfile);
1585 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1587 if (mfsize != bsize)
1588 return -1;
1590 diff = 0;
1591 for (i=0; i<bsize; i++)
1593 if (buf[i] != bits[i])
1594 diff++;
1596 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1597 desc, mfsize, bsize, diff);
1599 return diff;
1602 /* For debugging or dumping the raw EMFs produced by
1603 * new test functions.
1605 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1607 BYTE buf[MF_BUFSIZE];
1608 UINT mfsize, i;
1610 if (!winetest_debug) return;
1612 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1613 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1615 printf("EMF %s has bits:\n{\n ", desc);
1616 for (i = 0; i < mfsize; i++)
1618 printf ("0x%02x", buf[i]);
1619 if (i == mfsize-1)
1620 printf ("\n");
1621 else if (i % 8 == 7)
1622 printf (",\n ");
1623 else
1624 printf (", ");
1626 printf ("};\n");
1629 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1631 BYTE *emf;
1632 BYTE buf[MF_BUFSIZE];
1633 UINT mfsize, offset;
1635 if (!winetest_debug) return;
1637 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1638 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1640 printf("EMF %s has records:\n", desc);
1642 emf = buf;
1643 offset = 0;
1644 while(offset < mfsize)
1646 EMR *emr = (EMR *)(emf + offset);
1647 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1648 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1649 offset += emr->nSize;
1653 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1655 const BYTE *buf;
1656 DWORD i;
1658 if (!winetest_debug) return;
1660 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1661 buf = (const BYTE *)emr;
1662 for (i = 0; i < emr->nSize; i++)
1664 printf ("0x%02x", buf[i]);
1665 if (i == emr->nSize - 1)
1666 printf ("\n");
1667 else if (i % 8 == 7)
1668 printf (",\n");
1669 else
1670 printf (", ");
1672 printf ("};\n");
1675 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1677 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1678 eto->rclBounds.right, eto->rclBounds.bottom);
1679 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1680 trace("exScale: %f\n", eto->exScale);
1681 trace("eyScale: %f\n", eto->eyScale);
1682 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1683 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1684 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1685 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1686 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1687 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1688 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1691 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1692 const char *desc, BOOL ignore_scaling)
1694 int diff;
1696 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1697 desc, emr1->iType, emr2->iType);
1699 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1700 desc, emr1->nSize, emr2->nSize);
1702 /* iType and nSize mismatches are fatal */
1703 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1705 /* contents of EMR_GDICOMMENT are not interesting */
1706 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1708 /* different Windows versions setup DC scaling differently when
1709 * converting an old style metafile to an EMF.
1711 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1712 emr1->iType == EMR_SETVIEWPORTEXTEX))
1713 return TRUE;
1715 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1717 EMREXTTEXTOUTW *eto1, *eto2;
1719 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1720 memcpy(eto1, emr1, emr1->nSize);
1721 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1722 memcpy(eto2, emr2, emr2->nSize);
1724 /* different Windows versions setup DC scaling differently */
1725 eto1->exScale = eto1->eyScale = 0.0;
1726 eto2->exScale = eto2->eyScale = 0.0;
1728 diff = memcmp(eto1, eto2, emr1->nSize);
1729 if (diff)
1731 dump_EMREXTTEXTOUT(eto1);
1732 dump_EMREXTTEXTOUT(eto2);
1734 HeapFree(GetProcessHeap(), 0, eto1);
1735 HeapFree(GetProcessHeap(), 0, eto2);
1737 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1739 /* We have to take care of NT4 differences here */
1740 diff = memcmp(emr1, emr2, emr1->nSize);
1741 if (diff)
1743 ENHMETARECORD *emr_nt4;
1745 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1746 memcpy(emr_nt4, emr2, emr2->nSize);
1747 /* Correct the nRgnSize field */
1748 emr_nt4->dParm[5] = sizeof(RECT);
1750 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1751 if (!diff)
1752 win_skip("Catered for NT4 differences\n");
1754 HeapFree(GetProcessHeap(), 0, emr_nt4);
1757 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1759 EMRPOLYBEZIER16 *eto1, *eto2;
1761 eto1 = (EMRPOLYBEZIER16*)emr1;
1762 eto2 = (EMRPOLYBEZIER16*)emr2;
1764 diff = eto1->cpts != eto2->cpts;
1765 if(!diff)
1766 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1768 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1770 EMRPOLYBEZIER *eto1, *eto2;
1772 eto1 = (EMRPOLYBEZIER*)emr1;
1773 eto2 = (EMRPOLYBEZIER*)emr2;
1775 diff = eto1->cptl != eto2->cptl;
1776 if(!diff)
1777 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1779 else
1780 diff = memcmp(emr1, emr2, emr1->nSize);
1782 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1784 if (diff)
1786 dump_emf_record(emr1, "expected bits");
1787 dump_emf_record(emr2, "actual bits");
1790 return diff == 0; /* report all non-fatal record mismatches */
1793 /* Compare the EMF produced by a test function with the
1794 * expected raw EMF data in "bits".
1795 * Return value is 0 for a perfect match,
1796 * -1 if lengths aren't equal,
1797 * otherwise returns the number of non-matching bytes.
1799 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1800 UINT bsize, const char *desc,
1801 BOOL ignore_scaling)
1803 unsigned char buf[MF_BUFSIZE];
1804 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1805 const ENHMETAHEADER *emh1, *emh2;
1807 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1808 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1810 /* ENHMETAHEADER size could differ, depending on platform */
1811 diff_nt4 = sizeof(SIZEL);
1812 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1814 if (mfsize < MF_BUFSIZE)
1816 ok(mfsize == bsize ||
1817 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1818 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1819 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1821 else
1822 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1823 desc, mfsize, bsize);
1825 /* basic things must match */
1826 emh1 = (const ENHMETAHEADER *)bits;
1827 emh2 = (const ENHMETAHEADER *)buf;
1828 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1829 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1830 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1831 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1833 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1834 ok(emh1->nSize == emh2->nSize ||
1835 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1836 broken(emh1->nSize - diff_9x == emh2->nSize),
1837 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1838 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1839 ok(emh1->nBytes == emh2->nBytes ||
1840 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1841 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1842 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1843 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1845 offset1 = emh1->nSize;
1846 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1847 while (offset1 < emh1->nBytes)
1849 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1850 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1852 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1853 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1855 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1857 /* We have already bailed out if iType or nSize don't match */
1858 offset1 += emr1->nSize;
1859 offset2 += emr2->nSize;
1861 return 0;
1865 /* tests blitting to an EMF */
1866 static void test_emf_BitBlt(void)
1868 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1869 HBITMAP hBitmap, hOldBitmap;
1870 HENHMETAFILE hMetafile;
1871 #define BMP_DIM 4
1872 BITMAPINFOHEADER bmih =
1874 sizeof(BITMAPINFOHEADER),
1875 BMP_DIM,/* biWidth */
1876 BMP_DIM,/* biHeight */
1877 1, /* biPlanes */
1878 24, /* biBitCount */
1879 BI_RGB, /* biCompression */
1880 0, /* biXPelsPerMeter */
1881 0, /* biYPelsPerMeter */
1882 0, /* biClrUsed */
1883 0, /* biClrImportant */
1885 void *bits;
1886 XFORM xform;
1887 BOOL ret;
1889 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1890 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1892 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1893 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1894 ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
1895 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1896 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1897 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1898 DIB_RGB_COLORS, &bits, NULL, 0);
1899 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1901 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1902 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1904 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1905 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1906 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1908 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1909 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1910 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1911 ok( ret, "BitBlt(WHITENESS) failed\n" );
1913 ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
1914 ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
1915 ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
1916 ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
1917 ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
1918 memset(&xform, 0, sizeof(xform));
1919 xform.eM11 = 0.5;
1920 xform.eM22 = 1.0;
1921 ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
1923 ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
1924 ok( ret, "StretchBlt(SRCCOPY) failed\n" );
1926 hMetafile = CloseEnhMetaFile(hdcMetafile);
1927 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1929 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1930 "emf_BitBlt", FALSE) != 0)
1932 dump_emf_bits(hMetafile, "emf_BitBlt");
1933 dump_emf_records(hMetafile, "emf_BitBlt");
1936 SelectObject(hdcBitmap, hOldBitmap);
1937 DeleteObject(hBitmap);
1938 DeleteDC(hdcBitmap);
1939 DeleteDC(hdcDisplay);
1940 #undef BMP_DIM
1943 static void test_emf_DCBrush(void)
1945 HDC hdcMetafile;
1946 HENHMETAFILE hMetafile;
1947 HBRUSH hBrush;
1948 HPEN hPen;
1949 BOOL ret;
1950 COLORREF color;
1952 if (!pSetDCBrushColor || !pSetDCPenColor)
1954 win_skip( "SetDCBrush/PenColor not supported\n" );
1955 return;
1958 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1959 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1961 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1962 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1964 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1965 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1967 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1968 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1970 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1971 ok( color == 0, "SetDCPenColor returned %x\n", color );
1973 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1975 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1976 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1978 hMetafile = CloseEnhMetaFile(hdcMetafile);
1979 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1981 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1982 "emf_DC_Brush", FALSE ) != 0)
1984 dump_emf_bits(hMetafile, "emf_DC_Brush");
1985 dump_emf_records(hMetafile, "emf_DC_Brush");
1987 ret = DeleteEnhMetaFile(hMetafile);
1988 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1989 ret = DeleteObject(hBrush);
1990 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1991 ret = DeleteObject(hPen);
1992 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1995 /* Test a blank metafile. May be used as a template for new tests. */
1997 static void test_mf_Blank(void)
1999 HDC hdcMetafile;
2000 HMETAFILE hMetafile;
2001 INT caps;
2002 BOOL ret;
2003 INT type;
2005 hdcMetafile = CreateMetaFileA(NULL);
2006 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2007 trace("hdcMetafile %p\n", hdcMetafile);
2009 /* Tests on metafile initialization */
2010 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
2011 ok (caps == DT_METAFILE,
2012 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
2014 hMetafile = CloseMetaFile(hdcMetafile);
2015 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2016 type = GetObjectType(hMetafile);
2017 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2018 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2020 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2021 "mf_blank") != 0)
2023 dump_mf_bits(hMetafile, "mf_Blank");
2024 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2027 ret = DeleteMetaFile(hMetafile);
2028 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2031 static void test_CopyMetaFile(void)
2033 HDC hdcMetafile;
2034 HMETAFILE hMetafile, hmf_copy;
2035 BOOL ret;
2036 char temp_path[MAX_PATH];
2037 char mf_name[MAX_PATH];
2038 INT type;
2040 hdcMetafile = CreateMetaFileA(NULL);
2041 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2042 trace("hdcMetafile %p\n", hdcMetafile);
2044 hMetafile = CloseMetaFile(hdcMetafile);
2045 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2046 type = GetObjectType(hMetafile);
2047 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2049 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2050 "mf_blank") != 0)
2052 dump_mf_bits(hMetafile, "mf_Blank");
2053 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2056 GetTempPathA(MAX_PATH, temp_path);
2057 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
2059 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
2060 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
2062 type = GetObjectType(hmf_copy);
2063 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
2065 ret = DeleteMetaFile(hMetafile);
2066 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2068 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
2070 dump_mf_bits(hmf_copy, "mf_Blank");
2071 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
2074 ret = DeleteMetaFile(hmf_copy);
2075 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
2077 DeleteFileA(mf_name);
2080 static void test_SetMetaFileBits(void)
2082 HMETAFILE hmf;
2083 INT type;
2084 BOOL ret;
2085 BYTE buf[256];
2086 METAHEADER *mh;
2088 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2089 trace("hmf %p\n", hmf);
2090 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2091 type = GetObjectType(hmf);
2092 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
2094 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2096 dump_mf_bits(hmf, "mf_Graphics");
2097 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2100 ret = DeleteMetaFile(hmf);
2101 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2103 /* NULL data crashes XP SP1 */
2104 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2106 /* Now with zero size */
2107 SetLastError(0xdeadbeef);
2108 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2109 trace("hmf %p\n", hmf);
2110 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2111 ok(GetLastError() == ERROR_INVALID_DATA ||
2112 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2113 "wrong error %d\n", GetLastError());
2115 /* Now with odd size */
2116 SetLastError(0xdeadbeef);
2117 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2118 trace("hmf %p\n", hmf);
2119 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2120 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2122 /* Now with zeroed out header fields */
2123 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2124 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2125 mh = (METAHEADER *)buf;
2126 /* corruption of any of the below fields leads to a failure */
2127 mh->mtType = 0;
2128 mh->mtVersion = 0;
2129 mh->mtHeaderSize = 0;
2130 SetLastError(0xdeadbeef);
2131 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2132 trace("hmf %p\n", hmf);
2133 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2134 ok(GetLastError() == ERROR_INVALID_DATA ||
2135 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2136 "wrong error %d\n", GetLastError());
2138 /* Now with corrupted mtSize field */
2139 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2140 mh = (METAHEADER *)buf;
2141 /* corruption of mtSize doesn't lead to a failure */
2142 mh->mtSize *= 2;
2143 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2144 trace("hmf %p\n", hmf);
2145 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2147 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2149 dump_mf_bits(hmf, "mf_Graphics");
2150 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2153 ret = DeleteMetaFile(hmf);
2154 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2156 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2157 /* Now with zeroed out mtSize field */
2158 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2159 mh = (METAHEADER *)buf;
2160 /* zeroing mtSize doesn't lead to a failure */
2161 mh->mtSize = 0;
2162 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2163 trace("hmf %p\n", hmf);
2164 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2166 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2168 dump_mf_bits(hmf, "mf_Graphics");
2169 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2172 ret = DeleteMetaFile(hmf);
2173 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2174 #endif
2177 /* Simple APIs from mfdrv/graphics.c
2180 static void test_mf_Graphics(void)
2182 HDC hdcMetafile;
2183 HMETAFILE hMetafile;
2184 POINT oldpoint;
2185 BOOL ret;
2187 hdcMetafile = CreateMetaFileA(NULL);
2188 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2189 trace("hdcMetafile %p\n", hdcMetafile);
2191 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2192 ok( ret, "MoveToEx error %d.\n", GetLastError());
2193 ret = LineTo(hdcMetafile, 2, 2);
2194 ok( ret, "LineTo error %d.\n", GetLastError());
2195 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2196 ok( ret, "MoveToEx error %d.\n", GetLastError());
2198 /* oldpoint gets garbage under Win XP, so the following test would
2199 * work under Wine but fails under Windows:
2201 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2202 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2203 * oldpoint.x, oldpoint.y);
2206 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2207 ok( ret, "Ellipse error %d.\n", GetLastError());
2209 hMetafile = CloseMetaFile(hdcMetafile);
2210 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2211 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2213 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2214 "mf_Graphics") != 0)
2216 dump_mf_bits(hMetafile, "mf_Graphics");
2217 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2220 ret = DeleteMetaFile(hMetafile);
2221 ok( ret, "DeleteMetaFile(%p) error %d\n",
2222 hMetafile, GetLastError());
2225 static void test_mf_PatternBrush(void)
2227 HDC hdcMetafile;
2228 HMETAFILE hMetafile;
2229 LOGBRUSH *orig_lb;
2230 HBRUSH hBrush;
2231 BOOL ret;
2233 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2235 orig_lb->lbStyle = BS_PATTERN;
2236 orig_lb->lbColor = RGB(0, 0, 0);
2237 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2238 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2240 hBrush = CreateBrushIndirect (orig_lb);
2241 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2243 hdcMetafile = CreateMetaFileA(NULL);
2244 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2245 trace("hdcMetafile %p\n", hdcMetafile);
2247 hBrush = SelectObject(hdcMetafile, hBrush);
2248 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2250 hMetafile = CloseMetaFile(hdcMetafile);
2251 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2252 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2254 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2255 "mf_Pattern_Brush") != 0)
2257 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2258 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2261 ret = DeleteMetaFile(hMetafile);
2262 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2263 ret = DeleteObject(hBrush);
2264 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2265 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2266 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2267 GetLastError());
2268 HeapFree (GetProcessHeap(), 0, orig_lb);
2271 static void test_mf_DCBrush(void)
2273 HDC hdcMetafile;
2274 HMETAFILE hMetafile;
2275 HBRUSH hBrush;
2276 HPEN hPen;
2277 BOOL ret;
2278 COLORREF color;
2280 if (!pSetDCBrushColor || !pSetDCPenColor)
2282 win_skip( "SetDCBrush/PenColor not supported\n" );
2283 return;
2286 hdcMetafile = CreateMetaFileA(NULL);
2287 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2289 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2290 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2292 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2293 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2295 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2296 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2298 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2299 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2301 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2303 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2304 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2306 hMetafile = CloseMetaFile(hdcMetafile);
2307 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2309 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2311 dump_mf_bits(hMetafile, "mf_DCBrush");
2312 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2314 ret = DeleteMetaFile(hMetafile);
2315 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2318 static void test_mf_ExtTextOut_on_path(void)
2320 HDC hdcMetafile;
2321 HMETAFILE hMetafile;
2322 BOOL ret;
2323 static const INT dx[4] = { 3, 5, 8, 12 };
2325 hdcMetafile = CreateMetaFileA(NULL);
2326 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2327 trace("hdcMetafile %p\n", hdcMetafile);
2329 ret = BeginPath(hdcMetafile);
2330 ok(!ret, "BeginPath on metafile DC should fail\n");
2332 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2333 ok(ret, "ExtTextOut error %d\n", GetLastError());
2335 ret = EndPath(hdcMetafile);
2336 ok(!ret, "EndPath on metafile DC should fail\n");
2338 hMetafile = CloseMetaFile(hdcMetafile);
2339 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2341 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2342 "mf_TextOut_on_path") != 0)
2344 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2345 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2348 ret = DeleteMetaFile(hMetafile);
2349 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2352 static void test_emf_ExtTextOut_on_path(void)
2354 HWND hwnd;
2355 HDC hdcDisplay, hdcMetafile;
2356 HENHMETAFILE hMetafile;
2357 BOOL ret;
2358 static const INT dx[4] = { 3, 5, 8, 12 };
2360 /* Win9x doesn't play EMFs on invisible windows */
2361 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2362 0, 0, 200, 200, 0, 0, 0, NULL);
2363 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2365 hdcDisplay = GetDC(hwnd);
2366 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2368 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2369 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2371 ret = BeginPath(hdcMetafile);
2372 ok(ret, "BeginPath error %d\n", GetLastError());
2374 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2375 ok(ret, "ExtTextOut error %d\n", GetLastError());
2377 ret = EndPath(hdcMetafile);
2378 ok(ret, "EndPath error %d\n", GetLastError());
2380 hMetafile = CloseEnhMetaFile(hdcMetafile);
2381 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2383 /* this doesn't succeed yet: EMF has correct size, all EMF records
2384 * are there, but their contents don't match for different reasons.
2386 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2387 "emf_TextOut_on_path", FALSE) != 0)
2389 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2390 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2393 ret = DeleteEnhMetaFile(hMetafile);
2394 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2395 ret = ReleaseDC(hwnd, hdcDisplay);
2396 ok(ret, "ReleaseDC error %d\n", GetLastError());
2397 DestroyWindow(hwnd);
2400 static const unsigned char EMF_CLIPPING[] =
2402 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2404 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2406 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2407 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2408 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2409 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2411 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2412 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2414 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2415 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2416 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2417 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2418 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2419 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2420 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2421 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2422 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2423 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2424 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2425 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2426 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2427 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2430 static void translate( POINT *pt, UINT count, const XFORM *xform )
2432 while (count--)
2434 FLOAT x = (FLOAT)pt->x;
2435 FLOAT y = (FLOAT)pt->y;
2436 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2437 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2438 pt++;
2442 /* Compare rectangles allowing rounding errors */
2443 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2445 return abs(rc1->left - rc2->left) <= 1 &&
2446 abs(rc1->top - rc2->top) <= 1 &&
2447 abs(rc1->right - rc2->right) <= 1 &&
2448 abs(rc1->bottom - rc2->bottom) <= 1;
2451 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2452 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2454 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2456 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2457 union _rgn
2459 RGNDATA data;
2460 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2462 const union _rgn *rgn1;
2463 union _rgn rgn2;
2464 RECT rect, rc_transformed;
2465 const RECT *rc = (const RECT *)param;
2466 HRGN hrgn;
2467 XFORM xform;
2468 INT ret;
2469 BOOL is_win9x;
2471 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2472 clip->cbRgnData, clip->iMode);
2474 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2475 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2476 "too small data block: %u bytes\n", clip->cbRgnData);
2477 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2478 return 0;
2480 rgn1 = (const union _rgn *)clip->RgnData;
2482 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2483 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2484 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2485 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2486 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2488 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2490 rect = *(const RECT *)rgn1->data.Buffer;
2491 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2492 ok(EqualRect(&rect, rc), "rects don't match\n");
2494 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2495 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2496 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2497 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2498 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2499 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2501 hrgn = CreateRectRgn(0, 0, 0, 0);
2503 memset(&xform, 0, sizeof(xform));
2504 SetLastError(0xdeadbeef);
2505 ret = GetWorldTransform(hdc, &xform);
2506 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2507 if (!is_win9x)
2508 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2510 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2512 ret = GetClipRgn(hdc, hrgn);
2513 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2515 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2517 ret = GetClipRgn(hdc, hrgn);
2518 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2520 /* Win9x returns empty clipping region */
2521 if (is_win9x) return 1;
2523 ret = GetRegionData(hrgn, 0, NULL);
2524 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2526 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2527 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2529 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2530 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2531 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2532 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2533 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2535 rect = rgn2.data.rdh.rcBound;
2536 rc_transformed = *rc;
2537 translate((POINT *)&rc_transformed, 2, &xform);
2538 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2539 rc_transformed.right, rc_transformed.bottom);
2540 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2542 rect = *(const RECT *)rgn2.data.Buffer;
2543 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2544 rc_transformed = *rc;
2545 translate((POINT *)&rc_transformed, 2, &xform);
2546 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2547 rc_transformed.right, rc_transformed.bottom);
2548 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2550 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2551 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2552 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2553 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2554 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2555 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2557 DeleteObject(hrgn);
2559 return 1;
2562 static void test_emf_clipping(void)
2564 static const RECT rc = { 0, 0, 100, 100 };
2565 RECT rc_clip = { 100, 100, 1024, 1024 };
2566 HWND hwnd;
2567 HDC hdc;
2568 HENHMETAFILE hemf;
2569 HRGN hrgn;
2570 INT ret;
2571 RECT rc_res, rc_sclip;
2573 SetLastError(0xdeadbeef);
2574 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2575 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2577 /* Need to write something to the emf, otherwise Windows won't play it back */
2578 LineTo(hdc, 1, 1);
2580 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2581 ret = SelectClipRgn(hdc, hrgn);
2582 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2584 SetLastError(0xdeadbeef);
2585 hemf = CloseEnhMetaFile(hdc);
2586 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2588 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2589 "emf_clipping", FALSE) != 0)
2591 dump_emf_bits(hemf, "emf_clipping");
2592 dump_emf_records(hemf, "emf_clipping");
2595 DeleteObject(hrgn);
2597 /* Win9x doesn't play EMFs on invisible windows */
2598 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2599 0, 0, 200, 200, 0, 0, 0, NULL);
2600 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2602 hdc = GetDC(hwnd);
2604 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2605 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2607 DeleteEnhMetaFile(hemf);
2608 ReleaseDC(hwnd, hdc);
2609 DestroyWindow(hwnd);
2611 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2613 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2614 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2615 SelectClipRgn(hdc, hrgn);
2616 SetRect(&rc_res, -1, -1, -1, -1);
2617 ret = GetClipBox(hdc, &rc_res);
2618 ok(ret == SIMPLEREGION, "got %d\n", ret);
2619 ok(EqualRect(&rc_res, &rc_sclip),
2620 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2621 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2622 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2624 OffsetRect(&rc_sclip, -100, -100);
2625 ret = OffsetClipRgn(hdc, -100, -100);
2626 ok(ret == SIMPLEREGION, "got %d\n", ret);
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 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2636 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2637 if (ret == COMPLEXREGION)
2639 /* XP returns COMPLEXREGION although region contains only 1 rect */
2640 ret = GetClipRgn(hdc, hrgn);
2641 ok(ret == 1, "expected 1, got %d\n", ret);
2642 ret = rgn_rect_count(hrgn);
2643 ok(ret == 1, "expected 1, got %d\n", ret);
2645 SetRect(&rc_res, -1, -1, -1, -1);
2646 ret = GetClipBox(hdc, &rc_res);
2647 ok(ret == SIMPLEREGION, "got %d\n", ret);
2648 ok(EqualRect(&rc_res, &rc),
2649 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2650 rc.left, rc.top, rc.right, rc.bottom,
2651 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2653 SetRect(&rc_sclip, 0, 0, 100, 50);
2654 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2655 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2656 if (ret == COMPLEXREGION)
2658 /* XP returns COMPLEXREGION although region contains only 1 rect */
2659 ret = GetClipRgn(hdc, hrgn);
2660 ok(ret == 1, "expected 1, got %d\n", ret);
2661 ret = rgn_rect_count(hrgn);
2662 ok(ret == 1, "expected 1, got %d\n", ret);
2664 SetRect(&rc_res, -1, -1, -1, -1);
2665 ret = GetClipBox(hdc, &rc_res);
2666 ok(ret == SIMPLEREGION, "got %d\n", ret);
2667 ok(EqualRect(&rc_res, &rc_sclip),
2668 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2669 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2670 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2672 hemf = CloseEnhMetaFile(hdc);
2673 DeleteEnhMetaFile(hemf);
2674 DeleteObject(hrgn);
2677 static const unsigned char MF_CLIP_BITS[] = {
2678 /* METAHEADER */
2679 0x01, 0x00, /* mtType */
2680 0x09, 0x00, /* mtHeaderSize */
2681 0x00, 0x03, /* mtVersion */
2682 0x32, 0x00, 0x00, 0x00, /* mtSize */
2683 0x01, 0x00, /* mtNoObjects */
2684 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2685 0x00, 0x00, /* reserved */
2687 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2688 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2689 0xff, 0x06, /* META_CREATEREGION */
2690 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2691 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2692 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2693 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2694 0x02, 0x00,
2696 /* METARECORD for SelectObject */
2697 0x04, 0x00, 0x00, 0x00,
2698 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2699 0x00, 0x00,
2701 /* METARECORD */
2702 0x04, 0x00, 0x00, 0x00,
2703 0xf0, 0x01, /* META_DELETEOBJECT */
2704 0x00, 0x00,
2706 /* METARECORD for MoveTo(1,0x30) */
2707 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2708 0x14, 0x02, /* META_MOVETO */
2709 0x30, 0x00, /* y */
2710 0x01, 0x00, /* x */
2712 /* METARECORD for LineTo(0x20, 0x30) */
2713 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2714 0x13, 0x02, /* META_LINETO */
2715 0x30, 0x00, /* y */
2716 0x20, 0x00, /* x */
2718 /* EOF */
2719 0x03, 0x00, 0x00, 0x00,
2720 0x00, 0x00
2723 static int clip_mf_enum_proc_seen_selectclipregion;
2724 static int clip_mf_enum_proc_seen_selectobject;
2726 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2727 METARECORD *mr, int n_objs, LPARAM param)
2729 switch (mr->rdFunction) {
2730 case META_SELECTCLIPREGION:
2731 clip_mf_enum_proc_seen_selectclipregion++;
2732 break;
2733 case META_SELECTOBJECT:
2734 clip_mf_enum_proc_seen_selectobject++;
2735 break;
2737 return 1;
2740 static void test_mf_clipping(void)
2742 /* left top right bottom */
2743 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2744 HWND hwnd;
2745 HDC hdc;
2746 HMETAFILE hmf;
2747 HRGN hrgn;
2748 INT ret;
2750 SetLastError(0xdeadbeef);
2751 hdc = CreateMetaFileA(NULL);
2752 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2754 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2755 ret = SelectClipRgn(hdc, hrgn);
2756 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2757 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2759 /* Draw a line that starts off left of the clip region and ends inside it */
2760 MoveToEx(hdc, 0x1, 0x30, NULL);
2761 LineTo(hdc, 0x20, 0x30);
2763 SetLastError(0xdeadbeef);
2764 hmf = CloseMetaFile(hdc);
2765 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2767 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2768 "mf_clipping") != 0)
2770 dump_mf_bits(hmf, "mf_clipping");
2773 DeleteObject(hrgn);
2775 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2776 0, 0, 200, 200, 0, 0, 0, NULL);
2777 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2779 hdc = GetDC(hwnd);
2781 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2782 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2784 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2785 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2786 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2787 ok(clip_mf_enum_proc_seen_selectobject == 1,
2788 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2790 DeleteMetaFile(hmf);
2791 ReleaseDC(hwnd, hdc);
2792 DestroyWindow(hwnd);
2795 static const unsigned char MF_PATH_BITS[] =
2797 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2798 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2799 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2800 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2801 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2802 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2803 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2804 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2805 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2806 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2807 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2810 static void test_mf_GetPath(void)
2812 HDC hdc;
2813 HMETAFILE hmf;
2814 BOOL ret;
2815 int size;
2817 SetLastError(0xdeadbeef);
2818 hdc = CreateMetaFileA(NULL);
2819 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2821 BeginPath(hdc);
2822 ret = MoveToEx(hdc, 50, 50, NULL);
2823 ok( ret, "MoveToEx error %d.\n", GetLastError());
2824 ret = LineTo(hdc, 50, 150);
2825 ok( ret, "LineTo error %d.\n", GetLastError());
2826 ret = LineTo(hdc, 150, 150);
2827 ok( ret, "LineTo error %d.\n", GetLastError());
2828 ret = LineTo(hdc, 150, 50);
2829 ok( ret, "LineTo error %d.\n", GetLastError());
2830 ret = LineTo(hdc, 50, 50);
2831 ok( ret, "LineTo error %d.\n", GetLastError());
2832 Rectangle(hdc, 10, 10, 20, 20);
2833 EndPath(hdc);
2835 size = GetPath(hdc, NULL, NULL, 0);
2836 ok( size == -1, "GetPath returned %d.\n", size);
2838 hmf = CloseMetaFile(hdc);
2839 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2841 if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
2843 dump_mf_bits(hmf, "mf_GetPath");
2844 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2847 ret = DeleteMetaFile(hmf);
2848 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2851 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2853 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2854 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2855 /* When using MM_TEXT Win9x does not update the mapping mode
2856 * until a record is played which actually outputs something */
2857 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2858 LPtoDP(hdc, mapping, 2);
2859 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2860 lpEMFR->iType, lpEMFR->nSize,
2861 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2863 if (lpEMFR->iType == EMR_LINETO)
2865 INT x0, y0, x1, y1;
2866 if (!lpMFP || lpMFP->mm == MM_TEXT)
2868 x0 = 0;
2869 y0 = 0;
2870 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2871 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2873 else
2875 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2877 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2878 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2879 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2880 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2882 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2883 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2884 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2885 x0, y0, x1, y1);
2887 return TRUE;
2890 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2892 HDC hdcMf;
2893 HMETAFILE hmf;
2894 HENHMETAFILE hemf;
2895 BOOL ret;
2896 UINT size;
2897 LPBYTE pBits;
2899 hdcMf = CreateMetaFileA(NULL);
2900 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2901 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2902 ok(ret, "LineTo failed with error %d\n", GetLastError());
2903 hmf = CloseMetaFile(hdcMf);
2904 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2906 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2908 dump_mf_bits(hmf, "mf_LineTo");
2909 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2912 size = GetMetaFileBitsEx(hmf, 0, NULL);
2913 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2914 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2915 GetMetaFileBitsEx(hmf, size, pBits);
2916 DeleteMetaFile(hmf);
2917 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2918 HeapFree(GetProcessHeap(), 0, pBits);
2919 return hemf;
2922 static void test_mf_conversions(void)
2924 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2926 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2927 HENHMETAFILE hemf;
2928 METAFILEPICT mfp;
2929 RECT rect = { 0, 0, 100, 100 };
2930 mfp.mm = MM_ANISOTROPIC;
2931 mfp.xExt = 100;
2932 mfp.yExt = 100;
2933 mfp.hMF = NULL;
2934 hemf = create_converted_emf(&mfp);
2936 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2937 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2939 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2940 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2943 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2945 DeleteEnhMetaFile(hemf);
2946 DeleteDC(hdcOffscreen);
2949 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2951 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2952 HENHMETAFILE hemf;
2953 METAFILEPICT mfp;
2954 RECT rect = { 0, 0, 100, 100 };
2955 mfp.mm = MM_TEXT;
2956 mfp.xExt = 0;
2957 mfp.yExt = 0;
2958 mfp.hMF = NULL;
2959 hemf = create_converted_emf(&mfp);
2961 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2962 "emf_LineTo MM_TEXT", TRUE) != 0)
2964 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2965 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2968 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2970 DeleteEnhMetaFile(hemf);
2971 DeleteDC(hdcOffscreen);
2974 trace("Testing MF->EMF conversion (NULL mfp)\n");
2976 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2977 HENHMETAFILE hemf;
2978 RECT rect = { 0, 0, 100, 100 };
2979 hemf = create_converted_emf(NULL);
2981 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2982 "emf_LineTo NULL", TRUE) != 0)
2984 dump_emf_bits(hemf, "emf_LineTo NULL");
2985 dump_emf_records(hemf, "emf_LineTo NULL");
2988 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2990 DeleteEnhMetaFile(hemf);
2991 DeleteDC(hdcOffscreen);
2995 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2996 LONG mm, LONG xExt, LONG yExt,
2997 RECTL * rclBounds, RECTL * rclFrame)
2999 METAFILEPICT mfp;
3000 METAFILEPICT * mfpPtr = NULL;
3001 HENHMETAFILE emf;
3002 ENHMETAHEADER header;
3003 UINT res;
3005 if (!mfpIsNull)
3007 mfp.mm = mm;
3008 mfp.xExt = xExt;
3009 mfp.yExt = yExt;
3010 mfpPtr = &mfp;
3013 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
3014 ok(emf != NULL, "SetWinMetaFileBits failed\n");
3015 if (!emf) return FALSE;
3016 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
3017 ok(res != 0, "GetEnhMetaHeader failed\n");
3018 DeleteEnhMetaFile(emf);
3019 if (!res) return FALSE;
3021 *rclBounds = header.rclBounds;
3022 *rclFrame = header.rclFrame;
3023 return TRUE;
3026 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3027 LONG mm, LONG xExt, LONG yExt,
3028 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
3030 RECTL rclBounds, rclFrame;
3032 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
3034 const char * msg;
3035 char buf[64];
3037 if (mfpIsNull)
3039 msg = "mfp == NULL";
3041 else
3043 const char * mm_str;
3044 switch (mm)
3046 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
3047 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
3048 default: mm_str = "Unexpected";
3050 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
3051 msg = buf;
3054 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
3055 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
3056 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
3057 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
3058 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
3059 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
3060 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
3061 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
3065 static void test_SetWinMetaFileBits(void)
3067 HMETAFILE wmf;
3068 HDC wmfDC;
3069 BYTE * buffer;
3070 UINT buffer_size;
3071 RECT rect;
3072 UINT res;
3073 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
3074 RECTL rclBoundsIsotropic, rclFrameIsotropic;
3075 RECTL rclBounds, rclFrame;
3076 HDC dc;
3077 LONG diffx, diffy;
3079 wmfDC = CreateMetaFileA(NULL);
3080 ok(wmfDC != NULL, "CreateMetaFile failed\n");
3081 if (!wmfDC) return;
3083 SetWindowExtEx(wmfDC, 100, 100, NULL);
3084 rect.left = rect.top = 0;
3085 rect.right = rect.bottom = 50;
3086 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
3087 wmf = CloseMetaFile(wmfDC);
3088 ok(wmf != NULL, "Metafile creation failed\n");
3089 if (!wmf) return;
3091 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
3092 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
3093 if (buffer_size == 0)
3095 DeleteMetaFile(wmf);
3096 return;
3099 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
3100 ok(buffer != NULL, "HeapAlloc failed\n");
3101 if (!buffer)
3103 DeleteMetaFile(wmf);
3104 return;
3107 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
3108 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3109 DeleteMetaFile(wmf);
3110 if (res != buffer_size)
3112 HeapFree(GetProcessHeap(), 0, buffer);
3113 return;
3116 /* Get the reference bounds and frame */
3117 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3118 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3120 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
3121 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
3122 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3124 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3125 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3126 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
3127 if (diffx < 0) diffx = -diffx;
3128 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3130 dc = CreateCompatibleDC(NULL);
3132 /* Allow 1 mm difference (rounding errors) */
3133 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
3134 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
3135 if (diffx < 0) diffx = -diffx;
3136 if (diffy < 0) diffy = -diffy;
3137 todo_wine
3139 ok(diffx <= 1 && diffy <= 1,
3140 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3141 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
3144 /* Allow 1 mm difference (rounding errors) */
3145 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
3146 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
3147 if (diffx < 0) diffx = -diffx;
3148 if (diffy < 0) diffy = -diffy;
3149 todo_wine
3151 ok(diffx <= 1 && diffy <= 1,
3152 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3153 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
3155 DeleteDC(dc);
3157 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3158 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3160 /* If xExt or yExt is zero or negative, the whole device surface is used */
3161 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3162 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3163 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3164 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3165 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3166 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3167 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3168 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3169 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3170 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3171 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3172 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3174 /* MSDN says that negative xExt and yExt values specify a ratio.
3175 Check that this is wrong and the whole device surface is used */
3176 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3177 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3179 /* Ordinary conversions */
3181 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3183 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3184 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3185 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3186 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3189 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3191 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3192 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3193 ok(rclBounds.left == 0 && rclBounds.top == 0,
3194 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3196 /* Wine has a rounding error */
3197 diffx = rclBounds.right - rclBounds.bottom;
3198 if (diffx < 0) diffx = -diffx;
3199 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3202 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3204 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3205 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3208 HeapFree(GetProcessHeap(), 0, buffer);
3211 static BOOL near_match(int x, int y)
3213 int epsilon = min(abs(x), abs(y));
3215 epsilon = max(epsilon/100, 2);
3217 if(x < y - epsilon || x > y + epsilon) return FALSE;
3218 return TRUE;
3221 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3223 HENHMETAFILE emf;
3224 HDC display_dc, emf_dc;
3225 ENHMETAHEADER *enh_header;
3226 UINT size, emf_size, i;
3227 WORD check = 0;
3228 DWORD rec_num = 0;
3229 METAHEADER *mh = NULL;
3230 METARECORD *rec;
3231 INT horz_res, vert_res, horz_size, vert_size;
3232 INT curve_caps, line_caps, poly_caps;
3234 display_dc = GetDC(NULL);
3235 ok(display_dc != NULL, "display_dc is NULL\n");
3237 horz_res = GetDeviceCaps(display_dc, HORZRES);
3238 vert_res = GetDeviceCaps(display_dc, VERTRES);
3239 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3240 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3242 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3243 ok(emf_dc != NULL, "emf_dc is NULL\n");
3245 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3246 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3248 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3249 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3251 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3252 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3254 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3255 Rectangle(emf_dc, 0, 0, 1000, 20);
3256 emf = CloseEnhMetaFile(emf_dc);
3257 ok(emf != NULL, "emf is NULL\n");
3259 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3260 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3261 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3262 DeleteEnhMetaFile(emf);
3263 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3264 have different resolutions */
3265 enh_header->szlDevice.cx *= scale;
3266 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3267 ok(emf != NULL, "emf is NULL\n");
3268 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3270 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3271 ok(size ||
3272 broken(size == 0), /* some versions of winxp fail for some reason */
3273 "GetWinMetaFileBits returns 0\n");
3274 if(!size) goto end;
3275 mh = HeapAlloc(GetProcessHeap(), 0, size);
3276 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3278 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3279 ok(check == 0, "check %04x\n", check);
3281 rec = (METARECORD*)(mh + 1);
3283 while(rec->rdSize && rec->rdFunction)
3285 const DWORD chunk_size = 0x2000;
3286 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3288 if(rec_num < mfcomment_chunks)
3290 DWORD this_chunk_size = chunk_size;
3292 if(rec_num == mfcomment_chunks - 1)
3293 this_chunk_size = emf_size - rec_num * chunk_size;
3295 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3296 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3297 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3298 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3299 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3300 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3301 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3302 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3303 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3304 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3305 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3306 /* parm[8] is the checksum, tested above */
3307 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3308 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3309 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3310 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3311 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3312 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3313 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3314 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 */
3315 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3316 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3319 else if(rec_num == mfcomment_chunks)
3321 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3322 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3324 else if(rec_num == mfcomment_chunks + 1)
3326 POINT pt;
3327 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3328 switch(mode)
3330 case MM_TEXT:
3331 case MM_ISOTROPIC:
3332 case MM_ANISOTROPIC:
3333 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3334 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3335 break;
3336 case MM_LOMETRIC:
3337 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3338 pt.x = MulDiv( rc->left, 1, 10);
3339 break;
3340 case MM_HIMETRIC:
3341 pt.y = -rc->top + 1;
3342 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3343 break;
3344 case MM_LOENGLISH:
3345 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3346 pt.x = MulDiv( rc->left, 10, 254);
3347 break;
3348 case MM_HIENGLISH:
3349 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3350 pt.x = MulDiv( rc->left, 100, 254);
3351 break;
3352 case MM_TWIPS:
3353 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3354 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3355 break;
3356 default:
3357 pt.x = pt.y = 0;
3359 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3360 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3362 if(rec_num == mfcomment_chunks + 2)
3364 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3365 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3366 "got %d\n", (short)rec->rdParm[0]);
3367 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3368 "got %d\n", (short)rec->rdParm[1]);
3371 rec_num++;
3372 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3375 end:
3376 HeapFree(GetProcessHeap(), 0, mh);
3377 HeapFree(GetProcessHeap(), 0, enh_header);
3378 DeleteEnhMetaFile(emf);
3380 ReleaseDC(NULL, display_dc);
3383 static void test_GetWinMetaFileBits(void)
3385 UINT mode;
3386 RECT frames[] =
3388 { 1000, 2000, 3000, 6000},
3389 {-1000, 2000, 3000, 6000},
3390 { 1000, -2000, 3000, 6000},
3391 { 1005, 2005, 3000, 6000},
3392 {-1005, -2005, 3000, 6000},
3393 {-1005, -2010, 3000, 6000},
3394 {-1005, 2010, 3000, 6000},
3395 { 0, 0, 1, 1},
3396 { -1, -1, 1, 1},
3397 { 0, 0, 0, 0}
3400 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3402 RECT *rc;
3403 for(rc = frames; rc->right - rc->left > 0; rc++)
3405 getwinmetafilebits(mode, 1, rc);
3406 getwinmetafilebits(mode, 2, rc);
3411 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3412 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3413 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3415 static void test_gdiis(void)
3417 RECT rect = {0,0,100,100};
3418 HDC hdc, hemfDC, hmfDC;
3419 HENHMETAFILE hemf;
3420 HMODULE hgdi32;
3422 /* resolve all the functions */
3423 hgdi32 = GetModuleHandleA("gdi32.dll");
3424 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3425 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3426 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3428 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3430 win_skip("Needed GdiIs* functions are not available\n");
3431 return;
3434 /* try with nothing */
3435 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3436 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3437 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3439 /* try with a metafile */
3440 hmfDC = CreateMetaFileA(NULL);
3441 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3442 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3443 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3444 DeleteMetaFile(CloseMetaFile(hmfDC));
3446 /* try with an enhanced metafile */
3447 hdc = GetDC(NULL);
3448 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3449 ok(hemfDC != NULL, "failed to create emf\n");
3451 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3452 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3453 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3455 hemf = CloseEnhMetaFile(hemfDC);
3456 ok(hemf != NULL, "failed to close EMF\n");
3457 DeleteEnhMetaFile(hemf);
3458 ReleaseDC(NULL,hdc);
3461 static void test_SetEnhMetaFileBits(void)
3463 BYTE data[256];
3464 HENHMETAFILE hemf;
3465 ENHMETAHEADER *emh;
3467 memset(data, 0xAA, sizeof(data));
3468 SetLastError(0xdeadbeef);
3469 hemf = SetEnhMetaFileBits(sizeof(data), data);
3470 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3471 ok(GetLastError() == ERROR_INVALID_DATA ||
3472 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3473 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3475 emh = (ENHMETAHEADER *)data;
3476 memset(emh, 0, sizeof(*emh));
3478 emh->iType = EMR_HEADER;
3479 emh->nSize = sizeof(*emh);
3480 emh->dSignature = ENHMETA_SIGNATURE;
3481 /* emh->nVersion = 0x10000; XP doesn't care about version */
3482 emh->nBytes = sizeof(*emh);
3483 /* emh->nRecords = 1; XP doesn't care about records */
3484 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3486 SetLastError(0xdeadbeef);
3487 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3488 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3489 DeleteEnhMetaFile(hemf);
3491 /* XP refuses to load unaligned EMF */
3492 emh->nBytes++;
3493 SetLastError(0xdeadbeef);
3494 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3495 ok(!hemf ||
3496 broken(hemf != NULL), /* Win9x, WinMe */
3497 "SetEnhMetaFileBits should fail\n");
3498 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3499 DeleteEnhMetaFile(hemf);
3501 emh->dSignature = 0;
3502 emh->nBytes--;
3503 SetLastError(0xdeadbeef);
3504 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3505 ok(!hemf ||
3506 broken(hemf != NULL), /* Win9x, WinMe */
3507 "SetEnhMetaFileBits should fail\n");
3508 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3509 DeleteEnhMetaFile(hemf);
3512 static void test_emf_polybezier(void)
3514 HDC hdcMetafile;
3515 HENHMETAFILE hemf;
3516 POINT pts[4];
3517 BOOL ret;
3519 SetLastError(0xdeadbeef);
3520 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3521 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3523 pts[0].x = pts[0].y = 10;
3524 pts[1].x = pts[1].y = 20;
3525 pts[2].x = pts[2].y = 15;
3526 pts[3].x = pts[3].y = 25;
3527 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3528 ok( ret, "PolyBezierTo failed\n" );
3529 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3530 ok( ret, "PolyBezier failed\n" );
3532 pts[0].x = pts[0].y = 32769;
3533 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3534 ok( ret, "PolyBezier failed\n" );
3535 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3536 ok( ret, "PolyBezierTo failed\n" );
3538 hemf = CloseEnhMetaFile(hdcMetafile);
3539 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3541 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3542 "emf_Bezier", FALSE) != 0)
3544 dump_emf_bits(hemf, "emf_Bezier");
3545 dump_emf_records(hemf, "emf_Bezier");
3548 DeleteEnhMetaFile(hemf);
3551 static const unsigned char EMF_PATH_BITS[] =
3553 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3555 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3557 0xe6, 0xff, 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff,
3558 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3559 0xf8, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3560 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3562 0x80, 0x07, 0x00, 0x00, 0xd3, 0x03, 0x00, 0x00,
3563 0xfc, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00,
3564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3565 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
3566 0xd3, 0xf3, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3567 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3568 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3569 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3570 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3571 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3572 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3573 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3574 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3575 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3576 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3577 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3578 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3579 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3580 0x13, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3581 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3582 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3583 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3586 static void test_emf_GetPath(void)
3588 HDC hdcMetafile;
3589 HENHMETAFILE hemf;
3590 BOOL ret;
3591 int size;
3593 SetLastError(0xdeadbeef);
3594 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3595 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3597 BeginPath(hdcMetafile);
3598 ret = MoveToEx(hdcMetafile, 50, 50, NULL);
3599 ok( ret, "MoveToEx error %d.\n", GetLastError());
3600 ret = LineTo(hdcMetafile, 50, 150);
3601 ok( ret, "LineTo error %d.\n", GetLastError());
3602 ret = LineTo(hdcMetafile, 150, 150);
3603 ok( ret, "LineTo error %d.\n", GetLastError());
3604 ret = LineTo(hdcMetafile, 150, 50);
3605 ok( ret, "LineTo error %d.\n", GetLastError());
3606 ret = LineTo(hdcMetafile, 50, 50);
3607 ok( ret, "LineTo error %d.\n", GetLastError());
3608 Rectangle(hdcMetafile, 10, 10, 20, 20);
3609 EndPath(hdcMetafile);
3611 size = GetPath(hdcMetafile, NULL, NULL, 0);
3612 todo_wine ok( size == 9, "GetPath returned %d.\n", size);
3614 hemf = CloseEnhMetaFile(hdcMetafile);
3615 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3617 if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_GetPath", FALSE) != 0)
3619 dump_emf_bits(hemf, "test_emf_GetPath");
3620 dump_emf_records(hemf, "test_emf_GetPath");
3623 DeleteEnhMetaFile(hemf);
3626 static void test_emf_PolyPolyline(void)
3628 HDC hdcMetafile;
3629 HENHMETAFILE hemf;
3630 POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3631 DWORD counts[2];
3632 BOOL ret;
3634 SetLastError(0xdeadbeef);
3635 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3636 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3638 ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
3639 ok( !ret, "PolyPolyline\n" );
3641 SetLastError( 0xdeadbeef );
3642 counts[0] = 0;
3643 counts[1] = 1;
3644 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3645 ok( !ret, "PolyPolyline\n" );
3646 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3648 SetLastError( 0xdeadbeef );
3649 counts[0] = 1;
3650 counts[1] = 1;
3651 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3652 ok( !ret, "PolyPolyline\n" );
3653 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3655 SetLastError( 0xdeadbeef );
3656 counts[0] = 2;
3657 counts[1] = 1;
3658 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3659 ok( !ret, "PolyPolyline\n" );
3660 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3662 counts[0] = 2;
3663 counts[1] = 2;
3664 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3665 ok( ret, "PolyPolyline\n" );
3667 hemf = CloseEnhMetaFile(hdcMetafile);
3668 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3670 if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
3671 "emf_PolyPolyline", FALSE) != 0)
3673 dump_emf_bits(hemf, "emf_PolyPolyline");
3674 dump_emf_records(hemf, "emf_PolyPolyline");
3677 DeleteEnhMetaFile(hemf);
3680 static void test_emf_GradientFill(void)
3682 HDC mf;
3683 HENHMETAFILE hemf;
3684 TRIVERTEX v[] =
3686 { 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
3687 { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
3688 { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
3689 { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
3690 { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
3692 GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
3693 BOOL ret;
3695 mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
3696 ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
3698 /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
3699 * means it allocates three mesh indices rather than two per
3700 * rectangle. This results in uninitialised values being written
3701 * to the EMF which is rather difficult to test against.
3703 * Note also that the final vertex here is not required, yet it is
3704 * written to the EMF, but is not considered in the bounds
3705 * calculation.
3707 ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
3708 GRADIENT_FILL_TRIANGLE );
3709 ok( ret, "GradientFill\n" );
3711 hemf = CloseEnhMetaFile( mf );
3712 ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
3714 if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
3715 "emf_GradientFill", FALSE ) != 0)
3717 dump_emf_bits( hemf, "emf_GradientFill" );
3718 dump_emf_records( hemf, "emf_GradientFill" );
3721 DeleteEnhMetaFile( hemf );
3724 START_TEST(metafile)
3726 init_function_pointers();
3728 /* For enhanced metafiles (enhmfdrv) */
3729 test_ExtTextOut();
3730 test_ExtTextOutScale();
3731 test_SaveDC();
3732 test_emf_BitBlt();
3733 test_emf_DCBrush();
3734 test_emf_ExtTextOut_on_path();
3735 test_emf_clipping();
3736 test_emf_polybezier();
3737 test_emf_GetPath();
3738 test_emf_PolyPolyline();
3739 test_emf_GradientFill();
3741 /* For win-format metafiles (mfdrv) */
3742 test_mf_SaveDC();
3743 test_mf_Blank();
3744 test_mf_Graphics();
3745 test_mf_PatternBrush();
3746 test_mf_DCBrush();
3747 test_CopyMetaFile();
3748 test_SetMetaFileBits();
3749 test_mf_ExtTextOut_on_path();
3750 test_mf_clipping();
3751 test_mf_GetPath();
3753 /* For metafile conversions */
3754 test_mf_conversions();
3755 test_SetWinMetaFileBits();
3756 test_GetWinMetaFileBits();
3758 test_gdiis();
3759 test_SetEnhMetaFileBits();