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;
333 static int select_no;
335 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
336 hdc, emr->iType, emr->nSize, (void *)param);
339 SetLastError(0xdeadbeef);
340 ret = GetWorldTransform(hdc, &xform);
341 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
343 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
344 trace("window org (%d,%d)\n", pt.x, pt.y);
345 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
346 trace("vport org (%d,%d)\n", pt.x, pt.y);
347 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
348 trace("window ext (%d,%d)\n", size.cx, size.cy);
349 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
350 trace("vport ext (%d,%d)\n", size.cx, size.cy);
354 ok(ret, "GetWorldTransform error %u\n", GetLastError());
355 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
358 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
364 static RECT exp_bounds = { 0, 0, 150, 150 };
366 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
368 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
369 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
370 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
371 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
372 emf->szlDevice.cx, emf->szlDevice.cy);
374 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
375 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
380 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
386 const EMRLINETO *line = (const EMRLINETO *)emr;
387 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
390 case EMR_SETWINDOWORGEX:
392 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
393 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
396 case EMR_SETWINDOWEXTEX:
398 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
399 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
402 case EMR_SETVIEWPORTORGEX:
404 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
405 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
408 case EMR_SETVIEWPORTEXTEX:
410 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
411 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
416 trace("EMR_SAVEDC\n");
421 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
422 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
427 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
428 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
431 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
432 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
435 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
436 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
439 ok(restore_no <= 3, "restore_no %d\n", restore_no);
440 save_state += restoredc->iRelative;
443 case EMR_SELECTOBJECT:
445 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
446 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
451 ok(save_state == 0, "EOF save_state %d\n", save_state);
452 ok(select_no == 3, "Too many/few selects %i\n",select_no);
457 SetLastError(0xdeadbeef);
458 ret = GetWorldTransform(hdc, &xform);
459 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
461 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
462 trace("window org (%d,%d)\n", pt.x, pt.y);
463 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
464 trace("vport org (%d,%d)\n", pt.x, pt.y);
465 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
466 trace("window ext (%d,%d)\n", size.cx, size.cy);
467 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
468 trace("vport ext (%d,%d)\n", size.cx, size.cy);
472 ok(ret, "GetWorldTransform error %u\n", GetLastError());
473 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
479 static void test_SaveDC(void)
481 HDC hdcMetafile, hdcDisplay;
482 HENHMETAFILE hMetafile;
487 HFONT hFont,hFont2,hFontOld,hFontCheck;
488 static const RECT rc = { 0, 0, 150, 150 };
490 /* Win9x doesn't play EMFs on invisible windows */
491 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
492 0, 0, 200, 200, 0, 0, 0, NULL);
493 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
495 hdcDisplay = GetDC(hwnd);
496 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
498 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
499 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
501 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
503 /* Need to write something to the emf, otherwise Windows won't play it back */
504 LineTo(hdcMetafile, 150, 150);
506 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
507 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
508 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
509 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
511 /* Force Win9x to update DC state */
512 SetPixelV(hdcMetafile, 50, 50, 0);
514 ret = GetViewportOrgEx(hdcMetafile, &pt);
515 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
516 ret = GetViewportExtEx(hdcMetafile, &size);
517 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
518 ret = SaveDC(hdcMetafile);
519 ok(ret == 1, "ret = %d\n", ret);
521 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
522 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
523 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
524 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
526 /* Force Win9x to update DC state */
527 SetPixelV(hdcMetafile, 50, 50, 0);
529 ret = GetViewportOrgEx(hdcMetafile, &pt);
530 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
531 ret = GetViewportExtEx(hdcMetafile, &size);
532 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
533 ret = SaveDC(hdcMetafile);
534 ok(ret == 2, "ret = %d\n", ret);
536 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
537 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
538 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
539 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
540 SetPolyFillMode( hdcMetafile, ALTERNATE );
541 SetBkColor( hdcMetafile, 0 );
543 /* Force Win9x to update DC state */
544 SetPixelV(hdcMetafile, 50, 50, 0);
546 ret = GetViewportOrgEx(hdcMetafile, &pt);
547 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
548 ret = GetViewportExtEx(hdcMetafile, &size);
549 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
550 ret = SaveDC(hdcMetafile);
551 ok(ret == 3, "ret = %d\n", ret);
553 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
554 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
555 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
556 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
558 SetPolyFillMode( hdcMetafile, WINDING );
559 SetBkColor( hdcMetafile, 0x123456 );
560 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
561 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
563 /* Force Win9x to update DC state */
564 SetPixelV(hdcMetafile, 50, 50, 0);
566 ret = GetViewportOrgEx(hdcMetafile, &pt);
567 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
568 ret = GetViewportExtEx(hdcMetafile, &size);
569 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
570 ret = RestoreDC(hdcMetafile, -1);
571 ok(ret, "ret = %d\n", ret);
573 ret = GetViewportOrgEx(hdcMetafile, &pt);
574 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
575 ret = GetViewportExtEx(hdcMetafile, &size);
576 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
577 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
578 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
579 ret = SaveDC(hdcMetafile);
580 ok(ret == 3, "ret = %d\n", ret);
582 ret = GetViewportOrgEx(hdcMetafile, &pt);
583 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
584 ret = GetViewportExtEx(hdcMetafile, &size);
585 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
586 ret = RestoreDC(hdcMetafile, 1);
587 ok(ret, "ret = %d\n", ret);
588 ret = GetViewportOrgEx(hdcMetafile, &pt);
589 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
590 ret = GetViewportExtEx(hdcMetafile, &size);
591 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
593 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
594 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
595 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
596 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
598 /* Force Win9x to update DC state */
599 SetPixelV(hdcMetafile, 50, 50, 0);
601 ret = GetViewportOrgEx(hdcMetafile, &pt);
602 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
603 ret = GetViewportExtEx(hdcMetafile, &size);
604 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
605 ret = SaveDC(hdcMetafile);
606 ok(ret == 1, "ret = %d\n", ret);
608 ret = GetViewportOrgEx(hdcMetafile, &pt);
609 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
610 ret = GetViewportExtEx(hdcMetafile, &size);
611 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
612 ret = SaveDC(hdcMetafile);
613 ok(ret == 2, "ret = %d\n", ret);
615 memset(&orig_lf, 0, sizeof(orig_lf));
616 orig_lf.lfCharSet = ANSI_CHARSET;
617 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
618 orig_lf.lfWeight = FW_DONTCARE;
619 orig_lf.lfHeight = 7;
620 orig_lf.lfQuality = DEFAULT_QUALITY;
621 lstrcpyA(orig_lf.lfFaceName, "Arial");
622 hFont = CreateFontIndirectA(&orig_lf);
623 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
625 hFontOld = SelectObject(hdcMetafile, hFont);
627 hFont2 = CreateFontIndirectA(&orig_lf);
628 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
629 hFontCheck = SelectObject(hdcMetafile, hFont2);
630 ok(hFontCheck == hFont, "Font not selected\n");
632 /* Force Win9x to update DC state */
633 SetPixelV(hdcMetafile, 50, 50, 0);
635 ret = RestoreDC(hdcMetafile, 1);
636 ok(ret, "ret = %d\n", ret);
637 ret = GetViewportOrgEx(hdcMetafile, &pt);
638 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
639 ret = GetViewportExtEx(hdcMetafile, &size);
640 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
642 hFontCheck = SelectObject(hdcMetafile, hFontOld);
643 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
644 "Font not reverted with DC Restore\n");
646 ret = RestoreDC(hdcMetafile, -20);
647 ok(!ret, "ret = %d\n", ret);
648 ret = RestoreDC(hdcMetafile, 20);
649 ok(!ret, "ret = %d\n", ret);
651 hMetafile = CloseEnhMetaFile(hdcMetafile);
652 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
654 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
655 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
657 ret = DeleteObject(hFont);
658 ok( ret, "DeleteObject error %d\n", GetLastError());
659 ret = DeleteObject(hFont2);
660 ok( ret, "DeleteObject error %d\n", GetLastError());
661 ret = DeleteEnhMetaFile(hMetafile);
662 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
663 ret = ReleaseDC(hwnd, hdcDisplay);
664 ok( ret, "ReleaseDC error %d\n", GetLastError());
668 static void test_mf_SaveDC(void)
675 HFONT hFont,hFont2,hFontOld,hFontCheck;
677 hdcMetafile = CreateMetaFileA(NULL);
678 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
680 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
681 ok (ret, "SetMapMode should not fail\n");
683 /* Need to write something to the emf, otherwise Windows won't play it back */
684 LineTo(hdcMetafile, 150, 150);
686 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
687 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
688 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
689 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
691 /* Force Win9x to update DC state */
692 SetPixelV(hdcMetafile, 50, 50, 0);
694 ret = GetViewportOrgEx(hdcMetafile, &pt);
695 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
696 ret = GetViewportExtEx(hdcMetafile, &size);
697 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
698 ret = SaveDC(hdcMetafile);
699 ok(ret == 1, "ret = %d\n", ret);
701 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
702 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
703 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
704 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
706 /* Force Win9x to update DC state */
707 SetPixelV(hdcMetafile, 50, 50, 0);
709 ret = SaveDC(hdcMetafile);
710 ok(ret == 1, "ret = %d\n", ret);
712 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
713 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
714 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
715 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
717 /* Force Win9x to update DC state */
718 SetPixelV(hdcMetafile, 50, 50, 0);
719 SetPolyFillMode( hdcMetafile, ALTERNATE );
720 SetBkColor( hdcMetafile, 0 );
722 ret = SaveDC(hdcMetafile);
723 ok(ret == 1, "ret = %d\n", ret);
725 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
726 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
727 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
728 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
730 SetPolyFillMode( hdcMetafile, WINDING );
731 SetBkColor( hdcMetafile, 0x123456 );
732 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
733 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
735 /* Force Win9x to update DC state */
736 SetPixelV(hdcMetafile, 50, 50, 0);
738 ret = RestoreDC(hdcMetafile, -1);
739 ok(ret, "ret = %d\n", ret);
741 ret = SaveDC(hdcMetafile);
742 ok(ret == 1, "ret = %d\n", ret);
744 ret = RestoreDC(hdcMetafile, 1);
745 ok(ret, "ret = %d\n", ret);
747 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
748 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
749 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
750 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
752 /* Force Win9x to update DC state */
753 SetPixelV(hdcMetafile, 50, 50, 0);
755 ret = SaveDC(hdcMetafile);
756 ok(ret == 1, "ret = %d\n", ret);
758 ret = SaveDC(hdcMetafile);
759 ok(ret == 1, "ret = %d\n", ret);
761 memset(&orig_lf, 0, sizeof(orig_lf));
762 orig_lf.lfCharSet = ANSI_CHARSET;
763 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
764 orig_lf.lfWeight = FW_DONTCARE;
765 orig_lf.lfHeight = 7;
766 orig_lf.lfQuality = DEFAULT_QUALITY;
767 lstrcpyA(orig_lf.lfFaceName, "Arial");
768 hFont = CreateFontIndirectA(&orig_lf);
769 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
771 hFontOld = SelectObject(hdcMetafile, hFont);
773 hFont2 = CreateFontIndirectA(&orig_lf);
774 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
775 hFontCheck = SelectObject(hdcMetafile, hFont2);
776 ok(hFontCheck == hFont, "Font not selected\n");
778 /* Force Win9x to update DC state */
779 SetPixelV(hdcMetafile, 50, 50, 0);
781 ret = RestoreDC(hdcMetafile, 1);
782 ok(ret, "ret = %d\n", ret);
784 hFontCheck = SelectObject(hdcMetafile, hFontOld);
785 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
787 /* restore level is ignored */
788 ret = RestoreDC(hdcMetafile, -20);
789 ok(ret, "ret = %d\n", ret);
790 ret = RestoreDC(hdcMetafile, 20);
791 ok(ret, "ret = %d\n", ret);
792 ret = RestoreDC(hdcMetafile, 0);
793 ok(ret, "ret = %d\n", ret);
795 hMetafile = CloseMetaFile(hdcMetafile);
796 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
798 ret = DeleteMetaFile(hMetafile);
799 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
800 ret = DeleteObject(hFont);
801 ok( ret, "DeleteObject error %d\n", GetLastError());
802 ret = DeleteObject(hFont2);
803 ok( ret, "DeleteObject error %d\n", GetLastError());
807 /* Win-format metafile (mfdrv) tests */
808 /* These tests compare the generated metafiles byte-by-byte */
809 /* with the nominal results. */
811 /* Maximum size of sample metafiles in bytes. */
812 #define MF_BUFSIZE 512
814 /* 8x8 bitmap data for a pattern brush */
815 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
816 0x01, 0x00, 0x02, 0x00,
817 0x03, 0x00, 0x04, 0x00,
818 0x05, 0x00, 0x06, 0x00,
819 0x07, 0x00, 0x08, 0x00
822 /* Sample metafiles to be compared to the outputs of the
826 static const unsigned char MF_BLANK_BITS[] = {
827 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
832 static const unsigned char MF_GRAPHICS_BITS[] = {
833 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
836 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
837 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
838 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
839 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
840 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
841 0x00, 0x00, 0x00, 0x00
844 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
845 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
846 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
848 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
849 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
850 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
854 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
855 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
856 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
857 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
858 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
859 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
863 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
865 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
868 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
869 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
870 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
874 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
876 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
881 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
882 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
883 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
886 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
889 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
890 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
891 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
893 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
894 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
895 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
896 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
899 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
900 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
901 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
902 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
903 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
904 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
906 0x14, 0x00, 0x00, 0x00
909 static const unsigned char MF_LINETO_BITS[] = {
910 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
911 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
913 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
917 static const unsigned char EMF_LINETO_BITS[] = {
918 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
923 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
924 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
925 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
928 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
930 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
931 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
932 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
933 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
934 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
935 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
936 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
937 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
938 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
939 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
941 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
942 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
943 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
944 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
945 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
946 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
947 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
948 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
949 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
950 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
951 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
952 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
953 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
955 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
959 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
960 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
965 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
966 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
967 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
970 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
972 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
973 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
974 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
975 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
976 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
977 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
978 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
979 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
981 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
983 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
984 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
985 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
986 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
987 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
988 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
989 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
990 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
991 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
992 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
993 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
994 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
995 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
997 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
998 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1001 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1002 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1007 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1008 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1009 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1012 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1015 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1016 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1017 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1018 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1019 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1020 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1021 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1022 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1023 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1025 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1026 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1028 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1030 0x14, 0x00, 0x00, 0x00
1033 /* For debugging or dumping the raw metafiles produced by
1034 * new test functions.
1036 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1037 INT nobj, LPARAM param)
1039 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1040 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1044 /* For debugging or dumping the raw metafiles produced by
1045 * new test functions.
1048 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1050 BYTE buf[MF_BUFSIZE];
1053 if (!winetest_debug) return;
1055 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1056 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1058 printf ("MetaFile %s has bits:\n{\n ", desc);
1059 for (i=0; i<mfsize; i++)
1061 printf ("0x%02x", buf[i]);
1064 else if (i % 8 == 7)
1072 /* Compare the metafile produced by a test function with the
1073 * expected raw metafile data in "bits".
1074 * Return value is 0 for a perfect match,
1075 * -1 if lengths aren't equal,
1076 * otherwise returns the number of non-matching bytes.
1079 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1082 unsigned char buf[MF_BUFSIZE];
1086 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1087 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1088 if (mfsize < MF_BUFSIZE)
1089 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1090 desc, mfsize, bsize);
1092 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1093 desc, mfsize, bsize);
1094 if (mfsize != bsize)
1098 for (i=0; i<bsize; i++)
1100 if (buf[i] != bits[i])
1103 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1104 desc, mfsize, bsize, diff);
1109 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1111 unsigned char buf[MF_BUFSIZE];
1112 DWORD mfsize, rd_size, i;
1117 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1118 assert(hfile != INVALID_HANDLE_VALUE);
1120 mfsize = GetFileSize(hfile, NULL);
1121 assert(mfsize <= MF_BUFSIZE);
1123 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1124 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1128 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1130 if (mfsize != bsize)
1134 for (i=0; i<bsize; i++)
1136 if (buf[i] != bits[i])
1139 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1140 desc, mfsize, bsize, diff);
1145 /* For debugging or dumping the raw EMFs produced by
1146 * new test functions.
1148 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1150 BYTE buf[MF_BUFSIZE];
1153 if (!winetest_debug) return;
1155 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1156 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1158 printf("EMF %s has bits:\n{\n ", desc);
1159 for (i = 0; i < mfsize; i++)
1161 printf ("0x%02x", buf[i]);
1164 else if (i % 8 == 7)
1172 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1175 BYTE buf[MF_BUFSIZE];
1176 UINT mfsize, offset;
1178 if (!winetest_debug) return;
1180 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1181 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1183 printf("EMF %s has records:\n", desc);
1187 while(offset < mfsize)
1189 EMR *emr = (EMR *)(emf + offset);
1190 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1191 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1192 offset += emr->nSize;
1196 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1201 if (!winetest_debug) return;
1203 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1204 buf = (const BYTE *)emr;
1205 for (i = 0; i < emr->nSize; i++)
1207 printf ("0x%02x", buf[i]);
1208 if (i == emr->nSize - 1)
1210 else if (i % 8 == 7)
1218 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1220 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1221 eto->rclBounds.right, eto->rclBounds.bottom);
1222 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1223 trace("exScale: %f\n", eto->exScale);
1224 trace("eyScale: %f\n", eto->eyScale);
1225 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1226 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1227 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1228 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1229 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1230 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1231 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1234 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1235 const char *desc, BOOL ignore_scaling)
1239 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1240 desc, emr1->iType, emr2->iType);
1242 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1243 desc, emr1->nSize, emr2->nSize);
1245 /* iType and nSize mismatches are fatal */
1246 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1248 /* contents of EMR_GDICOMMENT are not interesting */
1249 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1251 /* different Windows versions setup DC scaling differently when
1252 * converting an old style metafile to an EMF.
1254 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1255 emr1->iType == EMR_SETVIEWPORTEXTEX))
1258 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1260 EMREXTTEXTOUTW *eto1, *eto2;
1262 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1263 memcpy(eto1, emr1, emr1->nSize);
1264 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1265 memcpy(eto2, emr2, emr2->nSize);
1267 /* different Windows versions setup DC scaling differently */
1268 eto1->exScale = eto1->eyScale = 0.0;
1269 eto2->exScale = eto2->eyScale = 0.0;
1271 diff = memcmp(eto1, eto2, emr1->nSize);
1274 dump_EMREXTTEXTOUT(eto1);
1275 dump_EMREXTTEXTOUT(eto2);
1277 HeapFree(GetProcessHeap(), 0, eto1);
1278 HeapFree(GetProcessHeap(), 0, eto2);
1281 diff = memcmp(emr1, emr2, emr1->nSize);
1283 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1287 dump_emf_record(emr1, "expected bits");
1288 dump_emf_record(emr2, "actual bits");
1291 return diff == 0; /* report all non-fatal record mismatches */
1294 /* Compare the EMF produced by a test function with the
1295 * expected raw EMF data in "bits".
1296 * Return value is 0 for a perfect match,
1297 * -1 if lengths aren't equal,
1298 * otherwise returns the number of non-matching bytes.
1300 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1301 UINT bsize, const char *desc,
1302 BOOL ignore_scaling)
1304 unsigned char buf[MF_BUFSIZE];
1305 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1306 const ENHMETAHEADER *emh1, *emh2;
1308 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1309 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1311 /* ENHMETAHEADER size could differ, depending on platform */
1312 diff_nt4 = sizeof(SIZEL);
1313 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1315 if (mfsize < MF_BUFSIZE)
1317 ok(mfsize == bsize ||
1318 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1319 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1320 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1323 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1324 desc, mfsize, bsize);
1326 /* basic things must match */
1327 emh1 = (const ENHMETAHEADER *)bits;
1328 emh2 = (const ENHMETAHEADER *)buf;
1329 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1330 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1331 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1332 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1334 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1335 ok(emh1->nSize == emh2->nSize ||
1336 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1337 broken(emh1->nSize - diff_9x == emh2->nSize),
1338 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1339 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1340 ok(emh1->nBytes == emh2->nBytes ||
1341 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1342 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1343 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1344 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1346 offset1 = emh1->nSize;
1347 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1348 while (offset1 < emh1->nBytes)
1350 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1351 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1353 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1354 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1356 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1358 /* We have already bailed out if iType or nSize don't match */
1359 offset1 += emr1->nSize;
1360 offset2 += emr2->nSize;
1365 /* Test a blank metafile. May be used as a template for new tests. */
1367 static void test_mf_Blank(void)
1370 HMETAFILE hMetafile;
1375 hdcMetafile = CreateMetaFileA(NULL);
1376 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1377 trace("hdcMetafile %p\n", hdcMetafile);
1379 /* Tests on metafile initialization */
1380 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1381 ok (caps == DT_METAFILE,
1382 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1384 hMetafile = CloseMetaFile(hdcMetafile);
1385 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1386 type = GetObjectType(hMetafile);
1387 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1388 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1390 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1393 dump_mf_bits(hMetafile, "mf_Blank");
1394 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1397 ret = DeleteMetaFile(hMetafile);
1398 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1401 static void test_CopyMetaFile(void)
1404 HMETAFILE hMetafile, hmf_copy;
1406 char temp_path[MAX_PATH];
1407 char mf_name[MAX_PATH];
1410 hdcMetafile = CreateMetaFileA(NULL);
1411 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1412 trace("hdcMetafile %p\n", hdcMetafile);
1414 hMetafile = CloseMetaFile(hdcMetafile);
1415 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1416 type = GetObjectType(hMetafile);
1417 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1419 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1422 dump_mf_bits(hMetafile, "mf_Blank");
1423 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1426 GetTempPathA(MAX_PATH, temp_path);
1427 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1429 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1430 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1432 type = GetObjectType(hmf_copy);
1433 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1435 ret = DeleteMetaFile(hMetafile);
1436 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1438 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1440 dump_mf_bits(hMetafile, "mf_Blank");
1441 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1444 ret = DeleteMetaFile(hmf_copy);
1445 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1447 DeleteFileA(mf_name);
1450 static void test_SetMetaFileBits(void)
1458 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1459 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1460 type = GetObjectType(hmf);
1461 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1463 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1465 dump_mf_bits(hmf, "mf_Graphics");
1466 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1469 ret = DeleteMetaFile(hmf);
1470 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1472 /* NULL data crashes XP SP1 */
1473 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1475 /* Now with not zero size */
1476 SetLastError(0xdeadbeef);
1477 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1478 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1479 ok(GetLastError() == ERROR_INVALID_DATA ||
1480 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1481 "wrong error %d\n", GetLastError());
1483 /* Now with not even size */
1484 SetLastError(0xdeadbeef);
1485 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1486 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1487 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1489 /* Now with zeroed out or faked some header fields */
1490 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1491 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1492 mh = (METAHEADER *)buf;
1493 /* corruption of any of the below fields leads to a failure */
1496 mh->mtHeaderSize = 0;
1497 SetLastError(0xdeadbeef);
1498 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1499 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1500 ok(GetLastError() == ERROR_INVALID_DATA ||
1501 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1502 "wrong error %d\n", GetLastError());
1504 /* Now with corrupted mtSize field */
1505 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1506 mh = (METAHEADER *)buf;
1507 /* corruption of mtSize doesn't lead to a failure */
1509 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1510 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1512 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1514 dump_mf_bits(hmf, "mf_Graphics");
1515 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1518 ret = DeleteMetaFile(hmf);
1519 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1521 /* Now with zeroed out mtSize field */
1522 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1523 mh = (METAHEADER *)buf;
1524 /* zeroing mtSize doesn't lead to a failure */
1526 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1527 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1529 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1531 dump_mf_bits(hmf, "mf_Graphics");
1532 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1535 ret = DeleteMetaFile(hmf);
1536 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1539 /* Simple APIs from mfdrv/graphics.c
1542 static void test_mf_Graphics(void)
1545 HMETAFILE hMetafile;
1549 hdcMetafile = CreateMetaFileA(NULL);
1550 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1551 trace("hdcMetafile %p\n", hdcMetafile);
1553 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1554 ok( ret, "MoveToEx error %d.\n", GetLastError());
1555 ret = LineTo(hdcMetafile, 2, 2);
1556 ok( ret, "LineTo error %d.\n", GetLastError());
1557 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1558 ok( ret, "MoveToEx error %d.\n", GetLastError());
1560 /* oldpoint gets garbage under Win XP, so the following test would
1561 * work under Wine but fails under Windows:
1563 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1564 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1565 * oldpoint.x, oldpoint.y);
1568 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1569 ok( ret, "Ellipse error %d.\n", GetLastError());
1571 hMetafile = CloseMetaFile(hdcMetafile);
1572 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1573 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1575 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1576 "mf_Graphics") != 0)
1578 dump_mf_bits(hMetafile, "mf_Graphics");
1579 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1582 ret = DeleteMetaFile(hMetafile);
1583 ok( ret, "DeleteMetaFile(%p) error %d\n",
1584 hMetafile, GetLastError());
1587 static void test_mf_PatternBrush(void)
1590 HMETAFILE hMetafile;
1595 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1597 orig_lb->lbStyle = BS_PATTERN;
1598 orig_lb->lbColor = RGB(0, 0, 0);
1599 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1600 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1602 hBrush = CreateBrushIndirect (orig_lb);
1603 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1605 hdcMetafile = CreateMetaFileA(NULL);
1606 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1607 trace("hdcMetafile %p\n", hdcMetafile);
1609 hBrush = SelectObject(hdcMetafile, hBrush);
1610 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1612 hMetafile = CloseMetaFile(hdcMetafile);
1613 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1614 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1616 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1617 "mf_Pattern_Brush") != 0)
1619 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1620 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1623 ret = DeleteMetaFile(hMetafile);
1624 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1625 ret = DeleteObject(hBrush);
1626 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1627 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1628 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1630 HeapFree (GetProcessHeap(), 0, orig_lb);
1633 static void test_mf_ExtTextOut_on_path(void)
1636 HMETAFILE hMetafile;
1638 static const INT dx[4] = { 3, 5, 8, 12 };
1640 hdcMetafile = CreateMetaFileA(NULL);
1641 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1642 trace("hdcMetafile %p\n", hdcMetafile);
1644 ret = BeginPath(hdcMetafile);
1645 ok(!ret, "BeginPath on metafile DC should fail\n");
1647 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1648 ok(ret, "ExtTextOut error %d\n", GetLastError());
1650 ret = EndPath(hdcMetafile);
1651 ok(!ret, "EndPath on metafile DC should fail\n");
1653 hMetafile = CloseMetaFile(hdcMetafile);
1654 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1656 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1657 "mf_TextOut_on_path") != 0)
1659 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1660 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1663 ret = DeleteMetaFile(hMetafile);
1664 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1667 static void test_emf_ExtTextOut_on_path(void)
1670 HDC hdcDisplay, hdcMetafile;
1671 HENHMETAFILE hMetafile;
1673 static const INT dx[4] = { 3, 5, 8, 12 };
1675 /* Win9x doesn't play EMFs on invisible windows */
1676 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1677 0, 0, 200, 200, 0, 0, 0, NULL);
1678 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1680 hdcDisplay = GetDC(hwnd);
1681 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1683 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1684 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1686 ret = BeginPath(hdcMetafile);
1687 ok(ret, "BeginPath error %d\n", GetLastError());
1689 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1690 ok(ret, "ExtTextOut error %d\n", GetLastError());
1692 ret = EndPath(hdcMetafile);
1693 ok(ret, "EndPath error %d\n", GetLastError());
1695 hMetafile = CloseEnhMetaFile(hdcMetafile);
1696 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1698 /* this doesn't succeed yet: EMF has correct size, all EMF records
1699 * are there, but their contents don't match for different reasons.
1701 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1702 "emf_TextOut_on_path", FALSE) != 0)
1704 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1705 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1708 ret = DeleteEnhMetaFile(hMetafile);
1709 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1710 ret = ReleaseDC(hwnd, hdcDisplay);
1711 ok(ret, "ReleaseDC error %d\n", GetLastError());
1712 DestroyWindow(hwnd);
1715 static const unsigned char EMF_CLIPPING[] =
1717 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1719 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1721 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1722 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1723 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1724 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1726 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1727 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1729 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1730 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1731 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1732 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1733 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1734 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1735 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1736 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1737 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1738 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1739 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1740 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1741 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1742 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1745 static void translate( POINT *pt, UINT count, const XFORM *xform )
1749 FLOAT x = (FLOAT)pt->x;
1750 FLOAT y = (FLOAT)pt->y;
1751 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1752 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1757 /* Compare rectangles allowing rounding errors */
1758 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1760 return abs(rc1->left - rc2->left) <= 1 &&
1761 abs(rc1->top - rc2->top) <= 1 &&
1762 abs(rc1->right - rc2->right) <= 1 &&
1763 abs(rc1->bottom - rc2->bottom) <= 1;
1766 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1767 const ENHMETARECORD *emr, int n_objs, LPARAM param)
1769 if (emr->iType == EMR_EXTSELECTCLIPRGN)
1771 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1775 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1777 const union _rgn *rgn1;
1779 RECT rect, rc_transformed;
1780 const RECT *rc = (const RECT *)param;
1786 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1787 clip->cbRgnData, clip->iMode);
1789 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1790 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1791 "too small data block: %u bytes\n", clip->cbRgnData);
1792 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1795 rgn1 = (const union _rgn *)clip->RgnData;
1797 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1798 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1799 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1800 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1801 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1803 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1805 rect = *(const RECT *)rgn1->data.Buffer;
1806 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1807 ok(EqualRect(&rect, rc), "rects don't match\n");
1809 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1810 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1811 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1812 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1814 hrgn = CreateRectRgn(0, 0, 0, 0);
1816 memset(&xform, 0, sizeof(xform));
1817 SetLastError(0xdeadbeef);
1818 ret = GetWorldTransform(hdc, &xform);
1819 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1821 ok(ret, "GetWorldTransform error %u\n", GetLastError());
1823 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1825 ret = GetClipRgn(hdc, hrgn);
1826 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1828 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1830 ret = GetClipRgn(hdc, hrgn);
1831 ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1833 /* Win9x returns empty clipping region */
1834 if (is_win9x) return 1;
1836 ret = GetRegionData(hrgn, 0, NULL);
1837 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1839 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1841 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1842 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1843 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1844 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1845 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1847 rect = rgn2.data.rdh.rcBound;
1848 rc_transformed = *rc;
1849 translate((POINT *)&rc_transformed, 2, &xform);
1850 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1851 rc_transformed.right, rc_transformed.bottom);
1852 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1854 rect = *(const RECT *)rgn2.data.Buffer;
1855 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1856 rc_transformed = *rc;
1857 translate((POINT *)&rc_transformed, 2, &xform);
1858 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1859 rc_transformed.right, rc_transformed.bottom);
1860 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1862 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1863 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1864 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1865 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1872 static void test_emf_clipping(void)
1874 static const RECT rc = { 0, 0, 100, 100 };
1875 RECT rc_clip = { 100, 100, 1024, 1024 };
1882 SetLastError(0xdeadbeef);
1883 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1884 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1886 /* Need to write something to the emf, otherwise Windows won't play it back */
1889 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1890 ret = SelectClipRgn(hdc, hrgn);
1891 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1893 SetLastError(0xdeadbeef);
1894 hemf = CloseEnhMetaFile(hdc);
1895 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1897 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1898 "emf_clipping", FALSE) != 0)
1900 dump_emf_bits(hemf, "emf_clipping");
1901 dump_emf_records(hemf, "emf_clipping");
1906 /* Win9x doesn't play EMFs on invisible windows */
1907 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1908 0, 0, 200, 200, 0, 0, 0, NULL);
1909 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1913 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1914 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1916 DeleteEnhMetaFile(hemf);
1917 ReleaseDC(hwnd, hdc);
1918 DestroyWindow(hwnd);
1921 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1923 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1924 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1925 /* When using MM_TEXT Win9x does not update the mapping mode
1926 * until a record is played which actually outputs something */
1927 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1928 LPtoDP(hdc, mapping, 2);
1929 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1930 lpEMFR->iType, lpEMFR->nSize,
1931 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1933 if (lpEMFR->iType == EMR_LINETO)
1936 if (!lpMFP || lpMFP->mm == MM_TEXT)
1940 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1941 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1945 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1947 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1948 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1949 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1950 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1952 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1953 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1954 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1960 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1969 hdcMf = CreateMetaFile(NULL);
1970 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1971 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1972 ok(ret, "LineTo failed with error %d\n", GetLastError());
1973 hmf = CloseMetaFile(hdcMf);
1974 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1976 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1978 dump_mf_bits(hmf, "mf_LineTo");
1979 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1982 size = GetMetaFileBitsEx(hmf, 0, NULL);
1983 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1984 pBits = HeapAlloc(GetProcessHeap(), 0, size);
1985 GetMetaFileBitsEx(hmf, size, pBits);
1986 DeleteMetaFile(hmf);
1987 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1988 HeapFree(GetProcessHeap(), 0, pBits);
1992 static void test_mf_conversions(void)
1994 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1996 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1999 RECT rect = { 0, 0, 100, 100 };
2000 mfp.mm = MM_ANISOTROPIC;
2004 hemf = create_converted_emf(&mfp);
2006 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2007 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2009 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2010 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2013 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2015 DeleteEnhMetaFile(hemf);
2016 DeleteDC(hdcOffscreen);
2019 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2021 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2024 RECT rect = { 0, 0, 100, 100 };
2029 hemf = create_converted_emf(&mfp);
2031 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2032 "emf_LineTo MM_TEXT", TRUE) != 0)
2034 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2035 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2038 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2040 DeleteEnhMetaFile(hemf);
2041 DeleteDC(hdcOffscreen);
2044 trace("Testing MF->EMF conversion (NULL mfp)\n");
2046 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2048 RECT rect = { 0, 0, 100, 100 };
2049 hemf = create_converted_emf(NULL);
2051 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2052 "emf_LineTo NULL", TRUE) != 0)
2054 dump_emf_bits(hemf, "emf_LineTo NULL");
2055 dump_emf_records(hemf, "emf_LineTo NULL");
2058 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2060 DeleteEnhMetaFile(hemf);
2061 DeleteDC(hdcOffscreen);
2065 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2066 LONG mm, LONG xExt, LONG yExt,
2067 RECTL * rclBounds, RECTL * rclFrame)
2070 METAFILEPICT * mfpPtr = NULL;
2072 ENHMETAHEADER header;
2083 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2084 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2085 if (!emf) return FALSE;
2086 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2087 ok(res != 0, "GetEnhMetaHeader failed\n");
2088 DeleteEnhMetaFile(emf);
2089 if (!res) return FALSE;
2091 *rclBounds = header.rclBounds;
2092 *rclFrame = header.rclFrame;
2096 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2097 LONG mm, LONG xExt, LONG yExt,
2098 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2100 RECTL rclBounds, rclFrame;
2102 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2109 msg = "mfp == NULL";
2113 const char * mm_str;
2116 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2117 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2118 default: mm_str = "Unexpected";
2120 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2124 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2125 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2126 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2127 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2128 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2129 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2130 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2131 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2135 static void test_SetWinMetaFileBits(void)
2143 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2144 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2145 RECTL rclBounds, rclFrame;
2149 wmfDC = CreateMetaFile(NULL);
2150 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2153 SetWindowExtEx(wmfDC, 100, 100, NULL);
2154 rect.left = rect.top = 0;
2155 rect.right = rect.bottom = 50;
2156 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2157 wmf = CloseMetaFile(wmfDC);
2158 ok(wmf != NULL, "Metafile creation failed\n");
2161 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2162 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2163 if (buffer_size == 0)
2165 DeleteMetaFile(wmf);
2169 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2170 ok(buffer != NULL, "HeapAlloc failed\n");
2173 DeleteMetaFile(wmf);
2177 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2178 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2179 DeleteMetaFile(wmf);
2180 if (res != buffer_size)
2182 HeapFree(GetProcessHeap(), 0, buffer);
2186 /* Get the reference bounds and frame */
2187 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2188 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2190 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2191 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2192 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2194 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2195 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2196 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2197 if (diffx < 0) diffx = -diffx;
2198 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2200 dc = CreateCompatibleDC(NULL);
2202 /* Allow 1 mm difference (rounding errors) */
2203 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2204 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2205 if (diffx < 0) diffx = -diffx;
2206 if (diffy < 0) diffy = -diffy;
2209 ok(diffx <= 1 && diffy <= 1,
2210 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2211 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2214 /* Allow 1 mm difference (rounding errors) */
2215 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2216 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2217 if (diffx < 0) diffx = -diffx;
2218 if (diffy < 0) diffy = -diffy;
2221 ok(diffx <= 1 && diffy <= 1,
2222 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2223 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2227 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2228 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2230 /* If xExt or yExt is zero or negative, the whole device surface is used */
2231 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2232 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2233 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2234 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2235 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2236 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2237 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2238 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2239 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2240 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2241 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2242 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2244 /* MSDN says that negative xExt and yExt values specify a ratio.
2245 Check that this is wrong and the whole device surface is used */
2246 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2247 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2249 /* Ordinary conversions */
2251 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2253 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2254 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2255 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2256 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2259 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2261 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2262 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2263 ok(rclBounds.left == 0 && rclBounds.top == 0,
2264 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2266 /* Wine has a rounding error */
2267 diffx = rclBounds.right - rclBounds.bottom;
2268 if (diffx < 0) diffx = -diffx;
2269 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2272 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2274 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2275 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2278 HeapFree(GetProcessHeap(), 0, buffer);
2281 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2282 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2283 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2285 static void test_gdiis(void)
2287 RECT rect = {0,0,100,100};
2288 HDC hdc, hemfDC, hmfDC;
2292 /* resolve all the functions */
2293 hgdi32 = GetModuleHandle("gdi32");
2294 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2295 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2296 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2298 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2300 win_skip("Needed GdiIs* functions are not available\n");
2304 /* try with nothing */
2305 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2306 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2307 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2309 /* try with a metafile */
2310 hmfDC = CreateMetaFile(NULL);
2311 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2312 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2313 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2314 DeleteMetaFile(CloseMetaFile(hmfDC));
2316 /* try with an enhanced metafile */
2318 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2319 ok(hemfDC != NULL, "failed to create emf\n");
2321 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2322 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2323 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2325 hemf = CloseEnhMetaFile(hemfDC);
2326 ok(hemf != NULL, "failed to close EMF\n");
2327 DeleteEnhMetaFile(hemf);
2328 ReleaseDC(NULL,hdc);
2331 static void test_SetEnhMetaFileBits(void)
2337 memset(data, 0xAA, sizeof(data));
2338 SetLastError(0xdeadbeef);
2339 hemf = SetEnhMetaFileBits(sizeof(data), data);
2340 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2341 ok(GetLastError() == ERROR_INVALID_DATA ||
2342 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2343 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2345 emh = (ENHMETAHEADER *)data;
2346 memset(emh, 0, sizeof(*emh));
2348 emh->iType = EMR_HEADER;
2349 emh->nSize = sizeof(*emh);
2350 emh->dSignature = ENHMETA_SIGNATURE;
2351 /* emh->nVersion = 0x10000; XP doesn't care about version */
2352 emh->nBytes = sizeof(*emh);
2353 /* emh->nRecords = 1; XP doesn't care about records */
2354 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2356 SetLastError(0xdeadbeef);
2357 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2358 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2359 DeleteEnhMetaFile(hemf);
2361 /* XP refuses to load unaligned EMF */
2363 SetLastError(0xdeadbeef);
2364 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2366 broken(hemf != NULL), /* Win9x, WinMe */
2367 "SetEnhMetaFileBits should fail\n");
2368 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2369 DeleteEnhMetaFile(hemf);
2371 emh->dSignature = 0;
2373 SetLastError(0xdeadbeef);
2374 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2376 broken(hemf != NULL), /* Win9x, WinMe */
2377 "SetEnhMetaFileBits should fail\n");
2378 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2379 DeleteEnhMetaFile(hemf);
2382 START_TEST(metafile)
2384 init_function_pointers();
2386 /* For enhanced metafiles (enhmfdrv) */
2390 /* For win-format metafiles (mfdrv) */
2394 test_mf_PatternBrush();
2395 test_CopyMetaFile();
2396 test_SetMetaFileBits();
2397 test_mf_ExtTextOut_on_path();
2398 test_emf_ExtTextOut_on_path();
2399 test_emf_clipping();
2401 /* For metafile conversions */
2402 test_mf_conversions();
2403 test_SetWinMetaFileBits();
2406 test_SetEnhMetaFileBits();