gdi32/tests: Add some traces and fix a few comments.
[wine] / dlls / gdi32 / tests / metafile.c
1 /*
2  * Unit tests for metafile functions
3  *
4  * Copyright (c) 2002 Dmitry Timoshkov
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
24
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
33
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
37
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
40
41 #define GDI_GET_PROC(func)                                     \
42     p ## func = (void *)GetProcAddress(hGDI, #func);           \
43     if(!p ## func)                                             \
44         trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
45
46 static void init_function_pointers(void)
47 {
48     HMODULE hGDI;
49
50     pGetRelAbs = NULL;
51     pSetRelAbs = NULL;
52
53     hGDI = GetModuleHandleA("gdi32.dll");
54     assert(hGDI);
55     GDI_GET_PROC(GetRelAbs);
56     GDI_GET_PROC(SetRelAbs);
57 }
58
59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60     const ENHMETARECORD *emr, int n_objs, LPARAM param)
61 {
62     static int n_record;
63     DWORD i;
64     const INT *dx;
65     INT *orig_dx = (INT *)param;
66     LOGFONTA device_lf;
67     INT ret;
68
69     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70            hdc, emr->iType, emr->nSize, (void *)param);
71
72     if(!hdc) return 1;
73
74     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
75
76     switch (emr->iType)
77     {
78     case EMR_HEADER:
79         ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
80         ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
81         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
82         ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
83         ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
84         ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
85         ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
86
87         /* GetBkMode, GetRelAbs do not get reset to the default value */
88         ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
89         if(pSetRelAbs && pGetRelAbs)
90             ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
91
92         n_record = 0;
93         break;
94
95     case EMR_EXTTEXTOUTA:
96     {
97         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
98         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
99
100         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
102
103         /* compare up to lfOutPrecision, other values are not interesting,
104          * and in fact sometimes arbitrary adapted by Win9x.
105          */
106         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
107         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
108
109         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
110         {
111             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
112                                      n_record, i, dx[i], orig_dx[i]);
113         }
114         n_record++;
115         emr_processed = TRUE;
116         break;
117     }
118
119     case EMR_EXTTEXTOUTW:
120     {
121         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
123
124         SetLastError(0xdeadbeef);
125         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
126         ok( ret == sizeof(device_lf) ||
127             broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
128             "GetObjectA error %d\n", GetLastError());
129
130         /* compare up to lfOutPrecision, other values are not interesting,
131          * and in fact sometimes arbitrary adapted by Win9x.
132          */
133         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
134         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
135
136         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
137         {
138             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
139                                      n_record, i, dx[i], orig_dx[i]);
140         }
141         n_record++;
142         emr_processed = TRUE;
143         break;
144     }
145
146     default:
147         break;
148     }
149
150     return 1;
151 }
152
153 static void test_ExtTextOut(void)
154 {
155     HWND hwnd;
156     HDC hdcDisplay, hdcMetafile;
157     HENHMETAFILE hMetafile;
158     HFONT hFont;
159     static const char text[] = "Simple text to test ExtTextOut on metafiles";
160     INT i, len, dx[256];
161     static const RECT rc = { 0, 0, 100, 100 };
162     BOOL ret;
163
164     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
165
166     /* Win9x doesn't play EMFs on invisible windows */
167     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
168                            0, 0, 200, 200, 0, 0, 0, NULL);
169     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
170
171     hdcDisplay = GetDC(hwnd);
172     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
173
174     trace("hdcDisplay %p\n", hdcDisplay);
175
176     SetMapMode(hdcDisplay, MM_TEXT);
177
178     memset(&orig_lf, 0, sizeof(orig_lf));
179
180     orig_lf.lfCharSet = ANSI_CHARSET;
181     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
182     orig_lf.lfWeight = FW_DONTCARE;
183     orig_lf.lfHeight = 7;
184     orig_lf.lfQuality = DEFAULT_QUALITY;
185     lstrcpyA(orig_lf.lfFaceName, "Arial");
186     hFont = CreateFontIndirectA(&orig_lf);
187     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
188
189     hFont = SelectObject(hdcDisplay, hFont);
190
191     len = lstrlenA(text);
192     for (i = 0; i < len; i++)
193     {
194         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
195         ok( ret, "GetCharWidthA error %d\n", GetLastError());
196     }
197     hFont = SelectObject(hdcDisplay, hFont);
198
199     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
200     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
201
202     trace("hdcMetafile %p\n", hdcMetafile);
203
204     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
205        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
206
207     hFont = SelectObject(hdcMetafile, hFont);
208
209     /* 1. pass NULL lpDx */
210     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
211     ok( ret, "ExtTextOutA error %d\n", GetLastError());
212
213     /* 2. pass custom lpDx */
214     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
215     ok( ret, "ExtTextOutA error %d\n", GetLastError());
216
217     hFont = SelectObject(hdcMetafile, hFont);
218     ret = DeleteObject(hFont);
219     ok( ret, "DeleteObject error %d\n", GetLastError());
220
221     hMetafile = CloseEnhMetaFile(hdcMetafile);
222     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
223
224     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
225
226     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
227     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
228
229     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
230     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
231     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
232     SetROP2(hdcDisplay, R2_NOT);
233     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
234     SetPolyFillMode(hdcDisplay, WINDING);
235     SetStretchBltMode(hdcDisplay, HALFTONE);
236
237     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
238     SetBkMode(hdcDisplay, OPAQUE);
239
240     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
241     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
242
243     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
244         "text align %08x\n", GetTextAlign(hdcDisplay));
245     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
246     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
247     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
248     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
249     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
250     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
251
252     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
253
254     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
255        "A valid hdc has to require a valid rc\n");
256
257     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
258        "A null hdc does not require a valid rc\n");
259
260     ret = DeleteEnhMetaFile(hMetafile);
261     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
262     ret = ReleaseDC(hwnd, hdcDisplay);
263     ok( ret, "ReleaseDC error %d\n", GetLastError());
264     DestroyWindow(hwnd);
265 }
266
267 static void check_dc_state(HDC hdc, int restore_no,
268                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
269                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
270 {
271     BOOL ret;
272     XFORM xform;
273     POINT vp_org, win_org;
274     SIZE vp_size, win_size;
275     FLOAT xscale, yscale, edx, edy;
276
277     SetLastError(0xdeadbeef);
278     ret = GetWorldTransform(hdc, &xform);
279     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
280     ok(ret, "GetWorldTransform error %u\n", GetLastError());
281
282     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
283
284     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
285     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
286
287     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
288     trace("x scale %f\n", xscale);
289     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
290        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
291
292     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
293     trace("y scale %f\n", yscale);
294     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
295        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
296
297     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
298     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
299     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
300     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
301
302     return;
303
304 win9x_here:
305
306     GetWindowOrgEx(hdc, &win_org);
307     GetViewportOrgEx(hdc, &vp_org);
308     GetWindowExtEx(hdc, &win_size);
309     GetViewportExtEx(hdc, &vp_size);
310
311     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
312     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
313
314     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
315     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
316
317     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
318     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
319
320     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
321     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
322 }
323
324 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
325                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
326 {
327     BOOL ret;
328     XFORM xform;
329     POINT pt;
330     SIZE size;
331     static int save_state;
332     static int restore_no;
333     static int select_no;
334
335     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
336            hdc, emr->iType, emr->nSize, (void *)param);
337
338     trace("BEFORE:\n");
339     SetLastError(0xdeadbeef);
340     ret = GetWorldTransform(hdc, &xform);
341     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
342     {
343         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
344         trace("window org (%d,%d)\n", pt.x, pt.y);
345         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
346         trace("vport org (%d,%d)\n", pt.x, pt.y);
347         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
348         trace("window ext (%d,%d)\n", size.cx, size.cy);
349         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
350         trace("vport ext (%d,%d)\n", size.cx, size.cy);
351     }
352     else
353     {
354         ok(ret, "GetWorldTransform error %u\n", GetLastError());
355         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
356     }
357
358     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
359
360     switch (emr->iType)
361     {
362     case EMR_HEADER:
363     {
364         static RECT exp_bounds = { 0, 0, 150, 150 };
365         RECT bounds;
366         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
367
368         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
369                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
370                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
371         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
372                emf->szlDevice.cx, emf->szlDevice.cy);
373
374         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
375         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
376
377         save_state = 0;
378         restore_no = 0;
379         select_no = 0;
380         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
381         break;
382     }
383
384     case EMR_LINETO:
385         {
386             const EMRLINETO *line = (const EMRLINETO *)emr;
387             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
388             break;
389         }
390     case EMR_SETWINDOWORGEX:
391         {
392             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
393             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
394             break;
395         }
396     case EMR_SETWINDOWEXTEX:
397         {
398             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
399             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
400             break;
401         }
402     case EMR_SETVIEWPORTORGEX:
403         {
404             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
405             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
406             break;
407         }
408     case EMR_SETVIEWPORTEXTEX:
409         {
410             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
411             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
412             break;
413         }
414     case EMR_SAVEDC:
415         save_state++;
416         trace("EMR_SAVEDC\n");
417         break;
418
419     case EMR_RESTOREDC:
420         {
421             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
422             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
423
424             switch(++restore_no)
425             {
426             case 1:
427                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
428                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
429                 break;
430             case 2:
431                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
432                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
433                 break;
434             case 3:
435                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
436                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
437                 break;
438             }
439             ok(restore_no <= 3, "restore_no %d\n", restore_no);
440             save_state += restoredc->iRelative;
441             break;
442         }
443     case EMR_SELECTOBJECT:
444         {
445             const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
446             trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
447             select_no ++;
448             break;
449         }
450     case EMR_EOF:
451         ok(save_state == 0, "EOF save_state %d\n", save_state);
452         ok(select_no == 3, "Too many/few selects  %i\n",select_no);
453         break;
454     }
455
456     trace("AFTER:\n");
457     SetLastError(0xdeadbeef);
458     ret = GetWorldTransform(hdc, &xform);
459     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
460     {
461         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
462         trace("window org (%d,%d)\n", pt.x, pt.y);
463         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
464         trace("vport org (%d,%d)\n", pt.x, pt.y);
465         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
466         trace("window ext (%d,%d)\n", size.cx, size.cy);
467         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
468         trace("vport ext (%d,%d)\n", size.cx, size.cy);
469     }
470     else
471     {
472         ok(ret, "GetWorldTransform error %u\n", GetLastError());
473         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
474     }
475
476     return 1;
477 }
478
479 static void test_SaveDC(void)
480 {
481     HDC hdcMetafile, hdcDisplay;
482     HENHMETAFILE hMetafile;
483     HWND hwnd;
484     int ret;
485     POINT pt;
486     SIZE size;
487     HFONT hFont,hFont2,hFontOld,hFontCheck;
488     static const RECT rc = { 0, 0, 150, 150 };
489
490     /* Win9x doesn't play EMFs on invisible windows */
491     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
492                            0, 0, 200, 200, 0, 0, 0, NULL);
493     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
494
495     hdcDisplay = GetDC(hwnd);
496     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
497
498     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
499     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
500
501     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
502
503     /* Need to write something to the emf, otherwise Windows won't play it back */
504     LineTo(hdcMetafile, 150, 150);
505
506     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
507     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
508     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
509     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
510
511     /* Force Win9x to update DC state */
512     SetPixelV(hdcMetafile, 50, 50, 0);
513
514     ret = GetViewportOrgEx(hdcMetafile, &pt);
515     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
516     ret = GetViewportExtEx(hdcMetafile, &size);
517     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
518     ret = SaveDC(hdcMetafile);
519     ok(ret == 1, "ret = %d\n", ret);
520
521     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
522     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
523     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
524     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
525
526     /* Force Win9x to update DC state */
527     SetPixelV(hdcMetafile, 50, 50, 0);
528
529     ret = GetViewportOrgEx(hdcMetafile, &pt);
530     ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
531     ret = GetViewportExtEx(hdcMetafile, &size);
532     ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
533     ret = SaveDC(hdcMetafile);
534     ok(ret == 2, "ret = %d\n", ret);
535
536     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
537     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
538     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
539     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
540     SetPolyFillMode( hdcMetafile, ALTERNATE );
541     SetBkColor( hdcMetafile, 0 );
542
543     /* Force Win9x to update DC state */
544     SetPixelV(hdcMetafile, 50, 50, 0);
545
546     ret = GetViewportOrgEx(hdcMetafile, &pt);
547     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
548     ret = GetViewportExtEx(hdcMetafile, &size);
549     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
550     ret = SaveDC(hdcMetafile);
551     ok(ret == 3, "ret = %d\n", ret);
552
553     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
554     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
555     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
556     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
557
558     SetPolyFillMode( hdcMetafile, WINDING );
559     SetBkColor( hdcMetafile, 0x123456 );
560     ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
561     ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
562
563     /* Force Win9x to update DC state */
564     SetPixelV(hdcMetafile, 50, 50, 0);
565
566     ret = GetViewportOrgEx(hdcMetafile, &pt);
567     ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
568     ret = GetViewportExtEx(hdcMetafile, &size);
569     ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
570     ret = RestoreDC(hdcMetafile, -1);
571     ok(ret, "ret = %d\n", ret);
572
573     ret = GetViewportOrgEx(hdcMetafile, &pt);
574     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
575     ret = GetViewportExtEx(hdcMetafile, &size);
576     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
577     ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
578     ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
579     ret = SaveDC(hdcMetafile);
580     ok(ret == 3, "ret = %d\n", ret);
581
582     ret = GetViewportOrgEx(hdcMetafile, &pt);
583     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
584     ret = GetViewportExtEx(hdcMetafile, &size);
585     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
586     ret = RestoreDC(hdcMetafile, 1);
587     ok(ret, "ret = %d\n", ret);
588     ret = GetViewportOrgEx(hdcMetafile, &pt);
589     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
590     ret = GetViewportExtEx(hdcMetafile, &size);
591     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
592
593     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
594     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
595     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
596     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
597
598     /* Force Win9x to update DC state */
599     SetPixelV(hdcMetafile, 50, 50, 0);
600
601     ret = GetViewportOrgEx(hdcMetafile, &pt);
602     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
603     ret = GetViewportExtEx(hdcMetafile, &size);
604     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
605     ret = SaveDC(hdcMetafile);
606     ok(ret == 1, "ret = %d\n", ret);
607
608     ret = GetViewportOrgEx(hdcMetafile, &pt);
609     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
610     ret = GetViewportExtEx(hdcMetafile, &size);
611     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
612     ret = SaveDC(hdcMetafile);
613     ok(ret == 2, "ret = %d\n", ret);
614
615     memset(&orig_lf, 0, sizeof(orig_lf));
616     orig_lf.lfCharSet = ANSI_CHARSET;
617     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
618     orig_lf.lfWeight = FW_DONTCARE;
619     orig_lf.lfHeight = 7;
620     orig_lf.lfQuality = DEFAULT_QUALITY;
621     lstrcpyA(orig_lf.lfFaceName, "Arial");
622     hFont = CreateFontIndirectA(&orig_lf);
623     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
624
625     hFontOld = SelectObject(hdcMetafile, hFont);
626
627     hFont2 = CreateFontIndirectA(&orig_lf);
628     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
629     hFontCheck = SelectObject(hdcMetafile, hFont2);
630     ok(hFontCheck == hFont, "Font not selected\n");
631
632     /* Force Win9x to update DC state */
633     SetPixelV(hdcMetafile, 50, 50, 0);
634
635     ret = RestoreDC(hdcMetafile, 1);
636     ok(ret, "ret = %d\n", ret);
637     ret = GetViewportOrgEx(hdcMetafile, &pt);
638     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
639     ret = GetViewportExtEx(hdcMetafile, &size);
640     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
641
642     hFontCheck = SelectObject(hdcMetafile, hFontOld);
643     ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
644        "Font not reverted with DC Restore\n");
645
646     ret = RestoreDC(hdcMetafile, -20);
647     ok(!ret, "ret = %d\n", ret);
648     ret = RestoreDC(hdcMetafile, 20);
649     ok(!ret, "ret = %d\n", ret);
650
651     hMetafile = CloseEnhMetaFile(hdcMetafile);
652     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
653
654     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
655     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
656
657     ret = DeleteObject(hFont);
658     ok( ret, "DeleteObject error %d\n", GetLastError());
659     ret = DeleteObject(hFont2);
660     ok( ret, "DeleteObject error %d\n", GetLastError());
661     ret = DeleteEnhMetaFile(hMetafile);
662     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
663     ret = ReleaseDC(hwnd, hdcDisplay);
664     ok( ret, "ReleaseDC error %d\n", GetLastError());
665     DestroyWindow(hwnd);
666 }
667
668 static void test_mf_SaveDC(void)
669 {
670     HDC hdcMetafile;
671     HMETAFILE hMetafile;
672     int ret;
673     POINT pt;
674     SIZE size;
675     HFONT hFont,hFont2,hFontOld,hFontCheck;
676
677     hdcMetafile = CreateMetaFileA(NULL);
678     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
679
680     ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
681     ok (ret, "SetMapMode should not fail\n");
682
683     /* Need to write something to the emf, otherwise Windows won't play it back */
684     LineTo(hdcMetafile, 150, 150);
685
686     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
687     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
688     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
689     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
690
691     /* Force Win9x to update DC state */
692     SetPixelV(hdcMetafile, 50, 50, 0);
693
694     ret = GetViewportOrgEx(hdcMetafile, &pt);
695     todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
696     ret = GetViewportExtEx(hdcMetafile, &size);
697     todo_wine ok (!ret, "GetViewportExtEx should fail\n");
698     ret = SaveDC(hdcMetafile);
699     ok(ret == 1, "ret = %d\n", ret);
700
701     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
702     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
703     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
704     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
705
706     /* Force Win9x to update DC state */
707     SetPixelV(hdcMetafile, 50, 50, 0);
708
709     ret = SaveDC(hdcMetafile);
710     ok(ret == 1, "ret = %d\n", ret);
711
712     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
713     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
714     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
715     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
716
717     /* Force Win9x to update DC state */
718     SetPixelV(hdcMetafile, 50, 50, 0);
719     SetPolyFillMode( hdcMetafile, ALTERNATE );
720     SetBkColor( hdcMetafile, 0 );
721
722     ret = SaveDC(hdcMetafile);
723     ok(ret == 1, "ret = %d\n", ret);
724
725     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
726     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
727     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
728     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
729
730     SetPolyFillMode( hdcMetafile, WINDING );
731     SetBkColor( hdcMetafile, 0x123456 );
732     todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
733     todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
734
735     /* Force Win9x to update DC state */
736     SetPixelV(hdcMetafile, 50, 50, 0);
737
738     ret = RestoreDC(hdcMetafile, -1);
739     ok(ret, "ret = %d\n", ret);
740
741     ret = SaveDC(hdcMetafile);
742     ok(ret == 1, "ret = %d\n", ret);
743
744     ret = RestoreDC(hdcMetafile, 1);
745     ok(ret, "ret = %d\n", ret);
746
747     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
748     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
749     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
750     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
751
752     /* Force Win9x to update DC state */
753     SetPixelV(hdcMetafile, 50, 50, 0);
754
755     ret = SaveDC(hdcMetafile);
756     ok(ret == 1, "ret = %d\n", ret);
757
758     ret = SaveDC(hdcMetafile);
759     ok(ret == 1, "ret = %d\n", ret);
760
761     memset(&orig_lf, 0, sizeof(orig_lf));
762     orig_lf.lfCharSet = ANSI_CHARSET;
763     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
764     orig_lf.lfWeight = FW_DONTCARE;
765     orig_lf.lfHeight = 7;
766     orig_lf.lfQuality = DEFAULT_QUALITY;
767     lstrcpyA(orig_lf.lfFaceName, "Arial");
768     hFont = CreateFontIndirectA(&orig_lf);
769     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
770
771     hFontOld = SelectObject(hdcMetafile, hFont);
772
773     hFont2 = CreateFontIndirectA(&orig_lf);
774     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
775     hFontCheck = SelectObject(hdcMetafile, hFont2);
776     ok(hFontCheck == hFont, "Font not selected\n");
777
778     /* Force Win9x to update DC state */
779     SetPixelV(hdcMetafile, 50, 50, 0);
780
781     ret = RestoreDC(hdcMetafile, 1);
782     ok(ret, "ret = %d\n", ret);
783
784     hFontCheck = SelectObject(hdcMetafile, hFontOld);
785     ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
786
787     /* restore level is ignored */
788     ret = RestoreDC(hdcMetafile, -20);
789     ok(ret, "ret = %d\n", ret);
790     ret = RestoreDC(hdcMetafile, 20);
791     ok(ret, "ret = %d\n", ret);
792     ret = RestoreDC(hdcMetafile, 0);
793     ok(ret, "ret = %d\n", ret);
794
795     hMetafile = CloseMetaFile(hdcMetafile);
796     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
797
798     ret = DeleteMetaFile(hMetafile);
799     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
800     ret = DeleteObject(hFont);
801     ok( ret, "DeleteObject error %d\n", GetLastError());
802     ret = DeleteObject(hFont2);
803     ok( ret, "DeleteObject error %d\n", GetLastError());
804 }
805
806
807 /* Win-format metafile (mfdrv) tests */
808 /* These tests compare the generated metafiles byte-by-byte */
809 /* with the nominal results. */
810
811 /* Maximum size of sample metafiles in bytes. */
812 #define MF_BUFSIZE 512
813
814 /* 8x8 bitmap data for a pattern brush */
815 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
816     0x01, 0x00, 0x02, 0x00,
817     0x03, 0x00, 0x04, 0x00,
818     0x05, 0x00, 0x06, 0x00,
819     0x07, 0x00, 0x08, 0x00
820 };
821
822 /* Sample metafiles to be compared to the outputs of the
823  * test functions.
824  */
825
826 static const unsigned char MF_BLANK_BITS[] = {
827     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
828     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
829     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
830 };
831
832 static const unsigned char MF_GRAPHICS_BITS[] = {
833     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
834     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
835     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
836     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
837     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
838     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
839     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
840     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
841     0x00, 0x00, 0x00, 0x00
842 };
843
844 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
845     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
846     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
847     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
848     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
849     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
850     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
851     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
854     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
855     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
856     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
857     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
858     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
859     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
860     0x00, 0x00
861 };
862
863 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
864 {
865     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
866     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
867     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
868     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
869     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
870     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
871     0x00, 0x00
872 };
873
874 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
875 {
876     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
877     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
879     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
881     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
882     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
883     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
886     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
887     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
888     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
889     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
890     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
891     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
893     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
894     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
895     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
896     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
897     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
899     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
900     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
901     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
902     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
903     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
904     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
905     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
906     0x14, 0x00, 0x00, 0x00
907 };
908
909 static const unsigned char MF_LINETO_BITS[] = {
910     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
911     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
912     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
913     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
914     0x00, 0x00
915 };
916
917 static const unsigned char EMF_LINETO_BITS[] = {
918     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
919     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
921     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
923     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
924     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
925     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
928     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
929     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
930     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
931     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
932     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
933     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
934     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
935     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
936     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
937     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
938     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
939     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
940     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
941     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
942     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
943     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
944     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
945     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
946     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
947     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
948     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
949     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
950     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
951     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
952     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
953     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
955     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
956     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
957 };
958
959 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
960     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
961     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
963     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
965     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
966     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
967     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
970     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
971     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
972     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
973     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
974     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
975     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
976     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
977     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
978     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
979     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
980     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
981     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
982     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
983     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
984     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
985     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
986     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
987     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
988     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
989     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
990     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
991     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
992     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
993     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
994     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
995     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
997     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
998     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
999 };
1000
1001 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1002     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1003     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1004     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1005     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1006     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1007     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1008     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1009     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1010     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1012     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1013     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1015     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1016     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1017     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1018     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1019     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1020     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1021     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1022     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1023     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1024     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1025     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1026     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1027     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1028     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1029     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1030     0x14, 0x00, 0x00, 0x00
1031 };
1032
1033 /* For debugging or dumping the raw metafiles produced by
1034  * new test functions.
1035  */
1036 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1037                                  INT nobj, LPARAM param)
1038 {
1039     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1040            hdc, mr->rdFunction, mr->rdSize, (void *)param);
1041     return TRUE;
1042 }
1043
1044 /* For debugging or dumping the raw metafiles produced by
1045  * new test functions.
1046  */
1047
1048 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1049 {
1050     BYTE buf[MF_BUFSIZE];
1051     UINT mfsize, i;
1052
1053     if (!winetest_debug) return;
1054
1055     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1056     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1057
1058     printf ("MetaFile %s has bits:\n{\n    ", desc);
1059     for (i=0; i<mfsize; i++)
1060     {
1061         printf ("0x%02x", buf[i]);
1062         if (i == mfsize-1)
1063             printf ("\n");
1064         else if (i % 8 == 7)
1065             printf (",\n    ");
1066         else
1067             printf (", ");
1068     }
1069     printf ("};\n");
1070 }
1071
1072 /* Compare the metafile produced by a test function with the
1073  * expected raw metafile data in "bits".
1074  * Return value is 0 for a perfect match,
1075  * -1 if lengths aren't equal,
1076  * otherwise returns the number of non-matching bytes.
1077  */
1078
1079 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1080     const char *desc)
1081 {
1082     unsigned char buf[MF_BUFSIZE];
1083     UINT mfsize, i;
1084     int diff;
1085
1086     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1087     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1088     if (mfsize < MF_BUFSIZE)
1089         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1090             desc, mfsize, bsize);
1091     else
1092         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1093             desc, mfsize, bsize);
1094     if (mfsize != bsize)
1095         return -1;
1096
1097     diff = 0;
1098     for (i=0; i<bsize; i++)
1099     {
1100        if (buf[i] !=  bits[i])
1101            diff++;
1102     }
1103     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1104         desc, mfsize, bsize, diff);
1105
1106     return diff; 
1107 }
1108
1109 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1110 {
1111     unsigned char buf[MF_BUFSIZE];
1112     DWORD mfsize, rd_size, i;
1113     int diff;
1114     HANDLE hfile;
1115     BOOL ret;
1116
1117     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1118     assert(hfile != INVALID_HANDLE_VALUE);
1119
1120     mfsize = GetFileSize(hfile, NULL);
1121     assert(mfsize <= MF_BUFSIZE);
1122
1123     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1124     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1125
1126     CloseHandle(hfile);
1127
1128     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1129
1130     if (mfsize != bsize)
1131         return -1;
1132
1133     diff = 0;
1134     for (i=0; i<bsize; i++)
1135     {
1136         if (buf[i] != bits[i])
1137             diff++;
1138     }
1139     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1140         desc, mfsize, bsize, diff);
1141
1142     return diff; 
1143 }
1144
1145 /* For debugging or dumping the raw EMFs produced by
1146  * new test functions.
1147  */
1148 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1149 {
1150     BYTE buf[MF_BUFSIZE];
1151     UINT mfsize, i;
1152
1153     if (!winetest_debug) return;
1154
1155     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1156     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1157
1158     printf("EMF %s has bits:\n{\n    ", desc);
1159     for (i = 0; i < mfsize; i++)
1160     {
1161         printf ("0x%02x", buf[i]);
1162         if (i == mfsize-1)
1163             printf ("\n");
1164         else if (i % 8 == 7)
1165             printf (",\n    ");
1166         else
1167             printf (", ");
1168     }
1169     printf ("};\n");
1170 }
1171
1172 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1173 {
1174     BYTE *emf;
1175     BYTE buf[MF_BUFSIZE];
1176     UINT mfsize, offset;
1177
1178     if (!winetest_debug) return;
1179
1180     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1181     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1182
1183     printf("EMF %s has records:\n", desc);
1184
1185     emf = buf;
1186     offset = 0;
1187     while(offset < mfsize)
1188     {
1189         EMR *emr = (EMR *)(emf + offset);
1190         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1191         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1192         offset += emr->nSize;
1193     }
1194 }
1195
1196 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1197 {
1198     const BYTE *buf;
1199     DWORD i;
1200
1201     if (!winetest_debug) return;
1202
1203     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1204     buf = (const BYTE *)emr;
1205     for (i = 0; i < emr->nSize; i++)
1206     {
1207         printf ("0x%02x", buf[i]);
1208         if (i == emr->nSize - 1)
1209             printf ("\n");
1210         else if (i % 8 == 7)
1211             printf (",\n");
1212         else
1213             printf (", ");
1214     }
1215     printf ("};\n");
1216 }
1217
1218 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1219 {
1220     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1221           eto->rclBounds.right, eto->rclBounds.bottom);
1222     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1223     trace("exScale: %f\n", eto->exScale);
1224     trace("eyScale: %f\n", eto->eyScale);
1225     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1226     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1227     trace("emrtext.offString %#x\n", eto->emrtext.offString);
1228     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1229     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1230           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1231     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1232 }
1233
1234 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1235                              const char *desc, BOOL ignore_scaling)
1236 {
1237     int diff;
1238
1239     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1240        desc, emr1->iType, emr2->iType);
1241
1242     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1243        desc, emr1->nSize, emr2->nSize);
1244
1245     /* iType and nSize mismatches are fatal */
1246     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1247
1248     /* contents of EMR_GDICOMMENT are not interesting */
1249     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1250
1251     /* different Windows versions setup DC scaling differently when
1252      * converting an old style metafile to an EMF.
1253      */
1254     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1255                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1256         return TRUE;
1257
1258     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1259     {
1260         EMREXTTEXTOUTW *eto1, *eto2;
1261
1262         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1263         memcpy(eto1, emr1, emr1->nSize);
1264         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1265         memcpy(eto2, emr2, emr2->nSize);
1266
1267         /* different Windows versions setup DC scaling differently */
1268         eto1->exScale = eto1->eyScale = 0.0;
1269         eto2->exScale = eto2->eyScale = 0.0;
1270
1271         diff = memcmp(eto1, eto2, emr1->nSize);
1272         if (diff)
1273         {
1274             dump_EMREXTTEXTOUT(eto1);
1275             dump_EMREXTTEXTOUT(eto2);
1276         }
1277         HeapFree(GetProcessHeap(), 0, eto1);
1278         HeapFree(GetProcessHeap(), 0, eto2);
1279     }
1280     else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1281     {
1282         /* We have to take care of NT4 differences here */
1283         diff = memcmp(emr1, emr2, emr1->nSize);
1284         if (diff)
1285         {
1286             ENHMETARECORD *emr_nt4;
1287
1288             emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1289             memcpy(emr_nt4, emr2, emr2->nSize);
1290             /* Correct the nRgnSize field */
1291             emr_nt4->dParm[5] = sizeof(RECT);
1292
1293             diff = memcmp(emr1, emr_nt4, emr1->nSize);
1294             if (!diff)
1295                 win_skip("Catered for NT4 differences\n");
1296
1297             HeapFree(GetProcessHeap(), 0, emr_nt4);
1298         }
1299     }
1300     else
1301         diff = memcmp(emr1, emr2, emr1->nSize);
1302
1303     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1304
1305     if (diff)
1306     {
1307         dump_emf_record(emr1, "expected bits");
1308         dump_emf_record(emr2, "actual bits");
1309     }
1310
1311     return diff == 0; /* report all non-fatal record mismatches */
1312 }
1313
1314 /* Compare the EMF produced by a test function with the
1315  * expected raw EMF data in "bits".
1316  * Return value is 0 for a perfect match,
1317  * -1 if lengths aren't equal,
1318  * otherwise returns the number of non-matching bytes.
1319  */
1320 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1321                             UINT bsize, const char *desc,
1322                             BOOL ignore_scaling)
1323 {
1324     unsigned char buf[MF_BUFSIZE];
1325     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1326     const ENHMETAHEADER *emh1, *emh2;
1327
1328     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1329     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1330
1331     /* ENHMETAHEADER size could differ, depending on platform */
1332     diff_nt4 = sizeof(SIZEL);
1333     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1334
1335     if (mfsize < MF_BUFSIZE)
1336     {
1337         ok(mfsize == bsize ||
1338            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1339            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1340            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1341     }
1342     else
1343         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1344            desc, mfsize, bsize);
1345
1346     /* basic things must match */
1347     emh1 = (const ENHMETAHEADER *)bits;
1348     emh2 = (const ENHMETAHEADER *)buf;
1349     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1350     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1351     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1352     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1353
1354     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1355     ok(emh1->nSize == emh2->nSize ||
1356        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1357        broken(emh1->nSize - diff_9x == emh2->nSize),
1358        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1359     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1360     ok(emh1->nBytes == emh2->nBytes ||
1361        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1362        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1363        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1364     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1365
1366     offset1 = emh1->nSize;
1367     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1368     while (offset1 < emh1->nBytes)
1369     {
1370         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1371         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1372
1373         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1374               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1375
1376         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1377
1378         /* We have already bailed out if iType or nSize don't match */
1379         offset1 += emr1->nSize;
1380         offset2 += emr2->nSize;
1381     }
1382     return 0;
1383 }
1384
1385 /* Test a blank metafile.  May be used as a template for new tests. */
1386
1387 static void test_mf_Blank(void)
1388 {
1389     HDC hdcMetafile;
1390     HMETAFILE hMetafile;
1391     INT caps;
1392     BOOL ret;
1393     INT type;
1394
1395     hdcMetafile = CreateMetaFileA(NULL);
1396     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1397     trace("hdcMetafile %p\n", hdcMetafile);
1398
1399 /* Tests on metafile initialization */
1400     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1401     ok (caps == DT_METAFILE,
1402         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1403
1404     hMetafile = CloseMetaFile(hdcMetafile);
1405     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1406     type = GetObjectType(hMetafile);
1407     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1408     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1409
1410     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1411         "mf_blank") != 0)
1412     {
1413         dump_mf_bits(hMetafile, "mf_Blank");
1414         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1415     }
1416
1417     ret = DeleteMetaFile(hMetafile);
1418     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1419 }
1420
1421 static void test_CopyMetaFile(void)
1422 {
1423     HDC hdcMetafile;
1424     HMETAFILE hMetafile, hmf_copy;
1425     BOOL ret;
1426     char temp_path[MAX_PATH];
1427     char mf_name[MAX_PATH];
1428     INT type;
1429
1430     hdcMetafile = CreateMetaFileA(NULL);
1431     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1432     trace("hdcMetafile %p\n", hdcMetafile);
1433
1434     hMetafile = CloseMetaFile(hdcMetafile);
1435     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1436     type = GetObjectType(hMetafile);
1437     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1438
1439     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1440         "mf_blank") != 0)
1441     {
1442         dump_mf_bits(hMetafile, "mf_Blank");
1443         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1444     }
1445
1446     GetTempPathA(MAX_PATH, temp_path);
1447     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1448
1449     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1450     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1451
1452     type = GetObjectType(hmf_copy);
1453     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1454
1455     ret = DeleteMetaFile(hMetafile);
1456     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1457
1458     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1459     {
1460         dump_mf_bits(hmf_copy, "mf_Blank");
1461         EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1462     }
1463
1464     ret = DeleteMetaFile(hmf_copy);
1465     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1466
1467     DeleteFileA(mf_name);
1468 }
1469
1470 static void test_SetMetaFileBits(void)
1471 {
1472     HMETAFILE hmf;
1473     INT type;
1474     BOOL ret;
1475     BYTE buf[256];
1476     METAHEADER *mh;
1477
1478     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1479     trace("hmf %p\n", hmf);
1480     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1481     type = GetObjectType(hmf);
1482     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1483
1484     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1485     {
1486         dump_mf_bits(hmf, "mf_Graphics");
1487         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1488     }
1489
1490     ret = DeleteMetaFile(hmf);
1491     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1492
1493     /* NULL data crashes XP SP1 */
1494     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1495
1496     /* Now with zero size */
1497     SetLastError(0xdeadbeef);
1498     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1499     trace("hmf %p\n", hmf);
1500     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1501     ok(GetLastError() == ERROR_INVALID_DATA ||
1502        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1503        "wrong error %d\n", GetLastError());
1504
1505     /* Now with odd size */
1506     SetLastError(0xdeadbeef);
1507     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1508     trace("hmf %p\n", hmf);
1509     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1510     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1511
1512     /* Now with zeroed out header fields */
1513     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1514     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1515     mh = (METAHEADER *)buf;
1516     /* corruption of any of the below fields leads to a failure */
1517     mh->mtType = 0;
1518     mh->mtVersion = 0;
1519     mh->mtHeaderSize = 0;
1520     SetLastError(0xdeadbeef);
1521     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1522     trace("hmf %p\n", hmf);
1523     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1524     ok(GetLastError() == ERROR_INVALID_DATA ||
1525        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1526        "wrong error %d\n", GetLastError());
1527
1528     /* Now with corrupted mtSize field */
1529     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1530     mh = (METAHEADER *)buf;
1531     /* corruption of mtSize doesn't lead to a failure */
1532     mh->mtSize *= 2;
1533     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1534     trace("hmf %p\n", hmf);
1535     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1536
1537     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1538     {
1539         dump_mf_bits(hmf, "mf_Graphics");
1540         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1541     }
1542
1543     ret = DeleteMetaFile(hmf);
1544     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1545
1546     /* Now with zeroed out mtSize field */
1547     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1548     mh = (METAHEADER *)buf;
1549     /* zeroing mtSize doesn't lead to a failure */
1550     mh->mtSize = 0;
1551     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1552     trace("hmf %p\n", hmf);
1553     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1554
1555     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1556     {
1557         dump_mf_bits(hmf, "mf_Graphics");
1558         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1559     }
1560
1561     ret = DeleteMetaFile(hmf);
1562     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1563 }
1564
1565 /* Simple APIs from mfdrv/graphics.c
1566  */
1567
1568 static void test_mf_Graphics(void)
1569 {
1570     HDC hdcMetafile;
1571     HMETAFILE hMetafile;
1572     POINT oldpoint;
1573     BOOL ret;
1574
1575     hdcMetafile = CreateMetaFileA(NULL);
1576     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1577     trace("hdcMetafile %p\n", hdcMetafile);
1578
1579     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1580     ok( ret, "MoveToEx error %d.\n", GetLastError());
1581     ret = LineTo(hdcMetafile, 2, 2);
1582     ok( ret, "LineTo error %d.\n", GetLastError());
1583     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1584     ok( ret, "MoveToEx error %d.\n", GetLastError());
1585
1586 /* oldpoint gets garbage under Win XP, so the following test would
1587  * work under Wine but fails under Windows:
1588  *
1589  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1590  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1591  *       oldpoint.x, oldpoint.y);
1592  */
1593
1594     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1595     ok( ret, "Ellipse error %d.\n", GetLastError());
1596
1597     hMetafile = CloseMetaFile(hdcMetafile);
1598     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1599     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1600
1601     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1602         "mf_Graphics") != 0)
1603     {
1604         dump_mf_bits(hMetafile, "mf_Graphics");
1605         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1606     }
1607
1608     ret = DeleteMetaFile(hMetafile);
1609     ok( ret, "DeleteMetaFile(%p) error %d\n",
1610         hMetafile, GetLastError());
1611 }
1612
1613 static void test_mf_PatternBrush(void)
1614 {
1615     HDC hdcMetafile;
1616     HMETAFILE hMetafile;
1617     LOGBRUSH *orig_lb;
1618     HBRUSH hBrush;
1619     BOOL ret;
1620
1621     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1622
1623     orig_lb->lbStyle = BS_PATTERN;
1624     orig_lb->lbColor = RGB(0, 0, 0);
1625     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1626     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1627
1628     hBrush = CreateBrushIndirect (orig_lb);
1629     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1630
1631     hdcMetafile = CreateMetaFileA(NULL);
1632     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1633     trace("hdcMetafile %p\n", hdcMetafile);
1634
1635     hBrush = SelectObject(hdcMetafile, hBrush);
1636     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1637
1638     hMetafile = CloseMetaFile(hdcMetafile);
1639     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1640     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1641
1642     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1643         "mf_Pattern_Brush") != 0)
1644     {
1645         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1646         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1647     }
1648
1649     ret = DeleteMetaFile(hMetafile);
1650     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1651     ret = DeleteObject(hBrush);
1652     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1653     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1654     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1655         GetLastError());
1656     HeapFree (GetProcessHeap(), 0, orig_lb);
1657 }
1658
1659 static void test_mf_ExtTextOut_on_path(void)
1660 {
1661     HDC hdcMetafile;
1662     HMETAFILE hMetafile;
1663     BOOL ret;
1664     static const INT dx[4] = { 3, 5, 8, 12 };
1665
1666     hdcMetafile = CreateMetaFileA(NULL);
1667     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1668     trace("hdcMetafile %p\n", hdcMetafile);
1669
1670     ret = BeginPath(hdcMetafile);
1671     ok(!ret, "BeginPath on metafile DC should fail\n");
1672
1673     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1674     ok(ret, "ExtTextOut error %d\n", GetLastError());
1675
1676     ret = EndPath(hdcMetafile);
1677     ok(!ret, "EndPath on metafile DC should fail\n");
1678
1679     hMetafile = CloseMetaFile(hdcMetafile);
1680     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1681
1682     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1683         "mf_TextOut_on_path") != 0)
1684     {
1685         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1686         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1687     }
1688
1689     ret = DeleteMetaFile(hMetafile);
1690     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1691 }
1692
1693 static void test_emf_ExtTextOut_on_path(void)
1694 {
1695     HWND hwnd;
1696     HDC hdcDisplay, hdcMetafile;
1697     HENHMETAFILE hMetafile;
1698     BOOL ret;
1699     static const INT dx[4] = { 3, 5, 8, 12 };
1700
1701     /* Win9x doesn't play EMFs on invisible windows */
1702     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1703                            0, 0, 200, 200, 0, 0, 0, NULL);
1704     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1705
1706     hdcDisplay = GetDC(hwnd);
1707     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1708
1709     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1710     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1711
1712     ret = BeginPath(hdcMetafile);
1713     ok(ret, "BeginPath error %d\n", GetLastError());
1714
1715     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1716     ok(ret, "ExtTextOut error %d\n", GetLastError());
1717
1718     ret = EndPath(hdcMetafile);
1719     ok(ret, "EndPath error %d\n", GetLastError());
1720
1721     hMetafile = CloseEnhMetaFile(hdcMetafile);
1722     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1723
1724     /* this doesn't succeed yet: EMF has correct size, all EMF records
1725      * are there, but their contents don't match for different reasons.
1726      */
1727     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1728         "emf_TextOut_on_path", FALSE) != 0)
1729     {
1730         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1731         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1732     }
1733
1734     ret = DeleteEnhMetaFile(hMetafile);
1735     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1736     ret = ReleaseDC(hwnd, hdcDisplay);
1737     ok(ret, "ReleaseDC error %d\n", GetLastError());
1738     DestroyWindow(hwnd);
1739 }
1740
1741 static const unsigned char EMF_CLIPPING[] =
1742 {
1743     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1744     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1745     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1746     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1747     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1748     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1749     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1750     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1751     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1752     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1753     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1754     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1755     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1756     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1757     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1758     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1759     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1760     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1761     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1762     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1763     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1764     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1765     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1766     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1767     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1768     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1769 };
1770
1771 static void translate( POINT *pt, UINT count, const XFORM *xform )
1772 {
1773     while (count--)
1774     {
1775         FLOAT x = (FLOAT)pt->x;
1776         FLOAT y = (FLOAT)pt->y;
1777         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1778         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1779         pt++;
1780     }
1781 }
1782
1783 /* Compare rectangles allowing rounding errors */
1784 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1785 {
1786     return abs(rc1->left - rc2->left) <= 1 &&
1787            abs(rc1->top - rc2->top) <= 1 &&
1788            abs(rc1->right - rc2->right) <= 1 &&
1789            abs(rc1->bottom - rc2->bottom) <= 1;
1790 }
1791
1792 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1793                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1794 {
1795     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1796     {
1797         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1798         union _rgn
1799         {
1800             RGNDATA data;
1801             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1802         };
1803         const union _rgn *rgn1;
1804         union _rgn rgn2;
1805         RECT rect, rc_transformed;
1806         const RECT *rc = (const RECT *)param;
1807         HRGN hrgn;
1808         XFORM xform;
1809         INT ret;
1810         BOOL is_win9x;
1811
1812         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1813                clip->cbRgnData, clip->iMode);
1814
1815         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1816         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1817            "too small data block: %u bytes\n", clip->cbRgnData);
1818         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1819             return 0;
1820
1821         rgn1 = (const union _rgn *)clip->RgnData;
1822
1823         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1824               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1825               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1826               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1827               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1828
1829         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1830
1831         rect = *(const RECT *)rgn1->data.Buffer;
1832         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1833         ok(EqualRect(&rect, rc), "rects don't match\n");
1834
1835         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1836         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1837         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1838         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
1839            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
1840            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1841
1842         hrgn = CreateRectRgn(0, 0, 0, 0);
1843
1844         memset(&xform, 0, sizeof(xform));
1845         SetLastError(0xdeadbeef);
1846         ret = GetWorldTransform(hdc, &xform);
1847         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1848         if (!is_win9x)
1849             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1850
1851         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1852
1853         ret = GetClipRgn(hdc, hrgn);
1854         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1855
1856         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1857
1858         ret = GetClipRgn(hdc, hrgn);
1859         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
1860
1861         /* Win9x returns empty clipping region */
1862         if (is_win9x) return 1;
1863
1864         ret = GetRegionData(hrgn, 0, NULL);
1865         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1866
1867         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1868
1869         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1870               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1871               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1872               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1873               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1874
1875         rect = rgn2.data.rdh.rcBound;
1876         rc_transformed = *rc;
1877         translate((POINT *)&rc_transformed, 2, &xform);
1878         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1879               rc_transformed.right, rc_transformed.bottom);
1880         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1881
1882         rect = *(const RECT *)rgn2.data.Buffer;
1883         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1884         rc_transformed = *rc;
1885         translate((POINT *)&rc_transformed, 2, &xform);
1886         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1887               rc_transformed.right, rc_transformed.bottom);
1888         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1889
1890         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1891         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1892         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1893         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
1894            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
1895            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1896
1897         DeleteObject(hrgn);
1898     }
1899     return 1;
1900 }
1901
1902 static void test_emf_clipping(void)
1903 {
1904     static const RECT rc = { 0, 0, 100, 100 };
1905     RECT rc_clip = { 100, 100, 1024, 1024 };
1906     HWND hwnd;
1907     HDC hdc;
1908     HENHMETAFILE hemf;
1909     HRGN hrgn;
1910     INT ret;
1911
1912     SetLastError(0xdeadbeef);
1913     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1914     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1915
1916     /* Need to write something to the emf, otherwise Windows won't play it back */
1917     LineTo(hdc, 1, 1);
1918
1919     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1920     ret = SelectClipRgn(hdc, hrgn);
1921     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1922
1923     SetLastError(0xdeadbeef);
1924     hemf = CloseEnhMetaFile(hdc);
1925     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1926
1927     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1928         "emf_clipping", FALSE) != 0)
1929     {
1930         dump_emf_bits(hemf, "emf_clipping");
1931         dump_emf_records(hemf, "emf_clipping");
1932     }
1933
1934     DeleteObject(hrgn);
1935
1936     /* Win9x doesn't play EMFs on invisible windows */
1937     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1938                            0, 0, 200, 200, 0, 0, 0, NULL);
1939     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1940
1941     hdc = GetDC(hwnd);
1942
1943     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1944     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1945
1946     DeleteEnhMetaFile(hemf);
1947     ReleaseDC(hwnd, hdc);
1948     DestroyWindow(hwnd);
1949 }
1950
1951 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1952 {
1953     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1954     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1955     /* When using MM_TEXT Win9x does not update the mapping mode 
1956      * until a record is played which actually outputs something */
1957     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1958     LPtoDP(hdc, mapping, 2);
1959     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1960            lpEMFR->iType, lpEMFR->nSize,
1961            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1962
1963     if (lpEMFR->iType == EMR_LINETO)
1964     {
1965         INT x0, y0, x1, y1;
1966         if (!lpMFP || lpMFP->mm == MM_TEXT)
1967         {
1968             x0 = 0;
1969             y0 = 0;
1970             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1971             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1972         }
1973         else
1974         {
1975             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1976             
1977             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1978             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1979             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1980             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1981         }
1982         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1983             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1984             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1985             x0, y0, x1, y1);
1986     }
1987     return TRUE;
1988 }
1989
1990 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1991 {
1992     HDC hdcMf;
1993     HMETAFILE hmf;
1994     HENHMETAFILE hemf;
1995     BOOL ret;
1996     UINT size;
1997     LPBYTE pBits;
1998
1999     hdcMf = CreateMetaFile(NULL);
2000     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2001     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2002     ok(ret, "LineTo failed with error %d\n", GetLastError());
2003     hmf = CloseMetaFile(hdcMf);
2004     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2005
2006     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2007     {
2008         dump_mf_bits(hmf, "mf_LineTo");
2009         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2010     }
2011
2012     size = GetMetaFileBitsEx(hmf, 0, NULL);
2013     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2014     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2015     GetMetaFileBitsEx(hmf, size, pBits);
2016     DeleteMetaFile(hmf);
2017     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2018     HeapFree(GetProcessHeap(), 0, pBits);
2019     return hemf;
2020 }
2021
2022 static void test_mf_conversions(void)
2023 {
2024     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2025     {
2026         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2027         HENHMETAFILE hemf;
2028         METAFILEPICT mfp;
2029         RECT rect = { 0, 0, 100, 100 };
2030         mfp.mm = MM_ANISOTROPIC;
2031         mfp.xExt = 100;
2032         mfp.yExt = 100;
2033         mfp.hMF = NULL;
2034         hemf = create_converted_emf(&mfp);
2035
2036         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2037                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2038         {
2039             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2040             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2041         }
2042
2043         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2044
2045         DeleteEnhMetaFile(hemf);
2046         DeleteDC(hdcOffscreen);
2047     }
2048
2049     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2050     {
2051         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2052         HENHMETAFILE hemf;
2053         METAFILEPICT mfp;
2054         RECT rect = { 0, 0, 100, 100 };
2055         mfp.mm = MM_TEXT;
2056         mfp.xExt = 0;
2057         mfp.yExt = 0;
2058         mfp.hMF = NULL;
2059         hemf = create_converted_emf(&mfp);
2060
2061         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2062                              "emf_LineTo MM_TEXT", TRUE) != 0)
2063         {
2064             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2065             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2066         }
2067
2068         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2069
2070         DeleteEnhMetaFile(hemf);
2071         DeleteDC(hdcOffscreen);
2072     }
2073
2074     trace("Testing MF->EMF conversion (NULL mfp)\n");
2075     {
2076         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2077         HENHMETAFILE hemf;
2078         RECT rect = { 0, 0, 100, 100 };
2079         hemf = create_converted_emf(NULL);
2080
2081         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2082                              "emf_LineTo NULL", TRUE) != 0)
2083         {
2084             dump_emf_bits(hemf, "emf_LineTo NULL");
2085             dump_emf_records(hemf, "emf_LineTo NULL");
2086         }
2087
2088         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2089
2090         DeleteEnhMetaFile(hemf);
2091         DeleteDC(hdcOffscreen);
2092     }
2093 }
2094
2095 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2096                                        LONG mm, LONG xExt, LONG yExt,
2097                                        RECTL * rclBounds, RECTL * rclFrame)
2098 {
2099   METAFILEPICT mfp;
2100   METAFILEPICT * mfpPtr = NULL;
2101   HENHMETAFILE emf;
2102   ENHMETAHEADER header;
2103   UINT res;
2104
2105   if (!mfpIsNull)
2106   {
2107     mfp.mm = mm;
2108     mfp.xExt = xExt;
2109     mfp.yExt = yExt;
2110     mfpPtr = &mfp;
2111   }
2112
2113   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2114   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2115   if (!emf) return FALSE;
2116   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2117   ok(res != 0, "GetEnhMetaHeader failed\n");
2118   DeleteEnhMetaFile(emf);
2119   if (!res) return FALSE;
2120
2121   *rclBounds = header.rclBounds;
2122   *rclFrame = header.rclFrame;
2123   return TRUE;
2124 }
2125
2126 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2127                                          LONG mm, LONG xExt, LONG yExt,
2128                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2129 {
2130   RECTL rclBounds, rclFrame;
2131
2132   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2133   {
2134     const char * msg;
2135     char buf[64];
2136
2137     if (mfpIsNull)
2138     {
2139        msg = "mfp == NULL";
2140     }
2141     else
2142     {
2143       const char * mm_str;
2144       switch (mm)
2145       {
2146          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2147          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2148          default:             mm_str = "Unexpected";
2149       }
2150       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2151       msg = buf;
2152     }
2153
2154     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2155     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2156     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2157     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2158     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2159     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2160     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2161     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2162   }
2163 }
2164
2165 static void test_SetWinMetaFileBits(void)
2166 {
2167   HMETAFILE wmf;
2168   HDC wmfDC;
2169   BYTE * buffer;
2170   UINT buffer_size;
2171   RECT rect;
2172   UINT res;
2173   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2174   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2175   RECTL rclBounds, rclFrame;
2176   HDC dc;
2177   LONG diffx, diffy;
2178
2179   wmfDC = CreateMetaFile(NULL);
2180   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2181   if (!wmfDC) return;
2182
2183   SetWindowExtEx(wmfDC, 100, 100, NULL);
2184   rect.left = rect.top = 0;
2185   rect.right = rect.bottom = 50;
2186   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2187   wmf = CloseMetaFile(wmfDC);
2188   ok(wmf != NULL, "Metafile creation failed\n");
2189   if (!wmf) return;
2190
2191   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2192   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2193   if (buffer_size == 0)
2194   {
2195     DeleteMetaFile(wmf);
2196     return;
2197   }
2198
2199   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2200   ok(buffer != NULL, "HeapAlloc failed\n");
2201   if (!buffer)
2202   {
2203     DeleteMetaFile(wmf);
2204     return;
2205   }
2206
2207   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2208   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2209   DeleteMetaFile(wmf);
2210   if (res != buffer_size)
2211   {
2212      HeapFree(GetProcessHeap(), 0, buffer);
2213      return;
2214   }
2215
2216   /* Get the reference bounds and frame */
2217   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2218   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2219
2220   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2221      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2222      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2223
2224   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2225   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2226   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2227   if (diffx < 0) diffx = -diffx;
2228   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2229
2230   dc = CreateCompatibleDC(NULL);
2231
2232   /* Allow 1 mm difference (rounding errors) */
2233   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2234   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2235   if (diffx < 0) diffx = -diffx;
2236   if (diffy < 0) diffy = -diffy;
2237   todo_wine
2238   {
2239   ok(diffx <= 1 && diffy <= 1,
2240      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2241      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2242   }
2243
2244   /* Allow 1 mm difference (rounding errors) */
2245   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2246   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2247   if (diffx < 0) diffx = -diffx;
2248   if (diffy < 0) diffy = -diffy;
2249   todo_wine
2250   {
2251   ok(diffx <= 1 && diffy <= 1,
2252      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2253      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2254   }
2255   DeleteDC(dc);
2256
2257   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2258   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2259
2260   /* If xExt or yExt is zero or negative, the whole device surface is used */
2261   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2262   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2263   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2264   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2265   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2266   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2267   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2268   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2269   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2270   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2271   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2272   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2273
2274   /* MSDN says that negative xExt and yExt values specify a ratio.
2275      Check that this is wrong and the whole device surface is used */
2276   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2277   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2278
2279   /* Ordinary conversions */
2280
2281   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2282   {
2283     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2284        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2285     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2286        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2287   }
2288
2289   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2290   {
2291     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2292        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2293     ok(rclBounds.left == 0 && rclBounds.top == 0,
2294        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2295
2296     /* Wine has a rounding error */
2297     diffx = rclBounds.right - rclBounds.bottom;
2298     if (diffx < 0) diffx = -diffx;
2299     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2300   }
2301
2302   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2303   {
2304     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2305        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2306   }
2307
2308   HeapFree(GetProcessHeap(), 0, buffer);
2309 }
2310
2311 static void getwinmetafilebits(UINT mode, int scale)
2312 {
2313     HENHMETAFILE emf;
2314     HDC display_dc, emf_dc;
2315     RECT rc;
2316     ENHMETAHEADER *enh_header;
2317     UINT size, emf_size, i;
2318     WORD check = 0;
2319     DWORD rec_num = 0;
2320     METAHEADER *mh;
2321     METARECORD *rec;
2322     INT horz_res, vert_res, horz_size, vert_size;
2323
2324     display_dc = GetDC(NULL);
2325
2326     horz_res = GetDeviceCaps(display_dc, HORZRES);
2327     vert_res = GetDeviceCaps(display_dc, VERTRES);
2328     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2329     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2330
2331     SetRect(&rc, 1000, 2000, 3000, 6000);
2332     emf_dc = CreateEnhMetaFileA(display_dc, NULL, &rc, NULL);
2333     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2334         Rectangle(emf_dc, 0, 0, 1000, 20);
2335     emf = CloseEnhMetaFile(emf_dc);
2336
2337     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2338     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2339     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2340     DeleteEnhMetaFile(emf);
2341     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2342        have different resolutions */
2343     enh_header->szlDevice.cx *= scale;
2344     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2345
2346     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2347     ok(size, "GetWinMetaFileBits returns 0\n");
2348     mh = HeapAlloc(GetProcessHeap(), 0, size);
2349     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2350
2351     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2352     ok(check == 0, "check %04x\n", check);
2353
2354     rec = (METARECORD*)(mh + 1);
2355
2356     while(rec->rdSize && rec->rdFunction)
2357     {
2358         const DWORD chunk_size = 0x2000;
2359         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2360
2361         if(rec_num < mfcomment_chunks)
2362         {
2363             DWORD this_chunk_size = chunk_size;
2364
2365             if(rec_num == mfcomment_chunks - 1)
2366                 this_chunk_size = emf_size - rec_num * chunk_size;
2367
2368             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2369             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2370             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2371             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2372             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2373             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2374             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
2375             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2376             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2377             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2378             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2379             /* parm[8] is the checksum, tested above */
2380             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2381             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2382             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2383             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2384             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2385             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2386             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2387             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 */
2388             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2389             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2390         }
2391
2392         else if(rec_num == mfcomment_chunks)
2393         {
2394             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2395             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2396         }
2397         else if(rec_num == mfcomment_chunks + 1)
2398         {
2399             POINT pt;
2400             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2401             switch(mode)
2402             {
2403             case MM_TEXT:
2404             case MM_ISOTROPIC:
2405             case MM_ANISOTROPIC:
2406                 pt.y = MulDiv(rc.top, vert_res, vert_size * 100);
2407                 pt.x = MulDiv(rc.left, horz_res, horz_size * 100);
2408                 break;
2409             case MM_LOMETRIC:
2410                 pt.y = MulDiv(-rc.top, 1, 10) + 1;
2411                 pt.x = MulDiv(rc.left, 1, 10);
2412                 break;
2413             case MM_HIMETRIC:
2414                 pt.y = -rc.top + 1;
2415                 pt.x = rc.left;
2416                 break;
2417             case MM_LOENGLISH:
2418                 pt.y = MulDiv(-rc.top, 10, 254) + 1;
2419                 pt.x = MulDiv( rc.left, 10, 254);
2420                 break;
2421             case MM_HIENGLISH:
2422                 pt.y = MulDiv(-rc.top, 100, 254) + 1;
2423                 pt.x = MulDiv( rc.left, 100, 254);
2424                 break;
2425             case MM_TWIPS:
2426                 pt.y = MulDiv(-rc.top, 72 * 20, 2540) + 1;
2427                 pt.x = MulDiv( rc.left, 72 * 20, 2540);
2428                 break;
2429             default:
2430                 pt.x = pt.y = 0;
2431             }
2432             ok((short)rec->rdParm[0] == pt.y, "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2433             ok((short)rec->rdParm[1] == pt.x, "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2434         }
2435         if(rec_num == mfcomment_chunks + 2)
2436         {
2437             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2438             ok((short)rec->rdParm[0] == MulDiv(rc.bottom - rc.top, vert_res, vert_size * 100), "got %d\n", (short)rec->rdParm[0]);
2439             ok((short)rec->rdParm[1] == MulDiv(rc.right - rc.left, horz_res, horz_size * 100), "got %d\n", (short)rec->rdParm[1]);
2440         }
2441
2442         rec_num++;
2443         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2444     }
2445
2446     HeapFree(GetProcessHeap(), 0, mh);
2447     HeapFree(GetProcessHeap(), 0, enh_header);
2448     DeleteEnhMetaFile(emf);
2449
2450     ReleaseDC(NULL, display_dc);
2451 }
2452
2453 static void test_GetWinMetaFileBits(void)
2454 {
2455     UINT mode;
2456
2457     for(mode = MM_MIN; mode <= MM_MAX; mode++)
2458     {
2459         getwinmetafilebits(mode, 1);
2460         getwinmetafilebits(mode, 2);
2461     }
2462 }
2463
2464 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2465 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2466 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2467
2468 static void test_gdiis(void)
2469 {
2470     RECT rect = {0,0,100,100};
2471     HDC hdc, hemfDC, hmfDC;
2472     HENHMETAFILE hemf;
2473     HMODULE hgdi32;
2474
2475     /* resolve all the functions */
2476     hgdi32 = GetModuleHandle("gdi32");
2477     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2478     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2479     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2480
2481     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2482     {
2483         win_skip("Needed GdiIs* functions are not available\n");
2484         return;
2485     }
2486
2487     /* try with nothing */
2488     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2489     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2490     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2491
2492     /* try with a metafile */
2493     hmfDC = CreateMetaFile(NULL);
2494     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2495     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2496     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2497     DeleteMetaFile(CloseMetaFile(hmfDC));
2498
2499     /* try with an enhanced metafile */
2500     hdc = GetDC(NULL);
2501     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2502     ok(hemfDC != NULL, "failed to create emf\n");
2503
2504     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2505     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2506     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2507
2508     hemf = CloseEnhMetaFile(hemfDC);
2509     ok(hemf != NULL, "failed to close EMF\n");
2510     DeleteEnhMetaFile(hemf);
2511     ReleaseDC(NULL,hdc);
2512 }
2513
2514 static void test_SetEnhMetaFileBits(void)
2515 {
2516     BYTE data[256];
2517     HENHMETAFILE hemf;
2518     ENHMETAHEADER *emh;
2519
2520     memset(data, 0xAA, sizeof(data));
2521     SetLastError(0xdeadbeef);
2522     hemf = SetEnhMetaFileBits(sizeof(data), data);
2523     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2524     ok(GetLastError() == ERROR_INVALID_DATA ||
2525        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2526        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2527
2528     emh = (ENHMETAHEADER *)data;
2529     memset(emh, 0, sizeof(*emh));
2530
2531     emh->iType = EMR_HEADER;
2532     emh->nSize = sizeof(*emh);
2533     emh->dSignature = ENHMETA_SIGNATURE;
2534     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2535     emh->nBytes = sizeof(*emh);
2536     /* emh->nRecords = 1; XP doesn't care about records */
2537     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2538
2539     SetLastError(0xdeadbeef);
2540     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2541     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2542     DeleteEnhMetaFile(hemf);
2543
2544     /* XP refuses to load unaligned EMF */
2545     emh->nBytes++;
2546     SetLastError(0xdeadbeef);
2547     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2548     ok(!hemf ||
2549        broken(hemf != NULL), /* Win9x, WinMe */
2550        "SetEnhMetaFileBits should fail\n");
2551     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2552     DeleteEnhMetaFile(hemf);
2553
2554     emh->dSignature = 0;
2555     emh->nBytes--;
2556     SetLastError(0xdeadbeef);
2557     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2558     ok(!hemf ||
2559        broken(hemf != NULL), /* Win9x, WinMe */
2560        "SetEnhMetaFileBits should fail\n");
2561     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2562     DeleteEnhMetaFile(hemf);
2563 }
2564
2565 START_TEST(metafile)
2566 {
2567     init_function_pointers();
2568
2569     /* For enhanced metafiles (enhmfdrv) */
2570     test_ExtTextOut();
2571     test_SaveDC();
2572
2573     /* For win-format metafiles (mfdrv) */
2574     test_mf_SaveDC();
2575     test_mf_Blank();
2576     test_mf_Graphics();
2577     test_mf_PatternBrush();
2578     test_CopyMetaFile();
2579     test_SetMetaFileBits();
2580     test_mf_ExtTextOut_on_path();
2581     test_emf_ExtTextOut_on_path();
2582     test_emf_clipping();
2583
2584     /* For metafile conversions */
2585     test_mf_conversions();
2586     test_SetWinMetaFileBits();
2587     test_GetWinMetaFileBits();
2588
2589     test_gdiis();
2590     test_SetEnhMetaFileBits();
2591 }