wined3d: Pass gl_info to surface_bind().
[wine] / dlls / gdi32 / tests / metafile.c
1 /*
2  * Unit tests for metafile functions
3  *
4  * Copyright (c) 2002 Dmitry Timoshkov
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
24
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
33
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
37
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
40
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); \
45
46 static void init_function_pointers(void)
47 {
48     HMODULE hGDI;
49
50     pGetRelAbs = NULL;
51     pSetRelAbs = NULL;
52
53     hGDI = GetModuleHandleA("gdi32.dll");
54     assert(hGDI);
55     GDI_GET_PROC(GetRelAbs);
56     GDI_GET_PROC(SetRelAbs);
57 }
58
59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60     const ENHMETARECORD *emr, int n_objs, LPARAM param)
61 {
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;
68
69     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70            hdc, emr->iType, emr->nSize, (void *)param);
71
72     if(!hdc) return 1;
73
74     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
75
76     switch (emr->iType)
77     {
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));
86
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));
91
92         n_record = 0;
93         break;
94
95     case EMR_EXTTEXTOUTA:
96     {
97         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
98         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
99
100         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
102
103         /* compare up to lfOutPrecision, other values are not interesting,
104          * and in fact sometimes arbitrary adapted by Win9x.
105          */
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");
108
109         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
110         {
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]);
113         }
114         n_record++;
115         emr_processed = TRUE;
116         break;
117     }
118
119     case EMR_EXTTEXTOUTW:
120     {
121         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
123
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());
129
130         /* compare up to lfOutPrecision, other values are not interesting,
131          * and in fact sometimes arbitrary adapted by Win9x.
132          */
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");
135
136         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
137         {
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]);
140         }
141         n_record++;
142         emr_processed = TRUE;
143         break;
144     }
145
146     default:
147         break;
148     }
149
150     return 1;
151 }
152
153 static void test_ExtTextOut(void)
154 {
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;
163
164     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
165
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());
170
171     hdcDisplay = GetDC(hwnd);
172     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
173
174     trace("hdcDisplay %p\n", hdcDisplay);
175
176     SetMapMode(hdcDisplay, MM_TEXT);
177
178     memset(&orig_lf, 0, sizeof(orig_lf));
179
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());
188
189     hFont = SelectObject(hdcDisplay, hFont);
190
191     len = lstrlenA(text);
192     for (i = 0; i < len; i++)
193     {
194         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
195         ok( ret, "GetCharWidthA error %d\n", GetLastError());
196     }
197     hFont = SelectObject(hdcDisplay, hFont);
198
199     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
200     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
201
202     trace("hdcMetafile %p\n", hdcMetafile);
203
204     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
205        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
206
207     hFont = SelectObject(hdcMetafile, hFont);
208
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());
212
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());
216
217     hFont = SelectObject(hdcMetafile, hFont);
218     ret = DeleteObject(hFont);
219     ok( ret, "DeleteObject error %d\n", GetLastError());
220
221     hMetafile = CloseEnhMetaFile(hdcMetafile);
222     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
223
224     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
225
226     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
227     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
228
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);
236
237     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
238     SetBkMode(hdcDisplay, OPAQUE);
239
240     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
241     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
242
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));
251
252     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
253
254     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
255        "A valid hdc has to require a valid rc\n");
256
257     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
258        "A null hdc does not require a valid rc\n");
259
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);
265 }
266
267 struct eto_scale_test_record
268 {
269     INT graphics_mode;
270     INT map_mode;
271     double ex_scale;
272     double ey_scale;
273     BOOL processed;
274 };
275
276 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
277     const ENHMETARECORD *emr, int n_objs, LPARAM param)
278 {
279     struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
280
281     if (emr->iType == EMR_EXTTEXTOUTW)
282     {
283         const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
284         trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
285               test->graphics_mode, test->map_mode,
286               pExtTextOutW->exScale, pExtTextOutW->eyScale,
287               test->ex_scale, test->ey_scale);
288         ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
289            "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
290         ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
291            "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
292         test->processed = TRUE;
293     }
294
295     return 1;
296 }
297
298 static void test_ExtTextOutScale(void)
299 {
300     const RECT rc = { 0, 0, 100, 100 };
301     const WCHAR str[] = {'a',0 };
302     struct eto_scale_test_record test;
303     HDC hdcDisplay, hdcMetafile;
304     HENHMETAFILE hMetafile;
305     HWND hwnd;
306     SIZE wndext, vportext;
307     int horzSize, vertSize, horzRes, vertRes;
308     int ret;
309     int i;
310
311     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
312                            0, 0, 200, 200, 0, 0, 0, NULL);
313     ok(hwnd != 0, "CreateWindowExA failed\n");
314
315     hdcDisplay = GetDC(hwnd);
316     ok(hdcDisplay != 0, "GetDC failed\n");
317
318     horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
319     horzRes  = GetDeviceCaps(hdcDisplay, HORZRES);
320     vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
321     vertRes  = GetDeviceCaps(hdcDisplay, VERTRES);
322     ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
323
324     for (i = 0; i < 16; i++)
325     {
326         test.graphics_mode = i / 8 + 1;
327         test.map_mode      = i % 8 + 1;
328
329         ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
330         ok(ret, "SetGraphicsMode failed\n");
331         ret = SetMapMode(hdcDisplay, test.map_mode);
332         ok(ret, "SetMapMode failed\n");
333
334         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
335         {
336             ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
337             ok(ret, "SetWindowExtEx failed\n");
338             ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
339             ok(ret, "SetViewportExtEx failed\n");
340         }
341
342         ret = GetViewportExtEx(hdcDisplay, &vportext);
343         ok(ret, "GetViewportExtEx failed\n");
344         ret = GetWindowExtEx(hdcDisplay, &wndext);
345         ok(ret, "GetWindowExtEx failed\n");
346
347         trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
348                test.graphics_mode, test.map_mode,
349                wndext.cx, wndext.cy, vportext.cx, vportext.cy,
350                horzSize, horzRes, vertSize, vertRes);
351
352         if (test.graphics_mode == GM_COMPATIBLE)
353         {
354             test.ex_scale = 100.0 * ((FLOAT)horzSize  / (FLOAT)horzRes) /
355                                     ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
356             test.ey_scale = 100.0 * ((FLOAT)vertSize  / (FLOAT)vertRes) /
357                                     ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
358         }
359         else
360         {
361             test.ex_scale = 0.0;
362             test.ey_scale = 0.0;
363         }
364
365         hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
366         ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
367
368         ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
369         ok(ret, "SetGraphicsMode failed\n");
370         ret = SetMapMode(hdcMetafile, test.map_mode);
371         ok(ret, "SetMapMode failed\n");
372
373         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
374         {
375             ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
376             ok(ret, "SetWindowExtEx failed\n");
377             ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
378             ok(ret, "SetViewportExtEx failed\n");
379         }
380
381         ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
382         ok(ret, "ExtTextOutW failed\n");
383
384         hMetafile = CloseEnhMetaFile(hdcMetafile);
385         ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
386
387         test.processed = 0;
388         ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
389         ok(ret, "EnumEnhMetaFile failed\n");
390         ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
391
392         ret = DeleteEnhMetaFile(hMetafile);
393         ok(ret, "DeleteEnhMetaFile failed\n");
394     }
395
396     ret = ReleaseDC(hwnd, hdcDisplay);
397     ok(ret, "ReleaseDC failed\n");
398     DestroyWindow(hwnd);
399 }
400
401
402 static void check_dc_state(HDC hdc, int restore_no,
403                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
404                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
405 {
406     BOOL ret;
407     XFORM xform;
408     POINT vp_org, win_org;
409     SIZE vp_size, win_size;
410     FLOAT xscale, yscale, edx, edy;
411
412     SetLastError(0xdeadbeef);
413     ret = GetWorldTransform(hdc, &xform);
414     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
415     ok(ret, "GetWorldTransform error %u\n", GetLastError());
416
417     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
418
419     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
420     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
421
422     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
423     trace("x scale %f\n", xscale);
424     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
425        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
426
427     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
428     trace("y scale %f\n", yscale);
429     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
430        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
431
432     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
433     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
434     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
435     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
436
437     return;
438
439 win9x_here:
440
441     GetWindowOrgEx(hdc, &win_org);
442     GetViewportOrgEx(hdc, &vp_org);
443     GetWindowExtEx(hdc, &win_size);
444     GetViewportExtEx(hdc, &vp_size);
445
446     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
447     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
448
449     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
450     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
451
452     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
453     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
454
455     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
456     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
457 }
458
459 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
460                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
461 {
462     BOOL ret;
463     XFORM xform;
464     POINT pt;
465     SIZE size;
466     static int save_state;
467     static int restore_no;
468     static int select_no;
469
470     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
471            hdc, emr->iType, emr->nSize, (void *)param);
472
473     trace("BEFORE:\n");
474     SetLastError(0xdeadbeef);
475     ret = GetWorldTransform(hdc, &xform);
476     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
477     {
478         ret = GetWindowOrgEx(hdc, &pt);
479         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
480         trace("window org (%d,%d)\n", pt.x, pt.y);
481         ret = GetViewportOrgEx(hdc, &pt);
482         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
483         trace("vport org (%d,%d)\n", pt.x, pt.y);
484         ret = GetWindowExtEx(hdc, &size);
485         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
486         trace("window ext (%d,%d)\n", size.cx, size.cy);
487         ret = GetViewportExtEx(hdc, &size);
488         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
489         trace("vport ext (%d,%d)\n", size.cx, size.cy);
490     }
491     else
492     {
493         ok(ret, "GetWorldTransform error %u\n", GetLastError());
494         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
495     }
496
497     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
498
499     switch (emr->iType)
500     {
501     case EMR_HEADER:
502     {
503         static RECT exp_bounds = { 0, 0, 150, 150 };
504         RECT bounds;
505         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
506
507         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
508                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
509                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
510         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
511                emf->szlDevice.cx, emf->szlDevice.cy);
512
513         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
514         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
515
516         save_state = 0;
517         restore_no = 0;
518         select_no = 0;
519         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
520         break;
521     }
522
523     case EMR_LINETO:
524         {
525             const EMRLINETO *line = (const EMRLINETO *)emr;
526             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
527             break;
528         }
529     case EMR_SETWINDOWORGEX:
530         {
531             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
532             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
533             break;
534         }
535     case EMR_SETWINDOWEXTEX:
536         {
537             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
538             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
539             break;
540         }
541     case EMR_SETVIEWPORTORGEX:
542         {
543             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
544             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
545             break;
546         }
547     case EMR_SETVIEWPORTEXTEX:
548         {
549             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
550             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
551             break;
552         }
553     case EMR_SAVEDC:
554         save_state++;
555         trace("EMR_SAVEDC\n");
556         break;
557
558     case EMR_RESTOREDC:
559         {
560             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
561             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
562
563             switch(++restore_no)
564             {
565             case 1:
566                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
567                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
568                 break;
569             case 2:
570                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
571                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
572                 break;
573             case 3:
574                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
575                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
576                 break;
577             }
578             ok(restore_no <= 3, "restore_no %d\n", restore_no);
579             save_state += restoredc->iRelative;
580             break;
581         }
582     case EMR_SELECTOBJECT:
583         {
584             const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
585             trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
586             select_no ++;
587             break;
588         }
589     case EMR_EOF:
590         ok(save_state == 0, "EOF save_state %d\n", save_state);
591         ok(select_no == 3, "Too many/few selects  %i\n",select_no);
592         break;
593     }
594
595     trace("AFTER:\n");
596     SetLastError(0xdeadbeef);
597     ret = GetWorldTransform(hdc, &xform);
598     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
599     {
600         ret = GetWindowOrgEx(hdc, &pt);
601         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
602         trace("window org (%d,%d)\n", pt.x, pt.y);
603         ret = GetViewportOrgEx(hdc, &pt);
604         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
605         trace("vport org (%d,%d)\n", pt.x, pt.y);
606         ret = GetWindowExtEx(hdc, &size);
607         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
608         trace("window ext (%d,%d)\n", size.cx, size.cy);
609         ret = GetViewportExtEx(hdc, &size);
610         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
611         trace("vport ext (%d,%d)\n", size.cx, size.cy);
612     }
613     else
614     {
615         ok(ret, "GetWorldTransform error %u\n", GetLastError());
616         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
617     }
618
619     return 1;
620 }
621
622 static void test_SaveDC(void)
623 {
624     HDC hdcMetafile, hdcDisplay;
625     HENHMETAFILE hMetafile;
626     HWND hwnd;
627     int ret;
628     POINT pt;
629     SIZE size;
630     HFONT hFont,hFont2,hFontOld,hFontCheck;
631     static const RECT rc = { 0, 0, 150, 150 };
632
633     /* Win9x doesn't play EMFs on invisible windows */
634     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
635                            0, 0, 200, 200, 0, 0, 0, NULL);
636     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
637
638     hdcDisplay = GetDC(hwnd);
639     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
640
641     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
642     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
643
644     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
645
646     /* Need to write something to the emf, otherwise Windows won't play it back */
647     LineTo(hdcMetafile, 150, 150);
648
649     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
650     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
651     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
652     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
653
654     /* Force Win9x to update DC state */
655     SetPixelV(hdcMetafile, 50, 50, 0);
656
657     ret = GetViewportOrgEx(hdcMetafile, &pt);
658     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
659     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
660     ret = GetViewportExtEx(hdcMetafile, &size);
661     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
662     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
663     ret = SaveDC(hdcMetafile);
664     ok(ret == 1, "ret = %d\n", ret);
665
666     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
667     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
668     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
669     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
670
671     /* Force Win9x to update DC state */
672     SetPixelV(hdcMetafile, 50, 50, 0);
673
674     ret = GetViewportOrgEx(hdcMetafile, &pt);
675     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
676     ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
677     ret = GetViewportExtEx(hdcMetafile, &size);
678     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
679     ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
680     ret = SaveDC(hdcMetafile);
681     ok(ret == 2, "ret = %d\n", ret);
682
683     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
684     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
685     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
686     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
687     SetPolyFillMode( hdcMetafile, ALTERNATE );
688     SetBkColor( hdcMetafile, 0 );
689
690     /* Force Win9x to update DC state */
691     SetPixelV(hdcMetafile, 50, 50, 0);
692
693     ret = GetViewportOrgEx(hdcMetafile, &pt);
694     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
695     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
696     ret = GetViewportExtEx(hdcMetafile, &size);
697     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
698     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
699     ret = SaveDC(hdcMetafile);
700     ok(ret == 3, "ret = %d\n", ret);
701
702     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
703     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
704     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
705     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
706
707     SetPolyFillMode( hdcMetafile, WINDING );
708     SetBkColor( hdcMetafile, 0x123456 );
709     ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
710     ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
711
712     /* Force Win9x to update DC state */
713     SetPixelV(hdcMetafile, 50, 50, 0);
714
715     ret = GetViewportOrgEx(hdcMetafile, &pt);
716     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
717     ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
718     ret = GetViewportExtEx(hdcMetafile, &size);
719     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
720     ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
721     ret = RestoreDC(hdcMetafile, -1);
722     ok(ret, "ret = %d\n", ret);
723
724     ret = GetViewportOrgEx(hdcMetafile, &pt);
725     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
726     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
727     ret = GetViewportExtEx(hdcMetafile, &size);
728     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
729     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
730     ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
731     ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
732     ret = SaveDC(hdcMetafile);
733     ok(ret == 3, "ret = %d\n", ret);
734
735     ret = GetViewportOrgEx(hdcMetafile, &pt);
736     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
737     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
738     ret = GetViewportExtEx(hdcMetafile, &size);
739     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
740     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
741     ret = RestoreDC(hdcMetafile, 1);
742     ok(ret, "ret = %d\n", ret);
743     ret = GetViewportOrgEx(hdcMetafile, &pt);
744     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
745     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
746     ret = GetViewportExtEx(hdcMetafile, &size);
747     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
748     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
749
750     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
751     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
752     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
753     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
754
755     /* Force Win9x to update DC state */
756     SetPixelV(hdcMetafile, 50, 50, 0);
757
758     ret = GetViewportOrgEx(hdcMetafile, &pt);
759     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
760     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
761     ret = GetViewportExtEx(hdcMetafile, &size);
762     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
763     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
764     ret = SaveDC(hdcMetafile);
765     ok(ret == 1, "ret = %d\n", ret);
766
767     ret = GetViewportOrgEx(hdcMetafile, &pt);
768     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
769     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
770     ret = GetViewportExtEx(hdcMetafile, &size);
771     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
772     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
773     ret = SaveDC(hdcMetafile);
774     ok(ret == 2, "ret = %d\n", ret);
775
776     memset(&orig_lf, 0, sizeof(orig_lf));
777     orig_lf.lfCharSet = ANSI_CHARSET;
778     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
779     orig_lf.lfWeight = FW_DONTCARE;
780     orig_lf.lfHeight = 7;
781     orig_lf.lfQuality = DEFAULT_QUALITY;
782     lstrcpyA(orig_lf.lfFaceName, "Arial");
783     hFont = CreateFontIndirectA(&orig_lf);
784     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
785
786     hFontOld = SelectObject(hdcMetafile, hFont);
787
788     hFont2 = CreateFontIndirectA(&orig_lf);
789     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
790     hFontCheck = SelectObject(hdcMetafile, hFont2);
791     ok(hFontCheck == hFont, "Font not selected\n");
792
793     /* Force Win9x to update DC state */
794     SetPixelV(hdcMetafile, 50, 50, 0);
795
796     ret = RestoreDC(hdcMetafile, 1);
797     ok(ret, "ret = %d\n", ret);
798     ret = GetViewportOrgEx(hdcMetafile, &pt);
799     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
800     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
801     ret = GetViewportExtEx(hdcMetafile, &size);
802     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
803     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
804
805     hFontCheck = SelectObject(hdcMetafile, hFontOld);
806     ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
807        "Font not reverted with DC Restore\n");
808
809     ret = RestoreDC(hdcMetafile, -20);
810     ok(!ret, "ret = %d\n", ret);
811     ret = RestoreDC(hdcMetafile, 20);
812     ok(!ret, "ret = %d\n", ret);
813
814     hMetafile = CloseEnhMetaFile(hdcMetafile);
815     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
816
817     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
818     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
819
820     ret = DeleteObject(hFont);
821     ok( ret, "DeleteObject error %d\n", GetLastError());
822     ret = DeleteObject(hFont2);
823     ok( ret, "DeleteObject error %d\n", GetLastError());
824     ret = DeleteEnhMetaFile(hMetafile);
825     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
826     ret = ReleaseDC(hwnd, hdcDisplay);
827     ok( ret, "ReleaseDC error %d\n", GetLastError());
828     DestroyWindow(hwnd);
829 }
830
831 static void test_mf_SaveDC(void)
832 {
833     HDC hdcMetafile;
834     HMETAFILE hMetafile;
835     int ret;
836     POINT pt;
837     SIZE size;
838     HFONT hFont,hFont2,hFontOld,hFontCheck;
839
840     hdcMetafile = CreateMetaFileA(NULL);
841     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
842
843     ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
844     ok (ret, "SetMapMode should not fail\n");
845
846     /* Need to write something to the emf, otherwise Windows won't play it back */
847     LineTo(hdcMetafile, 150, 150);
848
849     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
850     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
851     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
852     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
853
854     /* Force Win9x to update DC state */
855     SetPixelV(hdcMetafile, 50, 50, 0);
856
857     ret = GetViewportOrgEx(hdcMetafile, &pt);
858     todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
859     ret = GetViewportExtEx(hdcMetafile, &size);
860     todo_wine ok (!ret, "GetViewportExtEx should fail\n");
861     ret = SaveDC(hdcMetafile);
862     ok(ret == 1, "ret = %d\n", ret);
863
864     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
865     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
866     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
867     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
868
869     /* Force Win9x to update DC state */
870     SetPixelV(hdcMetafile, 50, 50, 0);
871
872     ret = SaveDC(hdcMetafile);
873     ok(ret == 1, "ret = %d\n", ret);
874
875     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
876     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
877     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
878     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
879
880     /* Force Win9x to update DC state */
881     SetPixelV(hdcMetafile, 50, 50, 0);
882     SetPolyFillMode( hdcMetafile, ALTERNATE );
883     SetBkColor( hdcMetafile, 0 );
884
885     ret = SaveDC(hdcMetafile);
886     ok(ret == 1, "ret = %d\n", ret);
887
888     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
889     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
890     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
891     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
892
893     SetPolyFillMode( hdcMetafile, WINDING );
894     SetBkColor( hdcMetafile, 0x123456 );
895     todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
896     todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
897
898     /* Force Win9x to update DC state */
899     SetPixelV(hdcMetafile, 50, 50, 0);
900
901     ret = RestoreDC(hdcMetafile, -1);
902     ok(ret, "ret = %d\n", ret);
903
904     ret = SaveDC(hdcMetafile);
905     ok(ret == 1, "ret = %d\n", ret);
906
907     ret = RestoreDC(hdcMetafile, 1);
908     ok(ret, "ret = %d\n", ret);
909
910     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
911     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
912     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
913     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
914
915     /* Force Win9x to update DC state */
916     SetPixelV(hdcMetafile, 50, 50, 0);
917
918     ret = SaveDC(hdcMetafile);
919     ok(ret == 1, "ret = %d\n", ret);
920
921     ret = SaveDC(hdcMetafile);
922     ok(ret == 1, "ret = %d\n", ret);
923
924     memset(&orig_lf, 0, sizeof(orig_lf));
925     orig_lf.lfCharSet = ANSI_CHARSET;
926     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
927     orig_lf.lfWeight = FW_DONTCARE;
928     orig_lf.lfHeight = 7;
929     orig_lf.lfQuality = DEFAULT_QUALITY;
930     lstrcpyA(orig_lf.lfFaceName, "Arial");
931     hFont = CreateFontIndirectA(&orig_lf);
932     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
933
934     hFontOld = SelectObject(hdcMetafile, hFont);
935
936     hFont2 = CreateFontIndirectA(&orig_lf);
937     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
938     hFontCheck = SelectObject(hdcMetafile, hFont2);
939     ok(hFontCheck == hFont, "Font not selected\n");
940
941     /* Force Win9x to update DC state */
942     SetPixelV(hdcMetafile, 50, 50, 0);
943
944     ret = RestoreDC(hdcMetafile, 1);
945     ok(ret, "ret = %d\n", ret);
946
947     hFontCheck = SelectObject(hdcMetafile, hFontOld);
948     ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
949
950     /* restore level is ignored */
951     ret = RestoreDC(hdcMetafile, -20);
952     ok(ret, "ret = %d\n", ret);
953     ret = RestoreDC(hdcMetafile, 20);
954     ok(ret, "ret = %d\n", ret);
955     ret = RestoreDC(hdcMetafile, 0);
956     ok(ret, "ret = %d\n", ret);
957
958     hMetafile = CloseMetaFile(hdcMetafile);
959     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
960
961     ret = DeleteMetaFile(hMetafile);
962     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
963     ret = DeleteObject(hFont);
964     ok( ret, "DeleteObject error %d\n", GetLastError());
965     ret = DeleteObject(hFont2);
966     ok( ret, "DeleteObject error %d\n", GetLastError());
967 }
968
969
970 /* Win-format metafile (mfdrv) tests */
971 /* These tests compare the generated metafiles byte-by-byte */
972 /* with the nominal results. */
973
974 /* Maximum size of sample metafiles in bytes. */
975 #define MF_BUFSIZE 512
976
977 /* 8x8 bitmap data for a pattern brush */
978 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
979     0x01, 0x00, 0x02, 0x00,
980     0x03, 0x00, 0x04, 0x00,
981     0x05, 0x00, 0x06, 0x00,
982     0x07, 0x00, 0x08, 0x00
983 };
984
985 /* Sample metafiles to be compared to the outputs of the
986  * test functions.
987  */
988
989 static const unsigned char MF_BLANK_BITS[] = {
990     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
991     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
992     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
993 };
994
995 static const unsigned char MF_GRAPHICS_BITS[] = {
996     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
997     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
998     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
999     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1000     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1001     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1002     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1003     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1004     0x00, 0x00, 0x00, 0x00
1005 };
1006
1007 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1008     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1009     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1010     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1011     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1012     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1013     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1014     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1015     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1016     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1017     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1018     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1019     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1020     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1021     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1022     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1023     0x00, 0x00
1024 };
1025
1026 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1027 {
1028     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1029     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1030     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1031     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1032     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1033     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1034     0x00, 0x00
1035 };
1036
1037 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1038 {
1039     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1040     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1044     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1045     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1046     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1048     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1049     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1050     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1051     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1052     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1053     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1054     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1056     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1057     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1058     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1059     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1060     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1062     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1063     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1064     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1065     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1066     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1067     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1068     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1069     0x14, 0x00, 0x00, 0x00
1070 };
1071
1072 static const unsigned char MF_LINETO_BITS[] = {
1073     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1074     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1075     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1076     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1077     0x00, 0x00
1078 };
1079
1080 static const unsigned char EMF_LINETO_BITS[] = {
1081     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1082     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1084     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1085     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1086     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1087     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1088     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1089     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1090     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1091     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1092     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1094     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1095     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1096     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1097     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1098     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1099     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1100     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1101     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1102     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1103     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1104     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1105     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1106     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1107     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1108     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1109     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1110     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1111     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1112     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1113     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1114     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1115     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1116     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1118     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1119     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1120 };
1121
1122 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1123     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1124     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1125     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1126     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1127     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1128     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1129     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1130     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1132     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1133     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1134     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1136     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1137     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1138     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1139     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1140     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1141     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1142     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1143     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1144     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1145     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1146     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1147     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1148     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1149     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1150     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1151     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1152     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1153     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1154     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1155     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1156     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1157     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1158     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1160     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1161     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1162 };
1163
1164 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1165     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1166     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1168     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1169     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1170     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1171     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1172     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1175     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1176     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1178     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1179     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1180     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1181     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1182     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1183     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1184     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1185     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1186     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1187     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1188     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1189     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1190     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1191     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1192     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193     0x14, 0x00, 0x00, 0x00
1194 };
1195
1196 static const unsigned char EMF_BITBLT[] =
1197 {
1198     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1199     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1201     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202     0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1203     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1204     0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1205     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1207     0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1208     0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1209     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210     0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1211     0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1212     0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1214     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1216     0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1217     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1219     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1220     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1221     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1222     0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1223     0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1224     0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1225     0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1226     0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1227     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1228     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1230     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1231     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1232     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235     0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1236     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1238     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239     0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1240     0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1241     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1242     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1244     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1246     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247     0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1248     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1249     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1250 };
1251
1252
1253 /* For debugging or dumping the raw metafiles produced by
1254  * new test functions.
1255  */
1256 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1257                                  INT nobj, LPARAM param)
1258 {
1259     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1260            hdc, mr->rdFunction, mr->rdSize, (void *)param);
1261     return TRUE;
1262 }
1263
1264 /* For debugging or dumping the raw metafiles produced by
1265  * new test functions.
1266  */
1267
1268 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1269 {
1270     BYTE buf[MF_BUFSIZE];
1271     UINT mfsize, i;
1272
1273     if (!winetest_debug) return;
1274
1275     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1276     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1277
1278     printf ("MetaFile %s has bits:\n{\n    ", desc);
1279     for (i=0; i<mfsize; i++)
1280     {
1281         printf ("0x%02x", buf[i]);
1282         if (i == mfsize-1)
1283             printf ("\n");
1284         else if (i % 8 == 7)
1285             printf (",\n    ");
1286         else
1287             printf (", ");
1288     }
1289     printf ("};\n");
1290 }
1291
1292 /* Compare the metafile produced by a test function with the
1293  * expected raw metafile data in "bits".
1294  * Return value is 0 for a perfect match,
1295  * -1 if lengths aren't equal,
1296  * otherwise returns the number of non-matching bytes.
1297  */
1298
1299 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1300     const char *desc)
1301 {
1302     unsigned char buf[MF_BUFSIZE];
1303     UINT mfsize, i;
1304     int diff;
1305
1306     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1307     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1308     if (mfsize < MF_BUFSIZE)
1309         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1310             desc, mfsize, bsize);
1311     else
1312         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1313             desc, mfsize, bsize);
1314     if (mfsize != bsize)
1315         return -1;
1316
1317     diff = 0;
1318     for (i=0; i<bsize; i++)
1319     {
1320        if (buf[i] !=  bits[i])
1321            diff++;
1322     }
1323     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1324         desc, mfsize, bsize, diff);
1325
1326     return diff; 
1327 }
1328
1329 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1330 {
1331     unsigned char buf[MF_BUFSIZE];
1332     DWORD mfsize, rd_size, i;
1333     int diff;
1334     HANDLE hfile;
1335     BOOL ret;
1336
1337     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1338     assert(hfile != INVALID_HANDLE_VALUE);
1339
1340     mfsize = GetFileSize(hfile, NULL);
1341     assert(mfsize <= MF_BUFSIZE);
1342
1343     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1344     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1345
1346     CloseHandle(hfile);
1347
1348     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1349
1350     if (mfsize != bsize)
1351         return -1;
1352
1353     diff = 0;
1354     for (i=0; i<bsize; i++)
1355     {
1356         if (buf[i] != bits[i])
1357             diff++;
1358     }
1359     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1360         desc, mfsize, bsize, diff);
1361
1362     return diff; 
1363 }
1364
1365 /* For debugging or dumping the raw EMFs produced by
1366  * new test functions.
1367  */
1368 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1369 {
1370     BYTE buf[MF_BUFSIZE];
1371     UINT mfsize, i;
1372
1373     if (!winetest_debug) return;
1374
1375     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1376     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1377
1378     printf("EMF %s has bits:\n{\n    ", desc);
1379     for (i = 0; i < mfsize; i++)
1380     {
1381         printf ("0x%02x", buf[i]);
1382         if (i == mfsize-1)
1383             printf ("\n");
1384         else if (i % 8 == 7)
1385             printf (",\n    ");
1386         else
1387             printf (", ");
1388     }
1389     printf ("};\n");
1390 }
1391
1392 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1393 {
1394     BYTE *emf;
1395     BYTE buf[MF_BUFSIZE];
1396     UINT mfsize, offset;
1397
1398     if (!winetest_debug) return;
1399
1400     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1401     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1402
1403     printf("EMF %s has records:\n", desc);
1404
1405     emf = buf;
1406     offset = 0;
1407     while(offset < mfsize)
1408     {
1409         EMR *emr = (EMR *)(emf + offset);
1410         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1411         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1412         offset += emr->nSize;
1413     }
1414 }
1415
1416 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1417 {
1418     const BYTE *buf;
1419     DWORD i;
1420
1421     if (!winetest_debug) return;
1422
1423     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1424     buf = (const BYTE *)emr;
1425     for (i = 0; i < emr->nSize; i++)
1426     {
1427         printf ("0x%02x", buf[i]);
1428         if (i == emr->nSize - 1)
1429             printf ("\n");
1430         else if (i % 8 == 7)
1431             printf (",\n");
1432         else
1433             printf (", ");
1434     }
1435     printf ("};\n");
1436 }
1437
1438 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1439 {
1440     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1441           eto->rclBounds.right, eto->rclBounds.bottom);
1442     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1443     trace("exScale: %f\n", eto->exScale);
1444     trace("eyScale: %f\n", eto->eyScale);
1445     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1446     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1447     trace("emrtext.offString %#x\n", eto->emrtext.offString);
1448     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1449     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1450           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1451     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1452 }
1453
1454 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1455                              const char *desc, BOOL ignore_scaling)
1456 {
1457     int diff;
1458
1459     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1460        desc, emr1->iType, emr2->iType);
1461
1462     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1463        desc, emr1->nSize, emr2->nSize);
1464
1465     /* iType and nSize mismatches are fatal */
1466     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1467
1468     /* contents of EMR_GDICOMMENT are not interesting */
1469     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1470
1471     /* different Windows versions setup DC scaling differently when
1472      * converting an old style metafile to an EMF.
1473      */
1474     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1475                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1476         return TRUE;
1477
1478     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1479     {
1480         EMREXTTEXTOUTW *eto1, *eto2;
1481
1482         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1483         memcpy(eto1, emr1, emr1->nSize);
1484         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1485         memcpy(eto2, emr2, emr2->nSize);
1486
1487         /* different Windows versions setup DC scaling differently */
1488         eto1->exScale = eto1->eyScale = 0.0;
1489         eto2->exScale = eto2->eyScale = 0.0;
1490
1491         diff = memcmp(eto1, eto2, emr1->nSize);
1492         if (diff)
1493         {
1494             dump_EMREXTTEXTOUT(eto1);
1495             dump_EMREXTTEXTOUT(eto2);
1496         }
1497         HeapFree(GetProcessHeap(), 0, eto1);
1498         HeapFree(GetProcessHeap(), 0, eto2);
1499     }
1500     else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1501     {
1502         /* We have to take care of NT4 differences here */
1503         diff = memcmp(emr1, emr2, emr1->nSize);
1504         if (diff)
1505         {
1506             ENHMETARECORD *emr_nt4;
1507
1508             emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1509             memcpy(emr_nt4, emr2, emr2->nSize);
1510             /* Correct the nRgnSize field */
1511             emr_nt4->dParm[5] = sizeof(RECT);
1512
1513             diff = memcmp(emr1, emr_nt4, emr1->nSize);
1514             if (!diff)
1515                 win_skip("Catered for NT4 differences\n");
1516
1517             HeapFree(GetProcessHeap(), 0, emr_nt4);
1518         }
1519     }
1520     else
1521         diff = memcmp(emr1, emr2, emr1->nSize);
1522
1523     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1524
1525     if (diff)
1526     {
1527         dump_emf_record(emr1, "expected bits");
1528         dump_emf_record(emr2, "actual bits");
1529     }
1530
1531     return diff == 0; /* report all non-fatal record mismatches */
1532 }
1533
1534 /* Compare the EMF produced by a test function with the
1535  * expected raw EMF data in "bits".
1536  * Return value is 0 for a perfect match,
1537  * -1 if lengths aren't equal,
1538  * otherwise returns the number of non-matching bytes.
1539  */
1540 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1541                             UINT bsize, const char *desc,
1542                             BOOL ignore_scaling)
1543 {
1544     unsigned char buf[MF_BUFSIZE];
1545     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1546     const ENHMETAHEADER *emh1, *emh2;
1547
1548     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1549     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1550
1551     /* ENHMETAHEADER size could differ, depending on platform */
1552     diff_nt4 = sizeof(SIZEL);
1553     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1554
1555     if (mfsize < MF_BUFSIZE)
1556     {
1557         ok(mfsize == bsize ||
1558            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1559            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1560            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1561     }
1562     else
1563         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1564            desc, mfsize, bsize);
1565
1566     /* basic things must match */
1567     emh1 = (const ENHMETAHEADER *)bits;
1568     emh2 = (const ENHMETAHEADER *)buf;
1569     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1570     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1571     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1572     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1573
1574     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1575     ok(emh1->nSize == emh2->nSize ||
1576        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1577        broken(emh1->nSize - diff_9x == emh2->nSize),
1578        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1579     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1580     ok(emh1->nBytes == emh2->nBytes ||
1581        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1582        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1583        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1584     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1585
1586     offset1 = emh1->nSize;
1587     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1588     while (offset1 < emh1->nBytes)
1589     {
1590         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1591         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1592
1593         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1594               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1595
1596         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1597
1598         /* We have already bailed out if iType or nSize don't match */
1599         offset1 += emr1->nSize;
1600         offset2 += emr2->nSize;
1601     }
1602     return 0;
1603 }
1604
1605
1606 /* tests blitting to an EMF */
1607 static void test_emf_BitBlt(void)
1608 {
1609     HDC hdcDisplay, hdcMetafile, hdcBitmap;
1610     HBITMAP hBitmap, hOldBitmap;
1611     HENHMETAFILE hMetafile;
1612 #define BMP_DIM 4
1613     BITMAPINFOHEADER bmih =
1614     {
1615         sizeof(BITMAPINFOHEADER),
1616         BMP_DIM,/* biWidth */
1617         BMP_DIM,/* biHeight */
1618         1,      /* biPlanes */
1619         24,     /* biBitCount */
1620         BI_RGB, /* biCompression */
1621         0,      /* biXPelsPerMeter */
1622         0,      /* biYPelsPerMeter */
1623         0,      /* biClrUsed */
1624         0,      /* biClrImportant */
1625     };
1626     void *bits;
1627     BOOL ret;
1628
1629     hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1630     ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1631
1632     hdcBitmap = CreateCompatibleDC(hdcDisplay);
1633     ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1634     bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1635     bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1636     hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1637                                DIB_RGB_COLORS, &bits, NULL, 0);
1638     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1639
1640     hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1641     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1642
1643     /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1644     ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1645     ok( ret, "BitBlt(BLACKNESS) failed\n" );
1646
1647     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1648     ok( ret, "BitBlt(SRCCOPY) failed\n" );
1649     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1650     ok( ret, "BitBlt(WHITENESS) failed\n" );
1651
1652     hMetafile = CloseEnhMetaFile(hdcMetafile);
1653     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1654
1655     if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1656         "emf_BitBlt", FALSE) != 0)
1657     {
1658         dump_emf_bits(hMetafile, "emf_BitBlt");
1659         dump_emf_records(hMetafile, "emf_BitBlt");
1660     }
1661
1662     SelectObject(hdcBitmap, hOldBitmap);
1663     DeleteObject(hBitmap);
1664     DeleteDC(hdcBitmap);
1665     DeleteDC(hdcDisplay);
1666 #undef BMP_DIM
1667 }
1668
1669 /* Test a blank metafile.  May be used as a template for new tests. */
1670
1671 static void test_mf_Blank(void)
1672 {
1673     HDC hdcMetafile;
1674     HMETAFILE hMetafile;
1675     INT caps;
1676     BOOL ret;
1677     INT type;
1678
1679     hdcMetafile = CreateMetaFileA(NULL);
1680     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1681     trace("hdcMetafile %p\n", hdcMetafile);
1682
1683 /* Tests on metafile initialization */
1684     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1685     ok (caps == DT_METAFILE,
1686         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1687
1688     hMetafile = CloseMetaFile(hdcMetafile);
1689     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1690     type = GetObjectType(hMetafile);
1691     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1692     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1693
1694     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1695         "mf_blank") != 0)
1696     {
1697         dump_mf_bits(hMetafile, "mf_Blank");
1698         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1699     }
1700
1701     ret = DeleteMetaFile(hMetafile);
1702     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1703 }
1704
1705 static void test_CopyMetaFile(void)
1706 {
1707     HDC hdcMetafile;
1708     HMETAFILE hMetafile, hmf_copy;
1709     BOOL ret;
1710     char temp_path[MAX_PATH];
1711     char mf_name[MAX_PATH];
1712     INT type;
1713
1714     hdcMetafile = CreateMetaFileA(NULL);
1715     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1716     trace("hdcMetafile %p\n", hdcMetafile);
1717
1718     hMetafile = CloseMetaFile(hdcMetafile);
1719     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1720     type = GetObjectType(hMetafile);
1721     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1722
1723     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1724         "mf_blank") != 0)
1725     {
1726         dump_mf_bits(hMetafile, "mf_Blank");
1727         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1728     }
1729
1730     GetTempPathA(MAX_PATH, temp_path);
1731     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1732
1733     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1734     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1735
1736     type = GetObjectType(hmf_copy);
1737     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1738
1739     ret = DeleteMetaFile(hMetafile);
1740     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1741
1742     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1743     {
1744         dump_mf_bits(hmf_copy, "mf_Blank");
1745         EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1746     }
1747
1748     ret = DeleteMetaFile(hmf_copy);
1749     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1750
1751     DeleteFileA(mf_name);
1752 }
1753
1754 static void test_SetMetaFileBits(void)
1755 {
1756     HMETAFILE hmf;
1757     INT type;
1758     BOOL ret;
1759     BYTE buf[256];
1760     METAHEADER *mh;
1761
1762     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1763     trace("hmf %p\n", hmf);
1764     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1765     type = GetObjectType(hmf);
1766     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1767
1768     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1769     {
1770         dump_mf_bits(hmf, "mf_Graphics");
1771         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1772     }
1773
1774     ret = DeleteMetaFile(hmf);
1775     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1776
1777     /* NULL data crashes XP SP1 */
1778     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1779
1780     /* Now with zero size */
1781     SetLastError(0xdeadbeef);
1782     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1783     trace("hmf %p\n", hmf);
1784     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1785     ok(GetLastError() == ERROR_INVALID_DATA ||
1786        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1787        "wrong error %d\n", GetLastError());
1788
1789     /* Now with odd size */
1790     SetLastError(0xdeadbeef);
1791     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1792     trace("hmf %p\n", hmf);
1793     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1794     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1795
1796     /* Now with zeroed out header fields */
1797     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1798     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1799     mh = (METAHEADER *)buf;
1800     /* corruption of any of the below fields leads to a failure */
1801     mh->mtType = 0;
1802     mh->mtVersion = 0;
1803     mh->mtHeaderSize = 0;
1804     SetLastError(0xdeadbeef);
1805     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1806     trace("hmf %p\n", hmf);
1807     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1808     ok(GetLastError() == ERROR_INVALID_DATA ||
1809        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1810        "wrong error %d\n", GetLastError());
1811
1812     /* Now with corrupted mtSize field */
1813     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1814     mh = (METAHEADER *)buf;
1815     /* corruption of mtSize doesn't lead to a failure */
1816     mh->mtSize *= 2;
1817     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1818     trace("hmf %p\n", hmf);
1819     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1820
1821     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1822     {
1823         dump_mf_bits(hmf, "mf_Graphics");
1824         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1825     }
1826
1827     ret = DeleteMetaFile(hmf);
1828     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1829
1830 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
1831     /* Now with zeroed out mtSize field */
1832     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1833     mh = (METAHEADER *)buf;
1834     /* zeroing mtSize doesn't lead to a failure */
1835     mh->mtSize = 0;
1836     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1837     trace("hmf %p\n", hmf);
1838     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1839
1840     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1841     {
1842         dump_mf_bits(hmf, "mf_Graphics");
1843         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1844     }
1845
1846     ret = DeleteMetaFile(hmf);
1847     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1848 #endif
1849 }
1850
1851 /* Simple APIs from mfdrv/graphics.c
1852  */
1853
1854 static void test_mf_Graphics(void)
1855 {
1856     HDC hdcMetafile;
1857     HMETAFILE hMetafile;
1858     POINT oldpoint;
1859     BOOL ret;
1860
1861     hdcMetafile = CreateMetaFileA(NULL);
1862     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1863     trace("hdcMetafile %p\n", hdcMetafile);
1864
1865     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1866     ok( ret, "MoveToEx error %d.\n", GetLastError());
1867     ret = LineTo(hdcMetafile, 2, 2);
1868     ok( ret, "LineTo error %d.\n", GetLastError());
1869     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1870     ok( ret, "MoveToEx error %d.\n", GetLastError());
1871
1872 /* oldpoint gets garbage under Win XP, so the following test would
1873  * work under Wine but fails under Windows:
1874  *
1875  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1876  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1877  *       oldpoint.x, oldpoint.y);
1878  */
1879
1880     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1881     ok( ret, "Ellipse error %d.\n", GetLastError());
1882
1883     hMetafile = CloseMetaFile(hdcMetafile);
1884     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1885     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1886
1887     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1888         "mf_Graphics") != 0)
1889     {
1890         dump_mf_bits(hMetafile, "mf_Graphics");
1891         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1892     }
1893
1894     ret = DeleteMetaFile(hMetafile);
1895     ok( ret, "DeleteMetaFile(%p) error %d\n",
1896         hMetafile, GetLastError());
1897 }
1898
1899 static void test_mf_PatternBrush(void)
1900 {
1901     HDC hdcMetafile;
1902     HMETAFILE hMetafile;
1903     LOGBRUSH *orig_lb;
1904     HBRUSH hBrush;
1905     BOOL ret;
1906
1907     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1908
1909     orig_lb->lbStyle = BS_PATTERN;
1910     orig_lb->lbColor = RGB(0, 0, 0);
1911     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1912     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1913
1914     hBrush = CreateBrushIndirect (orig_lb);
1915     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1916
1917     hdcMetafile = CreateMetaFileA(NULL);
1918     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1919     trace("hdcMetafile %p\n", hdcMetafile);
1920
1921     hBrush = SelectObject(hdcMetafile, hBrush);
1922     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1923
1924     hMetafile = CloseMetaFile(hdcMetafile);
1925     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1926     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1927
1928     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1929         "mf_Pattern_Brush") != 0)
1930     {
1931         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1932         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1933     }
1934
1935     ret = DeleteMetaFile(hMetafile);
1936     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1937     ret = DeleteObject(hBrush);
1938     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1939     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1940     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1941         GetLastError());
1942     HeapFree (GetProcessHeap(), 0, orig_lb);
1943 }
1944
1945 static void test_mf_ExtTextOut_on_path(void)
1946 {
1947     HDC hdcMetafile;
1948     HMETAFILE hMetafile;
1949     BOOL ret;
1950     static const INT dx[4] = { 3, 5, 8, 12 };
1951
1952     hdcMetafile = CreateMetaFileA(NULL);
1953     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1954     trace("hdcMetafile %p\n", hdcMetafile);
1955
1956     ret = BeginPath(hdcMetafile);
1957     ok(!ret, "BeginPath on metafile DC should fail\n");
1958
1959     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1960     ok(ret, "ExtTextOut error %d\n", GetLastError());
1961
1962     ret = EndPath(hdcMetafile);
1963     ok(!ret, "EndPath on metafile DC should fail\n");
1964
1965     hMetafile = CloseMetaFile(hdcMetafile);
1966     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1967
1968     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1969         "mf_TextOut_on_path") != 0)
1970     {
1971         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1972         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1973     }
1974
1975     ret = DeleteMetaFile(hMetafile);
1976     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1977 }
1978
1979 static void test_emf_ExtTextOut_on_path(void)
1980 {
1981     HWND hwnd;
1982     HDC hdcDisplay, hdcMetafile;
1983     HENHMETAFILE hMetafile;
1984     BOOL ret;
1985     static const INT dx[4] = { 3, 5, 8, 12 };
1986
1987     /* Win9x doesn't play EMFs on invisible windows */
1988     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1989                            0, 0, 200, 200, 0, 0, 0, NULL);
1990     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1991
1992     hdcDisplay = GetDC(hwnd);
1993     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1994
1995     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1996     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1997
1998     ret = BeginPath(hdcMetafile);
1999     ok(ret, "BeginPath error %d\n", GetLastError());
2000
2001     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2002     ok(ret, "ExtTextOut error %d\n", GetLastError());
2003
2004     ret = EndPath(hdcMetafile);
2005     ok(ret, "EndPath error %d\n", GetLastError());
2006
2007     hMetafile = CloseEnhMetaFile(hdcMetafile);
2008     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2009
2010     /* this doesn't succeed yet: EMF has correct size, all EMF records
2011      * are there, but their contents don't match for different reasons.
2012      */
2013     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2014         "emf_TextOut_on_path", FALSE) != 0)
2015     {
2016         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2017         dump_emf_records(hMetafile, "emf_TextOut_on_path");
2018     }
2019
2020     ret = DeleteEnhMetaFile(hMetafile);
2021     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2022     ret = ReleaseDC(hwnd, hdcDisplay);
2023     ok(ret, "ReleaseDC error %d\n", GetLastError());
2024     DestroyWindow(hwnd);
2025 }
2026
2027 static const unsigned char EMF_CLIPPING[] =
2028 {
2029     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2030     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2031     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2032     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2033     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2034     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2035     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2036     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2037     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2038     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2039     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2040     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2041     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2042     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2043     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2044     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2045     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2046     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2047     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2048     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2049     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2050     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2051     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2052     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2053     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2054     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2055 };
2056
2057 static void translate( POINT *pt, UINT count, const XFORM *xform )
2058 {
2059     while (count--)
2060     {
2061         FLOAT x = (FLOAT)pt->x;
2062         FLOAT y = (FLOAT)pt->y;
2063         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2064         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2065         pt++;
2066     }
2067 }
2068
2069 /* Compare rectangles allowing rounding errors */
2070 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2071 {
2072     return abs(rc1->left - rc2->left) <= 1 &&
2073            abs(rc1->top - rc2->top) <= 1 &&
2074            abs(rc1->right - rc2->right) <= 1 &&
2075            abs(rc1->bottom - rc2->bottom) <= 1;
2076 }
2077
2078 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2079                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
2080 {
2081     if (emr->iType == EMR_EXTSELECTCLIPRGN)
2082     {
2083         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2084         union _rgn
2085         {
2086             RGNDATA data;
2087             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2088         };
2089         const union _rgn *rgn1;
2090         union _rgn rgn2;
2091         RECT rect, rc_transformed;
2092         const RECT *rc = (const RECT *)param;
2093         HRGN hrgn;
2094         XFORM xform;
2095         INT ret;
2096         BOOL is_win9x;
2097
2098         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2099                clip->cbRgnData, clip->iMode);
2100
2101         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2102         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2103            "too small data block: %u bytes\n", clip->cbRgnData);
2104         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2105             return 0;
2106
2107         rgn1 = (const union _rgn *)clip->RgnData;
2108
2109         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2110               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2111               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2112               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2113               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2114
2115         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2116
2117         rect = *(const RECT *)rgn1->data.Buffer;
2118         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2119         ok(EqualRect(&rect, rc), "rects don't match\n");
2120
2121         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2122         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2123         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2124         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2125            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2126            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2127
2128         hrgn = CreateRectRgn(0, 0, 0, 0);
2129
2130         memset(&xform, 0, sizeof(xform));
2131         SetLastError(0xdeadbeef);
2132         ret = GetWorldTransform(hdc, &xform);
2133         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2134         if (!is_win9x)
2135             ok(ret, "GetWorldTransform error %u\n", GetLastError());
2136
2137         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2138
2139         ret = GetClipRgn(hdc, hrgn);
2140         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2141
2142         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2143
2144         ret = GetClipRgn(hdc, hrgn);
2145         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2146
2147         /* Win9x returns empty clipping region */
2148         if (is_win9x) return 1;
2149
2150         ret = GetRegionData(hrgn, 0, NULL);
2151         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2152
2153         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2154         ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2155
2156         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2157               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2158               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2159               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2160               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2161
2162         rect = rgn2.data.rdh.rcBound;
2163         rc_transformed = *rc;
2164         translate((POINT *)&rc_transformed, 2, &xform);
2165         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2166               rc_transformed.right, rc_transformed.bottom);
2167         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2168
2169         rect = *(const RECT *)rgn2.data.Buffer;
2170         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2171         rc_transformed = *rc;
2172         translate((POINT *)&rc_transformed, 2, &xform);
2173         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2174               rc_transformed.right, rc_transformed.bottom);
2175         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2176
2177         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2178         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2179         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2180         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2181            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2182            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2183
2184         DeleteObject(hrgn);
2185     }
2186     return 1;
2187 }
2188
2189 static void test_emf_clipping(void)
2190 {
2191     static const RECT rc = { 0, 0, 100, 100 };
2192     RECT rc_clip = { 100, 100, 1024, 1024 };
2193     HWND hwnd;
2194     HDC hdc;
2195     HENHMETAFILE hemf;
2196     HRGN hrgn;
2197     INT ret;
2198     RECT rc_res, rc_sclip;
2199
2200     SetLastError(0xdeadbeef);
2201     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2202     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2203
2204     /* Need to write something to the emf, otherwise Windows won't play it back */
2205     LineTo(hdc, 1, 1);
2206
2207     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2208     ret = SelectClipRgn(hdc, hrgn);
2209     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2210
2211     SetLastError(0xdeadbeef);
2212     hemf = CloseEnhMetaFile(hdc);
2213     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2214
2215     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2216         "emf_clipping", FALSE) != 0)
2217     {
2218         dump_emf_bits(hemf, "emf_clipping");
2219         dump_emf_records(hemf, "emf_clipping");
2220     }
2221
2222     DeleteObject(hrgn);
2223
2224     /* Win9x doesn't play EMFs on invisible windows */
2225     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2226                            0, 0, 200, 200, 0, 0, 0, NULL);
2227     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2228
2229     hdc = GetDC(hwnd);
2230
2231     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2232     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2233
2234     DeleteEnhMetaFile(hemf);
2235     ReleaseDC(hwnd, hdc);
2236     DestroyWindow(hwnd);
2237
2238     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2239
2240     SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2241     hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2242     SelectClipRgn(hdc, hrgn);
2243     ret = GetClipBox(hdc, &rc_res);
2244 todo_wine
2245     ok(ret == SIMPLEREGION, "got %d\n", ret);
2246     if(ret == SIMPLEREGION)
2247         ok(EqualRect(&rc_res, &rc_sclip),
2248                  "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2249                  rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2250                  rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2251
2252     hemf = CloseEnhMetaFile(hdc);
2253     DeleteEnhMetaFile(hemf);
2254     DeleteObject(hrgn);
2255     DeleteDC(hdc);
2256 }
2257
2258 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2259 {
2260     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2261     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2262     /* When using MM_TEXT Win9x does not update the mapping mode 
2263      * until a record is played which actually outputs something */
2264     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2265     LPtoDP(hdc, mapping, 2);
2266     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2267            lpEMFR->iType, lpEMFR->nSize,
2268            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2269
2270     if (lpEMFR->iType == EMR_LINETO)
2271     {
2272         INT x0, y0, x1, y1;
2273         if (!lpMFP || lpMFP->mm == MM_TEXT)
2274         {
2275             x0 = 0;
2276             y0 = 0;
2277             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2278             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2279         }
2280         else
2281         {
2282             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2283             
2284             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2285             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2286             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2287             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2288         }
2289         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2290             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2291             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2292             x0, y0, x1, y1);
2293     }
2294     return TRUE;
2295 }
2296
2297 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2298 {
2299     HDC hdcMf;
2300     HMETAFILE hmf;
2301     HENHMETAFILE hemf;
2302     BOOL ret;
2303     UINT size;
2304     LPBYTE pBits;
2305
2306     hdcMf = CreateMetaFile(NULL);
2307     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2308     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2309     ok(ret, "LineTo failed with error %d\n", GetLastError());
2310     hmf = CloseMetaFile(hdcMf);
2311     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2312
2313     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2314     {
2315         dump_mf_bits(hmf, "mf_LineTo");
2316         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2317     }
2318
2319     size = GetMetaFileBitsEx(hmf, 0, NULL);
2320     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2321     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2322     GetMetaFileBitsEx(hmf, size, pBits);
2323     DeleteMetaFile(hmf);
2324     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2325     HeapFree(GetProcessHeap(), 0, pBits);
2326     return hemf;
2327 }
2328
2329 static void test_mf_conversions(void)
2330 {
2331     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2332     {
2333         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2334         HENHMETAFILE hemf;
2335         METAFILEPICT mfp;
2336         RECT rect = { 0, 0, 100, 100 };
2337         mfp.mm = MM_ANISOTROPIC;
2338         mfp.xExt = 100;
2339         mfp.yExt = 100;
2340         mfp.hMF = NULL;
2341         hemf = create_converted_emf(&mfp);
2342
2343         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2344                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2345         {
2346             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2347             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2348         }
2349
2350         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2351
2352         DeleteEnhMetaFile(hemf);
2353         DeleteDC(hdcOffscreen);
2354     }
2355
2356     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2357     {
2358         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2359         HENHMETAFILE hemf;
2360         METAFILEPICT mfp;
2361         RECT rect = { 0, 0, 100, 100 };
2362         mfp.mm = MM_TEXT;
2363         mfp.xExt = 0;
2364         mfp.yExt = 0;
2365         mfp.hMF = NULL;
2366         hemf = create_converted_emf(&mfp);
2367
2368         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2369                              "emf_LineTo MM_TEXT", TRUE) != 0)
2370         {
2371             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2372             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2373         }
2374
2375         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2376
2377         DeleteEnhMetaFile(hemf);
2378         DeleteDC(hdcOffscreen);
2379     }
2380
2381     trace("Testing MF->EMF conversion (NULL mfp)\n");
2382     {
2383         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2384         HENHMETAFILE hemf;
2385         RECT rect = { 0, 0, 100, 100 };
2386         hemf = create_converted_emf(NULL);
2387
2388         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2389                              "emf_LineTo NULL", TRUE) != 0)
2390         {
2391             dump_emf_bits(hemf, "emf_LineTo NULL");
2392             dump_emf_records(hemf, "emf_LineTo NULL");
2393         }
2394
2395         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2396
2397         DeleteEnhMetaFile(hemf);
2398         DeleteDC(hdcOffscreen);
2399     }
2400 }
2401
2402 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2403                                        LONG mm, LONG xExt, LONG yExt,
2404                                        RECTL * rclBounds, RECTL * rclFrame)
2405 {
2406   METAFILEPICT mfp;
2407   METAFILEPICT * mfpPtr = NULL;
2408   HENHMETAFILE emf;
2409   ENHMETAHEADER header;
2410   UINT res;
2411
2412   if (!mfpIsNull)
2413   {
2414     mfp.mm = mm;
2415     mfp.xExt = xExt;
2416     mfp.yExt = yExt;
2417     mfpPtr = &mfp;
2418   }
2419
2420   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2421   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2422   if (!emf) return FALSE;
2423   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2424   ok(res != 0, "GetEnhMetaHeader failed\n");
2425   DeleteEnhMetaFile(emf);
2426   if (!res) return FALSE;
2427
2428   *rclBounds = header.rclBounds;
2429   *rclFrame = header.rclFrame;
2430   return TRUE;
2431 }
2432
2433 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2434                                          LONG mm, LONG xExt, LONG yExt,
2435                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2436 {
2437   RECTL rclBounds, rclFrame;
2438
2439   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2440   {
2441     const char * msg;
2442     char buf[64];
2443
2444     if (mfpIsNull)
2445     {
2446        msg = "mfp == NULL";
2447     }
2448     else
2449     {
2450       const char * mm_str;
2451       switch (mm)
2452       {
2453          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2454          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2455          default:             mm_str = "Unexpected";
2456       }
2457       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2458       msg = buf;
2459     }
2460
2461     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2462     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2463     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2464     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2465     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2466     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2467     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2468     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2469   }
2470 }
2471
2472 static void test_SetWinMetaFileBits(void)
2473 {
2474   HMETAFILE wmf;
2475   HDC wmfDC;
2476   BYTE * buffer;
2477   UINT buffer_size;
2478   RECT rect;
2479   UINT res;
2480   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2481   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2482   RECTL rclBounds, rclFrame;
2483   HDC dc;
2484   LONG diffx, diffy;
2485
2486   wmfDC = CreateMetaFile(NULL);
2487   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2488   if (!wmfDC) return;
2489
2490   SetWindowExtEx(wmfDC, 100, 100, NULL);
2491   rect.left = rect.top = 0;
2492   rect.right = rect.bottom = 50;
2493   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2494   wmf = CloseMetaFile(wmfDC);
2495   ok(wmf != NULL, "Metafile creation failed\n");
2496   if (!wmf) return;
2497
2498   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2499   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2500   if (buffer_size == 0)
2501   {
2502     DeleteMetaFile(wmf);
2503     return;
2504   }
2505
2506   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2507   ok(buffer != NULL, "HeapAlloc failed\n");
2508   if (!buffer)
2509   {
2510     DeleteMetaFile(wmf);
2511     return;
2512   }
2513
2514   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2515   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2516   DeleteMetaFile(wmf);
2517   if (res != buffer_size)
2518   {
2519      HeapFree(GetProcessHeap(), 0, buffer);
2520      return;
2521   }
2522
2523   /* Get the reference bounds and frame */
2524   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2525   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2526
2527   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2528      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2529      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2530
2531   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2532   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2533   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2534   if (diffx < 0) diffx = -diffx;
2535   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2536
2537   dc = CreateCompatibleDC(NULL);
2538
2539   /* Allow 1 mm difference (rounding errors) */
2540   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2541   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2542   if (diffx < 0) diffx = -diffx;
2543   if (diffy < 0) diffy = -diffy;
2544   todo_wine
2545   {
2546   ok(diffx <= 1 && diffy <= 1,
2547      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2548      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2549   }
2550
2551   /* Allow 1 mm difference (rounding errors) */
2552   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2553   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2554   if (diffx < 0) diffx = -diffx;
2555   if (diffy < 0) diffy = -diffy;
2556   todo_wine
2557   {
2558   ok(diffx <= 1 && diffy <= 1,
2559      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2560      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2561   }
2562   DeleteDC(dc);
2563
2564   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2565   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2566
2567   /* If xExt or yExt is zero or negative, the whole device surface is used */
2568   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2569   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2570   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2571   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2572   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2573   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2574   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2575   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2576   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2577   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2578   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2579   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2580
2581   /* MSDN says that negative xExt and yExt values specify a ratio.
2582      Check that this is wrong and the whole device surface is used */
2583   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2584   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2585
2586   /* Ordinary conversions */
2587
2588   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2589   {
2590     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2591        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2592     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2593        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2594   }
2595
2596   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2597   {
2598     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2599        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2600     ok(rclBounds.left == 0 && rclBounds.top == 0,
2601        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2602
2603     /* Wine has a rounding error */
2604     diffx = rclBounds.right - rclBounds.bottom;
2605     if (diffx < 0) diffx = -diffx;
2606     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2607   }
2608
2609   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2610   {
2611     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2612        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2613   }
2614
2615   HeapFree(GetProcessHeap(), 0, buffer);
2616 }
2617
2618 static BOOL near_match(int x, int y)
2619 {
2620     int epsilon = min(abs(x), abs(y));
2621
2622     epsilon = max(epsilon/100, 2);
2623
2624     if(x < y - epsilon || x > y + epsilon) return FALSE;
2625     return TRUE;
2626 }
2627
2628 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2629 {
2630     HENHMETAFILE emf;
2631     HDC display_dc, emf_dc;
2632     ENHMETAHEADER *enh_header;
2633     UINT size, emf_size, i;
2634     WORD check = 0;
2635     DWORD rec_num = 0;
2636     METAHEADER *mh = NULL;
2637     METARECORD *rec;
2638     INT horz_res, vert_res, horz_size, vert_size;
2639
2640     display_dc = GetDC(NULL);
2641     ok(display_dc != NULL, "display_dc is NULL\n");
2642
2643     horz_res = GetDeviceCaps(display_dc, HORZRES);
2644     vert_res = GetDeviceCaps(display_dc, VERTRES);
2645     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2646     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2647
2648     emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2649     ok(emf_dc != NULL, "emf_dc is NULL\n");
2650     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2651         Rectangle(emf_dc, 0, 0, 1000, 20);
2652     emf = CloseEnhMetaFile(emf_dc);
2653     ok(emf != NULL, "emf is NULL\n");
2654
2655     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2656     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2657     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2658     DeleteEnhMetaFile(emf);
2659     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2660        have different resolutions */
2661     enh_header->szlDevice.cx *= scale;
2662     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2663     ok(emf != NULL, "emf is NULL\n");
2664     ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2665
2666     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2667     ok(size ||
2668        broken(size == 0), /* some versions of winxp fail for some reason */
2669        "GetWinMetaFileBits returns 0\n");
2670     if(!size) goto end;
2671     mh = HeapAlloc(GetProcessHeap(), 0, size);
2672     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2673
2674     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2675     ok(check == 0, "check %04x\n", check);
2676
2677     rec = (METARECORD*)(mh + 1);
2678
2679     while(rec->rdSize && rec->rdFunction)
2680     {
2681         const DWORD chunk_size = 0x2000;
2682         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2683
2684         if(rec_num < mfcomment_chunks)
2685         {
2686             DWORD this_chunk_size = chunk_size;
2687
2688             if(rec_num == mfcomment_chunks - 1)
2689                 this_chunk_size = emf_size - rec_num * chunk_size;
2690
2691             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2692             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2693             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2694             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2695             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2696             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2697             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
2698             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2699             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2700             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2701             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2702             /* parm[8] is the checksum, tested above */
2703             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2704             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2705             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2706             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2707             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2708             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2709             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2710             ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15));  /* DWORD size remaining after current chunk */
2711             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2712             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2713         }
2714
2715         else if(rec_num == mfcomment_chunks)
2716         {
2717             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2718             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2719         }
2720         else if(rec_num == mfcomment_chunks + 1)
2721         {
2722             POINT pt;
2723             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2724             switch(mode)
2725             {
2726             case MM_TEXT:
2727             case MM_ISOTROPIC:
2728             case MM_ANISOTROPIC:
2729                 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2730                 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2731                 break;
2732             case MM_LOMETRIC:
2733                 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2734                 pt.x = MulDiv( rc->left, 1, 10);
2735                 break;
2736             case MM_HIMETRIC:
2737                 pt.y = -rc->top + 1;
2738                 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2739                 break;
2740             case MM_LOENGLISH:
2741                 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2742                 pt.x = MulDiv( rc->left, 10, 254);
2743                 break;
2744             case MM_HIENGLISH:
2745                 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2746                 pt.x = MulDiv( rc->left, 100, 254);
2747                 break;
2748             case MM_TWIPS:
2749                 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2750                 pt.x = MulDiv( rc->left, 72 * 20, 2540);
2751                 break;
2752             default:
2753                 pt.x = pt.y = 0;
2754             }
2755             ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2756             ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2757         }
2758         if(rec_num == mfcomment_chunks + 2)
2759         {
2760             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2761             ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
2762                "got %d\n", (short)rec->rdParm[0]);
2763             ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
2764                "got %d\n", (short)rec->rdParm[1]);
2765         }
2766
2767         rec_num++;
2768         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2769     }
2770
2771 end:
2772     HeapFree(GetProcessHeap(), 0, mh);
2773     HeapFree(GetProcessHeap(), 0, enh_header);
2774     DeleteEnhMetaFile(emf);
2775
2776     ReleaseDC(NULL, display_dc);
2777 }
2778
2779 static void test_GetWinMetaFileBits(void)
2780 {
2781     UINT mode;
2782     RECT frames[] =
2783     {
2784         { 1000,  2000, 3000, 6000},
2785         {-1000,  2000, 3000, 6000},
2786         { 1000, -2000, 3000, 6000},
2787         { 1005,  2005, 3000, 6000},
2788         {-1005, -2005, 3000, 6000},
2789         {-1005, -2010, 3000, 6000},
2790         {-1005,  2010, 3000, 6000},
2791         {    0,     0,    1,    1},
2792         {   -1,    -1,    1,    1},
2793         {    0,     0,    0,    0}
2794     };
2795
2796     for(mode = MM_MIN; mode <= MM_MAX; mode++)
2797     {
2798         RECT *rc;
2799         trace("mode %d\n", mode);
2800
2801         for(rc = frames; rc->right - rc->left > 0; rc++)
2802         {
2803             trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
2804             getwinmetafilebits(mode, 1, rc);
2805             getwinmetafilebits(mode, 2, rc);
2806         }
2807     }
2808 }
2809
2810 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2811 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2812 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2813
2814 static void test_gdiis(void)
2815 {
2816     RECT rect = {0,0,100,100};
2817     HDC hdc, hemfDC, hmfDC;
2818     HENHMETAFILE hemf;
2819     HMODULE hgdi32;
2820
2821     /* resolve all the functions */
2822     hgdi32 = GetModuleHandle("gdi32");
2823     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2824     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2825     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2826
2827     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2828     {
2829         win_skip("Needed GdiIs* functions are not available\n");
2830         return;
2831     }
2832
2833     /* try with nothing */
2834     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2835     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2836     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2837
2838     /* try with a metafile */
2839     hmfDC = CreateMetaFile(NULL);
2840     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2841     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2842     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2843     DeleteMetaFile(CloseMetaFile(hmfDC));
2844
2845     /* try with an enhanced metafile */
2846     hdc = GetDC(NULL);
2847     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2848     ok(hemfDC != NULL, "failed to create emf\n");
2849
2850     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2851     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2852     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2853
2854     hemf = CloseEnhMetaFile(hemfDC);
2855     ok(hemf != NULL, "failed to close EMF\n");
2856     DeleteEnhMetaFile(hemf);
2857     ReleaseDC(NULL,hdc);
2858 }
2859
2860 static void test_SetEnhMetaFileBits(void)
2861 {
2862     BYTE data[256];
2863     HENHMETAFILE hemf;
2864     ENHMETAHEADER *emh;
2865
2866     memset(data, 0xAA, sizeof(data));
2867     SetLastError(0xdeadbeef);
2868     hemf = SetEnhMetaFileBits(sizeof(data), data);
2869     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2870     ok(GetLastError() == ERROR_INVALID_DATA ||
2871        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2872        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2873
2874     emh = (ENHMETAHEADER *)data;
2875     memset(emh, 0, sizeof(*emh));
2876
2877     emh->iType = EMR_HEADER;
2878     emh->nSize = sizeof(*emh);
2879     emh->dSignature = ENHMETA_SIGNATURE;
2880     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2881     emh->nBytes = sizeof(*emh);
2882     /* emh->nRecords = 1; XP doesn't care about records */
2883     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2884
2885     SetLastError(0xdeadbeef);
2886     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2887     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2888     DeleteEnhMetaFile(hemf);
2889
2890     /* XP refuses to load unaligned EMF */
2891     emh->nBytes++;
2892     SetLastError(0xdeadbeef);
2893     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2894     ok(!hemf ||
2895        broken(hemf != NULL), /* Win9x, WinMe */
2896        "SetEnhMetaFileBits should fail\n");
2897     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2898     DeleteEnhMetaFile(hemf);
2899
2900     emh->dSignature = 0;
2901     emh->nBytes--;
2902     SetLastError(0xdeadbeef);
2903     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2904     ok(!hemf ||
2905        broken(hemf != NULL), /* Win9x, WinMe */
2906        "SetEnhMetaFileBits should fail\n");
2907     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2908     DeleteEnhMetaFile(hemf);
2909 }
2910
2911 START_TEST(metafile)
2912 {
2913     init_function_pointers();
2914
2915     /* For enhanced metafiles (enhmfdrv) */
2916     test_ExtTextOut();
2917     test_ExtTextOutScale();
2918     test_SaveDC();
2919     test_emf_BitBlt();
2920
2921     /* For win-format metafiles (mfdrv) */
2922     test_mf_SaveDC();
2923     test_mf_Blank();
2924     test_mf_Graphics();
2925     test_mf_PatternBrush();
2926     test_CopyMetaFile();
2927     test_SetMetaFileBits();
2928     test_mf_ExtTextOut_on_path();
2929     test_emf_ExtTextOut_on_path();
2930     test_emf_clipping();
2931
2932     /* For metafile conversions */
2933     test_mf_conversions();
2934     test_SetWinMetaFileBits();
2935     test_GetWinMetaFileBits();
2936
2937     test_gdiis();
2938     test_SetEnhMetaFileBits();
2939 }