gdi32: Add support for DIBINDEX colors in 1-bpp blits.
[wine.git] / dlls / gdi32 / tests / metafile.c
blob514e2b4109adeb07b1ffeb18fd5cb83a09dfc6a7
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);
40 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
41 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
43 #define GDI_GET_PROC(func) \
44 p ## func = (void *)GetProcAddress(hGDI, #func); \
45 if(!p ## func) \
46 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
48 static void init_function_pointers(void)
50 HMODULE hGDI;
52 pGetRelAbs = NULL;
53 pSetRelAbs = NULL;
55 hGDI = GetModuleHandleA("gdi32.dll");
56 assert(hGDI);
57 GDI_GET_PROC(GetRelAbs);
58 GDI_GET_PROC(SetRelAbs);
59 GDI_GET_PROC(SetDCBrushColor);
60 GDI_GET_PROC(SetDCPenColor);
63 static DWORD rgn_rect_count(HRGN hrgn)
65 DWORD size;
66 RGNDATA *data;
68 if (!hrgn) return 0;
69 if (!(size = GetRegionData(hrgn, 0, NULL))) return 0;
70 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0;
71 GetRegionData(hrgn, size, data);
72 size = data->rdh.nCount;
73 HeapFree(GetProcessHeap(), 0, data);
74 return size;
77 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
78 const ENHMETARECORD *emr, int n_objs, LPARAM param)
80 static int n_record;
81 DWORD i;
82 const INT *dx;
83 INT *orig_dx = (INT *)param;
84 LOGFONTA device_lf;
85 INT ret;
87 if(!hdc) return 1;
89 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
91 switch (emr->iType)
93 case EMR_HEADER:
94 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
95 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
96 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
97 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
98 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
99 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
100 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
102 /* GetBkMode, GetRelAbs do not get reset to the default value */
103 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
104 if(pSetRelAbs && pGetRelAbs)
105 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
107 n_record = 0;
108 break;
110 case EMR_EXTTEXTOUTA:
112 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
113 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
115 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
116 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
118 /* compare up to lfOutPrecision, other values are not interesting,
119 * and in fact sometimes arbitrary adapted by Win9x.
121 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
122 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
124 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
126 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
127 n_record, i, dx[i], orig_dx[i]);
129 n_record++;
130 emr_processed = TRUE;
131 break;
134 case EMR_EXTTEXTOUTW:
136 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
137 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
139 SetLastError(0xdeadbeef);
140 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
141 ok( ret == sizeof(device_lf) ||
142 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
143 "GetObjectA error %d\n", GetLastError());
145 /* compare up to lfOutPrecision, other values are not interesting,
146 * and in fact sometimes arbitrary adapted by Win9x.
148 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
149 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
151 ok(!emr_ExtTextOutW->rclBounds.left, "emr_ExtTextOutW->rclBounds.left = %d\n",
152 emr_ExtTextOutW->rclBounds.left);
153 ok(emr_ExtTextOutW->rclBounds.right != -1, "emr_ExtTextOutW->rclBounds.right = %d\n",
154 emr_ExtTextOutW->rclBounds.right);
155 ok(emr_ExtTextOutW->rclBounds.bottom != -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n",
156 emr_ExtTextOutW->rclBounds.bottom);
158 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
160 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
161 n_record, i, dx[i], orig_dx[i]);
163 n_record++;
164 emr_processed = TRUE;
165 break;
168 default:
169 break;
172 return 1;
175 static void test_ExtTextOut(void)
177 HWND hwnd;
178 HDC hdcDisplay, hdcMetafile;
179 HENHMETAFILE hMetafile;
180 HFONT hFont;
181 static const char text[] = "Simple text to test ExtTextOut on metafiles";
182 INT i, len, dx[256];
183 static const RECT rc = { 0, 0, 100, 100 };
184 BOOL ret;
186 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
188 /* Win9x doesn't play EMFs on invisible windows */
189 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
190 0, 0, 200, 200, 0, 0, 0, NULL);
191 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
193 hdcDisplay = GetDC(hwnd);
194 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
196 trace("hdcDisplay %p\n", hdcDisplay);
198 SetMapMode(hdcDisplay, MM_TEXT);
200 memset(&orig_lf, 0, sizeof(orig_lf));
202 orig_lf.lfCharSet = ANSI_CHARSET;
203 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
204 orig_lf.lfWeight = FW_DONTCARE;
205 orig_lf.lfHeight = 7;
206 orig_lf.lfQuality = DEFAULT_QUALITY;
207 lstrcpyA(orig_lf.lfFaceName, "Arial");
208 hFont = CreateFontIndirectA(&orig_lf);
209 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
211 hFont = SelectObject(hdcDisplay, hFont);
213 len = lstrlenA(text);
214 for (i = 0; i < len; i++)
216 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
217 ok( ret, "GetCharWidthA error %d\n", GetLastError());
219 hFont = SelectObject(hdcDisplay, hFont);
221 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
222 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
224 trace("hdcMetafile %p\n", hdcMetafile);
226 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
227 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
229 hFont = SelectObject(hdcMetafile, hFont);
231 /* 1. pass NULL lpDx */
232 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
233 ok( ret, "ExtTextOutA error %d\n", GetLastError());
235 /* 2. pass custom lpDx */
236 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
237 ok( ret, "ExtTextOutA error %d\n", GetLastError());
239 /* 3. pass NULL lprc */
240 ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL);
241 ok( ret, "ExtTextOutA error %d\n", GetLastError());
243 /* 4. test with unmatched BeginPath/EndPath calls */
244 ret = BeginPath(hdcMetafile);
245 ok( ret, "BeginPath error %d\n", GetLastError());
246 ret = BeginPath(hdcMetafile);
247 ok( ret, "BeginPath error %d\n", GetLastError());
248 ret = EndPath(hdcMetafile);
249 ok( ret, "BeginPath error %d\n", GetLastError());
250 ret = ExtTextOutA(hdcMetafile, 0, 60, 0, NULL, text, lstrlenA(text), NULL);
251 ok( ret, "ExtTextOutA error %d\n", GetLastError());
253 hFont = SelectObject(hdcMetafile, hFont);
254 ret = DeleteObject(hFont);
255 ok( ret, "DeleteObject error %d\n", GetLastError());
257 hMetafile = CloseEnhMetaFile(hdcMetafile);
258 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
260 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
262 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
263 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
265 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
266 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
267 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
268 SetROP2(hdcDisplay, R2_NOT);
269 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
270 SetPolyFillMode(hdcDisplay, WINDING);
271 SetStretchBltMode(hdcDisplay, HALFTONE);
273 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
274 SetBkMode(hdcDisplay, OPAQUE);
276 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
277 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
279 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
280 "text align %08x\n", GetTextAlign(hdcDisplay));
281 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
282 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
283 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
284 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
285 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
286 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
288 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
290 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
291 "A valid hdc has to require a valid rc\n");
293 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
294 "A null hdc does not require a valid rc\n");
296 ret = DeleteEnhMetaFile(hMetafile);
297 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
298 ret = ReleaseDC(hwnd, hdcDisplay);
299 ok( ret, "ReleaseDC error %d\n", GetLastError());
300 DestroyWindow(hwnd);
303 struct eto_scale_test_record
305 INT graphics_mode;
306 INT map_mode;
307 double ex_scale;
308 double ey_scale;
309 BOOL processed;
312 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
313 const ENHMETARECORD *emr, int n_objs, LPARAM param)
315 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
317 if (emr->iType == EMR_EXTTEXTOUTW)
319 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
320 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
321 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
322 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
323 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
324 test->processed = TRUE;
327 return 1;
330 static void test_ExtTextOutScale(void)
332 const RECT rc = { 0, 0, 100, 100 };
333 const WCHAR str[] = {'a',0 };
334 struct eto_scale_test_record test;
335 HDC hdcDisplay, hdcMetafile;
336 HENHMETAFILE hMetafile;
337 HWND hwnd;
338 SIZE wndext, vportext;
339 int horzSize, vertSize, horzRes, vertRes;
340 int ret;
341 int i;
343 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
344 0, 0, 200, 200, 0, 0, 0, NULL);
345 ok(hwnd != 0, "CreateWindowExA failed\n");
347 hdcDisplay = GetDC(hwnd);
348 ok(hdcDisplay != 0, "GetDC failed\n");
350 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
351 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
352 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
353 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
354 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
356 for (i = 0; i < 16; i++)
358 test.graphics_mode = i / 8 + 1;
359 test.map_mode = i % 8 + 1;
361 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
362 ok(ret, "SetGraphicsMode failed\n");
363 ret = SetMapMode(hdcDisplay, test.map_mode);
364 ok(ret, "SetMapMode failed\n");
366 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
368 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
369 ok(ret, "SetWindowExtEx failed\n");
370 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
371 ok(ret, "SetViewportExtEx failed\n");
374 ret = GetViewportExtEx(hdcDisplay, &vportext);
375 ok(ret, "GetViewportExtEx failed\n");
376 ret = GetWindowExtEx(hdcDisplay, &wndext);
377 ok(ret, "GetWindowExtEx failed\n");
379 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
380 test.graphics_mode, test.map_mode,
381 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
382 horzSize, horzRes, vertSize, vertRes);
384 if (test.graphics_mode == GM_COMPATIBLE)
386 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
387 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
388 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
389 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
391 else
393 test.ex_scale = 0.0;
394 test.ey_scale = 0.0;
397 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
398 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
400 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
401 ok(ret, "SetGraphicsMode failed\n");
402 ret = SetMapMode(hdcMetafile, test.map_mode);
403 ok(ret, "SetMapMode failed\n");
405 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
407 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
408 ok(ret, "SetWindowExtEx failed\n");
409 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
410 ok(ret, "SetViewportExtEx failed\n");
413 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
414 ok(ret, "ExtTextOutW failed\n");
416 hMetafile = CloseEnhMetaFile(hdcMetafile);
417 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
419 test.processed = 0;
420 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
421 ok(ret, "EnumEnhMetaFile failed\n");
422 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
424 ret = DeleteEnhMetaFile(hMetafile);
425 ok(ret, "DeleteEnhMetaFile failed\n");
428 ret = ReleaseDC(hwnd, hdcDisplay);
429 ok(ret, "ReleaseDC failed\n");
430 DestroyWindow(hwnd);
434 static void check_dc_state(HDC hdc, int restore_no,
435 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
436 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
438 BOOL ret;
439 XFORM xform;
440 POINT vp_org, win_org;
441 SIZE vp_size, win_size;
442 FLOAT xscale, yscale, edx, edy;
444 SetLastError(0xdeadbeef);
445 ret = GetWorldTransform(hdc, &xform);
446 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
447 ok(ret, "GetWorldTransform error %u\n", GetLastError());
449 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
451 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
452 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
454 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
455 trace("x scale %f\n", xscale);
456 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
457 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
459 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
460 trace("y scale %f\n", yscale);
461 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
462 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
464 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
465 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
466 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
467 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
469 return;
471 win9x_here:
473 GetWindowOrgEx(hdc, &win_org);
474 GetViewportOrgEx(hdc, &vp_org);
475 GetWindowExtEx(hdc, &win_size);
476 GetViewportExtEx(hdc, &vp_size);
478 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
479 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
481 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
482 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
484 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
485 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
487 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
488 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
491 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
492 const ENHMETARECORD *emr, int n_objs, LPARAM param)
494 BOOL ret;
495 XFORM xform;
496 POINT pt;
497 SIZE size;
498 static int save_state;
499 static int restore_no;
500 static int select_no;
502 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
503 hdc, emr->iType, emr->nSize, (void *)param);
505 SetLastError(0xdeadbeef);
506 ret = GetWorldTransform(hdc, &xform);
507 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
509 ret = GetWindowOrgEx(hdc, &pt);
510 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
511 trace("window org (%d,%d)\n", pt.x, pt.y);
512 ret = GetViewportOrgEx(hdc, &pt);
513 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
514 trace("vport org (%d,%d)\n", pt.x, pt.y);
515 ret = GetWindowExtEx(hdc, &size);
516 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
517 trace("window ext (%d,%d)\n", size.cx, size.cy);
518 ret = GetViewportExtEx(hdc, &size);
519 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
520 trace("vport ext (%d,%d)\n", size.cx, size.cy);
522 else
524 ok(ret, "GetWorldTransform error %u\n", GetLastError());
525 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
528 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
530 switch (emr->iType)
532 case EMR_HEADER:
534 static RECT exp_bounds = { 0, 0, 150, 150 };
535 RECT bounds;
536 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
538 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
539 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
540 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
541 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
542 emf->szlDevice.cx, emf->szlDevice.cy);
544 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
545 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
547 save_state = 0;
548 restore_no = 0;
549 select_no = 0;
550 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
551 break;
554 case EMR_LINETO:
556 const EMRLINETO *line = (const EMRLINETO *)emr;
557 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
558 break;
560 case EMR_SETWINDOWORGEX:
562 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
563 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
564 break;
566 case EMR_SETWINDOWEXTEX:
568 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
569 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
570 break;
572 case EMR_SETVIEWPORTORGEX:
574 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
575 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
576 break;
578 case EMR_SETVIEWPORTEXTEX:
580 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
581 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
582 break;
584 case EMR_SAVEDC:
585 save_state++;
586 trace("EMR_SAVEDC\n");
587 break;
589 case EMR_RESTOREDC:
591 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
592 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
594 switch(++restore_no)
596 case 1:
597 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
598 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
599 break;
600 case 2:
601 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
602 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
603 break;
604 case 3:
605 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
606 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
607 break;
609 ok(restore_no <= 3, "restore_no %d\n", restore_no);
610 save_state += restoredc->iRelative;
611 break;
613 case EMR_SELECTOBJECT:
615 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
616 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
617 select_no ++;
618 break;
620 case EMR_EOF:
621 ok(save_state == 0, "EOF save_state %d\n", save_state);
622 ok(select_no == 3, "Too many/few selects %i\n",select_no);
623 break;
626 SetLastError(0xdeadbeef);
627 ret = GetWorldTransform(hdc, &xform);
628 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
630 ret = GetWindowOrgEx(hdc, &pt);
631 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
632 trace("window org (%d,%d)\n", pt.x, pt.y);
633 ret = GetViewportOrgEx(hdc, &pt);
634 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
635 trace("vport org (%d,%d)\n", pt.x, pt.y);
636 ret = GetWindowExtEx(hdc, &size);
637 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
638 trace("window ext (%d,%d)\n", size.cx, size.cy);
639 ret = GetViewportExtEx(hdc, &size);
640 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
641 trace("vport ext (%d,%d)\n", size.cx, size.cy);
643 else
645 ok(ret, "GetWorldTransform error %u\n", GetLastError());
646 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
649 return 1;
652 static void test_SaveDC(void)
654 HDC hdcMetafile, hdcDisplay;
655 HENHMETAFILE hMetafile;
656 HWND hwnd;
657 int ret;
658 POINT pt;
659 SIZE size;
660 HFONT hFont,hFont2,hFontOld,hFontCheck;
661 static const RECT rc = { 0, 0, 150, 150 };
663 /* Win9x doesn't play EMFs on invisible windows */
664 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
665 0, 0, 200, 200, 0, 0, 0, NULL);
666 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
668 hdcDisplay = GetDC(hwnd);
669 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
671 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
672 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
674 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
676 /* Need to write something to the emf, otherwise Windows won't play it back */
677 LineTo(hdcMetafile, 150, 150);
679 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
680 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
681 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
682 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
684 /* Force Win9x to update DC state */
685 SetPixelV(hdcMetafile, 50, 50, 0);
687 ret = GetViewportOrgEx(hdcMetafile, &pt);
688 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
689 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
690 ret = GetViewportExtEx(hdcMetafile, &size);
691 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
692 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
693 ret = SaveDC(hdcMetafile);
694 ok(ret == 1, "ret = %d\n", ret);
696 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
697 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
698 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
699 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
701 /* Force Win9x to update DC state */
702 SetPixelV(hdcMetafile, 50, 50, 0);
704 ret = GetViewportOrgEx(hdcMetafile, &pt);
705 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
706 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
707 ret = GetViewportExtEx(hdcMetafile, &size);
708 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
709 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
710 ret = SaveDC(hdcMetafile);
711 ok(ret == 2, "ret = %d\n", ret);
713 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
714 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
715 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
716 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
717 SetPolyFillMode( hdcMetafile, ALTERNATE );
718 SetBkColor( hdcMetafile, 0 );
720 /* Force Win9x to update DC state */
721 SetPixelV(hdcMetafile, 50, 50, 0);
723 ret = GetViewportOrgEx(hdcMetafile, &pt);
724 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
725 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
726 ret = GetViewportExtEx(hdcMetafile, &size);
727 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
728 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
729 ret = SaveDC(hdcMetafile);
730 ok(ret == 3, "ret = %d\n", ret);
732 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
733 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
734 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
735 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
737 SetPolyFillMode( hdcMetafile, WINDING );
738 SetBkColor( hdcMetafile, 0x123456 );
739 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
740 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
742 /* Force Win9x to update DC state */
743 SetPixelV(hdcMetafile, 50, 50, 0);
745 ret = GetViewportOrgEx(hdcMetafile, &pt);
746 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
747 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
748 ret = GetViewportExtEx(hdcMetafile, &size);
749 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
750 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
751 ret = RestoreDC(hdcMetafile, -1);
752 ok(ret, "ret = %d\n", ret);
754 ret = GetViewportOrgEx(hdcMetafile, &pt);
755 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
756 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
757 ret = GetViewportExtEx(hdcMetafile, &size);
758 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
759 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
760 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
761 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
762 ret = SaveDC(hdcMetafile);
763 ok(ret == 3, "ret = %d\n", ret);
765 ret = GetViewportOrgEx(hdcMetafile, &pt);
766 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
767 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
768 ret = GetViewportExtEx(hdcMetafile, &size);
769 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
770 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
771 ret = RestoreDC(hdcMetafile, 1);
772 ok(ret, "ret = %d\n", ret);
773 ret = GetViewportOrgEx(hdcMetafile, &pt);
774 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
775 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
776 ret = GetViewportExtEx(hdcMetafile, &size);
777 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
778 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
780 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
781 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
782 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
783 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
785 /* Force Win9x to update DC state */
786 SetPixelV(hdcMetafile, 50, 50, 0);
788 ret = GetViewportOrgEx(hdcMetafile, &pt);
789 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
790 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
791 ret = GetViewportExtEx(hdcMetafile, &size);
792 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
793 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
794 ret = SaveDC(hdcMetafile);
795 ok(ret == 1, "ret = %d\n", ret);
797 ret = GetViewportOrgEx(hdcMetafile, &pt);
798 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
799 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
800 ret = GetViewportExtEx(hdcMetafile, &size);
801 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
802 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
803 ret = SaveDC(hdcMetafile);
804 ok(ret == 2, "ret = %d\n", ret);
806 memset(&orig_lf, 0, sizeof(orig_lf));
807 orig_lf.lfCharSet = ANSI_CHARSET;
808 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
809 orig_lf.lfWeight = FW_DONTCARE;
810 orig_lf.lfHeight = 7;
811 orig_lf.lfQuality = DEFAULT_QUALITY;
812 lstrcpyA(orig_lf.lfFaceName, "Arial");
813 hFont = CreateFontIndirectA(&orig_lf);
814 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
816 hFontOld = SelectObject(hdcMetafile, hFont);
818 hFont2 = CreateFontIndirectA(&orig_lf);
819 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
820 hFontCheck = SelectObject(hdcMetafile, hFont2);
821 ok(hFontCheck == hFont, "Font not selected\n");
823 /* Force Win9x to update DC state */
824 SetPixelV(hdcMetafile, 50, 50, 0);
826 ret = RestoreDC(hdcMetafile, 1);
827 ok(ret, "ret = %d\n", ret);
828 ret = GetViewportOrgEx(hdcMetafile, &pt);
829 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
830 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
831 ret = GetViewportExtEx(hdcMetafile, &size);
832 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
833 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
835 hFontCheck = SelectObject(hdcMetafile, hFontOld);
836 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
837 "Font not reverted with DC Restore\n");
839 ret = RestoreDC(hdcMetafile, -20);
840 ok(!ret, "ret = %d\n", ret);
841 ret = RestoreDC(hdcMetafile, 20);
842 ok(!ret, "ret = %d\n", ret);
844 hMetafile = CloseEnhMetaFile(hdcMetafile);
845 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
847 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
848 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
850 ret = DeleteObject(hFont);
851 ok( ret, "DeleteObject error %d\n", GetLastError());
852 ret = DeleteObject(hFont2);
853 ok( ret, "DeleteObject error %d\n", GetLastError());
854 ret = DeleteEnhMetaFile(hMetafile);
855 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
856 ret = ReleaseDC(hwnd, hdcDisplay);
857 ok( ret, "ReleaseDC error %d\n", GetLastError());
858 DestroyWindow(hwnd);
861 static void test_mf_SaveDC(void)
863 HDC hdcMetafile;
864 HMETAFILE hMetafile;
865 int ret;
866 POINT pt;
867 SIZE size;
868 HFONT hFont,hFont2,hFontOld,hFontCheck;
870 hdcMetafile = CreateMetaFileA(NULL);
871 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
873 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
874 ok (ret, "SetMapMode should not fail\n");
876 /* Need to write something to the emf, otherwise Windows won't play it back */
877 LineTo(hdcMetafile, 150, 150);
879 pt.x = pt.y = 5555;
880 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
881 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
882 pt.x = pt.y = 5555;
883 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
884 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
885 size.cx = size.cy = 5555;
886 SetWindowExtEx(hdcMetafile, 110, 110, &size );
887 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
888 size.cx = size.cy = 5555;
889 SetViewportExtEx(hdcMetafile, 120, 120, &size );
890 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
892 /* Force Win9x to update DC state */
893 SetPixelV(hdcMetafile, 50, 50, 0);
895 ret = GetViewportOrgEx(hdcMetafile, &pt);
896 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
897 ret = GetViewportExtEx(hdcMetafile, &size);
898 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
899 ret = SaveDC(hdcMetafile);
900 ok(ret == 1, "ret = %d\n", ret);
902 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
903 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
904 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
905 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
907 /* Force Win9x to update DC state */
908 SetPixelV(hdcMetafile, 50, 50, 0);
910 ret = SaveDC(hdcMetafile);
911 ok(ret == 1, "ret = %d\n", ret);
913 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
914 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
915 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
916 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
918 /* Force Win9x to update DC state */
919 SetPixelV(hdcMetafile, 50, 50, 0);
920 SetPolyFillMode( hdcMetafile, ALTERNATE );
921 SetBkColor( hdcMetafile, 0 );
923 ret = SaveDC(hdcMetafile);
924 ok(ret == 1, "ret = %d\n", ret);
926 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
927 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
928 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
929 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
931 SetPolyFillMode( hdcMetafile, WINDING );
932 SetBkColor( hdcMetafile, 0x123456 );
933 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
934 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
936 /* Force Win9x to update DC state */
937 SetPixelV(hdcMetafile, 50, 50, 0);
939 ret = RestoreDC(hdcMetafile, -1);
940 ok(ret, "ret = %d\n", ret);
942 ret = SaveDC(hdcMetafile);
943 ok(ret == 1, "ret = %d\n", ret);
945 ret = RestoreDC(hdcMetafile, 1);
946 ok(ret, "ret = %d\n", ret);
948 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
949 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
950 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
951 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
953 /* Force Win9x to update DC state */
954 SetPixelV(hdcMetafile, 50, 50, 0);
956 ret = SaveDC(hdcMetafile);
957 ok(ret == 1, "ret = %d\n", ret);
959 ret = SaveDC(hdcMetafile);
960 ok(ret == 1, "ret = %d\n", ret);
962 memset(&orig_lf, 0, sizeof(orig_lf));
963 orig_lf.lfCharSet = ANSI_CHARSET;
964 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
965 orig_lf.lfWeight = FW_DONTCARE;
966 orig_lf.lfHeight = 7;
967 orig_lf.lfQuality = DEFAULT_QUALITY;
968 lstrcpyA(orig_lf.lfFaceName, "Arial");
969 hFont = CreateFontIndirectA(&orig_lf);
970 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
972 hFontOld = SelectObject(hdcMetafile, hFont);
974 hFont2 = CreateFontIndirectA(&orig_lf);
975 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
976 hFontCheck = SelectObject(hdcMetafile, hFont2);
977 ok(hFontCheck == hFont, "Font not selected\n");
979 /* Force Win9x to update DC state */
980 SetPixelV(hdcMetafile, 50, 50, 0);
982 ret = RestoreDC(hdcMetafile, 1);
983 ok(ret, "ret = %d\n", ret);
985 hFontCheck = SelectObject(hdcMetafile, hFontOld);
986 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
988 /* restore level is ignored */
989 ret = RestoreDC(hdcMetafile, -20);
990 ok(ret, "ret = %d\n", ret);
991 ret = RestoreDC(hdcMetafile, 20);
992 ok(ret, "ret = %d\n", ret);
993 ret = RestoreDC(hdcMetafile, 0);
994 ok(ret, "ret = %d\n", ret);
996 hMetafile = CloseMetaFile(hdcMetafile);
997 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
999 ret = DeleteMetaFile(hMetafile);
1000 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1001 ret = DeleteObject(hFont);
1002 ok( ret, "DeleteObject error %d\n", GetLastError());
1003 ret = DeleteObject(hFont2);
1004 ok( ret, "DeleteObject error %d\n", GetLastError());
1008 /* Win-format metafile (mfdrv) tests */
1009 /* These tests compare the generated metafiles byte-by-byte */
1010 /* with the nominal results. */
1012 /* Maximum size of sample metafiles in bytes. */
1013 #define MF_BUFSIZE 1024
1015 /* 8x8 bitmap data for a pattern brush */
1016 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
1017 0x01, 0x00, 0x02, 0x00,
1018 0x03, 0x00, 0x04, 0x00,
1019 0x05, 0x00, 0x06, 0x00,
1020 0x07, 0x00, 0x08, 0x00
1023 /* Sample metafiles to be compared to the outputs of the
1024 * test functions.
1027 static const unsigned char MF_BLANK_BITS[] = {
1028 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1030 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1033 static const unsigned char MF_GRAPHICS_BITS[] = {
1034 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1035 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1037 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1038 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1039 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1040 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1041 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1042 0x00, 0x00, 0x00, 0x00
1045 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1046 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1047 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1048 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1049 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1050 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1051 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1052 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1056 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1057 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1058 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1059 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1060 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1061 0x00, 0x00
1064 static const unsigned char MF_DCBRUSH_BITS[] =
1066 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1067 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1068 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1069 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1070 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1071 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1073 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1074 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1075 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1076 0x00, 0x00, 0x00, 0x00
1079 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1081 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1084 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1085 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1086 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1087 0x00, 0x00
1090 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1092 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1097 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1098 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1099 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1102 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1105 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1106 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1107 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1108 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1109 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1111 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1112 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1114 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1115 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1116 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1117 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1118 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1119 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1120 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1122 0x14, 0x00, 0x00, 0x00
1125 static const unsigned char MF_LINETO_BITS[] = {
1126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1130 0x00, 0x00
1133 static const unsigned char EMF_LINETO_BITS[] = {
1134 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1139 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1140 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1141 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1144 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1147 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1148 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1149 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1150 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1151 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1152 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1154 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1155 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1156 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1157 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1158 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1161 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1162 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1163 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1164 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1165 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1166 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1167 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1168 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1169 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1170 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1171 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1175 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1176 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1180 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1181 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1182 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1183 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1185 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1186 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1189 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1190 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1191 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1192 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1193 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1194 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1195 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1196 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1197 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1199 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1200 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1201 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1202 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1203 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1204 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1205 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1206 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1207 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1208 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1209 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1210 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1211 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1213 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1217 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1218 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1220 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1223 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1224 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1225 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1228 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1231 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1232 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1233 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1234 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1235 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1236 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1237 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1238 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1239 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1241 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1242 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1244 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1246 0x14, 0x00, 0x00, 0x00
1249 static const unsigned char EMF_BITBLT[] =
1251 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1253 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1256 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1257 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1258 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1261 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1264 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1265 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1267 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1269 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1276 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1277 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1278 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1293 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1296 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1301 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1303 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1305 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1311 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1312 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1313 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1314 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1315 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1316 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1325 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1326 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1327 0x14, 0x00, 0x00, 0x00
1330 static const unsigned char EMF_DCBRUSH_BITS[] =
1332 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1333 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1334 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1335 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1336 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1337 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1338 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1339 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1341 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1342 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1345 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1346 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1347 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1348 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1349 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1350 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1351 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1352 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1353 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1354 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1357 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1358 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1359 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1360 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1361 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1362 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1363 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1365 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1366 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1367 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1368 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1369 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1370 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1372 0x14, 0x00, 0x00, 0x00
1375 static const unsigned char EMF_BEZIER_BITS[] =
1377 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1382 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1383 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1384 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1386 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1387 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1389 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1390 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1391 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1393 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1394 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1395 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1396 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1397 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1398 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1399 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1400 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1401 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1402 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1403 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1404 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1405 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1407 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1408 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1409 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1410 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1411 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1412 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1413 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1414 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1415 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1416 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1417 0x14, 0x00, 0x00, 0x00
1420 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1422 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1423 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1424 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1425 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1426 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1427 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1428 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1429 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1431 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1432 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1435 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1436 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1438 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1439 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1440 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1441 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1442 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1443 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1444 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1445 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1447 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1448 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1449 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1450 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1451 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1454 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1455 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1456 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1457 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1458 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1459 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1460 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1461 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1462 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1463 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1464 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1465 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1466 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1467 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1468 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1470 0x14, 0x00, 0x00, 0x00
1473 static const unsigned char EMF_GRADIENTFILL_BITS[] =
1475 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1476 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1477 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1478 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1479 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1480 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1481 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1482 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1485 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1487 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1488 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1489 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1490 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1491 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1492 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1493 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1494 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1495 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1497 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1498 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1499 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1500 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1501 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1502 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1503 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1504 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1505 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1508 0x14, 0x00, 0x00, 0x00
1511 /* For debugging or dumping the raw metafiles produced by
1512 * new test functions.
1514 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1515 INT nobj, LPARAM param)
1517 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1518 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1519 return TRUE;
1522 /* For debugging or dumping the raw metafiles produced by
1523 * new test functions.
1526 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1528 BYTE buf[MF_BUFSIZE];
1529 UINT mfsize, i;
1531 if (!winetest_debug) return;
1533 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1534 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1536 printf ("MetaFile %s has bits:\n{\n ", desc);
1537 for (i=0; i<mfsize; i++)
1539 printf ("0x%02x", buf[i]);
1540 if (i == mfsize-1)
1541 printf ("\n");
1542 else if (i % 8 == 7)
1543 printf (",\n ");
1544 else
1545 printf (", ");
1547 printf ("};\n");
1550 /* Compare the metafile produced by a test function with the
1551 * expected raw metafile data in "bits".
1552 * Return value is 0 for a perfect match,
1553 * -1 if lengths aren't equal,
1554 * otherwise returns the number of non-matching bytes.
1557 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1558 const char *desc)
1560 unsigned char buf[MF_BUFSIZE];
1561 UINT mfsize, i;
1562 int diff;
1564 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1565 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1566 if (mfsize < MF_BUFSIZE)
1567 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1568 desc, mfsize, bsize);
1569 else
1570 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1571 desc, mfsize, bsize);
1572 if (mfsize != bsize)
1573 return -1;
1575 diff = 0;
1576 for (i=0; i<bsize; i++)
1578 if (buf[i] != bits[i])
1579 diff++;
1581 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1582 desc, mfsize, bsize, diff);
1584 return diff;
1587 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1589 unsigned char buf[MF_BUFSIZE];
1590 DWORD mfsize, rd_size, i;
1591 int diff;
1592 HANDLE hfile;
1593 BOOL ret;
1595 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1596 assert(hfile != INVALID_HANDLE_VALUE);
1598 mfsize = GetFileSize(hfile, NULL);
1599 assert(mfsize <= MF_BUFSIZE);
1601 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1602 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1604 CloseHandle(hfile);
1606 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1608 if (mfsize != bsize)
1609 return -1;
1611 diff = 0;
1612 for (i=0; i<bsize; i++)
1614 if (buf[i] != bits[i])
1615 diff++;
1617 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1618 desc, mfsize, bsize, diff);
1620 return diff;
1623 /* For debugging or dumping the raw EMFs produced by
1624 * new test functions.
1626 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1628 BYTE buf[MF_BUFSIZE];
1629 UINT mfsize, i;
1631 if (!winetest_debug) return;
1633 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1634 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1636 printf("EMF %s has bits:\n{\n ", desc);
1637 for (i = 0; i < mfsize; i++)
1639 printf ("0x%02x", buf[i]);
1640 if (i == mfsize-1)
1641 printf ("\n");
1642 else if (i % 8 == 7)
1643 printf (",\n ");
1644 else
1645 printf (", ");
1647 printf ("};\n");
1650 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1652 BYTE *emf;
1653 BYTE buf[MF_BUFSIZE];
1654 UINT mfsize, offset;
1656 if (!winetest_debug) return;
1658 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1659 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1661 printf("EMF %s has records:\n", desc);
1663 emf = buf;
1664 offset = 0;
1665 while(offset < mfsize)
1667 EMR *emr = (EMR *)(emf + offset);
1668 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1669 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1670 offset += emr->nSize;
1674 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1676 const BYTE *buf;
1677 DWORD i;
1679 if (!winetest_debug) return;
1681 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1682 buf = (const BYTE *)emr;
1683 for (i = 0; i < emr->nSize; i++)
1685 printf ("0x%02x", buf[i]);
1686 if (i == emr->nSize - 1)
1687 printf ("\n");
1688 else if (i % 8 == 7)
1689 printf (",\n");
1690 else
1691 printf (", ");
1693 printf ("};\n");
1696 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1698 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1699 eto->rclBounds.right, eto->rclBounds.bottom);
1700 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1701 trace("exScale: %f\n", eto->exScale);
1702 trace("eyScale: %f\n", eto->eyScale);
1703 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1704 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1705 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1706 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1707 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1708 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1709 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1712 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1713 const char *desc, BOOL ignore_scaling)
1715 int diff;
1717 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1718 desc, emr1->iType, emr2->iType);
1720 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1721 desc, emr1->nSize, emr2->nSize);
1723 /* iType and nSize mismatches are fatal */
1724 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1726 /* contents of EMR_GDICOMMENT are not interesting */
1727 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1729 /* different Windows versions setup DC scaling differently when
1730 * converting an old style metafile to an EMF.
1732 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1733 emr1->iType == EMR_SETVIEWPORTEXTEX))
1734 return TRUE;
1736 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1738 EMREXTTEXTOUTW *eto1, *eto2;
1740 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1741 memcpy(eto1, emr1, emr1->nSize);
1742 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1743 memcpy(eto2, emr2, emr2->nSize);
1745 /* different Windows versions setup DC scaling differently */
1746 eto1->exScale = eto1->eyScale = 0.0;
1747 eto2->exScale = eto2->eyScale = 0.0;
1749 diff = memcmp(eto1, eto2, emr1->nSize);
1750 if (diff)
1752 dump_EMREXTTEXTOUT(eto1);
1753 dump_EMREXTTEXTOUT(eto2);
1755 HeapFree(GetProcessHeap(), 0, eto1);
1756 HeapFree(GetProcessHeap(), 0, eto2);
1758 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1760 /* We have to take care of NT4 differences here */
1761 diff = memcmp(emr1, emr2, emr1->nSize);
1762 if (diff)
1764 ENHMETARECORD *emr_nt4;
1766 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1767 memcpy(emr_nt4, emr2, emr2->nSize);
1768 /* Correct the nRgnSize field */
1769 emr_nt4->dParm[5] = sizeof(RECT);
1771 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1772 if (!diff)
1773 win_skip("Catered for NT4 differences\n");
1775 HeapFree(GetProcessHeap(), 0, emr_nt4);
1778 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1780 EMRPOLYBEZIER16 *eto1, *eto2;
1782 eto1 = (EMRPOLYBEZIER16*)emr1;
1783 eto2 = (EMRPOLYBEZIER16*)emr2;
1785 diff = eto1->cpts != eto2->cpts;
1786 if(!diff)
1787 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1789 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1791 EMRPOLYBEZIER *eto1, *eto2;
1793 eto1 = (EMRPOLYBEZIER*)emr1;
1794 eto2 = (EMRPOLYBEZIER*)emr2;
1796 diff = eto1->cptl != eto2->cptl;
1797 if(!diff)
1798 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1800 else
1801 diff = memcmp(emr1, emr2, emr1->nSize);
1803 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1805 if (diff)
1807 dump_emf_record(emr1, "expected bits");
1808 dump_emf_record(emr2, "actual bits");
1811 return diff == 0; /* report all non-fatal record mismatches */
1814 /* Compare the EMF produced by a test function with the
1815 * expected raw EMF data in "bits".
1816 * Return value is 0 for a perfect match,
1817 * -1 if lengths aren't equal,
1818 * otherwise returns the number of non-matching bytes.
1820 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1821 UINT bsize, const char *desc,
1822 BOOL ignore_scaling)
1824 unsigned char buf[MF_BUFSIZE];
1825 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1826 const ENHMETAHEADER *emh1, *emh2;
1828 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1829 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1831 /* ENHMETAHEADER size could differ, depending on platform */
1832 diff_nt4 = sizeof(SIZEL);
1833 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1835 if (mfsize < MF_BUFSIZE)
1837 ok(mfsize == bsize ||
1838 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1839 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1840 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1842 else
1843 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1844 desc, mfsize, bsize);
1846 /* basic things must match */
1847 emh1 = (const ENHMETAHEADER *)bits;
1848 emh2 = (const ENHMETAHEADER *)buf;
1849 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1850 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1851 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1852 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1854 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1855 ok(emh1->nSize == emh2->nSize ||
1856 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1857 broken(emh1->nSize - diff_9x == emh2->nSize),
1858 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1859 ok(emh1->rclBounds.left == emh2->rclBounds.left, "%s: expected rclBounds.left = %d, got %d\n",
1860 desc, emh1->rclBounds.left, emh2->rclBounds.left);
1861 ok(emh1->rclBounds.top == emh2->rclBounds.top, "%s: expected rclBounds.top = %d, got %d\n",
1862 desc, emh1->rclBounds.top, emh2->rclBounds.top);
1863 ok(emh1->rclBounds.right == emh2->rclBounds.right, "%s: expected rclBounds.right = %d, got %d\n",
1864 desc, emh1->rclBounds.right, emh2->rclBounds.right);
1865 ok(emh1->rclBounds.bottom == emh2->rclBounds.bottom, "%s: expected rclBounds.bottom = %d, got %d\n",
1866 desc, emh1->rclBounds.bottom, emh2->rclBounds.bottom);
1867 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1868 ok(emh1->nBytes == emh2->nBytes ||
1869 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1870 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1871 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1872 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1874 offset1 = emh1->nSize;
1875 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1876 while (offset1 < emh1->nBytes)
1878 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1879 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1881 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1882 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1884 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1886 /* We have already bailed out if iType or nSize don't match */
1887 offset1 += emr1->nSize;
1888 offset2 += emr2->nSize;
1890 return 0;
1894 /* tests blitting to an EMF */
1895 static void test_emf_BitBlt(void)
1897 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1898 HBITMAP hBitmap, hOldBitmap;
1899 HENHMETAFILE hMetafile;
1900 #define BMP_DIM 4
1901 BITMAPINFOHEADER bmih =
1903 sizeof(BITMAPINFOHEADER),
1904 BMP_DIM,/* biWidth */
1905 BMP_DIM,/* biHeight */
1906 1, /* biPlanes */
1907 24, /* biBitCount */
1908 BI_RGB, /* biCompression */
1909 0, /* biXPelsPerMeter */
1910 0, /* biYPelsPerMeter */
1911 0, /* biClrUsed */
1912 0, /* biClrImportant */
1914 void *bits;
1915 XFORM xform;
1916 BOOL ret;
1918 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1919 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1921 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1922 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1923 ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
1924 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1925 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1926 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1927 DIB_RGB_COLORS, &bits, NULL, 0);
1928 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1930 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1931 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1933 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1934 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1935 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1937 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1938 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1939 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1940 ok( ret, "BitBlt(WHITENESS) failed\n" );
1942 ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
1943 ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
1944 ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
1945 ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
1946 ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
1947 memset(&xform, 0, sizeof(xform));
1948 xform.eM11 = 0.5;
1949 xform.eM22 = 1.0;
1950 ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
1952 ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
1953 ok( ret, "StretchBlt(SRCCOPY) failed\n" );
1955 hMetafile = CloseEnhMetaFile(hdcMetafile);
1956 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1958 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1959 "emf_BitBlt", FALSE) != 0)
1961 dump_emf_bits(hMetafile, "emf_BitBlt");
1962 dump_emf_records(hMetafile, "emf_BitBlt");
1965 SelectObject(hdcBitmap, hOldBitmap);
1966 DeleteObject(hBitmap);
1967 DeleteDC(hdcBitmap);
1968 DeleteDC(hdcDisplay);
1969 #undef BMP_DIM
1972 static void test_emf_DCBrush(void)
1974 HDC hdcMetafile;
1975 HENHMETAFILE hMetafile;
1976 HBRUSH hBrush;
1977 HPEN hPen;
1978 BOOL ret;
1979 COLORREF color;
1981 if (!pSetDCBrushColor || !pSetDCPenColor)
1983 win_skip( "SetDCBrush/PenColor not supported\n" );
1984 return;
1987 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1988 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1990 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1991 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1993 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1994 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1996 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1997 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1999 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2000 ok( color == 0, "SetDCPenColor returned %x\n", color );
2002 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2004 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2005 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
2007 hMetafile = CloseEnhMetaFile(hdcMetafile);
2008 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
2010 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
2011 "emf_DC_Brush", FALSE ) != 0)
2013 dump_emf_bits(hMetafile, "emf_DC_Brush");
2014 dump_emf_records(hMetafile, "emf_DC_Brush");
2016 ret = DeleteEnhMetaFile(hMetafile);
2017 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2018 ret = DeleteObject(hBrush);
2019 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2020 ret = DeleteObject(hPen);
2021 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
2024 /* Test a blank metafile. May be used as a template for new tests. */
2026 static void test_mf_Blank(void)
2028 HDC hdcMetafile;
2029 HMETAFILE hMetafile;
2030 INT caps;
2031 BOOL ret;
2032 INT type;
2034 hdcMetafile = CreateMetaFileA(NULL);
2035 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2036 trace("hdcMetafile %p\n", hdcMetafile);
2038 /* Tests on metafile initialization */
2039 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
2040 ok (caps == DT_METAFILE,
2041 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
2043 hMetafile = CloseMetaFile(hdcMetafile);
2044 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2045 type = GetObjectType(hMetafile);
2046 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2047 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2049 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2050 "mf_blank") != 0)
2052 dump_mf_bits(hMetafile, "mf_Blank");
2053 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2056 ret = DeleteMetaFile(hMetafile);
2057 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2060 static void test_CopyMetaFile(void)
2062 HDC hdcMetafile;
2063 HMETAFILE hMetafile, hmf_copy;
2064 BOOL ret;
2065 char temp_path[MAX_PATH];
2066 char mf_name[MAX_PATH];
2067 INT type;
2069 hdcMetafile = CreateMetaFileA(NULL);
2070 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2071 trace("hdcMetafile %p\n", hdcMetafile);
2073 hMetafile = CloseMetaFile(hdcMetafile);
2074 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2075 type = GetObjectType(hMetafile);
2076 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2078 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2079 "mf_blank") != 0)
2081 dump_mf_bits(hMetafile, "mf_Blank");
2082 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2085 GetTempPathA(MAX_PATH, temp_path);
2086 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
2088 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
2089 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
2091 type = GetObjectType(hmf_copy);
2092 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
2094 ret = DeleteMetaFile(hMetafile);
2095 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2097 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
2099 dump_mf_bits(hmf_copy, "mf_Blank");
2100 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
2103 ret = DeleteMetaFile(hmf_copy);
2104 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
2106 DeleteFileA(mf_name);
2109 static void test_SetMetaFileBits(void)
2111 HMETAFILE hmf;
2112 INT type;
2113 BOOL ret;
2114 BYTE buf[256];
2115 METAHEADER *mh;
2117 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2118 trace("hmf %p\n", hmf);
2119 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2120 type = GetObjectType(hmf);
2121 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
2123 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2125 dump_mf_bits(hmf, "mf_Graphics");
2126 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2129 ret = DeleteMetaFile(hmf);
2130 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2132 /* NULL data crashes XP SP1 */
2133 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2135 /* Now with zero size */
2136 SetLastError(0xdeadbeef);
2137 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2138 trace("hmf %p\n", hmf);
2139 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2140 ok(GetLastError() == ERROR_INVALID_DATA ||
2141 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2142 "wrong error %d\n", GetLastError());
2144 /* Now with odd size */
2145 SetLastError(0xdeadbeef);
2146 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2147 trace("hmf %p\n", hmf);
2148 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2149 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2151 /* Now with zeroed out header fields */
2152 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2153 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2154 mh = (METAHEADER *)buf;
2155 /* corruption of any of the below fields leads to a failure */
2156 mh->mtType = 0;
2157 mh->mtVersion = 0;
2158 mh->mtHeaderSize = 0;
2159 SetLastError(0xdeadbeef);
2160 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2161 trace("hmf %p\n", hmf);
2162 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2163 ok(GetLastError() == ERROR_INVALID_DATA ||
2164 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2165 "wrong error %d\n", GetLastError());
2167 /* Now with corrupted mtSize field */
2168 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2169 mh = (METAHEADER *)buf;
2170 /* corruption of mtSize doesn't lead to a failure */
2171 mh->mtSize *= 2;
2172 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2173 trace("hmf %p\n", hmf);
2174 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2176 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2178 dump_mf_bits(hmf, "mf_Graphics");
2179 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2182 ret = DeleteMetaFile(hmf);
2183 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2185 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2186 /* Now with zeroed out mtSize field */
2187 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2188 mh = (METAHEADER *)buf;
2189 /* zeroing mtSize doesn't lead to a failure */
2190 mh->mtSize = 0;
2191 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2192 trace("hmf %p\n", hmf);
2193 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2195 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2197 dump_mf_bits(hmf, "mf_Graphics");
2198 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2201 ret = DeleteMetaFile(hmf);
2202 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2203 #endif
2206 /* Simple APIs from mfdrv/graphics.c
2209 static void test_mf_Graphics(void)
2211 HDC hdcMetafile;
2212 HMETAFILE hMetafile;
2213 POINT oldpoint;
2214 BOOL ret;
2216 hdcMetafile = CreateMetaFileA(NULL);
2217 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2218 trace("hdcMetafile %p\n", hdcMetafile);
2220 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2221 ok( ret, "MoveToEx error %d.\n", GetLastError());
2222 ret = LineTo(hdcMetafile, 2, 2);
2223 ok( ret, "LineTo error %d.\n", GetLastError());
2224 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2225 ok( ret, "MoveToEx error %d.\n", GetLastError());
2227 /* oldpoint gets garbage under Win XP, so the following test would
2228 * work under Wine but fails under Windows:
2230 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2231 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2232 * oldpoint.x, oldpoint.y);
2235 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2236 ok( ret, "Ellipse error %d.\n", GetLastError());
2238 hMetafile = CloseMetaFile(hdcMetafile);
2239 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2240 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2242 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2243 "mf_Graphics") != 0)
2245 dump_mf_bits(hMetafile, "mf_Graphics");
2246 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2249 ret = DeleteMetaFile(hMetafile);
2250 ok( ret, "DeleteMetaFile(%p) error %d\n",
2251 hMetafile, GetLastError());
2254 static void test_mf_PatternBrush(void)
2256 HDC hdcMetafile;
2257 HMETAFILE hMetafile;
2258 LOGBRUSH *orig_lb;
2259 HBRUSH hBrush;
2260 BOOL ret;
2262 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2264 orig_lb->lbStyle = BS_PATTERN;
2265 orig_lb->lbColor = RGB(0, 0, 0);
2266 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2267 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2269 hBrush = CreateBrushIndirect (orig_lb);
2270 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2272 hdcMetafile = CreateMetaFileA(NULL);
2273 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2274 trace("hdcMetafile %p\n", hdcMetafile);
2276 hBrush = SelectObject(hdcMetafile, hBrush);
2277 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2279 hMetafile = CloseMetaFile(hdcMetafile);
2280 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2281 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2283 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2284 "mf_Pattern_Brush") != 0)
2286 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2287 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2290 ret = DeleteMetaFile(hMetafile);
2291 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2292 ret = DeleteObject(hBrush);
2293 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2294 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2295 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2296 GetLastError());
2297 HeapFree (GetProcessHeap(), 0, orig_lb);
2300 static void test_mf_DCBrush(void)
2302 HDC hdcMetafile;
2303 HMETAFILE hMetafile;
2304 HBRUSH hBrush;
2305 HPEN hPen;
2306 BOOL ret;
2307 COLORREF color;
2309 if (!pSetDCBrushColor || !pSetDCPenColor)
2311 win_skip( "SetDCBrush/PenColor not supported\n" );
2312 return;
2315 hdcMetafile = CreateMetaFileA(NULL);
2316 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2318 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2319 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2321 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2322 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2324 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2325 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2327 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2328 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2330 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2332 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2333 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2335 hMetafile = CloseMetaFile(hdcMetafile);
2336 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2338 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2340 dump_mf_bits(hMetafile, "mf_DCBrush");
2341 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2343 ret = DeleteMetaFile(hMetafile);
2344 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2347 static void test_mf_ExtTextOut_on_path(void)
2349 HDC hdcMetafile;
2350 HMETAFILE hMetafile;
2351 BOOL ret;
2352 static const INT dx[4] = { 3, 5, 8, 12 };
2354 hdcMetafile = CreateMetaFileA(NULL);
2355 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2356 trace("hdcMetafile %p\n", hdcMetafile);
2358 ret = BeginPath(hdcMetafile);
2359 ok(!ret, "BeginPath on metafile DC should fail\n");
2361 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2362 ok(ret, "ExtTextOut error %d\n", GetLastError());
2364 ret = EndPath(hdcMetafile);
2365 ok(!ret, "EndPath on metafile DC should fail\n");
2367 hMetafile = CloseMetaFile(hdcMetafile);
2368 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2370 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2371 "mf_TextOut_on_path") != 0)
2373 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2374 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2377 ret = DeleteMetaFile(hMetafile);
2378 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2381 static void test_emf_ExtTextOut_on_path(void)
2383 HWND hwnd;
2384 HDC hdcDisplay, hdcMetafile;
2385 HENHMETAFILE hMetafile;
2386 BOOL ret;
2387 static const INT dx[4] = { 3, 5, 8, 12 };
2389 /* Win9x doesn't play EMFs on invisible windows */
2390 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2391 0, 0, 200, 200, 0, 0, 0, NULL);
2392 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2394 hdcDisplay = GetDC(hwnd);
2395 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2397 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2398 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2400 ret = BeginPath(hdcMetafile);
2401 ok(ret, "BeginPath error %d\n", GetLastError());
2403 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2404 todo_wine ok(ret, "ExtTextOut error %d\n", GetLastError());
2406 ret = EndPath(hdcMetafile);
2407 ok(ret, "EndPath error %d\n", GetLastError());
2409 hMetafile = CloseEnhMetaFile(hdcMetafile);
2410 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2412 /* this doesn't succeed yet: EMF has correct size, all EMF records
2413 * are there, but their contents don't match for different reasons.
2415 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2416 "emf_TextOut_on_path", FALSE) != 0)
2418 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2419 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2422 ret = DeleteEnhMetaFile(hMetafile);
2423 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2424 ret = ReleaseDC(hwnd, hdcDisplay);
2425 ok(ret, "ReleaseDC error %d\n", GetLastError());
2426 DestroyWindow(hwnd);
2429 static const unsigned char EMF_CLIPPING[] =
2431 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2433 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2435 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2436 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2437 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2438 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2440 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2441 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2443 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2444 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2445 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2446 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2447 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2448 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2449 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2450 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2451 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2452 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2453 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2454 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2455 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2456 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2459 static void translate( POINT *pt, UINT count, const XFORM *xform )
2461 while (count--)
2463 FLOAT x = (FLOAT)pt->x;
2464 FLOAT y = (FLOAT)pt->y;
2465 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2466 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2467 pt++;
2471 /* Compare rectangles allowing rounding errors */
2472 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2474 return abs(rc1->left - rc2->left) <= 1 &&
2475 abs(rc1->top - rc2->top) <= 1 &&
2476 abs(rc1->right - rc2->right) <= 1 &&
2477 abs(rc1->bottom - rc2->bottom) <= 1;
2480 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2481 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2483 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2485 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2486 union _rgn
2488 RGNDATA data;
2489 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2491 const union _rgn *rgn1;
2492 union _rgn rgn2;
2493 RECT rect, rc_transformed;
2494 const RECT *rc = (const RECT *)param;
2495 HRGN hrgn;
2496 XFORM xform;
2497 INT ret;
2498 BOOL is_win9x;
2500 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2501 clip->cbRgnData, clip->iMode);
2503 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2504 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2505 "too small data block: %u bytes\n", clip->cbRgnData);
2506 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2507 return 0;
2509 rgn1 = (const union _rgn *)clip->RgnData;
2511 trace("size %u, type %u, count %u, rgn size %u, bound %s\n",
2512 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2513 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2514 wine_dbgstr_rect(&rgn1->data.rdh.rcBound));
2516 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2518 rect = *(const RECT *)rgn1->data.Buffer;
2519 trace("rect %s\n", wine_dbgstr_rect(&rect));
2520 ok(EqualRect(&rect, rc), "rects don't match\n");
2522 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2523 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2524 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2525 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2526 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2527 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2529 hrgn = CreateRectRgn(0, 0, 0, 0);
2531 memset(&xform, 0, sizeof(xform));
2532 SetLastError(0xdeadbeef);
2533 ret = GetWorldTransform(hdc, &xform);
2534 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2535 if (!is_win9x)
2536 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2538 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2540 ret = GetClipRgn(hdc, hrgn);
2541 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2543 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2545 ret = GetClipRgn(hdc, hrgn);
2546 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2548 /* Win9x returns empty clipping region */
2549 if (is_win9x) return 1;
2551 ret = GetRegionData(hrgn, 0, NULL);
2552 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2554 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2555 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2557 trace("size %u, type %u, count %u, rgn size %u, bound %s\n", rgn2.data.rdh.dwSize,
2558 rgn2.data.rdh.iType, rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2559 wine_dbgstr_rect(&rgn2.data.rdh.rcBound));
2561 rect = rgn2.data.rdh.rcBound;
2562 rc_transformed = *rc;
2563 translate((POINT *)&rc_transformed, 2, &xform);
2564 trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed));
2565 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2567 rect = *(const RECT *)rgn2.data.Buffer;
2568 trace("rect %s\n", wine_dbgstr_rect(&rect));
2569 rc_transformed = *rc;
2570 translate((POINT *)&rc_transformed, 2, &xform);
2571 trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed));
2572 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2574 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2575 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2576 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2577 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2578 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2579 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2581 DeleteObject(hrgn);
2583 return 1;
2586 static void test_emf_clipping(void)
2588 static const RECT rc = { 0, 0, 100, 100 };
2589 RECT rc_clip = { 100, 100, 1024, 1024 };
2590 HWND hwnd;
2591 HDC hdc;
2592 HENHMETAFILE hemf;
2593 HRGN hrgn;
2594 INT ret;
2595 RECT rc_res, rc_sclip;
2597 SetLastError(0xdeadbeef);
2598 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2599 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2601 /* Need to write something to the emf, otherwise Windows won't play it back */
2602 LineTo(hdc, 1, 1);
2604 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2605 ret = SelectClipRgn(hdc, hrgn);
2606 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2608 SetLastError(0xdeadbeef);
2609 hemf = CloseEnhMetaFile(hdc);
2610 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2612 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2613 "emf_clipping", FALSE) != 0)
2615 dump_emf_bits(hemf, "emf_clipping");
2616 dump_emf_records(hemf, "emf_clipping");
2619 DeleteObject(hrgn);
2621 /* Win9x doesn't play EMFs on invisible windows */
2622 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2623 0, 0, 200, 200, 0, 0, 0, NULL);
2624 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2626 hdc = GetDC(hwnd);
2628 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2629 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2631 DeleteEnhMetaFile(hemf);
2632 ReleaseDC(hwnd, hdc);
2633 DestroyWindow(hwnd);
2635 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2637 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2638 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2639 SelectClipRgn(hdc, hrgn);
2640 SetRect(&rc_res, -1, -1, -1, -1);
2641 ret = GetClipBox(hdc, &rc_res);
2642 ok(ret == SIMPLEREGION, "got %d\n", ret);
2643 ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip),
2644 wine_dbgstr_rect(&rc_res));
2646 OffsetRect(&rc_sclip, -100, -100);
2647 ret = OffsetClipRgn(hdc, -100, -100);
2648 ok(ret == SIMPLEREGION, "got %d\n", ret);
2649 SetRect(&rc_res, -1, -1, -1, -1);
2650 ret = GetClipBox(hdc, &rc_res);
2651 ok(ret == SIMPLEREGION, "got %d\n", ret);
2652 ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip),
2653 wine_dbgstr_rect(&rc_res));
2655 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2656 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2657 if (ret == COMPLEXREGION)
2659 /* XP returns COMPLEXREGION although region contains only 1 rect */
2660 ret = GetClipRgn(hdc, hrgn);
2661 ok(ret == 1, "expected 1, got %d\n", ret);
2662 ret = rgn_rect_count(hrgn);
2663 ok(ret == 1, "expected 1, got %d\n", ret);
2665 SetRect(&rc_res, -1, -1, -1, -1);
2666 ret = GetClipBox(hdc, &rc_res);
2667 ok(ret == SIMPLEREGION, "got %d\n", ret);
2668 ok(EqualRect(&rc_res, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rc),
2669 wine_dbgstr_rect(&rc_res));
2671 SetRect(&rc_sclip, 0, 0, 100, 50);
2672 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2673 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2674 if (ret == COMPLEXREGION)
2676 /* XP returns COMPLEXREGION although region contains only 1 rect */
2677 ret = GetClipRgn(hdc, hrgn);
2678 ok(ret == 1, "expected 1, got %d\n", ret);
2679 ret = rgn_rect_count(hrgn);
2680 ok(ret == 1, "expected 1, got %d\n", ret);
2682 SetRect(&rc_res, -1, -1, -1, -1);
2683 ret = GetClipBox(hdc, &rc_res);
2684 ok(ret == SIMPLEREGION, "got %d\n", ret);
2685 ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip),
2686 wine_dbgstr_rect(&rc_res));
2688 hemf = CloseEnhMetaFile(hdc);
2689 DeleteEnhMetaFile(hemf);
2690 DeleteObject(hrgn);
2693 static const unsigned char MF_CLIP_BITS[] = {
2694 /* METAHEADER */
2695 0x01, 0x00, /* mtType */
2696 0x09, 0x00, /* mtHeaderSize */
2697 0x00, 0x03, /* mtVersion */
2698 0x32, 0x00, 0x00, 0x00, /* mtSize */
2699 0x01, 0x00, /* mtNoObjects */
2700 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2701 0x00, 0x00, /* reserved */
2703 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2704 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2705 0xff, 0x06, /* META_CREATEREGION */
2706 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2707 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2708 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2709 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2710 0x02, 0x00,
2712 /* METARECORD for SelectObject */
2713 0x04, 0x00, 0x00, 0x00,
2714 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2715 0x00, 0x00,
2717 /* METARECORD */
2718 0x04, 0x00, 0x00, 0x00,
2719 0xf0, 0x01, /* META_DELETEOBJECT */
2720 0x00, 0x00,
2722 /* METARECORD for MoveTo(1,0x30) */
2723 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2724 0x14, 0x02, /* META_MOVETO */
2725 0x30, 0x00, /* y */
2726 0x01, 0x00, /* x */
2728 /* METARECORD for LineTo(0x20, 0x30) */
2729 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2730 0x13, 0x02, /* META_LINETO */
2731 0x30, 0x00, /* y */
2732 0x20, 0x00, /* x */
2734 /* EOF */
2735 0x03, 0x00, 0x00, 0x00,
2736 0x00, 0x00
2739 static int clip_mf_enum_proc_seen_selectclipregion;
2740 static int clip_mf_enum_proc_seen_selectobject;
2742 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2743 METARECORD *mr, int n_objs, LPARAM param)
2745 switch (mr->rdFunction) {
2746 case META_SELECTCLIPREGION:
2747 clip_mf_enum_proc_seen_selectclipregion++;
2748 break;
2749 case META_SELECTOBJECT:
2750 clip_mf_enum_proc_seen_selectobject++;
2751 break;
2753 return 1;
2756 static void test_mf_clipping(void)
2758 /* left top right bottom */
2759 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2760 HWND hwnd;
2761 HDC hdc;
2762 HMETAFILE hmf;
2763 HRGN hrgn;
2764 INT ret;
2766 SetLastError(0xdeadbeef);
2767 hdc = CreateMetaFileA(NULL);
2768 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2770 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2771 ret = SelectClipRgn(hdc, hrgn);
2772 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2773 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2775 /* Draw a line that starts off left of the clip region and ends inside it */
2776 MoveToEx(hdc, 0x1, 0x30, NULL);
2777 LineTo(hdc, 0x20, 0x30);
2779 SetLastError(0xdeadbeef);
2780 hmf = CloseMetaFile(hdc);
2781 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2783 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2784 "mf_clipping") != 0)
2786 dump_mf_bits(hmf, "mf_clipping");
2789 DeleteObject(hrgn);
2791 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2792 0, 0, 200, 200, 0, 0, 0, NULL);
2793 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2795 hdc = GetDC(hwnd);
2797 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2798 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2800 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2801 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2802 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2803 ok(clip_mf_enum_proc_seen_selectobject == 1,
2804 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2806 DeleteMetaFile(hmf);
2807 ReleaseDC(hwnd, hdc);
2808 DestroyWindow(hwnd);
2811 static const unsigned char MF_PATH_BITS[] =
2813 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2814 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2815 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2816 0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2817 0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2818 0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2819 0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2820 0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2821 0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2822 0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2823 0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2826 static void test_mf_GetPath(void)
2828 HDC hdc;
2829 HMETAFILE hmf;
2830 BOOL ret;
2831 int size;
2833 SetLastError(0xdeadbeef);
2834 hdc = CreateMetaFileA(NULL);
2835 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2837 BeginPath(hdc);
2838 ret = MoveToEx(hdc, 50, 50, NULL);
2839 ok( ret, "MoveToEx error %d.\n", GetLastError());
2840 ret = LineTo(hdc, 50, 150);
2841 ok( ret, "LineTo error %d.\n", GetLastError());
2842 ret = LineTo(hdc, 150, 150);
2843 ok( ret, "LineTo error %d.\n", GetLastError());
2844 ret = LineTo(hdc, 150, 50);
2845 ok( ret, "LineTo error %d.\n", GetLastError());
2846 ret = LineTo(hdc, 50, 50);
2847 ok( ret, "LineTo error %d.\n", GetLastError());
2848 Rectangle(hdc, 10, 10, 20, 20);
2849 EndPath(hdc);
2851 size = GetPath(hdc, NULL, NULL, 0);
2852 ok( size == -1, "GetPath returned %d.\n", size);
2854 hmf = CloseMetaFile(hdc);
2855 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2857 if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
2859 dump_mf_bits(hmf, "mf_GetPath");
2860 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2863 ret = DeleteMetaFile(hmf);
2864 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2867 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2869 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2870 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2871 /* When using MM_TEXT Win9x does not update the mapping mode
2872 * until a record is played which actually outputs something */
2873 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2874 LPtoDP(hdc, mapping, 2);
2875 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2876 lpEMFR->iType, lpEMFR->nSize,
2877 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2879 if (lpEMFR->iType == EMR_LINETO)
2881 INT x0, y0, x1, y1;
2882 if (!lpMFP || lpMFP->mm == MM_TEXT)
2884 x0 = 0;
2885 y0 = 0;
2886 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2887 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2889 else
2891 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2893 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2894 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2895 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2896 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2898 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2899 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2900 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2901 x0, y0, x1, y1);
2903 return TRUE;
2906 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2908 HDC hdcMf;
2909 HMETAFILE hmf;
2910 HENHMETAFILE hemf;
2911 BOOL ret;
2912 UINT size;
2913 LPBYTE pBits;
2915 hdcMf = CreateMetaFileA(NULL);
2916 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2917 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2918 ok(ret, "LineTo failed with error %d\n", GetLastError());
2919 hmf = CloseMetaFile(hdcMf);
2920 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2922 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2924 dump_mf_bits(hmf, "mf_LineTo");
2925 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2928 size = GetMetaFileBitsEx(hmf, 0, NULL);
2929 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2930 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2931 GetMetaFileBitsEx(hmf, size, pBits);
2932 DeleteMetaFile(hmf);
2933 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2934 HeapFree(GetProcessHeap(), 0, pBits);
2935 return hemf;
2938 static void test_mf_conversions(void)
2940 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2942 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2943 HENHMETAFILE hemf;
2944 METAFILEPICT mfp;
2945 RECT rect = { 0, 0, 100, 100 };
2946 mfp.mm = MM_ANISOTROPIC;
2947 mfp.xExt = 100;
2948 mfp.yExt = 100;
2949 mfp.hMF = NULL;
2950 hemf = create_converted_emf(&mfp);
2952 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2953 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2955 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2956 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2959 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2961 DeleteEnhMetaFile(hemf);
2962 DeleteDC(hdcOffscreen);
2965 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2967 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2968 HENHMETAFILE hemf;
2969 METAFILEPICT mfp;
2970 RECT rect = { 0, 0, 100, 100 };
2971 mfp.mm = MM_TEXT;
2972 mfp.xExt = 0;
2973 mfp.yExt = 0;
2974 mfp.hMF = NULL;
2975 hemf = create_converted_emf(&mfp);
2977 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2978 "emf_LineTo MM_TEXT", TRUE) != 0)
2980 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2981 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2984 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2986 DeleteEnhMetaFile(hemf);
2987 DeleteDC(hdcOffscreen);
2990 trace("Testing MF->EMF conversion (NULL mfp)\n");
2992 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2993 HENHMETAFILE hemf;
2994 RECT rect = { 0, 0, 100, 100 };
2995 hemf = create_converted_emf(NULL);
2997 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2998 "emf_LineTo NULL", TRUE) != 0)
3000 dump_emf_bits(hemf, "emf_LineTo NULL");
3001 dump_emf_records(hemf, "emf_LineTo NULL");
3004 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
3006 DeleteEnhMetaFile(hemf);
3007 DeleteDC(hdcOffscreen);
3011 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3012 LONG mm, LONG xExt, LONG yExt,
3013 RECTL * rclBounds, RECTL * rclFrame)
3015 METAFILEPICT mfp;
3016 METAFILEPICT * mfpPtr = NULL;
3017 HENHMETAFILE emf;
3018 ENHMETAHEADER header;
3019 UINT res;
3021 if (!mfpIsNull)
3023 mfp.mm = mm;
3024 mfp.xExt = xExt;
3025 mfp.yExt = yExt;
3026 mfpPtr = &mfp;
3029 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
3030 ok(emf != NULL, "SetWinMetaFileBits failed\n");
3031 if (!emf) return FALSE;
3032 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
3033 ok(res != 0, "GetEnhMetaHeader failed\n");
3034 DeleteEnhMetaFile(emf);
3035 if (!res) return FALSE;
3037 *rclBounds = header.rclBounds;
3038 *rclFrame = header.rclFrame;
3039 return TRUE;
3042 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3043 LONG mm, LONG xExt, LONG yExt,
3044 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
3046 RECTL rclBounds, rclFrame;
3048 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
3050 const char * msg;
3051 char buf[64];
3053 if (mfpIsNull)
3055 msg = "mfp == NULL";
3057 else
3059 const char * mm_str;
3060 switch (mm)
3062 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
3063 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
3064 default: mm_str = "Unexpected";
3066 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
3067 msg = buf;
3070 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
3071 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
3072 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
3073 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
3074 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
3075 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
3076 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
3077 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
3081 static void test_SetWinMetaFileBits(void)
3083 HMETAFILE wmf;
3084 HDC wmfDC;
3085 BYTE * buffer;
3086 UINT buffer_size;
3087 RECT rect;
3088 UINT res;
3089 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
3090 RECTL rclBoundsIsotropic, rclFrameIsotropic;
3091 RECTL rclBounds, rclFrame;
3092 HDC dc;
3093 LONG diffx, diffy;
3095 wmfDC = CreateMetaFileA(NULL);
3096 ok(wmfDC != NULL, "CreateMetaFile failed\n");
3097 if (!wmfDC) return;
3099 SetWindowExtEx(wmfDC, 100, 100, NULL);
3100 SetRect(&rect, 0, 0, 50, 50);
3101 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
3102 wmf = CloseMetaFile(wmfDC);
3103 ok(wmf != NULL, "Metafile creation failed\n");
3104 if (!wmf) return;
3106 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
3107 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
3108 if (buffer_size == 0)
3110 DeleteMetaFile(wmf);
3111 return;
3114 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
3115 ok(buffer != NULL, "HeapAlloc failed\n");
3116 if (!buffer)
3118 DeleteMetaFile(wmf);
3119 return;
3122 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
3123 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3124 DeleteMetaFile(wmf);
3125 if (res != buffer_size)
3127 HeapFree(GetProcessHeap(), 0, buffer);
3128 return;
3131 /* Get the reference bounds and frame */
3132 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3133 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3135 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
3136 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
3137 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3139 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3140 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3141 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
3142 if (diffx < 0) diffx = -diffx;
3143 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3145 dc = CreateCompatibleDC(NULL);
3147 /* Allow 1 mm difference (rounding errors) */
3148 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
3149 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
3150 if (diffx < 0) diffx = -diffx;
3151 if (diffy < 0) diffy = -diffy;
3152 todo_wine
3154 ok(diffx <= 1 && diffy <= 1,
3155 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3156 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
3159 /* Allow 1 mm difference (rounding errors) */
3160 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
3161 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
3162 if (diffx < 0) diffx = -diffx;
3163 if (diffy < 0) diffy = -diffy;
3164 todo_wine
3166 ok(diffx <= 1 && diffy <= 1,
3167 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3168 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
3170 DeleteDC(dc);
3172 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3173 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3175 /* If xExt or yExt is zero or negative, the whole device surface is used */
3176 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3177 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3178 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3179 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3180 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3181 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3182 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3183 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3184 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3185 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3186 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3187 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3189 /* MSDN says that negative xExt and yExt values specify a ratio.
3190 Check that this is wrong and the whole device surface is used */
3191 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3192 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3194 /* Ordinary conversions */
3196 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3198 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3199 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3200 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3201 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3204 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3206 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3207 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3208 ok(rclBounds.left == 0 && rclBounds.top == 0,
3209 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3211 /* Wine has a rounding error */
3212 diffx = rclBounds.right - rclBounds.bottom;
3213 if (diffx < 0) diffx = -diffx;
3214 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3217 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3219 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3220 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3223 HeapFree(GetProcessHeap(), 0, buffer);
3226 static BOOL near_match(int x, int y)
3228 int epsilon = min(abs(x), abs(y));
3230 epsilon = max(epsilon/100, 2);
3232 if(x < y - epsilon || x > y + epsilon) return FALSE;
3233 return TRUE;
3236 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3238 HENHMETAFILE emf, emf2;
3239 HDC display_dc, emf_dc;
3240 ENHMETAHEADER *enh_header, *enh2_header;
3241 UINT size, emf_size, i, emf2_size;
3242 WORD check = 0;
3243 DWORD rec_num = 0;
3244 METAHEADER *mh = NULL;
3245 METARECORD *rec;
3246 INT horz_res, vert_res, horz_size, vert_size;
3247 INT curve_caps, line_caps, poly_caps;
3248 METAFILEPICT mfp;
3250 display_dc = GetDC(NULL);
3251 ok(display_dc != NULL, "display_dc is NULL\n");
3253 horz_res = GetDeviceCaps(display_dc, HORZRES);
3254 vert_res = GetDeviceCaps(display_dc, VERTRES);
3255 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3256 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3258 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3259 ok(emf_dc != NULL, "emf_dc is NULL\n");
3261 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3262 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3264 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3265 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3267 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3268 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3270 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3271 Rectangle(emf_dc, 0, 0, 1000, 20);
3272 emf = CloseEnhMetaFile(emf_dc);
3273 ok(emf != NULL, "emf is NULL\n");
3275 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3276 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3277 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3278 DeleteEnhMetaFile(emf);
3279 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3280 have different resolutions */
3281 enh_header->szlDevice.cx *= scale;
3282 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3283 ok(emf != NULL, "emf is NULL\n");
3284 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3286 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3287 ok(size ||
3288 broken(size == 0), /* some versions of winxp fail for some reason */
3289 "GetWinMetaFileBits returns 0\n");
3290 if(!size) goto end;
3291 mh = HeapAlloc(GetProcessHeap(), 0, size);
3292 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3294 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3295 ok(check == 0, "check %04x\n", check);
3297 rec = (METARECORD*)(mh + 1);
3299 while(rec->rdSize && rec->rdFunction)
3301 const DWORD chunk_size = 0x2000;
3302 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3304 if(rec_num < mfcomment_chunks)
3306 DWORD this_chunk_size = chunk_size;
3308 if(rec_num == mfcomment_chunks - 1)
3309 this_chunk_size = emf_size - rec_num * chunk_size;
3311 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3312 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3313 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3314 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3315 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3316 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3317 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3318 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3319 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3320 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3321 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3322 /* parm[8] is the checksum, tested above */
3323 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3324 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3325 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3326 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3327 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3328 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3329 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3330 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 */
3331 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3332 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3335 else if(rec_num == mfcomment_chunks)
3337 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3338 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3340 else if(rec_num == mfcomment_chunks + 1)
3342 POINT pt;
3343 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3344 switch(mode)
3346 case MM_TEXT:
3347 case MM_ISOTROPIC:
3348 case MM_ANISOTROPIC:
3349 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3350 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3351 break;
3352 case MM_LOMETRIC:
3353 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3354 pt.x = MulDiv( rc->left, 1, 10);
3355 break;
3356 case MM_HIMETRIC:
3357 pt.y = -rc->top + 1;
3358 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3359 break;
3360 case MM_LOENGLISH:
3361 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3362 pt.x = MulDiv( rc->left, 10, 254);
3363 break;
3364 case MM_HIENGLISH:
3365 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3366 pt.x = MulDiv( rc->left, 100, 254);
3367 break;
3368 case MM_TWIPS:
3369 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3370 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3371 break;
3372 default:
3373 pt.x = pt.y = 0;
3375 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3376 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3378 if(rec_num == mfcomment_chunks + 2)
3380 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3381 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3382 "got %d\n", (short)rec->rdParm[0]);
3383 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3384 "got %d\n", (short)rec->rdParm[1]);
3387 rec_num++;
3388 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3391 /* Show that we get the original back when we do the reverse conversion.
3392 mfp is ignored in this case. */
3393 mfp.mm = MM_ISOTROPIC;
3394 mfp.xExt = 0xcafe;
3395 mfp.yExt = 0xbeef;
3396 emf2 = SetWinMetaFileBits( size, (BYTE*)mh, NULL, &mfp );
3397 ok( !!emf2, "got NULL\n" );
3398 emf2_size = GetEnhMetaFileBits( emf2, 0, NULL );
3399 enh2_header = HeapAlloc( GetProcessHeap(), 0, emf2_size );
3400 emf2_size = GetEnhMetaFileBits( emf2, emf2_size, (BYTE*)enh2_header );
3401 ok( emf_size == emf2_size, "%d %d\n", emf_size, emf2_size );
3402 ok( !memcmp( enh_header, enh2_header, emf_size ), "mismatch\n" );
3403 HeapFree( GetProcessHeap(), 0, enh2_header );
3404 DeleteEnhMetaFile( emf2 );
3406 end:
3407 HeapFree(GetProcessHeap(), 0, mh);
3408 HeapFree(GetProcessHeap(), 0, enh_header);
3409 DeleteEnhMetaFile(emf);
3411 ReleaseDC(NULL, display_dc);
3414 static void test_GetWinMetaFileBits(void)
3416 UINT mode;
3417 RECT frames[] =
3419 { 1000, 2000, 3000, 6000},
3420 {-1000, 2000, 3000, 6000},
3421 { 1000, -2000, 3000, 6000},
3422 { 1005, 2005, 3000, 6000},
3423 {-1005, -2005, 3000, 6000},
3424 {-1005, -2010, 3000, 6000},
3425 {-1005, 2010, 3000, 6000},
3426 { 0, 0, 1, 1},
3427 { -1, -1, 1, 1},
3428 { 0, 0, 0, 0}
3431 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3433 RECT *rc;
3434 for(rc = frames; rc->right - rc->left > 0; rc++)
3436 getwinmetafilebits(mode, 1, rc);
3437 getwinmetafilebits(mode, 2, rc);
3442 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3443 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3444 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3446 static void test_gdiis(void)
3448 RECT rect = {0,0,100,100};
3449 HDC hdc, hemfDC, hmfDC;
3450 HENHMETAFILE hemf;
3451 HMODULE hgdi32;
3453 /* resolve all the functions */
3454 hgdi32 = GetModuleHandleA("gdi32.dll");
3455 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3456 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3457 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3459 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3461 win_skip("Needed GdiIs* functions are not available\n");
3462 return;
3465 /* try with nothing */
3466 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3467 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3468 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3470 /* try with a metafile */
3471 hmfDC = CreateMetaFileA(NULL);
3472 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3473 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3474 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3475 DeleteMetaFile(CloseMetaFile(hmfDC));
3477 /* try with an enhanced metafile */
3478 hdc = GetDC(NULL);
3479 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3480 ok(hemfDC != NULL, "failed to create emf\n");
3482 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3483 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3484 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3486 hemf = CloseEnhMetaFile(hemfDC);
3487 ok(hemf != NULL, "failed to close EMF\n");
3488 DeleteEnhMetaFile(hemf);
3489 ReleaseDC(NULL,hdc);
3492 static void test_SetEnhMetaFileBits(void)
3494 BYTE data[256];
3495 HENHMETAFILE hemf;
3496 ENHMETAHEADER *emh;
3498 memset(data, 0xAA, sizeof(data));
3499 SetLastError(0xdeadbeef);
3500 hemf = SetEnhMetaFileBits(sizeof(data), data);
3501 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3502 ok(GetLastError() == ERROR_INVALID_DATA ||
3503 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3504 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3506 emh = (ENHMETAHEADER *)data;
3507 memset(emh, 0, sizeof(*emh));
3509 emh->iType = EMR_HEADER;
3510 emh->nSize = sizeof(*emh);
3511 emh->dSignature = ENHMETA_SIGNATURE;
3512 /* emh->nVersion = 0x10000; XP doesn't care about version */
3513 emh->nBytes = sizeof(*emh);
3514 /* emh->nRecords = 1; XP doesn't care about records */
3515 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3517 SetLastError(0xdeadbeef);
3518 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3519 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3520 DeleteEnhMetaFile(hemf);
3522 /* XP refuses to load unaligned EMF */
3523 emh->nBytes++;
3524 SetLastError(0xdeadbeef);
3525 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3526 ok(!hemf ||
3527 broken(hemf != NULL), /* Win9x, WinMe */
3528 "SetEnhMetaFileBits should fail\n");
3529 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3530 DeleteEnhMetaFile(hemf);
3532 emh->dSignature = 0;
3533 emh->nBytes--;
3534 SetLastError(0xdeadbeef);
3535 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3536 ok(!hemf ||
3537 broken(hemf != NULL), /* Win9x, WinMe */
3538 "SetEnhMetaFileBits should fail\n");
3539 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3540 DeleteEnhMetaFile(hemf);
3543 static void test_emf_polybezier(void)
3545 HDC hdcMetafile;
3546 HENHMETAFILE hemf;
3547 POINT pts[4];
3548 BOOL ret;
3550 SetLastError(0xdeadbeef);
3551 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3552 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3554 pts[0].x = pts[0].y = 10;
3555 pts[1].x = pts[1].y = 20;
3556 pts[2].x = pts[2].y = 15;
3557 pts[3].x = pts[3].y = 25;
3558 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3559 ok( ret, "PolyBezierTo failed\n" );
3560 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3561 ok( ret, "PolyBezier failed\n" );
3563 pts[0].x = pts[0].y = 32769;
3564 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3565 ok( ret, "PolyBezier failed\n" );
3566 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3567 ok( ret, "PolyBezierTo failed\n" );
3569 hemf = CloseEnhMetaFile(hdcMetafile);
3570 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3572 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3573 "emf_Bezier", FALSE) != 0)
3575 dump_emf_bits(hemf, "emf_Bezier");
3576 dump_emf_records(hemf, "emf_Bezier");
3579 DeleteEnhMetaFile(hemf);
3582 static const unsigned char EMF_PATH_BITS[] =
3584 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3585 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3586 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3587 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
3588 0x70, 0x17, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00,
3589 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3590 0xf8, 0x02, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3591 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3593 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3594 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3596 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3597 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3598 0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3599 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3600 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3601 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3602 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3603 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3604 0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3605 0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3606 0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3607 0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3608 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3609 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3610 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3611 0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
3612 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3613 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3614 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3615 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3616 0x15, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
3617 0x28, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3618 0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3619 0x1a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
3620 0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3621 0x17, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
3622 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3623 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3624 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3625 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3626 0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
3627 0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3628 0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3629 0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3630 0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3631 0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
3632 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3633 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3634 0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3635 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3636 0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3637 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3638 0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
3639 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3640 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3641 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
3642 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3643 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3644 0x59, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3646 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3647 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
3648 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00,
3649 0x14, 0x00, 0x14, 0x00, 0x5a, 0x00, 0x00, 0x00,
3650 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3651 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3652 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
3653 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3654 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
3655 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00,
3656 0x14, 0x00, 0x14, 0x00, 0x5c, 0x00, 0x00, 0x00,
3657 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3658 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3659 0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00,
3660 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3661 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3662 0x1e, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x14, 0x00,
3663 0x14, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x14, 0x00,
3664 0x14, 0x00, 0x0a, 0x00, 0x06, 0x02, 0x04, 0x04,
3665 0x04, 0x02, 0x03, 0x06, 0x02, 0x00, 0x00, 0x00,
3666 0x29, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
3667 0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3668 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x42,
3669 0x00, 0x00, 0x34, 0x43, 0x3c, 0x00, 0x00, 0x00,
3670 0x08, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
3671 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3672 0x0a, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3673 0x96, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
3674 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3675 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3676 0xff, 0xff, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00,
3677 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3678 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3681 static const unsigned char EMF_EMPTY_PATH_BITS[] =
3683 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3685 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3687 0xd8, 0xff, 0xff, 0xff, 0xd8, 0xff, 0xff, 0xff,
3688 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3689 0xc8, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
3690 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3692 0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3693 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3695 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3696 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3697 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
3698 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
3699 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3700 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3701 0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
3702 0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
3703 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
3704 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
3705 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3706 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3707 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3710 static void test_emf_paths(void)
3712 POINT pts[9] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}, {30, 30}, {40, 20}, {20, 30}, {20, 20}, {20, 10}};
3713 DWORD counts[2] = {2, 2};
3714 BYTE types[9] = { PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO,
3715 PT_LINETO | PT_CLOSEFIGURE, PT_MOVETO, PT_LINETO };
3716 HDC hdcMetafile;
3717 HENHMETAFILE hemf;
3718 BOOL ret;
3719 int size;
3721 SetLastError(0xdeadbeef);
3722 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3723 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3725 BeginPath(hdcMetafile);
3726 ret = MoveToEx(hdcMetafile, 50, 50, NULL);
3727 ok( ret, "MoveToEx error %d.\n", GetLastError());
3728 ret = LineTo(hdcMetafile, 50, 150);
3729 ok( ret, "LineTo error %d.\n", GetLastError());
3730 ret = LineTo(hdcMetafile, 150, 150);
3731 ok( ret, "LineTo error %d.\n", GetLastError());
3732 ret = LineTo(hdcMetafile, 150, 50);
3733 ok( ret, "LineTo error %d.\n", GetLastError());
3734 ret = LineTo(hdcMetafile, 50, 50);
3735 ok( ret, "LineTo error %d.\n", GetLastError());
3736 Rectangle(hdcMetafile, 10, 10, 20, 20);
3737 Arc(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3738 ArcTo(hdcMetafile, 23, 23, 37, 27, 37, 27, 23, 23);
3739 Chord(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3740 Pie(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3741 Ellipse(hdcMetafile, 10, 10, 20, 20);
3742 RoundRect(hdcMetafile, 10, 10, 20, 20, 3, 5);
3743 Polyline(hdcMetafile, pts, 4);
3744 PolylineTo(hdcMetafile, pts, 4);
3745 PolyPolyline(hdcMetafile, pts, counts, 2);
3746 PolyDraw(hdcMetafile, pts, types, 9);
3747 AngleArc(hdcMetafile, 37, 36, 23, 90, 180);
3748 EndPath(hdcMetafile);
3750 size = GetPath(hdcMetafile, NULL, NULL, 0);
3751 ok( size == 112, "GetPath returned %d.\n", size);
3753 ret = StrokeAndFillPath( hdcMetafile );
3754 ok( ret, "StrokeAndFillPath failed err %d\n", GetLastError() );
3755 ret = StrokeAndFillPath( hdcMetafile );
3756 ok( !ret, "StrokeAndFillPath succeeded\n" );
3758 hemf = CloseEnhMetaFile(hdcMetafile);
3759 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3761 if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_paths", FALSE) != 0)
3763 dump_emf_bits(hemf, "test_emf_paths");
3764 dump_emf_records(hemf, "test_emf_paths");
3767 DeleteEnhMetaFile(hemf);
3769 SetLastError(0xdeadbeef);
3770 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3771 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3773 ret = BeginPath(hdcMetafile);
3774 ok( ret, "BeginPath failed error %d\n", GetLastError() );
3775 ret = CloseFigure(hdcMetafile);
3776 ok( ret, "CloseFigure failed error %d\n", GetLastError() );
3777 ret = BeginPath(hdcMetafile);
3778 ok( ret, "BeginPath failed error %d\n", GetLastError() );
3779 ret = EndPath(hdcMetafile);
3780 ok( ret, "EndPath failed error %d\n", GetLastError() );
3781 ret = EndPath(hdcMetafile);
3782 ok( !ret, "EndPath succeeded\n" );
3783 ret = CloseFigure(hdcMetafile);
3784 ok( !ret, "CloseFigure succeeded\n" );
3785 ret = BeginPath(hdcMetafile);
3786 ok( ret, "BeginPath failed error %d\n", GetLastError() );
3787 ret = AbortPath(hdcMetafile);
3788 ok( ret, "AbortPath failed error %d\n", GetLastError() );
3789 ret = AbortPath(hdcMetafile);
3790 ok( ret, "AbortPath failed error %d\n", GetLastError() );
3792 hemf = CloseEnhMetaFile(hdcMetafile);
3793 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3795 if (compare_emf_bits(hemf, EMF_EMPTY_PATH_BITS, sizeof(EMF_EMPTY_PATH_BITS), "empty path", FALSE) != 0)
3797 dump_emf_bits(hemf, "empty path");
3798 dump_emf_records(hemf, "empty path");
3801 DeleteEnhMetaFile(hemf);
3804 static void test_emf_PolyPolyline(void)
3806 HDC hdcMetafile;
3807 HENHMETAFILE hemf;
3808 POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3809 DWORD counts[2];
3810 BOOL ret;
3812 SetLastError(0xdeadbeef);
3813 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3814 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3816 ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
3817 ok( !ret, "PolyPolyline\n" );
3819 SetLastError( 0xdeadbeef );
3820 counts[0] = 0;
3821 counts[1] = 1;
3822 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3823 ok( !ret, "PolyPolyline\n" );
3824 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3826 SetLastError( 0xdeadbeef );
3827 counts[0] = 1;
3828 counts[1] = 1;
3829 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3830 ok( !ret, "PolyPolyline\n" );
3831 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3833 SetLastError( 0xdeadbeef );
3834 counts[0] = 2;
3835 counts[1] = 1;
3836 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3837 ok( !ret, "PolyPolyline\n" );
3838 ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3840 counts[0] = 2;
3841 counts[1] = 2;
3842 ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3843 ok( ret, "PolyPolyline\n" );
3845 hemf = CloseEnhMetaFile(hdcMetafile);
3846 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3848 if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
3849 "emf_PolyPolyline", FALSE) != 0)
3851 dump_emf_bits(hemf, "emf_PolyPolyline");
3852 dump_emf_records(hemf, "emf_PolyPolyline");
3855 DeleteEnhMetaFile(hemf);
3858 static void test_emf_GradientFill(void)
3860 HDC mf;
3861 HENHMETAFILE hemf;
3862 TRIVERTEX v[] =
3864 { 1, 10, 0xff00, 0x8000, 0x0000, 0x8001 },
3865 { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
3866 { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
3867 { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
3868 { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
3870 GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
3871 BOOL ret;
3873 mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
3874 ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
3876 /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
3877 * means it allocates three mesh indices rather than two per
3878 * rectangle. This results in uninitialised values being written
3879 * to the EMF which is rather difficult to test against.
3881 * Note also that the final vertex here is not required, yet it is
3882 * written to the EMF, but is not considered in the bounds
3883 * calculation.
3885 ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
3886 GRADIENT_FILL_TRIANGLE );
3887 ok( ret, "GradientFill\n" );
3889 hemf = CloseEnhMetaFile( mf );
3890 ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
3892 if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
3893 "emf_GradientFill", FALSE ) != 0)
3895 dump_emf_bits( hemf, "emf_GradientFill" );
3896 dump_emf_records( hemf, "emf_GradientFill" );
3899 DeleteEnhMetaFile( hemf );
3902 START_TEST(metafile)
3904 init_function_pointers();
3906 /* For enhanced metafiles (enhmfdrv) */
3907 test_ExtTextOut();
3908 test_ExtTextOutScale();
3909 test_SaveDC();
3910 test_emf_BitBlt();
3911 test_emf_DCBrush();
3912 test_emf_ExtTextOut_on_path();
3913 test_emf_clipping();
3914 test_emf_polybezier();
3915 test_emf_paths();
3916 test_emf_PolyPolyline();
3917 test_emf_GradientFill();
3919 /* For win-format metafiles (mfdrv) */
3920 test_mf_SaveDC();
3921 test_mf_Blank();
3922 test_mf_Graphics();
3923 test_mf_PatternBrush();
3924 test_mf_DCBrush();
3925 test_CopyMetaFile();
3926 test_SetMetaFileBits();
3927 test_mf_ExtTextOut_on_path();
3928 test_mf_clipping();
3929 test_mf_GetPath();
3931 /* For metafile conversions */
3932 test_mf_conversions();
3933 test_SetWinMetaFileBits();
3934 test_GetWinMetaFileBits();
3936 test_gdiis();
3937 test_SetEnhMetaFileBits();