usp10: Implement GPOS MarkToBase.
[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 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
41 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
42
43 #define GDI_GET_PROC(func)                                     \
44     p ## func = (void *)GetProcAddress(hGDI, #func);           \
45     if(!p ## func)                                             \
46         trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
47
48 static void init_function_pointers(void)
49 {
50     HMODULE hGDI;
51
52     pGetRelAbs = NULL;
53     pSetRelAbs = NULL;
54
55     hGDI = GetModuleHandleA("gdi32.dll");
56     assert(hGDI);
57     GDI_GET_PROC(GetRelAbs);
58     GDI_GET_PROC(SetRelAbs);
59     GDI_GET_PROC(SetDCBrushColor);
60     GDI_GET_PROC(SetDCPenColor);
61 }
62
63 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
64     const ENHMETARECORD *emr, int n_objs, LPARAM param)
65 {
66     static int n_record;
67     DWORD i;
68     const INT *dx;
69     INT *orig_dx = (INT *)param;
70     LOGFONTA device_lf;
71     INT ret;
72
73     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
74            hdc, emr->iType, emr->nSize, (void *)param);
75
76     if(!hdc) return 1;
77
78     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
79
80     switch (emr->iType)
81     {
82     case EMR_HEADER:
83         ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
84         ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
85         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
86         ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
87         ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
88         ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
89         ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
90
91         /* GetBkMode, GetRelAbs do not get reset to the default value */
92         ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
93         if(pSetRelAbs && pGetRelAbs)
94             ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
95
96         n_record = 0;
97         break;
98
99     case EMR_EXTTEXTOUTA:
100     {
101         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
102         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
103
104         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
105         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
106
107         /* compare up to lfOutPrecision, other values are not interesting,
108          * and in fact sometimes arbitrary adapted by Win9x.
109          */
110         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
111         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
112
113         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
114         {
115             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
116                                      n_record, i, dx[i], orig_dx[i]);
117         }
118         n_record++;
119         emr_processed = TRUE;
120         break;
121     }
122
123     case EMR_EXTTEXTOUTW:
124     {
125         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
126         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
127
128         SetLastError(0xdeadbeef);
129         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
130         ok( ret == sizeof(device_lf) ||
131             broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
132             "GetObjectA error %d\n", GetLastError());
133
134         /* compare up to lfOutPrecision, other values are not interesting,
135          * and in fact sometimes arbitrary adapted by Win9x.
136          */
137         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
138         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
139
140         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
141         {
142             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
143                                      n_record, i, dx[i], orig_dx[i]);
144         }
145         n_record++;
146         emr_processed = TRUE;
147         break;
148     }
149
150     default:
151         break;
152     }
153
154     return 1;
155 }
156
157 static void test_ExtTextOut(void)
158 {
159     HWND hwnd;
160     HDC hdcDisplay, hdcMetafile;
161     HENHMETAFILE hMetafile;
162     HFONT hFont;
163     static const char text[] = "Simple text to test ExtTextOut on metafiles";
164     INT i, len, dx[256];
165     static const RECT rc = { 0, 0, 100, 100 };
166     BOOL ret;
167
168     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
169
170     /* Win9x doesn't play EMFs on invisible windows */
171     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
172                            0, 0, 200, 200, 0, 0, 0, NULL);
173     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
174
175     hdcDisplay = GetDC(hwnd);
176     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
177
178     trace("hdcDisplay %p\n", hdcDisplay);
179
180     SetMapMode(hdcDisplay, MM_TEXT);
181
182     memset(&orig_lf, 0, sizeof(orig_lf));
183
184     orig_lf.lfCharSet = ANSI_CHARSET;
185     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
186     orig_lf.lfWeight = FW_DONTCARE;
187     orig_lf.lfHeight = 7;
188     orig_lf.lfQuality = DEFAULT_QUALITY;
189     lstrcpyA(orig_lf.lfFaceName, "Arial");
190     hFont = CreateFontIndirectA(&orig_lf);
191     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
192
193     hFont = SelectObject(hdcDisplay, hFont);
194
195     len = lstrlenA(text);
196     for (i = 0; i < len; i++)
197     {
198         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
199         ok( ret, "GetCharWidthA error %d\n", GetLastError());
200     }
201     hFont = SelectObject(hdcDisplay, hFont);
202
203     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
204     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
205
206     trace("hdcMetafile %p\n", hdcMetafile);
207
208     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
209        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
210
211     hFont = SelectObject(hdcMetafile, hFont);
212
213     /* 1. pass NULL lpDx */
214     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
215     ok( ret, "ExtTextOutA error %d\n", GetLastError());
216
217     /* 2. pass custom lpDx */
218     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
219     ok( ret, "ExtTextOutA error %d\n", GetLastError());
220
221     hFont = SelectObject(hdcMetafile, hFont);
222     ret = DeleteObject(hFont);
223     ok( ret, "DeleteObject error %d\n", GetLastError());
224
225     hMetafile = CloseEnhMetaFile(hdcMetafile);
226     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
227
228     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
229
230     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
231     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
232
233     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
234     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
235     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
236     SetROP2(hdcDisplay, R2_NOT);
237     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
238     SetPolyFillMode(hdcDisplay, WINDING);
239     SetStretchBltMode(hdcDisplay, HALFTONE);
240
241     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
242     SetBkMode(hdcDisplay, OPAQUE);
243
244     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
245     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
246
247     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
248         "text align %08x\n", GetTextAlign(hdcDisplay));
249     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
250     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
251     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
252     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
253     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
254     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
255
256     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
257
258     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
259        "A valid hdc has to require a valid rc\n");
260
261     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
262        "A null hdc does not require a valid rc\n");
263
264     ret = DeleteEnhMetaFile(hMetafile);
265     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
266     ret = ReleaseDC(hwnd, hdcDisplay);
267     ok( ret, "ReleaseDC error %d\n", GetLastError());
268     DestroyWindow(hwnd);
269 }
270
271 struct eto_scale_test_record
272 {
273     INT graphics_mode;
274     INT map_mode;
275     double ex_scale;
276     double ey_scale;
277     BOOL processed;
278 };
279
280 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
281     const ENHMETARECORD *emr, int n_objs, LPARAM param)
282 {
283     struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
284
285     if (emr->iType == EMR_EXTTEXTOUTW)
286     {
287         const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
288         trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
289               test->graphics_mode, test->map_mode,
290               pExtTextOutW->exScale, pExtTextOutW->eyScale,
291               test->ex_scale, test->ey_scale);
292         ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
293            "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
294         ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
295            "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
296         test->processed = TRUE;
297     }
298
299     return 1;
300 }
301
302 static void test_ExtTextOutScale(void)
303 {
304     const RECT rc = { 0, 0, 100, 100 };
305     const WCHAR str[] = {'a',0 };
306     struct eto_scale_test_record test;
307     HDC hdcDisplay, hdcMetafile;
308     HENHMETAFILE hMetafile;
309     HWND hwnd;
310     SIZE wndext, vportext;
311     int horzSize, vertSize, horzRes, vertRes;
312     int ret;
313     int i;
314
315     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
316                            0, 0, 200, 200, 0, 0, 0, NULL);
317     ok(hwnd != 0, "CreateWindowExA failed\n");
318
319     hdcDisplay = GetDC(hwnd);
320     ok(hdcDisplay != 0, "GetDC failed\n");
321
322     horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
323     horzRes  = GetDeviceCaps(hdcDisplay, HORZRES);
324     vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
325     vertRes  = GetDeviceCaps(hdcDisplay, VERTRES);
326     ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
327
328     for (i = 0; i < 16; i++)
329     {
330         test.graphics_mode = i / 8 + 1;
331         test.map_mode      = i % 8 + 1;
332
333         ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
334         ok(ret, "SetGraphicsMode failed\n");
335         ret = SetMapMode(hdcDisplay, test.map_mode);
336         ok(ret, "SetMapMode failed\n");
337
338         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
339         {
340             ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
341             ok(ret, "SetWindowExtEx failed\n");
342             ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
343             ok(ret, "SetViewportExtEx failed\n");
344         }
345
346         ret = GetViewportExtEx(hdcDisplay, &vportext);
347         ok(ret, "GetViewportExtEx failed\n");
348         ret = GetWindowExtEx(hdcDisplay, &wndext);
349         ok(ret, "GetWindowExtEx failed\n");
350
351         trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
352                test.graphics_mode, test.map_mode,
353                wndext.cx, wndext.cy, vportext.cx, vportext.cy,
354                horzSize, horzRes, vertSize, vertRes);
355
356         if (test.graphics_mode == GM_COMPATIBLE)
357         {
358             test.ex_scale = 100.0 * ((FLOAT)horzSize  / (FLOAT)horzRes) /
359                                     ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
360             test.ey_scale = 100.0 * ((FLOAT)vertSize  / (FLOAT)vertRes) /
361                                     ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
362         }
363         else
364         {
365             test.ex_scale = 0.0;
366             test.ey_scale = 0.0;
367         }
368
369         hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
370         ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
371
372         ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
373         ok(ret, "SetGraphicsMode failed\n");
374         ret = SetMapMode(hdcMetafile, test.map_mode);
375         ok(ret, "SetMapMode failed\n");
376
377         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
378         {
379             ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
380             ok(ret, "SetWindowExtEx failed\n");
381             ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
382             ok(ret, "SetViewportExtEx failed\n");
383         }
384
385         ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
386         ok(ret, "ExtTextOutW failed\n");
387
388         hMetafile = CloseEnhMetaFile(hdcMetafile);
389         ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
390
391         test.processed = 0;
392         ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
393         ok(ret, "EnumEnhMetaFile failed\n");
394         ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
395
396         ret = DeleteEnhMetaFile(hMetafile);
397         ok(ret, "DeleteEnhMetaFile failed\n");
398     }
399
400     ret = ReleaseDC(hwnd, hdcDisplay);
401     ok(ret, "ReleaseDC failed\n");
402     DestroyWindow(hwnd);
403 }
404
405
406 static void check_dc_state(HDC hdc, int restore_no,
407                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
408                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
409 {
410     BOOL ret;
411     XFORM xform;
412     POINT vp_org, win_org;
413     SIZE vp_size, win_size;
414     FLOAT xscale, yscale, edx, edy;
415
416     SetLastError(0xdeadbeef);
417     ret = GetWorldTransform(hdc, &xform);
418     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
419     ok(ret, "GetWorldTransform error %u\n", GetLastError());
420
421     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
422
423     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
424     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
425
426     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
427     trace("x scale %f\n", xscale);
428     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
429        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
430
431     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
432     trace("y scale %f\n", yscale);
433     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
434        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
435
436     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
437     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
438     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
439     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
440
441     return;
442
443 win9x_here:
444
445     GetWindowOrgEx(hdc, &win_org);
446     GetViewportOrgEx(hdc, &vp_org);
447     GetWindowExtEx(hdc, &win_size);
448     GetViewportExtEx(hdc, &vp_size);
449
450     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
451     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
452
453     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
454     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
455
456     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
457     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
458
459     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
460     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
461 }
462
463 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
464                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
465 {
466     BOOL ret;
467     XFORM xform;
468     POINT pt;
469     SIZE size;
470     static int save_state;
471     static int restore_no;
472     static int select_no;
473
474     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
475            hdc, emr->iType, emr->nSize, (void *)param);
476
477     trace("BEFORE:\n");
478     SetLastError(0xdeadbeef);
479     ret = GetWorldTransform(hdc, &xform);
480     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
481     {
482         ret = GetWindowOrgEx(hdc, &pt);
483         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
484         trace("window org (%d,%d)\n", pt.x, pt.y);
485         ret = GetViewportOrgEx(hdc, &pt);
486         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
487         trace("vport org (%d,%d)\n", pt.x, pt.y);
488         ret = GetWindowExtEx(hdc, &size);
489         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
490         trace("window ext (%d,%d)\n", size.cx, size.cy);
491         ret = GetViewportExtEx(hdc, &size);
492         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
493         trace("vport ext (%d,%d)\n", size.cx, size.cy);
494     }
495     else
496     {
497         ok(ret, "GetWorldTransform error %u\n", GetLastError());
498         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
499     }
500
501     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
502
503     switch (emr->iType)
504     {
505     case EMR_HEADER:
506     {
507         static RECT exp_bounds = { 0, 0, 150, 150 };
508         RECT bounds;
509         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
510
511         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
512                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
513                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
514         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
515                emf->szlDevice.cx, emf->szlDevice.cy);
516
517         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
518         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
519
520         save_state = 0;
521         restore_no = 0;
522         select_no = 0;
523         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
524         break;
525     }
526
527     case EMR_LINETO:
528         {
529             const EMRLINETO *line = (const EMRLINETO *)emr;
530             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
531             break;
532         }
533     case EMR_SETWINDOWORGEX:
534         {
535             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
536             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
537             break;
538         }
539     case EMR_SETWINDOWEXTEX:
540         {
541             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
542             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
543             break;
544         }
545     case EMR_SETVIEWPORTORGEX:
546         {
547             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
548             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
549             break;
550         }
551     case EMR_SETVIEWPORTEXTEX:
552         {
553             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
554             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
555             break;
556         }
557     case EMR_SAVEDC:
558         save_state++;
559         trace("EMR_SAVEDC\n");
560         break;
561
562     case EMR_RESTOREDC:
563         {
564             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
565             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
566
567             switch(++restore_no)
568             {
569             case 1:
570                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
571                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
572                 break;
573             case 2:
574                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
575                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
576                 break;
577             case 3:
578                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
579                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
580                 break;
581             }
582             ok(restore_no <= 3, "restore_no %d\n", restore_no);
583             save_state += restoredc->iRelative;
584             break;
585         }
586     case EMR_SELECTOBJECT:
587         {
588             const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
589             trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
590             select_no ++;
591             break;
592         }
593     case EMR_EOF:
594         ok(save_state == 0, "EOF save_state %d\n", save_state);
595         ok(select_no == 3, "Too many/few selects  %i\n",select_no);
596         break;
597     }
598
599     trace("AFTER:\n");
600     SetLastError(0xdeadbeef);
601     ret = GetWorldTransform(hdc, &xform);
602     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
603     {
604         ret = GetWindowOrgEx(hdc, &pt);
605         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
606         trace("window org (%d,%d)\n", pt.x, pt.y);
607         ret = GetViewportOrgEx(hdc, &pt);
608         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
609         trace("vport org (%d,%d)\n", pt.x, pt.y);
610         ret = GetWindowExtEx(hdc, &size);
611         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
612         trace("window ext (%d,%d)\n", size.cx, size.cy);
613         ret = GetViewportExtEx(hdc, &size);
614         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
615         trace("vport ext (%d,%d)\n", size.cx, size.cy);
616     }
617     else
618     {
619         ok(ret, "GetWorldTransform error %u\n", GetLastError());
620         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
621     }
622
623     return 1;
624 }
625
626 static void test_SaveDC(void)
627 {
628     HDC hdcMetafile, hdcDisplay;
629     HENHMETAFILE hMetafile;
630     HWND hwnd;
631     int ret;
632     POINT pt;
633     SIZE size;
634     HFONT hFont,hFont2,hFontOld,hFontCheck;
635     static const RECT rc = { 0, 0, 150, 150 };
636
637     /* Win9x doesn't play EMFs on invisible windows */
638     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
639                            0, 0, 200, 200, 0, 0, 0, NULL);
640     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
641
642     hdcDisplay = GetDC(hwnd);
643     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
644
645     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
646     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
647
648     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
649
650     /* Need to write something to the emf, otherwise Windows won't play it back */
651     LineTo(hdcMetafile, 150, 150);
652
653     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
654     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
655     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
656     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
657
658     /* Force Win9x to update DC state */
659     SetPixelV(hdcMetafile, 50, 50, 0);
660
661     ret = GetViewportOrgEx(hdcMetafile, &pt);
662     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
663     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
664     ret = GetViewportExtEx(hdcMetafile, &size);
665     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
666     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
667     ret = SaveDC(hdcMetafile);
668     ok(ret == 1, "ret = %d\n", ret);
669
670     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
671     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
672     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
673     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
674
675     /* Force Win9x to update DC state */
676     SetPixelV(hdcMetafile, 50, 50, 0);
677
678     ret = GetViewportOrgEx(hdcMetafile, &pt);
679     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
680     ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
681     ret = GetViewportExtEx(hdcMetafile, &size);
682     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
683     ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
684     ret = SaveDC(hdcMetafile);
685     ok(ret == 2, "ret = %d\n", ret);
686
687     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
688     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
689     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
690     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
691     SetPolyFillMode( hdcMetafile, ALTERNATE );
692     SetBkColor( hdcMetafile, 0 );
693
694     /* Force Win9x to update DC state */
695     SetPixelV(hdcMetafile, 50, 50, 0);
696
697     ret = GetViewportOrgEx(hdcMetafile, &pt);
698     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
699     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
700     ret = GetViewportExtEx(hdcMetafile, &size);
701     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
702     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
703     ret = SaveDC(hdcMetafile);
704     ok(ret == 3, "ret = %d\n", ret);
705
706     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
707     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
708     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
709     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
710
711     SetPolyFillMode( hdcMetafile, WINDING );
712     SetBkColor( hdcMetafile, 0x123456 );
713     ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
714     ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
715
716     /* Force Win9x to update DC state */
717     SetPixelV(hdcMetafile, 50, 50, 0);
718
719     ret = GetViewportOrgEx(hdcMetafile, &pt);
720     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
721     ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
722     ret = GetViewportExtEx(hdcMetafile, &size);
723     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
724     ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
725     ret = RestoreDC(hdcMetafile, -1);
726     ok(ret, "ret = %d\n", ret);
727
728     ret = GetViewportOrgEx(hdcMetafile, &pt);
729     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
730     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
731     ret = GetViewportExtEx(hdcMetafile, &size);
732     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
733     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
734     ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
735     ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
736     ret = SaveDC(hdcMetafile);
737     ok(ret == 3, "ret = %d\n", ret);
738
739     ret = GetViewportOrgEx(hdcMetafile, &pt);
740     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
741     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
742     ret = GetViewportExtEx(hdcMetafile, &size);
743     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
744     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
745     ret = RestoreDC(hdcMetafile, 1);
746     ok(ret, "ret = %d\n", ret);
747     ret = GetViewportOrgEx(hdcMetafile, &pt);
748     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
749     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
750     ret = GetViewportExtEx(hdcMetafile, &size);
751     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
752     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
753
754     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
755     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
756     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
757     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
758
759     /* Force Win9x to update DC state */
760     SetPixelV(hdcMetafile, 50, 50, 0);
761
762     ret = GetViewportOrgEx(hdcMetafile, &pt);
763     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
764     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
765     ret = GetViewportExtEx(hdcMetafile, &size);
766     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
767     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
768     ret = SaveDC(hdcMetafile);
769     ok(ret == 1, "ret = %d\n", ret);
770
771     ret = GetViewportOrgEx(hdcMetafile, &pt);
772     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
773     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
774     ret = GetViewportExtEx(hdcMetafile, &size);
775     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
776     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
777     ret = SaveDC(hdcMetafile);
778     ok(ret == 2, "ret = %d\n", ret);
779
780     memset(&orig_lf, 0, sizeof(orig_lf));
781     orig_lf.lfCharSet = ANSI_CHARSET;
782     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
783     orig_lf.lfWeight = FW_DONTCARE;
784     orig_lf.lfHeight = 7;
785     orig_lf.lfQuality = DEFAULT_QUALITY;
786     lstrcpyA(orig_lf.lfFaceName, "Arial");
787     hFont = CreateFontIndirectA(&orig_lf);
788     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
789
790     hFontOld = SelectObject(hdcMetafile, hFont);
791
792     hFont2 = CreateFontIndirectA(&orig_lf);
793     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
794     hFontCheck = SelectObject(hdcMetafile, hFont2);
795     ok(hFontCheck == hFont, "Font not selected\n");
796
797     /* Force Win9x to update DC state */
798     SetPixelV(hdcMetafile, 50, 50, 0);
799
800     ret = RestoreDC(hdcMetafile, 1);
801     ok(ret, "ret = %d\n", ret);
802     ret = GetViewportOrgEx(hdcMetafile, &pt);
803     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
804     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
805     ret = GetViewportExtEx(hdcMetafile, &size);
806     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
807     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
808
809     hFontCheck = SelectObject(hdcMetafile, hFontOld);
810     ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
811        "Font not reverted with DC Restore\n");
812
813     ret = RestoreDC(hdcMetafile, -20);
814     ok(!ret, "ret = %d\n", ret);
815     ret = RestoreDC(hdcMetafile, 20);
816     ok(!ret, "ret = %d\n", ret);
817
818     hMetafile = CloseEnhMetaFile(hdcMetafile);
819     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
820
821     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
822     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
823
824     ret = DeleteObject(hFont);
825     ok( ret, "DeleteObject error %d\n", GetLastError());
826     ret = DeleteObject(hFont2);
827     ok( ret, "DeleteObject error %d\n", GetLastError());
828     ret = DeleteEnhMetaFile(hMetafile);
829     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
830     ret = ReleaseDC(hwnd, hdcDisplay);
831     ok( ret, "ReleaseDC error %d\n", GetLastError());
832     DestroyWindow(hwnd);
833 }
834
835 static void test_mf_SaveDC(void)
836 {
837     HDC hdcMetafile;
838     HMETAFILE hMetafile;
839     int ret;
840     POINT pt;
841     SIZE size;
842     HFONT hFont,hFont2,hFontOld,hFontCheck;
843
844     hdcMetafile = CreateMetaFileA(NULL);
845     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
846
847     ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
848     ok (ret, "SetMapMode should not fail\n");
849
850     /* Need to write something to the emf, otherwise Windows won't play it back */
851     LineTo(hdcMetafile, 150, 150);
852
853     pt.x = pt.y = 5555;
854     SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
855     ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
856     pt.x = pt.y = 5555;
857     SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
858     ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
859     size.cx = size.cy = 5555;
860     SetWindowExtEx(hdcMetafile, 110, 110, &size );
861     ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
862     size.cx = size.cy = 5555;
863     SetViewportExtEx(hdcMetafile, 120, 120, &size );
864     ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
865
866     /* Force Win9x to update DC state */
867     SetPixelV(hdcMetafile, 50, 50, 0);
868
869     ret = GetViewportOrgEx(hdcMetafile, &pt);
870     todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
871     ret = GetViewportExtEx(hdcMetafile, &size);
872     todo_wine ok (!ret, "GetViewportExtEx should fail\n");
873     ret = SaveDC(hdcMetafile);
874     ok(ret == 1, "ret = %d\n", ret);
875
876     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
877     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
878     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
879     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
880
881     /* Force Win9x to update DC state */
882     SetPixelV(hdcMetafile, 50, 50, 0);
883
884     ret = SaveDC(hdcMetafile);
885     ok(ret == 1, "ret = %d\n", ret);
886
887     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
888     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
889     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
890     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
891
892     /* Force Win9x to update DC state */
893     SetPixelV(hdcMetafile, 50, 50, 0);
894     SetPolyFillMode( hdcMetafile, ALTERNATE );
895     SetBkColor( hdcMetafile, 0 );
896
897     ret = SaveDC(hdcMetafile);
898     ok(ret == 1, "ret = %d\n", ret);
899
900     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
901     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
902     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
903     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
904
905     SetPolyFillMode( hdcMetafile, WINDING );
906     SetBkColor( hdcMetafile, 0x123456 );
907     todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
908     todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
909
910     /* Force Win9x to update DC state */
911     SetPixelV(hdcMetafile, 50, 50, 0);
912
913     ret = RestoreDC(hdcMetafile, -1);
914     ok(ret, "ret = %d\n", ret);
915
916     ret = SaveDC(hdcMetafile);
917     ok(ret == 1, "ret = %d\n", ret);
918
919     ret = RestoreDC(hdcMetafile, 1);
920     ok(ret, "ret = %d\n", ret);
921
922     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
923     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
924     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
925     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
926
927     /* Force Win9x to update DC state */
928     SetPixelV(hdcMetafile, 50, 50, 0);
929
930     ret = SaveDC(hdcMetafile);
931     ok(ret == 1, "ret = %d\n", ret);
932
933     ret = SaveDC(hdcMetafile);
934     ok(ret == 1, "ret = %d\n", ret);
935
936     memset(&orig_lf, 0, sizeof(orig_lf));
937     orig_lf.lfCharSet = ANSI_CHARSET;
938     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
939     orig_lf.lfWeight = FW_DONTCARE;
940     orig_lf.lfHeight = 7;
941     orig_lf.lfQuality = DEFAULT_QUALITY;
942     lstrcpyA(orig_lf.lfFaceName, "Arial");
943     hFont = CreateFontIndirectA(&orig_lf);
944     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
945
946     hFontOld = SelectObject(hdcMetafile, hFont);
947
948     hFont2 = CreateFontIndirectA(&orig_lf);
949     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
950     hFontCheck = SelectObject(hdcMetafile, hFont2);
951     ok(hFontCheck == hFont, "Font not selected\n");
952
953     /* Force Win9x to update DC state */
954     SetPixelV(hdcMetafile, 50, 50, 0);
955
956     ret = RestoreDC(hdcMetafile, 1);
957     ok(ret, "ret = %d\n", ret);
958
959     hFontCheck = SelectObject(hdcMetafile, hFontOld);
960     ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
961
962     /* restore level is ignored */
963     ret = RestoreDC(hdcMetafile, -20);
964     ok(ret, "ret = %d\n", ret);
965     ret = RestoreDC(hdcMetafile, 20);
966     ok(ret, "ret = %d\n", ret);
967     ret = RestoreDC(hdcMetafile, 0);
968     ok(ret, "ret = %d\n", ret);
969
970     hMetafile = CloseMetaFile(hdcMetafile);
971     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
972
973     ret = DeleteMetaFile(hMetafile);
974     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
975     ret = DeleteObject(hFont);
976     ok( ret, "DeleteObject error %d\n", GetLastError());
977     ret = DeleteObject(hFont2);
978     ok( ret, "DeleteObject error %d\n", GetLastError());
979 }
980
981
982 /* Win-format metafile (mfdrv) tests */
983 /* These tests compare the generated metafiles byte-by-byte */
984 /* with the nominal results. */
985
986 /* Maximum size of sample metafiles in bytes. */
987 #define MF_BUFSIZE 512
988
989 /* 8x8 bitmap data for a pattern brush */
990 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
991     0x01, 0x00, 0x02, 0x00,
992     0x03, 0x00, 0x04, 0x00,
993     0x05, 0x00, 0x06, 0x00,
994     0x07, 0x00, 0x08, 0x00
995 };
996
997 /* Sample metafiles to be compared to the outputs of the
998  * test functions.
999  */
1000
1001 static const unsigned char MF_BLANK_BITS[] = {
1002     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1003     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1004     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1005 };
1006
1007 static const unsigned char MF_GRAPHICS_BITS[] = {
1008     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1009     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1010     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1011     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1012     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1013     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1014     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1015     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1016     0x00, 0x00, 0x00, 0x00
1017 };
1018
1019 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1020     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1021     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1022     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1023     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1024     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1025     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1026     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1027     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1029     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1030     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1031     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1032     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1033     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1034     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1035     0x00, 0x00
1036 };
1037
1038 static const unsigned char MF_DCBRUSH_BITS[] =
1039 {
1040     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1041     0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1042     0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1043     0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1044     0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1045     0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1046     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047     0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1048     0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1049     0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1050     0x00, 0x00, 0x00, 0x00
1051 };
1052
1053 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1054 {
1055     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1056     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1057     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1058     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1059     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1060     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1061     0x00, 0x00
1062 };
1063
1064 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1065 {
1066     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1067     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1071     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1072     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1073     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1074     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1076     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1077     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1078     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1079     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1080     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1081     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1083     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1084     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1085     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1086     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1087     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1089     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1090     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1091     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1092     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1093     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1094     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1095     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1096     0x14, 0x00, 0x00, 0x00
1097 };
1098
1099 static const unsigned char MF_LINETO_BITS[] = {
1100     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1101     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1102     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1103     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1104     0x00, 0x00
1105 };
1106
1107 static const unsigned char EMF_LINETO_BITS[] = {
1108     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1109     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1111     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1113     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1114     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1115     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1116     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1118     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1119     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1121     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1122     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1123     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1124     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1125     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1126     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1130     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1131     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1132     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1133     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1134     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1135     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1136     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1137     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1138     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1139     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1140     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1141     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1142     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1143     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1145     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1147 };
1148
1149 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1150     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1151     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1153     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1154     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1155     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1156     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1157     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1161     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1163     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1164     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1165     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1166     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1167     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1168     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1169     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1170     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1171     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1172     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1173     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1174     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1175     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1176     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1177     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1178     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1179     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1180     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1181     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1182     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1183     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1184     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1185     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1187     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1189 };
1190
1191 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1192     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1193     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1194     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1195     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1196     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1197     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1198     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1199     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1202     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1203     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1205     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1206     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1207     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1208     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1209     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1210     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1211     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1212     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1213     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1214     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1215     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1216     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1217     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1218     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1219     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1220     0x14, 0x00, 0x00, 0x00
1221 };
1222
1223 static const unsigned char EMF_BITBLT[] =
1224 {
1225     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1226     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1228     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229     0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1230     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1231     0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1232     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234     0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1235     0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1236     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237     0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1238     0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1239     0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1241     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1243     0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1244     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1246     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1247     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1249     0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1250     0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1251     0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1252     0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1253     0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1254     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1257     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262     0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1263     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1265     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266     0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1267     0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1268     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1269     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1271     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274     0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1275     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1277 };
1278
1279 static const unsigned char EMF_DCBRUSH_BITS[] =
1280 {
1281     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1282     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1283     0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1284     0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1285     0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1286     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1287     0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1288     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290     0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1291     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1292     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1294     0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1295     0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1296     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1297     0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1298     0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1299     0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1300     0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1301     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1302     0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1303     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305     0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1306     0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1307     0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1308     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1309     0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1310     0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1311     0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1312     0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1313     0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1314     0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1315     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1316     0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1317     0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1318     0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1319     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1320     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1321     0x14, 0x00, 0x00, 0x00
1322 };
1323
1324 static const unsigned char EMF_BEZIER_BITS[] =
1325 {
1326     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1327     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1328     0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1329     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330     0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1331     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1332     0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1333     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1334     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1336     0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1337     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1338     0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1339     0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1340     0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1341     0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1342     0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1343     0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1344     0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1345     0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1346     0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1347     0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1348     0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1349     0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1350     0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1351     0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1352     0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1353     0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1354     0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1355     0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1356     0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1357     0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1358     0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1359     0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1360     0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1361     0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1362     0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1363     0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1364     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1365     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1366     0x14, 0x00, 0x00, 0x00
1367 };
1368
1369 /* For debugging or dumping the raw metafiles produced by
1370  * new test functions.
1371  */
1372 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1373                                  INT nobj, LPARAM param)
1374 {
1375     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1376            hdc, mr->rdFunction, mr->rdSize, (void *)param);
1377     return TRUE;
1378 }
1379
1380 /* For debugging or dumping the raw metafiles produced by
1381  * new test functions.
1382  */
1383
1384 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1385 {
1386     BYTE buf[MF_BUFSIZE];
1387     UINT mfsize, i;
1388
1389     if (!winetest_debug) return;
1390
1391     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1392     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1393
1394     printf ("MetaFile %s has bits:\n{\n    ", desc);
1395     for (i=0; i<mfsize; i++)
1396     {
1397         printf ("0x%02x", buf[i]);
1398         if (i == mfsize-1)
1399             printf ("\n");
1400         else if (i % 8 == 7)
1401             printf (",\n    ");
1402         else
1403             printf (", ");
1404     }
1405     printf ("};\n");
1406 }
1407
1408 /* Compare the metafile produced by a test function with the
1409  * expected raw metafile data in "bits".
1410  * Return value is 0 for a perfect match,
1411  * -1 if lengths aren't equal,
1412  * otherwise returns the number of non-matching bytes.
1413  */
1414
1415 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1416     const char *desc)
1417 {
1418     unsigned char buf[MF_BUFSIZE];
1419     UINT mfsize, i;
1420     int diff;
1421
1422     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1423     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1424     if (mfsize < MF_BUFSIZE)
1425         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1426             desc, mfsize, bsize);
1427     else
1428         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1429             desc, mfsize, bsize);
1430     if (mfsize != bsize)
1431         return -1;
1432
1433     diff = 0;
1434     for (i=0; i<bsize; i++)
1435     {
1436        if (buf[i] !=  bits[i])
1437            diff++;
1438     }
1439     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1440         desc, mfsize, bsize, diff);
1441
1442     return diff; 
1443 }
1444
1445 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1446 {
1447     unsigned char buf[MF_BUFSIZE];
1448     DWORD mfsize, rd_size, i;
1449     int diff;
1450     HANDLE hfile;
1451     BOOL ret;
1452
1453     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1454     assert(hfile != INVALID_HANDLE_VALUE);
1455
1456     mfsize = GetFileSize(hfile, NULL);
1457     assert(mfsize <= MF_BUFSIZE);
1458
1459     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1460     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1461
1462     CloseHandle(hfile);
1463
1464     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1465
1466     if (mfsize != bsize)
1467         return -1;
1468
1469     diff = 0;
1470     for (i=0; i<bsize; i++)
1471     {
1472         if (buf[i] != bits[i])
1473             diff++;
1474     }
1475     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1476         desc, mfsize, bsize, diff);
1477
1478     return diff; 
1479 }
1480
1481 /* For debugging or dumping the raw EMFs produced by
1482  * new test functions.
1483  */
1484 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1485 {
1486     BYTE buf[MF_BUFSIZE];
1487     UINT mfsize, i;
1488
1489     if (!winetest_debug) return;
1490
1491     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1492     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1493
1494     printf("EMF %s has bits:\n{\n    ", desc);
1495     for (i = 0; i < mfsize; i++)
1496     {
1497         printf ("0x%02x", buf[i]);
1498         if (i == mfsize-1)
1499             printf ("\n");
1500         else if (i % 8 == 7)
1501             printf (",\n    ");
1502         else
1503             printf (", ");
1504     }
1505     printf ("};\n");
1506 }
1507
1508 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1509 {
1510     BYTE *emf;
1511     BYTE buf[MF_BUFSIZE];
1512     UINT mfsize, offset;
1513
1514     if (!winetest_debug) return;
1515
1516     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1517     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1518
1519     printf("EMF %s has records:\n", desc);
1520
1521     emf = buf;
1522     offset = 0;
1523     while(offset < mfsize)
1524     {
1525         EMR *emr = (EMR *)(emf + offset);
1526         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1527         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1528         offset += emr->nSize;
1529     }
1530 }
1531
1532 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1533 {
1534     const BYTE *buf;
1535     DWORD i;
1536
1537     if (!winetest_debug) return;
1538
1539     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1540     buf = (const BYTE *)emr;
1541     for (i = 0; i < emr->nSize; i++)
1542     {
1543         printf ("0x%02x", buf[i]);
1544         if (i == emr->nSize - 1)
1545             printf ("\n");
1546         else if (i % 8 == 7)
1547             printf (",\n");
1548         else
1549             printf (", ");
1550     }
1551     printf ("};\n");
1552 }
1553
1554 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1555 {
1556     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1557           eto->rclBounds.right, eto->rclBounds.bottom);
1558     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1559     trace("exScale: %f\n", eto->exScale);
1560     trace("eyScale: %f\n", eto->eyScale);
1561     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1562     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1563     trace("emrtext.offString %#x\n", eto->emrtext.offString);
1564     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1565     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1566           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1567     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1568 }
1569
1570 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1571                              const char *desc, BOOL ignore_scaling)
1572 {
1573     int diff;
1574
1575     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1576        desc, emr1->iType, emr2->iType);
1577
1578     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1579        desc, emr1->nSize, emr2->nSize);
1580
1581     /* iType and nSize mismatches are fatal */
1582     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1583
1584     /* contents of EMR_GDICOMMENT are not interesting */
1585     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1586
1587     /* different Windows versions setup DC scaling differently when
1588      * converting an old style metafile to an EMF.
1589      */
1590     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1591                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1592         return TRUE;
1593
1594     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1595     {
1596         EMREXTTEXTOUTW *eto1, *eto2;
1597
1598         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1599         memcpy(eto1, emr1, emr1->nSize);
1600         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1601         memcpy(eto2, emr2, emr2->nSize);
1602
1603         /* different Windows versions setup DC scaling differently */
1604         eto1->exScale = eto1->eyScale = 0.0;
1605         eto2->exScale = eto2->eyScale = 0.0;
1606
1607         diff = memcmp(eto1, eto2, emr1->nSize);
1608         if (diff)
1609         {
1610             dump_EMREXTTEXTOUT(eto1);
1611             dump_EMREXTTEXTOUT(eto2);
1612         }
1613         HeapFree(GetProcessHeap(), 0, eto1);
1614         HeapFree(GetProcessHeap(), 0, eto2);
1615     }
1616     else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1617     {
1618         /* We have to take care of NT4 differences here */
1619         diff = memcmp(emr1, emr2, emr1->nSize);
1620         if (diff)
1621         {
1622             ENHMETARECORD *emr_nt4;
1623
1624             emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1625             memcpy(emr_nt4, emr2, emr2->nSize);
1626             /* Correct the nRgnSize field */
1627             emr_nt4->dParm[5] = sizeof(RECT);
1628
1629             diff = memcmp(emr1, emr_nt4, emr1->nSize);
1630             if (!diff)
1631                 win_skip("Catered for NT4 differences\n");
1632
1633             HeapFree(GetProcessHeap(), 0, emr_nt4);
1634         }
1635     }
1636     else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1637     {
1638         EMRPOLYBEZIER16 *eto1, *eto2;
1639
1640         eto1 = (EMRPOLYBEZIER16*)emr1;
1641         eto2 = (EMRPOLYBEZIER16*)emr2;
1642
1643         diff = eto1->cpts != eto2->cpts;
1644         if(!diff)
1645             diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1646     }
1647     else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1648     {
1649         EMRPOLYBEZIER *eto1, *eto2;
1650
1651         eto1 = (EMRPOLYBEZIER*)emr1;
1652         eto2 = (EMRPOLYBEZIER*)emr2;
1653
1654         diff = eto1->cptl != eto2->cptl;
1655         if(!diff)
1656             diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1657     }
1658     else
1659         diff = memcmp(emr1, emr2, emr1->nSize);
1660
1661     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1662
1663     if (diff)
1664     {
1665         dump_emf_record(emr1, "expected bits");
1666         dump_emf_record(emr2, "actual bits");
1667     }
1668
1669     return diff == 0; /* report all non-fatal record mismatches */
1670 }
1671
1672 /* Compare the EMF produced by a test function with the
1673  * expected raw EMF data in "bits".
1674  * Return value is 0 for a perfect match,
1675  * -1 if lengths aren't equal,
1676  * otherwise returns the number of non-matching bytes.
1677  */
1678 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1679                             UINT bsize, const char *desc,
1680                             BOOL ignore_scaling)
1681 {
1682     unsigned char buf[MF_BUFSIZE];
1683     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1684     const ENHMETAHEADER *emh1, *emh2;
1685
1686     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1687     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1688
1689     /* ENHMETAHEADER size could differ, depending on platform */
1690     diff_nt4 = sizeof(SIZEL);
1691     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1692
1693     if (mfsize < MF_BUFSIZE)
1694     {
1695         ok(mfsize == bsize ||
1696            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1697            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1698            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1699     }
1700     else
1701         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1702            desc, mfsize, bsize);
1703
1704     /* basic things must match */
1705     emh1 = (const ENHMETAHEADER *)bits;
1706     emh2 = (const ENHMETAHEADER *)buf;
1707     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1708     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1709     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1710     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1711
1712     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1713     ok(emh1->nSize == emh2->nSize ||
1714        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1715        broken(emh1->nSize - diff_9x == emh2->nSize),
1716        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1717     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1718     ok(emh1->nBytes == emh2->nBytes ||
1719        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1720        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1721        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1722     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1723
1724     offset1 = emh1->nSize;
1725     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1726     while (offset1 < emh1->nBytes)
1727     {
1728         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1729         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1730
1731         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1732               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1733
1734         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1735
1736         /* We have already bailed out if iType or nSize don't match */
1737         offset1 += emr1->nSize;
1738         offset2 += emr2->nSize;
1739     }
1740     return 0;
1741 }
1742
1743
1744 /* tests blitting to an EMF */
1745 static void test_emf_BitBlt(void)
1746 {
1747     HDC hdcDisplay, hdcMetafile, hdcBitmap;
1748     HBITMAP hBitmap, hOldBitmap;
1749     HENHMETAFILE hMetafile;
1750 #define BMP_DIM 4
1751     BITMAPINFOHEADER bmih =
1752     {
1753         sizeof(BITMAPINFOHEADER),
1754         BMP_DIM,/* biWidth */
1755         BMP_DIM,/* biHeight */
1756         1,      /* biPlanes */
1757         24,     /* biBitCount */
1758         BI_RGB, /* biCompression */
1759         0,      /* biXPelsPerMeter */
1760         0,      /* biYPelsPerMeter */
1761         0,      /* biClrUsed */
1762         0,      /* biClrImportant */
1763     };
1764     void *bits;
1765     BOOL ret;
1766
1767     hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1768     ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1769
1770     hdcBitmap = CreateCompatibleDC(hdcDisplay);
1771     ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1772     bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1773     bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1774     hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1775                                DIB_RGB_COLORS, &bits, NULL, 0);
1776     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1777
1778     hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1779     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1780
1781     /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1782     ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1783     ok( ret, "BitBlt(BLACKNESS) failed\n" );
1784
1785     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1786     ok( ret, "BitBlt(SRCCOPY) failed\n" );
1787     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1788     ok( ret, "BitBlt(WHITENESS) failed\n" );
1789
1790     hMetafile = CloseEnhMetaFile(hdcMetafile);
1791     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1792
1793     if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1794         "emf_BitBlt", FALSE) != 0)
1795     {
1796         dump_emf_bits(hMetafile, "emf_BitBlt");
1797         dump_emf_records(hMetafile, "emf_BitBlt");
1798     }
1799
1800     SelectObject(hdcBitmap, hOldBitmap);
1801     DeleteObject(hBitmap);
1802     DeleteDC(hdcBitmap);
1803     DeleteDC(hdcDisplay);
1804 #undef BMP_DIM
1805 }
1806
1807 static void test_emf_DCBrush(void)
1808 {
1809     HDC hdcMetafile;
1810     HENHMETAFILE hMetafile;
1811     HBRUSH hBrush;
1812     HPEN hPen;
1813     BOOL ret;
1814     COLORREF color;
1815
1816     if (!pSetDCBrushColor || !pSetDCPenColor)
1817     {
1818         win_skip( "SetDCBrush/PenColor not supported\n" );
1819         return;
1820     }
1821
1822     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1823     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1824
1825     hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1826     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1827
1828     hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1829     ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1830
1831     color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1832     ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1833
1834     color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1835     ok( color == 0, "SetDCPenColor returned %x\n", color );
1836
1837     Rectangle( hdcMetafile, 10, 10, 20, 20 );
1838
1839     color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1840     ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1841
1842     hMetafile = CloseEnhMetaFile(hdcMetafile);
1843     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1844
1845     if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1846                           "emf_DC_Brush", FALSE ) != 0)
1847     {
1848         dump_emf_bits(hMetafile, "emf_DC_Brush");
1849         dump_emf_records(hMetafile, "emf_DC_Brush");
1850     }
1851     ret = DeleteEnhMetaFile(hMetafile);
1852     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1853     ret = DeleteObject(hBrush);
1854     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1855     ret = DeleteObject(hPen);
1856     ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1857 }
1858
1859 /* Test a blank metafile.  May be used as a template for new tests. */
1860
1861 static void test_mf_Blank(void)
1862 {
1863     HDC hdcMetafile;
1864     HMETAFILE hMetafile;
1865     INT caps;
1866     BOOL ret;
1867     INT type;
1868
1869     hdcMetafile = CreateMetaFileA(NULL);
1870     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1871     trace("hdcMetafile %p\n", hdcMetafile);
1872
1873 /* Tests on metafile initialization */
1874     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1875     ok (caps == DT_METAFILE,
1876         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1877
1878     hMetafile = CloseMetaFile(hdcMetafile);
1879     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1880     type = GetObjectType(hMetafile);
1881     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1882     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1883
1884     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1885         "mf_blank") != 0)
1886     {
1887         dump_mf_bits(hMetafile, "mf_Blank");
1888         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1889     }
1890
1891     ret = DeleteMetaFile(hMetafile);
1892     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1893 }
1894
1895 static void test_CopyMetaFile(void)
1896 {
1897     HDC hdcMetafile;
1898     HMETAFILE hMetafile, hmf_copy;
1899     BOOL ret;
1900     char temp_path[MAX_PATH];
1901     char mf_name[MAX_PATH];
1902     INT type;
1903
1904     hdcMetafile = CreateMetaFileA(NULL);
1905     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1906     trace("hdcMetafile %p\n", hdcMetafile);
1907
1908     hMetafile = CloseMetaFile(hdcMetafile);
1909     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1910     type = GetObjectType(hMetafile);
1911     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1912
1913     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1914         "mf_blank") != 0)
1915     {
1916         dump_mf_bits(hMetafile, "mf_Blank");
1917         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1918     }
1919
1920     GetTempPathA(MAX_PATH, temp_path);
1921     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1922
1923     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1924     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1925
1926     type = GetObjectType(hmf_copy);
1927     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1928
1929     ret = DeleteMetaFile(hMetafile);
1930     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1931
1932     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1933     {
1934         dump_mf_bits(hmf_copy, "mf_Blank");
1935         EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1936     }
1937
1938     ret = DeleteMetaFile(hmf_copy);
1939     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1940
1941     DeleteFileA(mf_name);
1942 }
1943
1944 static void test_SetMetaFileBits(void)
1945 {
1946     HMETAFILE hmf;
1947     INT type;
1948     BOOL ret;
1949     BYTE buf[256];
1950     METAHEADER *mh;
1951
1952     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1953     trace("hmf %p\n", hmf);
1954     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1955     type = GetObjectType(hmf);
1956     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1957
1958     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1959     {
1960         dump_mf_bits(hmf, "mf_Graphics");
1961         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1962     }
1963
1964     ret = DeleteMetaFile(hmf);
1965     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1966
1967     /* NULL data crashes XP SP1 */
1968     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1969
1970     /* Now with zero size */
1971     SetLastError(0xdeadbeef);
1972     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1973     trace("hmf %p\n", hmf);
1974     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1975     ok(GetLastError() == ERROR_INVALID_DATA ||
1976        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1977        "wrong error %d\n", GetLastError());
1978
1979     /* Now with odd size */
1980     SetLastError(0xdeadbeef);
1981     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1982     trace("hmf %p\n", hmf);
1983     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1984     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1985
1986     /* Now with zeroed out header fields */
1987     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1988     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1989     mh = (METAHEADER *)buf;
1990     /* corruption of any of the below fields leads to a failure */
1991     mh->mtType = 0;
1992     mh->mtVersion = 0;
1993     mh->mtHeaderSize = 0;
1994     SetLastError(0xdeadbeef);
1995     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1996     trace("hmf %p\n", hmf);
1997     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1998     ok(GetLastError() == ERROR_INVALID_DATA ||
1999        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2000        "wrong error %d\n", GetLastError());
2001
2002     /* Now with corrupted mtSize field */
2003     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2004     mh = (METAHEADER *)buf;
2005     /* corruption of mtSize doesn't lead to a failure */
2006     mh->mtSize *= 2;
2007     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2008     trace("hmf %p\n", hmf);
2009     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2010
2011     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2012     {
2013         dump_mf_bits(hmf, "mf_Graphics");
2014         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2015     }
2016
2017     ret = DeleteMetaFile(hmf);
2018     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2019
2020 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2021     /* Now with zeroed out mtSize field */
2022     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2023     mh = (METAHEADER *)buf;
2024     /* zeroing mtSize doesn't lead to a failure */
2025     mh->mtSize = 0;
2026     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2027     trace("hmf %p\n", hmf);
2028     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2029
2030     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2031     {
2032         dump_mf_bits(hmf, "mf_Graphics");
2033         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2034     }
2035
2036     ret = DeleteMetaFile(hmf);
2037     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2038 #endif
2039 }
2040
2041 /* Simple APIs from mfdrv/graphics.c
2042  */
2043
2044 static void test_mf_Graphics(void)
2045 {
2046     HDC hdcMetafile;
2047     HMETAFILE hMetafile;
2048     POINT oldpoint;
2049     BOOL ret;
2050
2051     hdcMetafile = CreateMetaFileA(NULL);
2052     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2053     trace("hdcMetafile %p\n", hdcMetafile);
2054
2055     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2056     ok( ret, "MoveToEx error %d.\n", GetLastError());
2057     ret = LineTo(hdcMetafile, 2, 2);
2058     ok( ret, "LineTo error %d.\n", GetLastError());
2059     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2060     ok( ret, "MoveToEx error %d.\n", GetLastError());
2061
2062 /* oldpoint gets garbage under Win XP, so the following test would
2063  * work under Wine but fails under Windows:
2064  *
2065  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
2066  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2067  *       oldpoint.x, oldpoint.y);
2068  */
2069
2070     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2071     ok( ret, "Ellipse error %d.\n", GetLastError());
2072
2073     hMetafile = CloseMetaFile(hdcMetafile);
2074     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2075     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2076
2077     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2078         "mf_Graphics") != 0)
2079     {
2080         dump_mf_bits(hMetafile, "mf_Graphics");
2081         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2082     }
2083
2084     ret = DeleteMetaFile(hMetafile);
2085     ok( ret, "DeleteMetaFile(%p) error %d\n",
2086         hMetafile, GetLastError());
2087 }
2088
2089 static void test_mf_PatternBrush(void)
2090 {
2091     HDC hdcMetafile;
2092     HMETAFILE hMetafile;
2093     LOGBRUSH *orig_lb;
2094     HBRUSH hBrush;
2095     BOOL ret;
2096
2097     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2098
2099     orig_lb->lbStyle = BS_PATTERN;
2100     orig_lb->lbColor = RGB(0, 0, 0);
2101     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2102     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2103
2104     hBrush = CreateBrushIndirect (orig_lb);
2105     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2106
2107     hdcMetafile = CreateMetaFileA(NULL);
2108     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2109     trace("hdcMetafile %p\n", hdcMetafile);
2110
2111     hBrush = SelectObject(hdcMetafile, hBrush);
2112     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2113
2114     hMetafile = CloseMetaFile(hdcMetafile);
2115     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2116     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2117
2118     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2119         "mf_Pattern_Brush") != 0)
2120     {
2121         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2122         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2123     }
2124
2125     ret = DeleteMetaFile(hMetafile);
2126     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2127     ret = DeleteObject(hBrush);
2128     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2129     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2130     ok( ret, "DeleteObject(HBITMAP) error %d\n",
2131         GetLastError());
2132     HeapFree (GetProcessHeap(), 0, orig_lb);
2133 }
2134
2135 static void test_mf_DCBrush(void)
2136 {
2137     HDC hdcMetafile;
2138     HMETAFILE hMetafile;
2139     HBRUSH hBrush;
2140     HPEN hPen;
2141     BOOL ret;
2142     COLORREF color;
2143
2144     if (!pSetDCBrushColor || !pSetDCPenColor)
2145     {
2146         win_skip( "SetDCBrush/PenColor not supported\n" );
2147         return;
2148     }
2149
2150     hdcMetafile = CreateMetaFileA(NULL);
2151     ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2152
2153     hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2154     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2155
2156     hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2157     ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2158
2159     color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2160     ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2161
2162     color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2163     ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2164
2165     Rectangle( hdcMetafile, 10, 10, 20, 20 );
2166
2167     color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2168     ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2169
2170     hMetafile = CloseMetaFile(hdcMetafile);
2171     ok( hMetafile != 0, "CloseMetaFile failed\n" );
2172
2173     if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2174     {
2175         dump_mf_bits(hMetafile, "mf_DCBrush");
2176         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2177     }
2178     ret = DeleteMetaFile(hMetafile);
2179     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2180 }
2181
2182 static void test_mf_ExtTextOut_on_path(void)
2183 {
2184     HDC hdcMetafile;
2185     HMETAFILE hMetafile;
2186     BOOL ret;
2187     static const INT dx[4] = { 3, 5, 8, 12 };
2188
2189     hdcMetafile = CreateMetaFileA(NULL);
2190     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2191     trace("hdcMetafile %p\n", hdcMetafile);
2192
2193     ret = BeginPath(hdcMetafile);
2194     ok(!ret, "BeginPath on metafile DC should fail\n");
2195
2196     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2197     ok(ret, "ExtTextOut error %d\n", GetLastError());
2198
2199     ret = EndPath(hdcMetafile);
2200     ok(!ret, "EndPath on metafile DC should fail\n");
2201
2202     hMetafile = CloseMetaFile(hdcMetafile);
2203     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2204
2205     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2206         "mf_TextOut_on_path") != 0)
2207     {
2208         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2209         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2210     }
2211
2212     ret = DeleteMetaFile(hMetafile);
2213     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2214 }
2215
2216 static void test_emf_ExtTextOut_on_path(void)
2217 {
2218     HWND hwnd;
2219     HDC hdcDisplay, hdcMetafile;
2220     HENHMETAFILE hMetafile;
2221     BOOL ret;
2222     static const INT dx[4] = { 3, 5, 8, 12 };
2223
2224     /* Win9x doesn't play EMFs on invisible windows */
2225     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2226                            0, 0, 200, 200, 0, 0, 0, NULL);
2227     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2228
2229     hdcDisplay = GetDC(hwnd);
2230     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2231
2232     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2233     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2234
2235     ret = BeginPath(hdcMetafile);
2236     ok(ret, "BeginPath error %d\n", GetLastError());
2237
2238     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2239     ok(ret, "ExtTextOut error %d\n", GetLastError());
2240
2241     ret = EndPath(hdcMetafile);
2242     ok(ret, "EndPath error %d\n", GetLastError());
2243
2244     hMetafile = CloseEnhMetaFile(hdcMetafile);
2245     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2246
2247     /* this doesn't succeed yet: EMF has correct size, all EMF records
2248      * are there, but their contents don't match for different reasons.
2249      */
2250     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2251         "emf_TextOut_on_path", FALSE) != 0)
2252     {
2253         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2254         dump_emf_records(hMetafile, "emf_TextOut_on_path");
2255     }
2256
2257     ret = DeleteEnhMetaFile(hMetafile);
2258     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2259     ret = ReleaseDC(hwnd, hdcDisplay);
2260     ok(ret, "ReleaseDC error %d\n", GetLastError());
2261     DestroyWindow(hwnd);
2262 }
2263
2264 static const unsigned char EMF_CLIPPING[] =
2265 {
2266     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2267     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2268     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2269     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2270     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2271     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2272     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2273     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2274     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2275     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2276     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2277     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2278     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2279     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2280     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2281     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2282     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2283     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2284     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2285     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2286     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2287     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2288     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2289     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2290     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2291     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2292 };
2293
2294 static void translate( POINT *pt, UINT count, const XFORM *xform )
2295 {
2296     while (count--)
2297     {
2298         FLOAT x = (FLOAT)pt->x;
2299         FLOAT y = (FLOAT)pt->y;
2300         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2301         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2302         pt++;
2303     }
2304 }
2305
2306 /* Compare rectangles allowing rounding errors */
2307 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2308 {
2309     return abs(rc1->left - rc2->left) <= 1 &&
2310            abs(rc1->top - rc2->top) <= 1 &&
2311            abs(rc1->right - rc2->right) <= 1 &&
2312            abs(rc1->bottom - rc2->bottom) <= 1;
2313 }
2314
2315 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2316                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
2317 {
2318     if (emr->iType == EMR_EXTSELECTCLIPRGN)
2319     {
2320         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2321         union _rgn
2322         {
2323             RGNDATA data;
2324             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2325         };
2326         const union _rgn *rgn1;
2327         union _rgn rgn2;
2328         RECT rect, rc_transformed;
2329         const RECT *rc = (const RECT *)param;
2330         HRGN hrgn;
2331         XFORM xform;
2332         INT ret;
2333         BOOL is_win9x;
2334
2335         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2336                clip->cbRgnData, clip->iMode);
2337
2338         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2339         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2340            "too small data block: %u bytes\n", clip->cbRgnData);
2341         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2342             return 0;
2343
2344         rgn1 = (const union _rgn *)clip->RgnData;
2345
2346         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2347               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2348               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2349               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2350               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2351
2352         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2353
2354         rect = *(const RECT *)rgn1->data.Buffer;
2355         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2356         ok(EqualRect(&rect, rc), "rects don't match\n");
2357
2358         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2359         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2360         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2361         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2362            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2363            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2364
2365         hrgn = CreateRectRgn(0, 0, 0, 0);
2366
2367         memset(&xform, 0, sizeof(xform));
2368         SetLastError(0xdeadbeef);
2369         ret = GetWorldTransform(hdc, &xform);
2370         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2371         if (!is_win9x)
2372             ok(ret, "GetWorldTransform error %u\n", GetLastError());
2373
2374         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2375
2376         ret = GetClipRgn(hdc, hrgn);
2377         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2378
2379         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2380
2381         ret = GetClipRgn(hdc, hrgn);
2382         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2383
2384         /* Win9x returns empty clipping region */
2385         if (is_win9x) return 1;
2386
2387         ret = GetRegionData(hrgn, 0, NULL);
2388         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2389
2390         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2391         ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2392
2393         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2394               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2395               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2396               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2397               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2398
2399         rect = rgn2.data.rdh.rcBound;
2400         rc_transformed = *rc;
2401         translate((POINT *)&rc_transformed, 2, &xform);
2402         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2403               rc_transformed.right, rc_transformed.bottom);
2404         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2405
2406         rect = *(const RECT *)rgn2.data.Buffer;
2407         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2408         rc_transformed = *rc;
2409         translate((POINT *)&rc_transformed, 2, &xform);
2410         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2411               rc_transformed.right, rc_transformed.bottom);
2412         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2413
2414         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2415         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2416         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2417         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2418            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2419            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2420
2421         DeleteObject(hrgn);
2422     }
2423     return 1;
2424 }
2425
2426 static void test_emf_clipping(void)
2427 {
2428     static const RECT rc = { 0, 0, 100, 100 };
2429     RECT rc_clip = { 100, 100, 1024, 1024 };
2430     HWND hwnd;
2431     HDC hdc;
2432     HENHMETAFILE hemf;
2433     HRGN hrgn;
2434     INT ret;
2435     RECT rc_res, rc_sclip;
2436
2437     SetLastError(0xdeadbeef);
2438     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2439     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2440
2441     /* Need to write something to the emf, otherwise Windows won't play it back */
2442     LineTo(hdc, 1, 1);
2443
2444     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2445     ret = SelectClipRgn(hdc, hrgn);
2446     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2447
2448     SetLastError(0xdeadbeef);
2449     hemf = CloseEnhMetaFile(hdc);
2450     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2451
2452     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2453         "emf_clipping", FALSE) != 0)
2454     {
2455         dump_emf_bits(hemf, "emf_clipping");
2456         dump_emf_records(hemf, "emf_clipping");
2457     }
2458
2459     DeleteObject(hrgn);
2460
2461     /* Win9x doesn't play EMFs on invisible windows */
2462     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2463                            0, 0, 200, 200, 0, 0, 0, NULL);
2464     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2465
2466     hdc = GetDC(hwnd);
2467
2468     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2469     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2470
2471     DeleteEnhMetaFile(hemf);
2472     ReleaseDC(hwnd, hdc);
2473     DestroyWindow(hwnd);
2474
2475     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2476
2477     SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2478     hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2479     SelectClipRgn(hdc, hrgn);
2480     ret = GetClipBox(hdc, &rc_res);
2481 todo_wine
2482     ok(ret == SIMPLEREGION, "got %d\n", ret);
2483     if(ret == SIMPLEREGION)
2484         ok(EqualRect(&rc_res, &rc_sclip),
2485                  "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2486                  rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2487                  rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2488
2489     hemf = CloseEnhMetaFile(hdc);
2490     DeleteEnhMetaFile(hemf);
2491     DeleteObject(hrgn);
2492     DeleteDC(hdc);
2493 }
2494
2495 static const unsigned char MF_CLIP_BITS[] = {
2496     /* METAHEADER */
2497     0x01, 0x00,             /* mtType */
2498     0x09, 0x00,             /* mtHeaderSize */
2499     0x00, 0x03,             /* mtVersion */
2500     0x32, 0x00, 0x00, 0x00, /* mtSize */
2501     0x01, 0x00,             /* mtNoObjects */
2502     0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2503     0x00, 0x00,             /* reserved */
2504
2505     /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2506     0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2507     0xff, 0x06,             /* META_CREATEREGION */
2508     0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2509     0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2510     0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2511     0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2512     0x02, 0x00,
2513
2514     /* METARECORD for SelectObject */
2515     0x04, 0x00, 0x00, 0x00,
2516     0x2d, 0x01,             /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2517     0x00, 0x00,
2518
2519     /* METARECORD */
2520     0x04, 0x00, 0x00, 0x00,
2521     0xf0, 0x01,             /* META_DELETEOBJECT */
2522     0x00, 0x00,
2523
2524     /* METARECORD for MoveTo(1,0x30) */
2525     0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2526     0x14, 0x02,             /* META_MOVETO */
2527     0x30, 0x00,             /* y */
2528     0x01, 0x00,             /* x */
2529
2530     /* METARECORD for LineTo(0x20, 0x30) */
2531     0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2532     0x13, 0x02,             /* META_LINETO */
2533     0x30, 0x00,             /* y */
2534     0x20, 0x00,             /* x */
2535
2536     /* EOF */
2537     0x03, 0x00, 0x00, 0x00,
2538     0x00, 0x00
2539 };
2540
2541 static int clip_mf_enum_proc_seen_selectclipregion;
2542 static int clip_mf_enum_proc_seen_selectobject;
2543
2544 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2545                                        METARECORD *mr, int n_objs, LPARAM param)
2546 {
2547     switch (mr->rdFunction) {
2548     case META_SELECTCLIPREGION:
2549         clip_mf_enum_proc_seen_selectclipregion++;
2550         break;
2551     case META_SELECTOBJECT:
2552         clip_mf_enum_proc_seen_selectobject++;
2553         break;
2554     }
2555     return 1;
2556 }
2557
2558 static void test_mf_clipping(void)
2559 {
2560                           /* left top right bottom */
2561     static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2562     HWND hwnd;
2563     HDC hdc;
2564     HMETAFILE hmf;
2565     HRGN hrgn;
2566     INT ret;
2567
2568     SetLastError(0xdeadbeef);
2569     hdc = CreateMetaFileA(NULL);
2570     ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2571
2572     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2573     ret = SelectClipRgn(hdc, hrgn);
2574     /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2575     ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2576
2577     /* Draw a line that starts off left of the clip region and ends inside it */
2578     MoveToEx(hdc, 0x1, 0x30, NULL);
2579     LineTo(hdc,  0x20, 0x30);
2580
2581     SetLastError(0xdeadbeef);
2582     hmf = CloseMetaFile(hdc);
2583     ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2584
2585     if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2586         "mf_clipping") != 0)
2587     {
2588         dump_mf_bits(hmf, "mf_clipping");
2589     }
2590
2591     DeleteObject(hrgn);
2592
2593     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2594                            0, 0, 200, 200, 0, 0, 0, NULL);
2595     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2596
2597     hdc = GetDC(hwnd);
2598
2599     ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2600     ok(ret, "EnumMetaFile error %d\n", GetLastError());
2601
2602     /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2603     ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2604        "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2605     ok(clip_mf_enum_proc_seen_selectobject == 1,
2606        "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2607
2608     DeleteMetaFile(hmf);
2609     ReleaseDC(hwnd, hdc);
2610     DestroyWindow(hwnd);
2611 }
2612
2613 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2614 {
2615     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2616     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2617     /* When using MM_TEXT Win9x does not update the mapping mode 
2618      * until a record is played which actually outputs something */
2619     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2620     LPtoDP(hdc, mapping, 2);
2621     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2622            lpEMFR->iType, lpEMFR->nSize,
2623            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2624
2625     if (lpEMFR->iType == EMR_LINETO)
2626     {
2627         INT x0, y0, x1, y1;
2628         if (!lpMFP || lpMFP->mm == MM_TEXT)
2629         {
2630             x0 = 0;
2631             y0 = 0;
2632             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2633             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2634         }
2635         else
2636         {
2637             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2638             
2639             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2640             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2641             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2642             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2643         }
2644         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2645             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2646             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2647             x0, y0, x1, y1);
2648     }
2649     return TRUE;
2650 }
2651
2652 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2653 {
2654     HDC hdcMf;
2655     HMETAFILE hmf;
2656     HENHMETAFILE hemf;
2657     BOOL ret;
2658     UINT size;
2659     LPBYTE pBits;
2660
2661     hdcMf = CreateMetaFile(NULL);
2662     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2663     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2664     ok(ret, "LineTo failed with error %d\n", GetLastError());
2665     hmf = CloseMetaFile(hdcMf);
2666     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2667
2668     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2669     {
2670         dump_mf_bits(hmf, "mf_LineTo");
2671         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2672     }
2673
2674     size = GetMetaFileBitsEx(hmf, 0, NULL);
2675     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2676     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2677     GetMetaFileBitsEx(hmf, size, pBits);
2678     DeleteMetaFile(hmf);
2679     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2680     HeapFree(GetProcessHeap(), 0, pBits);
2681     return hemf;
2682 }
2683
2684 static void test_mf_conversions(void)
2685 {
2686     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2687     {
2688         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2689         HENHMETAFILE hemf;
2690         METAFILEPICT mfp;
2691         RECT rect = { 0, 0, 100, 100 };
2692         mfp.mm = MM_ANISOTROPIC;
2693         mfp.xExt = 100;
2694         mfp.yExt = 100;
2695         mfp.hMF = NULL;
2696         hemf = create_converted_emf(&mfp);
2697
2698         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2699                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2700         {
2701             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2702             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2703         }
2704
2705         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2706
2707         DeleteEnhMetaFile(hemf);
2708         DeleteDC(hdcOffscreen);
2709     }
2710
2711     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2712     {
2713         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2714         HENHMETAFILE hemf;
2715         METAFILEPICT mfp;
2716         RECT rect = { 0, 0, 100, 100 };
2717         mfp.mm = MM_TEXT;
2718         mfp.xExt = 0;
2719         mfp.yExt = 0;
2720         mfp.hMF = NULL;
2721         hemf = create_converted_emf(&mfp);
2722
2723         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2724                              "emf_LineTo MM_TEXT", TRUE) != 0)
2725         {
2726             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2727             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2728         }
2729
2730         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2731
2732         DeleteEnhMetaFile(hemf);
2733         DeleteDC(hdcOffscreen);
2734     }
2735
2736     trace("Testing MF->EMF conversion (NULL mfp)\n");
2737     {
2738         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2739         HENHMETAFILE hemf;
2740         RECT rect = { 0, 0, 100, 100 };
2741         hemf = create_converted_emf(NULL);
2742
2743         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2744                              "emf_LineTo NULL", TRUE) != 0)
2745         {
2746             dump_emf_bits(hemf, "emf_LineTo NULL");
2747             dump_emf_records(hemf, "emf_LineTo NULL");
2748         }
2749
2750         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2751
2752         DeleteEnhMetaFile(hemf);
2753         DeleteDC(hdcOffscreen);
2754     }
2755 }
2756
2757 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2758                                        LONG mm, LONG xExt, LONG yExt,
2759                                        RECTL * rclBounds, RECTL * rclFrame)
2760 {
2761   METAFILEPICT mfp;
2762   METAFILEPICT * mfpPtr = NULL;
2763   HENHMETAFILE emf;
2764   ENHMETAHEADER header;
2765   UINT res;
2766
2767   if (!mfpIsNull)
2768   {
2769     mfp.mm = mm;
2770     mfp.xExt = xExt;
2771     mfp.yExt = yExt;
2772     mfpPtr = &mfp;
2773   }
2774
2775   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2776   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2777   if (!emf) return FALSE;
2778   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2779   ok(res != 0, "GetEnhMetaHeader failed\n");
2780   DeleteEnhMetaFile(emf);
2781   if (!res) return FALSE;
2782
2783   *rclBounds = header.rclBounds;
2784   *rclFrame = header.rclFrame;
2785   return TRUE;
2786 }
2787
2788 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2789                                          LONG mm, LONG xExt, LONG yExt,
2790                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2791 {
2792   RECTL rclBounds, rclFrame;
2793
2794   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2795   {
2796     const char * msg;
2797     char buf[64];
2798
2799     if (mfpIsNull)
2800     {
2801        msg = "mfp == NULL";
2802     }
2803     else
2804     {
2805       const char * mm_str;
2806       switch (mm)
2807       {
2808          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2809          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2810          default:             mm_str = "Unexpected";
2811       }
2812       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2813       msg = buf;
2814     }
2815
2816     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2817     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2818     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2819     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2820     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2821     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2822     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2823     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2824   }
2825 }
2826
2827 static void test_SetWinMetaFileBits(void)
2828 {
2829   HMETAFILE wmf;
2830   HDC wmfDC;
2831   BYTE * buffer;
2832   UINT buffer_size;
2833   RECT rect;
2834   UINT res;
2835   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2836   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2837   RECTL rclBounds, rclFrame;
2838   HDC dc;
2839   LONG diffx, diffy;
2840
2841   wmfDC = CreateMetaFile(NULL);
2842   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2843   if (!wmfDC) return;
2844
2845   SetWindowExtEx(wmfDC, 100, 100, NULL);
2846   rect.left = rect.top = 0;
2847   rect.right = rect.bottom = 50;
2848   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2849   wmf = CloseMetaFile(wmfDC);
2850   ok(wmf != NULL, "Metafile creation failed\n");
2851   if (!wmf) return;
2852
2853   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2854   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2855   if (buffer_size == 0)
2856   {
2857     DeleteMetaFile(wmf);
2858     return;
2859   }
2860
2861   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2862   ok(buffer != NULL, "HeapAlloc failed\n");
2863   if (!buffer)
2864   {
2865     DeleteMetaFile(wmf);
2866     return;
2867   }
2868
2869   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2870   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2871   DeleteMetaFile(wmf);
2872   if (res != buffer_size)
2873   {
2874      HeapFree(GetProcessHeap(), 0, buffer);
2875      return;
2876   }
2877
2878   /* Get the reference bounds and frame */
2879   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2880   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2881
2882   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2883      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2884      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2885
2886   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2887   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2888   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2889   if (diffx < 0) diffx = -diffx;
2890   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2891
2892   dc = CreateCompatibleDC(NULL);
2893
2894   /* Allow 1 mm difference (rounding errors) */
2895   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2896   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2897   if (diffx < 0) diffx = -diffx;
2898   if (diffy < 0) diffy = -diffy;
2899   todo_wine
2900   {
2901   ok(diffx <= 1 && diffy <= 1,
2902      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2903      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2904   }
2905
2906   /* Allow 1 mm difference (rounding errors) */
2907   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2908   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2909   if (diffx < 0) diffx = -diffx;
2910   if (diffy < 0) diffy = -diffy;
2911   todo_wine
2912   {
2913   ok(diffx <= 1 && diffy <= 1,
2914      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2915      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2916   }
2917   DeleteDC(dc);
2918
2919   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2920   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2921
2922   /* If xExt or yExt is zero or negative, the whole device surface is used */
2923   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2924   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2925   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2926   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2927   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2928   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2929   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2930   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2931   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2932   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2933   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2934   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2935
2936   /* MSDN says that negative xExt and yExt values specify a ratio.
2937      Check that this is wrong and the whole device surface is used */
2938   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2939   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2940
2941   /* Ordinary conversions */
2942
2943   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2944   {
2945     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2946        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2947     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2948        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2949   }
2950
2951   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2952   {
2953     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2954        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2955     ok(rclBounds.left == 0 && rclBounds.top == 0,
2956        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2957
2958     /* Wine has a rounding error */
2959     diffx = rclBounds.right - rclBounds.bottom;
2960     if (diffx < 0) diffx = -diffx;
2961     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2962   }
2963
2964   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2965   {
2966     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2967        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2968   }
2969
2970   HeapFree(GetProcessHeap(), 0, buffer);
2971 }
2972
2973 static BOOL near_match(int x, int y)
2974 {
2975     int epsilon = min(abs(x), abs(y));
2976
2977     epsilon = max(epsilon/100, 2);
2978
2979     if(x < y - epsilon || x > y + epsilon) return FALSE;
2980     return TRUE;
2981 }
2982
2983 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2984 {
2985     HENHMETAFILE emf;
2986     HDC display_dc, emf_dc;
2987     ENHMETAHEADER *enh_header;
2988     UINT size, emf_size, i;
2989     WORD check = 0;
2990     DWORD rec_num = 0;
2991     METAHEADER *mh = NULL;
2992     METARECORD *rec;
2993     INT horz_res, vert_res, horz_size, vert_size;
2994     INT curve_caps, line_caps, poly_caps;
2995
2996     display_dc = GetDC(NULL);
2997     ok(display_dc != NULL, "display_dc is NULL\n");
2998
2999     horz_res = GetDeviceCaps(display_dc, HORZRES);
3000     vert_res = GetDeviceCaps(display_dc, VERTRES);
3001     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3002     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3003
3004     emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3005     ok(emf_dc != NULL, "emf_dc is NULL\n");
3006
3007     curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3008     ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3009
3010     line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3011     ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3012
3013     poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3014     ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3015
3016     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3017         Rectangle(emf_dc, 0, 0, 1000, 20);
3018     emf = CloseEnhMetaFile(emf_dc);
3019     ok(emf != NULL, "emf is NULL\n");
3020
3021     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3022     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3023     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3024     DeleteEnhMetaFile(emf);
3025     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3026        have different resolutions */
3027     enh_header->szlDevice.cx *= scale;
3028     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3029     ok(emf != NULL, "emf is NULL\n");
3030     ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3031
3032     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3033     ok(size ||
3034        broken(size == 0), /* some versions of winxp fail for some reason */
3035        "GetWinMetaFileBits returns 0\n");
3036     if(!size) goto end;
3037     mh = HeapAlloc(GetProcessHeap(), 0, size);
3038     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3039
3040     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3041     ok(check == 0, "check %04x\n", check);
3042
3043     rec = (METARECORD*)(mh + 1);
3044
3045     while(rec->rdSize && rec->rdFunction)
3046     {
3047         const DWORD chunk_size = 0x2000;
3048         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3049
3050         if(rec_num < mfcomment_chunks)
3051         {
3052             DWORD this_chunk_size = chunk_size;
3053
3054             if(rec_num == mfcomment_chunks - 1)
3055                 this_chunk_size = emf_size - rec_num * chunk_size;
3056
3057             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3058             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3059             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3060             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3061             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3062             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3063             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
3064             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3065             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3066             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3067             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3068             /* parm[8] is the checksum, tested above */
3069             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3070             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3071             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3072             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3073             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3074             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3075             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3076             ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15));  /* DWORD size remaining after current chunk */
3077             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3078             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3079         }
3080
3081         else if(rec_num == mfcomment_chunks)
3082         {
3083             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3084             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3085         }
3086         else if(rec_num == mfcomment_chunks + 1)
3087         {
3088             POINT pt;
3089             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3090             switch(mode)
3091             {
3092             case MM_TEXT:
3093             case MM_ISOTROPIC:
3094             case MM_ANISOTROPIC:
3095                 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3096                 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3097                 break;
3098             case MM_LOMETRIC:
3099                 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3100                 pt.x = MulDiv( rc->left, 1, 10);
3101                 break;
3102             case MM_HIMETRIC:
3103                 pt.y = -rc->top + 1;
3104                 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3105                 break;
3106             case MM_LOENGLISH:
3107                 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3108                 pt.x = MulDiv( rc->left, 10, 254);
3109                 break;
3110             case MM_HIENGLISH:
3111                 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3112                 pt.x = MulDiv( rc->left, 100, 254);
3113                 break;
3114             case MM_TWIPS:
3115                 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3116                 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3117                 break;
3118             default:
3119                 pt.x = pt.y = 0;
3120             }
3121             ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3122             ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3123         }
3124         if(rec_num == mfcomment_chunks + 2)
3125         {
3126             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3127             ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3128                "got %d\n", (short)rec->rdParm[0]);
3129             ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3130                "got %d\n", (short)rec->rdParm[1]);
3131         }
3132
3133         rec_num++;
3134         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3135     }
3136
3137 end:
3138     HeapFree(GetProcessHeap(), 0, mh);
3139     HeapFree(GetProcessHeap(), 0, enh_header);
3140     DeleteEnhMetaFile(emf);
3141
3142     ReleaseDC(NULL, display_dc);
3143 }
3144
3145 static void test_GetWinMetaFileBits(void)
3146 {
3147     UINT mode;
3148     RECT frames[] =
3149     {
3150         { 1000,  2000, 3000, 6000},
3151         {-1000,  2000, 3000, 6000},
3152         { 1000, -2000, 3000, 6000},
3153         { 1005,  2005, 3000, 6000},
3154         {-1005, -2005, 3000, 6000},
3155         {-1005, -2010, 3000, 6000},
3156         {-1005,  2010, 3000, 6000},
3157         {    0,     0,    1,    1},
3158         {   -1,    -1,    1,    1},
3159         {    0,     0,    0,    0}
3160     };
3161
3162     for(mode = MM_MIN; mode <= MM_MAX; mode++)
3163     {
3164         RECT *rc;
3165         trace("mode %d\n", mode);
3166
3167         for(rc = frames; rc->right - rc->left > 0; rc++)
3168         {
3169             trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
3170             getwinmetafilebits(mode, 1, rc);
3171             getwinmetafilebits(mode, 2, rc);
3172         }
3173     }
3174 }
3175
3176 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3177 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3178 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3179
3180 static void test_gdiis(void)
3181 {
3182     RECT rect = {0,0,100,100};
3183     HDC hdc, hemfDC, hmfDC;
3184     HENHMETAFILE hemf;
3185     HMODULE hgdi32;
3186
3187     /* resolve all the functions */
3188     hgdi32 = GetModuleHandle("gdi32");
3189     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3190     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3191     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3192
3193     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3194     {
3195         win_skip("Needed GdiIs* functions are not available\n");
3196         return;
3197     }
3198
3199     /* try with nothing */
3200     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3201     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3202     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3203
3204     /* try with a metafile */
3205     hmfDC = CreateMetaFile(NULL);
3206     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3207     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3208     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3209     DeleteMetaFile(CloseMetaFile(hmfDC));
3210
3211     /* try with an enhanced metafile */
3212     hdc = GetDC(NULL);
3213     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3214     ok(hemfDC != NULL, "failed to create emf\n");
3215
3216     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3217     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3218     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3219
3220     hemf = CloseEnhMetaFile(hemfDC);
3221     ok(hemf != NULL, "failed to close EMF\n");
3222     DeleteEnhMetaFile(hemf);
3223     ReleaseDC(NULL,hdc);
3224 }
3225
3226 static void test_SetEnhMetaFileBits(void)
3227 {
3228     BYTE data[256];
3229     HENHMETAFILE hemf;
3230     ENHMETAHEADER *emh;
3231
3232     memset(data, 0xAA, sizeof(data));
3233     SetLastError(0xdeadbeef);
3234     hemf = SetEnhMetaFileBits(sizeof(data), data);
3235     ok(!hemf, "SetEnhMetaFileBits should fail\n");
3236     ok(GetLastError() == ERROR_INVALID_DATA ||
3237        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3238        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3239
3240     emh = (ENHMETAHEADER *)data;
3241     memset(emh, 0, sizeof(*emh));
3242
3243     emh->iType = EMR_HEADER;
3244     emh->nSize = sizeof(*emh);
3245     emh->dSignature = ENHMETA_SIGNATURE;
3246     /* emh->nVersion  = 0x10000; XP doesn't care about version */
3247     emh->nBytes = sizeof(*emh);
3248     /* emh->nRecords = 1; XP doesn't care about records */
3249     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3250
3251     SetLastError(0xdeadbeef);
3252     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3253     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3254     DeleteEnhMetaFile(hemf);
3255
3256     /* XP refuses to load unaligned EMF */
3257     emh->nBytes++;
3258     SetLastError(0xdeadbeef);
3259     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3260     ok(!hemf ||
3261        broken(hemf != NULL), /* Win9x, WinMe */
3262        "SetEnhMetaFileBits should fail\n");
3263     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3264     DeleteEnhMetaFile(hemf);
3265
3266     emh->dSignature = 0;
3267     emh->nBytes--;
3268     SetLastError(0xdeadbeef);
3269     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3270     ok(!hemf ||
3271        broken(hemf != NULL), /* Win9x, WinMe */
3272        "SetEnhMetaFileBits should fail\n");
3273     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3274     DeleteEnhMetaFile(hemf);
3275 }
3276
3277 static void test_emf_polybezier(void)
3278 {
3279     HDC hdcMetafile;
3280     HENHMETAFILE hemf;
3281     POINT pts[4];
3282     BOOL ret;
3283
3284     SetLastError(0xdeadbeef);
3285     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3286     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3287
3288     pts[0].x = pts[0].y = 10;
3289     pts[1].x = pts[1].y = 20;
3290     pts[2].x = pts[2].y = 15;
3291     pts[3].x = pts[3].y = 25;
3292     ret = PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO16 */
3293     ok( ret, "PolyBezierTo failed\n" );
3294     ret = PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER16   */
3295     ok( ret, "PolyBezier failed\n" );
3296
3297     pts[0].x = pts[0].y = 32769;
3298     ret = PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER   */
3299     ok( ret, "PolyBezier failed\n" );
3300     ret = PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO */
3301     ok( ret, "PolyBezierTo failed\n" );
3302
3303     hemf = CloseEnhMetaFile(hdcMetafile);
3304     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3305
3306     if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3307         "emf_Bezier", FALSE) != 0)
3308     {
3309         dump_emf_bits(hemf, "emf_Bezier");
3310         dump_emf_records(hemf, "emf_Bezier");
3311     }
3312
3313     DeleteEnhMetaFile(hemf);
3314 }
3315
3316 START_TEST(metafile)
3317 {
3318     init_function_pointers();
3319
3320     /* For enhanced metafiles (enhmfdrv) */
3321     test_ExtTextOut();
3322     test_ExtTextOutScale();
3323     test_SaveDC();
3324     test_emf_BitBlt();
3325     test_emf_DCBrush();
3326     test_emf_ExtTextOut_on_path();
3327     test_emf_clipping();
3328     test_emf_polybezier();
3329
3330     /* For win-format metafiles (mfdrv) */
3331     test_mf_SaveDC();
3332     test_mf_Blank();
3333     test_mf_Graphics();
3334     test_mf_PatternBrush();
3335     test_mf_DCBrush();
3336     test_CopyMetaFile();
3337     test_SetMetaFileBits();
3338     test_mf_ExtTextOut_on_path();
3339     test_mf_clipping();
3340
3341     /* For metafile conversions */
3342     test_mf_conversions();
3343     test_SetWinMetaFileBits();
3344     test_GetWinMetaFileBits();
3345
3346     test_gdiis();
3347     test_SetEnhMetaFileBits();
3348 }