push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / gdi32 / tests / metafile.c
blob6164050cbb4d570d5e3a1ccd985421fb1fdf1481
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 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
575 ret = GetViewportExtEx(hdcMetafile, &size);
576 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
577 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
578 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
579 ret = SaveDC(hdcMetafile);
580 ok(ret == 3, "ret = %d\n", ret);
582 ret = GetViewportOrgEx(hdcMetafile, &pt);
583 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
584 ret = GetViewportExtEx(hdcMetafile, &size);
585 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
586 ret = RestoreDC(hdcMetafile, 1);
587 ok(ret, "ret = %d\n", ret);
588 ret = GetViewportOrgEx(hdcMetafile, &pt);
589 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
590 ret = GetViewportExtEx(hdcMetafile, &size);
591 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
593 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
594 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
595 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
596 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
598 /* Force Win9x to update DC state */
599 SetPixelV(hdcMetafile, 50, 50, 0);
601 ret = GetViewportOrgEx(hdcMetafile, &pt);
602 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
603 ret = GetViewportExtEx(hdcMetafile, &size);
604 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
605 ret = SaveDC(hdcMetafile);
606 ok(ret == 1, "ret = %d\n", ret);
608 ret = GetViewportOrgEx(hdcMetafile, &pt);
609 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
610 ret = GetViewportExtEx(hdcMetafile, &size);
611 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
612 ret = SaveDC(hdcMetafile);
613 ok(ret == 2, "ret = %d\n", ret);
615 memset(&orig_lf, 0, sizeof(orig_lf));
616 orig_lf.lfCharSet = ANSI_CHARSET;
617 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
618 orig_lf.lfWeight = FW_DONTCARE;
619 orig_lf.lfHeight = 7;
620 orig_lf.lfQuality = DEFAULT_QUALITY;
621 lstrcpyA(orig_lf.lfFaceName, "Arial");
622 hFont = CreateFontIndirectA(&orig_lf);
623 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
625 hFontOld = SelectObject(hdcMetafile, hFont);
627 hFont2 = CreateFontIndirectA(&orig_lf);
628 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
629 hFontCheck = SelectObject(hdcMetafile, hFont2);
630 ok(hFontCheck == hFont, "Font not selected\n");
632 /* Force Win9x to update DC state */
633 SetPixelV(hdcMetafile, 50, 50, 0);
635 ret = RestoreDC(hdcMetafile, 1);
636 ok(ret, "ret = %d\n", ret);
637 ret = GetViewportOrgEx(hdcMetafile, &pt);
638 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
639 ret = GetViewportExtEx(hdcMetafile, &size);
640 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
642 hFontCheck = SelectObject(hdcMetafile, hFontOld);
643 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
644 "Font not reverted with DC Restore\n");
646 ret = RestoreDC(hdcMetafile, -20);
647 ok(!ret, "ret = %d\n", ret);
648 ret = RestoreDC(hdcMetafile, 20);
649 ok(!ret, "ret = %d\n", ret);
651 hMetafile = CloseEnhMetaFile(hdcMetafile);
652 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
654 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
655 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
657 ret = DeleteObject(hFont);
658 ok( ret, "DeleteObject error %d\n", GetLastError());
659 ret = DeleteObject(hFont2);
660 ok( ret, "DeleteObject error %d\n", GetLastError());
661 ret = DeleteEnhMetaFile(hMetafile);
662 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
663 ret = ReleaseDC(hwnd, hdcDisplay);
664 ok( ret, "ReleaseDC error %d\n", GetLastError());
665 DestroyWindow(hwnd);
668 static void test_mf_SaveDC(void)
670 HDC hdcMetafile;
671 HMETAFILE hMetafile;
672 int ret;
673 POINT pt;
674 SIZE size;
675 HFONT hFont,hFont2,hFontOld,hFontCheck;
677 hdcMetafile = CreateMetaFileA(NULL);
678 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
680 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
681 ok (ret, "SetMapMode should not fail\n");
683 /* Need to write something to the emf, otherwise Windows won't play it back */
684 LineTo(hdcMetafile, 150, 150);
686 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
687 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
688 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
689 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
691 /* Force Win9x to update DC state */
692 SetPixelV(hdcMetafile, 50, 50, 0);
694 ret = GetViewportOrgEx(hdcMetafile, &pt);
695 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
696 ret = GetViewportExtEx(hdcMetafile, &size);
697 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
698 ret = SaveDC(hdcMetafile);
699 ok(ret == 1, "ret = %d\n", ret);
701 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
702 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
703 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
704 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
706 /* Force Win9x to update DC state */
707 SetPixelV(hdcMetafile, 50, 50, 0);
709 ret = SaveDC(hdcMetafile);
710 ok(ret == 1, "ret = %d\n", ret);
712 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
713 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
714 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
715 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
717 /* Force Win9x to update DC state */
718 SetPixelV(hdcMetafile, 50, 50, 0);
719 SetPolyFillMode( hdcMetafile, ALTERNATE );
720 SetBkColor( hdcMetafile, 0 );
722 ret = SaveDC(hdcMetafile);
723 ok(ret == 1, "ret = %d\n", ret);
725 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
726 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
727 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
728 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
730 SetPolyFillMode( hdcMetafile, WINDING );
731 SetBkColor( hdcMetafile, 0x123456 );
732 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
733 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
735 /* Force Win9x to update DC state */
736 SetPixelV(hdcMetafile, 50, 50, 0);
738 ret = RestoreDC(hdcMetafile, -1);
739 ok(ret, "ret = %d\n", ret);
741 ret = SaveDC(hdcMetafile);
742 ok(ret == 1, "ret = %d\n", ret);
744 ret = RestoreDC(hdcMetafile, 1);
745 ok(ret, "ret = %d\n", ret);
747 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
748 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
749 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
750 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
752 /* Force Win9x to update DC state */
753 SetPixelV(hdcMetafile, 50, 50, 0);
755 ret = SaveDC(hdcMetafile);
756 ok(ret == 1, "ret = %d\n", ret);
758 ret = SaveDC(hdcMetafile);
759 ok(ret == 1, "ret = %d\n", ret);
761 memset(&orig_lf, 0, sizeof(orig_lf));
762 orig_lf.lfCharSet = ANSI_CHARSET;
763 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
764 orig_lf.lfWeight = FW_DONTCARE;
765 orig_lf.lfHeight = 7;
766 orig_lf.lfQuality = DEFAULT_QUALITY;
767 lstrcpyA(orig_lf.lfFaceName, "Arial");
768 hFont = CreateFontIndirectA(&orig_lf);
769 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
771 hFontOld = SelectObject(hdcMetafile, hFont);
773 hFont2 = CreateFontIndirectA(&orig_lf);
774 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
775 hFontCheck = SelectObject(hdcMetafile, hFont2);
776 ok(hFontCheck == hFont, "Font not selected\n");
778 /* Force Win9x to update DC state */
779 SetPixelV(hdcMetafile, 50, 50, 0);
781 ret = RestoreDC(hdcMetafile, 1);
782 ok(ret, "ret = %d\n", ret);
784 hFontCheck = SelectObject(hdcMetafile, hFontOld);
785 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
787 /* restore level is ignored */
788 ret = RestoreDC(hdcMetafile, -20);
789 ok(ret, "ret = %d\n", ret);
790 ret = RestoreDC(hdcMetafile, 20);
791 ok(ret, "ret = %d\n", ret);
792 ret = RestoreDC(hdcMetafile, 0);
793 ok(ret, "ret = %d\n", ret);
795 hMetafile = CloseMetaFile(hdcMetafile);
796 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
798 ret = DeleteMetaFile(hMetafile);
799 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
800 ret = DeleteObject(hFont);
801 ok( ret, "DeleteObject error %d\n", GetLastError());
802 ret = DeleteObject(hFont2);
803 ok( ret, "DeleteObject error %d\n", GetLastError());
807 /* Win-format metafile (mfdrv) tests */
808 /* These tests compare the generated metafiles byte-by-byte */
809 /* with the nominal results. */
811 /* Maximum size of sample metafiles in bytes. */
812 #define MF_BUFSIZE 512
814 /* 8x8 bitmap data for a pattern brush */
815 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
816 0x01, 0x00, 0x02, 0x00,
817 0x03, 0x00, 0x04, 0x00,
818 0x05, 0x00, 0x06, 0x00,
819 0x07, 0x00, 0x08, 0x00
822 /* Sample metafiles to be compared to the outputs of the
823 * test functions.
826 static const unsigned char MF_BLANK_BITS[] = {
827 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
832 static const unsigned char MF_GRAPHICS_BITS[] = {
833 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
834 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
835 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
836 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
837 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
838 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
839 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
840 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
841 0x00, 0x00, 0x00, 0x00
844 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
845 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
846 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
848 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
849 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
850 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
854 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
855 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
856 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
857 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
858 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
859 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
860 0x00, 0x00
863 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
865 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
866 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
867 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
868 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
869 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
870 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
871 0x00, 0x00
874 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
876 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
881 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
882 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
883 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
886 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
887 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
889 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
890 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
891 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
893 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
894 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
895 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
896 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
899 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
900 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
901 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
902 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
903 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
904 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
906 0x14, 0x00, 0x00, 0x00
909 static const unsigned char MF_LINETO_BITS[] = {
910 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
911 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
912 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
913 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
914 0x00, 0x00
917 static const unsigned char EMF_LINETO_BITS[] = {
918 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
923 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
924 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
925 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
928 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
930 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
931 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
932 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
933 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
934 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
935 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
936 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
937 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
938 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
939 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
941 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
942 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
943 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
944 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
945 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
946 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
947 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
948 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
949 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
950 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
951 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
952 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
953 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
955 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
959 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
960 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
965 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
966 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
967 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
970 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
971 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
972 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
973 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
974 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
975 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
976 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
977 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
978 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
979 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
981 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
983 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
984 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
985 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
986 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
987 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
988 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
989 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
990 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
991 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
992 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
993 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
994 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
995 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
997 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
998 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1001 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1002 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1007 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1008 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1009 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1012 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1015 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1016 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1017 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1018 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1019 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1020 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1021 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1022 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1023 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1025 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1026 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1028 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1030 0x14, 0x00, 0x00, 0x00
1033 /* For debugging or dumping the raw metafiles produced by
1034 * new test functions.
1036 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1037 INT nobj, LPARAM param)
1039 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1040 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1041 return TRUE;
1044 /* For debugging or dumping the raw metafiles produced by
1045 * new test functions.
1048 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1050 BYTE buf[MF_BUFSIZE];
1051 UINT mfsize, i;
1053 if (!winetest_debug) return;
1055 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1056 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1058 printf ("MetaFile %s has bits:\n{\n ", desc);
1059 for (i=0; i<mfsize; i++)
1061 printf ("0x%02x", buf[i]);
1062 if (i == mfsize-1)
1063 printf ("\n");
1064 else if (i % 8 == 7)
1065 printf (",\n ");
1066 else
1067 printf (", ");
1069 printf ("};\n");
1072 /* Compare the metafile produced by a test function with the
1073 * expected raw metafile data in "bits".
1074 * Return value is 0 for a perfect match,
1075 * -1 if lengths aren't equal,
1076 * otherwise returns the number of non-matching bytes.
1079 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1080 const char *desc)
1082 unsigned char buf[MF_BUFSIZE];
1083 UINT mfsize, i;
1084 int diff;
1086 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1087 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1088 if (mfsize < MF_BUFSIZE)
1089 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1090 desc, mfsize, bsize);
1091 else
1092 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1093 desc, mfsize, bsize);
1094 if (mfsize != bsize)
1095 return -1;
1097 diff = 0;
1098 for (i=0; i<bsize; i++)
1100 if (buf[i] != bits[i])
1101 diff++;
1103 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1104 desc, mfsize, bsize, diff);
1106 return diff;
1109 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1111 unsigned char buf[MF_BUFSIZE];
1112 DWORD mfsize, rd_size, i;
1113 int diff;
1114 HANDLE hfile;
1115 BOOL ret;
1117 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1118 assert(hfile != INVALID_HANDLE_VALUE);
1120 mfsize = GetFileSize(hfile, NULL);
1121 assert(mfsize <= MF_BUFSIZE);
1123 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1124 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1126 CloseHandle(hfile);
1128 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1130 if (mfsize != bsize)
1131 return -1;
1133 diff = 0;
1134 for (i=0; i<bsize; i++)
1136 if (buf[i] != bits[i])
1137 diff++;
1139 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1140 desc, mfsize, bsize, diff);
1142 return diff;
1145 /* For debugging or dumping the raw EMFs produced by
1146 * new test functions.
1148 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1150 BYTE buf[MF_BUFSIZE];
1151 UINT mfsize, i;
1153 if (!winetest_debug) return;
1155 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1156 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1158 printf("EMF %s has bits:\n{\n ", desc);
1159 for (i = 0; i < mfsize; i++)
1161 printf ("0x%02x", buf[i]);
1162 if (i == mfsize-1)
1163 printf ("\n");
1164 else if (i % 8 == 7)
1165 printf (",\n ");
1166 else
1167 printf (", ");
1169 printf ("};\n");
1172 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1174 BYTE *emf;
1175 BYTE buf[MF_BUFSIZE];
1176 UINT mfsize, offset;
1178 if (!winetest_debug) return;
1180 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1181 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1183 printf("EMF %s has records:\n", desc);
1185 emf = buf;
1186 offset = 0;
1187 while(offset < mfsize)
1189 EMR *emr = (EMR *)(emf + offset);
1190 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1191 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1192 offset += emr->nSize;
1196 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1198 const BYTE *buf;
1199 DWORD i;
1201 if (!winetest_debug) return;
1203 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1204 buf = (const BYTE *)emr;
1205 for (i = 0; i < emr->nSize; i++)
1207 printf ("0x%02x", buf[i]);
1208 if (i == emr->nSize - 1)
1209 printf ("\n");
1210 else if (i % 8 == 7)
1211 printf (",\n");
1212 else
1213 printf (", ");
1215 printf ("};\n");
1218 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1220 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1221 eto->rclBounds.right, eto->rclBounds.bottom);
1222 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1223 trace("exScale: %f\n", eto->exScale);
1224 trace("eyScale: %f\n", eto->eyScale);
1225 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1226 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1227 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1228 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1229 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1230 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1231 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1234 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1235 const char *desc, BOOL ignore_scaling)
1237 int diff;
1239 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1240 desc, emr1->iType, emr2->iType);
1242 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1243 desc, emr1->nSize, emr2->nSize);
1245 /* iType and nSize mismatches are fatal */
1246 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1248 /* contents of EMR_GDICOMMENT are not interesting */
1249 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1251 /* different Windows versions setup DC scaling differently when
1252 * converting an old style metafile to an EMF.
1254 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1255 emr1->iType == EMR_SETVIEWPORTEXTEX))
1256 return TRUE;
1258 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1260 EMREXTTEXTOUTW *eto1, *eto2;
1262 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1263 memcpy(eto1, emr1, emr1->nSize);
1264 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1265 memcpy(eto2, emr2, emr2->nSize);
1267 /* different Windows versions setup DC scaling differently */
1268 eto1->exScale = eto1->eyScale = 0.0;
1269 eto2->exScale = eto2->eyScale = 0.0;
1271 diff = memcmp(eto1, eto2, emr1->nSize);
1272 if (diff)
1274 dump_EMREXTTEXTOUT(eto1);
1275 dump_EMREXTTEXTOUT(eto2);
1277 HeapFree(GetProcessHeap(), 0, eto1);
1278 HeapFree(GetProcessHeap(), 0, eto2);
1280 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1282 /* We have to take care of NT4 differences here */
1283 diff = memcmp(emr1, emr2, emr1->nSize);
1284 if (diff)
1286 ENHMETARECORD *emr_nt4;
1288 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1289 memcpy(emr_nt4, emr2, emr2->nSize);
1290 /* Correct the nRgnSize field */
1291 emr_nt4->dParm[5] = sizeof(RECT);
1293 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1294 if (!diff)
1295 win_skip("Catered for NT4 differences\n");
1297 HeapFree(GetProcessHeap(), 0, emr_nt4);
1300 else
1301 diff = memcmp(emr1, emr2, emr1->nSize);
1303 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1305 if (diff)
1307 dump_emf_record(emr1, "expected bits");
1308 dump_emf_record(emr2, "actual bits");
1311 return diff == 0; /* report all non-fatal record mismatches */
1314 /* Compare the EMF produced by a test function with the
1315 * expected raw EMF data in "bits".
1316 * Return value is 0 for a perfect match,
1317 * -1 if lengths aren't equal,
1318 * otherwise returns the number of non-matching bytes.
1320 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1321 UINT bsize, const char *desc,
1322 BOOL ignore_scaling)
1324 unsigned char buf[MF_BUFSIZE];
1325 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1326 const ENHMETAHEADER *emh1, *emh2;
1328 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1329 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1331 /* ENHMETAHEADER size could differ, depending on platform */
1332 diff_nt4 = sizeof(SIZEL);
1333 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1335 if (mfsize < MF_BUFSIZE)
1337 ok(mfsize == bsize ||
1338 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1339 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1340 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1342 else
1343 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1344 desc, mfsize, bsize);
1346 /* basic things must match */
1347 emh1 = (const ENHMETAHEADER *)bits;
1348 emh2 = (const ENHMETAHEADER *)buf;
1349 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1350 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1351 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1352 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1354 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1355 ok(emh1->nSize == emh2->nSize ||
1356 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1357 broken(emh1->nSize - diff_9x == emh2->nSize),
1358 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1359 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1360 ok(emh1->nBytes == emh2->nBytes ||
1361 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1362 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1363 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1364 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1366 offset1 = emh1->nSize;
1367 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1368 while (offset1 < emh1->nBytes)
1370 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1371 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1373 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1374 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1376 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1378 /* We have already bailed out if iType or nSize don't match */
1379 offset1 += emr1->nSize;
1380 offset2 += emr2->nSize;
1382 return 0;
1385 /* Test a blank metafile. May be used as a template for new tests. */
1387 static void test_mf_Blank(void)
1389 HDC hdcMetafile;
1390 HMETAFILE hMetafile;
1391 INT caps;
1392 BOOL ret;
1393 INT type;
1395 hdcMetafile = CreateMetaFileA(NULL);
1396 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1397 trace("hdcMetafile %p\n", hdcMetafile);
1399 /* Tests on metafile initialization */
1400 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1401 ok (caps == DT_METAFILE,
1402 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1404 hMetafile = CloseMetaFile(hdcMetafile);
1405 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1406 type = GetObjectType(hMetafile);
1407 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1408 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1410 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1411 "mf_blank") != 0)
1413 dump_mf_bits(hMetafile, "mf_Blank");
1414 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1417 ret = DeleteMetaFile(hMetafile);
1418 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1421 static void test_CopyMetaFile(void)
1423 HDC hdcMetafile;
1424 HMETAFILE hMetafile, hmf_copy;
1425 BOOL ret;
1426 char temp_path[MAX_PATH];
1427 char mf_name[MAX_PATH];
1428 INT type;
1430 hdcMetafile = CreateMetaFileA(NULL);
1431 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1432 trace("hdcMetafile %p\n", hdcMetafile);
1434 hMetafile = CloseMetaFile(hdcMetafile);
1435 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1436 type = GetObjectType(hMetafile);
1437 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1439 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1440 "mf_blank") != 0)
1442 dump_mf_bits(hMetafile, "mf_Blank");
1443 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1446 GetTempPathA(MAX_PATH, temp_path);
1447 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1449 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1450 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1452 type = GetObjectType(hmf_copy);
1453 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1455 ret = DeleteMetaFile(hMetafile);
1456 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1458 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1460 dump_mf_bits(hMetafile, "mf_Blank");
1461 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1464 ret = DeleteMetaFile(hmf_copy);
1465 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1467 DeleteFileA(mf_name);
1470 static void test_SetMetaFileBits(void)
1472 HMETAFILE hmf;
1473 INT type;
1474 BOOL ret;
1475 BYTE buf[256];
1476 METAHEADER *mh;
1478 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1479 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1480 type = GetObjectType(hmf);
1481 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1483 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1485 dump_mf_bits(hmf, "mf_Graphics");
1486 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1489 ret = DeleteMetaFile(hmf);
1490 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1492 /* NULL data crashes XP SP1 */
1493 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1495 /* Now with not zero size */
1496 SetLastError(0xdeadbeef);
1497 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1498 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1499 ok(GetLastError() == ERROR_INVALID_DATA ||
1500 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1501 "wrong error %d\n", GetLastError());
1503 /* Now with not even size */
1504 SetLastError(0xdeadbeef);
1505 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1506 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1507 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1509 /* Now with zeroed out or faked some header fields */
1510 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1511 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1512 mh = (METAHEADER *)buf;
1513 /* corruption of any of the below fields leads to a failure */
1514 mh->mtType = 0;
1515 mh->mtVersion = 0;
1516 mh->mtHeaderSize = 0;
1517 SetLastError(0xdeadbeef);
1518 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1519 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1520 ok(GetLastError() == ERROR_INVALID_DATA ||
1521 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1522 "wrong error %d\n", GetLastError());
1524 /* Now with corrupted mtSize field */
1525 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1526 mh = (METAHEADER *)buf;
1527 /* corruption of mtSize doesn't lead to a failure */
1528 mh->mtSize *= 2;
1529 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1530 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1532 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1534 dump_mf_bits(hmf, "mf_Graphics");
1535 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1538 ret = DeleteMetaFile(hmf);
1539 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1541 /* Now with zeroed out mtSize field */
1542 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1543 mh = (METAHEADER *)buf;
1544 /* zeroing mtSize doesn't lead to a failure */
1545 mh->mtSize = 0;
1546 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1547 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1549 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1551 dump_mf_bits(hmf, "mf_Graphics");
1552 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1555 ret = DeleteMetaFile(hmf);
1556 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1559 /* Simple APIs from mfdrv/graphics.c
1562 static void test_mf_Graphics(void)
1564 HDC hdcMetafile;
1565 HMETAFILE hMetafile;
1566 POINT oldpoint;
1567 BOOL ret;
1569 hdcMetafile = CreateMetaFileA(NULL);
1570 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1571 trace("hdcMetafile %p\n", hdcMetafile);
1573 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1574 ok( ret, "MoveToEx error %d.\n", GetLastError());
1575 ret = LineTo(hdcMetafile, 2, 2);
1576 ok( ret, "LineTo error %d.\n", GetLastError());
1577 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1578 ok( ret, "MoveToEx error %d.\n", GetLastError());
1580 /* oldpoint gets garbage under Win XP, so the following test would
1581 * work under Wine but fails under Windows:
1583 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1584 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1585 * oldpoint.x, oldpoint.y);
1588 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1589 ok( ret, "Ellipse error %d.\n", GetLastError());
1591 hMetafile = CloseMetaFile(hdcMetafile);
1592 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1593 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1595 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1596 "mf_Graphics") != 0)
1598 dump_mf_bits(hMetafile, "mf_Graphics");
1599 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1602 ret = DeleteMetaFile(hMetafile);
1603 ok( ret, "DeleteMetaFile(%p) error %d\n",
1604 hMetafile, GetLastError());
1607 static void test_mf_PatternBrush(void)
1609 HDC hdcMetafile;
1610 HMETAFILE hMetafile;
1611 LOGBRUSH *orig_lb;
1612 HBRUSH hBrush;
1613 BOOL ret;
1615 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1617 orig_lb->lbStyle = BS_PATTERN;
1618 orig_lb->lbColor = RGB(0, 0, 0);
1619 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1620 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1622 hBrush = CreateBrushIndirect (orig_lb);
1623 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1625 hdcMetafile = CreateMetaFileA(NULL);
1626 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1627 trace("hdcMetafile %p\n", hdcMetafile);
1629 hBrush = SelectObject(hdcMetafile, hBrush);
1630 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1632 hMetafile = CloseMetaFile(hdcMetafile);
1633 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1634 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1636 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1637 "mf_Pattern_Brush") != 0)
1639 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1640 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1643 ret = DeleteMetaFile(hMetafile);
1644 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1645 ret = DeleteObject(hBrush);
1646 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1647 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1648 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1649 GetLastError());
1650 HeapFree (GetProcessHeap(), 0, orig_lb);
1653 static void test_mf_ExtTextOut_on_path(void)
1655 HDC hdcMetafile;
1656 HMETAFILE hMetafile;
1657 BOOL ret;
1658 static const INT dx[4] = { 3, 5, 8, 12 };
1660 hdcMetafile = CreateMetaFileA(NULL);
1661 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1662 trace("hdcMetafile %p\n", hdcMetafile);
1664 ret = BeginPath(hdcMetafile);
1665 ok(!ret, "BeginPath on metafile DC should fail\n");
1667 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1668 ok(ret, "ExtTextOut error %d\n", GetLastError());
1670 ret = EndPath(hdcMetafile);
1671 ok(!ret, "EndPath on metafile DC should fail\n");
1673 hMetafile = CloseMetaFile(hdcMetafile);
1674 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1676 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1677 "mf_TextOut_on_path") != 0)
1679 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1680 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1683 ret = DeleteMetaFile(hMetafile);
1684 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1687 static void test_emf_ExtTextOut_on_path(void)
1689 HWND hwnd;
1690 HDC hdcDisplay, hdcMetafile;
1691 HENHMETAFILE hMetafile;
1692 BOOL ret;
1693 static const INT dx[4] = { 3, 5, 8, 12 };
1695 /* Win9x doesn't play EMFs on invisible windows */
1696 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1697 0, 0, 200, 200, 0, 0, 0, NULL);
1698 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1700 hdcDisplay = GetDC(hwnd);
1701 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1703 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1704 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1706 ret = BeginPath(hdcMetafile);
1707 ok(ret, "BeginPath error %d\n", GetLastError());
1709 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1710 ok(ret, "ExtTextOut error %d\n", GetLastError());
1712 ret = EndPath(hdcMetafile);
1713 ok(ret, "EndPath error %d\n", GetLastError());
1715 hMetafile = CloseEnhMetaFile(hdcMetafile);
1716 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1718 /* this doesn't succeed yet: EMF has correct size, all EMF records
1719 * are there, but their contents don't match for different reasons.
1721 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1722 "emf_TextOut_on_path", FALSE) != 0)
1724 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1725 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1728 ret = DeleteEnhMetaFile(hMetafile);
1729 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1730 ret = ReleaseDC(hwnd, hdcDisplay);
1731 ok(ret, "ReleaseDC error %d\n", GetLastError());
1732 DestroyWindow(hwnd);
1735 static const unsigned char EMF_CLIPPING[] =
1737 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1738 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1739 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1741 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1742 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1743 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1744 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1746 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1747 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1749 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1750 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1751 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1752 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1753 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1754 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1755 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1756 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1757 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1758 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1759 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1760 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1761 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1762 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1765 static void translate( POINT *pt, UINT count, const XFORM *xform )
1767 while (count--)
1769 FLOAT x = (FLOAT)pt->x;
1770 FLOAT y = (FLOAT)pt->y;
1771 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1772 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1773 pt++;
1777 /* Compare rectangles allowing rounding errors */
1778 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1780 return abs(rc1->left - rc2->left) <= 1 &&
1781 abs(rc1->top - rc2->top) <= 1 &&
1782 abs(rc1->right - rc2->right) <= 1 &&
1783 abs(rc1->bottom - rc2->bottom) <= 1;
1786 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1787 const ENHMETARECORD *emr, int n_objs, LPARAM param)
1789 if (emr->iType == EMR_EXTSELECTCLIPRGN)
1791 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1792 union _rgn
1794 RGNDATA data;
1795 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1797 const union _rgn *rgn1;
1798 union _rgn rgn2;
1799 RECT rect, rc_transformed;
1800 const RECT *rc = (const RECT *)param;
1801 HRGN hrgn;
1802 XFORM xform;
1803 INT ret;
1804 BOOL is_win9x;
1806 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1807 clip->cbRgnData, clip->iMode);
1809 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1810 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1811 "too small data block: %u bytes\n", clip->cbRgnData);
1812 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1813 return 0;
1815 rgn1 = (const union _rgn *)clip->RgnData;
1817 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1818 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1819 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1820 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1821 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1823 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1825 rect = *(const RECT *)rgn1->data.Buffer;
1826 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1827 ok(EqualRect(&rect, rc), "rects don't match\n");
1829 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1830 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1831 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1832 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
1833 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
1834 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1836 hrgn = CreateRectRgn(0, 0, 0, 0);
1838 memset(&xform, 0, sizeof(xform));
1839 SetLastError(0xdeadbeef);
1840 ret = GetWorldTransform(hdc, &xform);
1841 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1842 if (!is_win9x)
1843 ok(ret, "GetWorldTransform error %u\n", GetLastError());
1845 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1847 ret = GetClipRgn(hdc, hrgn);
1848 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1850 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1852 ret = GetClipRgn(hdc, hrgn);
1853 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
1855 /* Win9x returns empty clipping region */
1856 if (is_win9x) return 1;
1858 ret = GetRegionData(hrgn, 0, NULL);
1859 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1861 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1863 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1864 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1865 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1866 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1867 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1869 rect = rgn2.data.rdh.rcBound;
1870 rc_transformed = *rc;
1871 translate((POINT *)&rc_transformed, 2, &xform);
1872 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1873 rc_transformed.right, rc_transformed.bottom);
1874 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1876 rect = *(const RECT *)rgn2.data.Buffer;
1877 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1878 rc_transformed = *rc;
1879 translate((POINT *)&rc_transformed, 2, &xform);
1880 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1881 rc_transformed.right, rc_transformed.bottom);
1882 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1884 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1885 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1886 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1887 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
1888 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
1889 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1891 DeleteObject(hrgn);
1893 return 1;
1896 static void test_emf_clipping(void)
1898 static const RECT rc = { 0, 0, 100, 100 };
1899 RECT rc_clip = { 100, 100, 1024, 1024 };
1900 HWND hwnd;
1901 HDC hdc;
1902 HENHMETAFILE hemf;
1903 HRGN hrgn;
1904 INT ret;
1906 SetLastError(0xdeadbeef);
1907 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1908 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1910 /* Need to write something to the emf, otherwise Windows won't play it back */
1911 LineTo(hdc, 1, 1);
1913 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1914 ret = SelectClipRgn(hdc, hrgn);
1915 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1917 SetLastError(0xdeadbeef);
1918 hemf = CloseEnhMetaFile(hdc);
1919 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1921 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1922 "emf_clipping", FALSE) != 0)
1924 dump_emf_bits(hemf, "emf_clipping");
1925 dump_emf_records(hemf, "emf_clipping");
1928 DeleteObject(hrgn);
1930 /* Win9x doesn't play EMFs on invisible windows */
1931 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1932 0, 0, 200, 200, 0, 0, 0, NULL);
1933 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1935 hdc = GetDC(hwnd);
1937 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1938 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1940 DeleteEnhMetaFile(hemf);
1941 ReleaseDC(hwnd, hdc);
1942 DestroyWindow(hwnd);
1945 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1947 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1948 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1949 /* When using MM_TEXT Win9x does not update the mapping mode
1950 * until a record is played which actually outputs something */
1951 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1952 LPtoDP(hdc, mapping, 2);
1953 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1954 lpEMFR->iType, lpEMFR->nSize,
1955 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1957 if (lpEMFR->iType == EMR_LINETO)
1959 INT x0, y0, x1, y1;
1960 if (!lpMFP || lpMFP->mm == MM_TEXT)
1962 x0 = 0;
1963 y0 = 0;
1964 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1965 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1967 else
1969 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1971 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1972 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1973 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1974 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1976 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1977 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1978 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1979 x0, y0, x1, y1);
1981 return TRUE;
1984 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1986 HDC hdcMf;
1987 HMETAFILE hmf;
1988 HENHMETAFILE hemf;
1989 BOOL ret;
1990 UINT size;
1991 LPBYTE pBits;
1993 hdcMf = CreateMetaFile(NULL);
1994 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1995 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1996 ok(ret, "LineTo failed with error %d\n", GetLastError());
1997 hmf = CloseMetaFile(hdcMf);
1998 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2000 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2002 dump_mf_bits(hmf, "mf_LineTo");
2003 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2006 size = GetMetaFileBitsEx(hmf, 0, NULL);
2007 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2008 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2009 GetMetaFileBitsEx(hmf, size, pBits);
2010 DeleteMetaFile(hmf);
2011 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2012 HeapFree(GetProcessHeap(), 0, pBits);
2013 return hemf;
2016 static void test_mf_conversions(void)
2018 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2020 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2021 HENHMETAFILE hemf;
2022 METAFILEPICT mfp;
2023 RECT rect = { 0, 0, 100, 100 };
2024 mfp.mm = MM_ANISOTROPIC;
2025 mfp.xExt = 100;
2026 mfp.yExt = 100;
2027 mfp.hMF = NULL;
2028 hemf = create_converted_emf(&mfp);
2030 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2031 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2033 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2034 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2037 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2039 DeleteEnhMetaFile(hemf);
2040 DeleteDC(hdcOffscreen);
2043 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2045 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2046 HENHMETAFILE hemf;
2047 METAFILEPICT mfp;
2048 RECT rect = { 0, 0, 100, 100 };
2049 mfp.mm = MM_TEXT;
2050 mfp.xExt = 0;
2051 mfp.yExt = 0;
2052 mfp.hMF = NULL;
2053 hemf = create_converted_emf(&mfp);
2055 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2056 "emf_LineTo MM_TEXT", TRUE) != 0)
2058 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2059 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2062 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2064 DeleteEnhMetaFile(hemf);
2065 DeleteDC(hdcOffscreen);
2068 trace("Testing MF->EMF conversion (NULL mfp)\n");
2070 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2071 HENHMETAFILE hemf;
2072 RECT rect = { 0, 0, 100, 100 };
2073 hemf = create_converted_emf(NULL);
2075 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2076 "emf_LineTo NULL", TRUE) != 0)
2078 dump_emf_bits(hemf, "emf_LineTo NULL");
2079 dump_emf_records(hemf, "emf_LineTo NULL");
2082 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2084 DeleteEnhMetaFile(hemf);
2085 DeleteDC(hdcOffscreen);
2089 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2090 LONG mm, LONG xExt, LONG yExt,
2091 RECTL * rclBounds, RECTL * rclFrame)
2093 METAFILEPICT mfp;
2094 METAFILEPICT * mfpPtr = NULL;
2095 HENHMETAFILE emf;
2096 ENHMETAHEADER header;
2097 UINT res;
2099 if (!mfpIsNull)
2101 mfp.mm = mm;
2102 mfp.xExt = xExt;
2103 mfp.yExt = yExt;
2104 mfpPtr = &mfp;
2107 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2108 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2109 if (!emf) return FALSE;
2110 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2111 ok(res != 0, "GetEnhMetaHeader failed\n");
2112 DeleteEnhMetaFile(emf);
2113 if (!res) return FALSE;
2115 *rclBounds = header.rclBounds;
2116 *rclFrame = header.rclFrame;
2117 return TRUE;
2120 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2121 LONG mm, LONG xExt, LONG yExt,
2122 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2124 RECTL rclBounds, rclFrame;
2126 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2128 const char * msg;
2129 char buf[64];
2131 if (mfpIsNull)
2133 msg = "mfp == NULL";
2135 else
2137 const char * mm_str;
2138 switch (mm)
2140 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2141 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2142 default: mm_str = "Unexpected";
2144 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2145 msg = buf;
2148 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2149 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2150 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2151 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2152 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2153 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2154 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2155 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2159 static void test_SetWinMetaFileBits(void)
2161 HMETAFILE wmf;
2162 HDC wmfDC;
2163 BYTE * buffer;
2164 UINT buffer_size;
2165 RECT rect;
2166 UINT res;
2167 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2168 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2169 RECTL rclBounds, rclFrame;
2170 HDC dc;
2171 LONG diffx, diffy;
2173 wmfDC = CreateMetaFile(NULL);
2174 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2175 if (!wmfDC) return;
2177 SetWindowExtEx(wmfDC, 100, 100, NULL);
2178 rect.left = rect.top = 0;
2179 rect.right = rect.bottom = 50;
2180 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2181 wmf = CloseMetaFile(wmfDC);
2182 ok(wmf != NULL, "Metafile creation failed\n");
2183 if (!wmf) return;
2185 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2186 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2187 if (buffer_size == 0)
2189 DeleteMetaFile(wmf);
2190 return;
2193 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2194 ok(buffer != NULL, "HeapAlloc failed\n");
2195 if (!buffer)
2197 DeleteMetaFile(wmf);
2198 return;
2201 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2202 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2203 DeleteMetaFile(wmf);
2204 if (res != buffer_size)
2206 HeapFree(GetProcessHeap(), 0, buffer);
2207 return;
2210 /* Get the reference bounds and frame */
2211 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2212 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2214 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2215 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2216 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2218 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2219 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2220 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2221 if (diffx < 0) diffx = -diffx;
2222 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2224 dc = CreateCompatibleDC(NULL);
2226 /* Allow 1 mm difference (rounding errors) */
2227 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2228 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2229 if (diffx < 0) diffx = -diffx;
2230 if (diffy < 0) diffy = -diffy;
2231 todo_wine
2233 ok(diffx <= 1 && diffy <= 1,
2234 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2235 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2238 /* Allow 1 mm difference (rounding errors) */
2239 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2240 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2241 if (diffx < 0) diffx = -diffx;
2242 if (diffy < 0) diffy = -diffy;
2243 todo_wine
2245 ok(diffx <= 1 && diffy <= 1,
2246 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2247 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2249 DeleteDC(dc);
2251 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2252 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2254 /* If xExt or yExt is zero or negative, the whole device surface is used */
2255 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2256 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2257 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2258 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2259 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2260 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2261 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2262 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2263 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2264 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2265 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2266 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2268 /* MSDN says that negative xExt and yExt values specify a ratio.
2269 Check that this is wrong and the whole device surface is used */
2270 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2271 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2273 /* Ordinary conversions */
2275 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2277 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2278 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2279 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2280 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2283 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2285 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2286 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2287 ok(rclBounds.left == 0 && rclBounds.top == 0,
2288 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2290 /* Wine has a rounding error */
2291 diffx = rclBounds.right - rclBounds.bottom;
2292 if (diffx < 0) diffx = -diffx;
2293 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2296 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2298 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2299 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2302 HeapFree(GetProcessHeap(), 0, buffer);
2305 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2306 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2307 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2309 static void test_gdiis(void)
2311 RECT rect = {0,0,100,100};
2312 HDC hdc, hemfDC, hmfDC;
2313 HENHMETAFILE hemf;
2314 HMODULE hgdi32;
2316 /* resolve all the functions */
2317 hgdi32 = GetModuleHandle("gdi32");
2318 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2319 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2320 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2322 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2324 win_skip("Needed GdiIs* functions are not available\n");
2325 return;
2328 /* try with nothing */
2329 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2330 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2331 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2333 /* try with a metafile */
2334 hmfDC = CreateMetaFile(NULL);
2335 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2336 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2337 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2338 DeleteMetaFile(CloseMetaFile(hmfDC));
2340 /* try with an enhanced metafile */
2341 hdc = GetDC(NULL);
2342 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2343 ok(hemfDC != NULL, "failed to create emf\n");
2345 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2346 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2347 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2349 hemf = CloseEnhMetaFile(hemfDC);
2350 ok(hemf != NULL, "failed to close EMF\n");
2351 DeleteEnhMetaFile(hemf);
2352 ReleaseDC(NULL,hdc);
2355 static void test_SetEnhMetaFileBits(void)
2357 BYTE data[256];
2358 HENHMETAFILE hemf;
2359 ENHMETAHEADER *emh;
2361 memset(data, 0xAA, sizeof(data));
2362 SetLastError(0xdeadbeef);
2363 hemf = SetEnhMetaFileBits(sizeof(data), data);
2364 ok(!hemf, "SetEnhMetaFileBits should fail\n");
2365 ok(GetLastError() == ERROR_INVALID_DATA ||
2366 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2367 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2369 emh = (ENHMETAHEADER *)data;
2370 memset(emh, 0, sizeof(*emh));
2372 emh->iType = EMR_HEADER;
2373 emh->nSize = sizeof(*emh);
2374 emh->dSignature = ENHMETA_SIGNATURE;
2375 /* emh->nVersion = 0x10000; XP doesn't care about version */
2376 emh->nBytes = sizeof(*emh);
2377 /* emh->nRecords = 1; XP doesn't care about records */
2378 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2380 SetLastError(0xdeadbeef);
2381 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2382 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2383 DeleteEnhMetaFile(hemf);
2385 /* XP refuses to load unaligned EMF */
2386 emh->nBytes++;
2387 SetLastError(0xdeadbeef);
2388 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2389 ok(!hemf ||
2390 broken(hemf != NULL), /* Win9x, WinMe */
2391 "SetEnhMetaFileBits should fail\n");
2392 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2393 DeleteEnhMetaFile(hemf);
2395 emh->dSignature = 0;
2396 emh->nBytes--;
2397 SetLastError(0xdeadbeef);
2398 hemf = SetEnhMetaFileBits(emh->nBytes, data);
2399 ok(!hemf ||
2400 broken(hemf != NULL), /* Win9x, WinMe */
2401 "SetEnhMetaFileBits should fail\n");
2402 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2403 DeleteEnhMetaFile(hemf);
2406 START_TEST(metafile)
2408 init_function_pointers();
2410 /* For enhanced metafiles (enhmfdrv) */
2411 test_ExtTextOut();
2412 test_SaveDC();
2414 /* For win-format metafiles (mfdrv) */
2415 test_mf_SaveDC();
2416 test_mf_Blank();
2417 test_mf_Graphics();
2418 test_mf_PatternBrush();
2419 test_CopyMetaFile();
2420 test_SetMetaFileBits();
2421 test_mf_ExtTextOut_on_path();
2422 test_emf_ExtTextOut_on_path();
2423 test_emf_clipping();
2425 /* For metafile conversions */
2426 test_mf_conversions();
2427 test_SetWinMetaFileBits();
2429 test_gdiis();
2430 test_SetEnhMetaFileBits();