quartz: Do not ignore current position in IEnumRegFiltersImpl_Next.
[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 void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
979 {
980     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
981           eto->rclBounds.right, eto->rclBounds.bottom);
982     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
983     trace("exScale: %f\n", eto->exScale);
984     trace("eyScale: %f\n", eto->eyScale);
985     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
986     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
987     trace("emrtext.offString %#x\n", eto->emrtext.offString);
988     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
989     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
990           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
991     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
992 }
993
994 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
995                              const char *desc, BOOL ignore_scaling, BOOL todo)
996 {
997     int diff;
998
999     if (emr1->iType != emr2->iType && todo)
1000     {
1001         todo_wine
1002         {
1003             ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1004                desc, emr1->iType, emr2->iType);
1005         }
1006     }
1007     else
1008         ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1009            desc, emr1->iType, emr2->iType);
1010
1011     if (emr1->nSize != emr2->nSize && todo)
1012     {
1013         todo_wine
1014         {
1015             ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1016                desc, emr1->nSize, emr2->nSize);
1017         }
1018     }
1019     else
1020         ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1021            desc, emr1->nSize, emr2->nSize);
1022
1023     /* iType and nSize mismatches are fatal */
1024     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1025
1026     /* contents of EMR_GDICOMMENT are not interesting */
1027     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1028
1029     /* different Windows versions setup DC scaling differently when
1030      * converting an old style metafile to an EMF.
1031      */
1032     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1033                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1034         return TRUE;
1035
1036     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1037     {
1038         EMREXTTEXTOUTW *eto1, *eto2;
1039
1040         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1041         memcpy(eto1, emr1, emr1->nSize);
1042         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1043         memcpy(eto2, emr2, emr2->nSize);
1044
1045         /* different Windows versions setup DC scaling differently */
1046         eto1->exScale = eto1->eyScale = 0.0;
1047         eto2->exScale = eto2->eyScale = 0.0;
1048
1049         diff = memcmp(eto1, eto2, emr1->nSize);
1050         if (diff)
1051         {
1052             dump_EMREXTTEXTOUT(eto1);
1053             dump_EMREXTTEXTOUT(eto2);
1054         }
1055         HeapFree(GetProcessHeap(), 0, eto1);
1056         HeapFree(GetProcessHeap(), 0, eto2);
1057     }
1058     else
1059         diff = memcmp(emr1, emr2, emr1->nSize);
1060     if (diff && todo)
1061     {
1062         todo_wine
1063             ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1064     }
1065     else
1066         ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1067
1068     if (diff)
1069     {
1070         dump_emf_record(emr1, "expected bits");
1071         dump_emf_record(emr2, "actual bits");
1072     }
1073
1074     return diff == 0 || todo; /* report all non-fatal record mismatches */
1075 }
1076
1077 /* Compare the EMF produced by a test function with the
1078  * expected raw EMF data in "bits".
1079  * Return value is 0 for a perfect match,
1080  * -1 if lengths aren't equal,
1081  * otherwise returns the number of non-matching bytes.
1082  */
1083 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1084                             UINT bsize, const char *desc,
1085                             BOOL ignore_scaling, BOOL todo)
1086 {
1087     unsigned char buf[MF_BUFSIZE];
1088     UINT mfsize, offset;
1089     const ENHMETAHEADER *emh1, *emh2;
1090
1091     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1092     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1093
1094     if (mfsize < MF_BUFSIZE)
1095     {
1096         if (mfsize != bsize && todo)
1097         {
1098         todo_wine
1099         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1100         }
1101         else
1102         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1103     }
1104     else
1105         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1106            desc, mfsize, bsize);
1107
1108     /* basic things must match */
1109     emh1 = (const ENHMETAHEADER *)bits;
1110     emh2 = (const ENHMETAHEADER *)buf;
1111     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1112     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1113     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1114     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1115
1116     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1117     ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1118     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1119     if (todo && emh1->nBytes != emh2->nBytes)
1120     {
1121         todo_wine
1122             ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1123     }
1124     else
1125         ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1126     if (todo && emh1->nRecords != emh2->nRecords)
1127     {
1128         todo_wine
1129             ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1130     }
1131     else
1132         ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1133
1134     offset = emh1->nSize;
1135     while (offset < emh1->nBytes)
1136     {
1137         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset);
1138         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset);
1139
1140         trace("EMF record %u, size %u/record %u, size %u\n",
1141               emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1142
1143         if (!match_emf_record(emr1, emr2, desc, ignore_scaling, todo)) return -1;
1144
1145         offset += emr1->nSize;
1146     }
1147     return 0;
1148 }
1149
1150 /* Test a blank metafile.  May be used as a template for new tests. */
1151
1152 static void test_mf_Blank(void)
1153 {
1154     HDC hdcMetafile;
1155     HMETAFILE hMetafile;
1156     INT caps;
1157     BOOL ret;
1158     INT type;
1159
1160     hdcMetafile = CreateMetaFileA(NULL);
1161     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1162     trace("hdcMetafile %p\n", hdcMetafile);
1163
1164 /* Tests on metafile initialization */
1165     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1166     ok (caps == DT_METAFILE,
1167         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1168
1169     hMetafile = CloseMetaFile(hdcMetafile);
1170     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1171     type = GetObjectType(hMetafile);
1172     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1173     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1174
1175     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1176         "mf_blank") != 0)
1177     {
1178         dump_mf_bits(hMetafile, "mf_Blank");
1179         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1180     }
1181
1182     ret = DeleteMetaFile(hMetafile);
1183     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1184 }
1185
1186 static void test_CopyMetaFile(void)
1187 {
1188     HDC hdcMetafile;
1189     HMETAFILE hMetafile, hmf_copy;
1190     BOOL ret;
1191     char temp_path[MAX_PATH];
1192     char mf_name[MAX_PATH];
1193     INT type;
1194
1195     hdcMetafile = CreateMetaFileA(NULL);
1196     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1197     trace("hdcMetafile %p\n", hdcMetafile);
1198
1199     hMetafile = CloseMetaFile(hdcMetafile);
1200     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1201     type = GetObjectType(hMetafile);
1202     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1203
1204     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1205         "mf_blank") != 0)
1206     {
1207         dump_mf_bits(hMetafile, "mf_Blank");
1208         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1209     }
1210
1211     GetTempPathA(MAX_PATH, temp_path);
1212     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1213
1214     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1215     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1216
1217     type = GetObjectType(hmf_copy);
1218     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1219
1220     ret = DeleteMetaFile(hMetafile);
1221     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1222
1223     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1224     {
1225         dump_mf_bits(hMetafile, "mf_Blank");
1226         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1227     }
1228
1229     ret = DeleteMetaFile(hmf_copy);
1230     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1231
1232     DeleteFileA(mf_name);
1233 }
1234
1235 static void test_SetMetaFileBits(void)
1236 {
1237     HMETAFILE hmf;
1238     INT type;
1239     BOOL ret;
1240     BYTE buf[256];
1241     METAHEADER *mh;
1242
1243     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1244     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1245     type = GetObjectType(hmf);
1246     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1247
1248     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1249     {
1250         dump_mf_bits(hmf, "mf_Graphics");
1251         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1252     }
1253
1254     ret = DeleteMetaFile(hmf);
1255     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1256
1257     /* NULL data crashes XP SP1 */
1258     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1259
1260     /* Now with not zero size */
1261     SetLastError(0xdeadbeef);
1262     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1263     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1264     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1265
1266     /* Now with not even size */
1267     SetLastError(0xdeadbeef);
1268     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1269     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1270     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1271
1272     /* Now with zeroed out or faked some header fields */
1273     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1274     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1275     mh = (METAHEADER *)buf;
1276     /* corruption of any of the below fields leads to a failure */
1277     mh->mtType = 0;
1278     mh->mtVersion = 0;
1279     mh->mtHeaderSize = 0;
1280     SetLastError(0xdeadbeef);
1281     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1282     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1283     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1284
1285     /* Now with corrupted mtSize field */
1286     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1287     mh = (METAHEADER *)buf;
1288     /* corruption of mtSize doesn't lead to a failure */
1289     mh->mtSize *= 2;
1290     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1291     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1292
1293     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1294     {
1295         dump_mf_bits(hmf, "mf_Graphics");
1296         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1297     }
1298
1299     ret = DeleteMetaFile(hmf);
1300     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1301
1302     /* Now with zeroed out mtSize field */
1303     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1304     mh = (METAHEADER *)buf;
1305     /* zeroing mtSize doesn't lead to a failure */
1306     mh->mtSize = 0;
1307     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1308     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1309
1310     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1311     {
1312         dump_mf_bits(hmf, "mf_Graphics");
1313         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1314     }
1315
1316     ret = DeleteMetaFile(hmf);
1317     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1318 }
1319
1320 /* Simple APIs from mfdrv/graphics.c
1321  */
1322
1323 static void test_mf_Graphics(void)
1324 {
1325     HDC hdcMetafile;
1326     HMETAFILE hMetafile;
1327     POINT oldpoint;
1328     BOOL ret;
1329
1330     hdcMetafile = CreateMetaFileA(NULL);
1331     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1332     trace("hdcMetafile %p\n", hdcMetafile);
1333
1334     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1335     ok( ret, "MoveToEx error %d.\n", GetLastError());
1336     ret = LineTo(hdcMetafile, 2, 2);
1337     ok( ret, "LineTo error %d.\n", GetLastError());
1338     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1339     ok( ret, "MoveToEx error %d.\n", GetLastError());
1340
1341 /* oldpoint gets garbage under Win XP, so the following test would
1342  * work under Wine but fails under Windows:
1343  *
1344  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1345  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1346  *       oldpoint.x, oldpoint.y);
1347  */
1348
1349     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1350     ok( ret, "Ellipse error %d.\n", GetLastError());
1351
1352     hMetafile = CloseMetaFile(hdcMetafile);
1353     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1354     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1355
1356     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1357         "mf_Graphics") != 0)
1358     {
1359         dump_mf_bits(hMetafile, "mf_Graphics");
1360         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1361     }
1362
1363     ret = DeleteMetaFile(hMetafile);
1364     ok( ret, "DeleteMetaFile(%p) error %d\n",
1365         hMetafile, GetLastError());
1366 }
1367
1368 static void test_mf_PatternBrush(void)
1369 {
1370     HDC hdcMetafile;
1371     HMETAFILE hMetafile;
1372     LOGBRUSH *orig_lb;
1373     HBRUSH hBrush;
1374     BOOL ret;
1375
1376     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1377
1378     orig_lb->lbStyle = BS_PATTERN;
1379     orig_lb->lbColor = RGB(0, 0, 0);
1380     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1381     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1382
1383     hBrush = CreateBrushIndirect (orig_lb);
1384     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1385
1386     hdcMetafile = CreateMetaFileA(NULL);
1387     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1388     trace("hdcMetafile %p\n", hdcMetafile);
1389
1390     hBrush = SelectObject(hdcMetafile, hBrush);
1391     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1392
1393     hMetafile = CloseMetaFile(hdcMetafile);
1394     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1395     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1396
1397     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1398         "mf_Pattern_Brush") != 0)
1399     {
1400         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1401         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1402     }
1403
1404     ret = DeleteMetaFile(hMetafile);
1405     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1406     ret = DeleteObject(hBrush);
1407     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1408     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1409     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1410         GetLastError());
1411     HeapFree (GetProcessHeap(), 0, orig_lb);
1412 }
1413
1414 static void test_mf_ExtTextOut_on_path(void)
1415 {
1416     HDC hdcMetafile;
1417     HMETAFILE hMetafile;
1418     BOOL ret;
1419     static const INT dx[4] = { 3, 5, 8, 12 };
1420
1421     hdcMetafile = CreateMetaFileA(NULL);
1422     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1423     trace("hdcMetafile %p\n", hdcMetafile);
1424
1425     ret = BeginPath(hdcMetafile);
1426     ok(!ret, "BeginPath on metafile DC should fail\n");
1427
1428     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1429     ok(ret, "ExtTextOut error %d\n", GetLastError());
1430
1431     ret = EndPath(hdcMetafile);
1432     ok(!ret, "EndPath on metafile DC should fail\n");
1433
1434     hMetafile = CloseMetaFile(hdcMetafile);
1435     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1436
1437     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1438         "mf_TextOut_on_path") != 0)
1439     {
1440         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1441         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1442     }
1443
1444     ret = DeleteMetaFile(hMetafile);
1445     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1446 }
1447
1448 static void test_emf_ExtTextOut_on_path(void)
1449 {
1450     HWND hwnd;
1451     HDC hdcDisplay, hdcMetafile;
1452     HENHMETAFILE hMetafile;
1453     BOOL ret;
1454     static const INT dx[4] = { 3, 5, 8, 12 };
1455
1456     /* Win9x doesn't play EMFs on invisible windows */
1457     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1458                            0, 0, 200, 200, 0, 0, 0, NULL);
1459     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1460
1461     hdcDisplay = GetDC(hwnd);
1462     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1463
1464     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1465     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1466
1467     ret = BeginPath(hdcMetafile);
1468     ok(ret, "BeginPath error %d\n", GetLastError());
1469
1470     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1471     ok(ret, "ExtTextOut error %d\n", GetLastError());
1472
1473     ret = EndPath(hdcMetafile);
1474     ok(ret, "EndPath error %d\n", GetLastError());
1475
1476     hMetafile = CloseEnhMetaFile(hdcMetafile);
1477     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1478
1479     /* this doesn't succeed yet: EMF has correct size, all EMF records
1480      * are there, but their contents don't match for different reasons.
1481      */
1482     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1483         "emf_TextOut_on_path", FALSE, FALSE) != 0)
1484     {
1485         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1486         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1487     }
1488
1489     ret = DeleteEnhMetaFile(hMetafile);
1490     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1491     ret = ReleaseDC(hwnd, hdcDisplay);
1492     ok(ret, "ReleaseDC error %d\n", GetLastError());
1493     DestroyWindow(hwnd);
1494 }
1495
1496 static const unsigned char EMF_CLIPPING[] =
1497 {
1498     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1499     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1500     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1501     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1502     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1503     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1504     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1505     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1507     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1508     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1509     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1511     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1512     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1513     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1514     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1515     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1516     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1517     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1518     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1519     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1520     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1521     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1522     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1523     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1524 };
1525
1526 static void translate( POINT *pt, UINT count, const XFORM *xform )
1527 {
1528     while (count--)
1529     {
1530         FLOAT x = (FLOAT)pt->x;
1531         FLOAT y = (FLOAT)pt->y;
1532         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1533         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1534         pt++;
1535     }
1536 }
1537
1538 /* Compare rectangles allowing rounding errors */
1539 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1540 {
1541     return abs(rc1->left - rc2->left) <= 1 &&
1542            abs(rc1->top - rc2->top) <= 1 &&
1543            abs(rc1->right - rc2->right) <= 1 &&
1544            abs(rc1->bottom - rc2->bottom) <= 1;
1545 }
1546
1547 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1548                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1549 {
1550     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1551     {
1552         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1553         union _rgn
1554         {
1555             RGNDATA data;
1556             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1557         };
1558         const union _rgn *rgn1;
1559         union _rgn rgn2;
1560         RECT rect, rc_transformed;
1561         const RECT *rc = (const RECT *)param;
1562         HRGN hrgn;
1563         XFORM xform;
1564         INT ret;
1565         BOOL is_win9x;
1566
1567         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1568                clip->cbRgnData, clip->iMode);
1569
1570         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1571         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1572            "too small data block: %u bytes\n", clip->cbRgnData);
1573         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1574             return 0;
1575
1576         rgn1 = (const union _rgn *)clip->RgnData;
1577
1578         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1579               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1580               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1581               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1582               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1583
1584         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1585
1586         rect = *(const RECT *)rgn1->data.Buffer;
1587         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1588         ok(EqualRect(&rect, rc), "rects don't match\n");
1589
1590         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1591         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1592         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1593         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1594
1595         hrgn = CreateRectRgn(0, 0, 0, 0);
1596
1597         memset(&xform, 0, sizeof(xform));
1598         SetLastError(0xdeadbeef);
1599         ret = GetWorldTransform(hdc, &xform);
1600         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1601         if (!is_win9x)
1602             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1603
1604         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1605
1606         ret = GetClipRgn(hdc, hrgn);
1607         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1608
1609         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1610
1611         ret = GetClipRgn(hdc, hrgn);
1612         ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1613
1614         /* Win9x returns empty clipping region */
1615         if (is_win9x) return 1;
1616
1617         ret = GetRegionData(hrgn, 0, NULL);
1618         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1619
1620         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1621
1622         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1623               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1624               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1625               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1626               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1627
1628         rect = rgn2.data.rdh.rcBound;
1629         rc_transformed = *rc;
1630         translate((POINT *)&rc_transformed, 2, &xform);
1631         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1632               rc_transformed.right, rc_transformed.bottom);
1633         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1634
1635         rect = *(const RECT *)rgn2.data.Buffer;
1636         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1637         rc_transformed = *rc;
1638         translate((POINT *)&rc_transformed, 2, &xform);
1639         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1640               rc_transformed.right, rc_transformed.bottom);
1641         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1642
1643         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1644         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1645         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1646         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1647
1648         DeleteObject(hrgn);
1649     }
1650     return 1;
1651 }
1652
1653 static void test_emf_clipping(void)
1654 {
1655     static const RECT rc = { 0, 0, 100, 100 };
1656     RECT rc_clip = { 100, 100, 1024, 1024 };
1657     HWND hwnd;
1658     HDC hdc;
1659     HENHMETAFILE hemf;
1660     HRGN hrgn;
1661     INT ret;
1662
1663     SetLastError(0xdeadbeef);
1664     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1665     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1666
1667     /* Need to write something to the emf, otherwise Windows won't play it back */
1668     LineTo(hdc, 1, 1);
1669
1670     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1671     ret = SelectClipRgn(hdc, hrgn);
1672     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1673
1674     SetLastError(0xdeadbeef);
1675     hemf = CloseEnhMetaFile(hdc);
1676     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1677
1678     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1679         "emf_clipping", FALSE, FALSE) != 0)
1680     {
1681         dump_emf_bits(hemf, "emf_clipping");
1682         dump_emf_records(hemf, "emf_clipping");
1683     }
1684
1685     DeleteObject(hrgn);
1686
1687     /* Win9x doesn't play EMFs on invisible windows */
1688     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1689                            0, 0, 200, 200, 0, 0, 0, NULL);
1690     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1691
1692     hdc = GetDC(hwnd);
1693
1694     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1695     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1696
1697     DeleteEnhMetaFile(hemf);
1698     ReleaseDC(hwnd, hdc);
1699     DestroyWindow(hwnd);
1700 }
1701
1702 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1703 {
1704     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1705     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1706     /* When using MM_TEXT Win9x does not update the mapping mode 
1707      * until a record is played which actually outputs something */
1708     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1709     LPtoDP(hdc, mapping, 2);
1710     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1711            lpEMFR->iType, lpEMFR->nSize,
1712            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1713
1714     if (lpEMFR->iType == EMR_LINETO)
1715     {
1716         INT x0, y0, x1, y1;
1717         if (!lpMFP || lpMFP->mm == MM_TEXT)
1718         {
1719             x0 = 0;
1720             y0 = 0;
1721             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1722             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1723         }
1724         else
1725         {
1726             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1727             
1728             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1729             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1730             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1731             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1732         }
1733         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1734             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1735             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1736             x0, y0, x1, y1);
1737     }
1738     return TRUE;
1739 }
1740
1741 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1742 {
1743     HDC hdcMf;
1744     HMETAFILE hmf;
1745     HENHMETAFILE hemf;
1746     BOOL ret;
1747     UINT size;
1748     LPBYTE pBits;
1749
1750     hdcMf = CreateMetaFile(NULL);
1751     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1752     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1753     ok(ret, "LineTo failed with error %d\n", GetLastError());
1754     hmf = CloseMetaFile(hdcMf);
1755     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1756
1757     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1758     {
1759         dump_mf_bits(hmf, "mf_LineTo");
1760         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1761     }
1762
1763     size = GetMetaFileBitsEx(hmf, 0, NULL);
1764     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1765     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1766     GetMetaFileBitsEx(hmf, size, pBits);
1767     DeleteMetaFile(hmf);
1768     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1769     HeapFree(GetProcessHeap(), 0, pBits);
1770     return hemf;
1771 }
1772
1773 static void test_mf_conversions(void)
1774 {
1775     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1776     {
1777         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1778         HENHMETAFILE hemf;
1779         METAFILEPICT mfp;
1780         RECT rect = { 0, 0, 100, 100 };
1781         mfp.mm = MM_ANISOTROPIC;
1782         mfp.xExt = 100;
1783         mfp.yExt = 100;
1784         mfp.hMF = NULL;
1785         hemf = create_converted_emf(&mfp);
1786
1787         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1788                              "emf_LineTo MM_ANISOTROPIC", TRUE, FALSE) != 0)
1789         {
1790             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1791             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1792         }
1793
1794         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1795
1796         DeleteEnhMetaFile(hemf);
1797         DeleteDC(hdcOffscreen);
1798     }
1799
1800     trace("Testing MF->EMF conversion (MM_TEXT)\n");
1801     {
1802         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1803         HENHMETAFILE hemf;
1804         METAFILEPICT mfp;
1805         RECT rect = { 0, 0, 100, 100 };
1806         mfp.mm = MM_TEXT;
1807         mfp.xExt = 0;
1808         mfp.yExt = 0;
1809         mfp.hMF = NULL;
1810         hemf = create_converted_emf(&mfp);
1811
1812         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1813                              "emf_LineTo MM_TEXT", TRUE, FALSE) != 0)
1814         {
1815             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1816             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1817         }
1818
1819         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1820
1821         DeleteEnhMetaFile(hemf);
1822         DeleteDC(hdcOffscreen);
1823     }
1824
1825     trace("Testing MF->EMF conversion (NULL mfp)\n");
1826     {
1827         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1828         HENHMETAFILE hemf;
1829         RECT rect = { 0, 0, 100, 100 };
1830         hemf = create_converted_emf(NULL);
1831
1832         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1833                              "emf_LineTo NULL", TRUE, FALSE) != 0)
1834         {
1835             dump_emf_bits(hemf, "emf_LineTo NULL");
1836             dump_emf_records(hemf, "emf_LineTo NULL");
1837         }
1838
1839         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1840
1841         DeleteEnhMetaFile(hemf);
1842         DeleteDC(hdcOffscreen);
1843     }
1844 }
1845
1846 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1847                                        LONG mm, LONG xExt, LONG yExt,
1848                                        RECTL * rclBounds, RECTL * rclFrame)
1849 {
1850   METAFILEPICT mfp;
1851   METAFILEPICT * mfpPtr = NULL;
1852   HENHMETAFILE emf;
1853   ENHMETAHEADER header;
1854   UINT res;
1855
1856   if (!mfpIsNull)
1857   {
1858     mfp.mm = mm;
1859     mfp.xExt = xExt;
1860     mfp.yExt = yExt;
1861     mfpPtr = &mfp;
1862   }
1863
1864   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1865   ok(emf != NULL, "SetWinMetaFileBits failed\n");
1866   if (!emf) return FALSE;
1867   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1868   ok(res != 0, "GetEnhMetaHeader failed\n");
1869   DeleteEnhMetaFile(emf);
1870   if (!res) return FALSE;
1871
1872   *rclBounds = header.rclBounds;
1873   *rclFrame = header.rclFrame;
1874   return TRUE;
1875 }
1876
1877 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1878                                          LONG mm, LONG xExt, LONG yExt,
1879                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1880 {
1881   RECTL rclBounds, rclFrame;
1882
1883   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1884   {
1885     const char * msg;
1886     char buf[64];
1887
1888     if (mfpIsNull)
1889     {
1890        msg = "mfp == NULL";
1891     }
1892     else
1893     {
1894       const char * mm_str;
1895       switch (mm)
1896       {
1897          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1898          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
1899          default:             mm_str = "Unexpected";
1900       }
1901       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1902       msg = buf;
1903     }
1904
1905     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1906     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1907     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1908     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1909     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1910     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1911     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1912     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1913   }
1914 }
1915
1916 static void test_SetWinMetaFileBits(void)
1917 {
1918   HMETAFILE wmf;
1919   HDC wmfDC;
1920   BYTE * buffer;
1921   UINT buffer_size;
1922   RECT rect;
1923   UINT res;
1924   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1925   RECTL rclBoundsIsotropic, rclFrameIsotropic;
1926   RECTL rclBounds, rclFrame;
1927   HDC dc;
1928   LONG diffx, diffy;
1929
1930   wmfDC = CreateMetaFile(NULL);
1931   ok(wmfDC != NULL, "CreateMetaFile failed\n");
1932   if (!wmfDC) return;
1933
1934   SetWindowExtEx(wmfDC, 100, 100, NULL);
1935   rect.left = rect.top = 0;
1936   rect.right = rect.bottom = 50;
1937   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1938   wmf = CloseMetaFile(wmfDC);
1939   ok(wmf != NULL, "Metafile creation failed\n");
1940   if (!wmf) return;
1941
1942   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1943   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1944   if (buffer_size == 0)
1945   {
1946     DeleteMetaFile(wmf);
1947     return;
1948   }
1949
1950   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1951   ok(buffer != NULL, "HeapAlloc failed\n");
1952   if (!buffer)
1953   {
1954     DeleteMetaFile(wmf);
1955     return;
1956   }
1957
1958   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1959   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1960   DeleteMetaFile(wmf);
1961   if (res != buffer_size)
1962   {
1963      HeapFree(GetProcessHeap(), 0, buffer);
1964      return;
1965   }
1966
1967   /* Get the reference bounds and frame */
1968   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1969   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
1970
1971   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1972      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1973      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1974
1975   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1976   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1977   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1978   if (diffx < 0) diffx = -diffx;
1979   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1980
1981   dc = CreateCompatibleDC(NULL);
1982
1983   /* Allow 1 mm difference (rounding errors) */
1984   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
1985   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
1986   if (diffx < 0) diffx = -diffx;
1987   if (diffy < 0) diffy = -diffy;
1988   todo_wine
1989   {
1990   ok(diffx <= 1 && diffy <= 1,
1991      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1992      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1993   }
1994
1995   /* Allow 1 mm difference (rounding errors) */
1996   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1997   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1998   if (diffx < 0) diffx = -diffx;
1999   if (diffy < 0) diffy = -diffy;
2000   todo_wine
2001   {
2002   ok(diffx <= 1 && diffy <= 1,
2003      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2004      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2005   }
2006   DeleteDC(dc);
2007
2008   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2009   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2010
2011   /* If xExt or yExt is zero or negative, the whole device surface is used */
2012   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2013   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2014   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2015   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2016   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2017   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2018   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2019   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2020   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2021   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2022   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2023   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2024
2025   /* MSDN says that negative xExt and yExt values specify a ratio.
2026      Check that this is wrong and the whole device surface is used */
2027   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2028   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2029
2030   /* Ordinary conversions */
2031
2032   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2033   {
2034     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2035        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2036     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2037        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2038   }
2039
2040   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2041   {
2042     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2043        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2044     ok(rclBounds.left == 0 && rclBounds.top == 0,
2045        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2046
2047     /* Wine has a rounding error */
2048     diffx = rclBounds.right - rclBounds.bottom;
2049     if (diffx < 0) diffx = -diffx;
2050     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2051   }
2052
2053   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2054   {
2055     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2056        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2057   }
2058
2059   HeapFree(GetProcessHeap(), 0, buffer);
2060 }
2061
2062 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2063 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2064 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2065
2066 static void test_gdiis(void)
2067 {
2068     RECT rect = {0,0,100,100};
2069     HDC hdc, hemfDC, hmfDC;
2070     HENHMETAFILE hemf;
2071     HMODULE hgdi32;
2072
2073     /* resolve all the functions */
2074     hgdi32 = GetModuleHandle("gdi32");
2075     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2076     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2077     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2078
2079     /* they should all exist or none should exist */
2080     if(!pGdiIsMetaPrintDC)
2081         return;
2082
2083     /* try with nothing */
2084     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2085     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2086     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2087
2088     /* try with a metafile */
2089     hmfDC = CreateMetaFile(NULL);
2090     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2091     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2092     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2093     DeleteMetaFile(CloseMetaFile(hmfDC));
2094
2095     /* try with an enhanced metafile */
2096     hdc = GetDC(NULL);
2097     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2098     ok(hemfDC != NULL, "failed to create emf\n");
2099
2100     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2101     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2102     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2103
2104     hemf = CloseEnhMetaFile(hemfDC);
2105     ok(hemf != NULL, "failed to close EMF\n");
2106     DeleteEnhMetaFile(hemf);
2107     ReleaseDC(NULL,hdc);
2108 }
2109
2110 static void test_SetEnhMetaFileBits(void)
2111 {
2112     BYTE data[256];
2113     HENHMETAFILE hemf;
2114     ENHMETAHEADER *emh;
2115
2116     memset(data, 0xAA, sizeof(data));
2117     SetLastError(0xdeadbeef);
2118     hemf = SetEnhMetaFileBits(sizeof(data), data);
2119     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2120     ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got %u\n", GetLastError());
2121
2122     emh = (ENHMETAHEADER *)data;
2123     memset(emh, 0, sizeof(*emh));
2124
2125     emh->iType = EMR_HEADER;
2126     emh->nSize = sizeof(*emh);
2127     emh->dSignature = ENHMETA_SIGNATURE;
2128     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2129     emh->nBytes = sizeof(*emh);
2130     /* emh->nRecords = 1; XP doesn't care about records */
2131     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2132
2133     SetLastError(0xdeadbeef);
2134     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2135     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2136     DeleteEnhMetaFile(hemf);
2137
2138     /* XP refuses to load unaligned EMF */
2139     emh->nBytes++;
2140     SetLastError(0xdeadbeef);
2141     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2142     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2143     /* XP doesn't set error in this case */
2144
2145     emh->dSignature = 0;
2146     emh->nBytes--;
2147     SetLastError(0xdeadbeef);
2148     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2149     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2150     /* XP doesn't set error in this case */
2151 }
2152
2153 START_TEST(metafile)
2154 {
2155     init_function_pointers();
2156
2157     /* For enhanced metafiles (enhmfdrv) */
2158     test_ExtTextOut();
2159     test_SaveDC();
2160
2161     /* For win-format metafiles (mfdrv) */
2162     test_mf_Blank();
2163     test_mf_Graphics();
2164     test_mf_PatternBrush();
2165     test_CopyMetaFile();
2166     test_SetMetaFileBits();
2167     test_mf_ExtTextOut_on_path();
2168     test_emf_ExtTextOut_on_path();
2169     test_emf_clipping();
2170
2171     /* For metafile conversions */
2172     test_mf_conversions();
2173     test_SetWinMetaFileBits();
2174
2175     test_gdiis();
2176     test_SetEnhMetaFileBits();
2177 }