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