wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / gdi32 / tests / metafile.c
blob9ccb9ced6649ed118270a7452b2373bb2918ecfa
1 /*
2 * Unit tests for metafile functions
4 * Copyright (c) 2002 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
41 #define GDI_GET_PROC(func) \
42 p ## func = (void *)GetProcAddress(hGDI, #func); \
43 if(!p ## func) \
44 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
46 static void init_function_pointers(void)
48 HMODULE hGDI;
50 pGetRelAbs = NULL;
51 pSetRelAbs = NULL;
53 hGDI = GetModuleHandleA("gdi32.dll");
54 assert(hGDI);
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)
62 static int n_record;
63 DWORD i;
64 const INT *dx;
65 INT *orig_dx = (INT *)param;
66 LOGFONTA device_lf;
67 INT ret;
69 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70 hdc, emr->iType, emr->nSize, (void *)param);
72 if(!hdc) return 1;
74 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
76 switch (emr->iType)
78 case EMR_HEADER:
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));
92 n_record = 0;
93 break;
95 case EMR_EXTTEXTOUTA:
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]);
114 n_record++;
115 emr_processed = TRUE;
116 break;
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]);
141 n_record++;
142 emr_processed = TRUE;
143 break;
146 default:
147 break;
150 return 1;
153 static void test_ExtTextOut(void)
155 HWND hwnd;
156 HDC hdcDisplay, hdcMetafile;
157 HENHMETAFILE hMetafile;
158 HFONT hFont;
159 static const char text[] = "Simple text to test ExtTextOut on metafiles";
160 INT i, len, dx[256];
161 static const RECT rc = { 0, 0, 100, 100 };
162 BOOL ret;
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());
264 DestroyWindow(hwnd);
267 struct eto_scale_test_record
269 INT graphics_mode;
270 INT map_mode;
271 double ex_scale;
272 double ey_scale;
273 BOOL processed;
276 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
277 const ENHMETARECORD *emr, int n_objs, LPARAM param)
279 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
281 if (emr->iType == EMR_EXTTEXTOUTW)
283 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
284 trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
285 test->graphics_mode, test->map_mode,
286 pExtTextOutW->exScale, pExtTextOutW->eyScale,
287 test->ex_scale, test->ey_scale);
288 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
289 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
290 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
291 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
292 test->processed = TRUE;
295 return 1;
298 static void test_ExtTextOutScale(void)
300 const RECT rc = { 0, 0, 100, 100 };
301 const WCHAR str[] = {'a',0 };
302 struct eto_scale_test_record test;
303 HDC hdcDisplay, hdcMetafile;
304 HENHMETAFILE hMetafile;
305 HWND hwnd;
306 SIZE wndext, vportext;
307 int horzSize, vertSize, horzRes, vertRes;
308 int ret;
309 int i;
311 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
312 0, 0, 200, 200, 0, 0, 0, NULL);
313 ok(hwnd != 0, "CreateWindowExA failed\n");
315 hdcDisplay = GetDC(hwnd);
316 ok(hdcDisplay != 0, "GetDC failed\n");
318 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
319 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
320 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
321 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
322 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
324 for (i = 0; i < 16; i++)
326 test.graphics_mode = i / 8 + 1;
327 test.map_mode = i % 8 + 1;
329 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
330 ok(ret, "SetGraphicsMode failed\n");
331 ret = SetMapMode(hdcDisplay, test.map_mode);
332 ok(ret, "SetMapMode failed\n");
334 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
336 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
337 ok(ret, "SetWindowExtEx failed\n");
338 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
339 ok(ret, "SetViewportExtEx failed\n");
342 ret = GetViewportExtEx(hdcDisplay, &vportext);
343 ok(ret, "GetViewportExtEx failed\n");
344 ret = GetWindowExtEx(hdcDisplay, &wndext);
345 ok(ret, "GetWindowExtEx failed\n");
347 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
348 test.graphics_mode, test.map_mode,
349 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
350 horzSize, horzRes, vertSize, vertRes);
352 if (test.graphics_mode == GM_COMPATIBLE)
354 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
355 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
356 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
357 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
359 else
361 test.ex_scale = 0.0;
362 test.ey_scale = 0.0;
365 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
366 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
368 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
369 ok(ret, "SetGraphicsMode failed\n");
370 ret = SetMapMode(hdcMetafile, test.map_mode);
371 ok(ret, "SetMapMode failed\n");
373 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
375 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
376 ok(ret, "SetWindowExtEx failed\n");
377 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
378 ok(ret, "SetViewportExtEx failed\n");
381 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
382 ok(ret, "ExtTextOutW failed\n");
384 hMetafile = CloseEnhMetaFile(hdcMetafile);
385 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
387 test.processed = 0;
388 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
389 ok(ret, "EnumEnhMetaFile failed\n");
390 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
392 ret = DeleteEnhMetaFile(hMetafile);
393 ok(ret, "DeleteEnhMetaFile failed\n");
396 ret = ReleaseDC(hwnd, hdcDisplay);
397 ok(ret, "ReleaseDC failed\n");
398 DestroyWindow(hwnd);
402 static void check_dc_state(HDC hdc, int restore_no,
403 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
404 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
406 BOOL ret;
407 XFORM xform;
408 POINT vp_org, win_org;
409 SIZE vp_size, win_size;
410 FLOAT xscale, yscale, edx, edy;
412 SetLastError(0xdeadbeef);
413 ret = GetWorldTransform(hdc, &xform);
414 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
415 ok(ret, "GetWorldTransform error %u\n", GetLastError());
417 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
419 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
420 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
422 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
423 trace("x scale %f\n", xscale);
424 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
425 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
427 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
428 trace("y scale %f\n", yscale);
429 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
430 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
432 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
433 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
434 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
435 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
437 return;
439 win9x_here:
441 GetWindowOrgEx(hdc, &win_org);
442 GetViewportOrgEx(hdc, &vp_org);
443 GetWindowExtEx(hdc, &win_size);
444 GetViewportExtEx(hdc, &vp_size);
446 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
447 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
449 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
450 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
452 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
453 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
455 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
456 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
459 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
460 const ENHMETARECORD *emr, int n_objs, LPARAM param)
462 BOOL ret;
463 XFORM xform;
464 POINT pt;
465 SIZE size;
466 static int save_state;
467 static int restore_no;
468 static int select_no;
470 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
471 hdc, emr->iType, emr->nSize, (void *)param);
473 trace("BEFORE:\n");
474 SetLastError(0xdeadbeef);
475 ret = GetWorldTransform(hdc, &xform);
476 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
478 ret = GetWindowOrgEx(hdc, &pt);
479 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
480 trace("window org (%d,%d)\n", pt.x, pt.y);
481 ret = GetViewportOrgEx(hdc, &pt);
482 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
483 trace("vport org (%d,%d)\n", pt.x, pt.y);
484 ret = GetWindowExtEx(hdc, &size);
485 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
486 trace("window ext (%d,%d)\n", size.cx, size.cy);
487 ret = GetViewportExtEx(hdc, &size);
488 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
489 trace("vport ext (%d,%d)\n", size.cx, size.cy);
491 else
493 ok(ret, "GetWorldTransform error %u\n", GetLastError());
494 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
497 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
499 switch (emr->iType)
501 case EMR_HEADER:
503 static RECT exp_bounds = { 0, 0, 150, 150 };
504 RECT bounds;
505 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
507 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
508 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
509 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
510 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
511 emf->szlDevice.cx, emf->szlDevice.cy);
513 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
514 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
516 save_state = 0;
517 restore_no = 0;
518 select_no = 0;
519 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
520 break;
523 case EMR_LINETO:
525 const EMRLINETO *line = (const EMRLINETO *)emr;
526 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
527 break;
529 case EMR_SETWINDOWORGEX:
531 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
532 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
533 break;
535 case EMR_SETWINDOWEXTEX:
537 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
538 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
539 break;
541 case EMR_SETVIEWPORTORGEX:
543 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
544 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
545 break;
547 case EMR_SETVIEWPORTEXTEX:
549 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
550 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
551 break;
553 case EMR_SAVEDC:
554 save_state++;
555 trace("EMR_SAVEDC\n");
556 break;
558 case EMR_RESTOREDC:
560 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
561 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
563 switch(++restore_no)
565 case 1:
566 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
567 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
568 break;
569 case 2:
570 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
571 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
572 break;
573 case 3:
574 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
575 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
576 break;
578 ok(restore_no <= 3, "restore_no %d\n", restore_no);
579 save_state += restoredc->iRelative;
580 break;
582 case EMR_SELECTOBJECT:
584 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
585 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
586 select_no ++;
587 break;
589 case EMR_EOF:
590 ok(save_state == 0, "EOF save_state %d\n", save_state);
591 ok(select_no == 3, "Too many/few selects %i\n",select_no);
592 break;
595 trace("AFTER:\n");
596 SetLastError(0xdeadbeef);
597 ret = GetWorldTransform(hdc, &xform);
598 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
600 ret = GetWindowOrgEx(hdc, &pt);
601 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
602 trace("window org (%d,%d)\n", pt.x, pt.y);
603 ret = GetViewportOrgEx(hdc, &pt);
604 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
605 trace("vport org (%d,%d)\n", pt.x, pt.y);
606 ret = GetWindowExtEx(hdc, &size);
607 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
608 trace("window ext (%d,%d)\n", size.cx, size.cy);
609 ret = GetViewportExtEx(hdc, &size);
610 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
611 trace("vport ext (%d,%d)\n", size.cx, size.cy);
613 else
615 ok(ret, "GetWorldTransform error %u\n", GetLastError());
616 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
619 return 1;
622 static void test_SaveDC(void)
624 HDC hdcMetafile, hdcDisplay;
625 HENHMETAFILE hMetafile;
626 HWND hwnd;
627 int ret;
628 POINT pt;
629 SIZE size;
630 HFONT hFont,hFont2,hFontOld,hFontCheck;
631 static const RECT rc = { 0, 0, 150, 150 };
633 /* Win9x doesn't play EMFs on invisible windows */
634 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
635 0, 0, 200, 200, 0, 0, 0, NULL);
636 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
638 hdcDisplay = GetDC(hwnd);
639 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
641 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
642 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
644 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
646 /* Need to write something to the emf, otherwise Windows won't play it back */
647 LineTo(hdcMetafile, 150, 150);
649 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
650 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
651 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
652 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
654 /* Force Win9x to update DC state */
655 SetPixelV(hdcMetafile, 50, 50, 0);
657 ret = GetViewportOrgEx(hdcMetafile, &pt);
658 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
659 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
660 ret = GetViewportExtEx(hdcMetafile, &size);
661 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
662 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
663 ret = SaveDC(hdcMetafile);
664 ok(ret == 1, "ret = %d\n", ret);
666 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
667 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
668 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
669 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
671 /* Force Win9x to update DC state */
672 SetPixelV(hdcMetafile, 50, 50, 0);
674 ret = GetViewportOrgEx(hdcMetafile, &pt);
675 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
676 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
677 ret = GetViewportExtEx(hdcMetafile, &size);
678 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
679 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
680 ret = SaveDC(hdcMetafile);
681 ok(ret == 2, "ret = %d\n", ret);
683 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
684 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
685 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
686 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
687 SetPolyFillMode( hdcMetafile, ALTERNATE );
688 SetBkColor( hdcMetafile, 0 );
690 /* Force Win9x to update DC state */
691 SetPixelV(hdcMetafile, 50, 50, 0);
693 ret = GetViewportOrgEx(hdcMetafile, &pt);
694 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
695 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
696 ret = GetViewportExtEx(hdcMetafile, &size);
697 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
698 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
699 ret = SaveDC(hdcMetafile);
700 ok(ret == 3, "ret = %d\n", ret);
702 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
703 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
704 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
705 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
707 SetPolyFillMode( hdcMetafile, WINDING );
708 SetBkColor( hdcMetafile, 0x123456 );
709 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
710 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
712 /* Force Win9x to update DC state */
713 SetPixelV(hdcMetafile, 50, 50, 0);
715 ret = GetViewportOrgEx(hdcMetafile, &pt);
716 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
717 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
718 ret = GetViewportExtEx(hdcMetafile, &size);
719 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
720 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
721 ret = RestoreDC(hdcMetafile, -1);
722 ok(ret, "ret = %d\n", ret);
724 ret = GetViewportOrgEx(hdcMetafile, &pt);
725 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
726 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
727 ret = GetViewportExtEx(hdcMetafile, &size);
728 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
729 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
730 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
731 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
732 ret = SaveDC(hdcMetafile);
733 ok(ret == 3, "ret = %d\n", ret);
735 ret = GetViewportOrgEx(hdcMetafile, &pt);
736 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
737 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
738 ret = GetViewportExtEx(hdcMetafile, &size);
739 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
740 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
741 ret = RestoreDC(hdcMetafile, 1);
742 ok(ret, "ret = %d\n", ret);
743 ret = GetViewportOrgEx(hdcMetafile, &pt);
744 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
745 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
746 ret = GetViewportExtEx(hdcMetafile, &size);
747 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
748 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
750 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
751 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
752 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
753 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
755 /* Force Win9x to update DC state */
756 SetPixelV(hdcMetafile, 50, 50, 0);
758 ret = GetViewportOrgEx(hdcMetafile, &pt);
759 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
760 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
761 ret = GetViewportExtEx(hdcMetafile, &size);
762 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
763 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
764 ret = SaveDC(hdcMetafile);
765 ok(ret == 1, "ret = %d\n", ret);
767 ret = GetViewportOrgEx(hdcMetafile, &pt);
768 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
769 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
770 ret = GetViewportExtEx(hdcMetafile, &size);
771 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
772 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
773 ret = SaveDC(hdcMetafile);
774 ok(ret == 2, "ret = %d\n", ret);
776 memset(&orig_lf, 0, sizeof(orig_lf));
777 orig_lf.lfCharSet = ANSI_CHARSET;
778 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
779 orig_lf.lfWeight = FW_DONTCARE;
780 orig_lf.lfHeight = 7;
781 orig_lf.lfQuality = DEFAULT_QUALITY;
782 lstrcpyA(orig_lf.lfFaceName, "Arial");
783 hFont = CreateFontIndirectA(&orig_lf);
784 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
786 hFontOld = SelectObject(hdcMetafile, hFont);
788 hFont2 = CreateFontIndirectA(&orig_lf);
789 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
790 hFontCheck = SelectObject(hdcMetafile, hFont2);
791 ok(hFontCheck == hFont, "Font not selected\n");
793 /* Force Win9x to update DC state */
794 SetPixelV(hdcMetafile, 50, 50, 0);
796 ret = RestoreDC(hdcMetafile, 1);
797 ok(ret, "ret = %d\n", ret);
798 ret = GetViewportOrgEx(hdcMetafile, &pt);
799 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
800 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
801 ret = GetViewportExtEx(hdcMetafile, &size);
802 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
803 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
805 hFontCheck = SelectObject(hdcMetafile, hFontOld);
806 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
807 "Font not reverted with DC Restore\n");
809 ret = RestoreDC(hdcMetafile, -20);
810 ok(!ret, "ret = %d\n", ret);
811 ret = RestoreDC(hdcMetafile, 20);
812 ok(!ret, "ret = %d\n", ret);
814 hMetafile = CloseEnhMetaFile(hdcMetafile);
815 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
817 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
818 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
820 ret = DeleteObject(hFont);
821 ok( ret, "DeleteObject error %d\n", GetLastError());
822 ret = DeleteObject(hFont2);
823 ok( ret, "DeleteObject error %d\n", GetLastError());
824 ret = DeleteEnhMetaFile(hMetafile);
825 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
826 ret = ReleaseDC(hwnd, hdcDisplay);
827 ok( ret, "ReleaseDC error %d\n", GetLastError());
828 DestroyWindow(hwnd);
831 static void test_mf_SaveDC(void)
833 HDC hdcMetafile;
834 HMETAFILE hMetafile;
835 int ret;
836 POINT pt;
837 SIZE size;
838 HFONT hFont,hFont2,hFontOld,hFontCheck;
840 hdcMetafile = CreateMetaFileA(NULL);
841 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
843 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
844 ok (ret, "SetMapMode should not fail\n");
846 /* Need to write something to the emf, otherwise Windows won't play it back */
847 LineTo(hdcMetafile, 150, 150);
849 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
850 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
851 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
852 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
854 /* Force Win9x to update DC state */
855 SetPixelV(hdcMetafile, 50, 50, 0);
857 ret = GetViewportOrgEx(hdcMetafile, &pt);
858 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
859 ret = GetViewportExtEx(hdcMetafile, &size);
860 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
861 ret = SaveDC(hdcMetafile);
862 ok(ret == 1, "ret = %d\n", ret);
864 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
865 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
866 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
867 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
869 /* Force Win9x to update DC state */
870 SetPixelV(hdcMetafile, 50, 50, 0);
872 ret = SaveDC(hdcMetafile);
873 ok(ret == 1, "ret = %d\n", ret);
875 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
876 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
877 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
878 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
880 /* Force Win9x to update DC state */
881 SetPixelV(hdcMetafile, 50, 50, 0);
882 SetPolyFillMode( hdcMetafile, ALTERNATE );
883 SetBkColor( hdcMetafile, 0 );
885 ret = SaveDC(hdcMetafile);
886 ok(ret == 1, "ret = %d\n", ret);
888 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
889 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
890 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
891 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
893 SetPolyFillMode( hdcMetafile, WINDING );
894 SetBkColor( hdcMetafile, 0x123456 );
895 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
896 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
898 /* Force Win9x to update DC state */
899 SetPixelV(hdcMetafile, 50, 50, 0);
901 ret = RestoreDC(hdcMetafile, -1);
902 ok(ret, "ret = %d\n", ret);
904 ret = SaveDC(hdcMetafile);
905 ok(ret == 1, "ret = %d\n", ret);
907 ret = RestoreDC(hdcMetafile, 1);
908 ok(ret, "ret = %d\n", ret);
910 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
911 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
912 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
913 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
915 /* Force Win9x to update DC state */
916 SetPixelV(hdcMetafile, 50, 50, 0);
918 ret = SaveDC(hdcMetafile);
919 ok(ret == 1, "ret = %d\n", ret);
921 ret = SaveDC(hdcMetafile);
922 ok(ret == 1, "ret = %d\n", ret);
924 memset(&orig_lf, 0, sizeof(orig_lf));
925 orig_lf.lfCharSet = ANSI_CHARSET;
926 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
927 orig_lf.lfWeight = FW_DONTCARE;
928 orig_lf.lfHeight = 7;
929 orig_lf.lfQuality = DEFAULT_QUALITY;
930 lstrcpyA(orig_lf.lfFaceName, "Arial");
931 hFont = CreateFontIndirectA(&orig_lf);
932 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
934 hFontOld = SelectObject(hdcMetafile, hFont);
936 hFont2 = CreateFontIndirectA(&orig_lf);
937 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
938 hFontCheck = SelectObject(hdcMetafile, hFont2);
939 ok(hFontCheck == hFont, "Font not selected\n");
941 /* Force Win9x to update DC state */
942 SetPixelV(hdcMetafile, 50, 50, 0);
944 ret = RestoreDC(hdcMetafile, 1);
945 ok(ret, "ret = %d\n", ret);
947 hFontCheck = SelectObject(hdcMetafile, hFontOld);
948 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
950 /* restore level is ignored */
951 ret = RestoreDC(hdcMetafile, -20);
952 ok(ret, "ret = %d\n", ret);
953 ret = RestoreDC(hdcMetafile, 20);
954 ok(ret, "ret = %d\n", ret);
955 ret = RestoreDC(hdcMetafile, 0);
956 ok(ret, "ret = %d\n", ret);
958 hMetafile = CloseMetaFile(hdcMetafile);
959 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
961 ret = DeleteMetaFile(hMetafile);
962 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
963 ret = DeleteObject(hFont);
964 ok( ret, "DeleteObject error %d\n", GetLastError());
965 ret = DeleteObject(hFont2);
966 ok( ret, "DeleteObject error %d\n", GetLastError());
970 /* Win-format metafile (mfdrv) tests */
971 /* These tests compare the generated metafiles byte-by-byte */
972 /* with the nominal results. */
974 /* Maximum size of sample metafiles in bytes. */
975 #define MF_BUFSIZE 512
977 /* 8x8 bitmap data for a pattern brush */
978 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
979 0x01, 0x00, 0x02, 0x00,
980 0x03, 0x00, 0x04, 0x00,
981 0x05, 0x00, 0x06, 0x00,
982 0x07, 0x00, 0x08, 0x00
985 /* Sample metafiles to be compared to the outputs of the
986 * test functions.
989 static const unsigned char MF_BLANK_BITS[] = {
990 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
992 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
995 static const unsigned char MF_GRAPHICS_BITS[] = {
996 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
997 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
998 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
999 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1000 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1001 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1002 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1003 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1004 0x00, 0x00, 0x00, 0x00
1007 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1008 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1009 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1011 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1012 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1013 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1018 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1019 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1020 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1021 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1022 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1023 0x00, 0x00
1026 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1028 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1030 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1031 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1032 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1033 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1034 0x00, 0x00
1037 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1039 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1040 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1044 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1045 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1046 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1048 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1049 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1051 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1052 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1053 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1054 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1056 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1057 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1058 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1059 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1062 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1063 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1064 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1065 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1066 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1067 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1068 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1069 0x14, 0x00, 0x00, 0x00
1072 static const unsigned char MF_LINETO_BITS[] = {
1073 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1075 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1076 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1077 0x00, 0x00
1080 static const unsigned char EMF_LINETO_BITS[] = {
1081 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1084 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1085 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1086 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1087 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1088 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1089 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1090 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1091 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1094 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1095 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1096 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1097 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1098 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1099 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1102 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1104 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1105 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1106 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1107 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1108 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1109 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1110 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1111 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1112 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1113 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1114 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1115 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1116 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1118 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1119 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1122 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1123 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1128 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1129 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1130 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1132 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1133 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1136 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1137 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1138 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1139 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1140 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1141 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1143 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1144 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1146 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1147 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1148 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1149 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1150 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1151 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1152 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1153 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1154 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1155 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1156 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1157 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1158 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1160 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1161 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1164 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1165 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1169 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1170 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1171 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1172 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1175 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1178 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1179 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1180 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1181 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1182 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1183 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1184 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1185 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1186 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1188 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1189 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1190 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1191 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1192 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193 0x14, 0x00, 0x00, 0x00
1196 static const unsigned char EMF_BITBLT[] =
1198 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1203 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1204 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1205 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1207 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1208 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1211 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1212 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1214 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1216 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1221 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1223 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1224 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1225 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1240 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1248 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1249 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1253 /* For debugging or dumping the raw metafiles produced by
1254 * new test functions.
1256 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1257 INT nobj, LPARAM param)
1259 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1260 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1261 return TRUE;
1264 /* For debugging or dumping the raw metafiles produced by
1265 * new test functions.
1268 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1270 BYTE buf[MF_BUFSIZE];
1271 UINT mfsize, i;
1273 if (!winetest_debug) return;
1275 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1276 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1278 printf ("MetaFile %s has bits:\n{\n ", desc);
1279 for (i=0; i<mfsize; i++)
1281 printf ("0x%02x", buf[i]);
1282 if (i == mfsize-1)
1283 printf ("\n");
1284 else if (i % 8 == 7)
1285 printf (",\n ");
1286 else
1287 printf (", ");
1289 printf ("};\n");
1292 /* Compare the metafile produced by a test function with the
1293 * expected raw metafile data in "bits".
1294 * Return value is 0 for a perfect match,
1295 * -1 if lengths aren't equal,
1296 * otherwise returns the number of non-matching bytes.
1299 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1300 const char *desc)
1302 unsigned char buf[MF_BUFSIZE];
1303 UINT mfsize, i;
1304 int diff;
1306 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1307 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1308 if (mfsize < MF_BUFSIZE)
1309 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1310 desc, mfsize, bsize);
1311 else
1312 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1313 desc, mfsize, bsize);
1314 if (mfsize != bsize)
1315 return -1;
1317 diff = 0;
1318 for (i=0; i<bsize; i++)
1320 if (buf[i] != bits[i])
1321 diff++;
1323 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1324 desc, mfsize, bsize, diff);
1326 return diff;
1329 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1331 unsigned char buf[MF_BUFSIZE];
1332 DWORD mfsize, rd_size, i;
1333 int diff;
1334 HANDLE hfile;
1335 BOOL ret;
1337 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1338 assert(hfile != INVALID_HANDLE_VALUE);
1340 mfsize = GetFileSize(hfile, NULL);
1341 assert(mfsize <= MF_BUFSIZE);
1343 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1344 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1346 CloseHandle(hfile);
1348 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1350 if (mfsize != bsize)
1351 return -1;
1353 diff = 0;
1354 for (i=0; i<bsize; i++)
1356 if (buf[i] != bits[i])
1357 diff++;
1359 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1360 desc, mfsize, bsize, diff);
1362 return diff;
1365 /* For debugging or dumping the raw EMFs produced by
1366 * new test functions.
1368 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1370 BYTE buf[MF_BUFSIZE];
1371 UINT mfsize, i;
1373 if (!winetest_debug) return;
1375 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1376 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1378 printf("EMF %s has bits:\n{\n ", desc);
1379 for (i = 0; i < mfsize; i++)
1381 printf ("0x%02x", buf[i]);
1382 if (i == mfsize-1)
1383 printf ("\n");
1384 else if (i % 8 == 7)
1385 printf (",\n ");
1386 else
1387 printf (", ");
1389 printf ("};\n");
1392 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1394 BYTE *emf;
1395 BYTE buf[MF_BUFSIZE];
1396 UINT mfsize, offset;
1398 if (!winetest_debug) return;
1400 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1401 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1403 printf("EMF %s has records:\n", desc);
1405 emf = buf;
1406 offset = 0;
1407 while(offset < mfsize)
1409 EMR *emr = (EMR *)(emf + offset);
1410 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1411 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1412 offset += emr->nSize;
1416 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1418 const BYTE *buf;
1419 DWORD i;
1421 if (!winetest_debug) return;
1423 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1424 buf = (const BYTE *)emr;
1425 for (i = 0; i < emr->nSize; i++)
1427 printf ("0x%02x", buf[i]);
1428 if (i == emr->nSize - 1)
1429 printf ("\n");
1430 else if (i % 8 == 7)
1431 printf (",\n");
1432 else
1433 printf (", ");
1435 printf ("};\n");
1438 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1440 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1441 eto->rclBounds.right, eto->rclBounds.bottom);
1442 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1443 trace("exScale: %f\n", eto->exScale);
1444 trace("eyScale: %f\n", eto->eyScale);
1445 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1446 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1447 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1448 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1449 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1450 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1451 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1454 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1455 const char *desc, BOOL ignore_scaling)
1457 int diff;
1459 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1460 desc, emr1->iType, emr2->iType);
1462 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1463 desc, emr1->nSize, emr2->nSize);
1465 /* iType and nSize mismatches are fatal */
1466 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1468 /* contents of EMR_GDICOMMENT are not interesting */
1469 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1471 /* different Windows versions setup DC scaling differently when
1472 * converting an old style metafile to an EMF.
1474 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1475 emr1->iType == EMR_SETVIEWPORTEXTEX))
1476 return TRUE;
1478 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1480 EMREXTTEXTOUTW *eto1, *eto2;
1482 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1483 memcpy(eto1, emr1, emr1->nSize);
1484 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1485 memcpy(eto2, emr2, emr2->nSize);
1487 /* different Windows versions setup DC scaling differently */
1488 eto1->exScale = eto1->eyScale = 0.0;
1489 eto2->exScale = eto2->eyScale = 0.0;
1491 diff = memcmp(eto1, eto2, emr1->nSize);
1492 if (diff)
1494 dump_EMREXTTEXTOUT(eto1);
1495 dump_EMREXTTEXTOUT(eto2);
1497 HeapFree(GetProcessHeap(), 0, eto1);
1498 HeapFree(GetProcessHeap(), 0, eto2);
1500 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1502 /* We have to take care of NT4 differences here */
1503 diff = memcmp(emr1, emr2, emr1->nSize);
1504 if (diff)
1506 ENHMETARECORD *emr_nt4;
1508 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1509 memcpy(emr_nt4, emr2, emr2->nSize);
1510 /* Correct the nRgnSize field */
1511 emr_nt4->dParm[5] = sizeof(RECT);
1513 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1514 if (!diff)
1515 win_skip("Catered for NT4 differences\n");
1517 HeapFree(GetProcessHeap(), 0, emr_nt4);
1520 else
1521 diff = memcmp(emr1, emr2, emr1->nSize);
1523 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1525 if (diff)
1527 dump_emf_record(emr1, "expected bits");
1528 dump_emf_record(emr2, "actual bits");
1531 return diff == 0; /* report all non-fatal record mismatches */
1534 /* Compare the EMF produced by a test function with the
1535 * expected raw EMF data in "bits".
1536 * Return value is 0 for a perfect match,
1537 * -1 if lengths aren't equal,
1538 * otherwise returns the number of non-matching bytes.
1540 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1541 UINT bsize, const char *desc,
1542 BOOL ignore_scaling)
1544 unsigned char buf[MF_BUFSIZE];
1545 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1546 const ENHMETAHEADER *emh1, *emh2;
1548 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1549 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1551 /* ENHMETAHEADER size could differ, depending on platform */
1552 diff_nt4 = sizeof(SIZEL);
1553 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1555 if (mfsize < MF_BUFSIZE)
1557 ok(mfsize == bsize ||
1558 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1559 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1560 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1562 else
1563 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1564 desc, mfsize, bsize);
1566 /* basic things must match */
1567 emh1 = (const ENHMETAHEADER *)bits;
1568 emh2 = (const ENHMETAHEADER *)buf;
1569 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1570 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1571 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1572 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1574 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1575 ok(emh1->nSize == emh2->nSize ||
1576 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1577 broken(emh1->nSize - diff_9x == emh2->nSize),
1578 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1579 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1580 ok(emh1->nBytes == emh2->nBytes ||
1581 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1582 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1583 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1584 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1586 offset1 = emh1->nSize;
1587 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1588 while (offset1 < emh1->nBytes)
1590 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1591 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1593 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1594 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1596 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1598 /* We have already bailed out if iType or nSize don't match */
1599 offset1 += emr1->nSize;
1600 offset2 += emr2->nSize;
1602 return 0;
1606 /* tests blitting to an EMF */
1607 static void test_emf_BitBlt(void)
1609 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1610 HBITMAP hBitmap, hOldBitmap;
1611 HENHMETAFILE hMetafile;
1612 #define BMP_DIM 4
1613 BITMAPINFOHEADER bmih =
1615 sizeof(BITMAPINFOHEADER),
1616 BMP_DIM,/* biWidth */
1617 BMP_DIM,/* biHeight */
1618 1, /* biPlanes */
1619 24, /* biBitCount */
1620 BI_RGB, /* biCompression */
1621 0, /* biXPelsPerMeter */
1622 0, /* biYPelsPerMeter */
1623 0, /* biClrUsed */
1624 0, /* biClrImportant */
1626 void *bits;
1627 BOOL ret;
1629 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1630 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1632 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1633 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1634 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1635 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1636 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1637 DIB_RGB_COLORS, &bits, NULL, 0);
1638 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1640 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1641 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1643 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1644 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1645 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1647 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1648 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1649 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1650 ok( ret, "BitBlt(WHITENESS) failed\n" );
1652 hMetafile = CloseEnhMetaFile(hdcMetafile);
1653 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1655 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1656 "emf_BitBlt", FALSE) != 0)
1658 dump_emf_bits(hMetafile, "emf_BitBlt");
1659 dump_emf_records(hMetafile, "emf_BitBlt");
1662 SelectObject(hdcBitmap, hOldBitmap);
1663 DeleteObject(hBitmap);
1664 DeleteDC(hdcBitmap);
1665 DeleteDC(hdcDisplay);
1666 #undef BMP_DIM
1669 /* Test a blank metafile. May be used as a template for new tests. */
1671 static void test_mf_Blank(void)
1673 HDC hdcMetafile;
1674 HMETAFILE hMetafile;
1675 INT caps;
1676 BOOL ret;
1677 INT type;
1679 hdcMetafile = CreateMetaFileA(NULL);
1680 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1681 trace("hdcMetafile %p\n", hdcMetafile);
1683 /* Tests on metafile initialization */
1684 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1685 ok (caps == DT_METAFILE,
1686 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1688 hMetafile = CloseMetaFile(hdcMetafile);
1689 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1690 type = GetObjectType(hMetafile);
1691 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1692 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1694 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1695 "mf_blank") != 0)
1697 dump_mf_bits(hMetafile, "mf_Blank");
1698 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1701 ret = DeleteMetaFile(hMetafile);
1702 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1705 static void test_CopyMetaFile(void)
1707 HDC hdcMetafile;
1708 HMETAFILE hMetafile, hmf_copy;
1709 BOOL ret;
1710 char temp_path[MAX_PATH];
1711 char mf_name[MAX_PATH];
1712 INT type;
1714 hdcMetafile = CreateMetaFileA(NULL);
1715 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1716 trace("hdcMetafile %p\n", hdcMetafile);
1718 hMetafile = CloseMetaFile(hdcMetafile);
1719 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1720 type = GetObjectType(hMetafile);
1721 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1723 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1724 "mf_blank") != 0)
1726 dump_mf_bits(hMetafile, "mf_Blank");
1727 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1730 GetTempPathA(MAX_PATH, temp_path);
1731 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1733 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1734 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1736 type = GetObjectType(hmf_copy);
1737 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1739 ret = DeleteMetaFile(hMetafile);
1740 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1742 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1744 dump_mf_bits(hmf_copy, "mf_Blank");
1745 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1748 ret = DeleteMetaFile(hmf_copy);
1749 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1751 DeleteFileA(mf_name);
1754 static void test_SetMetaFileBits(void)
1756 HMETAFILE hmf;
1757 INT type;
1758 BOOL ret;
1759 BYTE buf[256];
1760 METAHEADER *mh;
1762 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1763 trace("hmf %p\n", hmf);
1764 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1765 type = GetObjectType(hmf);
1766 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1768 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1770 dump_mf_bits(hmf, "mf_Graphics");
1771 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1774 ret = DeleteMetaFile(hmf);
1775 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1777 /* NULL data crashes XP SP1 */
1778 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1780 /* Now with zero size */
1781 SetLastError(0xdeadbeef);
1782 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1783 trace("hmf %p\n", hmf);
1784 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1785 ok(GetLastError() == ERROR_INVALID_DATA ||
1786 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1787 "wrong error %d\n", GetLastError());
1789 /* Now with odd size */
1790 SetLastError(0xdeadbeef);
1791 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1792 trace("hmf %p\n", hmf);
1793 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1794 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1796 /* Now with zeroed out header fields */
1797 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1798 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1799 mh = (METAHEADER *)buf;
1800 /* corruption of any of the below fields leads to a failure */
1801 mh->mtType = 0;
1802 mh->mtVersion = 0;
1803 mh->mtHeaderSize = 0;
1804 SetLastError(0xdeadbeef);
1805 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1806 trace("hmf %p\n", hmf);
1807 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1808 ok(GetLastError() == ERROR_INVALID_DATA ||
1809 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1810 "wrong error %d\n", GetLastError());
1812 /* Now with corrupted mtSize field */
1813 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1814 mh = (METAHEADER *)buf;
1815 /* corruption of mtSize doesn't lead to a failure */
1816 mh->mtSize *= 2;
1817 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1818 trace("hmf %p\n", hmf);
1819 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1821 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1823 dump_mf_bits(hmf, "mf_Graphics");
1824 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1827 ret = DeleteMetaFile(hmf);
1828 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1830 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
1831 /* Now with zeroed out mtSize field */
1832 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1833 mh = (METAHEADER *)buf;
1834 /* zeroing mtSize doesn't lead to a failure */
1835 mh->mtSize = 0;
1836 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1837 trace("hmf %p\n", hmf);
1838 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1840 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1842 dump_mf_bits(hmf, "mf_Graphics");
1843 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1846 ret = DeleteMetaFile(hmf);
1847 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1848 #endif
1851 /* Simple APIs from mfdrv/graphics.c
1854 static void test_mf_Graphics(void)
1856 HDC hdcMetafile;
1857 HMETAFILE hMetafile;
1858 POINT oldpoint;
1859 BOOL ret;
1861 hdcMetafile = CreateMetaFileA(NULL);
1862 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1863 trace("hdcMetafile %p\n", hdcMetafile);
1865 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1866 ok( ret, "MoveToEx error %d.\n", GetLastError());
1867 ret = LineTo(hdcMetafile, 2, 2);
1868 ok( ret, "LineTo error %d.\n", GetLastError());
1869 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1870 ok( ret, "MoveToEx error %d.\n", GetLastError());
1872 /* oldpoint gets garbage under Win XP, so the following test would
1873 * work under Wine but fails under Windows:
1875 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1876 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1877 * oldpoint.x, oldpoint.y);
1880 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1881 ok( ret, "Ellipse error %d.\n", GetLastError());
1883 hMetafile = CloseMetaFile(hdcMetafile);
1884 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1885 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1887 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1888 "mf_Graphics") != 0)
1890 dump_mf_bits(hMetafile, "mf_Graphics");
1891 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1894 ret = DeleteMetaFile(hMetafile);
1895 ok( ret, "DeleteMetaFile(%p) error %d\n",
1896 hMetafile, GetLastError());
1899 static void test_mf_PatternBrush(void)
1901 HDC hdcMetafile;
1902 HMETAFILE hMetafile;
1903 LOGBRUSH *orig_lb;
1904 HBRUSH hBrush;
1905 BOOL ret;
1907 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1909 orig_lb->lbStyle = BS_PATTERN;
1910 orig_lb->lbColor = RGB(0, 0, 0);
1911 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1912 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1914 hBrush = CreateBrushIndirect (orig_lb);
1915 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1917 hdcMetafile = CreateMetaFileA(NULL);
1918 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1919 trace("hdcMetafile %p\n", hdcMetafile);
1921 hBrush = SelectObject(hdcMetafile, hBrush);
1922 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1924 hMetafile = CloseMetaFile(hdcMetafile);
1925 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1926 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1928 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1929 "mf_Pattern_Brush") != 0)
1931 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1932 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1935 ret = DeleteMetaFile(hMetafile);
1936 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1937 ret = DeleteObject(hBrush);
1938 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1939 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1940 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1941 GetLastError());
1942 HeapFree (GetProcessHeap(), 0, orig_lb);
1945 static void test_mf_ExtTextOut_on_path(void)
1947 HDC hdcMetafile;
1948 HMETAFILE hMetafile;
1949 BOOL ret;
1950 static const INT dx[4] = { 3, 5, 8, 12 };
1952 hdcMetafile = CreateMetaFileA(NULL);
1953 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1954 trace("hdcMetafile %p\n", hdcMetafile);
1956 ret = BeginPath(hdcMetafile);
1957 ok(!ret, "BeginPath on metafile DC should fail\n");
1959 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1960 ok(ret, "ExtTextOut error %d\n", GetLastError());
1962 ret = EndPath(hdcMetafile);
1963 ok(!ret, "EndPath on metafile DC should fail\n");
1965 hMetafile = CloseMetaFile(hdcMetafile);
1966 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1968 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1969 "mf_TextOut_on_path") != 0)
1971 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1972 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1975 ret = DeleteMetaFile(hMetafile);
1976 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1979 static void test_emf_ExtTextOut_on_path(void)
1981 HWND hwnd;
1982 HDC hdcDisplay, hdcMetafile;
1983 HENHMETAFILE hMetafile;
1984 BOOL ret;
1985 static const INT dx[4] = { 3, 5, 8, 12 };
1987 /* Win9x doesn't play EMFs on invisible windows */
1988 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1989 0, 0, 200, 200, 0, 0, 0, NULL);
1990 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1992 hdcDisplay = GetDC(hwnd);
1993 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1995 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1996 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1998 ret = BeginPath(hdcMetafile);
1999 ok(ret, "BeginPath error %d\n", GetLastError());
2001 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2002 ok(ret, "ExtTextOut error %d\n", GetLastError());
2004 ret = EndPath(hdcMetafile);
2005 ok(ret, "EndPath error %d\n", GetLastError());
2007 hMetafile = CloseEnhMetaFile(hdcMetafile);
2008 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2010 /* this doesn't succeed yet: EMF has correct size, all EMF records
2011 * are there, but their contents don't match for different reasons.
2013 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2014 "emf_TextOut_on_path", FALSE) != 0)
2016 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2017 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2020 ret = DeleteEnhMetaFile(hMetafile);
2021 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2022 ret = ReleaseDC(hwnd, hdcDisplay);
2023 ok(ret, "ReleaseDC error %d\n", GetLastError());
2024 DestroyWindow(hwnd);
2027 static const unsigned char EMF_CLIPPING[] =
2029 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2030 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2031 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2032 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2033 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2034 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2035 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2036 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2037 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2038 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2039 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2040 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2041 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2042 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2043 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2044 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2045 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2046 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2047 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2048 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2049 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2050 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2051 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2052 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2053 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2054 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2057 static void translate( POINT *pt, UINT count, const XFORM *xform )
2059 while (count--)
2061 FLOAT x = (FLOAT)pt->x;
2062 FLOAT y = (FLOAT)pt->y;
2063 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2064 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2065 pt++;
2069 /* Compare rectangles allowing rounding errors */
2070 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2072 return abs(rc1->left - rc2->left) <= 1 &&
2073 abs(rc1->top - rc2->top) <= 1 &&
2074 abs(rc1->right - rc2->right) <= 1 &&
2075 abs(rc1->bottom - rc2->bottom) <= 1;
2078 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2079 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2081 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2083 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2084 union _rgn
2086 RGNDATA data;
2087 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2089 const union _rgn *rgn1;
2090 union _rgn rgn2;
2091 RECT rect, rc_transformed;
2092 const RECT *rc = (const RECT *)param;
2093 HRGN hrgn;
2094 XFORM xform;
2095 INT ret;
2096 BOOL is_win9x;
2098 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2099 clip->cbRgnData, clip->iMode);
2101 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2102 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2103 "too small data block: %u bytes\n", clip->cbRgnData);
2104 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2105 return 0;
2107 rgn1 = (const union _rgn *)clip->RgnData;
2109 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2110 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2111 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2112 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2113 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2115 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2117 rect = *(const RECT *)rgn1->data.Buffer;
2118 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2119 ok(EqualRect(&rect, rc), "rects don't match\n");
2121 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2122 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2123 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2124 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2125 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2126 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2128 hrgn = CreateRectRgn(0, 0, 0, 0);
2130 memset(&xform, 0, sizeof(xform));
2131 SetLastError(0xdeadbeef);
2132 ret = GetWorldTransform(hdc, &xform);
2133 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2134 if (!is_win9x)
2135 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2137 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2139 ret = GetClipRgn(hdc, hrgn);
2140 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2142 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2144 ret = GetClipRgn(hdc, hrgn);
2145 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2147 /* Win9x returns empty clipping region */
2148 if (is_win9x) return 1;
2150 ret = GetRegionData(hrgn, 0, NULL);
2151 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2153 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2154 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2156 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2157 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2158 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2159 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2160 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2162 rect = rgn2.data.rdh.rcBound;
2163 rc_transformed = *rc;
2164 translate((POINT *)&rc_transformed, 2, &xform);
2165 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2166 rc_transformed.right, rc_transformed.bottom);
2167 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2169 rect = *(const RECT *)rgn2.data.Buffer;
2170 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2171 rc_transformed = *rc;
2172 translate((POINT *)&rc_transformed, 2, &xform);
2173 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2174 rc_transformed.right, rc_transformed.bottom);
2175 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2177 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2178 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2179 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2180 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2181 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2182 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2184 DeleteObject(hrgn);
2186 return 1;
2189 static void test_emf_clipping(void)
2191 static const RECT rc = { 0, 0, 100, 100 };
2192 RECT rc_clip = { 100, 100, 1024, 1024 };
2193 HWND hwnd;
2194 HDC hdc;
2195 HENHMETAFILE hemf;
2196 HRGN hrgn;
2197 INT ret;
2198 RECT rc_res, rc_sclip;
2200 SetLastError(0xdeadbeef);
2201 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2202 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2204 /* Need to write something to the emf, otherwise Windows won't play it back */
2205 LineTo(hdc, 1, 1);
2207 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2208 ret = SelectClipRgn(hdc, hrgn);
2209 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2211 SetLastError(0xdeadbeef);
2212 hemf = CloseEnhMetaFile(hdc);
2213 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2215 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2216 "emf_clipping", FALSE) != 0)
2218 dump_emf_bits(hemf, "emf_clipping");
2219 dump_emf_records(hemf, "emf_clipping");
2222 DeleteObject(hrgn);
2224 /* Win9x doesn't play EMFs on invisible windows */
2225 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2226 0, 0, 200, 200, 0, 0, 0, NULL);
2227 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2229 hdc = GetDC(hwnd);
2231 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2232 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2234 DeleteEnhMetaFile(hemf);
2235 ReleaseDC(hwnd, hdc);
2236 DestroyWindow(hwnd);
2238 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2240 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2241 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2242 SelectClipRgn(hdc, hrgn);
2243 ret = GetClipBox(hdc, &rc_res);
2244 todo_wine
2245 ok(ret == SIMPLEREGION, "got %d\n", ret);
2246 if(ret == SIMPLEREGION)
2247 ok(EqualRect(&rc_res, &rc_sclip),
2248 "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2249 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2250 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2252 hemf = CloseEnhMetaFile(hdc);
2253 DeleteEnhMetaFile(hemf);
2254 DeleteObject(hrgn);
2255 DeleteDC(hdc);
2258 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2260 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2261 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2262 /* When using MM_TEXT Win9x does not update the mapping mode
2263 * until a record is played which actually outputs something */
2264 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2265 LPtoDP(hdc, mapping, 2);
2266 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2267 lpEMFR->iType, lpEMFR->nSize,
2268 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2270 if (lpEMFR->iType == EMR_LINETO)
2272 INT x0, y0, x1, y1;
2273 if (!lpMFP || lpMFP->mm == MM_TEXT)
2275 x0 = 0;
2276 y0 = 0;
2277 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2278 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2280 else
2282 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2284 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2285 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2286 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2287 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2289 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2290 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2291 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2292 x0, y0, x1, y1);
2294 return TRUE;
2297 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2299 HDC hdcMf;
2300 HMETAFILE hmf;
2301 HENHMETAFILE hemf;
2302 BOOL ret;
2303 UINT size;
2304 LPBYTE pBits;
2306 hdcMf = CreateMetaFile(NULL);
2307 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2308 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2309 ok(ret, "LineTo failed with error %d\n", GetLastError());
2310 hmf = CloseMetaFile(hdcMf);
2311 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2313 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2315 dump_mf_bits(hmf, "mf_LineTo");
2316 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2319 size = GetMetaFileBitsEx(hmf, 0, NULL);
2320 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2321 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2322 GetMetaFileBitsEx(hmf, size, pBits);
2323 DeleteMetaFile(hmf);
2324 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2325 HeapFree(GetProcessHeap(), 0, pBits);
2326 return hemf;
2329 static void test_mf_conversions(void)
2331 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2333 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2334 HENHMETAFILE hemf;
2335 METAFILEPICT mfp;
2336 RECT rect = { 0, 0, 100, 100 };
2337 mfp.mm = MM_ANISOTROPIC;
2338 mfp.xExt = 100;
2339 mfp.yExt = 100;
2340 mfp.hMF = NULL;
2341 hemf = create_converted_emf(&mfp);
2343 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2344 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2346 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2347 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2350 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2352 DeleteEnhMetaFile(hemf);
2353 DeleteDC(hdcOffscreen);
2356 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2358 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2359 HENHMETAFILE hemf;
2360 METAFILEPICT mfp;
2361 RECT rect = { 0, 0, 100, 100 };
2362 mfp.mm = MM_TEXT;
2363 mfp.xExt = 0;
2364 mfp.yExt = 0;
2365 mfp.hMF = NULL;
2366 hemf = create_converted_emf(&mfp);
2368 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2369 "emf_LineTo MM_TEXT", TRUE) != 0)
2371 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2372 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2375 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2377 DeleteEnhMetaFile(hemf);
2378 DeleteDC(hdcOffscreen);
2381 trace("Testing MF->EMF conversion (NULL mfp)\n");
2383 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2384 HENHMETAFILE hemf;
2385 RECT rect = { 0, 0, 100, 100 };
2386 hemf = create_converted_emf(NULL);
2388 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2389 "emf_LineTo NULL", TRUE) != 0)
2391 dump_emf_bits(hemf, "emf_LineTo NULL");
2392 dump_emf_records(hemf, "emf_LineTo NULL");
2395 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2397 DeleteEnhMetaFile(hemf);
2398 DeleteDC(hdcOffscreen);
2402 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2403 LONG mm, LONG xExt, LONG yExt,
2404 RECTL * rclBounds, RECTL * rclFrame)
2406 METAFILEPICT mfp;
2407 METAFILEPICT * mfpPtr = NULL;
2408 HENHMETAFILE emf;
2409 ENHMETAHEADER header;
2410 UINT res;
2412 if (!mfpIsNull)
2414 mfp.mm = mm;
2415 mfp.xExt = xExt;
2416 mfp.yExt = yExt;
2417 mfpPtr = &mfp;
2420 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2421 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2422 if (!emf) return FALSE;
2423 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2424 ok(res != 0, "GetEnhMetaHeader failed\n");
2425 DeleteEnhMetaFile(emf);
2426 if (!res) return FALSE;
2428 *rclBounds = header.rclBounds;
2429 *rclFrame = header.rclFrame;
2430 return TRUE;
2433 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2434 LONG mm, LONG xExt, LONG yExt,
2435 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2437 RECTL rclBounds, rclFrame;
2439 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2441 const char * msg;
2442 char buf[64];
2444 if (mfpIsNull)
2446 msg = "mfp == NULL";
2448 else
2450 const char * mm_str;
2451 switch (mm)
2453 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2454 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2455 default: mm_str = "Unexpected";
2457 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2458 msg = buf;
2461 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2462 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2463 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2464 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2465 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2466 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2467 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2468 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2472 static void test_SetWinMetaFileBits(void)
2474 HMETAFILE wmf;
2475 HDC wmfDC;
2476 BYTE * buffer;
2477 UINT buffer_size;
2478 RECT rect;
2479 UINT res;
2480 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2481 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2482 RECTL rclBounds, rclFrame;
2483 HDC dc;
2484 LONG diffx, diffy;
2486 wmfDC = CreateMetaFile(NULL);
2487 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2488 if (!wmfDC) return;
2490 SetWindowExtEx(wmfDC, 100, 100, NULL);
2491 rect.left = rect.top = 0;
2492 rect.right = rect.bottom = 50;
2493 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2494 wmf = CloseMetaFile(wmfDC);
2495 ok(wmf != NULL, "Metafile creation failed\n");
2496 if (!wmf) return;
2498 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2499 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2500 if (buffer_size == 0)
2502 DeleteMetaFile(wmf);
2503 return;
2506 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2507 ok(buffer != NULL, "HeapAlloc failed\n");
2508 if (!buffer)
2510 DeleteMetaFile(wmf);
2511 return;
2514 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2515 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2516 DeleteMetaFile(wmf);
2517 if (res != buffer_size)
2519 HeapFree(GetProcessHeap(), 0, buffer);
2520 return;
2523 /* Get the reference bounds and frame */
2524 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2525 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2527 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2528 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2529 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2531 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2532 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2533 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2534 if (diffx < 0) diffx = -diffx;
2535 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2537 dc = CreateCompatibleDC(NULL);
2539 /* Allow 1 mm difference (rounding errors) */
2540 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2541 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2542 if (diffx < 0) diffx = -diffx;
2543 if (diffy < 0) diffy = -diffy;
2544 todo_wine
2546 ok(diffx <= 1 && diffy <= 1,
2547 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2548 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2551 /* Allow 1 mm difference (rounding errors) */
2552 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2553 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2554 if (diffx < 0) diffx = -diffx;
2555 if (diffy < 0) diffy = -diffy;
2556 todo_wine
2558 ok(diffx <= 1 && diffy <= 1,
2559 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2560 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2562 DeleteDC(dc);
2564 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2565 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2567 /* If xExt or yExt is zero or negative, the whole device surface is used */
2568 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2569 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2570 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2571 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2572 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2573 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2574 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2575 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2576 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2577 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2578 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2579 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2581 /* MSDN says that negative xExt and yExt values specify a ratio.
2582 Check that this is wrong and the whole device surface is used */
2583 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2584 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2586 /* Ordinary conversions */
2588 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2590 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2591 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2592 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2593 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2596 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2598 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2599 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2600 ok(rclBounds.left == 0 && rclBounds.top == 0,
2601 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2603 /* Wine has a rounding error */
2604 diffx = rclBounds.right - rclBounds.bottom;
2605 if (diffx < 0) diffx = -diffx;
2606 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2609 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2611 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2612 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2615 HeapFree(GetProcessHeap(), 0, buffer);
2618 static BOOL near_match(int x, int y)
2620 int epsilon = min(abs(x), abs(y));
2622 epsilon = max(epsilon/100, 2);
2624 if(x < y - epsilon || x > y + epsilon) return FALSE;
2625 return TRUE;
2628 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2630 HENHMETAFILE emf;
2631 HDC display_dc, emf_dc;
2632 ENHMETAHEADER *enh_header;
2633 UINT size, emf_size, i;
2634 WORD check = 0;
2635 DWORD rec_num = 0;
2636 METAHEADER *mh = NULL;
2637 METARECORD *rec;
2638 INT horz_res, vert_res, horz_size, vert_size;
2640 display_dc = GetDC(NULL);
2641 ok(display_dc != NULL, "display_dc is NULL\n");
2643 horz_res = GetDeviceCaps(display_dc, HORZRES);
2644 vert_res = GetDeviceCaps(display_dc, VERTRES);
2645 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2646 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2648 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2649 ok(emf_dc != NULL, "emf_dc is NULL\n");
2650 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2651 Rectangle(emf_dc, 0, 0, 1000, 20);
2652 emf = CloseEnhMetaFile(emf_dc);
2653 ok(emf != NULL, "emf is NULL\n");
2655 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2656 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2657 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2658 DeleteEnhMetaFile(emf);
2659 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2660 have different resolutions */
2661 enh_header->szlDevice.cx *= scale;
2662 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2663 ok(emf != NULL, "emf is NULL\n");
2664 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2666 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2667 ok(size ||
2668 broken(size == 0), /* some versions of winxp fail for some reason */
2669 "GetWinMetaFileBits returns 0\n");
2670 if(!size) goto end;
2671 mh = HeapAlloc(GetProcessHeap(), 0, size);
2672 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2674 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2675 ok(check == 0, "check %04x\n", check);
2677 rec = (METARECORD*)(mh + 1);
2679 while(rec->rdSize && rec->rdFunction)
2681 const DWORD chunk_size = 0x2000;
2682 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2684 if(rec_num < mfcomment_chunks)
2686 DWORD this_chunk_size = chunk_size;
2688 if(rec_num == mfcomment_chunks - 1)
2689 this_chunk_size = emf_size - rec_num * chunk_size;
2691 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2692 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2693 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2694 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2695 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2696 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2697 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
2698 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2699 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2700 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2701 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2702 /* parm[8] is the checksum, tested above */
2703 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2704 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2705 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2706 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2707 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2708 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2709 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2710 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 */
2711 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2712 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2715 else if(rec_num == mfcomment_chunks)
2717 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2718 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2720 else if(rec_num == mfcomment_chunks + 1)
2722 POINT pt;
2723 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2724 switch(mode)
2726 case MM_TEXT:
2727 case MM_ISOTROPIC:
2728 case MM_ANISOTROPIC:
2729 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2730 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2731 break;
2732 case MM_LOMETRIC:
2733 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2734 pt.x = MulDiv( rc->left, 1, 10);
2735 break;
2736 case MM_HIMETRIC:
2737 pt.y = -rc->top + 1;
2738 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2739 break;
2740 case MM_LOENGLISH:
2741 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2742 pt.x = MulDiv( rc->left, 10, 254);
2743 break;
2744 case MM_HIENGLISH:
2745 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2746 pt.x = MulDiv( rc->left, 100, 254);
2747 break;
2748 case MM_TWIPS:
2749 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2750 pt.x = MulDiv( rc->left, 72 * 20, 2540);
2751 break;
2752 default:
2753 pt.x = pt.y = 0;
2755 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2756 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2758 if(rec_num == mfcomment_chunks + 2)
2760 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2761 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
2762 "got %d\n", (short)rec->rdParm[0]);
2763 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
2764 "got %d\n", (short)rec->rdParm[1]);
2767 rec_num++;
2768 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2771 end:
2772 HeapFree(GetProcessHeap(), 0, mh);
2773 HeapFree(GetProcessHeap(), 0, enh_header);
2774 DeleteEnhMetaFile(emf);
2776 ReleaseDC(NULL, display_dc);
2779 static void test_GetWinMetaFileBits(void)
2781 UINT mode;
2782 RECT frames[] =
2784 { 1000, 2000, 3000, 6000},
2785 {-1000, 2000, 3000, 6000},
2786 { 1000, -2000, 3000, 6000},
2787 { 1005, 2005, 3000, 6000},
2788 {-1005, -2005, 3000, 6000},
2789 {-1005, -2010, 3000, 6000},
2790 {-1005, 2010, 3000, 6000},
2791 { 0, 0, 1, 1},
2792 { -1, -1, 1, 1},
2793 { 0, 0, 0, 0}
2796 for(mode = MM_MIN; mode <= MM_MAX; mode++)
2798 RECT *rc;
2799 trace("mode %d\n", mode);
2801 for(rc = frames; rc->right - rc->left > 0; rc++)
2803 trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
2804 getwinmetafilebits(mode, 1, rc);
2805 getwinmetafilebits(mode, 2, rc);
2810 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2811 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2812 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2814 static void test_gdiis(void)
2816 RECT rect = {0,0,100,100};
2817 HDC hdc, hemfDC, hmfDC;
2818 HENHMETAFILE hemf;
2819 HMODULE hgdi32;
2821 /* resolve all the functions */
2822 hgdi32 = GetModuleHandle("gdi32");
2823 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2824 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2825 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2827 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2829 win_skip("Needed GdiIs* functions are not available\n");
2830 return;
2833 /* try with nothing */
2834 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2835 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2836 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2838 /* try with a metafile */
2839 hmfDC = CreateMetaFile(NULL);
2840 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2841 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2842 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2843 DeleteMetaFile(CloseMetaFile(hmfDC));
2845 /* try with an enhanced metafile */
2846 hdc = GetDC(NULL);
2847 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2848 ok(hemfDC != NULL, "failed to create emf\n");
2850 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2851 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2852 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2854 hemf = CloseEnhMetaFile(hemfDC);
2855 ok(hemf != NULL, "failed to close EMF\n");
2856 DeleteEnhMetaFile(hemf);
2857 ReleaseDC(NULL,hdc);
2860 static void test_SetEnhMetaFileBits(void)
2862 BYTE data[256];
2863 HENHMETAFILE hemf;
2864 ENHMETAHEADER *emh;
2866 memset(data, 0xAA, sizeof(data));
2867 SetLastError(0xdeadbeef);
2868 hemf = SetEnhMetaFileBits(sizeof(data), data);
2869 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2870 ok(GetLastError() == ERROR_INVALID_DATA ||
2871 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2872 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2874 emh = (ENHMETAHEADER *)data;
2875 memset(emh, 0, sizeof(*emh));
2877 emh->iType = EMR_HEADER;
2878 emh->nSize = sizeof(*emh);
2879 emh->dSignature = ENHMETA_SIGNATURE;
2880 /* emh->nVersion = 0x10000; XP doesn't care about version */
2881 emh->nBytes = sizeof(*emh);
2882 /* emh->nRecords = 1; XP doesn't care about records */
2883 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2885 SetLastError(0xdeadbeef);
2886 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2887 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2888 DeleteEnhMetaFile(hemf);
2890 /* XP refuses to load unaligned EMF */
2891 emh->nBytes++;
2892 SetLastError(0xdeadbeef);
2893 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2894 ok(!hemf ||
2895 broken(hemf != NULL), /* Win9x, WinMe */
2896 "SetEnhMetaFileBits should fail\n");
2897 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2898 DeleteEnhMetaFile(hemf);
2900 emh->dSignature = 0;
2901 emh->nBytes--;
2902 SetLastError(0xdeadbeef);
2903 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2904 ok(!hemf ||
2905 broken(hemf != NULL), /* Win9x, WinMe */
2906 "SetEnhMetaFileBits should fail\n");
2907 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2908 DeleteEnhMetaFile(hemf);
2911 START_TEST(metafile)
2913 init_function_pointers();
2915 /* For enhanced metafiles (enhmfdrv) */
2916 test_ExtTextOut();
2917 test_ExtTextOutScale();
2918 test_SaveDC();
2919 test_emf_BitBlt();
2921 /* For win-format metafiles (mfdrv) */
2922 test_mf_SaveDC();
2923 test_mf_Blank();
2924 test_mf_Graphics();
2925 test_mf_PatternBrush();
2926 test_CopyMetaFile();
2927 test_SetMetaFileBits();
2928 test_mf_ExtTextOut_on_path();
2929 test_emf_ExtTextOut_on_path();
2930 test_emf_clipping();
2932 /* For metafile conversions */
2933 test_mf_conversions();
2934 test_SetWinMetaFileBits();
2935 test_GetWinMetaFileBits();
2937 test_gdiis();
2938 test_SetEnhMetaFileBits();