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