push 502c994fb3b2157cb8d5bfd04fb7e4ce7daec2a1
[wine/hacks.git] / dlls / gdi32 / tests / metafile.c
blob63c2cc4b02494e1009137c8b0d9a3d96d2b44851
1 /*
2 * Unit tests for metafile functions
4 * Copyright (c) 2002 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
41 #define GDI_GET_PROC(func) \
42 p ## func = (void *)GetProcAddress(hGDI, #func); \
43 if(!p ## func) \
44 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
46 static void init_function_pointers(void)
48 HMODULE hGDI;
50 pGetRelAbs = NULL;
51 pSetRelAbs = NULL;
53 hGDI = GetModuleHandleA("gdi32.dll");
54 assert(hGDI);
55 GDI_GET_PROC(GetRelAbs);
56 GDI_GET_PROC(SetRelAbs);
59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60 const ENHMETARECORD *emr, int n_objs, LPARAM param)
62 static int n_record;
63 DWORD i;
64 const INT *dx;
65 INT *orig_dx = (INT *)param;
66 LOGFONTA device_lf;
67 INT ret;
69 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70 hdc, emr->iType, emr->nSize, (void *)param);
72 if(!hdc) return 1;
74 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
76 switch (emr->iType)
78 case EMR_HEADER:
79 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
80 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
81 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
82 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
83 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
84 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
85 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
87 /* GetBkMode, GetRelAbs do not get reset to the default value */
88 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
89 if(pSetRelAbs && pGetRelAbs)
90 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
92 n_record = 0;
93 break;
95 case EMR_EXTTEXTOUTA:
97 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
98 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
100 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
103 /* compare up to lfOutPrecision, other values are not interesting,
104 * and in fact sometimes arbitrary adapted by Win9x.
106 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
107 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
109 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
111 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
112 n_record, i, dx[i], orig_dx[i]);
114 n_record++;
115 emr_processed = TRUE;
116 break;
119 case EMR_EXTTEXTOUTW:
121 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
124 SetLastError(0xdeadbeef);
125 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
126 ok( ret == sizeof(device_lf) ||
127 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
128 "GetObjectA error %d\n", GetLastError());
130 /* compare up to lfOutPrecision, other values are not interesting,
131 * and in fact sometimes arbitrary adapted by Win9x.
133 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
134 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
136 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
138 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
139 n_record, i, dx[i], orig_dx[i]);
141 n_record++;
142 emr_processed = TRUE;
143 break;
146 default:
147 break;
150 return 1;
153 static void test_ExtTextOut(void)
155 HWND hwnd;
156 HDC hdcDisplay, hdcMetafile;
157 HENHMETAFILE hMetafile;
158 HFONT hFont;
159 static const char text[] = "Simple text to test ExtTextOut on metafiles";
160 INT i, len, dx[256];
161 static const RECT rc = { 0, 0, 100, 100 };
162 BOOL ret;
164 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
166 /* Win9x doesn't play EMFs on invisible windows */
167 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
168 0, 0, 200, 200, 0, 0, 0, NULL);
169 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
171 hdcDisplay = GetDC(hwnd);
172 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
174 trace("hdcDisplay %p\n", hdcDisplay);
176 SetMapMode(hdcDisplay, MM_TEXT);
178 memset(&orig_lf, 0, sizeof(orig_lf));
180 orig_lf.lfCharSet = ANSI_CHARSET;
181 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
182 orig_lf.lfWeight = FW_DONTCARE;
183 orig_lf.lfHeight = 7;
184 orig_lf.lfQuality = DEFAULT_QUALITY;
185 lstrcpyA(orig_lf.lfFaceName, "Arial");
186 hFont = CreateFontIndirectA(&orig_lf);
187 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
189 hFont = SelectObject(hdcDisplay, hFont);
191 len = lstrlenA(text);
192 for (i = 0; i < len; i++)
194 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
195 ok( ret, "GetCharWidthA error %d\n", GetLastError());
197 hFont = SelectObject(hdcDisplay, hFont);
199 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
200 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
202 trace("hdcMetafile %p\n", hdcMetafile);
204 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
205 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
207 hFont = SelectObject(hdcMetafile, hFont);
209 /* 1. pass NULL lpDx */
210 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
211 ok( ret, "ExtTextOutA error %d\n", GetLastError());
213 /* 2. pass custom lpDx */
214 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
215 ok( ret, "ExtTextOutA error %d\n", GetLastError());
217 hFont = SelectObject(hdcMetafile, hFont);
218 ret = DeleteObject(hFont);
219 ok( ret, "DeleteObject error %d\n", GetLastError());
221 hMetafile = CloseEnhMetaFile(hdcMetafile);
222 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
224 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
226 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
227 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
229 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
230 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
231 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
232 SetROP2(hdcDisplay, R2_NOT);
233 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
234 SetPolyFillMode(hdcDisplay, WINDING);
235 SetStretchBltMode(hdcDisplay, HALFTONE);
237 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
238 SetBkMode(hdcDisplay, OPAQUE);
240 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
241 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
243 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
244 "text align %08x\n", GetTextAlign(hdcDisplay));
245 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
246 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
247 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
248 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
249 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
250 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
252 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
254 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
255 "A valid hdc has to require a valid rc\n");
257 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
258 "A null hdc does not require a valid rc\n");
260 ret = DeleteEnhMetaFile(hMetafile);
261 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
262 ret = ReleaseDC(hwnd, hdcDisplay);
263 ok( ret, "ReleaseDC error %d\n", GetLastError());
264 DestroyWindow(hwnd);
267 static void check_dc_state(HDC hdc, int restore_no,
268 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
269 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
271 BOOL ret;
272 XFORM xform;
273 POINT vp_org, win_org;
274 SIZE vp_size, win_size;
275 FLOAT xscale, yscale, edx, edy;
277 SetLastError(0xdeadbeef);
278 ret = GetWorldTransform(hdc, &xform);
279 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
280 ok(ret, "GetWorldTransform error %u\n", GetLastError());
282 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
284 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
285 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
287 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
288 trace("x scale %f\n", xscale);
289 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
290 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
292 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
293 trace("y scale %f\n", yscale);
294 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
295 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
297 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
298 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
299 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
300 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
302 return;
304 win9x_here:
306 GetWindowOrgEx(hdc, &win_org);
307 GetViewportOrgEx(hdc, &vp_org);
308 GetWindowExtEx(hdc, &win_size);
309 GetViewportExtEx(hdc, &vp_size);
311 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
312 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
314 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
315 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
317 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
318 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
320 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
321 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
324 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
325 const ENHMETARECORD *emr, int n_objs, LPARAM param)
327 BOOL ret;
328 XFORM xform;
329 POINT pt;
330 SIZE size;
331 static int save_state;
332 static int restore_no;
333 static int select_no;
335 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
336 hdc, emr->iType, emr->nSize, (void *)param);
338 trace("BEFORE:\n");
339 SetLastError(0xdeadbeef);
340 ret = GetWorldTransform(hdc, &xform);
341 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
343 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
344 trace("window org (%d,%d)\n", pt.x, pt.y);
345 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
346 trace("vport org (%d,%d)\n", pt.x, pt.y);
347 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
348 trace("window ext (%d,%d)\n", size.cx, size.cy);
349 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
350 trace("vport ext (%d,%d)\n", size.cx, size.cy);
352 else
354 ok(ret, "GetWorldTransform error %u\n", GetLastError());
355 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
358 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
360 switch (emr->iType)
362 case EMR_HEADER:
364 static RECT exp_bounds = { 0, 0, 150, 150 };
365 RECT bounds;
366 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
368 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
369 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
370 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
371 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
372 emf->szlDevice.cx, emf->szlDevice.cy);
374 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
375 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
377 save_state = 0;
378 restore_no = 0;
379 select_no = 0;
380 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
381 break;
384 case EMR_LINETO:
386 const EMRLINETO *line = (const EMRLINETO *)emr;
387 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
388 break;
390 case EMR_SETWINDOWORGEX:
392 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
393 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
394 break;
396 case EMR_SETWINDOWEXTEX:
398 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
399 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
400 break;
402 case EMR_SETVIEWPORTORGEX:
404 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
405 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
406 break;
408 case EMR_SETVIEWPORTEXTEX:
410 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
411 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
412 break;
414 case EMR_SAVEDC:
415 save_state++;
416 trace("EMR_SAVEDC\n");
417 break;
419 case EMR_RESTOREDC:
421 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
422 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
424 switch(++restore_no)
426 case 1:
427 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
428 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
429 break;
430 case 2:
431 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
432 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
433 break;
434 case 3:
435 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
436 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
437 break;
439 ok(restore_no <= 3, "restore_no %d\n", restore_no);
440 save_state += restoredc->iRelative;
441 break;
443 case EMR_SELECTOBJECT:
445 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
446 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
447 select_no ++;
448 break;
450 case EMR_EOF:
451 ok(save_state == 0, "EOF save_state %d\n", save_state);
452 ok(select_no == 3, "Too many/few selects %i\n",select_no);
453 break;
456 trace("AFTER:\n");
457 SetLastError(0xdeadbeef);
458 ret = GetWorldTransform(hdc, &xform);
459 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
461 ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
462 trace("window org (%d,%d)\n", pt.x, pt.y);
463 ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
464 trace("vport org (%d,%d)\n", pt.x, pt.y);
465 ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
466 trace("window ext (%d,%d)\n", size.cx, size.cy);
467 ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
468 trace("vport ext (%d,%d)\n", size.cx, size.cy);
470 else
472 ok(ret, "GetWorldTransform error %u\n", GetLastError());
473 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
476 return 1;
479 static void test_SaveDC(void)
481 HDC hdcMetafile, hdcDisplay;
482 HENHMETAFILE hMetafile;
483 HWND hwnd;
484 int ret;
485 POINT pt;
486 SIZE size;
487 HFONT hFont,hFont2,hFontOld,hFontCheck;
488 static const RECT rc = { 0, 0, 150, 150 };
490 /* Win9x doesn't play EMFs on invisible windows */
491 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
492 0, 0, 200, 200, 0, 0, 0, NULL);
493 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
495 hdcDisplay = GetDC(hwnd);
496 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
498 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
499 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
501 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
503 /* Need to write something to the emf, otherwise Windows won't play it back */
504 LineTo(hdcMetafile, 150, 150);
506 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
507 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
508 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
509 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
511 /* Force Win9x to update DC state */
512 SetPixelV(hdcMetafile, 50, 50, 0);
514 ret = GetViewportOrgEx(hdcMetafile, &pt);
515 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
516 ret = GetViewportExtEx(hdcMetafile, &size);
517 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
518 ret = SaveDC(hdcMetafile);
519 ok(ret == 1, "ret = %d\n", ret);
521 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
522 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
523 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
524 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
526 /* Force Win9x to update DC state */
527 SetPixelV(hdcMetafile, 50, 50, 0);
529 ret = GetViewportOrgEx(hdcMetafile, &pt);
530 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
531 ret = GetViewportExtEx(hdcMetafile, &size);
532 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
533 ret = SaveDC(hdcMetafile);
534 ok(ret == 2, "ret = %d\n", ret);
536 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
537 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
538 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
539 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
540 SetPolyFillMode( hdcMetafile, ALTERNATE );
541 SetBkColor( hdcMetafile, 0 );
543 /* Force Win9x to update DC state */
544 SetPixelV(hdcMetafile, 50, 50, 0);
546 ret = GetViewportOrgEx(hdcMetafile, &pt);
547 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
548 ret = GetViewportExtEx(hdcMetafile, &size);
549 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
550 ret = SaveDC(hdcMetafile);
551 ok(ret == 3, "ret = %d\n", ret);
553 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
554 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
555 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
556 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
558 SetPolyFillMode( hdcMetafile, WINDING );
559 SetBkColor( hdcMetafile, 0x123456 );
560 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
561 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
563 /* Force Win9x to update DC state */
564 SetPixelV(hdcMetafile, 50, 50, 0);
566 ret = GetViewportOrgEx(hdcMetafile, &pt);
567 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
568 ret = GetViewportExtEx(hdcMetafile, &size);
569 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
570 ret = RestoreDC(hdcMetafile, -1);
571 ok(ret, "ret = %d\n", ret);
573 ret = GetViewportOrgEx(hdcMetafile, &pt);
574 todo_wine ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
575 ret = GetViewportExtEx(hdcMetafile, &size);
576 todo_wine ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
577 todo_wine ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
578 todo_wine ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
579 ret = SaveDC(hdcMetafile);
580 ok(ret == 3, "ret = %d\n", ret);
582 ret = GetViewportOrgEx(hdcMetafile, &pt);
583 todo_wine ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
584 ret = GetViewportExtEx(hdcMetafile, &size);
585 todo_wine ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
586 ret = RestoreDC(hdcMetafile, 1);
587 ok(ret, "ret = %d\n", ret);
588 ret = GetViewportOrgEx(hdcMetafile, &pt);
589 todo_wine ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
590 ret = GetViewportExtEx(hdcMetafile, &size);
591 todo_wine ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
593 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
594 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
595 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
596 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
598 /* Force Win9x to update DC state */
599 SetPixelV(hdcMetafile, 50, 50, 0);
601 ret = GetViewportOrgEx(hdcMetafile, &pt);
602 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
603 ret = GetViewportExtEx(hdcMetafile, &size);
604 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
605 ret = SaveDC(hdcMetafile);
606 ok(ret == 1, "ret = %d\n", ret);
608 ret = GetViewportOrgEx(hdcMetafile, &pt);
609 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
610 ret = GetViewportExtEx(hdcMetafile, &size);
611 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
612 ret = SaveDC(hdcMetafile);
613 ok(ret == 2, "ret = %d\n", ret);
615 memset(&orig_lf, 0, sizeof(orig_lf));
616 orig_lf.lfCharSet = ANSI_CHARSET;
617 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
618 orig_lf.lfWeight = FW_DONTCARE;
619 orig_lf.lfHeight = 7;
620 orig_lf.lfQuality = DEFAULT_QUALITY;
621 lstrcpyA(orig_lf.lfFaceName, "Arial");
622 hFont = CreateFontIndirectA(&orig_lf);
623 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
625 hFontOld = SelectObject(hdcMetafile, hFont);
627 hFont2 = CreateFontIndirectA(&orig_lf);
628 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
629 hFontCheck = SelectObject(hdcMetafile, hFont2);
630 ok(hFontCheck == hFont, "Font not selected\n");
632 /* Force Win9x to update DC state */
633 SetPixelV(hdcMetafile, 50, 50, 0);
635 ret = RestoreDC(hdcMetafile, 1);
636 ok(ret, "ret = %d\n", ret);
637 ret = GetViewportOrgEx(hdcMetafile, &pt);
638 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
639 ret = GetViewportExtEx(hdcMetafile, &size);
640 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
642 hFontCheck = SelectObject(hdcMetafile, hFontOld);
643 todo_wine ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
644 "Font not reverted with DC Restore\n");
646 hMetafile = CloseEnhMetaFile(hdcMetafile);
647 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
649 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
650 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
652 ret = DeleteObject(hFont);
653 ok( ret, "DeleteObject error %d\n", GetLastError());
654 ret = DeleteObject(hFont2);
655 ok( ret, "DeleteObject error %d\n", GetLastError());
656 ret = DeleteEnhMetaFile(hMetafile);
657 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
658 ret = ReleaseDC(hwnd, hdcDisplay);
659 ok( ret, "ReleaseDC error %d\n", GetLastError());
660 DestroyWindow(hwnd);
663 static void test_mf_SaveDC(void)
665 HDC hdcMetafile;
666 HMETAFILE hMetafile;
667 int ret;
668 POINT pt;
669 SIZE size;
670 HFONT hFont,hFont2,hFontOld,hFontCheck;
672 hdcMetafile = CreateMetaFileA(NULL);
673 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
675 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
676 ok (ret, "SetMapMode should not fail\n");
678 /* Need to write something to the emf, otherwise Windows won't play it back */
679 LineTo(hdcMetafile, 150, 150);
681 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
682 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
683 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
684 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
686 /* Force Win9x to update DC state */
687 SetPixelV(hdcMetafile, 50, 50, 0);
689 ret = GetViewportOrgEx(hdcMetafile, &pt);
690 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
691 ret = GetViewportExtEx(hdcMetafile, &size);
692 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
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 = SaveDC(hdcMetafile);
705 todo_wine ok(ret == 1, "ret = %d\n", ret);
707 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
708 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
709 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
710 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
712 /* Force Win9x to update DC state */
713 SetPixelV(hdcMetafile, 50, 50, 0);
714 SetPolyFillMode( hdcMetafile, ALTERNATE );
715 SetBkColor( hdcMetafile, 0 );
717 ret = SaveDC(hdcMetafile);
718 todo_wine ok(ret == 1, "ret = %d\n", ret);
720 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
721 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
722 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
723 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
725 SetPolyFillMode( hdcMetafile, WINDING );
726 SetBkColor( hdcMetafile, 0x123456 );
727 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
728 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
730 /* Force Win9x to update DC state */
731 SetPixelV(hdcMetafile, 50, 50, 0);
733 ret = RestoreDC(hdcMetafile, -1);
734 ok(ret, "ret = %d\n", ret);
736 ret = SaveDC(hdcMetafile);
737 todo_wine ok(ret == 1, "ret = %d\n", ret);
739 ret = RestoreDC(hdcMetafile, 1);
740 todo_wine ok(ret, "ret = %d\n", ret);
742 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
743 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
744 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
745 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
747 /* Force Win9x to update DC state */
748 SetPixelV(hdcMetafile, 50, 50, 0);
750 ret = SaveDC(hdcMetafile);
751 todo_wine ok(ret == 1, "ret = %d\n", ret);
753 ret = SaveDC(hdcMetafile);
754 todo_wine ok(ret == 1, "ret = %d\n", ret);
756 memset(&orig_lf, 0, sizeof(orig_lf));
757 orig_lf.lfCharSet = ANSI_CHARSET;
758 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
759 orig_lf.lfWeight = FW_DONTCARE;
760 orig_lf.lfHeight = 7;
761 orig_lf.lfQuality = DEFAULT_QUALITY;
762 lstrcpyA(orig_lf.lfFaceName, "Arial");
763 hFont = CreateFontIndirectA(&orig_lf);
764 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
766 hFontOld = SelectObject(hdcMetafile, hFont);
768 hFont2 = CreateFontIndirectA(&orig_lf);
769 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
770 hFontCheck = SelectObject(hdcMetafile, hFont2);
771 ok(hFontCheck == hFont, "Font not selected\n");
773 /* Force Win9x to update DC state */
774 SetPixelV(hdcMetafile, 50, 50, 0);
776 ret = RestoreDC(hdcMetafile, 1);
778 hFontCheck = SelectObject(hdcMetafile, hFontOld);
779 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
781 hMetafile = CloseMetaFile(hdcMetafile);
782 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
784 ret = DeleteMetaFile(hMetafile);
785 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
786 ret = DeleteObject(hFont);
787 ok( ret, "DeleteObject error %d\n", GetLastError());
788 ret = DeleteObject(hFont2);
789 ok( ret, "DeleteObject error %d\n", GetLastError());
793 /* Win-format metafile (mfdrv) tests */
794 /* These tests compare the generated metafiles byte-by-byte */
795 /* with the nominal results. */
797 /* Maximum size of sample metafiles in bytes. */
798 #define MF_BUFSIZE 512
800 /* 8x8 bitmap data for a pattern brush */
801 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
802 0x01, 0x00, 0x02, 0x00,
803 0x03, 0x00, 0x04, 0x00,
804 0x05, 0x00, 0x06, 0x00,
805 0x07, 0x00, 0x08, 0x00
808 /* Sample metafiles to be compared to the outputs of the
809 * test functions.
812 static const unsigned char MF_BLANK_BITS[] = {
813 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
815 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
818 static const unsigned char MF_GRAPHICS_BITS[] = {
819 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
822 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
823 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
824 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
825 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
826 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
827 0x00, 0x00, 0x00, 0x00
830 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
831 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
832 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
833 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
834 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
835 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
836 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
837 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
841 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
842 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
843 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
844 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
845 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
846 0x00, 0x00
849 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
851 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
854 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
855 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
856 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
857 0x00, 0x00
860 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
862 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
865 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
866 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
867 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
868 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
869 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
872 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
873 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
874 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
875 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
876 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
877 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
879 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
881 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
882 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
885 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
886 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
887 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
888 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
889 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
890 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
891 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
892 0x14, 0x00, 0x00, 0x00
895 static const unsigned char MF_LINETO_BITS[] = {
896 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
897 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
898 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
899 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
900 0x00, 0x00
903 static const unsigned char EMF_LINETO_BITS[] = {
904 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
906 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
907 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
908 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
909 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
910 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
911 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
913 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
914 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
915 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
917 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
918 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
919 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
920 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
921 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
922 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
923 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
924 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
925 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
927 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
928 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
929 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
930 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
931 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
932 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
933 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
934 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
935 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
936 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
937 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
938 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
939 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
941 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
945 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
946 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
948 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
951 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
952 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
953 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
955 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
956 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
957 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
958 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
959 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
960 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
961 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
962 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
963 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
964 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
965 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
966 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
967 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
969 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
970 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
971 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
972 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
973 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
974 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
975 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
976 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
977 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
978 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
979 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
980 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
981 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
983 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
987 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
988 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
990 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
992 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
993 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
994 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
995 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
997 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
998 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
999 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1000 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1001 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1002 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1003 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1004 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1005 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1006 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1007 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1008 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1009 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1011 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1012 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1014 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1015 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1016 0x14, 0x00, 0x00, 0x00
1019 /* For debugging or dumping the raw metafiles produced by
1020 * new test functions.
1022 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1023 INT nobj, LPARAM param)
1025 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1026 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1027 return TRUE;
1030 /* For debugging or dumping the raw metafiles produced by
1031 * new test functions.
1034 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1036 BYTE buf[MF_BUFSIZE];
1037 UINT mfsize, i;
1039 if (!winetest_debug) return;
1041 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1042 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1044 printf ("MetaFile %s has bits:\n{\n ", desc);
1045 for (i=0; i<mfsize; i++)
1047 printf ("0x%02x", buf[i]);
1048 if (i == mfsize-1)
1049 printf ("\n");
1050 else if (i % 8 == 7)
1051 printf (",\n ");
1052 else
1053 printf (", ");
1055 printf ("};\n");
1058 /* Compare the metafile produced by a test function with the
1059 * expected raw metafile data in "bits".
1060 * Return value is 0 for a perfect match,
1061 * -1 if lengths aren't equal,
1062 * otherwise returns the number of non-matching bytes.
1065 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1066 const char *desc)
1068 unsigned char buf[MF_BUFSIZE];
1069 UINT mfsize, i;
1070 int diff;
1072 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1073 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1074 if (mfsize < MF_BUFSIZE)
1075 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1076 desc, mfsize, bsize);
1077 else
1078 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1079 desc, mfsize, bsize);
1080 if (mfsize != bsize)
1081 return -1;
1083 diff = 0;
1084 for (i=0; i<bsize; i++)
1086 if (buf[i] != bits[i])
1087 diff++;
1089 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1090 desc, mfsize, bsize, diff);
1092 return diff;
1095 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1097 unsigned char buf[MF_BUFSIZE];
1098 DWORD mfsize, rd_size, i;
1099 int diff;
1100 HANDLE hfile;
1101 BOOL ret;
1103 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1104 assert(hfile != INVALID_HANDLE_VALUE);
1106 mfsize = GetFileSize(hfile, NULL);
1107 assert(mfsize <= MF_BUFSIZE);
1109 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1110 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1112 CloseHandle(hfile);
1114 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1116 if (mfsize != bsize)
1117 return -1;
1119 diff = 0;
1120 for (i=0; i<bsize; i++)
1122 if (buf[i] != bits[i])
1123 diff++;
1125 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1126 desc, mfsize, bsize, diff);
1128 return diff;
1131 /* For debugging or dumping the raw EMFs produced by
1132 * new test functions.
1134 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1136 BYTE buf[MF_BUFSIZE];
1137 UINT mfsize, i;
1139 if (!winetest_debug) return;
1141 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1142 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1144 printf("EMF %s has bits:\n{\n ", desc);
1145 for (i = 0; i < mfsize; i++)
1147 printf ("0x%02x", buf[i]);
1148 if (i == mfsize-1)
1149 printf ("\n");
1150 else if (i % 8 == 7)
1151 printf (",\n ");
1152 else
1153 printf (", ");
1155 printf ("};\n");
1158 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1160 BYTE *emf;
1161 BYTE buf[MF_BUFSIZE];
1162 UINT mfsize, offset;
1164 if (!winetest_debug) return;
1166 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1167 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1169 printf("EMF %s has records:\n", desc);
1171 emf = buf;
1172 offset = 0;
1173 while(offset < mfsize)
1175 EMR *emr = (EMR *)(emf + offset);
1176 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1177 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1178 offset += emr->nSize;
1182 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1184 const BYTE *buf;
1185 DWORD i;
1187 if (!winetest_debug) return;
1189 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1190 buf = (const BYTE *)emr;
1191 for (i = 0; i < emr->nSize; i++)
1193 printf ("0x%02x", buf[i]);
1194 if (i == emr->nSize - 1)
1195 printf ("\n");
1196 else if (i % 8 == 7)
1197 printf (",\n");
1198 else
1199 printf (", ");
1201 printf ("};\n");
1204 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1206 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1207 eto->rclBounds.right, eto->rclBounds.bottom);
1208 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1209 trace("exScale: %f\n", eto->exScale);
1210 trace("eyScale: %f\n", eto->eyScale);
1211 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1212 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1213 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1214 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1215 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1216 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1217 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1220 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1221 const char *desc, BOOL ignore_scaling)
1223 int diff;
1225 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1226 desc, emr1->iType, emr2->iType);
1228 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1229 desc, emr1->nSize, emr2->nSize);
1231 /* iType and nSize mismatches are fatal */
1232 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1234 /* contents of EMR_GDICOMMENT are not interesting */
1235 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1237 /* different Windows versions setup DC scaling differently when
1238 * converting an old style metafile to an EMF.
1240 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1241 emr1->iType == EMR_SETVIEWPORTEXTEX))
1242 return TRUE;
1244 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1246 EMREXTTEXTOUTW *eto1, *eto2;
1248 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1249 memcpy(eto1, emr1, emr1->nSize);
1250 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1251 memcpy(eto2, emr2, emr2->nSize);
1253 /* different Windows versions setup DC scaling differently */
1254 eto1->exScale = eto1->eyScale = 0.0;
1255 eto2->exScale = eto2->eyScale = 0.0;
1257 diff = memcmp(eto1, eto2, emr1->nSize);
1258 if (diff)
1260 dump_EMREXTTEXTOUT(eto1);
1261 dump_EMREXTTEXTOUT(eto2);
1263 HeapFree(GetProcessHeap(), 0, eto1);
1264 HeapFree(GetProcessHeap(), 0, eto2);
1266 else
1267 diff = memcmp(emr1, emr2, emr1->nSize);
1269 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1271 if (diff)
1273 dump_emf_record(emr1, "expected bits");
1274 dump_emf_record(emr2, "actual bits");
1277 return diff == 0; /* report all non-fatal record mismatches */
1280 /* Compare the EMF produced by a test function with the
1281 * expected raw EMF data in "bits".
1282 * Return value is 0 for a perfect match,
1283 * -1 if lengths aren't equal,
1284 * otherwise returns the number of non-matching bytes.
1286 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1287 UINT bsize, const char *desc,
1288 BOOL ignore_scaling)
1290 unsigned char buf[MF_BUFSIZE];
1291 UINT mfsize, offset;
1292 const ENHMETAHEADER *emh1, *emh2;
1294 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1295 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1297 if (mfsize < MF_BUFSIZE)
1299 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1301 else
1302 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1303 desc, mfsize, bsize);
1305 /* basic things must match */
1306 emh1 = (const ENHMETAHEADER *)bits;
1307 emh2 = (const ENHMETAHEADER *)buf;
1308 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1309 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1310 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1311 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1313 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1314 ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1315 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1316 ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1317 ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1319 offset = emh1->nSize;
1320 while (offset < emh1->nBytes)
1322 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset);
1323 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset);
1325 trace("EMF record %u, size %u/record %u, size %u\n",
1326 emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1328 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1330 offset += emr1->nSize;
1332 return 0;
1335 /* Test a blank metafile. May be used as a template for new tests. */
1337 static void test_mf_Blank(void)
1339 HDC hdcMetafile;
1340 HMETAFILE hMetafile;
1341 INT caps;
1342 BOOL ret;
1343 INT type;
1345 hdcMetafile = CreateMetaFileA(NULL);
1346 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1347 trace("hdcMetafile %p\n", hdcMetafile);
1349 /* Tests on metafile initialization */
1350 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1351 ok (caps == DT_METAFILE,
1352 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1354 hMetafile = CloseMetaFile(hdcMetafile);
1355 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1356 type = GetObjectType(hMetafile);
1357 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1358 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1360 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1361 "mf_blank") != 0)
1363 dump_mf_bits(hMetafile, "mf_Blank");
1364 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1367 ret = DeleteMetaFile(hMetafile);
1368 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1371 static void test_CopyMetaFile(void)
1373 HDC hdcMetafile;
1374 HMETAFILE hMetafile, hmf_copy;
1375 BOOL ret;
1376 char temp_path[MAX_PATH];
1377 char mf_name[MAX_PATH];
1378 INT type;
1380 hdcMetafile = CreateMetaFileA(NULL);
1381 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1382 trace("hdcMetafile %p\n", hdcMetafile);
1384 hMetafile = CloseMetaFile(hdcMetafile);
1385 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1386 type = GetObjectType(hMetafile);
1387 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1389 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1390 "mf_blank") != 0)
1392 dump_mf_bits(hMetafile, "mf_Blank");
1393 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1396 GetTempPathA(MAX_PATH, temp_path);
1397 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1399 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1400 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1402 type = GetObjectType(hmf_copy);
1403 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1405 ret = DeleteMetaFile(hMetafile);
1406 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1408 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1410 dump_mf_bits(hMetafile, "mf_Blank");
1411 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1414 ret = DeleteMetaFile(hmf_copy);
1415 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1417 DeleteFileA(mf_name);
1420 static void test_SetMetaFileBits(void)
1422 HMETAFILE hmf;
1423 INT type;
1424 BOOL ret;
1425 BYTE buf[256];
1426 METAHEADER *mh;
1428 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1429 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1430 type = GetObjectType(hmf);
1431 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1433 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1435 dump_mf_bits(hmf, "mf_Graphics");
1436 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1439 ret = DeleteMetaFile(hmf);
1440 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1442 /* NULL data crashes XP SP1 */
1443 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1445 /* Now with not zero size */
1446 SetLastError(0xdeadbeef);
1447 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1448 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1449 ok(GetLastError() == ERROR_INVALID_DATA ||
1450 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1451 "wrong error %d\n", GetLastError());
1453 /* Now with not even size */
1454 SetLastError(0xdeadbeef);
1455 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1456 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1457 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1459 /* Now with zeroed out or faked some header fields */
1460 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1461 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1462 mh = (METAHEADER *)buf;
1463 /* corruption of any of the below fields leads to a failure */
1464 mh->mtType = 0;
1465 mh->mtVersion = 0;
1466 mh->mtHeaderSize = 0;
1467 SetLastError(0xdeadbeef);
1468 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1469 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1470 ok(GetLastError() == ERROR_INVALID_DATA ||
1471 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1472 "wrong error %d\n", GetLastError());
1474 /* Now with corrupted mtSize field */
1475 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1476 mh = (METAHEADER *)buf;
1477 /* corruption of mtSize doesn't lead to a failure */
1478 mh->mtSize *= 2;
1479 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1480 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1482 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1484 dump_mf_bits(hmf, "mf_Graphics");
1485 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1488 ret = DeleteMetaFile(hmf);
1489 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1491 /* Now with zeroed out mtSize field */
1492 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1493 mh = (METAHEADER *)buf;
1494 /* zeroing mtSize doesn't lead to a failure */
1495 mh->mtSize = 0;
1496 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1497 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1499 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1501 dump_mf_bits(hmf, "mf_Graphics");
1502 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1505 ret = DeleteMetaFile(hmf);
1506 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1509 /* Simple APIs from mfdrv/graphics.c
1512 static void test_mf_Graphics(void)
1514 HDC hdcMetafile;
1515 HMETAFILE hMetafile;
1516 POINT oldpoint;
1517 BOOL ret;
1519 hdcMetafile = CreateMetaFileA(NULL);
1520 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1521 trace("hdcMetafile %p\n", hdcMetafile);
1523 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1524 ok( ret, "MoveToEx error %d.\n", GetLastError());
1525 ret = LineTo(hdcMetafile, 2, 2);
1526 ok( ret, "LineTo error %d.\n", GetLastError());
1527 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1528 ok( ret, "MoveToEx error %d.\n", GetLastError());
1530 /* oldpoint gets garbage under Win XP, so the following test would
1531 * work under Wine but fails under Windows:
1533 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1534 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1535 * oldpoint.x, oldpoint.y);
1538 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1539 ok( ret, "Ellipse error %d.\n", GetLastError());
1541 hMetafile = CloseMetaFile(hdcMetafile);
1542 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1543 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1545 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1546 "mf_Graphics") != 0)
1548 dump_mf_bits(hMetafile, "mf_Graphics");
1549 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1552 ret = DeleteMetaFile(hMetafile);
1553 ok( ret, "DeleteMetaFile(%p) error %d\n",
1554 hMetafile, GetLastError());
1557 static void test_mf_PatternBrush(void)
1559 HDC hdcMetafile;
1560 HMETAFILE hMetafile;
1561 LOGBRUSH *orig_lb;
1562 HBRUSH hBrush;
1563 BOOL ret;
1565 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1567 orig_lb->lbStyle = BS_PATTERN;
1568 orig_lb->lbColor = RGB(0, 0, 0);
1569 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1570 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1572 hBrush = CreateBrushIndirect (orig_lb);
1573 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1575 hdcMetafile = CreateMetaFileA(NULL);
1576 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1577 trace("hdcMetafile %p\n", hdcMetafile);
1579 hBrush = SelectObject(hdcMetafile, hBrush);
1580 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1582 hMetafile = CloseMetaFile(hdcMetafile);
1583 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1584 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1586 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1587 "mf_Pattern_Brush") != 0)
1589 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1590 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1593 ret = DeleteMetaFile(hMetafile);
1594 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1595 ret = DeleteObject(hBrush);
1596 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1597 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1598 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1599 GetLastError());
1600 HeapFree (GetProcessHeap(), 0, orig_lb);
1603 static void test_mf_ExtTextOut_on_path(void)
1605 HDC hdcMetafile;
1606 HMETAFILE hMetafile;
1607 BOOL ret;
1608 static const INT dx[4] = { 3, 5, 8, 12 };
1610 hdcMetafile = CreateMetaFileA(NULL);
1611 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1612 trace("hdcMetafile %p\n", hdcMetafile);
1614 ret = BeginPath(hdcMetafile);
1615 ok(!ret, "BeginPath on metafile DC should fail\n");
1617 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1618 ok(ret, "ExtTextOut error %d\n", GetLastError());
1620 ret = EndPath(hdcMetafile);
1621 ok(!ret, "EndPath on metafile DC should fail\n");
1623 hMetafile = CloseMetaFile(hdcMetafile);
1624 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1626 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1627 "mf_TextOut_on_path") != 0)
1629 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1630 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1633 ret = DeleteMetaFile(hMetafile);
1634 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1637 static void test_emf_ExtTextOut_on_path(void)
1639 HWND hwnd;
1640 HDC hdcDisplay, hdcMetafile;
1641 HENHMETAFILE hMetafile;
1642 BOOL ret;
1643 static const INT dx[4] = { 3, 5, 8, 12 };
1645 /* Win9x doesn't play EMFs on invisible windows */
1646 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1647 0, 0, 200, 200, 0, 0, 0, NULL);
1648 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1650 hdcDisplay = GetDC(hwnd);
1651 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1653 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1654 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1656 ret = BeginPath(hdcMetafile);
1657 ok(ret, "BeginPath error %d\n", GetLastError());
1659 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1660 ok(ret, "ExtTextOut error %d\n", GetLastError());
1662 ret = EndPath(hdcMetafile);
1663 ok(ret, "EndPath error %d\n", GetLastError());
1665 hMetafile = CloseEnhMetaFile(hdcMetafile);
1666 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1668 /* this doesn't succeed yet: EMF has correct size, all EMF records
1669 * are there, but their contents don't match for different reasons.
1671 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1672 "emf_TextOut_on_path", FALSE) != 0)
1674 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1675 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1678 ret = DeleteEnhMetaFile(hMetafile);
1679 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1680 ret = ReleaseDC(hwnd, hdcDisplay);
1681 ok(ret, "ReleaseDC error %d\n", GetLastError());
1682 DestroyWindow(hwnd);
1685 static const unsigned char EMF_CLIPPING[] =
1687 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1689 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1691 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1692 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1693 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1694 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1696 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1697 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1699 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1700 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1701 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1702 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1703 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1704 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1705 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1706 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1707 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1708 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1709 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1710 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1711 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1712 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1715 static void translate( POINT *pt, UINT count, const XFORM *xform )
1717 while (count--)
1719 FLOAT x = (FLOAT)pt->x;
1720 FLOAT y = (FLOAT)pt->y;
1721 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1722 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1723 pt++;
1727 /* Compare rectangles allowing rounding errors */
1728 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1730 return abs(rc1->left - rc2->left) <= 1 &&
1731 abs(rc1->top - rc2->top) <= 1 &&
1732 abs(rc1->right - rc2->right) <= 1 &&
1733 abs(rc1->bottom - rc2->bottom) <= 1;
1736 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1737 const ENHMETARECORD *emr, int n_objs, LPARAM param)
1739 if (emr->iType == EMR_EXTSELECTCLIPRGN)
1741 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1742 union _rgn
1744 RGNDATA data;
1745 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1747 const union _rgn *rgn1;
1748 union _rgn rgn2;
1749 RECT rect, rc_transformed;
1750 const RECT *rc = (const RECT *)param;
1751 HRGN hrgn;
1752 XFORM xform;
1753 INT ret;
1754 BOOL is_win9x;
1756 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1757 clip->cbRgnData, clip->iMode);
1759 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1760 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1761 "too small data block: %u bytes\n", clip->cbRgnData);
1762 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1763 return 0;
1765 rgn1 = (const union _rgn *)clip->RgnData;
1767 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1768 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1769 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1770 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1771 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1773 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1775 rect = *(const RECT *)rgn1->data.Buffer;
1776 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1777 ok(EqualRect(&rect, rc), "rects don't match\n");
1779 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1780 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1781 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1782 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1784 hrgn = CreateRectRgn(0, 0, 0, 0);
1786 memset(&xform, 0, sizeof(xform));
1787 SetLastError(0xdeadbeef);
1788 ret = GetWorldTransform(hdc, &xform);
1789 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1790 if (!is_win9x)
1791 ok(ret, "GetWorldTransform error %u\n", GetLastError());
1793 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1795 ret = GetClipRgn(hdc, hrgn);
1796 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1798 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1800 ret = GetClipRgn(hdc, hrgn);
1801 ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1803 /* Win9x returns empty clipping region */
1804 if (is_win9x) return 1;
1806 ret = GetRegionData(hrgn, 0, NULL);
1807 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1809 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1811 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1812 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1813 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1814 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1815 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1817 rect = rgn2.data.rdh.rcBound;
1818 rc_transformed = *rc;
1819 translate((POINT *)&rc_transformed, 2, &xform);
1820 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1821 rc_transformed.right, rc_transformed.bottom);
1822 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1824 rect = *(const RECT *)rgn2.data.Buffer;
1825 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1826 rc_transformed = *rc;
1827 translate((POINT *)&rc_transformed, 2, &xform);
1828 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1829 rc_transformed.right, rc_transformed.bottom);
1830 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1832 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1833 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1834 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1835 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1837 DeleteObject(hrgn);
1839 return 1;
1842 static void test_emf_clipping(void)
1844 static const RECT rc = { 0, 0, 100, 100 };
1845 RECT rc_clip = { 100, 100, 1024, 1024 };
1846 HWND hwnd;
1847 HDC hdc;
1848 HENHMETAFILE hemf;
1849 HRGN hrgn;
1850 INT ret;
1852 SetLastError(0xdeadbeef);
1853 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1854 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1856 /* Need to write something to the emf, otherwise Windows won't play it back */
1857 LineTo(hdc, 1, 1);
1859 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1860 ret = SelectClipRgn(hdc, hrgn);
1861 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1863 SetLastError(0xdeadbeef);
1864 hemf = CloseEnhMetaFile(hdc);
1865 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1867 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1868 "emf_clipping", FALSE) != 0)
1870 dump_emf_bits(hemf, "emf_clipping");
1871 dump_emf_records(hemf, "emf_clipping");
1874 DeleteObject(hrgn);
1876 /* Win9x doesn't play EMFs on invisible windows */
1877 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1878 0, 0, 200, 200, 0, 0, 0, NULL);
1879 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1881 hdc = GetDC(hwnd);
1883 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1884 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1886 DeleteEnhMetaFile(hemf);
1887 ReleaseDC(hwnd, hdc);
1888 DestroyWindow(hwnd);
1891 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1893 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1894 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1895 /* When using MM_TEXT Win9x does not update the mapping mode
1896 * until a record is played which actually outputs something */
1897 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1898 LPtoDP(hdc, mapping, 2);
1899 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1900 lpEMFR->iType, lpEMFR->nSize,
1901 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1903 if (lpEMFR->iType == EMR_LINETO)
1905 INT x0, y0, x1, y1;
1906 if (!lpMFP || lpMFP->mm == MM_TEXT)
1908 x0 = 0;
1909 y0 = 0;
1910 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1911 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1913 else
1915 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1917 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1918 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1919 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1920 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1922 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1923 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1924 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1925 x0, y0, x1, y1);
1927 return TRUE;
1930 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1932 HDC hdcMf;
1933 HMETAFILE hmf;
1934 HENHMETAFILE hemf;
1935 BOOL ret;
1936 UINT size;
1937 LPBYTE pBits;
1939 hdcMf = CreateMetaFile(NULL);
1940 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1941 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1942 ok(ret, "LineTo failed with error %d\n", GetLastError());
1943 hmf = CloseMetaFile(hdcMf);
1944 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1946 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1948 dump_mf_bits(hmf, "mf_LineTo");
1949 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1952 size = GetMetaFileBitsEx(hmf, 0, NULL);
1953 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1954 pBits = HeapAlloc(GetProcessHeap(), 0, size);
1955 GetMetaFileBitsEx(hmf, size, pBits);
1956 DeleteMetaFile(hmf);
1957 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1958 HeapFree(GetProcessHeap(), 0, pBits);
1959 return hemf;
1962 static void test_mf_conversions(void)
1964 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1966 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1967 HENHMETAFILE hemf;
1968 METAFILEPICT mfp;
1969 RECT rect = { 0, 0, 100, 100 };
1970 mfp.mm = MM_ANISOTROPIC;
1971 mfp.xExt = 100;
1972 mfp.yExt = 100;
1973 mfp.hMF = NULL;
1974 hemf = create_converted_emf(&mfp);
1976 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1977 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1979 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1980 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1983 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1985 DeleteEnhMetaFile(hemf);
1986 DeleteDC(hdcOffscreen);
1989 trace("Testing MF->EMF conversion (MM_TEXT)\n");
1991 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1992 HENHMETAFILE hemf;
1993 METAFILEPICT mfp;
1994 RECT rect = { 0, 0, 100, 100 };
1995 mfp.mm = MM_TEXT;
1996 mfp.xExt = 0;
1997 mfp.yExt = 0;
1998 mfp.hMF = NULL;
1999 hemf = create_converted_emf(&mfp);
2001 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2002 "emf_LineTo MM_TEXT", TRUE) != 0)
2004 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2005 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2008 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2010 DeleteEnhMetaFile(hemf);
2011 DeleteDC(hdcOffscreen);
2014 trace("Testing MF->EMF conversion (NULL mfp)\n");
2016 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2017 HENHMETAFILE hemf;
2018 RECT rect = { 0, 0, 100, 100 };
2019 hemf = create_converted_emf(NULL);
2021 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2022 "emf_LineTo NULL", TRUE) != 0)
2024 dump_emf_bits(hemf, "emf_LineTo NULL");
2025 dump_emf_records(hemf, "emf_LineTo NULL");
2028 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2030 DeleteEnhMetaFile(hemf);
2031 DeleteDC(hdcOffscreen);
2035 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2036 LONG mm, LONG xExt, LONG yExt,
2037 RECTL * rclBounds, RECTL * rclFrame)
2039 METAFILEPICT mfp;
2040 METAFILEPICT * mfpPtr = NULL;
2041 HENHMETAFILE emf;
2042 ENHMETAHEADER header;
2043 UINT res;
2045 if (!mfpIsNull)
2047 mfp.mm = mm;
2048 mfp.xExt = xExt;
2049 mfp.yExt = yExt;
2050 mfpPtr = &mfp;
2053 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2054 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2055 if (!emf) return FALSE;
2056 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2057 ok(res != 0, "GetEnhMetaHeader failed\n");
2058 DeleteEnhMetaFile(emf);
2059 if (!res) return FALSE;
2061 *rclBounds = header.rclBounds;
2062 *rclFrame = header.rclFrame;
2063 return TRUE;
2066 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2067 LONG mm, LONG xExt, LONG yExt,
2068 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2070 RECTL rclBounds, rclFrame;
2072 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2074 const char * msg;
2075 char buf[64];
2077 if (mfpIsNull)
2079 msg = "mfp == NULL";
2081 else
2083 const char * mm_str;
2084 switch (mm)
2086 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2087 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2088 default: mm_str = "Unexpected";
2090 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2091 msg = buf;
2094 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2095 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2096 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2097 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2098 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2099 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2100 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2101 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2105 static void test_SetWinMetaFileBits(void)
2107 HMETAFILE wmf;
2108 HDC wmfDC;
2109 BYTE * buffer;
2110 UINT buffer_size;
2111 RECT rect;
2112 UINT res;
2113 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2114 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2115 RECTL rclBounds, rclFrame;
2116 HDC dc;
2117 LONG diffx, diffy;
2119 wmfDC = CreateMetaFile(NULL);
2120 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2121 if (!wmfDC) return;
2123 SetWindowExtEx(wmfDC, 100, 100, NULL);
2124 rect.left = rect.top = 0;
2125 rect.right = rect.bottom = 50;
2126 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2127 wmf = CloseMetaFile(wmfDC);
2128 ok(wmf != NULL, "Metafile creation failed\n");
2129 if (!wmf) return;
2131 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2132 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2133 if (buffer_size == 0)
2135 DeleteMetaFile(wmf);
2136 return;
2139 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2140 ok(buffer != NULL, "HeapAlloc failed\n");
2141 if (!buffer)
2143 DeleteMetaFile(wmf);
2144 return;
2147 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2148 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2149 DeleteMetaFile(wmf);
2150 if (res != buffer_size)
2152 HeapFree(GetProcessHeap(), 0, buffer);
2153 return;
2156 /* Get the reference bounds and frame */
2157 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2158 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2160 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2161 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2162 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2164 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2165 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2166 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2167 if (diffx < 0) diffx = -diffx;
2168 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2170 dc = CreateCompatibleDC(NULL);
2172 /* Allow 1 mm difference (rounding errors) */
2173 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2174 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2175 if (diffx < 0) diffx = -diffx;
2176 if (diffy < 0) diffy = -diffy;
2177 todo_wine
2179 ok(diffx <= 1 && diffy <= 1,
2180 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2181 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2184 /* Allow 1 mm difference (rounding errors) */
2185 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2186 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2187 if (diffx < 0) diffx = -diffx;
2188 if (diffy < 0) diffy = -diffy;
2189 todo_wine
2191 ok(diffx <= 1 && diffy <= 1,
2192 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2193 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2195 DeleteDC(dc);
2197 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2198 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2200 /* If xExt or yExt is zero or negative, the whole device surface is used */
2201 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2202 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2203 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2204 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2205 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2206 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2207 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2208 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2209 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2210 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2211 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2212 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2214 /* MSDN says that negative xExt and yExt values specify a ratio.
2215 Check that this is wrong and the whole device surface is used */
2216 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2217 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2219 /* Ordinary conversions */
2221 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2223 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2224 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2225 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2226 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2229 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2231 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2232 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2233 ok(rclBounds.left == 0 && rclBounds.top == 0,
2234 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2236 /* Wine has a rounding error */
2237 diffx = rclBounds.right - rclBounds.bottom;
2238 if (diffx < 0) diffx = -diffx;
2239 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2242 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2244 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2245 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2248 HeapFree(GetProcessHeap(), 0, buffer);
2251 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2252 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2253 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2255 static void test_gdiis(void)
2257 RECT rect = {0,0,100,100};
2258 HDC hdc, hemfDC, hmfDC;
2259 HENHMETAFILE hemf;
2260 HMODULE hgdi32;
2262 /* resolve all the functions */
2263 hgdi32 = GetModuleHandle("gdi32");
2264 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2265 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2266 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2268 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2270 win_skip("Needed GdiIs* functions are not available\n");
2271 return;
2274 /* try with nothing */
2275 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2276 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2277 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2279 /* try with a metafile */
2280 hmfDC = CreateMetaFile(NULL);
2281 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2282 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2283 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2284 DeleteMetaFile(CloseMetaFile(hmfDC));
2286 /* try with an enhanced metafile */
2287 hdc = GetDC(NULL);
2288 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2289 ok(hemfDC != NULL, "failed to create emf\n");
2291 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2292 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2293 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2295 hemf = CloseEnhMetaFile(hemfDC);
2296 ok(hemf != NULL, "failed to close EMF\n");
2297 DeleteEnhMetaFile(hemf);
2298 ReleaseDC(NULL,hdc);
2301 static void test_SetEnhMetaFileBits(void)
2303 BYTE data[256];
2304 HENHMETAFILE hemf;
2305 ENHMETAHEADER *emh;
2307 memset(data, 0xAA, sizeof(data));
2308 SetLastError(0xdeadbeef);
2309 hemf = SetEnhMetaFileBits(sizeof(data), data);
2310 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2311 ok(GetLastError() == ERROR_INVALID_DATA ||
2312 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2313 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2315 emh = (ENHMETAHEADER *)data;
2316 memset(emh, 0, sizeof(*emh));
2318 emh->iType = EMR_HEADER;
2319 emh->nSize = sizeof(*emh);
2320 emh->dSignature = ENHMETA_SIGNATURE;
2321 /* emh->nVersion = 0x10000; XP doesn't care about version */
2322 emh->nBytes = sizeof(*emh);
2323 /* emh->nRecords = 1; XP doesn't care about records */
2324 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2326 SetLastError(0xdeadbeef);
2327 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2328 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2329 DeleteEnhMetaFile(hemf);
2331 /* XP refuses to load unaligned EMF */
2332 emh->nBytes++;
2333 SetLastError(0xdeadbeef);
2334 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2335 ok(!hemf ||
2336 broken(hemf != NULL), /* Win9x, WinMe */
2337 "SetEnhMetaFileBits should fail\n");
2338 todo_wine
2339 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2340 DeleteEnhMetaFile(hemf);
2342 emh->dSignature = 0;
2343 emh->nBytes--;
2344 SetLastError(0xdeadbeef);
2345 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2346 ok(!hemf ||
2347 broken(hemf != NULL), /* Win9x, WinMe */
2348 "SetEnhMetaFileBits should fail\n");
2349 todo_wine
2350 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2351 DeleteEnhMetaFile(hemf);
2354 START_TEST(metafile)
2356 init_function_pointers();
2358 /* For enhanced metafiles (enhmfdrv) */
2359 test_ExtTextOut();
2360 test_SaveDC();
2362 /* For win-format metafiles (mfdrv) */
2363 test_mf_SaveDC();
2364 test_mf_Blank();
2365 test_mf_Graphics();
2366 test_mf_PatternBrush();
2367 test_CopyMetaFile();
2368 test_SetMetaFileBits();
2369 test_mf_ExtTextOut_on_path();
2370 test_emf_ExtTextOut_on_path();
2371 test_emf_clipping();
2373 /* For metafile conversions */
2374 test_mf_conversions();
2375 test_SetWinMetaFileBits();
2377 test_gdiis();
2378 test_SetEnhMetaFileBits();