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 SetLastError(0xdeadbeef);
125 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
126 ok( ret == sizeof(device_lf) ||
127 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
128 "GetObjectA error %d\n", GetLastError());
130 /* compare up to lfOutPrecision, other values are not interesting,
131 * and in fact sometimes arbitrary adapted by Win9x.
133 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
134 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
136 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
138 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
139 n_record, i, dx[i], orig_dx[i]);
142 emr_processed = TRUE;
153 static void test_ExtTextOut(void)
156 HDC hdcDisplay, hdcMetafile;
157 HENHMETAFILE hMetafile;
159 static const char text[] = "Simple text to test ExtTextOut on metafiles";
161 static const RECT rc = { 0, 0, 100, 100 };
164 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
166 /* Win9x doesn't play EMFs on invisible windows */
167 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
168 0, 0, 200, 200, 0, 0, 0, NULL);
169 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
171 hdcDisplay = GetDC(hwnd);
172 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
174 trace("hdcDisplay %p\n", hdcDisplay);
176 SetMapMode(hdcDisplay, MM_TEXT);
178 memset(&orig_lf, 0, sizeof(orig_lf));
180 orig_lf.lfCharSet = ANSI_CHARSET;
181 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
182 orig_lf.lfWeight = FW_DONTCARE;
183 orig_lf.lfHeight = 7;
184 orig_lf.lfQuality = DEFAULT_QUALITY;
185 lstrcpyA(orig_lf.lfFaceName, "Arial");
186 hFont = CreateFontIndirectA(&orig_lf);
187 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
189 hFont = SelectObject(hdcDisplay, hFont);
191 len = lstrlenA(text);
192 for (i = 0; i < len; i++)
194 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
195 ok( ret, "GetCharWidthA error %d\n", GetLastError());
197 hFont = SelectObject(hdcDisplay, hFont);
199 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
200 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
202 trace("hdcMetafile %p\n", hdcMetafile);
204 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
205 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
207 hFont = SelectObject(hdcMetafile, hFont);
209 /* 1. pass NULL lpDx */
210 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
211 ok( ret, "ExtTextOutA error %d\n", GetLastError());
213 /* 2. pass custom lpDx */
214 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
215 ok( ret, "ExtTextOutA error %d\n", GetLastError());
217 hFont = SelectObject(hdcMetafile, hFont);
218 ret = DeleteObject(hFont);
219 ok( ret, "DeleteObject error %d\n", GetLastError());
221 hMetafile = CloseEnhMetaFile(hdcMetafile);
222 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
224 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
226 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
227 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
229 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
230 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
231 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
232 SetROP2(hdcDisplay, R2_NOT);
233 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
234 SetPolyFillMode(hdcDisplay, WINDING);
235 SetStretchBltMode(hdcDisplay, HALFTONE);
237 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
238 SetBkMode(hdcDisplay, OPAQUE);
240 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
241 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
243 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
244 "text align %08x\n", GetTextAlign(hdcDisplay));
245 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
246 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
247 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
248 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
249 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
250 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
252 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
254 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
255 "A valid hdc has to require a valid rc\n");
257 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
258 "A null hdc does not require a valid rc\n");
260 ret = DeleteEnhMetaFile(hMetafile);
261 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
262 ret = ReleaseDC(hwnd, hdcDisplay);
263 ok( ret, "ReleaseDC error %d\n", GetLastError());
267 static void check_dc_state(HDC hdc, int restore_no,
268 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
269 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
273 POINT vp_org, win_org;
274 SIZE vp_size, win_size;
275 FLOAT xscale, yscale, edx, edy;
277 SetLastError(0xdeadbeef);
278 ret = GetWorldTransform(hdc, &xform);
279 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
280 ok(ret, "GetWorldTransform error %u\n", GetLastError());
282 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
284 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
285 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
287 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
288 trace("x scale %f\n", xscale);
289 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
290 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
292 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
293 trace("y scale %f\n", yscale);
294 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
295 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
297 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
298 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
299 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
300 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
306 GetWindowOrgEx(hdc, &win_org);
307 GetViewportOrgEx(hdc, &vp_org);
308 GetWindowExtEx(hdc, &win_size);
309 GetViewportExtEx(hdc, &vp_size);
311 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
312 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
314 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
315 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
317 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
318 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
320 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
321 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
324 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
325 const ENHMETARECORD *emr, int n_objs, LPARAM param)
331 static int save_state;
332 static int restore_no;
334 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
335 hdc, emr->iType, emr->nSize, (void *)param);
338 SetLastError(0xdeadbeef);
339 ret = GetWorldTransform(hdc, &xform);
340 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
342 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
343 trace("window org (%d,%d)\n", pt.x, pt.y);
344 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
345 trace("vport org (%d,%d)\n", pt.x, pt.y);
346 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
347 trace("window ext (%d,%d)\n", size.cx, size.cy);
348 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
349 trace("vport ext (%d,%d)\n", size.cx, size.cy);
353 ok(ret, "GetWorldTransform error %u\n", GetLastError());
354 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
357 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
363 static RECT exp_bounds = { 0, 0, 150, 150 };
365 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
367 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
368 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
369 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
370 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
371 emf->szlDevice.cx, emf->szlDevice.cy);
373 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
374 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
378 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
384 const EMRLINETO *line = (const EMRLINETO *)emr;
385 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
388 case EMR_SETWINDOWORGEX:
390 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
391 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
394 case EMR_SETWINDOWEXTEX:
396 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
397 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
400 case EMR_SETVIEWPORTORGEX:
402 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
403 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
406 case EMR_SETVIEWPORTEXTEX:
408 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
409 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
414 trace("EMR_SAVEDC\n");
419 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
420 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
425 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
426 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
429 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
430 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
433 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
434 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
437 ok(restore_no <= 3, "restore_no %d\n", restore_no);
438 save_state += restoredc->iRelative;
442 ok(save_state == 0, "EOF save_state %d\n", save_state);
447 SetLastError(0xdeadbeef);
448 ret = GetWorldTransform(hdc, &xform);
449 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
451 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
452 trace("window org (%d,%d)\n", pt.x, pt.y);
453 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
454 trace("vport org (%d,%d)\n", pt.x, pt.y);
455 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
456 trace("window ext (%d,%d)\n", size.cx, size.cy);
457 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
458 trace("vport ext (%d,%d)\n", size.cx, size.cy);
462 ok(ret, "GetWorldTransform error %u\n", GetLastError());
463 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
469 static void test_SaveDC(void)
471 HDC hdcMetafile, hdcDisplay;
472 HENHMETAFILE hMetafile;
475 static const RECT rc = { 0, 0, 150, 150 };
477 /* Win9x doesn't play EMFs on invisible windows */
478 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
479 0, 0, 200, 200, 0, 0, 0, NULL);
480 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
482 hdcDisplay = GetDC(hwnd);
483 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
485 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
486 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
488 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
490 /* Need to write something to the emf, otherwise Windows won't play it back */
491 LineTo(hdcMetafile, 150, 150);
493 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
494 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
495 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
496 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
498 /* Force Win9x to update DC state */
499 SetPixelV(hdcMetafile, 50, 50, 0);
501 ret = SaveDC(hdcMetafile);
502 ok(ret == 1, "ret = %d\n", ret);
504 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
505 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
506 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
507 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
509 /* Force Win9x to update DC state */
510 SetPixelV(hdcMetafile, 50, 50, 0);
512 ret = SaveDC(hdcMetafile);
513 ok(ret == 2, "ret = %d\n", ret);
515 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
516 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
517 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
518 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
520 /* Force Win9x to update DC state */
521 SetPixelV(hdcMetafile, 50, 50, 0);
523 ret = SaveDC(hdcMetafile);
524 ok(ret == 3, "ret = %d\n", ret);
526 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
527 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
528 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
529 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
531 /* Force Win9x to update DC state */
532 SetPixelV(hdcMetafile, 50, 50, 0);
534 ret = RestoreDC(hdcMetafile, -1);
535 ok(ret, "ret = %d\n", ret);
537 ret = SaveDC(hdcMetafile);
538 ok(ret == 3, "ret = %d\n", ret);
540 ret = RestoreDC(hdcMetafile, 1);
541 ok(ret, "ret = %d\n", ret);
543 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
544 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
545 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
546 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
548 /* Force Win9x to update DC state */
549 SetPixelV(hdcMetafile, 50, 50, 0);
551 ret = SaveDC(hdcMetafile);
552 ok(ret == 1, "ret = %d\n", ret);
554 ret = SaveDC(hdcMetafile);
555 ok(ret == 2, "ret = %d\n", ret);
557 hMetafile = CloseEnhMetaFile(hdcMetafile);
558 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
560 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
561 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
563 ret = DeleteEnhMetaFile(hMetafile);
564 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
565 ret = ReleaseDC(hwnd, hdcDisplay);
566 ok( ret, "ReleaseDC error %d\n", GetLastError());
570 /* Win-format metafile (mfdrv) tests */
571 /* These tests compare the generated metafiles byte-by-byte */
572 /* with the nominal results. */
574 /* Maximum size of sample metafiles in bytes. */
575 #define MF_BUFSIZE 512
577 /* 8x8 bitmap data for a pattern brush */
578 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
579 0x01, 0x00, 0x02, 0x00,
580 0x03, 0x00, 0x04, 0x00,
581 0x05, 0x00, 0x06, 0x00,
582 0x07, 0x00, 0x08, 0x00
585 /* Sample metafiles to be compared to the outputs of the
589 static const unsigned char MF_BLANK_BITS[] = {
590 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
595 static const unsigned char MF_GRAPHICS_BITS[] = {
596 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
599 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
600 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
601 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
602 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
603 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
604 0x00, 0x00, 0x00, 0x00
607 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
608 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
609 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
611 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
612 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
613 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
618 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
619 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
620 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
621 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
622 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
626 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
628 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
629 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
630 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
631 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
632 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
633 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
637 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
639 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
644 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
645 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
646 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
649 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
652 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
653 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
654 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
656 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
658 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
659 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
662 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
663 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
664 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
665 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
666 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
667 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
668 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
669 0x14, 0x00, 0x00, 0x00
672 static const unsigned char MF_LINETO_BITS[] = {
673 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
674 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
675 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
676 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
680 static const unsigned char EMF_LINETO_BITS[] = {
681 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
686 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
687 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
688 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
691 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
694 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
695 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
696 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
697 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
698 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
699 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
700 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
701 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
702 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
704 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
705 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
706 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
707 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
708 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
709 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
710 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
711 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
712 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
713 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
714 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
715 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
716 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
718 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
722 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
723 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
728 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
729 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
730 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
733 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
734 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
736 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
737 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
738 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
739 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
740 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
741 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
744 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
745 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
746 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
747 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
748 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
749 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
750 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
751 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
752 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
753 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
754 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
755 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
756 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
757 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
758 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
760 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
764 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
765 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
770 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
771 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
772 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
775 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
778 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
779 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
780 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
781 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
782 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
783 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
784 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
785 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
786 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
788 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
789 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
791 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
793 0x14, 0x00, 0x00, 0x00
796 /* For debugging or dumping the raw metafiles produced by
797 * new test functions.
799 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
800 INT nobj, LPARAM param)
802 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
803 hdc, mr->rdFunction, mr->rdSize, (void *)param);
807 /* For debugging or dumping the raw metafiles produced by
808 * new test functions.
811 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
813 BYTE buf[MF_BUFSIZE];
816 if (!winetest_debug) return;
818 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
819 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
821 printf ("MetaFile %s has bits:\n{\n ", desc);
822 for (i=0; i<mfsize; i++)
824 printf ("0x%02x", buf[i]);
835 /* Compare the metafile produced by a test function with the
836 * expected raw metafile data in "bits".
837 * Return value is 0 for a perfect match,
838 * -1 if lengths aren't equal,
839 * otherwise returns the number of non-matching bytes.
842 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
845 unsigned char buf[MF_BUFSIZE];
849 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
850 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
851 if (mfsize < MF_BUFSIZE)
852 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
853 desc, mfsize, bsize);
855 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
856 desc, mfsize, bsize);
861 for (i=0; i<bsize; i++)
863 if (buf[i] != bits[i])
866 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
867 desc, mfsize, bsize, diff);
872 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
874 unsigned char buf[MF_BUFSIZE];
875 DWORD mfsize, rd_size, i;
880 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
881 assert(hfile != INVALID_HANDLE_VALUE);
883 mfsize = GetFileSize(hfile, NULL);
884 assert(mfsize <= MF_BUFSIZE);
886 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
887 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
891 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
897 for (i=0; i<bsize; i++)
899 if (buf[i] != bits[i])
902 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
903 desc, mfsize, bsize, diff);
908 /* For debugging or dumping the raw EMFs produced by
909 * new test functions.
911 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
913 BYTE buf[MF_BUFSIZE];
916 if (!winetest_debug) return;
918 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
919 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
921 printf("EMF %s has bits:\n{\n ", desc);
922 for (i = 0; i < mfsize; i++)
924 printf ("0x%02x", buf[i]);
935 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
938 BYTE buf[MF_BUFSIZE];
941 if (!winetest_debug) return;
943 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
944 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
946 printf("EMF %s has records:\n", desc);
950 while(offset < mfsize)
952 EMR *emr = (EMR *)(emf + offset);
953 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
954 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
955 offset += emr->nSize;
959 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
964 if (!winetest_debug) return;
966 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
967 buf = (const BYTE *)emr;
968 for (i = 0; i < emr->nSize; i++)
970 printf ("0x%02x", buf[i]);
971 if (i == emr->nSize - 1)
981 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
983 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
984 eto->rclBounds.right, eto->rclBounds.bottom);
985 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
986 trace("exScale: %f\n", eto->exScale);
987 trace("eyScale: %f\n", eto->eyScale);
988 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
989 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
990 trace("emrtext.offString %#x\n", eto->emrtext.offString);
991 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
992 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
993 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
994 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
997 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
998 const char *desc, BOOL ignore_scaling)
1002 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1003 desc, emr1->iType, emr2->iType);
1005 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1006 desc, emr1->nSize, emr2->nSize);
1008 /* iType and nSize mismatches are fatal */
1009 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1011 /* contents of EMR_GDICOMMENT are not interesting */
1012 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1014 /* different Windows versions setup DC scaling differently when
1015 * converting an old style metafile to an EMF.
1017 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1018 emr1->iType == EMR_SETVIEWPORTEXTEX))
1021 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1023 EMREXTTEXTOUTW *eto1, *eto2;
1025 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1026 memcpy(eto1, emr1, emr1->nSize);
1027 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1028 memcpy(eto2, emr2, emr2->nSize);
1030 /* different Windows versions setup DC scaling differently */
1031 eto1->exScale = eto1->eyScale = 0.0;
1032 eto2->exScale = eto2->eyScale = 0.0;
1034 diff = memcmp(eto1, eto2, emr1->nSize);
1037 dump_EMREXTTEXTOUT(eto1);
1038 dump_EMREXTTEXTOUT(eto2);
1040 HeapFree(GetProcessHeap(), 0, eto1);
1041 HeapFree(GetProcessHeap(), 0, eto2);
1044 diff = memcmp(emr1, emr2, emr1->nSize);
1046 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1050 dump_emf_record(emr1, "expected bits");
1051 dump_emf_record(emr2, "actual bits");
1054 return diff == 0; /* report all non-fatal record mismatches */
1057 /* Compare the EMF produced by a test function with the
1058 * expected raw EMF data in "bits".
1059 * Return value is 0 for a perfect match,
1060 * -1 if lengths aren't equal,
1061 * otherwise returns the number of non-matching bytes.
1063 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1064 UINT bsize, const char *desc,
1065 BOOL ignore_scaling)
1067 unsigned char buf[MF_BUFSIZE];
1068 UINT mfsize, offset;
1069 const ENHMETAHEADER *emh1, *emh2;
1071 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1072 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1074 if (mfsize < MF_BUFSIZE)
1076 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1079 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1080 desc, mfsize, bsize);
1082 /* basic things must match */
1083 emh1 = (const ENHMETAHEADER *)bits;
1084 emh2 = (const ENHMETAHEADER *)buf;
1085 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1086 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1087 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1088 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1090 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1091 ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1092 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1093 ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1094 ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1096 offset = emh1->nSize;
1097 while (offset < emh1->nBytes)
1099 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset);
1100 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset);
1102 trace("EMF record %u, size %u/record %u, size %u\n",
1103 emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1105 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1107 offset += emr1->nSize;
1112 /* Test a blank metafile. May be used as a template for new tests. */
1114 static void test_mf_Blank(void)
1117 HMETAFILE hMetafile;
1122 hdcMetafile = CreateMetaFileA(NULL);
1123 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1124 trace("hdcMetafile %p\n", hdcMetafile);
1126 /* Tests on metafile initialization */
1127 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1128 ok (caps == DT_METAFILE,
1129 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1131 hMetafile = CloseMetaFile(hdcMetafile);
1132 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1133 type = GetObjectType(hMetafile);
1134 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1135 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1137 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1140 dump_mf_bits(hMetafile, "mf_Blank");
1141 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1144 ret = DeleteMetaFile(hMetafile);
1145 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1148 static void test_CopyMetaFile(void)
1151 HMETAFILE hMetafile, hmf_copy;
1153 char temp_path[MAX_PATH];
1154 char mf_name[MAX_PATH];
1157 hdcMetafile = CreateMetaFileA(NULL);
1158 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1159 trace("hdcMetafile %p\n", hdcMetafile);
1161 hMetafile = CloseMetaFile(hdcMetafile);
1162 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1163 type = GetObjectType(hMetafile);
1164 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1166 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1169 dump_mf_bits(hMetafile, "mf_Blank");
1170 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1173 GetTempPathA(MAX_PATH, temp_path);
1174 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1176 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1177 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1179 type = GetObjectType(hmf_copy);
1180 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1182 ret = DeleteMetaFile(hMetafile);
1183 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1185 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1187 dump_mf_bits(hMetafile, "mf_Blank");
1188 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1191 ret = DeleteMetaFile(hmf_copy);
1192 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1194 DeleteFileA(mf_name);
1197 static void test_SetMetaFileBits(void)
1205 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1206 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1207 type = GetObjectType(hmf);
1208 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1210 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1212 dump_mf_bits(hmf, "mf_Graphics");
1213 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1216 ret = DeleteMetaFile(hmf);
1217 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1219 /* NULL data crashes XP SP1 */
1220 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1222 /* Now with not zero size */
1223 SetLastError(0xdeadbeef);
1224 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1225 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1226 ok(GetLastError() == ERROR_INVALID_DATA ||
1227 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1228 "wrong error %d\n", GetLastError());
1230 /* Now with not even size */
1231 SetLastError(0xdeadbeef);
1232 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1233 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1234 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1236 /* Now with zeroed out or faked some header fields */
1237 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1238 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1239 mh = (METAHEADER *)buf;
1240 /* corruption of any of the below fields leads to a failure */
1243 mh->mtHeaderSize = 0;
1244 SetLastError(0xdeadbeef);
1245 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1246 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1247 ok(GetLastError() == ERROR_INVALID_DATA ||
1248 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1249 "wrong error %d\n", GetLastError());
1251 /* Now with corrupted mtSize field */
1252 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1253 mh = (METAHEADER *)buf;
1254 /* corruption of mtSize doesn't lead to a failure */
1256 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1257 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1259 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1261 dump_mf_bits(hmf, "mf_Graphics");
1262 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1265 ret = DeleteMetaFile(hmf);
1266 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1268 /* Now with zeroed out mtSize field */
1269 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1270 mh = (METAHEADER *)buf;
1271 /* zeroing mtSize doesn't lead to a failure */
1273 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1274 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1276 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1278 dump_mf_bits(hmf, "mf_Graphics");
1279 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1282 ret = DeleteMetaFile(hmf);
1283 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1286 /* Simple APIs from mfdrv/graphics.c
1289 static void test_mf_Graphics(void)
1292 HMETAFILE hMetafile;
1296 hdcMetafile = CreateMetaFileA(NULL);
1297 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1298 trace("hdcMetafile %p\n", hdcMetafile);
1300 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1301 ok( ret, "MoveToEx error %d.\n", GetLastError());
1302 ret = LineTo(hdcMetafile, 2, 2);
1303 ok( ret, "LineTo error %d.\n", GetLastError());
1304 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1305 ok( ret, "MoveToEx error %d.\n", GetLastError());
1307 /* oldpoint gets garbage under Win XP, so the following test would
1308 * work under Wine but fails under Windows:
1310 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1311 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1312 * oldpoint.x, oldpoint.y);
1315 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1316 ok( ret, "Ellipse error %d.\n", GetLastError());
1318 hMetafile = CloseMetaFile(hdcMetafile);
1319 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1320 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1322 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1323 "mf_Graphics") != 0)
1325 dump_mf_bits(hMetafile, "mf_Graphics");
1326 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1329 ret = DeleteMetaFile(hMetafile);
1330 ok( ret, "DeleteMetaFile(%p) error %d\n",
1331 hMetafile, GetLastError());
1334 static void test_mf_PatternBrush(void)
1337 HMETAFILE hMetafile;
1342 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1344 orig_lb->lbStyle = BS_PATTERN;
1345 orig_lb->lbColor = RGB(0, 0, 0);
1346 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1347 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1349 hBrush = CreateBrushIndirect (orig_lb);
1350 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1352 hdcMetafile = CreateMetaFileA(NULL);
1353 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1354 trace("hdcMetafile %p\n", hdcMetafile);
1356 hBrush = SelectObject(hdcMetafile, hBrush);
1357 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1359 hMetafile = CloseMetaFile(hdcMetafile);
1360 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1361 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1363 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1364 "mf_Pattern_Brush") != 0)
1366 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1367 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1370 ret = DeleteMetaFile(hMetafile);
1371 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1372 ret = DeleteObject(hBrush);
1373 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1374 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1375 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1377 HeapFree (GetProcessHeap(), 0, orig_lb);
1380 static void test_mf_ExtTextOut_on_path(void)
1383 HMETAFILE hMetafile;
1385 static const INT dx[4] = { 3, 5, 8, 12 };
1387 hdcMetafile = CreateMetaFileA(NULL);
1388 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1389 trace("hdcMetafile %p\n", hdcMetafile);
1391 ret = BeginPath(hdcMetafile);
1392 ok(!ret, "BeginPath on metafile DC should fail\n");
1394 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1395 ok(ret, "ExtTextOut error %d\n", GetLastError());
1397 ret = EndPath(hdcMetafile);
1398 ok(!ret, "EndPath on metafile DC should fail\n");
1400 hMetafile = CloseMetaFile(hdcMetafile);
1401 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1403 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1404 "mf_TextOut_on_path") != 0)
1406 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1407 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1410 ret = DeleteMetaFile(hMetafile);
1411 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1414 static void test_emf_ExtTextOut_on_path(void)
1417 HDC hdcDisplay, hdcMetafile;
1418 HENHMETAFILE hMetafile;
1420 static const INT dx[4] = { 3, 5, 8, 12 };
1422 /* Win9x doesn't play EMFs on invisible windows */
1423 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1424 0, 0, 200, 200, 0, 0, 0, NULL);
1425 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1427 hdcDisplay = GetDC(hwnd);
1428 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1430 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1431 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1433 ret = BeginPath(hdcMetafile);
1434 ok(ret, "BeginPath error %d\n", GetLastError());
1436 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1437 ok(ret, "ExtTextOut error %d\n", GetLastError());
1439 ret = EndPath(hdcMetafile);
1440 ok(ret, "EndPath error %d\n", GetLastError());
1442 hMetafile = CloseEnhMetaFile(hdcMetafile);
1443 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1445 /* this doesn't succeed yet: EMF has correct size, all EMF records
1446 * are there, but their contents don't match for different reasons.
1448 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1449 "emf_TextOut_on_path", FALSE) != 0)
1451 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1452 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1455 ret = DeleteEnhMetaFile(hMetafile);
1456 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1457 ret = ReleaseDC(hwnd, hdcDisplay);
1458 ok(ret, "ReleaseDC error %d\n", GetLastError());
1459 DestroyWindow(hwnd);
1462 static const unsigned char EMF_CLIPPING[] =
1464 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1469 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1470 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1471 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1473 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1474 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1476 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1477 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1478 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1479 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1480 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1481 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1482 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1483 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1484 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1485 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1486 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1487 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1488 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1489 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1492 static void translate( POINT *pt, UINT count, const XFORM *xform )
1496 FLOAT x = (FLOAT)pt->x;
1497 FLOAT y = (FLOAT)pt->y;
1498 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1499 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1504 /* Compare rectangles allowing rounding errors */
1505 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1507 return abs(rc1->left - rc2->left) <= 1 &&
1508 abs(rc1->top - rc2->top) <= 1 &&
1509 abs(rc1->right - rc2->right) <= 1 &&
1510 abs(rc1->bottom - rc2->bottom) <= 1;
1513 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1514 const ENHMETARECORD *emr, int n_objs, LPARAM param)
1516 if (emr->iType == EMR_EXTSELECTCLIPRGN)
1518 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1522 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1524 const union _rgn *rgn1;
1526 RECT rect, rc_transformed;
1527 const RECT *rc = (const RECT *)param;
1533 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1534 clip->cbRgnData, clip->iMode);
1536 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1537 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1538 "too small data block: %u bytes\n", clip->cbRgnData);
1539 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1542 rgn1 = (const union _rgn *)clip->RgnData;
1544 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1545 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1546 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1547 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1548 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1550 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1552 rect = *(const RECT *)rgn1->data.Buffer;
1553 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1554 ok(EqualRect(&rect, rc), "rects don't match\n");
1556 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1557 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1558 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1559 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1561 hrgn = CreateRectRgn(0, 0, 0, 0);
1563 memset(&xform, 0, sizeof(xform));
1564 SetLastError(0xdeadbeef);
1565 ret = GetWorldTransform(hdc, &xform);
1566 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1568 ok(ret, "GetWorldTransform error %u\n", GetLastError());
1570 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1572 ret = GetClipRgn(hdc, hrgn);
1573 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1575 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1577 ret = GetClipRgn(hdc, hrgn);
1578 ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1580 /* Win9x returns empty clipping region */
1581 if (is_win9x) return 1;
1583 ret = GetRegionData(hrgn, 0, NULL);
1584 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1586 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1588 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1589 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1590 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1591 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1592 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1594 rect = rgn2.data.rdh.rcBound;
1595 rc_transformed = *rc;
1596 translate((POINT *)&rc_transformed, 2, &xform);
1597 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1598 rc_transformed.right, rc_transformed.bottom);
1599 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1601 rect = *(const RECT *)rgn2.data.Buffer;
1602 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1603 rc_transformed = *rc;
1604 translate((POINT *)&rc_transformed, 2, &xform);
1605 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1606 rc_transformed.right, rc_transformed.bottom);
1607 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1609 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1610 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1611 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1612 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1619 static void test_emf_clipping(void)
1621 static const RECT rc = { 0, 0, 100, 100 };
1622 RECT rc_clip = { 100, 100, 1024, 1024 };
1629 SetLastError(0xdeadbeef);
1630 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1631 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1633 /* Need to write something to the emf, otherwise Windows won't play it back */
1636 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1637 ret = SelectClipRgn(hdc, hrgn);
1638 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1640 SetLastError(0xdeadbeef);
1641 hemf = CloseEnhMetaFile(hdc);
1642 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1644 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1645 "emf_clipping", FALSE) != 0)
1647 dump_emf_bits(hemf, "emf_clipping");
1648 dump_emf_records(hemf, "emf_clipping");
1653 /* Win9x doesn't play EMFs on invisible windows */
1654 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1655 0, 0, 200, 200, 0, 0, 0, NULL);
1656 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1660 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1661 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1663 DeleteEnhMetaFile(hemf);
1664 ReleaseDC(hwnd, hdc);
1665 DestroyWindow(hwnd);
1668 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1670 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1671 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1672 /* When using MM_TEXT Win9x does not update the mapping mode
1673 * until a record is played which actually outputs something */
1674 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1675 LPtoDP(hdc, mapping, 2);
1676 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1677 lpEMFR->iType, lpEMFR->nSize,
1678 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1680 if (lpEMFR->iType == EMR_LINETO)
1683 if (!lpMFP || lpMFP->mm == MM_TEXT)
1687 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1688 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1692 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1694 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1695 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1696 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1697 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1699 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1700 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1701 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1707 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1716 hdcMf = CreateMetaFile(NULL);
1717 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1718 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1719 ok(ret, "LineTo failed with error %d\n", GetLastError());
1720 hmf = CloseMetaFile(hdcMf);
1721 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1723 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1725 dump_mf_bits(hmf, "mf_LineTo");
1726 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1729 size = GetMetaFileBitsEx(hmf, 0, NULL);
1730 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1731 pBits = HeapAlloc(GetProcessHeap(), 0, size);
1732 GetMetaFileBitsEx(hmf, size, pBits);
1733 DeleteMetaFile(hmf);
1734 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1735 HeapFree(GetProcessHeap(), 0, pBits);
1739 static void test_mf_conversions(void)
1741 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1743 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1746 RECT rect = { 0, 0, 100, 100 };
1747 mfp.mm = MM_ANISOTROPIC;
1751 hemf = create_converted_emf(&mfp);
1753 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1754 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1756 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1757 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1760 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1762 DeleteEnhMetaFile(hemf);
1763 DeleteDC(hdcOffscreen);
1766 trace("Testing MF->EMF conversion (MM_TEXT)\n");
1768 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1771 RECT rect = { 0, 0, 100, 100 };
1776 hemf = create_converted_emf(&mfp);
1778 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1779 "emf_LineTo MM_TEXT", TRUE) != 0)
1781 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1782 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1785 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1787 DeleteEnhMetaFile(hemf);
1788 DeleteDC(hdcOffscreen);
1791 trace("Testing MF->EMF conversion (NULL mfp)\n");
1793 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1795 RECT rect = { 0, 0, 100, 100 };
1796 hemf = create_converted_emf(NULL);
1798 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1799 "emf_LineTo NULL", TRUE) != 0)
1801 dump_emf_bits(hemf, "emf_LineTo NULL");
1802 dump_emf_records(hemf, "emf_LineTo NULL");
1805 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1807 DeleteEnhMetaFile(hemf);
1808 DeleteDC(hdcOffscreen);
1812 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1813 LONG mm, LONG xExt, LONG yExt,
1814 RECTL * rclBounds, RECTL * rclFrame)
1817 METAFILEPICT * mfpPtr = NULL;
1819 ENHMETAHEADER header;
1830 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1831 ok(emf != NULL, "SetWinMetaFileBits failed\n");
1832 if (!emf) return FALSE;
1833 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1834 ok(res != 0, "GetEnhMetaHeader failed\n");
1835 DeleteEnhMetaFile(emf);
1836 if (!res) return FALSE;
1838 *rclBounds = header.rclBounds;
1839 *rclFrame = header.rclFrame;
1843 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1844 LONG mm, LONG xExt, LONG yExt,
1845 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1847 RECTL rclBounds, rclFrame;
1849 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1856 msg = "mfp == NULL";
1860 const char * mm_str;
1863 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1864 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
1865 default: mm_str = "Unexpected";
1867 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1871 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1872 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1873 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1874 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1875 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1876 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1877 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1878 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1882 static void test_SetWinMetaFileBits(void)
1890 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1891 RECTL rclBoundsIsotropic, rclFrameIsotropic;
1892 RECTL rclBounds, rclFrame;
1896 wmfDC = CreateMetaFile(NULL);
1897 ok(wmfDC != NULL, "CreateMetaFile failed\n");
1900 SetWindowExtEx(wmfDC, 100, 100, NULL);
1901 rect.left = rect.top = 0;
1902 rect.right = rect.bottom = 50;
1903 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1904 wmf = CloseMetaFile(wmfDC);
1905 ok(wmf != NULL, "Metafile creation failed\n");
1908 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1909 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1910 if (buffer_size == 0)
1912 DeleteMetaFile(wmf);
1916 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1917 ok(buffer != NULL, "HeapAlloc failed\n");
1920 DeleteMetaFile(wmf);
1924 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1925 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1926 DeleteMetaFile(wmf);
1927 if (res != buffer_size)
1929 HeapFree(GetProcessHeap(), 0, buffer);
1933 /* Get the reference bounds and frame */
1934 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1935 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1937 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1938 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1939 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1941 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1942 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1943 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1944 if (diffx < 0) diffx = -diffx;
1945 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1947 dc = CreateCompatibleDC(NULL);
1949 /* Allow 1 mm difference (rounding errors) */
1950 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
1951 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
1952 if (diffx < 0) diffx = -diffx;
1953 if (diffy < 0) diffy = -diffy;
1956 ok(diffx <= 1 && diffy <= 1,
1957 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1958 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1961 /* Allow 1 mm difference (rounding errors) */
1962 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1963 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1964 if (diffx < 0) diffx = -diffx;
1965 if (diffy < 0) diffy = -diffy;
1968 ok(diffx <= 1 && diffy <= 1,
1969 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1970 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1974 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1975 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1977 /* If xExt or yExt is zero or negative, the whole device surface is used */
1978 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1979 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1980 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1981 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1982 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1983 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1984 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1985 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1986 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1987 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1988 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1989 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1991 /* MSDN says that negative xExt and yExt values specify a ratio.
1992 Check that this is wrong and the whole device surface is used */
1993 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1994 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1996 /* Ordinary conversions */
1998 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2000 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2001 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2002 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2003 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2006 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2008 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2009 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2010 ok(rclBounds.left == 0 && rclBounds.top == 0,
2011 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2013 /* Wine has a rounding error */
2014 diffx = rclBounds.right - rclBounds.bottom;
2015 if (diffx < 0) diffx = -diffx;
2016 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2019 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2021 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2022 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2025 HeapFree(GetProcessHeap(), 0, buffer);
2028 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2029 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2030 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2032 static void test_gdiis(void)
2034 RECT rect = {0,0,100,100};
2035 HDC hdc, hemfDC, hmfDC;
2039 /* resolve all the functions */
2040 hgdi32 = GetModuleHandle("gdi32");
2041 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2042 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2043 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2045 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2047 win_skip("Needed GdiIs* functions are not available\n");
2051 /* try with nothing */
2052 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2053 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2054 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2056 /* try with a metafile */
2057 hmfDC = CreateMetaFile(NULL);
2058 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2059 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2060 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2061 DeleteMetaFile(CloseMetaFile(hmfDC));
2063 /* try with an enhanced metafile */
2065 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2066 ok(hemfDC != NULL, "failed to create emf\n");
2068 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2069 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2070 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2072 hemf = CloseEnhMetaFile(hemfDC);
2073 ok(hemf != NULL, "failed to close EMF\n");
2074 DeleteEnhMetaFile(hemf);
2075 ReleaseDC(NULL,hdc);
2078 static void test_SetEnhMetaFileBits(void)
2084 memset(data, 0xAA, sizeof(data));
2085 SetLastError(0xdeadbeef);
2086 hemf = SetEnhMetaFileBits(sizeof(data), data);
2087 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2088 ok(GetLastError() == ERROR_INVALID_DATA ||
2089 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2090 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2092 emh = (ENHMETAHEADER *)data;
2093 memset(emh, 0, sizeof(*emh));
2095 emh->iType = EMR_HEADER;
2096 emh->nSize = sizeof(*emh);
2097 emh->dSignature = ENHMETA_SIGNATURE;
2098 /* emh->nVersion = 0x10000; XP doesn't care about version */
2099 emh->nBytes = sizeof(*emh);
2100 /* emh->nRecords = 1; XP doesn't care about records */
2101 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2103 SetLastError(0xdeadbeef);
2104 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2105 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2106 DeleteEnhMetaFile(hemf);
2108 /* XP refuses to load unaligned EMF */
2110 SetLastError(0xdeadbeef);
2111 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2113 broken(hemf != NULL), /* Win9x, WinMe */
2114 "SetEnhMetaFileBits should fail\n");
2116 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2117 DeleteEnhMetaFile(hemf);
2119 emh->dSignature = 0;
2121 SetLastError(0xdeadbeef);
2122 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2124 broken(hemf != NULL), /* Win9x, WinMe */
2125 "SetEnhMetaFileBits should fail\n");
2127 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2128 DeleteEnhMetaFile(hemf);
2131 START_TEST(metafile)
2133 init_function_pointers();
2135 /* For enhanced metafiles (enhmfdrv) */
2139 /* For win-format metafiles (mfdrv) */
2142 test_mf_PatternBrush();
2143 test_CopyMetaFile();
2144 test_SetMetaFileBits();
2145 test_mf_ExtTextOut_on_path();
2146 test_emf_ExtTextOut_on_path();
2147 test_emf_clipping();
2149 /* For metafile conversions */
2150 test_mf_conversions();
2151 test_SetWinMetaFileBits();
2154 test_SetEnhMetaFileBits();