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 ret = GetWindowOrgEx(hdc, &pt);
344 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
345 trace("window org (%d,%d)\n", pt.x, pt.y);
346 ret = GetViewportOrgEx(hdc, &pt);
347 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
348 trace("vport org (%d,%d)\n", pt.x, pt.y);
349 ret = GetWindowExtEx(hdc, &size);
350 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
351 trace("window ext (%d,%d)\n", size.cx, size.cy);
352 ret = GetViewportExtEx(hdc, &size);
353 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
354 trace("vport ext (%d,%d)\n", size.cx, size.cy);
358 ok(ret, "GetWorldTransform error %u\n", GetLastError());
359 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
362 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
368 static RECT exp_bounds = { 0, 0, 150, 150 };
370 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
372 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
373 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
374 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
375 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
376 emf->szlDevice.cx, emf->szlDevice.cy);
378 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
379 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
384 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
390 const EMRLINETO *line = (const EMRLINETO *)emr;
391 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
394 case EMR_SETWINDOWORGEX:
396 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
397 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
400 case EMR_SETWINDOWEXTEX:
402 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
403 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
406 case EMR_SETVIEWPORTORGEX:
408 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
409 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
412 case EMR_SETVIEWPORTEXTEX:
414 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
415 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
420 trace("EMR_SAVEDC\n");
425 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
426 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
431 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
432 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
435 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
436 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
439 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
440 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
443 ok(restore_no <= 3, "restore_no %d\n", restore_no);
444 save_state += restoredc->iRelative;
447 case EMR_SELECTOBJECT:
449 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
450 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
455 ok(save_state == 0, "EOF save_state %d\n", save_state);
456 ok(select_no == 3, "Too many/few selects %i\n",select_no);
461 SetLastError(0xdeadbeef);
462 ret = GetWorldTransform(hdc, &xform);
463 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
465 ret = GetWindowOrgEx(hdc, &pt);
466 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
467 trace("window org (%d,%d)\n", pt.x, pt.y);
468 ret = GetViewportOrgEx(hdc, &pt);
469 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
470 trace("vport org (%d,%d)\n", pt.x, pt.y);
471 ret = GetWindowExtEx(hdc, &size);
472 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
473 trace("window ext (%d,%d)\n", size.cx, size.cy);
474 ret = GetViewportExtEx(hdc, &size);
475 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
476 trace("vport ext (%d,%d)\n", size.cx, size.cy);
480 ok(ret, "GetWorldTransform error %u\n", GetLastError());
481 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
487 static void test_SaveDC(void)
489 HDC hdcMetafile, hdcDisplay;
490 HENHMETAFILE hMetafile;
495 HFONT hFont,hFont2,hFontOld,hFontCheck;
496 static const RECT rc = { 0, 0, 150, 150 };
498 /* Win9x doesn't play EMFs on invisible windows */
499 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
500 0, 0, 200, 200, 0, 0, 0, NULL);
501 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
503 hdcDisplay = GetDC(hwnd);
504 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
506 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
507 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
509 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
511 /* Need to write something to the emf, otherwise Windows won't play it back */
512 LineTo(hdcMetafile, 150, 150);
514 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
515 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
516 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
517 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
519 /* Force Win9x to update DC state */
520 SetPixelV(hdcMetafile, 50, 50, 0);
522 ret = GetViewportOrgEx(hdcMetafile, &pt);
523 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
524 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
525 ret = GetViewportExtEx(hdcMetafile, &size);
526 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
527 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
528 ret = SaveDC(hdcMetafile);
529 ok(ret == 1, "ret = %d\n", ret);
531 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
532 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
533 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
534 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
536 /* Force Win9x to update DC state */
537 SetPixelV(hdcMetafile, 50, 50, 0);
539 ret = GetViewportOrgEx(hdcMetafile, &pt);
540 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
541 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
542 ret = GetViewportExtEx(hdcMetafile, &size);
543 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
544 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
545 ret = SaveDC(hdcMetafile);
546 ok(ret == 2, "ret = %d\n", ret);
548 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
549 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
550 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
551 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
552 SetPolyFillMode( hdcMetafile, ALTERNATE );
553 SetBkColor( hdcMetafile, 0 );
555 /* Force Win9x to update DC state */
556 SetPixelV(hdcMetafile, 50, 50, 0);
558 ret = GetViewportOrgEx(hdcMetafile, &pt);
559 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
560 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
561 ret = GetViewportExtEx(hdcMetafile, &size);
562 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
563 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
564 ret = SaveDC(hdcMetafile);
565 ok(ret == 3, "ret = %d\n", ret);
567 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
568 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
569 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
570 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
572 SetPolyFillMode( hdcMetafile, WINDING );
573 SetBkColor( hdcMetafile, 0x123456 );
574 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
575 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
577 /* Force Win9x to update DC state */
578 SetPixelV(hdcMetafile, 50, 50, 0);
580 ret = GetViewportOrgEx(hdcMetafile, &pt);
581 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
582 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
583 ret = GetViewportExtEx(hdcMetafile, &size);
584 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
585 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
586 ret = RestoreDC(hdcMetafile, -1);
587 ok(ret, "ret = %d\n", ret);
589 ret = GetViewportOrgEx(hdcMetafile, &pt);
590 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
591 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
592 ret = GetViewportExtEx(hdcMetafile, &size);
593 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
594 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
595 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
596 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
597 ret = SaveDC(hdcMetafile);
598 ok(ret == 3, "ret = %d\n", ret);
600 ret = GetViewportOrgEx(hdcMetafile, &pt);
601 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
602 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
603 ret = GetViewportExtEx(hdcMetafile, &size);
604 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
605 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
606 ret = RestoreDC(hdcMetafile, 1);
607 ok(ret, "ret = %d\n", ret);
608 ret = GetViewportOrgEx(hdcMetafile, &pt);
609 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
610 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
611 ret = GetViewportExtEx(hdcMetafile, &size);
612 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
613 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
615 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
616 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
617 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
618 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
620 /* Force Win9x to update DC state */
621 SetPixelV(hdcMetafile, 50, 50, 0);
623 ret = GetViewportOrgEx(hdcMetafile, &pt);
624 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
625 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
626 ret = GetViewportExtEx(hdcMetafile, &size);
627 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
628 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
629 ret = SaveDC(hdcMetafile);
630 ok(ret == 1, "ret = %d\n", ret);
632 ret = GetViewportOrgEx(hdcMetafile, &pt);
633 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
634 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
635 ret = GetViewportExtEx(hdcMetafile, &size);
636 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
637 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
638 ret = SaveDC(hdcMetafile);
639 ok(ret == 2, "ret = %d\n", ret);
641 memset(&orig_lf, 0, sizeof(orig_lf));
642 orig_lf.lfCharSet = ANSI_CHARSET;
643 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
644 orig_lf.lfWeight = FW_DONTCARE;
645 orig_lf.lfHeight = 7;
646 orig_lf.lfQuality = DEFAULT_QUALITY;
647 lstrcpyA(orig_lf.lfFaceName, "Arial");
648 hFont = CreateFontIndirectA(&orig_lf);
649 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
651 hFontOld = SelectObject(hdcMetafile, hFont);
653 hFont2 = CreateFontIndirectA(&orig_lf);
654 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
655 hFontCheck = SelectObject(hdcMetafile, hFont2);
656 ok(hFontCheck == hFont, "Font not selected\n");
658 /* Force Win9x to update DC state */
659 SetPixelV(hdcMetafile, 50, 50, 0);
661 ret = RestoreDC(hdcMetafile, 1);
662 ok(ret, "ret = %d\n", ret);
663 ret = GetViewportOrgEx(hdcMetafile, &pt);
664 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
665 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
666 ret = GetViewportExtEx(hdcMetafile, &size);
667 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
668 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
670 hFontCheck = SelectObject(hdcMetafile, hFontOld);
671 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
672 "Font not reverted with DC Restore\n");
674 ret = RestoreDC(hdcMetafile, -20);
675 ok(!ret, "ret = %d\n", ret);
676 ret = RestoreDC(hdcMetafile, 20);
677 ok(!ret, "ret = %d\n", ret);
679 hMetafile = CloseEnhMetaFile(hdcMetafile);
680 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
682 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
683 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
685 ret = DeleteObject(hFont);
686 ok( ret, "DeleteObject error %d\n", GetLastError());
687 ret = DeleteObject(hFont2);
688 ok( ret, "DeleteObject error %d\n", GetLastError());
689 ret = DeleteEnhMetaFile(hMetafile);
690 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
691 ret = ReleaseDC(hwnd, hdcDisplay);
692 ok( ret, "ReleaseDC error %d\n", GetLastError());
696 static void test_mf_SaveDC(void)
703 HFONT hFont,hFont2,hFontOld,hFontCheck;
705 hdcMetafile = CreateMetaFileA(NULL);
706 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
708 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
709 ok (ret, "SetMapMode should not fail\n");
711 /* Need to write something to the emf, otherwise Windows won't play it back */
712 LineTo(hdcMetafile, 150, 150);
714 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
715 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
716 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
717 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
719 /* Force Win9x to update DC state */
720 SetPixelV(hdcMetafile, 50, 50, 0);
722 ret = GetViewportOrgEx(hdcMetafile, &pt);
723 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
724 ret = GetViewportExtEx(hdcMetafile, &size);
725 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
726 ret = SaveDC(hdcMetafile);
727 ok(ret == 1, "ret = %d\n", ret);
729 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
730 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
731 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
732 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
734 /* Force Win9x to update DC state */
735 SetPixelV(hdcMetafile, 50, 50, 0);
737 ret = SaveDC(hdcMetafile);
738 ok(ret == 1, "ret = %d\n", ret);
740 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
741 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
742 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
743 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
745 /* Force Win9x to update DC state */
746 SetPixelV(hdcMetafile, 50, 50, 0);
747 SetPolyFillMode( hdcMetafile, ALTERNATE );
748 SetBkColor( hdcMetafile, 0 );
750 ret = SaveDC(hdcMetafile);
751 ok(ret == 1, "ret = %d\n", ret);
753 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
754 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
755 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
756 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
758 SetPolyFillMode( hdcMetafile, WINDING );
759 SetBkColor( hdcMetafile, 0x123456 );
760 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
761 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
763 /* Force Win9x to update DC state */
764 SetPixelV(hdcMetafile, 50, 50, 0);
766 ret = RestoreDC(hdcMetafile, -1);
767 ok(ret, "ret = %d\n", ret);
769 ret = SaveDC(hdcMetafile);
770 ok(ret == 1, "ret = %d\n", ret);
772 ret = RestoreDC(hdcMetafile, 1);
773 ok(ret, "ret = %d\n", ret);
775 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
776 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
777 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
778 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
780 /* Force Win9x to update DC state */
781 SetPixelV(hdcMetafile, 50, 50, 0);
783 ret = SaveDC(hdcMetafile);
784 ok(ret == 1, "ret = %d\n", ret);
786 ret = SaveDC(hdcMetafile);
787 ok(ret == 1, "ret = %d\n", ret);
789 memset(&orig_lf, 0, sizeof(orig_lf));
790 orig_lf.lfCharSet = ANSI_CHARSET;
791 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
792 orig_lf.lfWeight = FW_DONTCARE;
793 orig_lf.lfHeight = 7;
794 orig_lf.lfQuality = DEFAULT_QUALITY;
795 lstrcpyA(orig_lf.lfFaceName, "Arial");
796 hFont = CreateFontIndirectA(&orig_lf);
797 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
799 hFontOld = SelectObject(hdcMetafile, hFont);
801 hFont2 = CreateFontIndirectA(&orig_lf);
802 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
803 hFontCheck = SelectObject(hdcMetafile, hFont2);
804 ok(hFontCheck == hFont, "Font not selected\n");
806 /* Force Win9x to update DC state */
807 SetPixelV(hdcMetafile, 50, 50, 0);
809 ret = RestoreDC(hdcMetafile, 1);
810 ok(ret, "ret = %d\n", ret);
812 hFontCheck = SelectObject(hdcMetafile, hFontOld);
813 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
815 /* restore level is ignored */
816 ret = RestoreDC(hdcMetafile, -20);
817 ok(ret, "ret = %d\n", ret);
818 ret = RestoreDC(hdcMetafile, 20);
819 ok(ret, "ret = %d\n", ret);
820 ret = RestoreDC(hdcMetafile, 0);
821 ok(ret, "ret = %d\n", ret);
823 hMetafile = CloseMetaFile(hdcMetafile);
824 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
826 ret = DeleteMetaFile(hMetafile);
827 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
828 ret = DeleteObject(hFont);
829 ok( ret, "DeleteObject error %d\n", GetLastError());
830 ret = DeleteObject(hFont2);
831 ok( ret, "DeleteObject error %d\n", GetLastError());
835 /* Win-format metafile (mfdrv) tests */
836 /* These tests compare the generated metafiles byte-by-byte */
837 /* with the nominal results. */
839 /* Maximum size of sample metafiles in bytes. */
840 #define MF_BUFSIZE 512
842 /* 8x8 bitmap data for a pattern brush */
843 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
844 0x01, 0x00, 0x02, 0x00,
845 0x03, 0x00, 0x04, 0x00,
846 0x05, 0x00, 0x06, 0x00,
847 0x07, 0x00, 0x08, 0x00
850 /* Sample metafiles to be compared to the outputs of the
854 static const unsigned char MF_BLANK_BITS[] = {
855 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
856 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
857 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
860 static const unsigned char MF_GRAPHICS_BITS[] = {
861 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
862 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
864 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
865 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
866 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
867 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
868 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
869 0x00, 0x00, 0x00, 0x00
872 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
873 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
874 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
875 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
876 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
877 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
878 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
879 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
883 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
884 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
885 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
886 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
887 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
891 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
893 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
894 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
895 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
896 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
897 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
898 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
902 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
904 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
906 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
908 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
909 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
910 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
911 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
913 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
914 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
915 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
917 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
918 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
919 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
921 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
922 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
923 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
924 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
925 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
927 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
928 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
929 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
930 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
931 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
932 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
933 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
934 0x14, 0x00, 0x00, 0x00
937 static const unsigned char MF_LINETO_BITS[] = {
938 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
939 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
941 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
945 static const unsigned char EMF_LINETO_BITS[] = {
946 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
948 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
951 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
952 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
953 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
955 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
956 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
957 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
958 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
959 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
960 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
961 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
962 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
963 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
964 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
965 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
966 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
967 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
969 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
970 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
971 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
972 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
973 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
974 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
975 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
976 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
977 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
978 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
979 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
980 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
981 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
983 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
987 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
988 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
990 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
993 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
994 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
995 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
997 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
998 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1000 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1001 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1002 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1003 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1004 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1005 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1006 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1007 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1008 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1009 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1011 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1012 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1013 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1014 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1015 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1016 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1017 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1018 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1019 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1020 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1021 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1022 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1023 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1024 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1025 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1026 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1029 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1030 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1031 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1032 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1033 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1035 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1036 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1037 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1038 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1039 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1040 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1041 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1043 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1044 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1045 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1046 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1047 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1048 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1049 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1050 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1051 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1052 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1053 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1054 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1055 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1056 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1057 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1058 0x14, 0x00, 0x00, 0x00
1061 static const unsigned char EMF_BITBLT[] =
1063 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1065 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1067 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1068 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1069 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1070 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1071 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1072 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1073 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1076 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1077 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1078 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1079 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1081 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1084 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1086 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1087 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1088 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1089 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1090 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1091 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1097 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1099 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1102 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1105 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1113 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1118 /* For debugging or dumping the raw metafiles produced by
1119 * new test functions.
1121 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1122 INT nobj, LPARAM param)
1124 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1125 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1129 /* For debugging or dumping the raw metafiles produced by
1130 * new test functions.
1133 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1135 BYTE buf[MF_BUFSIZE];
1138 if (!winetest_debug) return;
1140 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1141 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1143 printf ("MetaFile %s has bits:\n{\n ", desc);
1144 for (i=0; i<mfsize; i++)
1146 printf ("0x%02x", buf[i]);
1149 else if (i % 8 == 7)
1157 /* Compare the metafile produced by a test function with the
1158 * expected raw metafile data in "bits".
1159 * Return value is 0 for a perfect match,
1160 * -1 if lengths aren't equal,
1161 * otherwise returns the number of non-matching bytes.
1164 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1167 unsigned char buf[MF_BUFSIZE];
1171 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1172 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1173 if (mfsize < MF_BUFSIZE)
1174 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1175 desc, mfsize, bsize);
1177 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1178 desc, mfsize, bsize);
1179 if (mfsize != bsize)
1183 for (i=0; i<bsize; i++)
1185 if (buf[i] != bits[i])
1188 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1189 desc, mfsize, bsize, diff);
1194 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1196 unsigned char buf[MF_BUFSIZE];
1197 DWORD mfsize, rd_size, i;
1202 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1203 assert(hfile != INVALID_HANDLE_VALUE);
1205 mfsize = GetFileSize(hfile, NULL);
1206 assert(mfsize <= MF_BUFSIZE);
1208 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1209 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1213 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1215 if (mfsize != bsize)
1219 for (i=0; i<bsize; i++)
1221 if (buf[i] != bits[i])
1224 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1225 desc, mfsize, bsize, diff);
1230 /* For debugging or dumping the raw EMFs produced by
1231 * new test functions.
1233 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1235 BYTE buf[MF_BUFSIZE];
1238 if (!winetest_debug) return;
1240 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1241 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1243 printf("EMF %s has bits:\n{\n ", desc);
1244 for (i = 0; i < mfsize; i++)
1246 printf ("0x%02x", buf[i]);
1249 else if (i % 8 == 7)
1257 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1260 BYTE buf[MF_BUFSIZE];
1261 UINT mfsize, offset;
1263 if (!winetest_debug) return;
1265 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1266 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1268 printf("EMF %s has records:\n", desc);
1272 while(offset < mfsize)
1274 EMR *emr = (EMR *)(emf + offset);
1275 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1276 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1277 offset += emr->nSize;
1281 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1286 if (!winetest_debug) return;
1288 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1289 buf = (const BYTE *)emr;
1290 for (i = 0; i < emr->nSize; i++)
1292 printf ("0x%02x", buf[i]);
1293 if (i == emr->nSize - 1)
1295 else if (i % 8 == 7)
1303 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1305 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1306 eto->rclBounds.right, eto->rclBounds.bottom);
1307 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1308 trace("exScale: %f\n", eto->exScale);
1309 trace("eyScale: %f\n", eto->eyScale);
1310 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1311 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1312 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1313 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1314 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1315 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1316 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1319 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1320 const char *desc, BOOL ignore_scaling)
1324 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1325 desc, emr1->iType, emr2->iType);
1327 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1328 desc, emr1->nSize, emr2->nSize);
1330 /* iType and nSize mismatches are fatal */
1331 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1333 /* contents of EMR_GDICOMMENT are not interesting */
1334 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1336 /* different Windows versions setup DC scaling differently when
1337 * converting an old style metafile to an EMF.
1339 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1340 emr1->iType == EMR_SETVIEWPORTEXTEX))
1343 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1345 EMREXTTEXTOUTW *eto1, *eto2;
1347 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1348 memcpy(eto1, emr1, emr1->nSize);
1349 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1350 memcpy(eto2, emr2, emr2->nSize);
1352 /* different Windows versions setup DC scaling differently */
1353 eto1->exScale = eto1->eyScale = 0.0;
1354 eto2->exScale = eto2->eyScale = 0.0;
1356 diff = memcmp(eto1, eto2, emr1->nSize);
1359 dump_EMREXTTEXTOUT(eto1);
1360 dump_EMREXTTEXTOUT(eto2);
1362 HeapFree(GetProcessHeap(), 0, eto1);
1363 HeapFree(GetProcessHeap(), 0, eto2);
1365 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1367 /* We have to take care of NT4 differences here */
1368 diff = memcmp(emr1, emr2, emr1->nSize);
1371 ENHMETARECORD *emr_nt4;
1373 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1374 memcpy(emr_nt4, emr2, emr2->nSize);
1375 /* Correct the nRgnSize field */
1376 emr_nt4->dParm[5] = sizeof(RECT);
1378 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1380 win_skip("Catered for NT4 differences\n");
1382 HeapFree(GetProcessHeap(), 0, emr_nt4);
1386 diff = memcmp(emr1, emr2, emr1->nSize);
1388 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1392 dump_emf_record(emr1, "expected bits");
1393 dump_emf_record(emr2, "actual bits");
1396 return diff == 0; /* report all non-fatal record mismatches */
1399 /* Compare the EMF produced by a test function with the
1400 * expected raw EMF data in "bits".
1401 * Return value is 0 for a perfect match,
1402 * -1 if lengths aren't equal,
1403 * otherwise returns the number of non-matching bytes.
1405 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1406 UINT bsize, const char *desc,
1407 BOOL ignore_scaling)
1409 unsigned char buf[MF_BUFSIZE];
1410 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1411 const ENHMETAHEADER *emh1, *emh2;
1413 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1414 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1416 /* ENHMETAHEADER size could differ, depending on platform */
1417 diff_nt4 = sizeof(SIZEL);
1418 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1420 if (mfsize < MF_BUFSIZE)
1422 ok(mfsize == bsize ||
1423 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1424 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1425 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1428 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1429 desc, mfsize, bsize);
1431 /* basic things must match */
1432 emh1 = (const ENHMETAHEADER *)bits;
1433 emh2 = (const ENHMETAHEADER *)buf;
1434 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1435 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1436 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1437 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1439 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1440 ok(emh1->nSize == emh2->nSize ||
1441 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1442 broken(emh1->nSize - diff_9x == emh2->nSize),
1443 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1444 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1445 ok(emh1->nBytes == emh2->nBytes ||
1446 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1447 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1448 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1449 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1451 offset1 = emh1->nSize;
1452 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1453 while (offset1 < emh1->nBytes)
1455 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1456 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1458 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1459 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1461 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1463 /* We have already bailed out if iType or nSize don't match */
1464 offset1 += emr1->nSize;
1465 offset2 += emr2->nSize;
1471 /* tests blitting to an EMF */
1472 static void test_emf_BitBlt(void)
1474 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1475 HBITMAP hBitmap, hOldBitmap;
1476 HENHMETAFILE hMetafile;
1478 BITMAPINFOHEADER bmih =
1480 sizeof(BITMAPINFOHEADER),
1481 BMP_DIM,/* biWidth */
1482 BMP_DIM,/* biHeight */
1484 24, /* biBitCount */
1485 BI_RGB, /* biCompression */
1486 0, /* biXPelsPerMeter */
1487 0, /* biYPelsPerMeter */
1489 0, /* biClrImportant */
1494 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1495 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1497 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1498 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1499 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1500 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1501 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1502 DIB_RGB_COLORS, &bits, NULL, 0);
1503 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1505 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1506 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1508 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1509 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1510 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1512 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1513 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1514 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1515 ok( ret, "BitBlt(WHITENESS) failed\n" );
1517 hMetafile = CloseEnhMetaFile(hdcMetafile);
1518 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1520 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1521 "emf_BitBlt", FALSE) != 0)
1523 dump_emf_bits(hMetafile, "emf_BitBlt");
1524 dump_emf_records(hMetafile, "emf_BitBlt");
1527 SelectObject(hdcBitmap, hOldBitmap);
1528 DeleteObject(hBitmap);
1529 DeleteDC(hdcBitmap);
1530 DeleteDC(hdcDisplay);
1534 /* Test a blank metafile. May be used as a template for new tests. */
1536 static void test_mf_Blank(void)
1539 HMETAFILE hMetafile;
1544 hdcMetafile = CreateMetaFileA(NULL);
1545 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1546 trace("hdcMetafile %p\n", hdcMetafile);
1548 /* Tests on metafile initialization */
1549 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1550 ok (caps == DT_METAFILE,
1551 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1553 hMetafile = CloseMetaFile(hdcMetafile);
1554 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1555 type = GetObjectType(hMetafile);
1556 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1557 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1559 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1562 dump_mf_bits(hMetafile, "mf_Blank");
1563 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1566 ret = DeleteMetaFile(hMetafile);
1567 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1570 static void test_CopyMetaFile(void)
1573 HMETAFILE hMetafile, hmf_copy;
1575 char temp_path[MAX_PATH];
1576 char mf_name[MAX_PATH];
1579 hdcMetafile = CreateMetaFileA(NULL);
1580 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1581 trace("hdcMetafile %p\n", hdcMetafile);
1583 hMetafile = CloseMetaFile(hdcMetafile);
1584 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1585 type = GetObjectType(hMetafile);
1586 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1588 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1591 dump_mf_bits(hMetafile, "mf_Blank");
1592 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1595 GetTempPathA(MAX_PATH, temp_path);
1596 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1598 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1599 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1601 type = GetObjectType(hmf_copy);
1602 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1604 ret = DeleteMetaFile(hMetafile);
1605 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1607 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1609 dump_mf_bits(hmf_copy, "mf_Blank");
1610 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1613 ret = DeleteMetaFile(hmf_copy);
1614 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1616 DeleteFileA(mf_name);
1619 static void test_SetMetaFileBits(void)
1627 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1628 trace("hmf %p\n", hmf);
1629 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1630 type = GetObjectType(hmf);
1631 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1633 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1635 dump_mf_bits(hmf, "mf_Graphics");
1636 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1639 ret = DeleteMetaFile(hmf);
1640 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1642 /* NULL data crashes XP SP1 */
1643 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1645 /* Now with zero size */
1646 SetLastError(0xdeadbeef);
1647 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1648 trace("hmf %p\n", hmf);
1649 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1650 ok(GetLastError() == ERROR_INVALID_DATA ||
1651 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1652 "wrong error %d\n", GetLastError());
1654 /* Now with odd size */
1655 SetLastError(0xdeadbeef);
1656 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1657 trace("hmf %p\n", hmf);
1658 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1659 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1661 /* Now with zeroed out header fields */
1662 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1663 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1664 mh = (METAHEADER *)buf;
1665 /* corruption of any of the below fields leads to a failure */
1668 mh->mtHeaderSize = 0;
1669 SetLastError(0xdeadbeef);
1670 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1671 trace("hmf %p\n", hmf);
1672 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1673 ok(GetLastError() == ERROR_INVALID_DATA ||
1674 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1675 "wrong error %d\n", GetLastError());
1677 /* Now with corrupted mtSize field */
1678 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1679 mh = (METAHEADER *)buf;
1680 /* corruption of mtSize doesn't lead to a failure */
1682 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1683 trace("hmf %p\n", hmf);
1684 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1686 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1688 dump_mf_bits(hmf, "mf_Graphics");
1689 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1692 ret = DeleteMetaFile(hmf);
1693 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1695 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
1696 /* Now with zeroed out mtSize field */
1697 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1698 mh = (METAHEADER *)buf;
1699 /* zeroing mtSize doesn't lead to a failure */
1701 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1702 trace("hmf %p\n", hmf);
1703 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1705 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1707 dump_mf_bits(hmf, "mf_Graphics");
1708 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1711 ret = DeleteMetaFile(hmf);
1712 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1716 /* Simple APIs from mfdrv/graphics.c
1719 static void test_mf_Graphics(void)
1722 HMETAFILE hMetafile;
1726 hdcMetafile = CreateMetaFileA(NULL);
1727 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1728 trace("hdcMetafile %p\n", hdcMetafile);
1730 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1731 ok( ret, "MoveToEx error %d.\n", GetLastError());
1732 ret = LineTo(hdcMetafile, 2, 2);
1733 ok( ret, "LineTo error %d.\n", GetLastError());
1734 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1735 ok( ret, "MoveToEx error %d.\n", GetLastError());
1737 /* oldpoint gets garbage under Win XP, so the following test would
1738 * work under Wine but fails under Windows:
1740 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1741 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1742 * oldpoint.x, oldpoint.y);
1745 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1746 ok( ret, "Ellipse error %d.\n", GetLastError());
1748 hMetafile = CloseMetaFile(hdcMetafile);
1749 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1750 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1752 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1753 "mf_Graphics") != 0)
1755 dump_mf_bits(hMetafile, "mf_Graphics");
1756 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1759 ret = DeleteMetaFile(hMetafile);
1760 ok( ret, "DeleteMetaFile(%p) error %d\n",
1761 hMetafile, GetLastError());
1764 static void test_mf_PatternBrush(void)
1767 HMETAFILE hMetafile;
1772 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1774 orig_lb->lbStyle = BS_PATTERN;
1775 orig_lb->lbColor = RGB(0, 0, 0);
1776 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1777 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1779 hBrush = CreateBrushIndirect (orig_lb);
1780 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1782 hdcMetafile = CreateMetaFileA(NULL);
1783 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1784 trace("hdcMetafile %p\n", hdcMetafile);
1786 hBrush = SelectObject(hdcMetafile, hBrush);
1787 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1789 hMetafile = CloseMetaFile(hdcMetafile);
1790 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1791 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1793 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1794 "mf_Pattern_Brush") != 0)
1796 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1797 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1800 ret = DeleteMetaFile(hMetafile);
1801 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1802 ret = DeleteObject(hBrush);
1803 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1804 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1805 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1807 HeapFree (GetProcessHeap(), 0, orig_lb);
1810 static void test_mf_ExtTextOut_on_path(void)
1813 HMETAFILE hMetafile;
1815 static const INT dx[4] = { 3, 5, 8, 12 };
1817 hdcMetafile = CreateMetaFileA(NULL);
1818 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1819 trace("hdcMetafile %p\n", hdcMetafile);
1821 ret = BeginPath(hdcMetafile);
1822 ok(!ret, "BeginPath on metafile DC should fail\n");
1824 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1825 ok(ret, "ExtTextOut error %d\n", GetLastError());
1827 ret = EndPath(hdcMetafile);
1828 ok(!ret, "EndPath on metafile DC should fail\n");
1830 hMetafile = CloseMetaFile(hdcMetafile);
1831 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1833 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1834 "mf_TextOut_on_path") != 0)
1836 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1837 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1840 ret = DeleteMetaFile(hMetafile);
1841 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1844 static void test_emf_ExtTextOut_on_path(void)
1847 HDC hdcDisplay, hdcMetafile;
1848 HENHMETAFILE hMetafile;
1850 static const INT dx[4] = { 3, 5, 8, 12 };
1852 /* Win9x doesn't play EMFs on invisible windows */
1853 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1854 0, 0, 200, 200, 0, 0, 0, NULL);
1855 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1857 hdcDisplay = GetDC(hwnd);
1858 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1860 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1861 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1863 ret = BeginPath(hdcMetafile);
1864 ok(ret, "BeginPath error %d\n", GetLastError());
1866 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1867 ok(ret, "ExtTextOut error %d\n", GetLastError());
1869 ret = EndPath(hdcMetafile);
1870 ok(ret, "EndPath error %d\n", GetLastError());
1872 hMetafile = CloseEnhMetaFile(hdcMetafile);
1873 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1875 /* this doesn't succeed yet: EMF has correct size, all EMF records
1876 * are there, but their contents don't match for different reasons.
1878 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1879 "emf_TextOut_on_path", FALSE) != 0)
1881 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1882 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1885 ret = DeleteEnhMetaFile(hMetafile);
1886 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1887 ret = ReleaseDC(hwnd, hdcDisplay);
1888 ok(ret, "ReleaseDC error %d\n", GetLastError());
1889 DestroyWindow(hwnd);
1892 static const unsigned char EMF_CLIPPING[] =
1894 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1896 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1898 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1899 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1900 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1901 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1902 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1903 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1904 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1906 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1907 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1908 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1909 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1910 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1911 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1912 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1913 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1914 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1915 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1916 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1917 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1918 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1919 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1922 static void translate( POINT *pt, UINT count, const XFORM *xform )
1926 FLOAT x = (FLOAT)pt->x;
1927 FLOAT y = (FLOAT)pt->y;
1928 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1929 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1934 /* Compare rectangles allowing rounding errors */
1935 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1937 return abs(rc1->left - rc2->left) <= 1 &&
1938 abs(rc1->top - rc2->top) <= 1 &&
1939 abs(rc1->right - rc2->right) <= 1 &&
1940 abs(rc1->bottom - rc2->bottom) <= 1;
1943 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1944 const ENHMETARECORD *emr, int n_objs, LPARAM param)
1946 if (emr->iType == EMR_EXTSELECTCLIPRGN)
1948 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1952 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1954 const union _rgn *rgn1;
1956 RECT rect, rc_transformed;
1957 const RECT *rc = (const RECT *)param;
1963 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1964 clip->cbRgnData, clip->iMode);
1966 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1967 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1968 "too small data block: %u bytes\n", clip->cbRgnData);
1969 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1972 rgn1 = (const union _rgn *)clip->RgnData;
1974 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1975 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1976 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1977 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1978 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1980 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1982 rect = *(const RECT *)rgn1->data.Buffer;
1983 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1984 ok(EqualRect(&rect, rc), "rects don't match\n");
1986 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1987 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1988 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1989 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
1990 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
1991 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1993 hrgn = CreateRectRgn(0, 0, 0, 0);
1995 memset(&xform, 0, sizeof(xform));
1996 SetLastError(0xdeadbeef);
1997 ret = GetWorldTransform(hdc, &xform);
1998 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2000 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2002 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2004 ret = GetClipRgn(hdc, hrgn);
2005 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2007 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2009 ret = GetClipRgn(hdc, hrgn);
2010 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2012 /* Win9x returns empty clipping region */
2013 if (is_win9x) return 1;
2015 ret = GetRegionData(hrgn, 0, NULL);
2016 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2018 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2019 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2021 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2022 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2023 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2024 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2025 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2027 rect = rgn2.data.rdh.rcBound;
2028 rc_transformed = *rc;
2029 translate((POINT *)&rc_transformed, 2, &xform);
2030 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2031 rc_transformed.right, rc_transformed.bottom);
2032 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2034 rect = *(const RECT *)rgn2.data.Buffer;
2035 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2036 rc_transformed = *rc;
2037 translate((POINT *)&rc_transformed, 2, &xform);
2038 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2039 rc_transformed.right, rc_transformed.bottom);
2040 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2042 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2043 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2044 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2045 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2046 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2047 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2054 static void test_emf_clipping(void)
2056 static const RECT rc = { 0, 0, 100, 100 };
2057 RECT rc_clip = { 100, 100, 1024, 1024 };
2063 RECT rc_res, rc_sclip;
2065 SetLastError(0xdeadbeef);
2066 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2067 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2069 /* Need to write something to the emf, otherwise Windows won't play it back */
2072 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2073 ret = SelectClipRgn(hdc, hrgn);
2074 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2076 SetLastError(0xdeadbeef);
2077 hemf = CloseEnhMetaFile(hdc);
2078 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2080 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2081 "emf_clipping", FALSE) != 0)
2083 dump_emf_bits(hemf, "emf_clipping");
2084 dump_emf_records(hemf, "emf_clipping");
2089 /* Win9x doesn't play EMFs on invisible windows */
2090 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2091 0, 0, 200, 200, 0, 0, 0, NULL);
2092 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2096 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2097 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2099 DeleteEnhMetaFile(hemf);
2100 ReleaseDC(hwnd, hdc);
2101 DestroyWindow(hwnd);
2103 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2105 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2106 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2107 SelectClipRgn(hdc, hrgn);
2108 ret = GetClipBox(hdc, &rc_res);
2110 ok(ret == SIMPLEREGION, "got %d\n", ret);
2111 if(ret == SIMPLEREGION)
2112 ok(EqualRect(&rc_res, &rc_sclip),
2113 "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2114 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2115 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2117 hemf = CloseEnhMetaFile(hdc);
2118 DeleteEnhMetaFile(hemf);
2123 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2125 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2126 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2127 /* When using MM_TEXT Win9x does not update the mapping mode
2128 * until a record is played which actually outputs something */
2129 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2130 LPtoDP(hdc, mapping, 2);
2131 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2132 lpEMFR->iType, lpEMFR->nSize,
2133 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2135 if (lpEMFR->iType == EMR_LINETO)
2138 if (!lpMFP || lpMFP->mm == MM_TEXT)
2142 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2143 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2147 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2149 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2150 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2151 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2152 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2154 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2155 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2156 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2162 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2171 hdcMf = CreateMetaFile(NULL);
2172 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2173 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2174 ok(ret, "LineTo failed with error %d\n", GetLastError());
2175 hmf = CloseMetaFile(hdcMf);
2176 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2178 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2180 dump_mf_bits(hmf, "mf_LineTo");
2181 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2184 size = GetMetaFileBitsEx(hmf, 0, NULL);
2185 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2186 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2187 GetMetaFileBitsEx(hmf, size, pBits);
2188 DeleteMetaFile(hmf);
2189 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2190 HeapFree(GetProcessHeap(), 0, pBits);
2194 static void test_mf_conversions(void)
2196 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2198 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2201 RECT rect = { 0, 0, 100, 100 };
2202 mfp.mm = MM_ANISOTROPIC;
2206 hemf = create_converted_emf(&mfp);
2208 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2209 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2211 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2212 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2215 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2217 DeleteEnhMetaFile(hemf);
2218 DeleteDC(hdcOffscreen);
2221 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2223 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2226 RECT rect = { 0, 0, 100, 100 };
2231 hemf = create_converted_emf(&mfp);
2233 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2234 "emf_LineTo MM_TEXT", TRUE) != 0)
2236 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2237 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2240 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2242 DeleteEnhMetaFile(hemf);
2243 DeleteDC(hdcOffscreen);
2246 trace("Testing MF->EMF conversion (NULL mfp)\n");
2248 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2250 RECT rect = { 0, 0, 100, 100 };
2251 hemf = create_converted_emf(NULL);
2253 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2254 "emf_LineTo NULL", TRUE) != 0)
2256 dump_emf_bits(hemf, "emf_LineTo NULL");
2257 dump_emf_records(hemf, "emf_LineTo NULL");
2260 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2262 DeleteEnhMetaFile(hemf);
2263 DeleteDC(hdcOffscreen);
2267 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2268 LONG mm, LONG xExt, LONG yExt,
2269 RECTL * rclBounds, RECTL * rclFrame)
2272 METAFILEPICT * mfpPtr = NULL;
2274 ENHMETAHEADER header;
2285 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2286 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2287 if (!emf) return FALSE;
2288 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2289 ok(res != 0, "GetEnhMetaHeader failed\n");
2290 DeleteEnhMetaFile(emf);
2291 if (!res) return FALSE;
2293 *rclBounds = header.rclBounds;
2294 *rclFrame = header.rclFrame;
2298 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2299 LONG mm, LONG xExt, LONG yExt,
2300 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2302 RECTL rclBounds, rclFrame;
2304 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2311 msg = "mfp == NULL";
2315 const char * mm_str;
2318 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2319 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2320 default: mm_str = "Unexpected";
2322 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2326 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2327 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2328 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2329 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2330 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2331 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2332 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2333 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2337 static void test_SetWinMetaFileBits(void)
2345 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2346 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2347 RECTL rclBounds, rclFrame;
2351 wmfDC = CreateMetaFile(NULL);
2352 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2355 SetWindowExtEx(wmfDC, 100, 100, NULL);
2356 rect.left = rect.top = 0;
2357 rect.right = rect.bottom = 50;
2358 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2359 wmf = CloseMetaFile(wmfDC);
2360 ok(wmf != NULL, "Metafile creation failed\n");
2363 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2364 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2365 if (buffer_size == 0)
2367 DeleteMetaFile(wmf);
2371 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2372 ok(buffer != NULL, "HeapAlloc failed\n");
2375 DeleteMetaFile(wmf);
2379 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2380 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2381 DeleteMetaFile(wmf);
2382 if (res != buffer_size)
2384 HeapFree(GetProcessHeap(), 0, buffer);
2388 /* Get the reference bounds and frame */
2389 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2390 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2392 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2393 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2394 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2396 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2397 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2398 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2399 if (diffx < 0) diffx = -diffx;
2400 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2402 dc = CreateCompatibleDC(NULL);
2404 /* Allow 1 mm difference (rounding errors) */
2405 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2406 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2407 if (diffx < 0) diffx = -diffx;
2408 if (diffy < 0) diffy = -diffy;
2411 ok(diffx <= 1 && diffy <= 1,
2412 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2413 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2416 /* Allow 1 mm difference (rounding errors) */
2417 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2418 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2419 if (diffx < 0) diffx = -diffx;
2420 if (diffy < 0) diffy = -diffy;
2423 ok(diffx <= 1 && diffy <= 1,
2424 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2425 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2429 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2430 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2432 /* If xExt or yExt is zero or negative, the whole device surface is used */
2433 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2434 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2435 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2436 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2437 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2438 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2439 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2440 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2441 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2442 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2443 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2444 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2446 /* MSDN says that negative xExt and yExt values specify a ratio.
2447 Check that this is wrong and the whole device surface is used */
2448 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2449 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2451 /* Ordinary conversions */
2453 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2455 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2456 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2457 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2458 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2461 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2463 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2464 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2465 ok(rclBounds.left == 0 && rclBounds.top == 0,
2466 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2468 /* Wine has a rounding error */
2469 diffx = rclBounds.right - rclBounds.bottom;
2470 if (diffx < 0) diffx = -diffx;
2471 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2474 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2476 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2477 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2480 HeapFree(GetProcessHeap(), 0, buffer);
2483 static BOOL near_match(int x, int y)
2485 int epsilon = min(abs(x), abs(y));
2487 epsilon = max(epsilon/100, 2);
2489 if(x < y - epsilon || x > y + epsilon) return FALSE;
2493 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2496 HDC display_dc, emf_dc;
2497 ENHMETAHEADER *enh_header;
2498 UINT size, emf_size, i;
2501 METAHEADER *mh = NULL;
2503 INT horz_res, vert_res, horz_size, vert_size;
2505 display_dc = GetDC(NULL);
2506 ok(display_dc != NULL, "display_dc is NULL\n");
2508 horz_res = GetDeviceCaps(display_dc, HORZRES);
2509 vert_res = GetDeviceCaps(display_dc, VERTRES);
2510 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2511 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2513 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2514 ok(emf_dc != NULL, "emf_dc is NULL\n");
2515 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2516 Rectangle(emf_dc, 0, 0, 1000, 20);
2517 emf = CloseEnhMetaFile(emf_dc);
2518 ok(emf != NULL, "emf is NULL\n");
2520 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2521 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2522 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2523 DeleteEnhMetaFile(emf);
2524 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2525 have different resolutions */
2526 enh_header->szlDevice.cx *= scale;
2527 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2528 ok(emf != NULL, "emf is NULL\n");
2529 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2531 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2533 broken(size == 0), /* some versions of winxp fail for some reason */
2534 "GetWinMetaFileBits returns 0\n");
2536 mh = HeapAlloc(GetProcessHeap(), 0, size);
2537 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2539 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2540 ok(check == 0, "check %04x\n", check);
2542 rec = (METARECORD*)(mh + 1);
2544 while(rec->rdSize && rec->rdFunction)
2546 const DWORD chunk_size = 0x2000;
2547 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2549 if(rec_num < mfcomment_chunks)
2551 DWORD this_chunk_size = chunk_size;
2553 if(rec_num == mfcomment_chunks - 1)
2554 this_chunk_size = emf_size - rec_num * chunk_size;
2556 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2557 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2558 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2559 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2560 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2561 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2562 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
2563 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2564 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2565 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2566 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2567 /* parm[8] is the checksum, tested above */
2568 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2569 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2570 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2571 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2572 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2573 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2574 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2575 ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15)); /* DWORD size remaining after current chunk */
2576 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2577 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2580 else if(rec_num == mfcomment_chunks)
2582 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2583 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2585 else if(rec_num == mfcomment_chunks + 1)
2588 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2593 case MM_ANISOTROPIC:
2594 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2595 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2598 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2599 pt.x = MulDiv( rc->left, 1, 10);
2602 pt.y = -rc->top + 1;
2603 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2606 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2607 pt.x = MulDiv( rc->left, 10, 254);
2610 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2611 pt.x = MulDiv( rc->left, 100, 254);
2614 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2615 pt.x = MulDiv( rc->left, 72 * 20, 2540);
2620 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2621 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2623 if(rec_num == mfcomment_chunks + 2)
2625 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2626 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
2627 "got %d\n", (short)rec->rdParm[0]);
2628 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
2629 "got %d\n", (short)rec->rdParm[1]);
2633 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2637 HeapFree(GetProcessHeap(), 0, mh);
2638 HeapFree(GetProcessHeap(), 0, enh_header);
2639 DeleteEnhMetaFile(emf);
2641 ReleaseDC(NULL, display_dc);
2644 static void test_GetWinMetaFileBits(void)
2649 { 1000, 2000, 3000, 6000},
2650 {-1000, 2000, 3000, 6000},
2651 { 1000, -2000, 3000, 6000},
2652 { 1005, 2005, 3000, 6000},
2653 {-1005, -2005, 3000, 6000},
2654 {-1005, -2010, 3000, 6000},
2655 {-1005, 2010, 3000, 6000},
2661 for(mode = MM_MIN; mode <= MM_MAX; mode++)
2664 trace("mode %d\n", mode);
2666 for(rc = frames; rc->right - rc->left > 0; rc++)
2668 trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
2669 getwinmetafilebits(mode, 1, rc);
2670 getwinmetafilebits(mode, 2, rc);
2675 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2676 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2677 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2679 static void test_gdiis(void)
2681 RECT rect = {0,0,100,100};
2682 HDC hdc, hemfDC, hmfDC;
2686 /* resolve all the functions */
2687 hgdi32 = GetModuleHandle("gdi32");
2688 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2689 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2690 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2692 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2694 win_skip("Needed GdiIs* functions are not available\n");
2698 /* try with nothing */
2699 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2700 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2701 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2703 /* try with a metafile */
2704 hmfDC = CreateMetaFile(NULL);
2705 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2706 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2707 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2708 DeleteMetaFile(CloseMetaFile(hmfDC));
2710 /* try with an enhanced metafile */
2712 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2713 ok(hemfDC != NULL, "failed to create emf\n");
2715 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2716 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2717 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2719 hemf = CloseEnhMetaFile(hemfDC);
2720 ok(hemf != NULL, "failed to close EMF\n");
2721 DeleteEnhMetaFile(hemf);
2722 ReleaseDC(NULL,hdc);
2725 static void test_SetEnhMetaFileBits(void)
2731 memset(data, 0xAA, sizeof(data));
2732 SetLastError(0xdeadbeef);
2733 hemf = SetEnhMetaFileBits(sizeof(data), data);
2734 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2735 ok(GetLastError() == ERROR_INVALID_DATA ||
2736 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2737 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2739 emh = (ENHMETAHEADER *)data;
2740 memset(emh, 0, sizeof(*emh));
2742 emh->iType = EMR_HEADER;
2743 emh->nSize = sizeof(*emh);
2744 emh->dSignature = ENHMETA_SIGNATURE;
2745 /* emh->nVersion = 0x10000; XP doesn't care about version */
2746 emh->nBytes = sizeof(*emh);
2747 /* emh->nRecords = 1; XP doesn't care about records */
2748 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2750 SetLastError(0xdeadbeef);
2751 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2752 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2753 DeleteEnhMetaFile(hemf);
2755 /* XP refuses to load unaligned EMF */
2757 SetLastError(0xdeadbeef);
2758 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2760 broken(hemf != NULL), /* Win9x, WinMe */
2761 "SetEnhMetaFileBits should fail\n");
2762 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2763 DeleteEnhMetaFile(hemf);
2765 emh->dSignature = 0;
2767 SetLastError(0xdeadbeef);
2768 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2770 broken(hemf != NULL), /* Win9x, WinMe */
2771 "SetEnhMetaFileBits should fail\n");
2772 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2773 DeleteEnhMetaFile(hemf);
2776 START_TEST(metafile)
2778 init_function_pointers();
2780 /* For enhanced metafiles (enhmfdrv) */
2785 /* For win-format metafiles (mfdrv) */
2789 test_mf_PatternBrush();
2790 test_CopyMetaFile();
2791 test_SetMetaFileBits();
2792 test_mf_ExtTextOut_on_path();
2793 test_emf_ExtTextOut_on_path();
2794 test_emf_clipping();
2796 /* For metafile conversions */
2797 test_mf_conversions();
2798 test_SetWinMetaFileBits();
2799 test_GetWinMetaFileBits();
2802 test_SetEnhMetaFileBits();