gdi32: Slightly relax EMF record comparisons allowing rounding errors.
[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         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
125         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
126
127         /* compare up to lfOutPrecision, other values are not interesting,
128          * and in fact sometimes arbitrary adapted by Win9x.
129          */
130         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
131         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
132
133         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
134         {
135             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
136                                      n_record, i, dx[i], orig_dx[i]);
137         }
138         n_record++;
139         emr_processed = TRUE;
140         break;
141     }
142
143     default:
144         break;
145     }
146
147     return 1;
148 }
149
150 static void test_ExtTextOut(void)
151 {
152     HWND hwnd;
153     HDC hdcDisplay, hdcMetafile;
154     HENHMETAFILE hMetafile;
155     HFONT hFont;
156     static const char text[] = "Simple text to test ExtTextOut on metafiles";
157     INT i, len, dx[256];
158     static const RECT rc = { 0, 0, 100, 100 };
159     BOOL ret;
160
161     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
162
163     /* Win9x doesn't play EMFs on invisible windows */
164     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
165                            0, 0, 200, 200, 0, 0, 0, NULL);
166     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
167
168     hdcDisplay = GetDC(hwnd);
169     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
170
171     trace("hdcDisplay %p\n", hdcDisplay);
172
173     SetMapMode(hdcDisplay, MM_TEXT);
174
175     memset(&orig_lf, 0, sizeof(orig_lf));
176
177     orig_lf.lfCharSet = ANSI_CHARSET;
178     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
179     orig_lf.lfWeight = FW_DONTCARE;
180     orig_lf.lfHeight = 7;
181     orig_lf.lfQuality = DEFAULT_QUALITY;
182     lstrcpyA(orig_lf.lfFaceName, "Arial");
183     hFont = CreateFontIndirectA(&orig_lf);
184     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
185
186     hFont = SelectObject(hdcDisplay, hFont);
187
188     len = lstrlenA(text);
189     for (i = 0; i < len; i++)
190     {
191         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
192         ok( ret, "GetCharWidthA error %d\n", GetLastError());
193     }
194     hFont = SelectObject(hdcDisplay, hFont);
195
196     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
198
199     trace("hdcMetafile %p\n", hdcMetafile);
200
201     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
202        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
203
204     hFont = SelectObject(hdcMetafile, hFont);
205
206     /* 1. pass NULL lpDx */
207     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
208     ok( ret, "ExtTextOutA error %d\n", GetLastError());
209
210     /* 2. pass custom lpDx */
211     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
212     ok( ret, "ExtTextOutA error %d\n", GetLastError());
213
214     hFont = SelectObject(hdcMetafile, hFont);
215     ret = DeleteObject(hFont);
216     ok( ret, "DeleteObject error %d\n", GetLastError());
217
218     hMetafile = CloseEnhMetaFile(hdcMetafile);
219     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
220
221     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
222
223     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
225
226     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
227     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
228     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
229     SetROP2(hdcDisplay, R2_NOT);
230     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
231     SetPolyFillMode(hdcDisplay, WINDING);
232     SetStretchBltMode(hdcDisplay, HALFTONE);
233
234     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
235     SetBkMode(hdcDisplay, OPAQUE);
236
237     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
238     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
239
240     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
241         "text align %08x\n", GetTextAlign(hdcDisplay));
242     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
243     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
244     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
245     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
246     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
247     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
248
249     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
250
251     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
252        "A valid hdc has to require a valid rc\n");
253
254     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
255        "A null hdc does not require a valid rc\n");
256
257     ret = DeleteEnhMetaFile(hMetafile);
258     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
259     ret = ReleaseDC(hwnd, hdcDisplay);
260     ok( ret, "ReleaseDC error %d\n", GetLastError());
261     DestroyWindow(hwnd);
262 }
263
264 static void check_dc_state(HDC hdc, int restore_no,
265                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
266                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
267 {
268     BOOL ret;
269     XFORM xform;
270     POINT vp_org, win_org;
271     SIZE vp_size, win_size;
272     FLOAT xscale, yscale, edx, edy;
273
274     SetLastError(0xdeadbeef);
275     ret = GetWorldTransform(hdc, &xform);
276     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
277     ok(ret, "GetWorldTransform error %u\n", GetLastError());
278
279     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
280
281     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
282     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
283
284     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
285     trace("x scale %f\n", xscale);
286     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
287        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
288
289     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
290     trace("y scale %f\n", yscale);
291     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
292        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
293
294     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
295     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
296     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
297     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
298
299     return;
300
301 win9x_here:
302
303     GetWindowOrgEx(hdc, &win_org);
304     GetViewportOrgEx(hdc, &vp_org);
305     GetWindowExtEx(hdc, &win_size);
306     GetViewportExtEx(hdc, &vp_size);
307
308     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
309     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
310
311     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
312     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
313
314     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
315     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
316
317     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
318     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
319 }
320
321 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
322                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
323 {
324     BOOL ret;
325     XFORM xform;
326     POINT pt;
327     SIZE size;
328     static int save_state;
329     static int restore_no;
330
331     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
332            hdc, emr->iType, emr->nSize, (void *)param);
333
334     trace("BEFORE:\n");
335     SetLastError(0xdeadbeef);
336     ret = GetWorldTransform(hdc, &xform);
337     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
338     {
339         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
340         trace("window org (%d,%d)\n", pt.x, pt.y);
341         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
342         trace("vport org (%d,%d)\n", pt.x, pt.y);
343         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
344         trace("window ext (%d,%d)\n", size.cx, size.cy);
345         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
346         trace("vport ext (%d,%d)\n", size.cx, size.cy);
347     }
348     else
349     {
350         ok(ret, "GetWorldTransform error %u\n", GetLastError());
351         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
352     }
353
354     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
355
356     switch (emr->iType)
357     {
358     case EMR_HEADER:
359     {
360         static RECT exp_bounds = { 0, 0, 150, 150 };
361         RECT bounds;
362         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
363
364         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
365                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
366                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
367         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
368                emf->szlDevice.cx, emf->szlDevice.cy);
369
370         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
371         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
372
373         save_state = 0;
374         restore_no = 0;
375         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
376         break;
377     }
378
379     case EMR_LINETO:
380         {
381             const EMRLINETO *line = (const EMRLINETO *)emr;
382             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
383             break;
384         }
385     case EMR_SETWINDOWORGEX:
386         {
387             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
388             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
389             break;
390         }
391     case EMR_SETWINDOWEXTEX:
392         {
393             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
394             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
395             break;
396         }
397     case EMR_SETVIEWPORTORGEX:
398         {
399             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
400             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
401             break;
402         }
403     case EMR_SETVIEWPORTEXTEX:
404         {
405             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
406             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
407             break;
408         }
409     case EMR_SAVEDC:
410         save_state++;
411         trace("EMR_SAVEDC\n");
412         break;
413
414     case EMR_RESTOREDC:
415         {
416             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
417             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
418
419             switch(++restore_no)
420             {
421             case 1:
422                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
423                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
424                 break;
425             case 2:
426                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
427                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
428                 break;
429             case 3:
430                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
431                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
432                 break;
433             }
434             ok(restore_no <= 3, "restore_no %d\n", restore_no);
435             save_state += restoredc->iRelative;
436             break;
437         }
438     case EMR_EOF:
439         ok(save_state == 0, "EOF save_state %d\n", save_state);
440         break;
441     }
442
443     trace("AFTER:\n");
444     SetLastError(0xdeadbeef);
445     ret = GetWorldTransform(hdc, &xform);
446     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
447     {
448         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
449         trace("window org (%d,%d)\n", pt.x, pt.y);
450         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
451         trace("vport org (%d,%d)\n", pt.x, pt.y);
452         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
453         trace("window ext (%d,%d)\n", size.cx, size.cy);
454         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
455         trace("vport ext (%d,%d)\n", size.cx, size.cy);
456     }
457     else
458     {
459         ok(ret, "GetWorldTransform error %u\n", GetLastError());
460         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
461     }
462
463     return 1;
464 }
465
466 static void test_SaveDC(void)
467 {
468     HDC hdcMetafile, hdcDisplay;
469     HENHMETAFILE hMetafile;
470     HWND hwnd;
471     int ret;
472     static const RECT rc = { 0, 0, 150, 150 };
473
474     /* Win9x doesn't play EMFs on invisible windows */
475     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
476                            0, 0, 200, 200, 0, 0, 0, NULL);
477     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
478
479     hdcDisplay = GetDC(hwnd);
480     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
481
482     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
483     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
484
485     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
486
487     /* Need to write something to the emf, otherwise Windows won't play it back */
488     LineTo(hdcMetafile, 150, 150);
489
490     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
491     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
492     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
493     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
494
495     /* Force Win9x to update DC state */
496     SetPixelV(hdcMetafile, 50, 50, 0);
497
498     ret = SaveDC(hdcMetafile);
499     ok(ret == 1, "ret = %d\n", ret);
500
501     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
502     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
503     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
504     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
505
506     /* Force Win9x to update DC state */
507     SetPixelV(hdcMetafile, 50, 50, 0);
508
509     ret = SaveDC(hdcMetafile);
510     ok(ret == 2, "ret = %d\n", ret);
511
512     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
513     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
514     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
515     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
516
517     /* Force Win9x to update DC state */
518     SetPixelV(hdcMetafile, 50, 50, 0);
519
520     ret = SaveDC(hdcMetafile);
521     ok(ret == 3, "ret = %d\n", ret);
522
523     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
524     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
525     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
526     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
527
528     /* Force Win9x to update DC state */
529     SetPixelV(hdcMetafile, 50, 50, 0);
530
531     ret = RestoreDC(hdcMetafile, -1);
532     ok(ret, "ret = %d\n", ret);
533
534     ret = SaveDC(hdcMetafile);
535     ok(ret == 3, "ret = %d\n", ret);
536
537     ret = RestoreDC(hdcMetafile, 1);
538     ok(ret, "ret = %d\n", ret);
539
540     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
541     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
542     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
543     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
544
545     /* Force Win9x to update DC state */
546     SetPixelV(hdcMetafile, 50, 50, 0);
547
548     ret = SaveDC(hdcMetafile);
549     ok(ret == 1, "ret = %d\n", ret);
550
551     ret = SaveDC(hdcMetafile);
552     ok(ret == 2, "ret = %d\n", ret);
553
554     hMetafile = CloseEnhMetaFile(hdcMetafile);
555     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
556
557     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
558     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
559
560     ret = DeleteEnhMetaFile(hMetafile);
561     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
562     ret = ReleaseDC(hwnd, hdcDisplay);
563     ok( ret, "ReleaseDC error %d\n", GetLastError());
564     DestroyWindow(hwnd);
565 }
566
567 /* Win-format metafile (mfdrv) tests */
568 /* These tests compare the generated metafiles byte-by-byte */
569 /* with the nominal results. */
570
571 /* Maximum size of sample metafiles in bytes. */
572 #define MF_BUFSIZE 512
573
574 /* 8x8 bitmap data for a pattern brush */
575 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
576     0x01, 0x00, 0x02, 0x00,
577     0x03, 0x00, 0x04, 0x00,
578     0x05, 0x00, 0x06, 0x00,
579     0x07, 0x00, 0x08, 0x00
580 };
581
582 /* Sample metafiles to be compared to the outputs of the
583  * test functions.
584  */
585
586 static const unsigned char MF_BLANK_BITS[] = {
587     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
588     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
589     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
590 };
591
592 static const unsigned char MF_GRAPHICS_BITS[] = {
593     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
594     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
595     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
596     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
597     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
598     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
599     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
600     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
601     0x00, 0x00, 0x00, 0x00
602 };
603
604 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
605     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
606     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
607     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
608     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
609     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
610     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
611     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
615     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
616     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
617     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
618     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
619     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
620     0x00, 0x00
621 };
622
623 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
624 {
625     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
626     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
627     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
628     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
629     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
630     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
631     0x00, 0x00
632 };
633
634 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
635 {
636     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
637     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
639     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
641     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
642     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
643     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
646     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
647     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
649     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
650     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
651     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
653     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
654     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
655     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
656     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
657     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
659     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
660     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
661     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
662     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
663     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
664     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
665     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
666     0x14, 0x00, 0x00, 0x00
667 };
668
669 static const unsigned char MF_LINETO_BITS[] = {
670     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
671     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
672     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
673     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
674     0x00, 0x00
675 };
676
677 static const unsigned char EMF_LINETO_BITS[] = {
678     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
679     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
681     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
683     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
684     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
685     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
688     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
689     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
691     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
692     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
693     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
694     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
695     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
696     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
697     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
698     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
699     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
700     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
701     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
702     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
703     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
704     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
705     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
706     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
707     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
708     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
709     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
710     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
711     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
712     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
713     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
714     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
715     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
716     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
717 };
718
719 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
720     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
721     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
723     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
725     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
726     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
727     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
728     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
730     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
731     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
733     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
734     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
735     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
736     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
737     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
738     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
739     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
740     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
741     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
742     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
743     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
744     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
745     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
746     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
747     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
748     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
749     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
750     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
751     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
752     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
753     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
754     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
755     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
756     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
757     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
758     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
759 };
760
761 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
762     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
763     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
765     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
767     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
768     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
769     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
772     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
773     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
775     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
776     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
777     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
778     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
779     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
780     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
781     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
782     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
783     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
784     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
785     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
786     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
787     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
788     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
789     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
790     0x14, 0x00, 0x00, 0x00
791 };
792
793 /* For debugging or dumping the raw metafiles produced by
794  * new test functions.
795  */
796 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
797                                  INT nobj, LPARAM param)
798 {
799     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
800            hdc, mr->rdFunction, mr->rdSize, (void *)param);
801     return TRUE;
802 }
803
804 /* For debugging or dumping the raw metafiles produced by
805  * new test functions.
806  */
807
808 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
809 {
810     BYTE buf[MF_BUFSIZE];
811     UINT mfsize, i;
812
813     if (!winetest_debug) return;
814
815     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
816     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
817
818     printf ("MetaFile %s has bits:\n{\n    ", desc);
819     for (i=0; i<mfsize; i++)
820     {
821         printf ("0x%02x", buf[i]);
822         if (i == mfsize-1)
823             printf ("\n");
824         else if (i % 8 == 7)
825             printf (",\n    ");
826         else
827             printf (", ");
828     }
829     printf ("};\n");
830 }
831
832 /* Compare the metafile produced by a test function with the
833  * expected raw metafile data in "bits".
834  * Return value is 0 for a perfect match,
835  * -1 if lengths aren't equal,
836  * otherwise returns the number of non-matching bytes.
837  */
838
839 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
840     const char *desc)
841 {
842     unsigned char buf[MF_BUFSIZE];
843     UINT mfsize, i;
844     int diff;
845
846     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
847     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
848     if (mfsize < MF_BUFSIZE)
849         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
850             desc, mfsize, bsize);
851     else
852         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
853             desc, mfsize, bsize);
854     if (mfsize != bsize)
855         return -1;
856
857     diff = 0;
858     for (i=0; i<bsize; i++)
859     {
860        if (buf[i] !=  bits[i])
861            diff++;
862     }
863     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
864         desc, mfsize, bsize, diff);
865
866     return diff; 
867 }
868
869 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
870 {
871     unsigned char buf[MF_BUFSIZE];
872     DWORD mfsize, rd_size, i;
873     int diff;
874     HANDLE hfile;
875     BOOL ret;
876
877     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
878     assert(hfile != INVALID_HANDLE_VALUE);
879
880     mfsize = GetFileSize(hfile, NULL);
881     assert(mfsize <= MF_BUFSIZE);
882
883     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
884     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
885
886     CloseHandle(hfile);
887
888     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
889
890     if (mfsize != bsize)
891         return -1;
892
893     diff = 0;
894     for (i=0; i<bsize; i++)
895     {
896         if (buf[i] != bits[i])
897             diff++;
898     }
899     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
900         desc, mfsize, bsize, diff);
901
902     return diff; 
903 }
904
905 /* For debugging or dumping the raw EMFs produced by
906  * new test functions.
907  */
908 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
909 {
910     BYTE buf[MF_BUFSIZE];
911     UINT mfsize, i;
912
913     if (!winetest_debug) return;
914
915     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
916     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
917
918     printf("EMF %s has bits:\n{\n    ", desc);
919     for (i = 0; i < mfsize; i++)
920     {
921         printf ("0x%02x", buf[i]);
922         if (i == mfsize-1)
923             printf ("\n");
924         else if (i % 8 == 7)
925             printf (",\n    ");
926         else
927             printf (", ");
928     }
929     printf ("};\n");
930 }
931
932 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
933 {
934     BYTE *emf;
935     BYTE buf[MF_BUFSIZE];
936     UINT mfsize, offset;
937
938     if (!winetest_debug) return;
939
940     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
941     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
942
943     printf("EMF %s has records:\n", desc);
944
945     emf = buf;
946     offset = 0;
947     while(offset < mfsize)
948     {
949         EMR *emr = (EMR *)(emf + offset);
950         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
951         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
952         offset += emr->nSize;
953     }
954 }
955
956 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
957 {
958     const BYTE *buf;
959     DWORD i;
960
961     if (!winetest_debug) return;
962
963     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
964     buf = (const BYTE *)emr;
965     for (i = 0; i < emr->nSize; i++)
966     {
967         printf ("0x%02x", buf[i]);
968         if (i == emr->nSize - 1)
969             printf ("\n");
970         else if (i % 8 == 7)
971             printf (",\n");
972         else
973             printf (", ");
974     }
975     printf ("};\n");
976 }
977
978 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
979                              const char *desc, BOOL ignore_scaling, BOOL todo)
980 {
981     int diff;
982
983     if (emr1->iType != emr2->iType && todo)
984     {
985         todo_wine
986         {
987             ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
988                desc, emr1->iType, emr2->iType);
989         }
990     }
991     else
992         ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
993            desc, emr1->iType, emr2->iType);
994
995     if (emr1->nSize != emr2->nSize && todo)
996     {
997         todo_wine
998         {
999             ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1000                desc, emr1->nSize, emr2->nSize);
1001         }
1002     }
1003     else
1004         ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1005            desc, emr1->nSize, emr2->nSize);
1006
1007     /* iType and nSize mismatches are fatal */
1008     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1009
1010     /* contents of EMR_GDICOMMENT are not interesting */
1011     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1012
1013     /* different Windows versions setup DC scaling differently when
1014      * converting an old style metafile to an EMF.
1015      */
1016     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1017                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1018         return TRUE;
1019
1020     diff = memcmp(emr1->dParm, emr2->dParm, emr1->nSize - sizeof(EMR));
1021     if (diff && todo)
1022     {
1023         todo_wine
1024             ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1025     }
1026     else
1027         ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1028
1029     if (diff)
1030     {
1031         dump_emf_record(emr1, "expected bits");
1032         dump_emf_record(emr2, "actual bits");
1033     }
1034
1035     return diff == 0 || todo; /* report all non-fatal record mismatches */
1036 }
1037
1038 /* Compare the EMF produced by a test function with the
1039  * expected raw EMF data in "bits".
1040  * Return value is 0 for a perfect match,
1041  * -1 if lengths aren't equal,
1042  * otherwise returns the number of non-matching bytes.
1043  */
1044 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1045                             UINT bsize, const char *desc,
1046                             BOOL ignore_scaling, BOOL todo)
1047 {
1048     unsigned char buf[MF_BUFSIZE];
1049     UINT mfsize, offset;
1050     const ENHMETAHEADER *emh1, *emh2;
1051
1052     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1053     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1054
1055     if (mfsize < MF_BUFSIZE)
1056     {
1057         if (mfsize != bsize && todo)
1058         {
1059         todo_wine
1060         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1061         }
1062         else
1063         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1064     }
1065     else
1066         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1067            desc, mfsize, bsize);
1068
1069     /* basic things must match */
1070     emh1 = (const ENHMETAHEADER *)bits;
1071     emh2 = (const ENHMETAHEADER *)buf;
1072     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1073     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1074     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1075     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1076
1077     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1078     ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1079     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1080     if (todo && emh1->nBytes != emh2->nBytes)
1081     {
1082         todo_wine
1083             ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1084     }
1085     else
1086         ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1087     if (todo && emh1->nRecords != emh2->nRecords)
1088     {
1089         todo_wine
1090             ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1091     }
1092     else
1093         ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1094
1095     offset = emh1->nSize;
1096     while (offset < emh1->nBytes)
1097     {
1098         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset);
1099         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset);
1100
1101         trace("EMF record %u, size %u/record %u, size %u\n",
1102               emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1103
1104         if (!match_emf_record(emr1, emr2, desc, ignore_scaling, todo)) return -1;
1105
1106         offset += emr1->nSize;
1107     }
1108     return 0;
1109 }
1110
1111 /* Test a blank metafile.  May be used as a template for new tests. */
1112
1113 static void test_mf_Blank(void)
1114 {
1115     HDC hdcMetafile;
1116     HMETAFILE hMetafile;
1117     INT caps;
1118     BOOL ret;
1119     INT type;
1120
1121     hdcMetafile = CreateMetaFileA(NULL);
1122     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1123     trace("hdcMetafile %p\n", hdcMetafile);
1124
1125 /* Tests on metafile initialization */
1126     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1127     ok (caps == DT_METAFILE,
1128         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1129
1130     hMetafile = CloseMetaFile(hdcMetafile);
1131     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1132     type = GetObjectType(hMetafile);
1133     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1134     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1135
1136     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1137         "mf_blank") != 0)
1138     {
1139         dump_mf_bits(hMetafile, "mf_Blank");
1140         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1141     }
1142
1143     ret = DeleteMetaFile(hMetafile);
1144     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1145 }
1146
1147 static void test_CopyMetaFile(void)
1148 {
1149     HDC hdcMetafile;
1150     HMETAFILE hMetafile, hmf_copy;
1151     BOOL ret;
1152     char temp_path[MAX_PATH];
1153     char mf_name[MAX_PATH];
1154     INT type;
1155
1156     hdcMetafile = CreateMetaFileA(NULL);
1157     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1158     trace("hdcMetafile %p\n", hdcMetafile);
1159
1160     hMetafile = CloseMetaFile(hdcMetafile);
1161     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1162     type = GetObjectType(hMetafile);
1163     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1164
1165     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1166         "mf_blank") != 0)
1167     {
1168         dump_mf_bits(hMetafile, "mf_Blank");
1169         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1170     }
1171
1172     GetTempPathA(MAX_PATH, temp_path);
1173     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1174
1175     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1176     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1177
1178     type = GetObjectType(hmf_copy);
1179     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1180
1181     ret = DeleteMetaFile(hMetafile);
1182     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1183
1184     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1185     {
1186         dump_mf_bits(hMetafile, "mf_Blank");
1187         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1188     }
1189
1190     ret = DeleteMetaFile(hmf_copy);
1191     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1192
1193     DeleteFileA(mf_name);
1194 }
1195
1196 static void test_SetMetaFileBits(void)
1197 {
1198     HMETAFILE hmf;
1199     INT type;
1200     BOOL ret;
1201     BYTE buf[256];
1202     METAHEADER *mh;
1203
1204     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1205     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1206     type = GetObjectType(hmf);
1207     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1208
1209     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1210     {
1211         dump_mf_bits(hmf, "mf_Graphics");
1212         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1213     }
1214
1215     ret = DeleteMetaFile(hmf);
1216     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1217
1218     /* NULL data crashes XP SP1 */
1219     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1220
1221     /* Now with not zero size */
1222     SetLastError(0xdeadbeef);
1223     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1224     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1225     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1226
1227     /* Now with not even size */
1228     SetLastError(0xdeadbeef);
1229     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1230     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1231     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1232
1233     /* Now with zeroed out or faked some header fields */
1234     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1235     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1236     mh = (METAHEADER *)buf;
1237     /* corruption of any of the below fields leads to a failure */
1238     mh->mtType = 0;
1239     mh->mtVersion = 0;
1240     mh->mtHeaderSize = 0;
1241     SetLastError(0xdeadbeef);
1242     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1243     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1244     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1245
1246     /* Now with corrupted mtSize field */
1247     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1248     mh = (METAHEADER *)buf;
1249     /* corruption of mtSize doesn't lead to a failure */
1250     mh->mtSize *= 2;
1251     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1252     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1253
1254     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1255     {
1256         dump_mf_bits(hmf, "mf_Graphics");
1257         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1258     }
1259
1260     ret = DeleteMetaFile(hmf);
1261     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1262
1263     /* Now with zeroed out mtSize field */
1264     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1265     mh = (METAHEADER *)buf;
1266     /* zeroing mtSize doesn't lead to a failure */
1267     mh->mtSize = 0;
1268     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1269     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1270
1271     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1272     {
1273         dump_mf_bits(hmf, "mf_Graphics");
1274         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1275     }
1276
1277     ret = DeleteMetaFile(hmf);
1278     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1279 }
1280
1281 /* Simple APIs from mfdrv/graphics.c
1282  */
1283
1284 static void test_mf_Graphics(void)
1285 {
1286     HDC hdcMetafile;
1287     HMETAFILE hMetafile;
1288     POINT oldpoint;
1289     BOOL ret;
1290
1291     hdcMetafile = CreateMetaFileA(NULL);
1292     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1293     trace("hdcMetafile %p\n", hdcMetafile);
1294
1295     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1296     ok( ret, "MoveToEx error %d.\n", GetLastError());
1297     ret = LineTo(hdcMetafile, 2, 2);
1298     ok( ret, "LineTo error %d.\n", GetLastError());
1299     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1300     ok( ret, "MoveToEx error %d.\n", GetLastError());
1301
1302 /* oldpoint gets garbage under Win XP, so the following test would
1303  * work under Wine but fails under Windows:
1304  *
1305  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1306  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1307  *       oldpoint.x, oldpoint.y);
1308  */
1309
1310     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1311     ok( ret, "Ellipse error %d.\n", GetLastError());
1312
1313     hMetafile = CloseMetaFile(hdcMetafile);
1314     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1315     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1316
1317     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1318         "mf_Graphics") != 0)
1319     {
1320         dump_mf_bits(hMetafile, "mf_Graphics");
1321         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1322     }
1323
1324     ret = DeleteMetaFile(hMetafile);
1325     ok( ret, "DeleteMetaFile(%p) error %d\n",
1326         hMetafile, GetLastError());
1327 }
1328
1329 static void test_mf_PatternBrush(void)
1330 {
1331     HDC hdcMetafile;
1332     HMETAFILE hMetafile;
1333     LOGBRUSH *orig_lb;
1334     HBRUSH hBrush;
1335     BOOL ret;
1336
1337     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1338
1339     orig_lb->lbStyle = BS_PATTERN;
1340     orig_lb->lbColor = RGB(0, 0, 0);
1341     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1342     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1343
1344     hBrush = CreateBrushIndirect (orig_lb);
1345     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1346
1347     hdcMetafile = CreateMetaFileA(NULL);
1348     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1349     trace("hdcMetafile %p\n", hdcMetafile);
1350
1351     hBrush = SelectObject(hdcMetafile, hBrush);
1352     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1353
1354     hMetafile = CloseMetaFile(hdcMetafile);
1355     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1356     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1357
1358     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1359         "mf_Pattern_Brush") != 0)
1360     {
1361         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1362         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1363     }
1364
1365     ret = DeleteMetaFile(hMetafile);
1366     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1367     ret = DeleteObject(hBrush);
1368     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1369     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1370     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1371         GetLastError());
1372     HeapFree (GetProcessHeap(), 0, orig_lb);
1373 }
1374
1375 static void test_mf_ExtTextOut_on_path(void)
1376 {
1377     HDC hdcMetafile;
1378     HMETAFILE hMetafile;
1379     BOOL ret;
1380     static const INT dx[4] = { 3, 5, 8, 12 };
1381
1382     hdcMetafile = CreateMetaFileA(NULL);
1383     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1384     trace("hdcMetafile %p\n", hdcMetafile);
1385
1386     ret = BeginPath(hdcMetafile);
1387     ok(!ret, "BeginPath on metafile DC should fail\n");
1388
1389     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1390     ok(ret, "ExtTextOut error %d\n", GetLastError());
1391
1392     ret = EndPath(hdcMetafile);
1393     ok(!ret, "EndPath on metafile DC should fail\n");
1394
1395     hMetafile = CloseMetaFile(hdcMetafile);
1396     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1397
1398     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1399         "mf_TextOut_on_path") != 0)
1400     {
1401         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1402         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1403     }
1404
1405     ret = DeleteMetaFile(hMetafile);
1406     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1407 }
1408
1409 static void test_emf_ExtTextOut_on_path(void)
1410 {
1411     HWND hwnd;
1412     HDC hdcDisplay, hdcMetafile;
1413     HENHMETAFILE hMetafile;
1414     BOOL ret;
1415     static const INT dx[4] = { 3, 5, 8, 12 };
1416
1417     /* Win9x doesn't play EMFs on invisible windows */
1418     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1419                            0, 0, 200, 200, 0, 0, 0, NULL);
1420     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1421
1422     hdcDisplay = GetDC(hwnd);
1423     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1424
1425     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1426     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1427
1428     ret = BeginPath(hdcMetafile);
1429     ok(ret, "BeginPath error %d\n", GetLastError());
1430
1431     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1432     ok(ret, "ExtTextOut error %d\n", GetLastError());
1433
1434     ret = EndPath(hdcMetafile);
1435     ok(ret, "EndPath error %d\n", GetLastError());
1436
1437     hMetafile = CloseEnhMetaFile(hdcMetafile);
1438     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1439
1440     /* this doesn't succeed yet: EMF has correct size, all EMF records
1441      * are there, but their contents don't match for different reasons.
1442      */
1443     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1444         "emf_TextOut_on_path", FALSE, TRUE) != 0)
1445     {
1446         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1447         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1448     }
1449
1450     ret = DeleteEnhMetaFile(hMetafile);
1451     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1452     ret = ReleaseDC(hwnd, hdcDisplay);
1453     ok(ret, "ReleaseDC error %d\n", GetLastError());
1454     DestroyWindow(hwnd);
1455 }
1456
1457 static const unsigned char EMF_CLIPPING[] =
1458 {
1459     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1460     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1461     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1462     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1463     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1464     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1465     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1466     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1467     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1469     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1470     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1471     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1472     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1473     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1474     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1475     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1476     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1477     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1478     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1479     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1480     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1481     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1482     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1483     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1485 };
1486
1487 static void translate( POINT *pt, UINT count, const XFORM *xform )
1488 {
1489     while (count--)
1490     {
1491         FLOAT x = (FLOAT)pt->x;
1492         FLOAT y = (FLOAT)pt->y;
1493         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1494         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1495         pt++;
1496     }
1497 }
1498
1499 /* Compare rectangles allowing rounding errors */
1500 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1501 {
1502     return abs(rc1->left - rc2->left) <= 1 &&
1503            abs(rc1->top - rc2->top) <= 1 &&
1504            abs(rc1->right - rc2->right) <= 1 &&
1505            abs(rc1->bottom - rc2->bottom) <= 1;
1506 }
1507
1508 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1509                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1510 {
1511     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1512     {
1513         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1514         union _rgn
1515         {
1516             RGNDATA data;
1517             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1518         };
1519         const union _rgn *rgn1;
1520         union _rgn rgn2;
1521         RECT rect, rc_transformed;
1522         const RECT *rc = (const RECT *)param;
1523         HRGN hrgn;
1524         XFORM xform;
1525         INT ret;
1526         BOOL is_win9x;
1527
1528         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1529                clip->cbRgnData, clip->iMode);
1530
1531         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1532         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1533            "too small data block: %u bytes\n", clip->cbRgnData);
1534         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1535             return 0;
1536
1537         rgn1 = (const union _rgn *)clip->RgnData;
1538
1539         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1540               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1541               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1542               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1543               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1544
1545         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1546
1547         rect = *(const RECT *)rgn1->data.Buffer;
1548         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1549         ok(EqualRect(&rect, rc), "rects don't match\n");
1550
1551         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1552         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1553         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1554         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1555
1556         hrgn = CreateRectRgn(0, 0, 0, 0);
1557
1558         memset(&xform, 0, sizeof(xform));
1559         SetLastError(0xdeadbeef);
1560         ret = GetWorldTransform(hdc, &xform);
1561         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1562         if (!is_win9x)
1563             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1564
1565         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1566
1567         ret = GetClipRgn(hdc, hrgn);
1568         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1569
1570         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1571
1572         ret = GetClipRgn(hdc, hrgn);
1573         ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1574
1575         /* Win9x returns empty clipping region */
1576         if (is_win9x) return 1;
1577
1578         ret = GetRegionData(hrgn, 0, NULL);
1579         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1580
1581         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1582
1583         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1584               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1585               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1586               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1587               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1588
1589         rect = rgn2.data.rdh.rcBound;
1590         rc_transformed = *rc;
1591         translate((POINT *)&rc_transformed, 2, &xform);
1592         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1593               rc_transformed.right, rc_transformed.bottom);
1594         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1595
1596         rect = *(const RECT *)rgn2.data.Buffer;
1597         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1598         rc_transformed = *rc;
1599         translate((POINT *)&rc_transformed, 2, &xform);
1600         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1601               rc_transformed.right, rc_transformed.bottom);
1602         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1603
1604         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1605         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1606         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1607         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1608
1609         DeleteObject(hrgn);
1610     }
1611     return 1;
1612 }
1613
1614 static void test_emf_clipping(void)
1615 {
1616     static const RECT rc = { 0, 0, 100, 100 };
1617     RECT rc_clip = { 100, 100, 1024, 1024 };
1618     HWND hwnd;
1619     HDC hdc;
1620     HENHMETAFILE hemf;
1621     HRGN hrgn;
1622     INT ret;
1623
1624     SetLastError(0xdeadbeef);
1625     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1626     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1627
1628     /* Need to write something to the emf, otherwise Windows won't play it back */
1629     LineTo(hdc, 1, 1);
1630
1631     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1632     ret = SelectClipRgn(hdc, hrgn);
1633     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1634
1635     SetLastError(0xdeadbeef);
1636     hemf = CloseEnhMetaFile(hdc);
1637     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1638
1639     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1640         "emf_clipping", FALSE, TRUE) != 0)
1641     {
1642         dump_emf_bits(hemf, "emf_clipping");
1643         dump_emf_records(hemf, "emf_clipping");
1644     }
1645
1646     DeleteObject(hrgn);
1647
1648     /* Win9x doesn't play EMFs on invisible windows */
1649     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1650                            0, 0, 200, 200, 0, 0, 0, NULL);
1651     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1652
1653     hdc = GetDC(hwnd);
1654
1655     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1656     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1657
1658     DeleteEnhMetaFile(hemf);
1659     ReleaseDC(hwnd, hdc);
1660     DestroyWindow(hwnd);
1661 }
1662
1663 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1664 {
1665     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1666     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1667     /* When using MM_TEXT Win9x does not update the mapping mode 
1668      * until a record is played which actually outputs something */
1669     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1670     LPtoDP(hdc, mapping, 2);
1671     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1672            lpEMFR->iType, lpEMFR->nSize,
1673            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1674
1675     if (lpEMFR->iType == EMR_LINETO)
1676     {
1677         INT x0, y0, x1, y1;
1678         if (!lpMFP || lpMFP->mm == MM_TEXT)
1679         {
1680             x0 = 0;
1681             y0 = 0;
1682             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1683             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1684         }
1685         else
1686         {
1687             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1688             
1689             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1690             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1691             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1692             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1693         }
1694         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1695             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1696             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1697             x0, y0, x1, y1);
1698     }
1699     return TRUE;
1700 }
1701
1702 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1703 {
1704     HDC hdcMf;
1705     HMETAFILE hmf;
1706     HENHMETAFILE hemf;
1707     BOOL ret;
1708     UINT size;
1709     LPBYTE pBits;
1710
1711     hdcMf = CreateMetaFile(NULL);
1712     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1713     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1714     ok(ret, "LineTo failed with error %d\n", GetLastError());
1715     hmf = CloseMetaFile(hdcMf);
1716     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1717
1718     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1719     {
1720         dump_mf_bits(hmf, "mf_LineTo");
1721         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1722     }
1723
1724     size = GetMetaFileBitsEx(hmf, 0, NULL);
1725     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1726     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1727     GetMetaFileBitsEx(hmf, size, pBits);
1728     DeleteMetaFile(hmf);
1729     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1730     HeapFree(GetProcessHeap(), 0, pBits);
1731     return hemf;
1732 }
1733
1734 static void test_mf_conversions(void)
1735 {
1736     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1737     {
1738         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1739         HENHMETAFILE hemf;
1740         METAFILEPICT mfp;
1741         RECT rect = { 0, 0, 100, 100 };
1742         mfp.mm = MM_ANISOTROPIC;
1743         mfp.xExt = 100;
1744         mfp.yExt = 100;
1745         mfp.hMF = NULL;
1746         hemf = create_converted_emf(&mfp);
1747
1748         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1749                              "emf_LineTo MM_ANISOTROPIC", TRUE, TRUE) != 0)
1750         {
1751             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1752             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1753         }
1754
1755         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1756
1757         DeleteEnhMetaFile(hemf);
1758         DeleteDC(hdcOffscreen);
1759     }
1760
1761     trace("Testing MF->EMF conversion (MM_TEXT)\n");
1762     {
1763         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1764         HENHMETAFILE hemf;
1765         METAFILEPICT mfp;
1766         RECT rect = { 0, 0, 100, 100 };
1767         mfp.mm = MM_TEXT;
1768         mfp.xExt = 0;
1769         mfp.yExt = 0;
1770         mfp.hMF = NULL;
1771         hemf = create_converted_emf(&mfp);
1772
1773         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1774                              "emf_LineTo MM_TEXT", TRUE, TRUE) != 0)
1775         {
1776             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1777             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1778         }
1779
1780         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1781
1782         DeleteEnhMetaFile(hemf);
1783         DeleteDC(hdcOffscreen);
1784     }
1785
1786     trace("Testing MF->EMF conversion (NULL mfp)\n");
1787     {
1788         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1789         HENHMETAFILE hemf;
1790         RECT rect = { 0, 0, 100, 100 };
1791         hemf = create_converted_emf(NULL);
1792
1793         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1794                              "emf_LineTo NULL", TRUE, TRUE) != 0)
1795         {
1796             dump_emf_bits(hemf, "emf_LineTo NULL");
1797             dump_emf_records(hemf, "emf_LineTo NULL");
1798         }
1799
1800         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1801
1802         DeleteEnhMetaFile(hemf);
1803         DeleteDC(hdcOffscreen);
1804     }
1805 }
1806
1807 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1808                                        LONG mm, LONG xExt, LONG yExt,
1809                                        RECTL * rclBounds, RECTL * rclFrame)
1810 {
1811   METAFILEPICT mfp;
1812   METAFILEPICT * mfpPtr = NULL;
1813   HENHMETAFILE emf;
1814   ENHMETAHEADER header;
1815   UINT res;
1816
1817   if (!mfpIsNull)
1818   {
1819     mfp.mm = mm;
1820     mfp.xExt = xExt;
1821     mfp.yExt = yExt;
1822     mfpPtr = &mfp;
1823   }
1824
1825   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1826   ok(emf != NULL, "SetWinMetaFileBits failed\n");
1827   if (!emf) return FALSE;
1828   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1829   ok(res != 0, "GetEnhMetaHeader failed\n");
1830   DeleteEnhMetaFile(emf);
1831   if (!res) return FALSE;
1832
1833   *rclBounds = header.rclBounds;
1834   *rclFrame = header.rclFrame;
1835   return TRUE;
1836 }
1837
1838 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1839                                          LONG mm, LONG xExt, LONG yExt,
1840                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1841 {
1842   RECTL rclBounds, rclFrame;
1843
1844   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1845   {
1846     const char * msg;
1847     char buf[64];
1848
1849     if (mfpIsNull)
1850     {
1851        msg = "mfp == NULL";
1852     }
1853     else
1854     {
1855       const char * mm_str;
1856       switch (mm)
1857       {
1858          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1859          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
1860          default:             mm_str = "Unexpected";
1861       }
1862       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1863       msg = buf;
1864     }
1865
1866     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1867     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1868     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1869     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1870     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1871     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1872     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1873     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1874   }
1875 }
1876
1877 static void test_SetWinMetaFileBits(void)
1878 {
1879   HMETAFILE wmf;
1880   HDC wmfDC;
1881   BYTE * buffer;
1882   UINT buffer_size;
1883   RECT rect;
1884   UINT res;
1885   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1886   RECTL rclBoundsIsotropic, rclFrameIsotropic;
1887   RECTL rclBounds, rclFrame;
1888   HDC dc;
1889   LONG diffx, diffy;
1890
1891   wmfDC = CreateMetaFile(NULL);
1892   ok(wmfDC != NULL, "CreateMetaFile failed\n");
1893   if (!wmfDC) return;
1894
1895   SetWindowExtEx(wmfDC, 100, 100, NULL);
1896   rect.left = rect.top = 0;
1897   rect.right = rect.bottom = 50;
1898   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1899   wmf = CloseMetaFile(wmfDC);
1900   ok(wmf != NULL, "Metafile creation failed\n");
1901   if (!wmf) return;
1902
1903   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1904   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1905   if (buffer_size == 0)
1906   {
1907     DeleteMetaFile(wmf);
1908     return;
1909   }
1910
1911   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1912   ok(buffer != NULL, "HeapAlloc failed\n");
1913   if (!buffer)
1914   {
1915     DeleteMetaFile(wmf);
1916     return;
1917   }
1918
1919   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1920   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1921   DeleteMetaFile(wmf);
1922   if (res != buffer_size)
1923   {
1924      HeapFree(GetProcessHeap(), 0, buffer);
1925      return;
1926   }
1927
1928   /* Get the reference bounds and frame */
1929   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1930   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
1931
1932   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1933      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1934      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1935
1936   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1937   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1938   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1939   if (diffx < 0) diffx = -diffx;
1940   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1941
1942   dc = CreateCompatibleDC(NULL);
1943
1944   /* Allow 1 mm difference (rounding errors) */
1945   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
1946   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
1947   if (diffx < 0) diffx = -diffx;
1948   if (diffy < 0) diffy = -diffy;
1949   todo_wine
1950   {
1951   ok(diffx <= 1 && diffy <= 1,
1952      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1953      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1954   }
1955
1956   /* Allow 1 mm difference (rounding errors) */
1957   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1958   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1959   if (diffx < 0) diffx = -diffx;
1960   if (diffy < 0) diffy = -diffy;
1961   todo_wine
1962   {
1963   ok(diffx <= 1 && diffy <= 1,
1964      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1965      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1966   }
1967   DeleteDC(dc);
1968
1969   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1970   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1971
1972   /* If xExt or yExt is zero or negative, the whole device surface is used */
1973   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1974   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1975   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1976   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1977   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1978   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1979   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1980   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1981   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1982   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1983   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1984   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1985
1986   /* MSDN says that negative xExt and yExt values specify a ratio.
1987      Check that this is wrong and the whole device surface is used */
1988   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1989   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1990
1991   /* Ordinary conversions */
1992
1993   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1994   {
1995     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1996        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
1997     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
1998        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
1999   }
2000
2001   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2002   {
2003     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2004        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2005     ok(rclBounds.left == 0 && rclBounds.top == 0,
2006        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2007
2008     /* Wine has a rounding error */
2009     diffx = rclBounds.right - rclBounds.bottom;
2010     if (diffx < 0) diffx = -diffx;
2011     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2012   }
2013
2014   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2015   {
2016     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2017        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2018   }
2019
2020   HeapFree(GetProcessHeap(), 0, buffer);
2021 }
2022
2023 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2024 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2025 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2026
2027 static void test_gdiis(void)
2028 {
2029     RECT rect = {0,0,100,100};
2030     HDC hdc, hemfDC, hmfDC;
2031     HENHMETAFILE hemf;
2032     HMODULE hgdi32;
2033
2034     /* resolve all the functions */
2035     hgdi32 = GetModuleHandle("gdi32");
2036     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2037     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2038     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2039
2040     /* they should all exist or none should exist */
2041     if(!pGdiIsMetaPrintDC)
2042         return;
2043
2044     /* try with nothing */
2045     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2046     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2047     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2048
2049     /* try with a metafile */
2050     hmfDC = CreateMetaFile(NULL);
2051     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2052     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2053     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2054     DeleteMetaFile(CloseMetaFile(hmfDC));
2055
2056     /* try with an enhanced metafile */
2057     hdc = GetDC(NULL);
2058     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2059     ok(hemfDC != NULL, "failed to create emf\n");
2060
2061     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2062     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2063     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2064
2065     hemf = CloseEnhMetaFile(hemfDC);
2066     ok(hemf != NULL, "failed to close EMF\n");
2067     DeleteEnhMetaFile(hemf);
2068     ReleaseDC(NULL,hdc);
2069 }
2070
2071 static void test_SetEnhMetaFileBits(void)
2072 {
2073     BYTE data[256];
2074     HENHMETAFILE hemf;
2075     ENHMETAHEADER *emh;
2076
2077     memset(data, 0xAA, sizeof(data));
2078     SetLastError(0xdeadbeef);
2079     hemf = SetEnhMetaFileBits(sizeof(data), data);
2080     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2081     ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %u\n", GetLastError());
2082
2083     emh = (ENHMETAHEADER *)data;
2084     memset(emh, 0, sizeof(*emh));
2085
2086     emh->iType = EMR_HEADER;
2087     emh->nSize = sizeof(*emh);
2088     emh->dSignature = ENHMETA_SIGNATURE;
2089     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2090     emh->nBytes = sizeof(*emh);
2091     /* emh->nRecords = 1; XP doesn't care about records */
2092     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2093
2094     SetLastError(0xdeadbeef);
2095     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2096     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2097     DeleteEnhMetaFile(hemf);
2098
2099     /* XP refuses to load unaligned EMF */
2100     emh->nBytes++;
2101     SetLastError(0xdeadbeef);
2102     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2103     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2104     /* XP doesn't set error in this case */
2105
2106     emh->dSignature = 0;
2107     emh->nBytes--;
2108     SetLastError(0xdeadbeef);
2109     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2110     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2111     /* XP doesn't set error in this case */
2112 }
2113
2114 START_TEST(metafile)
2115 {
2116     init_function_pointers();
2117
2118     /* For enhanced metafiles (enhmfdrv) */
2119     test_ExtTextOut();
2120     test_SaveDC();
2121
2122     /* For win-format metafiles (mfdrv) */
2123     test_mf_Blank();
2124     test_mf_Graphics();
2125     test_mf_PatternBrush();
2126     test_CopyMetaFile();
2127     test_SetMetaFileBits();
2128     test_mf_ExtTextOut_on_path();
2129     test_emf_ExtTextOut_on_path();
2130     test_emf_clipping();
2131
2132     /* For metafile conversions */
2133     test_mf_conversions();
2134     test_SetWinMetaFileBits();
2135
2136     test_gdiis();
2137     test_SetEnhMetaFileBits();
2138 }