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