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