First draft of ExtTextOut on an open path.
[wine] / dlls / gdi / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 %ld, emr->nSize %ld, 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 %08lx\n", GetBkColor(hdc));
81         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08lx\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 %ld\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[%ld] (%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 %ld\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[%ld] (%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 %ld\n", GetLastError());
167
168     hdcDisplay = GetDC(hwnd);
169     ok(hdcDisplay != 0, "GetDC error %ld\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 %ld\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 %ld\n", GetLastError());
193     }
194     hFont = SelectObject(hdcDisplay, hFont);
195
196     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\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 %ld\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 %ld\n", GetLastError());
213
214     hFont = SelectObject(hdcMetafile, hFont);
215     ret = DeleteObject(hFont);
216     ok( ret, "DeleteObject error %ld\n", GetLastError());
217
218     hMetafile = CloseEnhMetaFile(hdcMetafile);
219     ok(hMetafile != 0, "CloseEnhMetaFile error %ld\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 %ld\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 %ld\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 %08lx\n", GetBkColor(hdcDisplay));
243     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08lx\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 %ld\n", GetLastError());
259     ret = ReleaseDC(hwnd, hdcDisplay);
260     ok( ret, "ReleaseDC error %ld\n", GetLastError());
261     DestroyWindow(hwnd);
262 }
263
264 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
265                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
266 {
267     static int save_state;
268     static int restore_no;
269
270     switch (emr->iType)
271     {
272     case EMR_HEADER:
273         save_state = 0;
274         restore_no = 0;
275         break;
276
277     case EMR_SAVEDC:
278         save_state++;
279         break;
280
281     case EMR_RESTOREDC:
282         {
283             EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr;
284             switch(++restore_no)
285             {
286             case 1:
287                 ok(restoredc->iRelative == -1, "first restore %ld\n", restoredc->iRelative);
288                 break;
289
290             case 2:
291                 ok(restoredc->iRelative == -3, "second restore %ld\n", restoredc->iRelative);
292                 break;
293             case 3:
294                 ok(restoredc->iRelative == -2, "third restore %ld\n", restoredc->iRelative);
295                 break;
296             }
297             ok(restore_no <= 3, "restore_no %d\n", restore_no);
298             save_state += restoredc->iRelative;
299             break;
300         }
301     case EMR_EOF:
302         ok(save_state == 0, "EOF save_state %d\n", save_state);
303         break;
304     }
305
306
307     return 1;        
308 }
309
310 void test_SaveDC(void)
311 {
312     HDC hdcMetafile, hdcDisplay;
313     HENHMETAFILE hMetafile;
314     HWND hwnd;
315     int ret;
316     static const RECT rc = { 0, 0, 100, 100 };
317
318     /* Win9x doesn't play EMFs on invisible windows */
319     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
320                            0, 0, 200, 200, 0, 0, 0, NULL);
321     ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
322
323     hdcDisplay = GetDC(hwnd);
324     ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
325
326     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
327     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
328
329     /* Need to write something to the emf, otherwise Windows won't play it back */
330     LineTo(hdcMetafile, 100, 100);
331
332     ret = SaveDC(hdcMetafile);
333     ok(ret == 1, "ret = %d\n", ret);
334
335     ret = SaveDC(hdcMetafile);
336     ok(ret == 2, "ret = %d\n", ret);
337
338     ret = SaveDC(hdcMetafile);
339     ok(ret == 3, "ret = %d\n", ret);
340
341     ret = RestoreDC(hdcMetafile, -1);
342     ok(ret, "ret = %d\n", ret);
343
344     ret = SaveDC(hdcMetafile);
345     ok(ret == 3, "ret = %d\n", ret);
346
347     ret = RestoreDC(hdcMetafile, 1);
348     ok(ret, "ret = %d\n", ret);
349
350     ret = SaveDC(hdcMetafile);
351     ok(ret == 1, "ret = %d\n", ret);
352
353     ret = SaveDC(hdcMetafile);
354     ok(ret == 2, "ret = %d\n", ret);
355
356     hMetafile = CloseEnhMetaFile(hdcMetafile);
357     ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
358
359     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
360     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
361
362     ret = DeleteEnhMetaFile(hMetafile);
363     ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
364     ret = ReleaseDC(hwnd, hdcDisplay);
365     ok( ret, "ReleaseDC error %ld\n", GetLastError());
366     DestroyWindow(hwnd);
367 }
368
369 /* Win-format metafile (mfdrv) tests */
370 /* These tests compare the generated metafiles byte-by-byte */
371 /* with the nominal results. */
372
373 /* Maximum size of sample metafiles in bytes. */
374 #define MF_BUFSIZE 256
375
376 /* 8x8 bitmap data for a pattern brush */
377 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
378     0x01, 0x00, 0x02, 0x00,
379     0x03, 0x00, 0x04, 0x00,
380     0x05, 0x00, 0x06, 0x00,
381     0x07, 0x00, 0x08, 0x00
382 };
383
384 /* Sample metafiles to be compared to the outputs of the
385  * test functions.
386  */
387
388 static const unsigned char MF_BLANK_BITS[] = {
389     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
390     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
391     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
392 };
393
394 static const unsigned char MF_GRAPHICS_BITS[] = {
395     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
396     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
397     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
398     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
399     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
400     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
401     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
402     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
403     0x00, 0x00, 0x00, 0x00
404 };
405
406 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
407     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
408     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
409     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
410     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
411     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
412     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
413     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
417     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
418     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
419     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
420     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
421     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
422     0x00, 0x00
423 };
424
425 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
426 {
427     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
428     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
429     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
430     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
431     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
432     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
433     0x00, 0x00
434 };
435
436 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
437 {
438     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
439     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
441     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
443     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
444     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
445     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
448     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
449     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
451     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
452     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
453     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
455     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
456     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
457     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
458     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
459     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
461     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
462     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
463     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
464     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
465     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
466     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
467     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
468     0x14, 0x00, 0x00, 0x00
469 };
470
471 /* For debugging or dumping the raw metafiles produced by
472  * new test functions.
473  */
474 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
475                                  INT nobj, LPARAM param)
476 {
477     trace("hdc %p, mr->rdFunction %d, mr->rdSize %lu, param %p\n",
478            hdc, mr->rdFunction, mr->rdSize, (void *)param);
479     return TRUE;
480 }
481
482 /* For debugging or dumping the raw metafiles produced by
483  * new test functions.
484  */
485
486 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
487 {
488     char buf[MF_BUFSIZE];
489     UINT mfsize, i;
490
491     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
492     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
493
494     printf ("MetaFile %s has bits:\n{\n    ", desc);
495     for (i=0; i<mfsize; i++)
496     {
497         printf ("0x%.2hhx", buf[i]);
498         if (i == mfsize-1)
499             printf ("\n");
500         else if (i % 8 == 7)
501             printf (",\n    ");
502         else
503             printf (", ");
504     }
505     printf ("};\n");
506 }
507
508 /* Compare the metafile produced by a test function with the
509  * expected raw metafile data in "bits".
510  * Return value is 0 for a perfect match,
511  * -1 if lengths aren't equal,
512  * otherwise returns the number of non-matching bytes.
513  */
514
515 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
516     const char *desc)
517 {
518     unsigned char buf[MF_BUFSIZE];
519     UINT mfsize, i;
520     int diff;
521
522     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
523     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
524     if (mfsize < MF_BUFSIZE)
525         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
526             desc, mfsize, bsize);
527     else
528         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
529             desc, mfsize, bsize);
530     if (mfsize != bsize)
531         return -1;
532
533     diff = 0;
534     for (i=0; i<bsize; i++)
535     {
536        if (buf[i] !=  bits[i])
537            diff++;
538     }
539     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
540         desc, mfsize, bsize, diff);
541
542     return diff; 
543 }
544
545 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
546 {
547     unsigned char buf[MF_BUFSIZE];
548     DWORD mfsize, rd_size, i;
549     int diff;
550     HANDLE hfile;
551     BOOL ret;
552
553     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
554     assert(hfile != INVALID_HANDLE_VALUE);
555
556     mfsize = GetFileSize(hfile, NULL);
557     assert(mfsize <= MF_BUFSIZE);
558
559     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
560     ok( ret && rd_size == mfsize, "ReadFile: error %ld\n", GetLastError());
561
562     CloseHandle(hfile);
563
564     ok(mfsize == bsize, "%s: mfsize=%ld, bsize=%d.\n", desc, mfsize, bsize);
565
566     if (mfsize != bsize)
567         return -1;
568
569     diff = 0;
570     for (i=0; i<bsize; i++)
571     {
572         if (buf[i] != bits[i])
573             diff++;
574     }
575     ok(diff == 0, "%s: mfsize=%ld, bsize=%d, diff=%d\n",
576         desc, mfsize, bsize, diff);
577
578     return diff; 
579 }
580
581 /* For debugging or dumping the raw EMFs produced by
582  * new test functions.
583  */
584 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
585 {
586     BYTE buf[MF_BUFSIZE];
587     UINT mfsize, i;
588
589     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
590     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
591
592     printf("EMF %s has bits:\n{\n    ", desc);
593     for (i = 0; i < mfsize; i++)
594     {
595         printf ("0x%02x", buf[i]);
596         if (i == mfsize-1)
597             printf ("\n");
598         else if (i % 8 == 7)
599             printf (",\n    ");
600         else
601             printf (", ");
602     }
603     printf ("};\n");
604 }
605
606 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
607 {
608     BYTE *emf;
609     BYTE buf[MF_BUFSIZE];
610     UINT mfsize, offset;
611
612     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
613     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
614
615     printf("EMF %s has records:\n", desc);
616
617     emf = buf;
618     offset = 0;
619     while(offset < mfsize)
620     {
621         EMR *emr = (EMR *)(emf + offset);
622         trace("emr->iType %ld, emr->nSize %lu\n", emr->iType, emr->nSize);
623         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
624         offset += emr->nSize;
625     }
626 }
627
628 /* Compare the EMF produced by a test function with the
629  * expected raw EMF data in "bits".
630  * Return value is 0 for a perfect match,
631  * -1 if lengths aren't equal,
632  * otherwise returns the number of non-matching bytes.
633  */
634 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
635                             UINT bsize, const char *desc, BOOL todo)
636 {
637     unsigned char buf[MF_BUFSIZE];
638     UINT mfsize, i;
639     int diff;
640
641     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
642     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
643
644     if (mfsize < MF_BUFSIZE)
645         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
646     else
647         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
648            desc, mfsize, bsize);
649     if (mfsize != bsize)
650         return -1;
651
652     diff = 0;
653     for (i = 0; i < bsize; i++)
654     {
655        if (buf[i] != bits[i])
656            diff++;
657     }
658     if (diff != 0 && todo)
659     {
660         todo_wine
661         {
662             ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
663                desc, mfsize, bsize, diff);
664         }
665         return 0;
666     }
667     else
668     {
669         ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
670            desc, mfsize, bsize, diff);
671
672         return diff;
673     }
674 }
675
676 /* Test a blank metafile.  May be used as a template for new tests. */
677
678 static void test_mf_Blank(void)
679 {
680     HDC hdcMetafile;
681     HMETAFILE hMetafile;
682     INT caps;
683     BOOL ret;
684     INT type;
685
686     hdcMetafile = CreateMetaFileA(NULL);
687     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
688     trace("hdcMetafile %p\n", hdcMetafile);
689
690 /* Tests on metafile initialization */
691     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
692     ok (caps == DT_METAFILE,
693         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
694
695     hMetafile = CloseMetaFile(hdcMetafile);
696     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
697     type = GetObjectType(hMetafile);
698     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
699     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
700
701     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
702         "mf_blank") != 0)
703     {
704         dump_mf_bits(hMetafile, "mf_Blank");
705         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
706     }
707
708     ret = DeleteMetaFile(hMetafile);
709     ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
710 }
711
712 static void test_CopyMetaFile(void)
713 {
714     HDC hdcMetafile;
715     HMETAFILE hMetafile, hmf_copy;
716     BOOL ret;
717     char temp_path[MAX_PATH];
718     char mf_name[MAX_PATH];
719     INT type;
720
721     hdcMetafile = CreateMetaFileA(NULL);
722     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
723     trace("hdcMetafile %p\n", hdcMetafile);
724
725     hMetafile = CloseMetaFile(hdcMetafile);
726     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
727     type = GetObjectType(hMetafile);
728     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
729
730     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
731         "mf_blank") != 0)
732     {
733         dump_mf_bits(hMetafile, "mf_Blank");
734         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
735     }
736
737     GetTempPathA(MAX_PATH, temp_path);
738     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
739
740     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
741     ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError());
742
743     type = GetObjectType(hmf_copy);
744     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
745
746     ret = DeleteMetaFile(hMetafile);
747     ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
748
749     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
750     {
751         dump_mf_bits(hMetafile, "mf_Blank");
752         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
753     }
754
755     ret = DeleteMetaFile(hmf_copy);
756     ok( ret, "DeleteMetaFile(%p) error %ld\n", hmf_copy, GetLastError());
757
758     DeleteFileA(mf_name);
759 }
760
761 static void test_SetMetaFileBits(void)
762 {
763     HMETAFILE hmf;
764     INT type;
765     BOOL ret;
766     BYTE buf[256];
767     METAHEADER *mh;
768
769     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
770     ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
771     type = GetObjectType(hmf);
772     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
773
774     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
775     {
776         dump_mf_bits(hmf, "mf_Graphics");
777         EnumMetaFile(0, hmf, mf_enum_proc, 0);
778     }
779
780     ret = DeleteMetaFile(hmf);
781     ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
782
783     /* NULL data crashes XP SP1 */
784     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
785
786     /* Now with not zero size */
787     SetLastError(0xdeadbeef);
788     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
789     ok(!hmf, "SetMetaFileBitsEx should fail\n");
790     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
791
792     /* Now with not even size */
793     SetLastError(0xdeadbeef);
794     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
795     ok(!hmf, "SetMetaFileBitsEx should fail\n");
796     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError());
797
798     /* Now with zeroed out or faked some header fields */
799     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
800     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
801     mh = (METAHEADER *)buf;
802     /* corruption of any of the below fields leads to a failure */
803     mh->mtType = 0;
804     mh->mtVersion = 0;
805     mh->mtHeaderSize = 0;
806     SetLastError(0xdeadbeef);
807     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
808     ok(!hmf, "SetMetaFileBitsEx should fail\n");
809     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
810
811     /* Now with corrupted mtSize field */
812     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
813     mh = (METAHEADER *)buf;
814     /* corruption of mtSize doesn't lead to a failure */
815     mh->mtSize *= 2;
816     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
817     ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
818
819     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
820     {
821         dump_mf_bits(hmf, "mf_Graphics");
822         EnumMetaFile(0, hmf, mf_enum_proc, 0);
823     }
824
825     ret = DeleteMetaFile(hmf);
826     ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
827
828     /* Now with zeroed out mtSize field */
829     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
830     mh = (METAHEADER *)buf;
831     /* zeroing mtSize doesn't lead to a failure */
832     mh->mtSize = 0;
833     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
834     ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
835
836     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
837     {
838         dump_mf_bits(hmf, "mf_Graphics");
839         EnumMetaFile(0, hmf, mf_enum_proc, 0);
840     }
841
842     ret = DeleteMetaFile(hmf);
843     ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
844 }
845
846 /* Simple APIs from mfdrv/graphics.c
847  */
848
849 static void test_mf_Graphics(void)
850 {
851     HDC hdcMetafile;
852     HMETAFILE hMetafile;
853     POINT oldpoint;
854     BOOL ret;
855
856     hdcMetafile = CreateMetaFileA(NULL);
857     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
858     trace("hdcMetafile %p\n", hdcMetafile);
859
860     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
861     ok( ret, "MoveToEx error %ld.\n", GetLastError());
862     ret = LineTo(hdcMetafile, 2, 2);
863     ok( ret, "LineTo error %ld.\n", GetLastError());
864     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
865     ok( ret, "MoveToEx error %ld.\n", GetLastError());
866
867 /* oldpoint gets garbage under Win XP, so the following test would
868  * work under Wine but fails under Windows:
869  *
870  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
871  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
872  *       oldpoint.x, oldpoint.y);
873  */
874
875     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
876     ok( ret, "Ellipse error %ld.\n", GetLastError());
877
878     hMetafile = CloseMetaFile(hdcMetafile);
879     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
880     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
881
882     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
883         "mf_Graphics") != 0)
884     {
885         dump_mf_bits(hMetafile, "mf_Graphics");
886         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
887     }
888
889     ret = DeleteMetaFile(hMetafile);
890     ok( ret, "DeleteMetaFile(%p) error %ld\n",
891         hMetafile, GetLastError());
892 }
893
894 static void test_mf_PatternBrush(void)
895 {
896     HDC hdcMetafile;
897     HMETAFILE hMetafile;
898     LOGBRUSH *orig_lb;
899     HBRUSH hBrush;
900     BOOL ret;
901
902     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
903
904     orig_lb->lbStyle = BS_PATTERN;
905     orig_lb->lbColor = RGB(0, 0, 0);
906     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
907     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
908
909     hBrush = CreateBrushIndirect (orig_lb);
910     ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
911
912     hdcMetafile = CreateMetaFileA(NULL);
913     ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
914     trace("hdcMetafile %p\n", hdcMetafile);
915
916     hBrush = SelectObject(hdcMetafile, hBrush);
917     ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
918
919     hMetafile = CloseMetaFile(hdcMetafile);
920     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
921     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
922
923     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
924         "mf_Pattern_Brush") != 0)
925     {
926         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
927         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
928     }
929
930     ret = DeleteMetaFile(hMetafile);
931     ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
932     ret = DeleteObject(hBrush);
933     ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
934     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
935     ok( ret, "DeleteObject(HBITMAP) error %ld\n",
936         GetLastError());
937     HeapFree (GetProcessHeap(), 0, orig_lb);
938 }
939
940 static void test_mf_ExtTextOut_on_path(void)
941 {
942     HDC hdcMetafile;
943     HMETAFILE hMetafile;
944     BOOL ret;
945     static const INT dx[4] = { 3, 5, 8, 12 };
946
947     hdcMetafile = CreateMetaFileA(NULL);
948     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
949     trace("hdcMetafile %p\n", hdcMetafile);
950
951     ret = BeginPath(hdcMetafile);
952     ok(!ret, "BeginPath on metafile DC should fail\n");
953
954     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
955     ok(ret, "ExtTextOut error %ld\n", GetLastError());
956
957     ret = EndPath(hdcMetafile);
958     ok(!ret, "EndPath on metafile DC should fail\n");
959
960     hMetafile = CloseMetaFile(hdcMetafile);
961     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
962
963     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
964         "mf_TextOut_on_path") != 0)
965     {
966         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
967         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
968     }
969
970     ret = DeleteMetaFile(hMetafile);
971     ok(ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
972 }
973
974 static void test_emf_ExtTextOut_on_path(void)
975 {
976     HWND hwnd;
977     HDC hdcDisplay, hdcMetafile;
978     HENHMETAFILE hMetafile;
979     BOOL ret;
980     static const INT dx[4] = { 3, 5, 8, 12 };
981
982     /* Win9x doesn't play EMFs on invisible windows */
983     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
984                            0, 0, 200, 200, 0, 0, 0, NULL);
985     ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
986
987     hdcDisplay = GetDC(hwnd);
988     ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
989
990     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
991     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
992
993     ret = BeginPath(hdcMetafile);
994     ok(ret, "BeginPath error %ld\n", GetLastError());
995
996     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
997     ok(ret, "ExtTextOut error %ld\n", GetLastError());
998
999     ret = EndPath(hdcMetafile);
1000     ok(ret, "EndPath error %ld\n", GetLastError());
1001
1002     hMetafile = CloseEnhMetaFile(hdcMetafile);
1003     ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
1004
1005     /* this doesn't succeed yet: EMF has correct size, all EMF records
1006      * are there, but their contents don't match for different reasons.
1007      */
1008     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1009         "emf_TextOut_on_path", TRUE) != 0)
1010     {
1011         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1012         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1013     }
1014
1015     ret = DeleteEnhMetaFile(hMetafile);
1016     ok(ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
1017     ret = ReleaseDC(hwnd, hdcDisplay);
1018     ok(ret, "ReleaseDC error %ld\n", GetLastError());
1019     DestroyWindow(hwnd);
1020 }
1021
1022 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1023 {
1024     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1025     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1026     /* When using MM_TEXT Win9x does not update the mapping mode 
1027      * until a record is played which actually outputs something */
1028     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1029     LPtoDP(hdc, mapping, 2);
1030     trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1031     if (lpEMFR->iType == EMR_LINETO)
1032     {
1033         INT x0, y0, x1, y1;
1034         if (!lpMFP || lpMFP->mm == MM_TEXT)
1035         {
1036             x0 = 0;
1037             y0 = 0;
1038             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1039             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1040         }
1041         else
1042         {
1043             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%ld\n", lpMFP->mm);
1044             
1045             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1046             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1047             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1048             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1049         }
1050         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1051             "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
1052             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1053             x0, y0, x1, y1);
1054     }
1055     return TRUE;
1056 }
1057
1058 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1059 {
1060     HDC hdcMf;
1061     HMETAFILE hmf;
1062     BOOL ret;
1063     UINT size;
1064     LPBYTE pBits;
1065
1066     hdcMf = CreateMetaFile(NULL);
1067     ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
1068     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1069     ok(ret, "LineTo failed with error %ld\n", GetLastError());
1070     hmf = CloseMetaFile(hdcMf);
1071     ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());
1072     size = GetMetaFileBitsEx(hmf, 0, NULL);
1073     ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
1074     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1075     GetMetaFileBitsEx(hmf, size, pBits);
1076     DeleteMetaFile(hmf);
1077     return SetWinMetaFileBits(size, pBits, NULL, mfp);
1078 }
1079
1080 static void test_mf_conversions(void)
1081 {
1082     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1083     {
1084         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1085         HENHMETAFILE hemf;
1086         METAFILEPICT mfp;
1087         RECT rect = { 0, 0, 100, 100 };
1088         mfp.mm = MM_ANISOTROPIC;
1089         mfp.xExt = 100;
1090         mfp.yExt = 100;
1091         mfp.hMF = NULL;
1092         hemf = create_converted_emf(&mfp);
1093         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1094         DeleteEnhMetaFile(hemf);
1095         DeleteDC(hdcOffscreen);
1096     }
1097
1098     trace("Testing MF->EMF conversion (MM_TEXT)\n");
1099     {
1100         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1101         HENHMETAFILE hemf;
1102         METAFILEPICT mfp;
1103         RECT rect = { 0, 0, 100, 100 };
1104         mfp.mm = MM_TEXT;
1105         mfp.xExt = 0;
1106         mfp.yExt = 0;
1107         mfp.hMF = NULL;
1108         hemf = create_converted_emf(&mfp);
1109         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1110         DeleteEnhMetaFile(hemf);
1111         DeleteDC(hdcOffscreen);
1112     }
1113
1114     trace("Testing MF->EMF conversion (NULL mfp)\n");
1115     {
1116         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1117         HENHMETAFILE hemf;
1118         RECT rect = { 0, 0, 100, 100 };
1119         hemf = create_converted_emf(NULL);
1120         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1121         DeleteEnhMetaFile(hemf);
1122         DeleteDC(hdcOffscreen);
1123     }
1124 }
1125
1126 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
1127 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
1128 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
1129
1130 static void test_gdiis(void)
1131 {
1132     RECT rect = {0,0,100,100};
1133     HDC hdc, hemfDC, hmfDC;
1134     HENHMETAFILE hemf;
1135     HMODULE hgdi32;
1136
1137     /* resolve all the functions */
1138     hgdi32 = GetModuleHandle("gdi32");
1139     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
1140     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
1141     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
1142
1143     /* they should all exist or none should exist */
1144     if(!pGdiIsMetaPrintDC)
1145         return;
1146
1147     /* try with nothing */
1148     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
1149     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
1150     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
1151
1152     /* try with a metafile */
1153     hmfDC = CreateMetaFile(NULL);
1154     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
1155     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
1156     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
1157     DeleteObject(CloseMetaFile(hmfDC));
1158
1159     /* try with an enhanced metafile */
1160     hdc = GetDC(NULL);
1161     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
1162     ok(hemfDC != NULL, "failed to create emf\n");
1163
1164     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
1165     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
1166     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
1167
1168     hemf = CloseEnhMetaFile(hemfDC);
1169     ok(hemf != NULL, "failed to close EMF\n");
1170     DeleteObject(hemf);
1171     ReleaseDC(NULL,hdc);
1172 }
1173
1174 START_TEST(metafile)
1175 {
1176     init_function_pointers();
1177
1178     /* For enhanced metafiles (enhmfdrv) */
1179     test_ExtTextOut();
1180     test_SaveDC();
1181
1182     /* For win-format metafiles (mfdrv) */
1183     test_mf_Blank();
1184     test_mf_Graphics();
1185     test_mf_PatternBrush();
1186     test_CopyMetaFile();
1187     test_SetMetaFileBits();
1188     test_mf_ExtTextOut_on_path();
1189     test_emf_ExtTextOut_on_path();
1190
1191     /* For metafile conversions */
1192     test_mf_conversions();
1193
1194     test_gdiis();
1195 }