cmd: Move externals list at the same place as the builtins one so it's easier to...
[wine/multimedia.git] / dlls / gdi32 / tests / metafile.c
blob206e15ad8a1de39dba013f4b245dd92393340282
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 /* For debugging or dumping the raw metafiles produced by
1325 * new test functions.
1327 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1328 INT nobj, LPARAM param)
1330 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1331 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1332 return TRUE;
1335 /* For debugging or dumping the raw metafiles produced by
1336 * new test functions.
1339 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1341 BYTE buf[MF_BUFSIZE];
1342 UINT mfsize, i;
1344 if (!winetest_debug) return;
1346 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1347 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1349 printf ("MetaFile %s has bits:\n{\n ", desc);
1350 for (i=0; i<mfsize; i++)
1352 printf ("0x%02x", buf[i]);
1353 if (i == mfsize-1)
1354 printf ("\n");
1355 else if (i % 8 == 7)
1356 printf (",\n ");
1357 else
1358 printf (", ");
1360 printf ("};\n");
1363 /* Compare the metafile produced by a test function with the
1364 * expected raw metafile data in "bits".
1365 * Return value is 0 for a perfect match,
1366 * -1 if lengths aren't equal,
1367 * otherwise returns the number of non-matching bytes.
1370 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1371 const char *desc)
1373 unsigned char buf[MF_BUFSIZE];
1374 UINT mfsize, i;
1375 int diff;
1377 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1378 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1379 if (mfsize < MF_BUFSIZE)
1380 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1381 desc, mfsize, bsize);
1382 else
1383 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1384 desc, mfsize, bsize);
1385 if (mfsize != bsize)
1386 return -1;
1388 diff = 0;
1389 for (i=0; i<bsize; i++)
1391 if (buf[i] != bits[i])
1392 diff++;
1394 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1395 desc, mfsize, bsize, diff);
1397 return diff;
1400 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1402 unsigned char buf[MF_BUFSIZE];
1403 DWORD mfsize, rd_size, i;
1404 int diff;
1405 HANDLE hfile;
1406 BOOL ret;
1408 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1409 assert(hfile != INVALID_HANDLE_VALUE);
1411 mfsize = GetFileSize(hfile, NULL);
1412 assert(mfsize <= MF_BUFSIZE);
1414 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1415 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1417 CloseHandle(hfile);
1419 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1421 if (mfsize != bsize)
1422 return -1;
1424 diff = 0;
1425 for (i=0; i<bsize; i++)
1427 if (buf[i] != bits[i])
1428 diff++;
1430 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1431 desc, mfsize, bsize, diff);
1433 return diff;
1436 /* For debugging or dumping the raw EMFs produced by
1437 * new test functions.
1439 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1441 BYTE buf[MF_BUFSIZE];
1442 UINT mfsize, i;
1444 if (!winetest_debug) return;
1446 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1447 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1449 printf("EMF %s has bits:\n{\n ", desc);
1450 for (i = 0; i < mfsize; i++)
1452 printf ("0x%02x", buf[i]);
1453 if (i == mfsize-1)
1454 printf ("\n");
1455 else if (i % 8 == 7)
1456 printf (",\n ");
1457 else
1458 printf (", ");
1460 printf ("};\n");
1463 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1465 BYTE *emf;
1466 BYTE buf[MF_BUFSIZE];
1467 UINT mfsize, offset;
1469 if (!winetest_debug) return;
1471 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1472 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1474 printf("EMF %s has records:\n", desc);
1476 emf = buf;
1477 offset = 0;
1478 while(offset < mfsize)
1480 EMR *emr = (EMR *)(emf + offset);
1481 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1482 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1483 offset += emr->nSize;
1487 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1489 const BYTE *buf;
1490 DWORD i;
1492 if (!winetest_debug) return;
1494 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1495 buf = (const BYTE *)emr;
1496 for (i = 0; i < emr->nSize; i++)
1498 printf ("0x%02x", buf[i]);
1499 if (i == emr->nSize - 1)
1500 printf ("\n");
1501 else if (i % 8 == 7)
1502 printf (",\n");
1503 else
1504 printf (", ");
1506 printf ("};\n");
1509 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1511 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1512 eto->rclBounds.right, eto->rclBounds.bottom);
1513 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1514 trace("exScale: %f\n", eto->exScale);
1515 trace("eyScale: %f\n", eto->eyScale);
1516 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1517 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1518 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1519 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1520 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1521 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1522 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1525 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1526 const char *desc, BOOL ignore_scaling)
1528 int diff;
1530 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1531 desc, emr1->iType, emr2->iType);
1533 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1534 desc, emr1->nSize, emr2->nSize);
1536 /* iType and nSize mismatches are fatal */
1537 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1539 /* contents of EMR_GDICOMMENT are not interesting */
1540 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1542 /* different Windows versions setup DC scaling differently when
1543 * converting an old style metafile to an EMF.
1545 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1546 emr1->iType == EMR_SETVIEWPORTEXTEX))
1547 return TRUE;
1549 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1551 EMREXTTEXTOUTW *eto1, *eto2;
1553 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1554 memcpy(eto1, emr1, emr1->nSize);
1555 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1556 memcpy(eto2, emr2, emr2->nSize);
1558 /* different Windows versions setup DC scaling differently */
1559 eto1->exScale = eto1->eyScale = 0.0;
1560 eto2->exScale = eto2->eyScale = 0.0;
1562 diff = memcmp(eto1, eto2, emr1->nSize);
1563 if (diff)
1565 dump_EMREXTTEXTOUT(eto1);
1566 dump_EMREXTTEXTOUT(eto2);
1568 HeapFree(GetProcessHeap(), 0, eto1);
1569 HeapFree(GetProcessHeap(), 0, eto2);
1571 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1573 /* We have to take care of NT4 differences here */
1574 diff = memcmp(emr1, emr2, emr1->nSize);
1575 if (diff)
1577 ENHMETARECORD *emr_nt4;
1579 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1580 memcpy(emr_nt4, emr2, emr2->nSize);
1581 /* Correct the nRgnSize field */
1582 emr_nt4->dParm[5] = sizeof(RECT);
1584 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1585 if (!diff)
1586 win_skip("Catered for NT4 differences\n");
1588 HeapFree(GetProcessHeap(), 0, emr_nt4);
1591 else
1592 diff = memcmp(emr1, emr2, emr1->nSize);
1594 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1596 if (diff)
1598 dump_emf_record(emr1, "expected bits");
1599 dump_emf_record(emr2, "actual bits");
1602 return diff == 0; /* report all non-fatal record mismatches */
1605 /* Compare the EMF produced by a test function with the
1606 * expected raw EMF data in "bits".
1607 * Return value is 0 for a perfect match,
1608 * -1 if lengths aren't equal,
1609 * otherwise returns the number of non-matching bytes.
1611 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1612 UINT bsize, const char *desc,
1613 BOOL ignore_scaling)
1615 unsigned char buf[MF_BUFSIZE];
1616 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1617 const ENHMETAHEADER *emh1, *emh2;
1619 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1620 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1622 /* ENHMETAHEADER size could differ, depending on platform */
1623 diff_nt4 = sizeof(SIZEL);
1624 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1626 if (mfsize < MF_BUFSIZE)
1628 ok(mfsize == bsize ||
1629 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1630 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1631 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1633 else
1634 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1635 desc, mfsize, bsize);
1637 /* basic things must match */
1638 emh1 = (const ENHMETAHEADER *)bits;
1639 emh2 = (const ENHMETAHEADER *)buf;
1640 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1641 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1642 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1643 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1645 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1646 ok(emh1->nSize == emh2->nSize ||
1647 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1648 broken(emh1->nSize - diff_9x == emh2->nSize),
1649 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1650 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1651 ok(emh1->nBytes == emh2->nBytes ||
1652 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1653 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1654 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1655 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1657 offset1 = emh1->nSize;
1658 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1659 while (offset1 < emh1->nBytes)
1661 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1662 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1664 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1665 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1667 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1669 /* We have already bailed out if iType or nSize don't match */
1670 offset1 += emr1->nSize;
1671 offset2 += emr2->nSize;
1673 return 0;
1677 /* tests blitting to an EMF */
1678 static void test_emf_BitBlt(void)
1680 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1681 HBITMAP hBitmap, hOldBitmap;
1682 HENHMETAFILE hMetafile;
1683 #define BMP_DIM 4
1684 BITMAPINFOHEADER bmih =
1686 sizeof(BITMAPINFOHEADER),
1687 BMP_DIM,/* biWidth */
1688 BMP_DIM,/* biHeight */
1689 1, /* biPlanes */
1690 24, /* biBitCount */
1691 BI_RGB, /* biCompression */
1692 0, /* biXPelsPerMeter */
1693 0, /* biYPelsPerMeter */
1694 0, /* biClrUsed */
1695 0, /* biClrImportant */
1697 void *bits;
1698 BOOL ret;
1700 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1701 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1703 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1704 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1705 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1706 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1707 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1708 DIB_RGB_COLORS, &bits, NULL, 0);
1709 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1711 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1712 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1714 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1715 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1716 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1718 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1719 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1720 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1721 ok( ret, "BitBlt(WHITENESS) failed\n" );
1723 hMetafile = CloseEnhMetaFile(hdcMetafile);
1724 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1726 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1727 "emf_BitBlt", FALSE) != 0)
1729 dump_emf_bits(hMetafile, "emf_BitBlt");
1730 dump_emf_records(hMetafile, "emf_BitBlt");
1733 SelectObject(hdcBitmap, hOldBitmap);
1734 DeleteObject(hBitmap);
1735 DeleteDC(hdcBitmap);
1736 DeleteDC(hdcDisplay);
1737 #undef BMP_DIM
1740 static void test_emf_DCBrush(void)
1742 HDC hdcMetafile;
1743 HENHMETAFILE hMetafile;
1744 HBRUSH hBrush;
1745 HPEN hPen;
1746 BOOL ret;
1747 COLORREF color;
1749 if (!pSetDCBrushColor || !pSetDCPenColor)
1751 win_skip( "SetDCBrush/PenColor not supported\n" );
1752 return;
1755 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1756 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1758 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1759 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1761 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1762 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1764 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1765 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1767 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1768 ok( color == 0, "SetDCPenColor returned %x\n", color );
1770 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1772 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1773 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1775 hMetafile = CloseEnhMetaFile(hdcMetafile);
1776 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1778 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1779 "emf_DC_Brush", FALSE ) != 0)
1781 dump_emf_bits(hMetafile, "emf_DC_Brush");
1782 dump_emf_records(hMetafile, "emf_DC_Brush");
1784 ret = DeleteEnhMetaFile(hMetafile);
1785 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1786 ret = DeleteObject(hBrush);
1787 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1788 ret = DeleteObject(hPen);
1789 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1792 /* Test a blank metafile. May be used as a template for new tests. */
1794 static void test_mf_Blank(void)
1796 HDC hdcMetafile;
1797 HMETAFILE hMetafile;
1798 INT caps;
1799 BOOL ret;
1800 INT type;
1802 hdcMetafile = CreateMetaFileA(NULL);
1803 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1804 trace("hdcMetafile %p\n", hdcMetafile);
1806 /* Tests on metafile initialization */
1807 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1808 ok (caps == DT_METAFILE,
1809 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1811 hMetafile = CloseMetaFile(hdcMetafile);
1812 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1813 type = GetObjectType(hMetafile);
1814 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1815 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1817 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1818 "mf_blank") != 0)
1820 dump_mf_bits(hMetafile, "mf_Blank");
1821 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1824 ret = DeleteMetaFile(hMetafile);
1825 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1828 static void test_CopyMetaFile(void)
1830 HDC hdcMetafile;
1831 HMETAFILE hMetafile, hmf_copy;
1832 BOOL ret;
1833 char temp_path[MAX_PATH];
1834 char mf_name[MAX_PATH];
1835 INT type;
1837 hdcMetafile = CreateMetaFileA(NULL);
1838 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1839 trace("hdcMetafile %p\n", hdcMetafile);
1841 hMetafile = CloseMetaFile(hdcMetafile);
1842 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1843 type = GetObjectType(hMetafile);
1844 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1846 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1847 "mf_blank") != 0)
1849 dump_mf_bits(hMetafile, "mf_Blank");
1850 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1853 GetTempPathA(MAX_PATH, temp_path);
1854 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1856 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1857 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1859 type = GetObjectType(hmf_copy);
1860 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1862 ret = DeleteMetaFile(hMetafile);
1863 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1865 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1867 dump_mf_bits(hmf_copy, "mf_Blank");
1868 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1871 ret = DeleteMetaFile(hmf_copy);
1872 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1874 DeleteFileA(mf_name);
1877 static void test_SetMetaFileBits(void)
1879 HMETAFILE hmf;
1880 INT type;
1881 BOOL ret;
1882 BYTE buf[256];
1883 METAHEADER *mh;
1885 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1886 trace("hmf %p\n", hmf);
1887 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1888 type = GetObjectType(hmf);
1889 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1891 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1893 dump_mf_bits(hmf, "mf_Graphics");
1894 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1897 ret = DeleteMetaFile(hmf);
1898 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1900 /* NULL data crashes XP SP1 */
1901 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1903 /* Now with zero size */
1904 SetLastError(0xdeadbeef);
1905 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1906 trace("hmf %p\n", hmf);
1907 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1908 ok(GetLastError() == ERROR_INVALID_DATA ||
1909 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1910 "wrong error %d\n", GetLastError());
1912 /* Now with odd size */
1913 SetLastError(0xdeadbeef);
1914 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1915 trace("hmf %p\n", hmf);
1916 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1917 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1919 /* Now with zeroed out header fields */
1920 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1921 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1922 mh = (METAHEADER *)buf;
1923 /* corruption of any of the below fields leads to a failure */
1924 mh->mtType = 0;
1925 mh->mtVersion = 0;
1926 mh->mtHeaderSize = 0;
1927 SetLastError(0xdeadbeef);
1928 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1929 trace("hmf %p\n", hmf);
1930 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1931 ok(GetLastError() == ERROR_INVALID_DATA ||
1932 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1933 "wrong error %d\n", GetLastError());
1935 /* Now with corrupted mtSize field */
1936 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1937 mh = (METAHEADER *)buf;
1938 /* corruption of mtSize doesn't lead to a failure */
1939 mh->mtSize *= 2;
1940 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1941 trace("hmf %p\n", hmf);
1942 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1944 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1946 dump_mf_bits(hmf, "mf_Graphics");
1947 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1950 ret = DeleteMetaFile(hmf);
1951 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1953 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
1954 /* Now with zeroed out mtSize field */
1955 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1956 mh = (METAHEADER *)buf;
1957 /* zeroing mtSize doesn't lead to a failure */
1958 mh->mtSize = 0;
1959 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1960 trace("hmf %p\n", hmf);
1961 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1963 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1965 dump_mf_bits(hmf, "mf_Graphics");
1966 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1969 ret = DeleteMetaFile(hmf);
1970 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1971 #endif
1974 /* Simple APIs from mfdrv/graphics.c
1977 static void test_mf_Graphics(void)
1979 HDC hdcMetafile;
1980 HMETAFILE hMetafile;
1981 POINT oldpoint;
1982 BOOL ret;
1984 hdcMetafile = CreateMetaFileA(NULL);
1985 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1986 trace("hdcMetafile %p\n", hdcMetafile);
1988 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1989 ok( ret, "MoveToEx error %d.\n", GetLastError());
1990 ret = LineTo(hdcMetafile, 2, 2);
1991 ok( ret, "LineTo error %d.\n", GetLastError());
1992 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1993 ok( ret, "MoveToEx error %d.\n", GetLastError());
1995 /* oldpoint gets garbage under Win XP, so the following test would
1996 * work under Wine but fails under Windows:
1998 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1999 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2000 * oldpoint.x, oldpoint.y);
2003 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2004 ok( ret, "Ellipse error %d.\n", GetLastError());
2006 hMetafile = CloseMetaFile(hdcMetafile);
2007 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2008 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2010 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2011 "mf_Graphics") != 0)
2013 dump_mf_bits(hMetafile, "mf_Graphics");
2014 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2017 ret = DeleteMetaFile(hMetafile);
2018 ok( ret, "DeleteMetaFile(%p) error %d\n",
2019 hMetafile, GetLastError());
2022 static void test_mf_PatternBrush(void)
2024 HDC hdcMetafile;
2025 HMETAFILE hMetafile;
2026 LOGBRUSH *orig_lb;
2027 HBRUSH hBrush;
2028 BOOL ret;
2030 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2032 orig_lb->lbStyle = BS_PATTERN;
2033 orig_lb->lbColor = RGB(0, 0, 0);
2034 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2035 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2037 hBrush = CreateBrushIndirect (orig_lb);
2038 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2040 hdcMetafile = CreateMetaFileA(NULL);
2041 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2042 trace("hdcMetafile %p\n", hdcMetafile);
2044 hBrush = SelectObject(hdcMetafile, hBrush);
2045 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2047 hMetafile = CloseMetaFile(hdcMetafile);
2048 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2049 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2051 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2052 "mf_Pattern_Brush") != 0)
2054 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2055 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2058 ret = DeleteMetaFile(hMetafile);
2059 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2060 ret = DeleteObject(hBrush);
2061 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2062 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2063 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2064 GetLastError());
2065 HeapFree (GetProcessHeap(), 0, orig_lb);
2068 static void test_mf_DCBrush(void)
2070 HDC hdcMetafile;
2071 HMETAFILE hMetafile;
2072 HBRUSH hBrush;
2073 HPEN hPen;
2074 BOOL ret;
2075 COLORREF color;
2077 if (!pSetDCBrushColor || !pSetDCPenColor)
2079 win_skip( "SetDCBrush/PenColor not supported\n" );
2080 return;
2083 hdcMetafile = CreateMetaFileA(NULL);
2084 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2086 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2087 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2089 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2090 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2092 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2093 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2095 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2096 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2098 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2100 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2101 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2103 hMetafile = CloseMetaFile(hdcMetafile);
2104 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2106 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2108 dump_mf_bits(hMetafile, "mf_DCBrush");
2109 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2111 ret = DeleteMetaFile(hMetafile);
2112 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2115 static void test_mf_ExtTextOut_on_path(void)
2117 HDC hdcMetafile;
2118 HMETAFILE hMetafile;
2119 BOOL ret;
2120 static const INT dx[4] = { 3, 5, 8, 12 };
2122 hdcMetafile = CreateMetaFileA(NULL);
2123 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2124 trace("hdcMetafile %p\n", hdcMetafile);
2126 ret = BeginPath(hdcMetafile);
2127 ok(!ret, "BeginPath on metafile DC should fail\n");
2129 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2130 ok(ret, "ExtTextOut error %d\n", GetLastError());
2132 ret = EndPath(hdcMetafile);
2133 ok(!ret, "EndPath on metafile DC should fail\n");
2135 hMetafile = CloseMetaFile(hdcMetafile);
2136 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2138 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2139 "mf_TextOut_on_path") != 0)
2141 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2142 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2145 ret = DeleteMetaFile(hMetafile);
2146 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2149 static void test_emf_ExtTextOut_on_path(void)
2151 HWND hwnd;
2152 HDC hdcDisplay, hdcMetafile;
2153 HENHMETAFILE hMetafile;
2154 BOOL ret;
2155 static const INT dx[4] = { 3, 5, 8, 12 };
2157 /* Win9x doesn't play EMFs on invisible windows */
2158 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2159 0, 0, 200, 200, 0, 0, 0, NULL);
2160 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2162 hdcDisplay = GetDC(hwnd);
2163 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2165 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2166 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2168 ret = BeginPath(hdcMetafile);
2169 ok(ret, "BeginPath error %d\n", GetLastError());
2171 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2172 ok(ret, "ExtTextOut error %d\n", GetLastError());
2174 ret = EndPath(hdcMetafile);
2175 ok(ret, "EndPath error %d\n", GetLastError());
2177 hMetafile = CloseEnhMetaFile(hdcMetafile);
2178 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2180 /* this doesn't succeed yet: EMF has correct size, all EMF records
2181 * are there, but their contents don't match for different reasons.
2183 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2184 "emf_TextOut_on_path", FALSE) != 0)
2186 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2187 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2190 ret = DeleteEnhMetaFile(hMetafile);
2191 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2192 ret = ReleaseDC(hwnd, hdcDisplay);
2193 ok(ret, "ReleaseDC error %d\n", GetLastError());
2194 DestroyWindow(hwnd);
2197 static const unsigned char EMF_CLIPPING[] =
2199 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2201 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2203 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2204 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2205 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2206 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2208 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2209 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2211 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2212 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2213 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2214 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2215 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2216 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2217 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2218 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2219 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2220 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2221 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2222 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2223 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2224 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2227 static void translate( POINT *pt, UINT count, const XFORM *xform )
2229 while (count--)
2231 FLOAT x = (FLOAT)pt->x;
2232 FLOAT y = (FLOAT)pt->y;
2233 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2234 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2235 pt++;
2239 /* Compare rectangles allowing rounding errors */
2240 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2242 return abs(rc1->left - rc2->left) <= 1 &&
2243 abs(rc1->top - rc2->top) <= 1 &&
2244 abs(rc1->right - rc2->right) <= 1 &&
2245 abs(rc1->bottom - rc2->bottom) <= 1;
2248 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2249 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2251 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2253 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2254 union _rgn
2256 RGNDATA data;
2257 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2259 const union _rgn *rgn1;
2260 union _rgn rgn2;
2261 RECT rect, rc_transformed;
2262 const RECT *rc = (const RECT *)param;
2263 HRGN hrgn;
2264 XFORM xform;
2265 INT ret;
2266 BOOL is_win9x;
2268 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2269 clip->cbRgnData, clip->iMode);
2271 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2272 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2273 "too small data block: %u bytes\n", clip->cbRgnData);
2274 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2275 return 0;
2277 rgn1 = (const union _rgn *)clip->RgnData;
2279 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2280 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2281 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2282 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2283 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2285 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2287 rect = *(const RECT *)rgn1->data.Buffer;
2288 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2289 ok(EqualRect(&rect, rc), "rects don't match\n");
2291 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2292 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2293 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2294 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2295 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2296 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2298 hrgn = CreateRectRgn(0, 0, 0, 0);
2300 memset(&xform, 0, sizeof(xform));
2301 SetLastError(0xdeadbeef);
2302 ret = GetWorldTransform(hdc, &xform);
2303 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2304 if (!is_win9x)
2305 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2307 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2309 ret = GetClipRgn(hdc, hrgn);
2310 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2312 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2314 ret = GetClipRgn(hdc, hrgn);
2315 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2317 /* Win9x returns empty clipping region */
2318 if (is_win9x) return 1;
2320 ret = GetRegionData(hrgn, 0, NULL);
2321 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2323 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2324 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2326 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2327 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2328 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2329 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2330 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2332 rect = rgn2.data.rdh.rcBound;
2333 rc_transformed = *rc;
2334 translate((POINT *)&rc_transformed, 2, &xform);
2335 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2336 rc_transformed.right, rc_transformed.bottom);
2337 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2339 rect = *(const RECT *)rgn2.data.Buffer;
2340 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2341 rc_transformed = *rc;
2342 translate((POINT *)&rc_transformed, 2, &xform);
2343 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2344 rc_transformed.right, rc_transformed.bottom);
2345 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2347 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2348 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2349 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2350 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2351 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2352 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2354 DeleteObject(hrgn);
2356 return 1;
2359 static void test_emf_clipping(void)
2361 static const RECT rc = { 0, 0, 100, 100 };
2362 RECT rc_clip = { 100, 100, 1024, 1024 };
2363 HWND hwnd;
2364 HDC hdc;
2365 HENHMETAFILE hemf;
2366 HRGN hrgn;
2367 INT ret;
2368 RECT rc_res, rc_sclip;
2370 SetLastError(0xdeadbeef);
2371 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2372 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2374 /* Need to write something to the emf, otherwise Windows won't play it back */
2375 LineTo(hdc, 1, 1);
2377 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2378 ret = SelectClipRgn(hdc, hrgn);
2379 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2381 SetLastError(0xdeadbeef);
2382 hemf = CloseEnhMetaFile(hdc);
2383 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2385 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2386 "emf_clipping", FALSE) != 0)
2388 dump_emf_bits(hemf, "emf_clipping");
2389 dump_emf_records(hemf, "emf_clipping");
2392 DeleteObject(hrgn);
2394 /* Win9x doesn't play EMFs on invisible windows */
2395 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2396 0, 0, 200, 200, 0, 0, 0, NULL);
2397 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2399 hdc = GetDC(hwnd);
2401 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2402 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2404 DeleteEnhMetaFile(hemf);
2405 ReleaseDC(hwnd, hdc);
2406 DestroyWindow(hwnd);
2408 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2410 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2411 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2412 SelectClipRgn(hdc, hrgn);
2413 ret = GetClipBox(hdc, &rc_res);
2414 todo_wine
2415 ok(ret == SIMPLEREGION, "got %d\n", ret);
2416 if(ret == SIMPLEREGION)
2417 ok(EqualRect(&rc_res, &rc_sclip),
2418 "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2419 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2420 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2422 hemf = CloseEnhMetaFile(hdc);
2423 DeleteEnhMetaFile(hemf);
2424 DeleteObject(hrgn);
2425 DeleteDC(hdc);
2428 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2430 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2431 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2432 /* When using MM_TEXT Win9x does not update the mapping mode
2433 * until a record is played which actually outputs something */
2434 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2435 LPtoDP(hdc, mapping, 2);
2436 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2437 lpEMFR->iType, lpEMFR->nSize,
2438 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2440 if (lpEMFR->iType == EMR_LINETO)
2442 INT x0, y0, x1, y1;
2443 if (!lpMFP || lpMFP->mm == MM_TEXT)
2445 x0 = 0;
2446 y0 = 0;
2447 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2448 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2450 else
2452 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2454 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2455 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2456 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2457 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2459 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2460 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2461 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2462 x0, y0, x1, y1);
2464 return TRUE;
2467 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2469 HDC hdcMf;
2470 HMETAFILE hmf;
2471 HENHMETAFILE hemf;
2472 BOOL ret;
2473 UINT size;
2474 LPBYTE pBits;
2476 hdcMf = CreateMetaFile(NULL);
2477 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2478 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2479 ok(ret, "LineTo failed with error %d\n", GetLastError());
2480 hmf = CloseMetaFile(hdcMf);
2481 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2483 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2485 dump_mf_bits(hmf, "mf_LineTo");
2486 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2489 size = GetMetaFileBitsEx(hmf, 0, NULL);
2490 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2491 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2492 GetMetaFileBitsEx(hmf, size, pBits);
2493 DeleteMetaFile(hmf);
2494 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2495 HeapFree(GetProcessHeap(), 0, pBits);
2496 return hemf;
2499 static void test_mf_conversions(void)
2501 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2503 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2504 HENHMETAFILE hemf;
2505 METAFILEPICT mfp;
2506 RECT rect = { 0, 0, 100, 100 };
2507 mfp.mm = MM_ANISOTROPIC;
2508 mfp.xExt = 100;
2509 mfp.yExt = 100;
2510 mfp.hMF = NULL;
2511 hemf = create_converted_emf(&mfp);
2513 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2514 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2516 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2517 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2520 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2522 DeleteEnhMetaFile(hemf);
2523 DeleteDC(hdcOffscreen);
2526 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2528 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2529 HENHMETAFILE hemf;
2530 METAFILEPICT mfp;
2531 RECT rect = { 0, 0, 100, 100 };
2532 mfp.mm = MM_TEXT;
2533 mfp.xExt = 0;
2534 mfp.yExt = 0;
2535 mfp.hMF = NULL;
2536 hemf = create_converted_emf(&mfp);
2538 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2539 "emf_LineTo MM_TEXT", TRUE) != 0)
2541 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2542 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2545 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2547 DeleteEnhMetaFile(hemf);
2548 DeleteDC(hdcOffscreen);
2551 trace("Testing MF->EMF conversion (NULL mfp)\n");
2553 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2554 HENHMETAFILE hemf;
2555 RECT rect = { 0, 0, 100, 100 };
2556 hemf = create_converted_emf(NULL);
2558 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2559 "emf_LineTo NULL", TRUE) != 0)
2561 dump_emf_bits(hemf, "emf_LineTo NULL");
2562 dump_emf_records(hemf, "emf_LineTo NULL");
2565 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2567 DeleteEnhMetaFile(hemf);
2568 DeleteDC(hdcOffscreen);
2572 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2573 LONG mm, LONG xExt, LONG yExt,
2574 RECTL * rclBounds, RECTL * rclFrame)
2576 METAFILEPICT mfp;
2577 METAFILEPICT * mfpPtr = NULL;
2578 HENHMETAFILE emf;
2579 ENHMETAHEADER header;
2580 UINT res;
2582 if (!mfpIsNull)
2584 mfp.mm = mm;
2585 mfp.xExt = xExt;
2586 mfp.yExt = yExt;
2587 mfpPtr = &mfp;
2590 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2591 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2592 if (!emf) return FALSE;
2593 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2594 ok(res != 0, "GetEnhMetaHeader failed\n");
2595 DeleteEnhMetaFile(emf);
2596 if (!res) return FALSE;
2598 *rclBounds = header.rclBounds;
2599 *rclFrame = header.rclFrame;
2600 return TRUE;
2603 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2604 LONG mm, LONG xExt, LONG yExt,
2605 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2607 RECTL rclBounds, rclFrame;
2609 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2611 const char * msg;
2612 char buf[64];
2614 if (mfpIsNull)
2616 msg = "mfp == NULL";
2618 else
2620 const char * mm_str;
2621 switch (mm)
2623 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2624 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2625 default: mm_str = "Unexpected";
2627 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2628 msg = buf;
2631 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2632 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2633 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2634 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2635 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2636 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2637 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2638 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2642 static void test_SetWinMetaFileBits(void)
2644 HMETAFILE wmf;
2645 HDC wmfDC;
2646 BYTE * buffer;
2647 UINT buffer_size;
2648 RECT rect;
2649 UINT res;
2650 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2651 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2652 RECTL rclBounds, rclFrame;
2653 HDC dc;
2654 LONG diffx, diffy;
2656 wmfDC = CreateMetaFile(NULL);
2657 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2658 if (!wmfDC) return;
2660 SetWindowExtEx(wmfDC, 100, 100, NULL);
2661 rect.left = rect.top = 0;
2662 rect.right = rect.bottom = 50;
2663 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2664 wmf = CloseMetaFile(wmfDC);
2665 ok(wmf != NULL, "Metafile creation failed\n");
2666 if (!wmf) return;
2668 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2669 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2670 if (buffer_size == 0)
2672 DeleteMetaFile(wmf);
2673 return;
2676 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2677 ok(buffer != NULL, "HeapAlloc failed\n");
2678 if (!buffer)
2680 DeleteMetaFile(wmf);
2681 return;
2684 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2685 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2686 DeleteMetaFile(wmf);
2687 if (res != buffer_size)
2689 HeapFree(GetProcessHeap(), 0, buffer);
2690 return;
2693 /* Get the reference bounds and frame */
2694 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2695 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2697 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2698 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2699 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2701 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2702 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2703 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2704 if (diffx < 0) diffx = -diffx;
2705 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2707 dc = CreateCompatibleDC(NULL);
2709 /* Allow 1 mm difference (rounding errors) */
2710 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2711 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2712 if (diffx < 0) diffx = -diffx;
2713 if (diffy < 0) diffy = -diffy;
2714 todo_wine
2716 ok(diffx <= 1 && diffy <= 1,
2717 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2718 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2721 /* Allow 1 mm difference (rounding errors) */
2722 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2723 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2724 if (diffx < 0) diffx = -diffx;
2725 if (diffy < 0) diffy = -diffy;
2726 todo_wine
2728 ok(diffx <= 1 && diffy <= 1,
2729 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2730 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2732 DeleteDC(dc);
2734 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2735 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2737 /* If xExt or yExt is zero or negative, the whole device surface is used */
2738 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2739 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2740 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2741 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2742 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2743 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2744 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2745 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2746 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2747 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2748 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2749 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2751 /* MSDN says that negative xExt and yExt values specify a ratio.
2752 Check that this is wrong and the whole device surface is used */
2753 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2754 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2756 /* Ordinary conversions */
2758 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2760 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2761 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2762 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2763 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2766 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2768 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2769 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2770 ok(rclBounds.left == 0 && rclBounds.top == 0,
2771 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2773 /* Wine has a rounding error */
2774 diffx = rclBounds.right - rclBounds.bottom;
2775 if (diffx < 0) diffx = -diffx;
2776 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2779 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2781 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2782 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2785 HeapFree(GetProcessHeap(), 0, buffer);
2788 static BOOL near_match(int x, int y)
2790 int epsilon = min(abs(x), abs(y));
2792 epsilon = max(epsilon/100, 2);
2794 if(x < y - epsilon || x > y + epsilon) return FALSE;
2795 return TRUE;
2798 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2800 HENHMETAFILE emf;
2801 HDC display_dc, emf_dc;
2802 ENHMETAHEADER *enh_header;
2803 UINT size, emf_size, i;
2804 WORD check = 0;
2805 DWORD rec_num = 0;
2806 METAHEADER *mh = NULL;
2807 METARECORD *rec;
2808 INT horz_res, vert_res, horz_size, vert_size;
2809 INT curve_caps, line_caps, poly_caps;
2811 display_dc = GetDC(NULL);
2812 ok(display_dc != NULL, "display_dc is NULL\n");
2814 horz_res = GetDeviceCaps(display_dc, HORZRES);
2815 vert_res = GetDeviceCaps(display_dc, VERTRES);
2816 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2817 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2819 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2820 ok(emf_dc != NULL, "emf_dc is NULL\n");
2822 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
2823 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
2825 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
2826 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
2828 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
2829 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
2831 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2832 Rectangle(emf_dc, 0, 0, 1000, 20);
2833 emf = CloseEnhMetaFile(emf_dc);
2834 ok(emf != NULL, "emf is NULL\n");
2836 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2837 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2838 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2839 DeleteEnhMetaFile(emf);
2840 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2841 have different resolutions */
2842 enh_header->szlDevice.cx *= scale;
2843 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2844 ok(emf != NULL, "emf is NULL\n");
2845 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2847 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2848 ok(size ||
2849 broken(size == 0), /* some versions of winxp fail for some reason */
2850 "GetWinMetaFileBits returns 0\n");
2851 if(!size) goto end;
2852 mh = HeapAlloc(GetProcessHeap(), 0, size);
2853 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2855 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2856 ok(check == 0, "check %04x\n", check);
2858 rec = (METARECORD*)(mh + 1);
2860 while(rec->rdSize && rec->rdFunction)
2862 const DWORD chunk_size = 0x2000;
2863 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2865 if(rec_num < mfcomment_chunks)
2867 DWORD this_chunk_size = chunk_size;
2869 if(rec_num == mfcomment_chunks - 1)
2870 this_chunk_size = emf_size - rec_num * chunk_size;
2872 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2873 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2874 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2875 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2876 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2877 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2878 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
2879 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2880 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2881 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2882 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2883 /* parm[8] is the checksum, tested above */
2884 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2885 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2886 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2887 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2888 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2889 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2890 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2891 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 */
2892 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2893 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2896 else if(rec_num == mfcomment_chunks)
2898 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2899 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2901 else if(rec_num == mfcomment_chunks + 1)
2903 POINT pt;
2904 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2905 switch(mode)
2907 case MM_TEXT:
2908 case MM_ISOTROPIC:
2909 case MM_ANISOTROPIC:
2910 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2911 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2912 break;
2913 case MM_LOMETRIC:
2914 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2915 pt.x = MulDiv( rc->left, 1, 10);
2916 break;
2917 case MM_HIMETRIC:
2918 pt.y = -rc->top + 1;
2919 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2920 break;
2921 case MM_LOENGLISH:
2922 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2923 pt.x = MulDiv( rc->left, 10, 254);
2924 break;
2925 case MM_HIENGLISH:
2926 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2927 pt.x = MulDiv( rc->left, 100, 254);
2928 break;
2929 case MM_TWIPS:
2930 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2931 pt.x = MulDiv( rc->left, 72 * 20, 2540);
2932 break;
2933 default:
2934 pt.x = pt.y = 0;
2936 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2937 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2939 if(rec_num == mfcomment_chunks + 2)
2941 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2942 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
2943 "got %d\n", (short)rec->rdParm[0]);
2944 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
2945 "got %d\n", (short)rec->rdParm[1]);
2948 rec_num++;
2949 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2952 end:
2953 HeapFree(GetProcessHeap(), 0, mh);
2954 HeapFree(GetProcessHeap(), 0, enh_header);
2955 DeleteEnhMetaFile(emf);
2957 ReleaseDC(NULL, display_dc);
2960 static void test_GetWinMetaFileBits(void)
2962 UINT mode;
2963 RECT frames[] =
2965 { 1000, 2000, 3000, 6000},
2966 {-1000, 2000, 3000, 6000},
2967 { 1000, -2000, 3000, 6000},
2968 { 1005, 2005, 3000, 6000},
2969 {-1005, -2005, 3000, 6000},
2970 {-1005, -2010, 3000, 6000},
2971 {-1005, 2010, 3000, 6000},
2972 { 0, 0, 1, 1},
2973 { -1, -1, 1, 1},
2974 { 0, 0, 0, 0}
2977 for(mode = MM_MIN; mode <= MM_MAX; mode++)
2979 RECT *rc;
2980 trace("mode %d\n", mode);
2982 for(rc = frames; rc->right - rc->left > 0; rc++)
2984 trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
2985 getwinmetafilebits(mode, 1, rc);
2986 getwinmetafilebits(mode, 2, rc);
2991 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2992 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2993 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2995 static void test_gdiis(void)
2997 RECT rect = {0,0,100,100};
2998 HDC hdc, hemfDC, hmfDC;
2999 HENHMETAFILE hemf;
3000 HMODULE hgdi32;
3002 /* resolve all the functions */
3003 hgdi32 = GetModuleHandle("gdi32");
3004 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3005 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3006 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3008 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3010 win_skip("Needed GdiIs* functions are not available\n");
3011 return;
3014 /* try with nothing */
3015 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3016 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3017 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3019 /* try with a metafile */
3020 hmfDC = CreateMetaFile(NULL);
3021 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3022 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3023 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3024 DeleteMetaFile(CloseMetaFile(hmfDC));
3026 /* try with an enhanced metafile */
3027 hdc = GetDC(NULL);
3028 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3029 ok(hemfDC != NULL, "failed to create emf\n");
3031 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3032 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3033 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3035 hemf = CloseEnhMetaFile(hemfDC);
3036 ok(hemf != NULL, "failed to close EMF\n");
3037 DeleteEnhMetaFile(hemf);
3038 ReleaseDC(NULL,hdc);
3041 static void test_SetEnhMetaFileBits(void)
3043 BYTE data[256];
3044 HENHMETAFILE hemf;
3045 ENHMETAHEADER *emh;
3047 memset(data, 0xAA, sizeof(data));
3048 SetLastError(0xdeadbeef);
3049 hemf = SetEnhMetaFileBits(sizeof(data), data);
3050 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3051 ok(GetLastError() == ERROR_INVALID_DATA ||
3052 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3053 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3055 emh = (ENHMETAHEADER *)data;
3056 memset(emh, 0, sizeof(*emh));
3058 emh->iType = EMR_HEADER;
3059 emh->nSize = sizeof(*emh);
3060 emh->dSignature = ENHMETA_SIGNATURE;
3061 /* emh->nVersion = 0x10000; XP doesn't care about version */
3062 emh->nBytes = sizeof(*emh);
3063 /* emh->nRecords = 1; XP doesn't care about records */
3064 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3066 SetLastError(0xdeadbeef);
3067 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3068 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3069 DeleteEnhMetaFile(hemf);
3071 /* XP refuses to load unaligned EMF */
3072 emh->nBytes++;
3073 SetLastError(0xdeadbeef);
3074 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3075 ok(!hemf ||
3076 broken(hemf != NULL), /* Win9x, WinMe */
3077 "SetEnhMetaFileBits should fail\n");
3078 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3079 DeleteEnhMetaFile(hemf);
3081 emh->dSignature = 0;
3082 emh->nBytes--;
3083 SetLastError(0xdeadbeef);
3084 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3085 ok(!hemf ||
3086 broken(hemf != NULL), /* Win9x, WinMe */
3087 "SetEnhMetaFileBits should fail\n");
3088 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3089 DeleteEnhMetaFile(hemf);
3092 START_TEST(metafile)
3094 init_function_pointers();
3096 /* For enhanced metafiles (enhmfdrv) */
3097 test_ExtTextOut();
3098 test_ExtTextOutScale();
3099 test_SaveDC();
3100 test_emf_BitBlt();
3101 test_emf_DCBrush();
3103 /* For win-format metafiles (mfdrv) */
3104 test_mf_SaveDC();
3105 test_mf_Blank();
3106 test_mf_Graphics();
3107 test_mf_PatternBrush();
3108 test_mf_DCBrush();
3109 test_CopyMetaFile();
3110 test_SetMetaFileBits();
3111 test_mf_ExtTextOut_on_path();
3112 test_emf_ExtTextOut_on_path();
3113 test_emf_clipping();
3115 /* For metafile conversions */
3116 test_mf_conversions();
3117 test_SetWinMetaFileBits();
3118 test_GetWinMetaFileBits();
3120 test_gdiis();
3121 test_SetEnhMetaFileBits();