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
25 #include "wine/test.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 */
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
41 #define GDI_GET_PROC(func) \
42 p ## func = (void *)GetProcAddress(hGDI, #func); \
44 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
46 static void init_function_pointers(void)
53 hGDI = GetModuleHandleA("gdi32.dll");
55 GDI_GET_PROC(GetRelAbs);
56 GDI_GET_PROC(SetRelAbs);
59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60 const ENHMETARECORD *emr, int n_objs, LPARAM param)
65 INT *orig_dx = (INT *)param;
69 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70 hdc, emr->iType, emr->nSize, (void *)param);
74 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
79 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
80 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
81 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
82 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
83 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
84 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
85 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
87 /* GetBkMode, GetRelAbs do not get reset to the default value */
88 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
89 if(pSetRelAbs && pGetRelAbs)
90 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
97 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
98 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
100 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
103 /* compare up to lfOutPrecision, other values are not interesting,
104 * and in fact sometimes arbitrary adapted by Win9x.
106 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
107 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
109 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
111 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
112 n_record, i, dx[i], orig_dx[i]);
115 emr_processed = TRUE;
119 case EMR_EXTTEXTOUTW:
121 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
124 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
125 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
127 /* compare up to lfOutPrecision, other values are not interesting,
128 * and in fact sometimes arbitrary adapted by Win9x.
130 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
131 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
133 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
135 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
136 n_record, i, dx[i], orig_dx[i]);
139 emr_processed = TRUE;
150 static void test_ExtTextOut(void)
153 HDC hdcDisplay, hdcMetafile;
154 HENHMETAFILE hMetafile;
156 static const char text[] = "Simple text to test ExtTextOut on metafiles";
158 static const RECT rc = { 0, 0, 100, 100 };
161 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
163 /* Win9x doesn't play EMFs on invisible windows */
164 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
165 0, 0, 200, 200, 0, 0, 0, NULL);
166 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
168 hdcDisplay = GetDC(hwnd);
169 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
171 trace("hdcDisplay %p\n", hdcDisplay);
173 SetMapMode(hdcDisplay, MM_TEXT);
175 memset(&orig_lf, 0, sizeof(orig_lf));
177 orig_lf.lfCharSet = ANSI_CHARSET;
178 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
179 orig_lf.lfWeight = FW_DONTCARE;
180 orig_lf.lfHeight = 7;
181 orig_lf.lfQuality = DEFAULT_QUALITY;
182 lstrcpyA(orig_lf.lfFaceName, "Arial");
183 hFont = CreateFontIndirectA(&orig_lf);
184 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
186 hFont = SelectObject(hdcDisplay, hFont);
188 len = lstrlenA(text);
189 for (i = 0; i < len; i++)
191 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
192 ok( ret, "GetCharWidthA error %d\n", GetLastError());
194 hFont = SelectObject(hdcDisplay, hFont);
196 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
199 trace("hdcMetafile %p\n", hdcMetafile);
201 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
202 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
204 hFont = SelectObject(hdcMetafile, hFont);
206 /* 1. pass NULL lpDx */
207 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
208 ok( ret, "ExtTextOutA error %d\n", GetLastError());
210 /* 2. pass custom lpDx */
211 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
212 ok( ret, "ExtTextOutA error %d\n", GetLastError());
214 hFont = SelectObject(hdcMetafile, hFont);
215 ret = DeleteObject(hFont);
216 ok( ret, "DeleteObject error %d\n", GetLastError());
218 hMetafile = CloseEnhMetaFile(hdcMetafile);
219 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
221 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
223 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
226 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
227 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
228 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
229 SetROP2(hdcDisplay, R2_NOT);
230 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
231 SetPolyFillMode(hdcDisplay, WINDING);
232 SetStretchBltMode(hdcDisplay, HALFTONE);
234 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
235 SetBkMode(hdcDisplay, OPAQUE);
237 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
238 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
240 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
241 "text align %08x\n", GetTextAlign(hdcDisplay));
242 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
243 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
244 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
245 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
246 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
247 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
249 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
251 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
252 "A valid hdc has to require a valid rc\n");
254 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
255 "A null hdc does not require a valid rc\n");
257 ret = DeleteEnhMetaFile(hMetafile);
258 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
259 ret = ReleaseDC(hwnd, hdcDisplay);
260 ok( ret, "ReleaseDC error %d\n", GetLastError());
264 static void check_dc_state(HDC hdc, int restore_no,
265 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
266 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
270 POINT vp_org, win_org;
271 SIZE vp_size, win_size;
272 FLOAT xscale, yscale, edx, edy;
274 SetLastError(0xdeadbeef);
275 ret = GetWorldTransform(hdc, &xform);
276 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
277 ok(ret, "GetWorldTransform error %u\n", GetLastError());
279 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
281 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
282 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
284 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
285 trace("x scale %f\n", xscale);
286 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
287 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
289 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
290 trace("y scale %f\n", yscale);
291 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
292 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
294 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
295 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
296 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
297 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
303 GetWindowOrgEx(hdc, &win_org);
304 GetViewportOrgEx(hdc, &vp_org);
305 GetWindowExtEx(hdc, &win_size);
306 GetViewportExtEx(hdc, &vp_size);
308 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
309 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
311 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
312 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
314 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
315 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
317 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
318 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
321 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
322 const ENHMETARECORD *emr, int n_objs, LPARAM param)
328 static int save_state;
329 static int restore_no;
331 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
332 hdc, emr->iType, emr->nSize, (void *)param);
335 SetLastError(0xdeadbeef);
336 ret = GetWorldTransform(hdc, &xform);
337 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
339 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
340 trace("window org (%d,%d)\n", pt.x, pt.y);
341 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
342 trace("vport org (%d,%d)\n", pt.x, pt.y);
343 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
344 trace("window ext (%d,%d)\n", size.cx, size.cy);
345 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
346 trace("vport ext (%d,%d)\n", size.cx, size.cy);
350 ok(ret, "GetWorldTransform error %u\n", GetLastError());
351 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
354 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
360 static RECT exp_bounds = { 0, 0, 150, 150 };
362 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
364 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
365 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
366 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
367 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
368 emf->szlDevice.cx, emf->szlDevice.cy);
370 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
371 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
375 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
381 const EMRLINETO *line = (const EMRLINETO *)emr;
382 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
385 case EMR_SETWINDOWORGEX:
387 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
388 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
391 case EMR_SETWINDOWEXTEX:
393 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
394 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
397 case EMR_SETVIEWPORTORGEX:
399 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
400 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
403 case EMR_SETVIEWPORTEXTEX:
405 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
406 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
411 trace("EMR_SAVEDC\n");
416 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
417 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
422 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
423 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
426 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
427 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
430 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
431 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
434 ok(restore_no <= 3, "restore_no %d\n", restore_no);
435 save_state += restoredc->iRelative;
439 ok(save_state == 0, "EOF save_state %d\n", save_state);
444 SetLastError(0xdeadbeef);
445 ret = GetWorldTransform(hdc, &xform);
446 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
448 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
449 trace("window org (%d,%d)\n", pt.x, pt.y);
450 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
451 trace("vport org (%d,%d)\n", pt.x, pt.y);
452 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
453 trace("window ext (%d,%d)\n", size.cx, size.cy);
454 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
455 trace("vport ext (%d,%d)\n", size.cx, size.cy);
459 ok(ret, "GetWorldTransform error %u\n", GetLastError());
460 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
466 static void test_SaveDC(void)
468 HDC hdcMetafile, hdcDisplay;
469 HENHMETAFILE hMetafile;
472 static const RECT rc = { 0, 0, 150, 150 };
474 /* Win9x doesn't play EMFs on invisible windows */
475 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
476 0, 0, 200, 200, 0, 0, 0, NULL);
477 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
479 hdcDisplay = GetDC(hwnd);
480 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
482 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
483 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
485 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
487 /* Need to write something to the emf, otherwise Windows won't play it back */
488 LineTo(hdcMetafile, 150, 150);
490 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
491 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
492 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
493 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
495 /* Force Win9x to update DC state */
496 SetPixelV(hdcMetafile, 50, 50, 0);
498 ret = SaveDC(hdcMetafile);
499 ok(ret == 1, "ret = %d\n", ret);
501 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
502 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
503 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
504 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
506 /* Force Win9x to update DC state */
507 SetPixelV(hdcMetafile, 50, 50, 0);
509 ret = SaveDC(hdcMetafile);
510 ok(ret == 2, "ret = %d\n", ret);
512 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
513 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
514 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
515 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
517 /* Force Win9x to update DC state */
518 SetPixelV(hdcMetafile, 50, 50, 0);
520 ret = SaveDC(hdcMetafile);
521 ok(ret == 3, "ret = %d\n", ret);
523 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
524 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
525 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
526 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
528 /* Force Win9x to update DC state */
529 SetPixelV(hdcMetafile, 50, 50, 0);
531 ret = RestoreDC(hdcMetafile, -1);
532 ok(ret, "ret = %d\n", ret);
534 ret = SaveDC(hdcMetafile);
535 ok(ret == 3, "ret = %d\n", ret);
537 ret = RestoreDC(hdcMetafile, 1);
538 ok(ret, "ret = %d\n", ret);
540 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
541 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
542 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
543 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
545 /* Force Win9x to update DC state */
546 SetPixelV(hdcMetafile, 50, 50, 0);
548 ret = SaveDC(hdcMetafile);
549 ok(ret == 1, "ret = %d\n", ret);
551 ret = SaveDC(hdcMetafile);
552 ok(ret == 2, "ret = %d\n", ret);
554 hMetafile = CloseEnhMetaFile(hdcMetafile);
555 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
557 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
558 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
560 ret = DeleteEnhMetaFile(hMetafile);
561 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
562 ret = ReleaseDC(hwnd, hdcDisplay);
563 ok( ret, "ReleaseDC error %d\n", GetLastError());
567 /* Win-format metafile (mfdrv) tests */
568 /* These tests compare the generated metafiles byte-by-byte */
569 /* with the nominal results. */
571 /* Maximum size of sample metafiles in bytes. */
572 #define MF_BUFSIZE 512
574 /* 8x8 bitmap data for a pattern brush */
575 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
576 0x01, 0x00, 0x02, 0x00,
577 0x03, 0x00, 0x04, 0x00,
578 0x05, 0x00, 0x06, 0x00,
579 0x07, 0x00, 0x08, 0x00
582 /* Sample metafiles to be compared to the outputs of the
586 static const unsigned char MF_BLANK_BITS[] = {
587 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
588 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
592 static const unsigned char MF_GRAPHICS_BITS[] = {
593 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
596 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
597 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
598 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
599 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
600 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
601 0x00, 0x00, 0x00, 0x00
604 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
605 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
606 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
607 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
608 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
609 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
610 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
615 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
616 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
617 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
618 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
619 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
623 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
625 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
627 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
628 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
629 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
630 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
634 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
636 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
641 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
642 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
643 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
646 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
649 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
650 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
651 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
653 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
655 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
656 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
659 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
660 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
661 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
662 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
663 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
664 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
665 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
666 0x14, 0x00, 0x00, 0x00
669 static const unsigned char MF_LINETO_BITS[] = {
670 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
671 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
672 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
673 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
677 static const unsigned char EMF_LINETO_BITS[] = {
678 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
683 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
684 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
685 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
688 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
691 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
692 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
693 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
694 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
695 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
696 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
699 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
701 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
702 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
703 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
704 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
705 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
706 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
707 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
708 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
709 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
710 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
711 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
712 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
713 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
715 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
719 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
720 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
725 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
726 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
727 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
730 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
733 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
734 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
735 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
736 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
737 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
738 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
739 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
740 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
741 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
743 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
744 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
745 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
746 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
747 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
748 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
749 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
750 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
751 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
752 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
753 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
754 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
755 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
757 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
761 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
762 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
765 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
767 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
768 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
769 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
772 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
775 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
776 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
777 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
778 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
779 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
780 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
781 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
782 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
783 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
784 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
785 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
786 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
788 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
789 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
790 0x14, 0x00, 0x00, 0x00
793 /* For debugging or dumping the raw metafiles produced by
794 * new test functions.
796 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
797 INT nobj, LPARAM param)
799 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
800 hdc, mr->rdFunction, mr->rdSize, (void *)param);
804 /* For debugging or dumping the raw metafiles produced by
805 * new test functions.
808 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
810 BYTE buf[MF_BUFSIZE];
813 if (!winetest_debug) return;
815 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
816 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
818 printf ("MetaFile %s has bits:\n{\n ", desc);
819 for (i=0; i<mfsize; i++)
821 printf ("0x%02x", buf[i]);
832 /* Compare the metafile produced by a test function with the
833 * expected raw metafile data in "bits".
834 * Return value is 0 for a perfect match,
835 * -1 if lengths aren't equal,
836 * otherwise returns the number of non-matching bytes.
839 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
842 unsigned char buf[MF_BUFSIZE];
846 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
847 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
848 if (mfsize < MF_BUFSIZE)
849 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
850 desc, mfsize, bsize);
852 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
853 desc, mfsize, bsize);
858 for (i=0; i<bsize; i++)
860 if (buf[i] != bits[i])
863 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
864 desc, mfsize, bsize, diff);
869 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
871 unsigned char buf[MF_BUFSIZE];
872 DWORD mfsize, rd_size, i;
877 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
878 assert(hfile != INVALID_HANDLE_VALUE);
880 mfsize = GetFileSize(hfile, NULL);
881 assert(mfsize <= MF_BUFSIZE);
883 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
884 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
888 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
894 for (i=0; i<bsize; i++)
896 if (buf[i] != bits[i])
899 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
900 desc, mfsize, bsize, diff);
905 /* For debugging or dumping the raw EMFs produced by
906 * new test functions.
908 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
910 BYTE buf[MF_BUFSIZE];
913 if (!winetest_debug) return;
915 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
916 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
918 printf("EMF %s has bits:\n{\n ", desc);
919 for (i = 0; i < mfsize; i++)
921 printf ("0x%02x", buf[i]);
932 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
935 BYTE buf[MF_BUFSIZE];
938 if (!winetest_debug) return;
940 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
941 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
943 printf("EMF %s has records:\n", desc);
947 while(offset < mfsize)
949 EMR *emr = (EMR *)(emf + offset);
950 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
951 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
952 offset += emr->nSize;
956 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
961 if (!winetest_debug) return;
963 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
964 buf = (const BYTE *)emr;
965 for (i = 0; i < emr->nSize; i++)
967 printf ("0x%02x", buf[i]);
968 if (i == emr->nSize - 1)
978 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
979 const char *desc, BOOL ignore_scaling, BOOL todo)
983 if (emr1->iType != emr2->iType && todo)
987 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
988 desc, emr1->iType, emr2->iType);
992 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
993 desc, emr1->iType, emr2->iType);
995 if (emr1->nSize != emr2->nSize && todo)
999 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1000 desc, emr1->nSize, emr2->nSize);
1004 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1005 desc, emr1->nSize, emr2->nSize);
1007 /* iType and nSize mismatches are fatal */
1008 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1010 /* contents of EMR_GDICOMMENT are not interesting */
1011 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1013 /* different Windows versions setup DC scaling differently when
1014 * converting an old style metafile to an EMF.
1016 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1017 emr1->iType == EMR_SETVIEWPORTEXTEX))
1020 diff = memcmp(emr1->dParm, emr2->dParm, emr1->nSize - sizeof(EMR));
1024 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1027 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1031 dump_emf_record(emr1, "expected bits");
1032 dump_emf_record(emr2, "actual bits");
1035 return diff == 0 || todo; /* report all non-fatal record mismatches */
1038 /* Compare the EMF produced by a test function with the
1039 * expected raw EMF data in "bits".
1040 * Return value is 0 for a perfect match,
1041 * -1 if lengths aren't equal,
1042 * otherwise returns the number of non-matching bytes.
1044 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1045 UINT bsize, const char *desc,
1046 BOOL ignore_scaling, BOOL todo)
1048 unsigned char buf[MF_BUFSIZE];
1049 UINT mfsize, offset;
1050 const ENHMETAHEADER *emh1, *emh2;
1052 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1053 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1055 if (mfsize < MF_BUFSIZE)
1057 if (mfsize != bsize && todo)
1060 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1063 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1066 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1067 desc, mfsize, bsize);
1069 /* basic things must match */
1070 emh1 = (const ENHMETAHEADER *)bits;
1071 emh2 = (const ENHMETAHEADER *)buf;
1072 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1073 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1074 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1075 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1077 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1078 ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1079 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1080 if (todo && emh1->nBytes != emh2->nBytes)
1083 ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1086 ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1087 if (todo && emh1->nRecords != emh2->nRecords)
1090 ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1093 ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1095 offset = emh1->nSize;
1096 while (offset < emh1->nBytes)
1098 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset);
1099 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset);
1101 trace("EMF record %u, size %u/record %u, size %u\n",
1102 emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1104 if (!match_emf_record(emr1, emr2, desc, ignore_scaling, todo)) return -1;
1106 offset += emr1->nSize;
1111 /* Test a blank metafile. May be used as a template for new tests. */
1113 static void test_mf_Blank(void)
1116 HMETAFILE hMetafile;
1121 hdcMetafile = CreateMetaFileA(NULL);
1122 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1123 trace("hdcMetafile %p\n", hdcMetafile);
1125 /* Tests on metafile initialization */
1126 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1127 ok (caps == DT_METAFILE,
1128 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1130 hMetafile = CloseMetaFile(hdcMetafile);
1131 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1132 type = GetObjectType(hMetafile);
1133 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1134 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1136 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1139 dump_mf_bits(hMetafile, "mf_Blank");
1140 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1143 ret = DeleteMetaFile(hMetafile);
1144 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1147 static void test_CopyMetaFile(void)
1150 HMETAFILE hMetafile, hmf_copy;
1152 char temp_path[MAX_PATH];
1153 char mf_name[MAX_PATH];
1156 hdcMetafile = CreateMetaFileA(NULL);
1157 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1158 trace("hdcMetafile %p\n", hdcMetafile);
1160 hMetafile = CloseMetaFile(hdcMetafile);
1161 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1162 type = GetObjectType(hMetafile);
1163 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1165 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1168 dump_mf_bits(hMetafile, "mf_Blank");
1169 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1172 GetTempPathA(MAX_PATH, temp_path);
1173 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1175 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1176 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1178 type = GetObjectType(hmf_copy);
1179 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1181 ret = DeleteMetaFile(hMetafile);
1182 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1184 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1186 dump_mf_bits(hMetafile, "mf_Blank");
1187 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1190 ret = DeleteMetaFile(hmf_copy);
1191 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1193 DeleteFileA(mf_name);
1196 static void test_SetMetaFileBits(void)
1204 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1205 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1206 type = GetObjectType(hmf);
1207 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1209 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1211 dump_mf_bits(hmf, "mf_Graphics");
1212 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1215 ret = DeleteMetaFile(hmf);
1216 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1218 /* NULL data crashes XP SP1 */
1219 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1221 /* Now with not zero size */
1222 SetLastError(0xdeadbeef);
1223 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1224 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1225 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1227 /* Now with not even size */
1228 SetLastError(0xdeadbeef);
1229 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1230 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1231 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1233 /* Now with zeroed out or faked some header fields */
1234 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1235 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1236 mh = (METAHEADER *)buf;
1237 /* corruption of any of the below fields leads to a failure */
1240 mh->mtHeaderSize = 0;
1241 SetLastError(0xdeadbeef);
1242 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1243 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1244 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1246 /* Now with corrupted mtSize field */
1247 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1248 mh = (METAHEADER *)buf;
1249 /* corruption of mtSize doesn't lead to a failure */
1251 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1252 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1254 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1256 dump_mf_bits(hmf, "mf_Graphics");
1257 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1260 ret = DeleteMetaFile(hmf);
1261 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1263 /* Now with zeroed out mtSize field */
1264 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1265 mh = (METAHEADER *)buf;
1266 /* zeroing mtSize doesn't lead to a failure */
1268 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1269 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1271 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1273 dump_mf_bits(hmf, "mf_Graphics");
1274 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1277 ret = DeleteMetaFile(hmf);
1278 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1281 /* Simple APIs from mfdrv/graphics.c
1284 static void test_mf_Graphics(void)
1287 HMETAFILE hMetafile;
1291 hdcMetafile = CreateMetaFileA(NULL);
1292 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1293 trace("hdcMetafile %p\n", hdcMetafile);
1295 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1296 ok( ret, "MoveToEx error %d.\n", GetLastError());
1297 ret = LineTo(hdcMetafile, 2, 2);
1298 ok( ret, "LineTo error %d.\n", GetLastError());
1299 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1300 ok( ret, "MoveToEx error %d.\n", GetLastError());
1302 /* oldpoint gets garbage under Win XP, so the following test would
1303 * work under Wine but fails under Windows:
1305 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1306 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1307 * oldpoint.x, oldpoint.y);
1310 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1311 ok( ret, "Ellipse error %d.\n", GetLastError());
1313 hMetafile = CloseMetaFile(hdcMetafile);
1314 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1315 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1317 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1318 "mf_Graphics") != 0)
1320 dump_mf_bits(hMetafile, "mf_Graphics");
1321 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1324 ret = DeleteMetaFile(hMetafile);
1325 ok( ret, "DeleteMetaFile(%p) error %d\n",
1326 hMetafile, GetLastError());
1329 static void test_mf_PatternBrush(void)
1332 HMETAFILE hMetafile;
1337 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1339 orig_lb->lbStyle = BS_PATTERN;
1340 orig_lb->lbColor = RGB(0, 0, 0);
1341 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1342 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1344 hBrush = CreateBrushIndirect (orig_lb);
1345 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1347 hdcMetafile = CreateMetaFileA(NULL);
1348 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1349 trace("hdcMetafile %p\n", hdcMetafile);
1351 hBrush = SelectObject(hdcMetafile, hBrush);
1352 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1354 hMetafile = CloseMetaFile(hdcMetafile);
1355 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1356 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1358 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1359 "mf_Pattern_Brush") != 0)
1361 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1362 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1365 ret = DeleteMetaFile(hMetafile);
1366 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1367 ret = DeleteObject(hBrush);
1368 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1369 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1370 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1372 HeapFree (GetProcessHeap(), 0, orig_lb);
1375 static void test_mf_ExtTextOut_on_path(void)
1378 HMETAFILE hMetafile;
1380 static const INT dx[4] = { 3, 5, 8, 12 };
1382 hdcMetafile = CreateMetaFileA(NULL);
1383 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1384 trace("hdcMetafile %p\n", hdcMetafile);
1386 ret = BeginPath(hdcMetafile);
1387 ok(!ret, "BeginPath on metafile DC should fail\n");
1389 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1390 ok(ret, "ExtTextOut error %d\n", GetLastError());
1392 ret = EndPath(hdcMetafile);
1393 ok(!ret, "EndPath on metafile DC should fail\n");
1395 hMetafile = CloseMetaFile(hdcMetafile);
1396 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1398 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1399 "mf_TextOut_on_path") != 0)
1401 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1402 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1405 ret = DeleteMetaFile(hMetafile);
1406 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1409 static void test_emf_ExtTextOut_on_path(void)
1412 HDC hdcDisplay, hdcMetafile;
1413 HENHMETAFILE hMetafile;
1415 static const INT dx[4] = { 3, 5, 8, 12 };
1417 /* Win9x doesn't play EMFs on invisible windows */
1418 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1419 0, 0, 200, 200, 0, 0, 0, NULL);
1420 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1422 hdcDisplay = GetDC(hwnd);
1423 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1425 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1426 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1428 ret = BeginPath(hdcMetafile);
1429 ok(ret, "BeginPath error %d\n", GetLastError());
1431 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1432 ok(ret, "ExtTextOut error %d\n", GetLastError());
1434 ret = EndPath(hdcMetafile);
1435 ok(ret, "EndPath error %d\n", GetLastError());
1437 hMetafile = CloseEnhMetaFile(hdcMetafile);
1438 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1440 /* this doesn't succeed yet: EMF has correct size, all EMF records
1441 * are there, but their contents don't match for different reasons.
1443 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1444 "emf_TextOut_on_path", FALSE, TRUE) != 0)
1446 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1447 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1450 ret = DeleteEnhMetaFile(hMetafile);
1451 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1452 ret = ReleaseDC(hwnd, hdcDisplay);
1453 ok(ret, "ReleaseDC error %d\n", GetLastError());
1454 DestroyWindow(hwnd);
1457 static const unsigned char EMF_CLIPPING[] =
1459 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1461 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1463 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1464 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1465 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1466 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1469 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1471 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1472 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1473 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1474 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1475 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1476 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1477 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1478 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1479 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1480 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1481 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1482 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1483 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1487 static void translate( POINT *pt, UINT count, const XFORM *xform )
1491 FLOAT x = (FLOAT)pt->x;
1492 FLOAT y = (FLOAT)pt->y;
1493 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1494 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1499 /* Compare rectangles allowing rounding errors */
1500 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1502 return abs(rc1->left - rc2->left) <= 1 &&
1503 abs(rc1->top - rc2->top) <= 1 &&
1504 abs(rc1->right - rc2->right) <= 1 &&
1505 abs(rc1->bottom - rc2->bottom) <= 1;
1508 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1509 const ENHMETARECORD *emr, int n_objs, LPARAM param)
1511 if (emr->iType == EMR_EXTSELECTCLIPRGN)
1513 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1517 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1519 const union _rgn *rgn1;
1521 RECT rect, rc_transformed;
1522 const RECT *rc = (const RECT *)param;
1528 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1529 clip->cbRgnData, clip->iMode);
1531 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1532 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1533 "too small data block: %u bytes\n", clip->cbRgnData);
1534 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1537 rgn1 = (const union _rgn *)clip->RgnData;
1539 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1540 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1541 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1542 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1543 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1545 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1547 rect = *(const RECT *)rgn1->data.Buffer;
1548 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1549 ok(EqualRect(&rect, rc), "rects don't match\n");
1551 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1552 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1553 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1554 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1556 hrgn = CreateRectRgn(0, 0, 0, 0);
1558 memset(&xform, 0, sizeof(xform));
1559 SetLastError(0xdeadbeef);
1560 ret = GetWorldTransform(hdc, &xform);
1561 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1563 ok(ret, "GetWorldTransform error %u\n", GetLastError());
1565 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1567 ret = GetClipRgn(hdc, hrgn);
1568 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1570 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1572 ret = GetClipRgn(hdc, hrgn);
1573 ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1575 /* Win9x returns empty clipping region */
1576 if (is_win9x) return 1;
1578 ret = GetRegionData(hrgn, 0, NULL);
1579 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1581 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1583 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1584 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1585 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1586 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1587 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1589 rect = rgn2.data.rdh.rcBound;
1590 rc_transformed = *rc;
1591 translate((POINT *)&rc_transformed, 2, &xform);
1592 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1593 rc_transformed.right, rc_transformed.bottom);
1594 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1596 rect = *(const RECT *)rgn2.data.Buffer;
1597 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1598 rc_transformed = *rc;
1599 translate((POINT *)&rc_transformed, 2, &xform);
1600 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1601 rc_transformed.right, rc_transformed.bottom);
1602 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1604 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1605 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1606 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1607 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1614 static void test_emf_clipping(void)
1616 static const RECT rc = { 0, 0, 100, 100 };
1617 RECT rc_clip = { 100, 100, 1024, 1024 };
1624 SetLastError(0xdeadbeef);
1625 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1626 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1628 /* Need to write something to the emf, otherwise Windows won't play it back */
1631 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1632 ret = SelectClipRgn(hdc, hrgn);
1633 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1635 SetLastError(0xdeadbeef);
1636 hemf = CloseEnhMetaFile(hdc);
1637 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1639 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1640 "emf_clipping", FALSE, TRUE) != 0)
1642 dump_emf_bits(hemf, "emf_clipping");
1643 dump_emf_records(hemf, "emf_clipping");
1648 /* Win9x doesn't play EMFs on invisible windows */
1649 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1650 0, 0, 200, 200, 0, 0, 0, NULL);
1651 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1655 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1656 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1658 DeleteEnhMetaFile(hemf);
1659 ReleaseDC(hwnd, hdc);
1660 DestroyWindow(hwnd);
1663 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1665 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1666 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1667 /* When using MM_TEXT Win9x does not update the mapping mode
1668 * until a record is played which actually outputs something */
1669 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1670 LPtoDP(hdc, mapping, 2);
1671 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1672 lpEMFR->iType, lpEMFR->nSize,
1673 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1675 if (lpEMFR->iType == EMR_LINETO)
1678 if (!lpMFP || lpMFP->mm == MM_TEXT)
1682 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1683 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1687 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1689 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1690 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1691 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1692 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1694 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1695 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1696 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1702 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1711 hdcMf = CreateMetaFile(NULL);
1712 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1713 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1714 ok(ret, "LineTo failed with error %d\n", GetLastError());
1715 hmf = CloseMetaFile(hdcMf);
1716 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1718 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1720 dump_mf_bits(hmf, "mf_LineTo");
1721 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1724 size = GetMetaFileBitsEx(hmf, 0, NULL);
1725 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1726 pBits = HeapAlloc(GetProcessHeap(), 0, size);
1727 GetMetaFileBitsEx(hmf, size, pBits);
1728 DeleteMetaFile(hmf);
1729 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1730 HeapFree(GetProcessHeap(), 0, pBits);
1734 static void test_mf_conversions(void)
1736 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1738 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1741 RECT rect = { 0, 0, 100, 100 };
1742 mfp.mm = MM_ANISOTROPIC;
1746 hemf = create_converted_emf(&mfp);
1748 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1749 "emf_LineTo MM_ANISOTROPIC", TRUE, TRUE) != 0)
1751 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1752 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1755 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1757 DeleteEnhMetaFile(hemf);
1758 DeleteDC(hdcOffscreen);
1761 trace("Testing MF->EMF conversion (MM_TEXT)\n");
1763 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1766 RECT rect = { 0, 0, 100, 100 };
1771 hemf = create_converted_emf(&mfp);
1773 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1774 "emf_LineTo MM_TEXT", TRUE, TRUE) != 0)
1776 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1777 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1780 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1782 DeleteEnhMetaFile(hemf);
1783 DeleteDC(hdcOffscreen);
1786 trace("Testing MF->EMF conversion (NULL mfp)\n");
1788 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1790 RECT rect = { 0, 0, 100, 100 };
1791 hemf = create_converted_emf(NULL);
1793 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1794 "emf_LineTo NULL", TRUE, TRUE) != 0)
1796 dump_emf_bits(hemf, "emf_LineTo NULL");
1797 dump_emf_records(hemf, "emf_LineTo NULL");
1800 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1802 DeleteEnhMetaFile(hemf);
1803 DeleteDC(hdcOffscreen);
1807 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1808 LONG mm, LONG xExt, LONG yExt,
1809 RECTL * rclBounds, RECTL * rclFrame)
1812 METAFILEPICT * mfpPtr = NULL;
1814 ENHMETAHEADER header;
1825 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1826 ok(emf != NULL, "SetWinMetaFileBits failed\n");
1827 if (!emf) return FALSE;
1828 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1829 ok(res != 0, "GetEnhMetaHeader failed\n");
1830 DeleteEnhMetaFile(emf);
1831 if (!res) return FALSE;
1833 *rclBounds = header.rclBounds;
1834 *rclFrame = header.rclFrame;
1838 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1839 LONG mm, LONG xExt, LONG yExt,
1840 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1842 RECTL rclBounds, rclFrame;
1844 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1851 msg = "mfp == NULL";
1855 const char * mm_str;
1858 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1859 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
1860 default: mm_str = "Unexpected";
1862 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1866 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1867 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1868 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1869 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1870 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1871 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1872 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1873 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1877 static void test_SetWinMetaFileBits(void)
1885 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1886 RECTL rclBoundsIsotropic, rclFrameIsotropic;
1887 RECTL rclBounds, rclFrame;
1891 wmfDC = CreateMetaFile(NULL);
1892 ok(wmfDC != NULL, "CreateMetaFile failed\n");
1895 SetWindowExtEx(wmfDC, 100, 100, NULL);
1896 rect.left = rect.top = 0;
1897 rect.right = rect.bottom = 50;
1898 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1899 wmf = CloseMetaFile(wmfDC);
1900 ok(wmf != NULL, "Metafile creation failed\n");
1903 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1904 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1905 if (buffer_size == 0)
1907 DeleteMetaFile(wmf);
1911 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1912 ok(buffer != NULL, "HeapAlloc failed\n");
1915 DeleteMetaFile(wmf);
1919 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1920 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1921 DeleteMetaFile(wmf);
1922 if (res != buffer_size)
1924 HeapFree(GetProcessHeap(), 0, buffer);
1928 /* Get the reference bounds and frame */
1929 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1930 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1932 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1933 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1934 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1936 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1937 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1938 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1939 if (diffx < 0) diffx = -diffx;
1940 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1942 dc = CreateCompatibleDC(NULL);
1944 /* Allow 1 mm difference (rounding errors) */
1945 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
1946 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
1947 if (diffx < 0) diffx = -diffx;
1948 if (diffy < 0) diffy = -diffy;
1951 ok(diffx <= 1 && diffy <= 1,
1952 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1953 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1956 /* Allow 1 mm difference (rounding errors) */
1957 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1958 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1959 if (diffx < 0) diffx = -diffx;
1960 if (diffy < 0) diffy = -diffy;
1963 ok(diffx <= 1 && diffy <= 1,
1964 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1965 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1969 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1970 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1972 /* If xExt or yExt is zero or negative, the whole device surface is used */
1973 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1974 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1975 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1976 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1977 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1978 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1979 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1980 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1981 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1982 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1983 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1984 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1986 /* MSDN says that negative xExt and yExt values specify a ratio.
1987 Check that this is wrong and the whole device surface is used */
1988 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1989 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1991 /* Ordinary conversions */
1993 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1995 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1996 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
1997 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
1998 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2001 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2003 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2004 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2005 ok(rclBounds.left == 0 && rclBounds.top == 0,
2006 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2008 /* Wine has a rounding error */
2009 diffx = rclBounds.right - rclBounds.bottom;
2010 if (diffx < 0) diffx = -diffx;
2011 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2014 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2016 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2017 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2020 HeapFree(GetProcessHeap(), 0, buffer);
2023 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2024 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2025 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2027 static void test_gdiis(void)
2029 RECT rect = {0,0,100,100};
2030 HDC hdc, hemfDC, hmfDC;
2034 /* resolve all the functions */
2035 hgdi32 = GetModuleHandle("gdi32");
2036 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2037 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2038 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2040 /* they should all exist or none should exist */
2041 if(!pGdiIsMetaPrintDC)
2044 /* try with nothing */
2045 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2046 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2047 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2049 /* try with a metafile */
2050 hmfDC = CreateMetaFile(NULL);
2051 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2052 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2053 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2054 DeleteMetaFile(CloseMetaFile(hmfDC));
2056 /* try with an enhanced metafile */
2058 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2059 ok(hemfDC != NULL, "failed to create emf\n");
2061 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2062 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2063 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2065 hemf = CloseEnhMetaFile(hemfDC);
2066 ok(hemf != NULL, "failed to close EMF\n");
2067 DeleteEnhMetaFile(hemf);
2068 ReleaseDC(NULL,hdc);
2071 static void test_SetEnhMetaFileBits(void)
2077 memset(data, 0xAA, sizeof(data));
2078 SetLastError(0xdeadbeef);
2079 hemf = SetEnhMetaFileBits(sizeof(data), data);
2080 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2081 ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %u\n", GetLastError());
2083 emh = (ENHMETAHEADER *)data;
2084 memset(emh, 0, sizeof(*emh));
2086 emh->iType = EMR_HEADER;
2087 emh->nSize = sizeof(*emh);
2088 emh->dSignature = ENHMETA_SIGNATURE;
2089 /* emh->nVersion = 0x10000; XP doesn't care about version */
2090 emh->nBytes = sizeof(*emh);
2091 /* emh->nRecords = 1; XP doesn't care about records */
2092 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2094 SetLastError(0xdeadbeef);
2095 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2096 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2097 DeleteEnhMetaFile(hemf);
2099 /* XP refuses to load unaligned EMF */
2101 SetLastError(0xdeadbeef);
2102 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2103 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2104 /* XP doesn't set error in this case */
2106 emh->dSignature = 0;
2108 SetLastError(0xdeadbeef);
2109 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2110 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2111 /* XP doesn't set error in this case */
2114 START_TEST(metafile)
2116 init_function_pointers();
2118 /* For enhanced metafiles (enhmfdrv) */
2122 /* For win-format metafiles (mfdrv) */
2125 test_mf_PatternBrush();
2126 test_CopyMetaFile();
2127 test_SetMetaFileBits();
2128 test_mf_ExtTextOut_on_path();
2129 test_emf_ExtTextOut_on_path();
2130 test_emf_clipping();
2132 /* For metafile conversions */
2133 test_mf_conversions();
2134 test_SetWinMetaFileBits();
2137 test_SetEnhMetaFileBits();