winex11: Create contexts at initialization time to avoid the need for locks.
[wine/multimedia.git] / dlls / gdi32 / tests / metafile.c
blobe6bab5d04d2af0fb04dd442b57267c9a46c702e0
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 int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
64 const ENHMETARECORD *emr, int n_objs, LPARAM param)
66 static int n_record;
67 DWORD i;
68 const INT *dx;
69 INT *orig_dx = (INT *)param;
70 LOGFONTA device_lf;
71 INT ret;
73 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
74 hdc, emr->iType, emr->nSize, (void *)param);
76 if(!hdc) return 1;
78 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
80 switch (emr->iType)
82 case EMR_HEADER:
83 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
84 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
85 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
86 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
87 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
88 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
89 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
91 /* GetBkMode, GetRelAbs do not get reset to the default value */
92 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
93 if(pSetRelAbs && pGetRelAbs)
94 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
96 n_record = 0;
97 break;
99 case EMR_EXTTEXTOUTA:
101 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
102 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
104 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
105 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
107 /* compare up to lfOutPrecision, other values are not interesting,
108 * and in fact sometimes arbitrary adapted by Win9x.
110 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
111 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
113 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
115 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
116 n_record, i, dx[i], orig_dx[i]);
118 n_record++;
119 emr_processed = TRUE;
120 break;
123 case EMR_EXTTEXTOUTW:
125 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
126 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
128 SetLastError(0xdeadbeef);
129 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
130 ok( ret == sizeof(device_lf) ||
131 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
132 "GetObjectA error %d\n", GetLastError());
134 /* compare up to lfOutPrecision, other values are not interesting,
135 * and in fact sometimes arbitrary adapted by Win9x.
137 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
138 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
140 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
142 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
143 n_record, i, dx[i], orig_dx[i]);
145 n_record++;
146 emr_processed = TRUE;
147 break;
150 default:
151 break;
154 return 1;
157 static void test_ExtTextOut(void)
159 HWND hwnd;
160 HDC hdcDisplay, hdcMetafile;
161 HENHMETAFILE hMetafile;
162 HFONT hFont;
163 static const char text[] = "Simple text to test ExtTextOut on metafiles";
164 INT i, len, dx[256];
165 static const RECT rc = { 0, 0, 100, 100 };
166 BOOL ret;
168 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
170 /* Win9x doesn't play EMFs on invisible windows */
171 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
172 0, 0, 200, 200, 0, 0, 0, NULL);
173 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
175 hdcDisplay = GetDC(hwnd);
176 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
178 trace("hdcDisplay %p\n", hdcDisplay);
180 SetMapMode(hdcDisplay, MM_TEXT);
182 memset(&orig_lf, 0, sizeof(orig_lf));
184 orig_lf.lfCharSet = ANSI_CHARSET;
185 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
186 orig_lf.lfWeight = FW_DONTCARE;
187 orig_lf.lfHeight = 7;
188 orig_lf.lfQuality = DEFAULT_QUALITY;
189 lstrcpyA(orig_lf.lfFaceName, "Arial");
190 hFont = CreateFontIndirectA(&orig_lf);
191 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
193 hFont = SelectObject(hdcDisplay, hFont);
195 len = lstrlenA(text);
196 for (i = 0; i < len; i++)
198 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
199 ok( ret, "GetCharWidthA error %d\n", GetLastError());
201 hFont = SelectObject(hdcDisplay, hFont);
203 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
204 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
206 trace("hdcMetafile %p\n", hdcMetafile);
208 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
209 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
211 hFont = SelectObject(hdcMetafile, hFont);
213 /* 1. pass NULL lpDx */
214 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
215 ok( ret, "ExtTextOutA error %d\n", GetLastError());
217 /* 2. pass custom lpDx */
218 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
219 ok( ret, "ExtTextOutA error %d\n", GetLastError());
221 hFont = SelectObject(hdcMetafile, hFont);
222 ret = DeleteObject(hFont);
223 ok( ret, "DeleteObject error %d\n", GetLastError());
225 hMetafile = CloseEnhMetaFile(hdcMetafile);
226 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
228 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
230 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
231 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
233 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
234 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
235 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
236 SetROP2(hdcDisplay, R2_NOT);
237 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
238 SetPolyFillMode(hdcDisplay, WINDING);
239 SetStretchBltMode(hdcDisplay, HALFTONE);
241 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
242 SetBkMode(hdcDisplay, OPAQUE);
244 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
245 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
247 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
248 "text align %08x\n", GetTextAlign(hdcDisplay));
249 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
250 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
251 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
252 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
253 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
254 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
256 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
258 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
259 "A valid hdc has to require a valid rc\n");
261 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
262 "A null hdc does not require a valid rc\n");
264 ret = DeleteEnhMetaFile(hMetafile);
265 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
266 ret = ReleaseDC(hwnd, hdcDisplay);
267 ok( ret, "ReleaseDC error %d\n", GetLastError());
268 DestroyWindow(hwnd);
271 struct eto_scale_test_record
273 INT graphics_mode;
274 INT map_mode;
275 double ex_scale;
276 double ey_scale;
277 BOOL processed;
280 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
281 const ENHMETARECORD *emr, int n_objs, LPARAM param)
283 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
285 if (emr->iType == EMR_EXTTEXTOUTW)
287 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
288 trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
289 test->graphics_mode, test->map_mode,
290 pExtTextOutW->exScale, pExtTextOutW->eyScale,
291 test->ex_scale, test->ey_scale);
292 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
293 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
294 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
295 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
296 test->processed = TRUE;
299 return 1;
302 static void test_ExtTextOutScale(void)
304 const RECT rc = { 0, 0, 100, 100 };
305 const WCHAR str[] = {'a',0 };
306 struct eto_scale_test_record test;
307 HDC hdcDisplay, hdcMetafile;
308 HENHMETAFILE hMetafile;
309 HWND hwnd;
310 SIZE wndext, vportext;
311 int horzSize, vertSize, horzRes, vertRes;
312 int ret;
313 int i;
315 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
316 0, 0, 200, 200, 0, 0, 0, NULL);
317 ok(hwnd != 0, "CreateWindowExA failed\n");
319 hdcDisplay = GetDC(hwnd);
320 ok(hdcDisplay != 0, "GetDC failed\n");
322 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
323 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
324 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
325 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
326 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
328 for (i = 0; i < 16; i++)
330 test.graphics_mode = i / 8 + 1;
331 test.map_mode = i % 8 + 1;
333 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
334 ok(ret, "SetGraphicsMode failed\n");
335 ret = SetMapMode(hdcDisplay, test.map_mode);
336 ok(ret, "SetMapMode failed\n");
338 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
340 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
341 ok(ret, "SetWindowExtEx failed\n");
342 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
343 ok(ret, "SetViewportExtEx failed\n");
346 ret = GetViewportExtEx(hdcDisplay, &vportext);
347 ok(ret, "GetViewportExtEx failed\n");
348 ret = GetWindowExtEx(hdcDisplay, &wndext);
349 ok(ret, "GetWindowExtEx failed\n");
351 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
352 test.graphics_mode, test.map_mode,
353 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
354 horzSize, horzRes, vertSize, vertRes);
356 if (test.graphics_mode == GM_COMPATIBLE)
358 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
359 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
360 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
361 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
363 else
365 test.ex_scale = 0.0;
366 test.ey_scale = 0.0;
369 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
370 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
372 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
373 ok(ret, "SetGraphicsMode failed\n");
374 ret = SetMapMode(hdcMetafile, test.map_mode);
375 ok(ret, "SetMapMode failed\n");
377 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
379 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
380 ok(ret, "SetWindowExtEx failed\n");
381 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
382 ok(ret, "SetViewportExtEx failed\n");
385 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
386 ok(ret, "ExtTextOutW failed\n");
388 hMetafile = CloseEnhMetaFile(hdcMetafile);
389 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
391 test.processed = 0;
392 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
393 ok(ret, "EnumEnhMetaFile failed\n");
394 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
396 ret = DeleteEnhMetaFile(hMetafile);
397 ok(ret, "DeleteEnhMetaFile failed\n");
400 ret = ReleaseDC(hwnd, hdcDisplay);
401 ok(ret, "ReleaseDC failed\n");
402 DestroyWindow(hwnd);
406 static void check_dc_state(HDC hdc, int restore_no,
407 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
408 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
410 BOOL ret;
411 XFORM xform;
412 POINT vp_org, win_org;
413 SIZE vp_size, win_size;
414 FLOAT xscale, yscale, edx, edy;
416 SetLastError(0xdeadbeef);
417 ret = GetWorldTransform(hdc, &xform);
418 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
419 ok(ret, "GetWorldTransform error %u\n", GetLastError());
421 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
423 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
424 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
426 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
427 trace("x scale %f\n", xscale);
428 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
429 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
431 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
432 trace("y scale %f\n", yscale);
433 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
434 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
436 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
437 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
438 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
439 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
441 return;
443 win9x_here:
445 GetWindowOrgEx(hdc, &win_org);
446 GetViewportOrgEx(hdc, &vp_org);
447 GetWindowExtEx(hdc, &win_size);
448 GetViewportExtEx(hdc, &vp_size);
450 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
451 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
453 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
454 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
456 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
457 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
459 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
460 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
463 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
464 const ENHMETARECORD *emr, int n_objs, LPARAM param)
466 BOOL ret;
467 XFORM xform;
468 POINT pt;
469 SIZE size;
470 static int save_state;
471 static int restore_no;
472 static int select_no;
474 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
475 hdc, emr->iType, emr->nSize, (void *)param);
477 trace("BEFORE:\n");
478 SetLastError(0xdeadbeef);
479 ret = GetWorldTransform(hdc, &xform);
480 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
482 ret = GetWindowOrgEx(hdc, &pt);
483 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
484 trace("window org (%d,%d)\n", pt.x, pt.y);
485 ret = GetViewportOrgEx(hdc, &pt);
486 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
487 trace("vport org (%d,%d)\n", pt.x, pt.y);
488 ret = GetWindowExtEx(hdc, &size);
489 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
490 trace("window ext (%d,%d)\n", size.cx, size.cy);
491 ret = GetViewportExtEx(hdc, &size);
492 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
493 trace("vport ext (%d,%d)\n", size.cx, size.cy);
495 else
497 ok(ret, "GetWorldTransform error %u\n", GetLastError());
498 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
501 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
503 switch (emr->iType)
505 case EMR_HEADER:
507 static RECT exp_bounds = { 0, 0, 150, 150 };
508 RECT bounds;
509 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
511 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
512 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
513 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
514 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
515 emf->szlDevice.cx, emf->szlDevice.cy);
517 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
518 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
520 save_state = 0;
521 restore_no = 0;
522 select_no = 0;
523 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
524 break;
527 case EMR_LINETO:
529 const EMRLINETO *line = (const EMRLINETO *)emr;
530 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
531 break;
533 case EMR_SETWINDOWORGEX:
535 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
536 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
537 break;
539 case EMR_SETWINDOWEXTEX:
541 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
542 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
543 break;
545 case EMR_SETVIEWPORTORGEX:
547 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
548 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
549 break;
551 case EMR_SETVIEWPORTEXTEX:
553 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
554 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
555 break;
557 case EMR_SAVEDC:
558 save_state++;
559 trace("EMR_SAVEDC\n");
560 break;
562 case EMR_RESTOREDC:
564 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
565 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
567 switch(++restore_no)
569 case 1:
570 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
571 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
572 break;
573 case 2:
574 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
575 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
576 break;
577 case 3:
578 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
579 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
580 break;
582 ok(restore_no <= 3, "restore_no %d\n", restore_no);
583 save_state += restoredc->iRelative;
584 break;
586 case EMR_SELECTOBJECT:
588 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
589 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
590 select_no ++;
591 break;
593 case EMR_EOF:
594 ok(save_state == 0, "EOF save_state %d\n", save_state);
595 ok(select_no == 3, "Too many/few selects %i\n",select_no);
596 break;
599 trace("AFTER:\n");
600 SetLastError(0xdeadbeef);
601 ret = GetWorldTransform(hdc, &xform);
602 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
604 ret = GetWindowOrgEx(hdc, &pt);
605 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
606 trace("window org (%d,%d)\n", pt.x, pt.y);
607 ret = GetViewportOrgEx(hdc, &pt);
608 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
609 trace("vport org (%d,%d)\n", pt.x, pt.y);
610 ret = GetWindowExtEx(hdc, &size);
611 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
612 trace("window ext (%d,%d)\n", size.cx, size.cy);
613 ret = GetViewportExtEx(hdc, &size);
614 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
615 trace("vport ext (%d,%d)\n", size.cx, size.cy);
617 else
619 ok(ret, "GetWorldTransform error %u\n", GetLastError());
620 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
623 return 1;
626 static void test_SaveDC(void)
628 HDC hdcMetafile, hdcDisplay;
629 HENHMETAFILE hMetafile;
630 HWND hwnd;
631 int ret;
632 POINT pt;
633 SIZE size;
634 HFONT hFont,hFont2,hFontOld,hFontCheck;
635 static const RECT rc = { 0, 0, 150, 150 };
637 /* Win9x doesn't play EMFs on invisible windows */
638 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
639 0, 0, 200, 200, 0, 0, 0, NULL);
640 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
642 hdcDisplay = GetDC(hwnd);
643 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
645 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
646 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
648 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
650 /* Need to write something to the emf, otherwise Windows won't play it back */
651 LineTo(hdcMetafile, 150, 150);
653 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
654 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
655 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
656 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
658 /* Force Win9x to update DC state */
659 SetPixelV(hdcMetafile, 50, 50, 0);
661 ret = GetViewportOrgEx(hdcMetafile, &pt);
662 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
663 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
664 ret = GetViewportExtEx(hdcMetafile, &size);
665 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
666 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
667 ret = SaveDC(hdcMetafile);
668 ok(ret == 1, "ret = %d\n", ret);
670 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
671 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
672 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
673 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
675 /* Force Win9x to update DC state */
676 SetPixelV(hdcMetafile, 50, 50, 0);
678 ret = GetViewportOrgEx(hdcMetafile, &pt);
679 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
680 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
681 ret = GetViewportExtEx(hdcMetafile, &size);
682 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
683 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
684 ret = SaveDC(hdcMetafile);
685 ok(ret == 2, "ret = %d\n", ret);
687 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
688 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
689 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
690 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
691 SetPolyFillMode( hdcMetafile, ALTERNATE );
692 SetBkColor( hdcMetafile, 0 );
694 /* Force Win9x to update DC state */
695 SetPixelV(hdcMetafile, 50, 50, 0);
697 ret = GetViewportOrgEx(hdcMetafile, &pt);
698 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
699 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
700 ret = GetViewportExtEx(hdcMetafile, &size);
701 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
702 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
703 ret = SaveDC(hdcMetafile);
704 ok(ret == 3, "ret = %d\n", ret);
706 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
707 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
708 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
709 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
711 SetPolyFillMode( hdcMetafile, WINDING );
712 SetBkColor( hdcMetafile, 0x123456 );
713 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
714 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
716 /* Force Win9x to update DC state */
717 SetPixelV(hdcMetafile, 50, 50, 0);
719 ret = GetViewportOrgEx(hdcMetafile, &pt);
720 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
721 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
722 ret = GetViewportExtEx(hdcMetafile, &size);
723 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
724 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
725 ret = RestoreDC(hdcMetafile, -1);
726 ok(ret, "ret = %d\n", ret);
728 ret = GetViewportOrgEx(hdcMetafile, &pt);
729 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
730 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
731 ret = GetViewportExtEx(hdcMetafile, &size);
732 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
733 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
734 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
735 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
736 ret = SaveDC(hdcMetafile);
737 ok(ret == 3, "ret = %d\n", ret);
739 ret = GetViewportOrgEx(hdcMetafile, &pt);
740 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
741 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
742 ret = GetViewportExtEx(hdcMetafile, &size);
743 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
744 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
745 ret = RestoreDC(hdcMetafile, 1);
746 ok(ret, "ret = %d\n", ret);
747 ret = GetViewportOrgEx(hdcMetafile, &pt);
748 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
749 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
750 ret = GetViewportExtEx(hdcMetafile, &size);
751 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
752 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
754 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
755 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
756 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
757 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
759 /* Force Win9x to update DC state */
760 SetPixelV(hdcMetafile, 50, 50, 0);
762 ret = GetViewportOrgEx(hdcMetafile, &pt);
763 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
764 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
765 ret = GetViewportExtEx(hdcMetafile, &size);
766 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
767 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
768 ret = SaveDC(hdcMetafile);
769 ok(ret == 1, "ret = %d\n", ret);
771 ret = GetViewportOrgEx(hdcMetafile, &pt);
772 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
773 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
774 ret = GetViewportExtEx(hdcMetafile, &size);
775 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
776 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
777 ret = SaveDC(hdcMetafile);
778 ok(ret == 2, "ret = %d\n", ret);
780 memset(&orig_lf, 0, sizeof(orig_lf));
781 orig_lf.lfCharSet = ANSI_CHARSET;
782 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
783 orig_lf.lfWeight = FW_DONTCARE;
784 orig_lf.lfHeight = 7;
785 orig_lf.lfQuality = DEFAULT_QUALITY;
786 lstrcpyA(orig_lf.lfFaceName, "Arial");
787 hFont = CreateFontIndirectA(&orig_lf);
788 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
790 hFontOld = SelectObject(hdcMetafile, hFont);
792 hFont2 = CreateFontIndirectA(&orig_lf);
793 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
794 hFontCheck = SelectObject(hdcMetafile, hFont2);
795 ok(hFontCheck == hFont, "Font not selected\n");
797 /* Force Win9x to update DC state */
798 SetPixelV(hdcMetafile, 50, 50, 0);
800 ret = RestoreDC(hdcMetafile, 1);
801 ok(ret, "ret = %d\n", ret);
802 ret = GetViewportOrgEx(hdcMetafile, &pt);
803 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
804 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
805 ret = GetViewportExtEx(hdcMetafile, &size);
806 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
807 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
809 hFontCheck = SelectObject(hdcMetafile, hFontOld);
810 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
811 "Font not reverted with DC Restore\n");
813 ret = RestoreDC(hdcMetafile, -20);
814 ok(!ret, "ret = %d\n", ret);
815 ret = RestoreDC(hdcMetafile, 20);
816 ok(!ret, "ret = %d\n", ret);
818 hMetafile = CloseEnhMetaFile(hdcMetafile);
819 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
821 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
822 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
824 ret = DeleteObject(hFont);
825 ok( ret, "DeleteObject error %d\n", GetLastError());
826 ret = DeleteObject(hFont2);
827 ok( ret, "DeleteObject error %d\n", GetLastError());
828 ret = DeleteEnhMetaFile(hMetafile);
829 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
830 ret = ReleaseDC(hwnd, hdcDisplay);
831 ok( ret, "ReleaseDC error %d\n", GetLastError());
832 DestroyWindow(hwnd);
835 static void test_mf_SaveDC(void)
837 HDC hdcMetafile;
838 HMETAFILE hMetafile;
839 int ret;
840 POINT pt;
841 SIZE size;
842 HFONT hFont,hFont2,hFontOld,hFontCheck;
844 hdcMetafile = CreateMetaFileA(NULL);
845 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
847 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
848 ok (ret, "SetMapMode should not fail\n");
850 /* Need to write something to the emf, otherwise Windows won't play it back */
851 LineTo(hdcMetafile, 150, 150);
853 pt.x = pt.y = 5555;
854 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
855 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
856 pt.x = pt.y = 5555;
857 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
858 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
859 size.cx = size.cy = 5555;
860 SetWindowExtEx(hdcMetafile, 110, 110, &size );
861 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
862 size.cx = size.cy = 5555;
863 SetViewportExtEx(hdcMetafile, 120, 120, &size );
864 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
866 /* Force Win9x to update DC state */
867 SetPixelV(hdcMetafile, 50, 50, 0);
869 ret = GetViewportOrgEx(hdcMetafile, &pt);
870 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
871 ret = GetViewportExtEx(hdcMetafile, &size);
872 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
873 ret = SaveDC(hdcMetafile);
874 ok(ret == 1, "ret = %d\n", ret);
876 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
877 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
878 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
879 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
881 /* Force Win9x to update DC state */
882 SetPixelV(hdcMetafile, 50, 50, 0);
884 ret = SaveDC(hdcMetafile);
885 ok(ret == 1, "ret = %d\n", ret);
887 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
888 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
889 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
890 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
892 /* Force Win9x to update DC state */
893 SetPixelV(hdcMetafile, 50, 50, 0);
894 SetPolyFillMode( hdcMetafile, ALTERNATE );
895 SetBkColor( hdcMetafile, 0 );
897 ret = SaveDC(hdcMetafile);
898 ok(ret == 1, "ret = %d\n", ret);
900 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
901 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
902 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
903 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
905 SetPolyFillMode( hdcMetafile, WINDING );
906 SetBkColor( hdcMetafile, 0x123456 );
907 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
908 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
910 /* Force Win9x to update DC state */
911 SetPixelV(hdcMetafile, 50, 50, 0);
913 ret = RestoreDC(hdcMetafile, -1);
914 ok(ret, "ret = %d\n", ret);
916 ret = SaveDC(hdcMetafile);
917 ok(ret == 1, "ret = %d\n", ret);
919 ret = RestoreDC(hdcMetafile, 1);
920 ok(ret, "ret = %d\n", ret);
922 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
923 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
924 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
925 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
927 /* Force Win9x to update DC state */
928 SetPixelV(hdcMetafile, 50, 50, 0);
930 ret = SaveDC(hdcMetafile);
931 ok(ret == 1, "ret = %d\n", ret);
933 ret = SaveDC(hdcMetafile);
934 ok(ret == 1, "ret = %d\n", ret);
936 memset(&orig_lf, 0, sizeof(orig_lf));
937 orig_lf.lfCharSet = ANSI_CHARSET;
938 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
939 orig_lf.lfWeight = FW_DONTCARE;
940 orig_lf.lfHeight = 7;
941 orig_lf.lfQuality = DEFAULT_QUALITY;
942 lstrcpyA(orig_lf.lfFaceName, "Arial");
943 hFont = CreateFontIndirectA(&orig_lf);
944 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
946 hFontOld = SelectObject(hdcMetafile, hFont);
948 hFont2 = CreateFontIndirectA(&orig_lf);
949 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
950 hFontCheck = SelectObject(hdcMetafile, hFont2);
951 ok(hFontCheck == hFont, "Font not selected\n");
953 /* Force Win9x to update DC state */
954 SetPixelV(hdcMetafile, 50, 50, 0);
956 ret = RestoreDC(hdcMetafile, 1);
957 ok(ret, "ret = %d\n", ret);
959 hFontCheck = SelectObject(hdcMetafile, hFontOld);
960 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
962 /* restore level is ignored */
963 ret = RestoreDC(hdcMetafile, -20);
964 ok(ret, "ret = %d\n", ret);
965 ret = RestoreDC(hdcMetafile, 20);
966 ok(ret, "ret = %d\n", ret);
967 ret = RestoreDC(hdcMetafile, 0);
968 ok(ret, "ret = %d\n", ret);
970 hMetafile = CloseMetaFile(hdcMetafile);
971 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
973 ret = DeleteMetaFile(hMetafile);
974 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
975 ret = DeleteObject(hFont);
976 ok( ret, "DeleteObject error %d\n", GetLastError());
977 ret = DeleteObject(hFont2);
978 ok( ret, "DeleteObject error %d\n", GetLastError());
982 /* Win-format metafile (mfdrv) tests */
983 /* These tests compare the generated metafiles byte-by-byte */
984 /* with the nominal results. */
986 /* Maximum size of sample metafiles in bytes. */
987 #define MF_BUFSIZE 512
989 /* 8x8 bitmap data for a pattern brush */
990 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
991 0x01, 0x00, 0x02, 0x00,
992 0x03, 0x00, 0x04, 0x00,
993 0x05, 0x00, 0x06, 0x00,
994 0x07, 0x00, 0x08, 0x00
997 /* Sample metafiles to be compared to the outputs of the
998 * test functions.
1001 static const unsigned char MF_BLANK_BITS[] = {
1002 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 static const unsigned char MF_GRAPHICS_BITS[] = {
1008 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1011 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1012 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1013 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1014 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1015 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1016 0x00, 0x00, 0x00, 0x00
1019 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1020 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1021 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1023 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1024 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1025 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1026 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1029 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1030 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1031 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1032 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1033 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1034 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1035 0x00, 0x00
1038 static const unsigned char MF_DCBRUSH_BITS[] =
1040 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1041 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1043 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1044 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1045 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1048 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1049 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1050 0x00, 0x00, 0x00, 0x00
1053 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1055 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1056 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1057 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1058 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1059 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1060 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1061 0x00, 0x00
1064 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1066 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1071 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1072 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1073 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1076 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1078 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1079 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1080 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1081 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1083 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1084 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1085 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1086 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1089 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1090 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1091 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1092 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1093 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1094 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1095 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1096 0x14, 0x00, 0x00, 0x00
1099 static const unsigned char MF_LINETO_BITS[] = {
1100 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1101 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1102 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1103 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1104 0x00, 0x00
1107 static const unsigned char EMF_LINETO_BITS[] = {
1108 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1113 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1114 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1115 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1118 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1121 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1122 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1123 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1124 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1125 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1131 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1132 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1133 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1134 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1135 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1136 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1137 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1138 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1139 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1140 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1141 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1142 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1143 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1145 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1149 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1150 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1154 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1155 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1156 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1157 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1163 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1164 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1165 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1166 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1167 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1168 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1169 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1170 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1171 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1173 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1174 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1175 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1176 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1177 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1178 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1179 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1180 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1181 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1182 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1183 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1184 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1185 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1187 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1191 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1192 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1194 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1196 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1197 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1198 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1199 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1202 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1205 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1206 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1207 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1208 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1209 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1210 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1211 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1212 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1213 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1215 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1216 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1218 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1220 0x14, 0x00, 0x00, 0x00
1223 static const unsigned char EMF_BITBLT[] =
1225 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1230 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1231 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1232 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1235 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1238 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1239 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1241 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1243 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1249 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1250 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1251 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1252 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1253 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x00, 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 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1267 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1275 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1279 static const unsigned char EMF_DCBRUSH_BITS[] =
1281 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1282 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1283 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1284 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1285 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1286 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1287 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1288 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1291 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1294 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1295 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1296 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1297 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1298 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1301 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1302 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1303 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1306 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1307 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1308 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1309 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1310 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1311 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1312 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1315 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1316 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1317 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1318 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1319 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1320 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1321 0x14, 0x00, 0x00, 0x00
1324 static const unsigned char EMF_BEZIER_BITS[] =
1326 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1328 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1331 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1332 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1333 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1336 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1338 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1339 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1340 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1342 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1343 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1344 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1345 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1346 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1347 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1348 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1349 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1350 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1351 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1352 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1353 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1354 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1355 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1356 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1357 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1358 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1359 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1360 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1361 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1362 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1363 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1364 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1365 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1366 0x14, 0x00, 0x00, 0x00
1369 /* For debugging or dumping the raw metafiles produced by
1370 * new test functions.
1372 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1373 INT nobj, LPARAM param)
1375 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1376 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1377 return TRUE;
1380 /* For debugging or dumping the raw metafiles produced by
1381 * new test functions.
1384 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1386 BYTE buf[MF_BUFSIZE];
1387 UINT mfsize, i;
1389 if (!winetest_debug) return;
1391 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1392 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1394 printf ("MetaFile %s has bits:\n{\n ", desc);
1395 for (i=0; i<mfsize; i++)
1397 printf ("0x%02x", buf[i]);
1398 if (i == mfsize-1)
1399 printf ("\n");
1400 else if (i % 8 == 7)
1401 printf (",\n ");
1402 else
1403 printf (", ");
1405 printf ("};\n");
1408 /* Compare the metafile produced by a test function with the
1409 * expected raw metafile data in "bits".
1410 * Return value is 0 for a perfect match,
1411 * -1 if lengths aren't equal,
1412 * otherwise returns the number of non-matching bytes.
1415 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1416 const char *desc)
1418 unsigned char buf[MF_BUFSIZE];
1419 UINT mfsize, i;
1420 int diff;
1422 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1423 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1424 if (mfsize < MF_BUFSIZE)
1425 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1426 desc, mfsize, bsize);
1427 else
1428 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1429 desc, mfsize, bsize);
1430 if (mfsize != bsize)
1431 return -1;
1433 diff = 0;
1434 for (i=0; i<bsize; i++)
1436 if (buf[i] != bits[i])
1437 diff++;
1439 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1440 desc, mfsize, bsize, diff);
1442 return diff;
1445 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1447 unsigned char buf[MF_BUFSIZE];
1448 DWORD mfsize, rd_size, i;
1449 int diff;
1450 HANDLE hfile;
1451 BOOL ret;
1453 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1454 assert(hfile != INVALID_HANDLE_VALUE);
1456 mfsize = GetFileSize(hfile, NULL);
1457 assert(mfsize <= MF_BUFSIZE);
1459 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1460 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1462 CloseHandle(hfile);
1464 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1466 if (mfsize != bsize)
1467 return -1;
1469 diff = 0;
1470 for (i=0; i<bsize; i++)
1472 if (buf[i] != bits[i])
1473 diff++;
1475 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1476 desc, mfsize, bsize, diff);
1478 return diff;
1481 /* For debugging or dumping the raw EMFs produced by
1482 * new test functions.
1484 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1486 BYTE buf[MF_BUFSIZE];
1487 UINT mfsize, i;
1489 if (!winetest_debug) return;
1491 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1492 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1494 printf("EMF %s has bits:\n{\n ", desc);
1495 for (i = 0; i < mfsize; i++)
1497 printf ("0x%02x", buf[i]);
1498 if (i == mfsize-1)
1499 printf ("\n");
1500 else if (i % 8 == 7)
1501 printf (",\n ");
1502 else
1503 printf (", ");
1505 printf ("};\n");
1508 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1510 BYTE *emf;
1511 BYTE buf[MF_BUFSIZE];
1512 UINT mfsize, offset;
1514 if (!winetest_debug) return;
1516 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1517 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1519 printf("EMF %s has records:\n", desc);
1521 emf = buf;
1522 offset = 0;
1523 while(offset < mfsize)
1525 EMR *emr = (EMR *)(emf + offset);
1526 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1527 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1528 offset += emr->nSize;
1532 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1534 const BYTE *buf;
1535 DWORD i;
1537 if (!winetest_debug) return;
1539 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1540 buf = (const BYTE *)emr;
1541 for (i = 0; i < emr->nSize; i++)
1543 printf ("0x%02x", buf[i]);
1544 if (i == emr->nSize - 1)
1545 printf ("\n");
1546 else if (i % 8 == 7)
1547 printf (",\n");
1548 else
1549 printf (", ");
1551 printf ("};\n");
1554 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1556 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1557 eto->rclBounds.right, eto->rclBounds.bottom);
1558 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1559 trace("exScale: %f\n", eto->exScale);
1560 trace("eyScale: %f\n", eto->eyScale);
1561 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1562 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1563 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1564 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1565 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1566 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1567 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1570 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1571 const char *desc, BOOL ignore_scaling)
1573 int diff;
1575 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1576 desc, emr1->iType, emr2->iType);
1578 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1579 desc, emr1->nSize, emr2->nSize);
1581 /* iType and nSize mismatches are fatal */
1582 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1584 /* contents of EMR_GDICOMMENT are not interesting */
1585 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1587 /* different Windows versions setup DC scaling differently when
1588 * converting an old style metafile to an EMF.
1590 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1591 emr1->iType == EMR_SETVIEWPORTEXTEX))
1592 return TRUE;
1594 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1596 EMREXTTEXTOUTW *eto1, *eto2;
1598 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1599 memcpy(eto1, emr1, emr1->nSize);
1600 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1601 memcpy(eto2, emr2, emr2->nSize);
1603 /* different Windows versions setup DC scaling differently */
1604 eto1->exScale = eto1->eyScale = 0.0;
1605 eto2->exScale = eto2->eyScale = 0.0;
1607 diff = memcmp(eto1, eto2, emr1->nSize);
1608 if (diff)
1610 dump_EMREXTTEXTOUT(eto1);
1611 dump_EMREXTTEXTOUT(eto2);
1613 HeapFree(GetProcessHeap(), 0, eto1);
1614 HeapFree(GetProcessHeap(), 0, eto2);
1616 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1618 /* We have to take care of NT4 differences here */
1619 diff = memcmp(emr1, emr2, emr1->nSize);
1620 if (diff)
1622 ENHMETARECORD *emr_nt4;
1624 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1625 memcpy(emr_nt4, emr2, emr2->nSize);
1626 /* Correct the nRgnSize field */
1627 emr_nt4->dParm[5] = sizeof(RECT);
1629 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1630 if (!diff)
1631 win_skip("Catered for NT4 differences\n");
1633 HeapFree(GetProcessHeap(), 0, emr_nt4);
1636 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1638 EMRPOLYBEZIER16 *eto1, *eto2;
1640 eto1 = (EMRPOLYBEZIER16*)emr1;
1641 eto2 = (EMRPOLYBEZIER16*)emr2;
1643 diff = eto1->cpts != eto2->cpts;
1644 if(!diff)
1645 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1647 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1649 EMRPOLYBEZIER *eto1, *eto2;
1651 eto1 = (EMRPOLYBEZIER*)emr1;
1652 eto2 = (EMRPOLYBEZIER*)emr2;
1654 diff = eto1->cptl != eto2->cptl;
1655 if(!diff)
1656 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1658 else
1659 diff = memcmp(emr1, emr2, emr1->nSize);
1661 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1663 if (diff)
1665 dump_emf_record(emr1, "expected bits");
1666 dump_emf_record(emr2, "actual bits");
1669 return diff == 0; /* report all non-fatal record mismatches */
1672 /* Compare the EMF produced by a test function with the
1673 * expected raw EMF data in "bits".
1674 * Return value is 0 for a perfect match,
1675 * -1 if lengths aren't equal,
1676 * otherwise returns the number of non-matching bytes.
1678 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1679 UINT bsize, const char *desc,
1680 BOOL ignore_scaling)
1682 unsigned char buf[MF_BUFSIZE];
1683 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1684 const ENHMETAHEADER *emh1, *emh2;
1686 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1687 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1689 /* ENHMETAHEADER size could differ, depending on platform */
1690 diff_nt4 = sizeof(SIZEL);
1691 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1693 if (mfsize < MF_BUFSIZE)
1695 ok(mfsize == bsize ||
1696 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1697 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1698 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1700 else
1701 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1702 desc, mfsize, bsize);
1704 /* basic things must match */
1705 emh1 = (const ENHMETAHEADER *)bits;
1706 emh2 = (const ENHMETAHEADER *)buf;
1707 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1708 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1709 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1710 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1712 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1713 ok(emh1->nSize == emh2->nSize ||
1714 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1715 broken(emh1->nSize - diff_9x == emh2->nSize),
1716 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1717 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1718 ok(emh1->nBytes == emh2->nBytes ||
1719 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1720 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1721 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1722 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1724 offset1 = emh1->nSize;
1725 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1726 while (offset1 < emh1->nBytes)
1728 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1729 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1731 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1732 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1734 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1736 /* We have already bailed out if iType or nSize don't match */
1737 offset1 += emr1->nSize;
1738 offset2 += emr2->nSize;
1740 return 0;
1744 /* tests blitting to an EMF */
1745 static void test_emf_BitBlt(void)
1747 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1748 HBITMAP hBitmap, hOldBitmap;
1749 HENHMETAFILE hMetafile;
1750 #define BMP_DIM 4
1751 BITMAPINFOHEADER bmih =
1753 sizeof(BITMAPINFOHEADER),
1754 BMP_DIM,/* biWidth */
1755 BMP_DIM,/* biHeight */
1756 1, /* biPlanes */
1757 24, /* biBitCount */
1758 BI_RGB, /* biCompression */
1759 0, /* biXPelsPerMeter */
1760 0, /* biYPelsPerMeter */
1761 0, /* biClrUsed */
1762 0, /* biClrImportant */
1764 void *bits;
1765 BOOL ret;
1767 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1768 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1770 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1771 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1772 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1773 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1774 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1775 DIB_RGB_COLORS, &bits, NULL, 0);
1776 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1778 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1779 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1781 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1782 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1783 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1785 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1786 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1787 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1788 ok( ret, "BitBlt(WHITENESS) failed\n" );
1790 hMetafile = CloseEnhMetaFile(hdcMetafile);
1791 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1793 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1794 "emf_BitBlt", FALSE) != 0)
1796 dump_emf_bits(hMetafile, "emf_BitBlt");
1797 dump_emf_records(hMetafile, "emf_BitBlt");
1800 SelectObject(hdcBitmap, hOldBitmap);
1801 DeleteObject(hBitmap);
1802 DeleteDC(hdcBitmap);
1803 DeleteDC(hdcDisplay);
1804 #undef BMP_DIM
1807 static void test_emf_DCBrush(void)
1809 HDC hdcMetafile;
1810 HENHMETAFILE hMetafile;
1811 HBRUSH hBrush;
1812 HPEN hPen;
1813 BOOL ret;
1814 COLORREF color;
1816 if (!pSetDCBrushColor || !pSetDCPenColor)
1818 win_skip( "SetDCBrush/PenColor not supported\n" );
1819 return;
1822 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1823 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1825 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1826 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1828 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1829 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1831 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1832 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1834 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1835 ok( color == 0, "SetDCPenColor returned %x\n", color );
1837 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1839 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1840 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1842 hMetafile = CloseEnhMetaFile(hdcMetafile);
1843 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1845 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1846 "emf_DC_Brush", FALSE ) != 0)
1848 dump_emf_bits(hMetafile, "emf_DC_Brush");
1849 dump_emf_records(hMetafile, "emf_DC_Brush");
1851 ret = DeleteEnhMetaFile(hMetafile);
1852 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1853 ret = DeleteObject(hBrush);
1854 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1855 ret = DeleteObject(hPen);
1856 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1859 /* Test a blank metafile. May be used as a template for new tests. */
1861 static void test_mf_Blank(void)
1863 HDC hdcMetafile;
1864 HMETAFILE hMetafile;
1865 INT caps;
1866 BOOL ret;
1867 INT type;
1869 hdcMetafile = CreateMetaFileA(NULL);
1870 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1871 trace("hdcMetafile %p\n", hdcMetafile);
1873 /* Tests on metafile initialization */
1874 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1875 ok (caps == DT_METAFILE,
1876 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1878 hMetafile = CloseMetaFile(hdcMetafile);
1879 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1880 type = GetObjectType(hMetafile);
1881 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1882 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1884 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1885 "mf_blank") != 0)
1887 dump_mf_bits(hMetafile, "mf_Blank");
1888 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1891 ret = DeleteMetaFile(hMetafile);
1892 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1895 static void test_CopyMetaFile(void)
1897 HDC hdcMetafile;
1898 HMETAFILE hMetafile, hmf_copy;
1899 BOOL ret;
1900 char temp_path[MAX_PATH];
1901 char mf_name[MAX_PATH];
1902 INT type;
1904 hdcMetafile = CreateMetaFileA(NULL);
1905 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1906 trace("hdcMetafile %p\n", hdcMetafile);
1908 hMetafile = CloseMetaFile(hdcMetafile);
1909 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1910 type = GetObjectType(hMetafile);
1911 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1913 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1914 "mf_blank") != 0)
1916 dump_mf_bits(hMetafile, "mf_Blank");
1917 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1920 GetTempPathA(MAX_PATH, temp_path);
1921 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1923 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1924 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1926 type = GetObjectType(hmf_copy);
1927 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1929 ret = DeleteMetaFile(hMetafile);
1930 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1932 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1934 dump_mf_bits(hmf_copy, "mf_Blank");
1935 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1938 ret = DeleteMetaFile(hmf_copy);
1939 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1941 DeleteFileA(mf_name);
1944 static void test_SetMetaFileBits(void)
1946 HMETAFILE hmf;
1947 INT type;
1948 BOOL ret;
1949 BYTE buf[256];
1950 METAHEADER *mh;
1952 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1953 trace("hmf %p\n", hmf);
1954 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1955 type = GetObjectType(hmf);
1956 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1958 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1960 dump_mf_bits(hmf, "mf_Graphics");
1961 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1964 ret = DeleteMetaFile(hmf);
1965 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1967 /* NULL data crashes XP SP1 */
1968 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1970 /* Now with zero size */
1971 SetLastError(0xdeadbeef);
1972 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1973 trace("hmf %p\n", hmf);
1974 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1975 ok(GetLastError() == ERROR_INVALID_DATA ||
1976 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1977 "wrong error %d\n", GetLastError());
1979 /* Now with odd size */
1980 SetLastError(0xdeadbeef);
1981 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1982 trace("hmf %p\n", hmf);
1983 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1984 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1986 /* Now with zeroed out header fields */
1987 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1988 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1989 mh = (METAHEADER *)buf;
1990 /* corruption of any of the below fields leads to a failure */
1991 mh->mtType = 0;
1992 mh->mtVersion = 0;
1993 mh->mtHeaderSize = 0;
1994 SetLastError(0xdeadbeef);
1995 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1996 trace("hmf %p\n", hmf);
1997 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1998 ok(GetLastError() == ERROR_INVALID_DATA ||
1999 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2000 "wrong error %d\n", GetLastError());
2002 /* Now with corrupted mtSize field */
2003 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2004 mh = (METAHEADER *)buf;
2005 /* corruption of mtSize doesn't lead to a failure */
2006 mh->mtSize *= 2;
2007 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2008 trace("hmf %p\n", hmf);
2009 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2011 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2013 dump_mf_bits(hmf, "mf_Graphics");
2014 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2017 ret = DeleteMetaFile(hmf);
2018 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2020 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2021 /* Now with zeroed out mtSize field */
2022 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2023 mh = (METAHEADER *)buf;
2024 /* zeroing mtSize doesn't lead to a failure */
2025 mh->mtSize = 0;
2026 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2027 trace("hmf %p\n", hmf);
2028 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2030 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2032 dump_mf_bits(hmf, "mf_Graphics");
2033 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2036 ret = DeleteMetaFile(hmf);
2037 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2038 #endif
2041 /* Simple APIs from mfdrv/graphics.c
2044 static void test_mf_Graphics(void)
2046 HDC hdcMetafile;
2047 HMETAFILE hMetafile;
2048 POINT oldpoint;
2049 BOOL ret;
2051 hdcMetafile = CreateMetaFileA(NULL);
2052 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2053 trace("hdcMetafile %p\n", hdcMetafile);
2055 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2056 ok( ret, "MoveToEx error %d.\n", GetLastError());
2057 ret = LineTo(hdcMetafile, 2, 2);
2058 ok( ret, "LineTo error %d.\n", GetLastError());
2059 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2060 ok( ret, "MoveToEx error %d.\n", GetLastError());
2062 /* oldpoint gets garbage under Win XP, so the following test would
2063 * work under Wine but fails under Windows:
2065 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2066 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2067 * oldpoint.x, oldpoint.y);
2070 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2071 ok( ret, "Ellipse error %d.\n", GetLastError());
2073 hMetafile = CloseMetaFile(hdcMetafile);
2074 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2075 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2077 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2078 "mf_Graphics") != 0)
2080 dump_mf_bits(hMetafile, "mf_Graphics");
2081 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2084 ret = DeleteMetaFile(hMetafile);
2085 ok( ret, "DeleteMetaFile(%p) error %d\n",
2086 hMetafile, GetLastError());
2089 static void test_mf_PatternBrush(void)
2091 HDC hdcMetafile;
2092 HMETAFILE hMetafile;
2093 LOGBRUSH *orig_lb;
2094 HBRUSH hBrush;
2095 BOOL ret;
2097 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2099 orig_lb->lbStyle = BS_PATTERN;
2100 orig_lb->lbColor = RGB(0, 0, 0);
2101 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2102 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2104 hBrush = CreateBrushIndirect (orig_lb);
2105 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2107 hdcMetafile = CreateMetaFileA(NULL);
2108 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2109 trace("hdcMetafile %p\n", hdcMetafile);
2111 hBrush = SelectObject(hdcMetafile, hBrush);
2112 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2114 hMetafile = CloseMetaFile(hdcMetafile);
2115 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2116 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2118 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2119 "mf_Pattern_Brush") != 0)
2121 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2122 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2125 ret = DeleteMetaFile(hMetafile);
2126 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2127 ret = DeleteObject(hBrush);
2128 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2129 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2130 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2131 GetLastError());
2132 HeapFree (GetProcessHeap(), 0, orig_lb);
2135 static void test_mf_DCBrush(void)
2137 HDC hdcMetafile;
2138 HMETAFILE hMetafile;
2139 HBRUSH hBrush;
2140 HPEN hPen;
2141 BOOL ret;
2142 COLORREF color;
2144 if (!pSetDCBrushColor || !pSetDCPenColor)
2146 win_skip( "SetDCBrush/PenColor not supported\n" );
2147 return;
2150 hdcMetafile = CreateMetaFileA(NULL);
2151 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2153 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2154 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2156 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2157 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2159 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2160 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2162 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2163 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2165 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2167 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2168 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2170 hMetafile = CloseMetaFile(hdcMetafile);
2171 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2173 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2175 dump_mf_bits(hMetafile, "mf_DCBrush");
2176 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2178 ret = DeleteMetaFile(hMetafile);
2179 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2182 static void test_mf_ExtTextOut_on_path(void)
2184 HDC hdcMetafile;
2185 HMETAFILE hMetafile;
2186 BOOL ret;
2187 static const INT dx[4] = { 3, 5, 8, 12 };
2189 hdcMetafile = CreateMetaFileA(NULL);
2190 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2191 trace("hdcMetafile %p\n", hdcMetafile);
2193 ret = BeginPath(hdcMetafile);
2194 ok(!ret, "BeginPath on metafile DC should fail\n");
2196 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2197 ok(ret, "ExtTextOut error %d\n", GetLastError());
2199 ret = EndPath(hdcMetafile);
2200 ok(!ret, "EndPath on metafile DC should fail\n");
2202 hMetafile = CloseMetaFile(hdcMetafile);
2203 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2205 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2206 "mf_TextOut_on_path") != 0)
2208 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2209 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2212 ret = DeleteMetaFile(hMetafile);
2213 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2216 static void test_emf_ExtTextOut_on_path(void)
2218 HWND hwnd;
2219 HDC hdcDisplay, hdcMetafile;
2220 HENHMETAFILE hMetafile;
2221 BOOL ret;
2222 static const INT dx[4] = { 3, 5, 8, 12 };
2224 /* Win9x doesn't play EMFs on invisible windows */
2225 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2226 0, 0, 200, 200, 0, 0, 0, NULL);
2227 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2229 hdcDisplay = GetDC(hwnd);
2230 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2232 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2233 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2235 ret = BeginPath(hdcMetafile);
2236 ok(ret, "BeginPath error %d\n", GetLastError());
2238 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2239 ok(ret, "ExtTextOut error %d\n", GetLastError());
2241 ret = EndPath(hdcMetafile);
2242 ok(ret, "EndPath error %d\n", GetLastError());
2244 hMetafile = CloseEnhMetaFile(hdcMetafile);
2245 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2247 /* this doesn't succeed yet: EMF has correct size, all EMF records
2248 * are there, but their contents don't match for different reasons.
2250 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2251 "emf_TextOut_on_path", FALSE) != 0)
2253 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2254 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2257 ret = DeleteEnhMetaFile(hMetafile);
2258 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2259 ret = ReleaseDC(hwnd, hdcDisplay);
2260 ok(ret, "ReleaseDC error %d\n", GetLastError());
2261 DestroyWindow(hwnd);
2264 static const unsigned char EMF_CLIPPING[] =
2266 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2268 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2270 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2271 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2272 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2273 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2275 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2276 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2278 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2279 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2280 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2281 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2282 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2283 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2284 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2285 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2286 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2287 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2288 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2289 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2290 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2291 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2294 static void translate( POINT *pt, UINT count, const XFORM *xform )
2296 while (count--)
2298 FLOAT x = (FLOAT)pt->x;
2299 FLOAT y = (FLOAT)pt->y;
2300 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2301 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2302 pt++;
2306 /* Compare rectangles allowing rounding errors */
2307 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2309 return abs(rc1->left - rc2->left) <= 1 &&
2310 abs(rc1->top - rc2->top) <= 1 &&
2311 abs(rc1->right - rc2->right) <= 1 &&
2312 abs(rc1->bottom - rc2->bottom) <= 1;
2315 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2316 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2318 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2320 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2321 union _rgn
2323 RGNDATA data;
2324 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2326 const union _rgn *rgn1;
2327 union _rgn rgn2;
2328 RECT rect, rc_transformed;
2329 const RECT *rc = (const RECT *)param;
2330 HRGN hrgn;
2331 XFORM xform;
2332 INT ret;
2333 BOOL is_win9x;
2335 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2336 clip->cbRgnData, clip->iMode);
2338 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2339 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2340 "too small data block: %u bytes\n", clip->cbRgnData);
2341 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2342 return 0;
2344 rgn1 = (const union _rgn *)clip->RgnData;
2346 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2347 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2348 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2349 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2350 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2352 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2354 rect = *(const RECT *)rgn1->data.Buffer;
2355 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2356 ok(EqualRect(&rect, rc), "rects don't match\n");
2358 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2359 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2360 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2361 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2362 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2363 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2365 hrgn = CreateRectRgn(0, 0, 0, 0);
2367 memset(&xform, 0, sizeof(xform));
2368 SetLastError(0xdeadbeef);
2369 ret = GetWorldTransform(hdc, &xform);
2370 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2371 if (!is_win9x)
2372 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2374 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2376 ret = GetClipRgn(hdc, hrgn);
2377 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2379 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2381 ret = GetClipRgn(hdc, hrgn);
2382 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2384 /* Win9x returns empty clipping region */
2385 if (is_win9x) return 1;
2387 ret = GetRegionData(hrgn, 0, NULL);
2388 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2390 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2391 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2393 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2394 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2395 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2396 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2397 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2399 rect = rgn2.data.rdh.rcBound;
2400 rc_transformed = *rc;
2401 translate((POINT *)&rc_transformed, 2, &xform);
2402 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2403 rc_transformed.right, rc_transformed.bottom);
2404 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2406 rect = *(const RECT *)rgn2.data.Buffer;
2407 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2408 rc_transformed = *rc;
2409 translate((POINT *)&rc_transformed, 2, &xform);
2410 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2411 rc_transformed.right, rc_transformed.bottom);
2412 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2414 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2415 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2416 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2417 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2418 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2419 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2421 DeleteObject(hrgn);
2423 return 1;
2426 static void test_emf_clipping(void)
2428 static const RECT rc = { 0, 0, 100, 100 };
2429 RECT rc_clip = { 100, 100, 1024, 1024 };
2430 HWND hwnd;
2431 HDC hdc;
2432 HENHMETAFILE hemf;
2433 HRGN hrgn;
2434 INT ret;
2435 RECT rc_res, rc_sclip;
2437 SetLastError(0xdeadbeef);
2438 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2439 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2441 /* Need to write something to the emf, otherwise Windows won't play it back */
2442 LineTo(hdc, 1, 1);
2444 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2445 ret = SelectClipRgn(hdc, hrgn);
2446 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2448 SetLastError(0xdeadbeef);
2449 hemf = CloseEnhMetaFile(hdc);
2450 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2452 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2453 "emf_clipping", FALSE) != 0)
2455 dump_emf_bits(hemf, "emf_clipping");
2456 dump_emf_records(hemf, "emf_clipping");
2459 DeleteObject(hrgn);
2461 /* Win9x doesn't play EMFs on invisible windows */
2462 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2463 0, 0, 200, 200, 0, 0, 0, NULL);
2464 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2466 hdc = GetDC(hwnd);
2468 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2469 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2471 DeleteEnhMetaFile(hemf);
2472 ReleaseDC(hwnd, hdc);
2473 DestroyWindow(hwnd);
2475 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2477 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2478 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2479 SelectClipRgn(hdc, hrgn);
2480 ret = GetClipBox(hdc, &rc_res);
2481 todo_wine
2482 ok(ret == SIMPLEREGION, "got %d\n", ret);
2483 if(ret == SIMPLEREGION)
2484 ok(EqualRect(&rc_res, &rc_sclip),
2485 "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2486 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2487 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2489 hemf = CloseEnhMetaFile(hdc);
2490 DeleteEnhMetaFile(hemf);
2491 DeleteObject(hrgn);
2492 DeleteDC(hdc);
2495 static const unsigned char MF_CLIP_BITS[] = {
2496 /* METAHEADER */
2497 0x01, 0x00, /* mtType */
2498 0x09, 0x00, /* mtHeaderSize */
2499 0x00, 0x03, /* mtVersion */
2500 0x32, 0x00, 0x00, 0x00, /* mtSize */
2501 0x01, 0x00, /* mtNoObjects */
2502 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2503 0x00, 0x00, /* reserved */
2505 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2506 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2507 0xff, 0x06, /* META_CREATEREGION */
2508 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2509 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2510 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2511 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2512 0x02, 0x00,
2514 /* METARECORD for SelectObject */
2515 0x04, 0x00, 0x00, 0x00,
2516 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2517 0x00, 0x00,
2519 /* METARECORD */
2520 0x04, 0x00, 0x00, 0x00,
2521 0xf0, 0x01, /* META_DELETEOBJECT */
2522 0x00, 0x00,
2524 /* METARECORD for MoveTo(1,0x30) */
2525 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2526 0x14, 0x02, /* META_MOVETO */
2527 0x30, 0x00, /* y */
2528 0x01, 0x00, /* x */
2530 /* METARECORD for LineTo(0x20, 0x30) */
2531 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2532 0x13, 0x02, /* META_LINETO */
2533 0x30, 0x00, /* y */
2534 0x20, 0x00, /* x */
2536 /* EOF */
2537 0x03, 0x00, 0x00, 0x00,
2538 0x00, 0x00
2541 static int clip_mf_enum_proc_seen_selectclipregion;
2542 static int clip_mf_enum_proc_seen_selectobject;
2544 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2545 METARECORD *mr, int n_objs, LPARAM param)
2547 switch (mr->rdFunction) {
2548 case META_SELECTCLIPREGION:
2549 clip_mf_enum_proc_seen_selectclipregion++;
2550 break;
2551 case META_SELECTOBJECT:
2552 clip_mf_enum_proc_seen_selectobject++;
2553 break;
2555 return 1;
2558 static void test_mf_clipping(void)
2560 /* left top right bottom */
2561 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2562 HWND hwnd;
2563 HDC hdc;
2564 HMETAFILE hmf;
2565 HRGN hrgn;
2566 INT ret;
2568 SetLastError(0xdeadbeef);
2569 hdc = CreateMetaFileA(NULL);
2570 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2572 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2573 ret = SelectClipRgn(hdc, hrgn);
2574 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2575 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2577 /* Draw a line that starts off left of the clip region and ends inside it */
2578 MoveToEx(hdc, 0x1, 0x30, NULL);
2579 LineTo(hdc, 0x20, 0x30);
2581 SetLastError(0xdeadbeef);
2582 hmf = CloseMetaFile(hdc);
2583 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2585 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2586 "mf_clipping") != 0)
2588 dump_mf_bits(hmf, "mf_clipping");
2591 DeleteObject(hrgn);
2593 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2594 0, 0, 200, 200, 0, 0, 0, NULL);
2595 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2597 hdc = GetDC(hwnd);
2599 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2600 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2602 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2603 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2604 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2605 ok(clip_mf_enum_proc_seen_selectobject == 1,
2606 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2608 DeleteMetaFile(hmf);
2609 ReleaseDC(hwnd, hdc);
2610 DestroyWindow(hwnd);
2613 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2615 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2616 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2617 /* When using MM_TEXT Win9x does not update the mapping mode
2618 * until a record is played which actually outputs something */
2619 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2620 LPtoDP(hdc, mapping, 2);
2621 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2622 lpEMFR->iType, lpEMFR->nSize,
2623 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2625 if (lpEMFR->iType == EMR_LINETO)
2627 INT x0, y0, x1, y1;
2628 if (!lpMFP || lpMFP->mm == MM_TEXT)
2630 x0 = 0;
2631 y0 = 0;
2632 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2633 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2635 else
2637 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2639 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2640 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2641 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2642 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2644 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2645 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2646 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2647 x0, y0, x1, y1);
2649 return TRUE;
2652 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2654 HDC hdcMf;
2655 HMETAFILE hmf;
2656 HENHMETAFILE hemf;
2657 BOOL ret;
2658 UINT size;
2659 LPBYTE pBits;
2661 hdcMf = CreateMetaFile(NULL);
2662 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2663 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2664 ok(ret, "LineTo failed with error %d\n", GetLastError());
2665 hmf = CloseMetaFile(hdcMf);
2666 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2668 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2670 dump_mf_bits(hmf, "mf_LineTo");
2671 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2674 size = GetMetaFileBitsEx(hmf, 0, NULL);
2675 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2676 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2677 GetMetaFileBitsEx(hmf, size, pBits);
2678 DeleteMetaFile(hmf);
2679 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2680 HeapFree(GetProcessHeap(), 0, pBits);
2681 return hemf;
2684 static void test_mf_conversions(void)
2686 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2688 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2689 HENHMETAFILE hemf;
2690 METAFILEPICT mfp;
2691 RECT rect = { 0, 0, 100, 100 };
2692 mfp.mm = MM_ANISOTROPIC;
2693 mfp.xExt = 100;
2694 mfp.yExt = 100;
2695 mfp.hMF = NULL;
2696 hemf = create_converted_emf(&mfp);
2698 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2699 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2701 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2702 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2705 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2707 DeleteEnhMetaFile(hemf);
2708 DeleteDC(hdcOffscreen);
2711 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2713 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2714 HENHMETAFILE hemf;
2715 METAFILEPICT mfp;
2716 RECT rect = { 0, 0, 100, 100 };
2717 mfp.mm = MM_TEXT;
2718 mfp.xExt = 0;
2719 mfp.yExt = 0;
2720 mfp.hMF = NULL;
2721 hemf = create_converted_emf(&mfp);
2723 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2724 "emf_LineTo MM_TEXT", TRUE) != 0)
2726 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2727 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2730 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2732 DeleteEnhMetaFile(hemf);
2733 DeleteDC(hdcOffscreen);
2736 trace("Testing MF->EMF conversion (NULL mfp)\n");
2738 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2739 HENHMETAFILE hemf;
2740 RECT rect = { 0, 0, 100, 100 };
2741 hemf = create_converted_emf(NULL);
2743 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2744 "emf_LineTo NULL", TRUE) != 0)
2746 dump_emf_bits(hemf, "emf_LineTo NULL");
2747 dump_emf_records(hemf, "emf_LineTo NULL");
2750 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2752 DeleteEnhMetaFile(hemf);
2753 DeleteDC(hdcOffscreen);
2757 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2758 LONG mm, LONG xExt, LONG yExt,
2759 RECTL * rclBounds, RECTL * rclFrame)
2761 METAFILEPICT mfp;
2762 METAFILEPICT * mfpPtr = NULL;
2763 HENHMETAFILE emf;
2764 ENHMETAHEADER header;
2765 UINT res;
2767 if (!mfpIsNull)
2769 mfp.mm = mm;
2770 mfp.xExt = xExt;
2771 mfp.yExt = yExt;
2772 mfpPtr = &mfp;
2775 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2776 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2777 if (!emf) return FALSE;
2778 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2779 ok(res != 0, "GetEnhMetaHeader failed\n");
2780 DeleteEnhMetaFile(emf);
2781 if (!res) return FALSE;
2783 *rclBounds = header.rclBounds;
2784 *rclFrame = header.rclFrame;
2785 return TRUE;
2788 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2789 LONG mm, LONG xExt, LONG yExt,
2790 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2792 RECTL rclBounds, rclFrame;
2794 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2796 const char * msg;
2797 char buf[64];
2799 if (mfpIsNull)
2801 msg = "mfp == NULL";
2803 else
2805 const char * mm_str;
2806 switch (mm)
2808 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2809 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2810 default: mm_str = "Unexpected";
2812 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2813 msg = buf;
2816 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2817 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2818 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2819 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2820 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2821 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2822 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2823 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2827 static void test_SetWinMetaFileBits(void)
2829 HMETAFILE wmf;
2830 HDC wmfDC;
2831 BYTE * buffer;
2832 UINT buffer_size;
2833 RECT rect;
2834 UINT res;
2835 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2836 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2837 RECTL rclBounds, rclFrame;
2838 HDC dc;
2839 LONG diffx, diffy;
2841 wmfDC = CreateMetaFile(NULL);
2842 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2843 if (!wmfDC) return;
2845 SetWindowExtEx(wmfDC, 100, 100, NULL);
2846 rect.left = rect.top = 0;
2847 rect.right = rect.bottom = 50;
2848 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2849 wmf = CloseMetaFile(wmfDC);
2850 ok(wmf != NULL, "Metafile creation failed\n");
2851 if (!wmf) return;
2853 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2854 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2855 if (buffer_size == 0)
2857 DeleteMetaFile(wmf);
2858 return;
2861 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2862 ok(buffer != NULL, "HeapAlloc failed\n");
2863 if (!buffer)
2865 DeleteMetaFile(wmf);
2866 return;
2869 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2870 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2871 DeleteMetaFile(wmf);
2872 if (res != buffer_size)
2874 HeapFree(GetProcessHeap(), 0, buffer);
2875 return;
2878 /* Get the reference bounds and frame */
2879 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2880 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2882 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2883 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2884 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2886 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2887 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2888 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2889 if (diffx < 0) diffx = -diffx;
2890 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2892 dc = CreateCompatibleDC(NULL);
2894 /* Allow 1 mm difference (rounding errors) */
2895 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2896 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2897 if (diffx < 0) diffx = -diffx;
2898 if (diffy < 0) diffy = -diffy;
2899 todo_wine
2901 ok(diffx <= 1 && diffy <= 1,
2902 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2903 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2906 /* Allow 1 mm difference (rounding errors) */
2907 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2908 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2909 if (diffx < 0) diffx = -diffx;
2910 if (diffy < 0) diffy = -diffy;
2911 todo_wine
2913 ok(diffx <= 1 && diffy <= 1,
2914 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2915 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2917 DeleteDC(dc);
2919 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2920 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2922 /* If xExt or yExt is zero or negative, the whole device surface is used */
2923 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2924 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2925 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2926 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2927 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2928 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2929 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2930 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2931 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2932 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2933 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2934 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2936 /* MSDN says that negative xExt and yExt values specify a ratio.
2937 Check that this is wrong and the whole device surface is used */
2938 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2939 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2941 /* Ordinary conversions */
2943 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2945 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2946 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2947 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2948 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2951 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2953 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2954 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2955 ok(rclBounds.left == 0 && rclBounds.top == 0,
2956 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2958 /* Wine has a rounding error */
2959 diffx = rclBounds.right - rclBounds.bottom;
2960 if (diffx < 0) diffx = -diffx;
2961 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2964 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2966 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2967 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2970 HeapFree(GetProcessHeap(), 0, buffer);
2973 static BOOL near_match(int x, int y)
2975 int epsilon = min(abs(x), abs(y));
2977 epsilon = max(epsilon/100, 2);
2979 if(x < y - epsilon || x > y + epsilon) return FALSE;
2980 return TRUE;
2983 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2985 HENHMETAFILE emf;
2986 HDC display_dc, emf_dc;
2987 ENHMETAHEADER *enh_header;
2988 UINT size, emf_size, i;
2989 WORD check = 0;
2990 DWORD rec_num = 0;
2991 METAHEADER *mh = NULL;
2992 METARECORD *rec;
2993 INT horz_res, vert_res, horz_size, vert_size;
2994 INT curve_caps, line_caps, poly_caps;
2996 display_dc = GetDC(NULL);
2997 ok(display_dc != NULL, "display_dc is NULL\n");
2999 horz_res = GetDeviceCaps(display_dc, HORZRES);
3000 vert_res = GetDeviceCaps(display_dc, VERTRES);
3001 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3002 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3004 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3005 ok(emf_dc != NULL, "emf_dc is NULL\n");
3007 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3008 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3010 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3011 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3013 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3014 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3016 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3017 Rectangle(emf_dc, 0, 0, 1000, 20);
3018 emf = CloseEnhMetaFile(emf_dc);
3019 ok(emf != NULL, "emf is NULL\n");
3021 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3022 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3023 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3024 DeleteEnhMetaFile(emf);
3025 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3026 have different resolutions */
3027 enh_header->szlDevice.cx *= scale;
3028 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3029 ok(emf != NULL, "emf is NULL\n");
3030 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3032 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3033 ok(size ||
3034 broken(size == 0), /* some versions of winxp fail for some reason */
3035 "GetWinMetaFileBits returns 0\n");
3036 if(!size) goto end;
3037 mh = HeapAlloc(GetProcessHeap(), 0, size);
3038 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3040 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3041 ok(check == 0, "check %04x\n", check);
3043 rec = (METARECORD*)(mh + 1);
3045 while(rec->rdSize && rec->rdFunction)
3047 const DWORD chunk_size = 0x2000;
3048 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3050 if(rec_num < mfcomment_chunks)
3052 DWORD this_chunk_size = chunk_size;
3054 if(rec_num == mfcomment_chunks - 1)
3055 this_chunk_size = emf_size - rec_num * chunk_size;
3057 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3058 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3059 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3060 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3061 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3062 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3063 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3064 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3065 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3066 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3067 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3068 /* parm[8] is the checksum, tested above */
3069 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3070 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3071 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3072 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3073 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3074 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3075 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3076 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 */
3077 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3078 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3081 else if(rec_num == mfcomment_chunks)
3083 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3084 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3086 else if(rec_num == mfcomment_chunks + 1)
3088 POINT pt;
3089 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3090 switch(mode)
3092 case MM_TEXT:
3093 case MM_ISOTROPIC:
3094 case MM_ANISOTROPIC:
3095 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3096 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3097 break;
3098 case MM_LOMETRIC:
3099 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3100 pt.x = MulDiv( rc->left, 1, 10);
3101 break;
3102 case MM_HIMETRIC:
3103 pt.y = -rc->top + 1;
3104 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3105 break;
3106 case MM_LOENGLISH:
3107 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3108 pt.x = MulDiv( rc->left, 10, 254);
3109 break;
3110 case MM_HIENGLISH:
3111 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3112 pt.x = MulDiv( rc->left, 100, 254);
3113 break;
3114 case MM_TWIPS:
3115 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3116 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3117 break;
3118 default:
3119 pt.x = pt.y = 0;
3121 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3122 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3124 if(rec_num == mfcomment_chunks + 2)
3126 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3127 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3128 "got %d\n", (short)rec->rdParm[0]);
3129 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3130 "got %d\n", (short)rec->rdParm[1]);
3133 rec_num++;
3134 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3137 end:
3138 HeapFree(GetProcessHeap(), 0, mh);
3139 HeapFree(GetProcessHeap(), 0, enh_header);
3140 DeleteEnhMetaFile(emf);
3142 ReleaseDC(NULL, display_dc);
3145 static void test_GetWinMetaFileBits(void)
3147 UINT mode;
3148 RECT frames[] =
3150 { 1000, 2000, 3000, 6000},
3151 {-1000, 2000, 3000, 6000},
3152 { 1000, -2000, 3000, 6000},
3153 { 1005, 2005, 3000, 6000},
3154 {-1005, -2005, 3000, 6000},
3155 {-1005, -2010, 3000, 6000},
3156 {-1005, 2010, 3000, 6000},
3157 { 0, 0, 1, 1},
3158 { -1, -1, 1, 1},
3159 { 0, 0, 0, 0}
3162 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3164 RECT *rc;
3165 trace("mode %d\n", mode);
3167 for(rc = frames; rc->right - rc->left > 0; rc++)
3169 trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
3170 getwinmetafilebits(mode, 1, rc);
3171 getwinmetafilebits(mode, 2, rc);
3176 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3177 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3178 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3180 static void test_gdiis(void)
3182 RECT rect = {0,0,100,100};
3183 HDC hdc, hemfDC, hmfDC;
3184 HENHMETAFILE hemf;
3185 HMODULE hgdi32;
3187 /* resolve all the functions */
3188 hgdi32 = GetModuleHandle("gdi32");
3189 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3190 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3191 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3193 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3195 win_skip("Needed GdiIs* functions are not available\n");
3196 return;
3199 /* try with nothing */
3200 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3201 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3202 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3204 /* try with a metafile */
3205 hmfDC = CreateMetaFile(NULL);
3206 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3207 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3208 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3209 DeleteMetaFile(CloseMetaFile(hmfDC));
3211 /* try with an enhanced metafile */
3212 hdc = GetDC(NULL);
3213 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3214 ok(hemfDC != NULL, "failed to create emf\n");
3216 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3217 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3218 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3220 hemf = CloseEnhMetaFile(hemfDC);
3221 ok(hemf != NULL, "failed to close EMF\n");
3222 DeleteEnhMetaFile(hemf);
3223 ReleaseDC(NULL,hdc);
3226 static void test_SetEnhMetaFileBits(void)
3228 BYTE data[256];
3229 HENHMETAFILE hemf;
3230 ENHMETAHEADER *emh;
3232 memset(data, 0xAA, sizeof(data));
3233 SetLastError(0xdeadbeef);
3234 hemf = SetEnhMetaFileBits(sizeof(data), data);
3235 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3236 ok(GetLastError() == ERROR_INVALID_DATA ||
3237 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3238 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3240 emh = (ENHMETAHEADER *)data;
3241 memset(emh, 0, sizeof(*emh));
3243 emh->iType = EMR_HEADER;
3244 emh->nSize = sizeof(*emh);
3245 emh->dSignature = ENHMETA_SIGNATURE;
3246 /* emh->nVersion = 0x10000; XP doesn't care about version */
3247 emh->nBytes = sizeof(*emh);
3248 /* emh->nRecords = 1; XP doesn't care about records */
3249 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3251 SetLastError(0xdeadbeef);
3252 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3253 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3254 DeleteEnhMetaFile(hemf);
3256 /* XP refuses to load unaligned EMF */
3257 emh->nBytes++;
3258 SetLastError(0xdeadbeef);
3259 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3260 ok(!hemf ||
3261 broken(hemf != NULL), /* Win9x, WinMe */
3262 "SetEnhMetaFileBits should fail\n");
3263 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3264 DeleteEnhMetaFile(hemf);
3266 emh->dSignature = 0;
3267 emh->nBytes--;
3268 SetLastError(0xdeadbeef);
3269 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3270 ok(!hemf ||
3271 broken(hemf != NULL), /* Win9x, WinMe */
3272 "SetEnhMetaFileBits should fail\n");
3273 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3274 DeleteEnhMetaFile(hemf);
3277 static void test_emf_polybezier(void)
3279 HDC hdcMetafile;
3280 HENHMETAFILE hemf;
3281 POINT pts[4];
3282 BOOL ret;
3284 SetLastError(0xdeadbeef);
3285 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3286 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3288 pts[0].x = pts[0].y = 10;
3289 pts[1].x = pts[1].y = 20;
3290 pts[2].x = pts[2].y = 15;
3291 pts[3].x = pts[3].y = 25;
3292 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3293 ok( ret, "PolyBezierTo failed\n" );
3294 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3295 ok( ret, "PolyBezier failed\n" );
3297 pts[0].x = pts[0].y = 32769;
3298 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3299 ok( ret, "PolyBezier failed\n" );
3300 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3301 ok( ret, "PolyBezierTo failed\n" );
3303 hemf = CloseEnhMetaFile(hdcMetafile);
3304 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3306 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3307 "emf_Bezier", FALSE) != 0)
3309 dump_emf_bits(hemf, "emf_Bezier");
3310 dump_emf_records(hemf, "emf_Bezier");
3313 DeleteEnhMetaFile(hemf);
3316 START_TEST(metafile)
3318 init_function_pointers();
3320 /* For enhanced metafiles (enhmfdrv) */
3321 test_ExtTextOut();
3322 test_ExtTextOutScale();
3323 test_SaveDC();
3324 test_emf_BitBlt();
3325 test_emf_DCBrush();
3326 test_emf_ExtTextOut_on_path();
3327 test_emf_clipping();
3328 test_emf_polybezier();
3330 /* For win-format metafiles (mfdrv) */
3331 test_mf_SaveDC();
3332 test_mf_Blank();
3333 test_mf_Graphics();
3334 test_mf_PatternBrush();
3335 test_mf_DCBrush();
3336 test_CopyMetaFile();
3337 test_SetMetaFileBits();
3338 test_mf_ExtTextOut_on_path();
3339 test_mf_clipping();
3341 /* For metafile conversions */
3342 test_mf_conversions();
3343 test_SetWinMetaFileBits();
3344 test_GetWinMetaFileBits();
3346 test_gdiis();
3347 test_SetEnhMetaFileBits();