Fixes for -Wmissing-declaration and -Wwrite-string warnings.
[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 CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
39     const ENHMETARECORD *emr, int n_objs, LPARAM param)
40 {
41     static int n_record;
42     DWORD i;
43     const INT *dx;
44     INT *orig_dx = (INT *)param;
45     LOGFONTA device_lf;
46     INT ret;
47
48     trace("hdc %p, emr->iType %ld, emr->nSize %ld, param %p\n",
49            hdc, emr->iType, emr->nSize, (void *)param);
50
51     if(!hdc) return 1;
52
53     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
54
55     switch (emr->iType)
56     {
57     case EMR_HEADER:
58         n_record = 0;
59         break;
60
61     case EMR_EXTTEXTOUTA:
62     {
63         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
64         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
65
66         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
67         ok( ret == sizeof(device_lf), "GetObjectA error %ld\n", GetLastError());
68
69         /* compare up to lfOutPrecision, other values are not interesting,
70          * and in fact sometimes arbitrary adapted by Win9x.
71          */
72         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
73         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
74
75         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
76         {
77             ok(orig_dx[i] == dx[i], "pass %d: dx[%ld] (%d) didn't match %d\n",
78                                      n_record, i, dx[i], orig_dx[i]);
79         }
80         n_record++;
81         emr_processed = TRUE;
82         break;
83     }
84
85     case EMR_EXTTEXTOUTW:
86     {
87         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
88         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
89
90         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
91         ok( ret == sizeof(device_lf), "GetObjectA error %ld\n", GetLastError());
92
93         /* compare up to lfOutPrecision, other values are not interesting,
94          * and in fact sometimes arbitrary adapted by Win9x.
95          */
96         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
97         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
98
99         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
100         {
101             ok(orig_dx[i] == dx[i], "pass %d: dx[%ld] (%d) didn't match %d\n",
102                                      n_record, i, dx[i], orig_dx[i]);
103         }
104         n_record++;
105         emr_processed = TRUE;
106         break;
107     }
108
109     default:
110         break;
111     }
112
113     return 1;
114 }
115
116 static void test_ExtTextOut(void)
117 {
118     HWND hwnd;
119     HDC hdcDisplay, hdcMetafile;
120     HENHMETAFILE hMetafile;
121     HFONT hFont;
122     static const char text[] = "Simple text to test ExtTextOut on metafiles";
123     INT i, len, dx[256];
124     static const RECT rc = { 0, 0, 100, 100 };
125     BOOL ret;
126
127     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
128
129     /* Win9x doesn't play EMFs on invisible windows */
130     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
131                            0, 0, 200, 200, 0, 0, 0, NULL);
132     ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
133
134     hdcDisplay = GetDC(hwnd);
135     ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
136
137     trace("hdcDisplay %p\n", hdcDisplay);
138
139     SetMapMode(hdcDisplay, MM_TEXT);
140
141     memset(&orig_lf, 0, sizeof(orig_lf));
142
143     orig_lf.lfCharSet = ANSI_CHARSET;
144     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
145     orig_lf.lfWeight = FW_DONTCARE;
146     orig_lf.lfHeight = 7;
147     orig_lf.lfQuality = DEFAULT_QUALITY;
148     lstrcpyA(orig_lf.lfFaceName, "Arial");
149     hFont = CreateFontIndirectA(&orig_lf);
150     ok(hFont != 0, "CreateFontIndirectA error %ld\n", GetLastError());
151
152     hFont = SelectObject(hdcDisplay, hFont);
153
154     len = lstrlenA(text);
155     for (i = 0; i < len; i++)
156     {
157         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
158         ok( ret, "GetCharWidthA error %ld\n", GetLastError());
159     }
160     hFont = SelectObject(hdcDisplay, hFont);
161
162     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
163     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
164
165     trace("hdcMetafile %p\n", hdcMetafile);
166
167     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
168        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
169
170     hFont = SelectObject(hdcMetafile, hFont);
171
172     /* 1. pass NULL lpDx */
173     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
174     ok( ret, "ExtTextOutA error %ld\n", GetLastError());
175
176     /* 2. pass custom lpDx */
177     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
178     ok( ret, "ExtTextOutA error %ld\n", GetLastError());
179
180     hFont = SelectObject(hdcMetafile, hFont);
181     ret = DeleteObject(hFont);
182     ok( ret, "DeleteObject error %ld\n", GetLastError());
183
184     hMetafile = CloseEnhMetaFile(hdcMetafile);
185     ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
186
187     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
188
189     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
190     ok( ret, "PlayEnhMetaFile error %ld\n", GetLastError());
191
192     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, &rc);
193     ok( ret, "EnumEnhMetaFile error %ld\n", GetLastError());
194
195     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
196
197     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, NULL),
198        "A valid hdc has to require a valid rc\n");
199
200     ok(EnumEnhMetaFile(NULL, hMetafile, emf_enum_proc, dx, NULL),
201        "A null hdc does not require a valid rc\n");
202
203     ret = DeleteEnhMetaFile(hMetafile);
204     ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
205     ret = ReleaseDC(hwnd, hdcDisplay);
206     ok( ret, "ReleaseDC error %ld\n", GetLastError());
207 }
208
209 /* Win-format metafile (mfdrv) tests */
210 /* These tests compare the generated metafiles byte-by-byte */
211 /* with the nominal results. */
212
213 /* Maximum size of sample metafiles in bytes. */
214 #define MF_BUFSIZE 256
215
216 /* 8x8 bitmap data for a pattern brush */
217 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
218     0x01, 0x00, 0x02, 0x00,
219     0x03, 0x00, 0x04, 0x00,
220     0x05, 0x00, 0x06, 0x00,
221     0x07, 0x00, 0x08, 0x00
222 };
223
224 /* Sample metafiles to be compared to the outputs of the
225  * test functions.
226  */
227
228 static const unsigned char MF_BLANK_BITS[] = {
229     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
230     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
231     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
232 };
233
234 static const unsigned char MF_GRAPHICS_BITS[] = {
235     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
236     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
237     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
238     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
239     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
240     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
241     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
242     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
243     0x00, 0x00, 0x00, 0x00
244 };
245
246 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
247     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
248     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
249     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
250     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
251     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
252     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
253     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
257     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
258     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
259     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
260     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
261     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
262     0x00, 0x00
263 };
264
265 /* For debugging or dumping the raw metafiles produced by
266  * new test functions.
267  */
268
269 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
270 {
271     char buf[MF_BUFSIZE];
272     UINT mfsize, i;
273
274     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
275     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
276
277     printf ("MetaFile %s has bits:\n{\n    ", desc);
278     for (i=0; i<mfsize; i++)
279     {
280         printf ("0x%.2hhx", buf[i]);
281         if (i == mfsize-1)
282             printf ("\n");
283         else if (i % 8 == 7)
284             printf (",\n    ");
285         else
286             printf (", ");
287     }
288     printf ("};\n");
289 }
290
291 /* Compare the metafile produced by a test function with the
292  * expected raw metafile data in "bits".
293  * Return value is 0 for a perfect match,
294  * -1 if lengths aren't equal,
295  * otherwise returns the number of non-matching bytes.
296  */
297
298 static int compare_mf_bits (const HMETAFILE mf, const char *bits, UINT bsize,
299     const char *desc)
300 {
301     char buf[MF_BUFSIZE];
302     UINT mfsize, i;
303     int diff;
304
305     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
306     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
307     if (mfsize < MF_BUFSIZE)
308         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
309             desc, mfsize, bsize);
310     else
311         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
312             desc, mfsize, bsize);
313     if (mfsize != bsize)
314         return -1;
315
316     diff = 0;
317     for (i=0; i<bsize; i++)
318     {
319        if (buf[i] !=  bits[i])
320            diff++;
321     }
322     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
323         desc, mfsize, bsize, diff);
324
325     return diff; 
326 }
327
328 /* Test a blank metafile.  May be used as a template for new tests. */
329
330 static void test_mf_Blank(void)
331 {
332     HDC hdcMetafile;
333     HMETAFILE hMetafile;
334     INT caps;
335     BOOL ret;
336
337     hdcMetafile = CreateMetaFileA(NULL);
338     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
339     trace("hdcMetafile %p\n", hdcMetafile);
340
341 /* Tests on metafile initialization */
342     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
343     ok (caps == DT_METAFILE,
344         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
345
346     hMetafile = CloseMetaFile(hdcMetafile);
347     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
348     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
349
350     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
351         "mf_blank") != 0)
352             dump_mf_bits (hMetafile, "mf_Blank");
353
354     ret = DeleteMetaFile(hMetafile);
355     ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
356 }
357
358 /* Simple APIs from mfdrv/graphics.c
359  */
360
361 static void test_mf_Graphics()
362 {
363     HDC hdcMetafile;
364     HMETAFILE hMetafile;
365     POINT oldpoint;
366     BOOL ret;
367
368     hdcMetafile = CreateMetaFileA(NULL);
369     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
370     trace("hdcMetafile %p\n", hdcMetafile);
371
372     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
373     ok( ret, "MoveToEx error %ld.\n", GetLastError());
374     ret = LineTo(hdcMetafile, 2, 2);
375     ok( ret, "LineTo error %ld.\n", GetLastError());
376     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
377     ok( ret, "MoveToEx error %ld.\n", GetLastError());
378
379 /* oldpoint gets garbage under Win XP, so the following test would
380  * work under Wine but fails under Windows:
381  *
382  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
383  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
384  *       oldpoint.x, oldpoint.y);
385  */
386
387     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
388     ok( ret, "Ellipse error %ld.\n", GetLastError());
389
390     hMetafile = CloseMetaFile(hdcMetafile);
391     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
392     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
393
394     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
395         "mf_Graphics") != 0)
396             dump_mf_bits (hMetafile, "mf_Graphics");
397
398     ret = DeleteMetaFile(hMetafile);
399     ok( ret, "DeleteMetaFile(%p) error %ld\n",
400         hMetafile, GetLastError());
401 }
402
403 static void test_mf_PatternBrush(void)
404 {
405     HDC hdcMetafile;
406     HMETAFILE hMetafile;
407     LOGBRUSH *orig_lb;
408     HBRUSH hBrush;
409     BOOL ret;
410
411     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
412
413     orig_lb->lbStyle = BS_PATTERN;
414     orig_lb->lbColor = RGB(0, 0, 0);
415     orig_lb->lbHatch = (INT) CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
416     ok((HBITMAP *)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
417
418     hBrush = CreateBrushIndirect (orig_lb);
419     ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
420
421     hdcMetafile = CreateMetaFileA(NULL);
422     ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
423     trace("hdcMetafile %p\n", hdcMetafile);
424
425     hBrush = SelectObject(hdcMetafile, hBrush);
426     ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
427
428     hMetafile = CloseMetaFile(hdcMetafile);
429     ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
430     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
431
432     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
433         "mf_Pattern_Brush") != 0)
434             dump_mf_bits (hMetafile, "mf_Pattern_Brush");
435
436     ret = DeleteMetaFile(hMetafile);
437     ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
438     ret = DeleteObject(hBrush);
439     ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
440     ret = DeleteObject((HBITMAP *)orig_lb->lbHatch);
441     ok( ret, "DeleteObject(HBITMAP) error %ld\n",
442         GetLastError());
443     HeapFree (GetProcessHeap(), 0, orig_lb);
444 }
445
446 static INT CALLBACK EmfMmTextEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
447 {
448     POINT mapping[2] = { { 0, 0 }, { 1000, 1000 } };
449     LPtoDP(hdc, mapping, 2);
450     trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
451     if (lpEMFR->iType == EMR_LINETO)
452     {
453         FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale;
454         INT xframe = LINE_X * (float)GetDeviceCaps(hdc, HORZSIZE) * 100.0f / (float)GetDeviceCaps(hdc, HORZRES);
455         INT yframe = LINE_Y * (float)GetDeviceCaps(hdc, VERTSIZE) * 100.0f / (float)GetDeviceCaps(hdc, VERTRES);
456         INT x0 = 0;
457         INT y0 = 0;
458         INT x1;
459         INT y1;
460         xSrcPixSize = (FLOAT) GetDeviceCaps(hdc, HORZSIZE) / GetDeviceCaps(hdc, HORZRES);
461         ySrcPixSize = (FLOAT) GetDeviceCaps(hdc, VERTSIZE) / GetDeviceCaps(hdc, VERTRES);
462         xscale = (FLOAT) 1000 * 100.0 /
463                  xframe * xSrcPixSize;
464         yscale = (FLOAT) 1000 * 100.0 /
465                  yframe * ySrcPixSize;
466         x1 = (INT)floor(xscale * 100.0 + 0.5f);
467         y1 = (INT)floor(yscale * 100.0 + 0.5f);
468         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
469             "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
470             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
471             x0, y0, x1, y1);
472     }
473     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
474     return TRUE;
475 }
476
477 static INT CALLBACK EmfMmAnisotropicEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
478 {
479     POINT mapping[2] = { { 0, 0 }, { 1000, 1000 } };
480     LPtoDP(hdc, mapping, 2);
481     trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
482     if (lpEMFR->iType == EMR_LINETO)
483     {
484         INT x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
485         INT y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
486         INT x1 = MulDiv(1000, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
487         INT y1 = MulDiv(1000, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
488         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
489             "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
490             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
491             x0, y0, x1, y1);
492     }
493     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
494     return TRUE;
495 }
496
497 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
498 {
499     HDC hdcMf;
500     HMETAFILE hmf;
501     BOOL ret;
502     UINT size;
503     LPBYTE pBits;
504
505     hdcMf = CreateMetaFile(NULL);
506     ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
507     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
508     ok(ret, "LineTo failed with error %ld\n", GetLastError());
509     hmf = CloseMetaFile(hdcMf);
510     ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());
511     size = GetMetaFileBitsEx(hmf, 0, NULL);
512     ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
513     pBits = HeapAlloc(GetProcessHeap(), 0, size);
514     GetMetaFileBitsEx(hmf, size, pBits);
515     DeleteMetaFile(hmf);
516     return SetWinMetaFileBits(size, pBits, NULL, mfp);
517 }
518
519 static void test_mf_conversions()
520 {
521     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
522     {
523         HDC hdcOffscreen = CreateCompatibleDC(NULL);
524         HENHMETAFILE hemf;
525         METAFILEPICT mfp;
526         RECT rect = { 0, 0, 100, 100 };
527         mfp.mm = MM_ANISOTROPIC;
528         mfp.xExt = 100;
529         mfp.yExt = 100;
530         mfp.hMF = NULL;
531         hemf = create_converted_emf(&mfp);
532         EnumEnhMetaFile(hdcOffscreen, hemf, EmfMmAnisotropicEnumProc, NULL, &rect);
533         DeleteEnhMetaFile(hemf);
534         DeleteDC(hdcOffscreen);
535     }
536
537     trace("Testing MF->EMF conversion (MM_TEXT)\n");
538     {
539         HDC hdcOffscreen = CreateCompatibleDC(NULL);
540         HENHMETAFILE hemf;
541         METAFILEPICT mfp;
542         RECT rect = { 0, 0, 100, 100 };
543         mfp.mm = MM_TEXT;
544         mfp.xExt = 0;
545         mfp.yExt = 0;
546         mfp.hMF = NULL;
547         hemf = create_converted_emf(&mfp);
548         EnumEnhMetaFile(hdcOffscreen, hemf, EmfMmTextEnumProc, NULL, &rect);
549         DeleteEnhMetaFile(hemf);
550         DeleteDC(hdcOffscreen);
551     }
552
553     trace("Testing MF->EMF conversion (NULL mfp)\n");
554     {
555         HDC hdcOffscreen = CreateCompatibleDC(NULL);
556         HENHMETAFILE hemf;
557         RECT rect = { 0, 0, 100, 100 };
558         hemf = create_converted_emf(NULL);
559         EnumEnhMetaFile(hdcOffscreen, hemf, EmfMmTextEnumProc, NULL, &rect);
560         DeleteEnhMetaFile(hemf);
561         DeleteDC(hdcOffscreen);
562     }
563 }
564
565 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
566 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
567 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
568
569 static void test_gdiis(void)
570 {
571     RECT rect = {0,0,100,100};
572     HDC hdc, hemfDC, hmfDC;
573     HENHMETAFILE hemf;
574     HMODULE hgdi32;
575
576     /* resolve all the functions */
577     hgdi32 = GetModuleHandle("gdi32");
578     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
579     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
580     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
581
582     /* they should all exist or none should exist */
583     if(!pGdiIsMetaPrintDC)
584         return;
585
586     /* try with nothing */
587     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
588     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
589     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
590
591     /* try with a metafile */
592     hmfDC = CreateMetaFile(NULL);
593     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
594     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
595     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
596     DeleteObject(CloseMetaFile(hmfDC));
597
598     /* try with an enhanced metafile */
599     hdc = GetDC(NULL);
600     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
601     ok(hemfDC != NULL, "failed to create emf\n");
602
603     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
604     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
605     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
606
607     hemf = CloseEnhMetaFile(hemfDC);
608     ok(hemf != NULL, "failed to close EMF\n");
609     DeleteObject(hemf);
610     ReleaseDC(NULL,hdc);
611 }
612
613 START_TEST(metafile)
614 {
615     /* For enhanced metafiles (enhmfdrv) */
616     test_ExtTextOut();
617
618     /* For win-format metafiles (mfdrv) */
619     test_mf_Blank();
620     test_mf_Graphics();
621     test_mf_PatternBrush();
622
623     /* For metafile conversions */
624     test_mf_conversions();
625
626     test_gdiis();
627 }