gdi32: Add tests for the map mode and window size records.
[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     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1480     type = GetObjectType(hmf);
1481     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1482
1483     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1484     {
1485         dump_mf_bits(hmf, "mf_Graphics");
1486         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1487     }
1488
1489     ret = DeleteMetaFile(hmf);
1490     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1491
1492     /* NULL data crashes XP SP1 */
1493     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1494
1495     /* Now with not zero size */
1496     SetLastError(0xdeadbeef);
1497     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1498     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1499     ok(GetLastError() == ERROR_INVALID_DATA ||
1500        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1501        "wrong error %d\n", GetLastError());
1502
1503     /* Now with not even size */
1504     SetLastError(0xdeadbeef);
1505     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1506     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1507     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1508
1509     /* Now with zeroed out or faked some header fields */
1510     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1511     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1512     mh = (METAHEADER *)buf;
1513     /* corruption of any of the below fields leads to a failure */
1514     mh->mtType = 0;
1515     mh->mtVersion = 0;
1516     mh->mtHeaderSize = 0;
1517     SetLastError(0xdeadbeef);
1518     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1519     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1520     ok(GetLastError() == ERROR_INVALID_DATA ||
1521        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1522        "wrong error %d\n", GetLastError());
1523
1524     /* Now with corrupted mtSize field */
1525     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1526     mh = (METAHEADER *)buf;
1527     /* corruption of mtSize doesn't lead to a failure */
1528     mh->mtSize *= 2;
1529     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1530     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1531
1532     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1533     {
1534         dump_mf_bits(hmf, "mf_Graphics");
1535         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1536     }
1537
1538     ret = DeleteMetaFile(hmf);
1539     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1540
1541     /* Now with zeroed out mtSize field */
1542     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1543     mh = (METAHEADER *)buf;
1544     /* zeroing mtSize doesn't lead to a failure */
1545     mh->mtSize = 0;
1546     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1547     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1548
1549     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1550     {
1551         dump_mf_bits(hmf, "mf_Graphics");
1552         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1553     }
1554
1555     ret = DeleteMetaFile(hmf);
1556     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1557 }
1558
1559 /* Simple APIs from mfdrv/graphics.c
1560  */
1561
1562 static void test_mf_Graphics(void)
1563 {
1564     HDC hdcMetafile;
1565     HMETAFILE hMetafile;
1566     POINT oldpoint;
1567     BOOL ret;
1568
1569     hdcMetafile = CreateMetaFileA(NULL);
1570     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1571     trace("hdcMetafile %p\n", hdcMetafile);
1572
1573     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1574     ok( ret, "MoveToEx error %d.\n", GetLastError());
1575     ret = LineTo(hdcMetafile, 2, 2);
1576     ok( ret, "LineTo error %d.\n", GetLastError());
1577     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1578     ok( ret, "MoveToEx error %d.\n", GetLastError());
1579
1580 /* oldpoint gets garbage under Win XP, so the following test would
1581  * work under Wine but fails under Windows:
1582  *
1583  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1584  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1585  *       oldpoint.x, oldpoint.y);
1586  */
1587
1588     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1589     ok( ret, "Ellipse error %d.\n", GetLastError());
1590
1591     hMetafile = CloseMetaFile(hdcMetafile);
1592     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1593     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1594
1595     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1596         "mf_Graphics") != 0)
1597     {
1598         dump_mf_bits(hMetafile, "mf_Graphics");
1599         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1600     }
1601
1602     ret = DeleteMetaFile(hMetafile);
1603     ok( ret, "DeleteMetaFile(%p) error %d\n",
1604         hMetafile, GetLastError());
1605 }
1606
1607 static void test_mf_PatternBrush(void)
1608 {
1609     HDC hdcMetafile;
1610     HMETAFILE hMetafile;
1611     LOGBRUSH *orig_lb;
1612     HBRUSH hBrush;
1613     BOOL ret;
1614
1615     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1616
1617     orig_lb->lbStyle = BS_PATTERN;
1618     orig_lb->lbColor = RGB(0, 0, 0);
1619     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1620     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1621
1622     hBrush = CreateBrushIndirect (orig_lb);
1623     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1624
1625     hdcMetafile = CreateMetaFileA(NULL);
1626     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1627     trace("hdcMetafile %p\n", hdcMetafile);
1628
1629     hBrush = SelectObject(hdcMetafile, hBrush);
1630     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1631
1632     hMetafile = CloseMetaFile(hdcMetafile);
1633     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1634     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1635
1636     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1637         "mf_Pattern_Brush") != 0)
1638     {
1639         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1640         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1641     }
1642
1643     ret = DeleteMetaFile(hMetafile);
1644     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1645     ret = DeleteObject(hBrush);
1646     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1647     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1648     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1649         GetLastError());
1650     HeapFree (GetProcessHeap(), 0, orig_lb);
1651 }
1652
1653 static void test_mf_ExtTextOut_on_path(void)
1654 {
1655     HDC hdcMetafile;
1656     HMETAFILE hMetafile;
1657     BOOL ret;
1658     static const INT dx[4] = { 3, 5, 8, 12 };
1659
1660     hdcMetafile = CreateMetaFileA(NULL);
1661     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1662     trace("hdcMetafile %p\n", hdcMetafile);
1663
1664     ret = BeginPath(hdcMetafile);
1665     ok(!ret, "BeginPath on metafile DC should fail\n");
1666
1667     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1668     ok(ret, "ExtTextOut error %d\n", GetLastError());
1669
1670     ret = EndPath(hdcMetafile);
1671     ok(!ret, "EndPath on metafile DC should fail\n");
1672
1673     hMetafile = CloseMetaFile(hdcMetafile);
1674     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1675
1676     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1677         "mf_TextOut_on_path") != 0)
1678     {
1679         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1680         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1681     }
1682
1683     ret = DeleteMetaFile(hMetafile);
1684     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1685 }
1686
1687 static void test_emf_ExtTextOut_on_path(void)
1688 {
1689     HWND hwnd;
1690     HDC hdcDisplay, hdcMetafile;
1691     HENHMETAFILE hMetafile;
1692     BOOL ret;
1693     static const INT dx[4] = { 3, 5, 8, 12 };
1694
1695     /* Win9x doesn't play EMFs on invisible windows */
1696     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1697                            0, 0, 200, 200, 0, 0, 0, NULL);
1698     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1699
1700     hdcDisplay = GetDC(hwnd);
1701     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1702
1703     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1704     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1705
1706     ret = BeginPath(hdcMetafile);
1707     ok(ret, "BeginPath error %d\n", GetLastError());
1708
1709     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1710     ok(ret, "ExtTextOut error %d\n", GetLastError());
1711
1712     ret = EndPath(hdcMetafile);
1713     ok(ret, "EndPath error %d\n", GetLastError());
1714
1715     hMetafile = CloseEnhMetaFile(hdcMetafile);
1716     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1717
1718     /* this doesn't succeed yet: EMF has correct size, all EMF records
1719      * are there, but their contents don't match for different reasons.
1720      */
1721     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1722         "emf_TextOut_on_path", FALSE) != 0)
1723     {
1724         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1725         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1726     }
1727
1728     ret = DeleteEnhMetaFile(hMetafile);
1729     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1730     ret = ReleaseDC(hwnd, hdcDisplay);
1731     ok(ret, "ReleaseDC error %d\n", GetLastError());
1732     DestroyWindow(hwnd);
1733 }
1734
1735 static const unsigned char EMF_CLIPPING[] =
1736 {
1737     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1738     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1739     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1740     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1741     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1742     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1743     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1744     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1745     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1746     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1747     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1748     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1749     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1750     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1751     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1752     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1753     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1754     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1755     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1756     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1757     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1758     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1759     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1760     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1761     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1762     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1763 };
1764
1765 static void translate( POINT *pt, UINT count, const XFORM *xform )
1766 {
1767     while (count--)
1768     {
1769         FLOAT x = (FLOAT)pt->x;
1770         FLOAT y = (FLOAT)pt->y;
1771         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1772         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1773         pt++;
1774     }
1775 }
1776
1777 /* Compare rectangles allowing rounding errors */
1778 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1779 {
1780     return abs(rc1->left - rc2->left) <= 1 &&
1781            abs(rc1->top - rc2->top) <= 1 &&
1782            abs(rc1->right - rc2->right) <= 1 &&
1783            abs(rc1->bottom - rc2->bottom) <= 1;
1784 }
1785
1786 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1787                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1788 {
1789     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1790     {
1791         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1792         union _rgn
1793         {
1794             RGNDATA data;
1795             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1796         };
1797         const union _rgn *rgn1;
1798         union _rgn rgn2;
1799         RECT rect, rc_transformed;
1800         const RECT *rc = (const RECT *)param;
1801         HRGN hrgn;
1802         XFORM xform;
1803         INT ret;
1804         BOOL is_win9x;
1805
1806         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1807                clip->cbRgnData, clip->iMode);
1808
1809         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1810         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1811            "too small data block: %u bytes\n", clip->cbRgnData);
1812         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1813             return 0;
1814
1815         rgn1 = (const union _rgn *)clip->RgnData;
1816
1817         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1818               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1819               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1820               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1821               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1822
1823         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1824
1825         rect = *(const RECT *)rgn1->data.Buffer;
1826         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1827         ok(EqualRect(&rect, rc), "rects don't match\n");
1828
1829         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1830         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1831         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1832         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
1833            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
1834            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1835
1836         hrgn = CreateRectRgn(0, 0, 0, 0);
1837
1838         memset(&xform, 0, sizeof(xform));
1839         SetLastError(0xdeadbeef);
1840         ret = GetWorldTransform(hdc, &xform);
1841         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1842         if (!is_win9x)
1843             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1844
1845         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1846
1847         ret = GetClipRgn(hdc, hrgn);
1848         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1849
1850         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1851
1852         ret = GetClipRgn(hdc, hrgn);
1853         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
1854
1855         /* Win9x returns empty clipping region */
1856         if (is_win9x) return 1;
1857
1858         ret = GetRegionData(hrgn, 0, NULL);
1859         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1860
1861         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1862
1863         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1864               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1865               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1866               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1867               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1868
1869         rect = rgn2.data.rdh.rcBound;
1870         rc_transformed = *rc;
1871         translate((POINT *)&rc_transformed, 2, &xform);
1872         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1873               rc_transformed.right, rc_transformed.bottom);
1874         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1875
1876         rect = *(const RECT *)rgn2.data.Buffer;
1877         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1878         rc_transformed = *rc;
1879         translate((POINT *)&rc_transformed, 2, &xform);
1880         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1881               rc_transformed.right, rc_transformed.bottom);
1882         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1883
1884         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1885         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1886         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1887         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
1888            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
1889            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1890
1891         DeleteObject(hrgn);
1892     }
1893     return 1;
1894 }
1895
1896 static void test_emf_clipping(void)
1897 {
1898     static const RECT rc = { 0, 0, 100, 100 };
1899     RECT rc_clip = { 100, 100, 1024, 1024 };
1900     HWND hwnd;
1901     HDC hdc;
1902     HENHMETAFILE hemf;
1903     HRGN hrgn;
1904     INT ret;
1905
1906     SetLastError(0xdeadbeef);
1907     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1908     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1909
1910     /* Need to write something to the emf, otherwise Windows won't play it back */
1911     LineTo(hdc, 1, 1);
1912
1913     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1914     ret = SelectClipRgn(hdc, hrgn);
1915     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1916
1917     SetLastError(0xdeadbeef);
1918     hemf = CloseEnhMetaFile(hdc);
1919     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1920
1921     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1922         "emf_clipping", FALSE) != 0)
1923     {
1924         dump_emf_bits(hemf, "emf_clipping");
1925         dump_emf_records(hemf, "emf_clipping");
1926     }
1927
1928     DeleteObject(hrgn);
1929
1930     /* Win9x doesn't play EMFs on invisible windows */
1931     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1932                            0, 0, 200, 200, 0, 0, 0, NULL);
1933     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1934
1935     hdc = GetDC(hwnd);
1936
1937     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1938     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1939
1940     DeleteEnhMetaFile(hemf);
1941     ReleaseDC(hwnd, hdc);
1942     DestroyWindow(hwnd);
1943 }
1944
1945 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1946 {
1947     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1948     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1949     /* When using MM_TEXT Win9x does not update the mapping mode 
1950      * until a record is played which actually outputs something */
1951     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1952     LPtoDP(hdc, mapping, 2);
1953     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1954            lpEMFR->iType, lpEMFR->nSize,
1955            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1956
1957     if (lpEMFR->iType == EMR_LINETO)
1958     {
1959         INT x0, y0, x1, y1;
1960         if (!lpMFP || lpMFP->mm == MM_TEXT)
1961         {
1962             x0 = 0;
1963             y0 = 0;
1964             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1965             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1966         }
1967         else
1968         {
1969             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1970             
1971             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1972             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1973             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1974             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1975         }
1976         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1977             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1978             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1979             x0, y0, x1, y1);
1980     }
1981     return TRUE;
1982 }
1983
1984 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1985 {
1986     HDC hdcMf;
1987     HMETAFILE hmf;
1988     HENHMETAFILE hemf;
1989     BOOL ret;
1990     UINT size;
1991     LPBYTE pBits;
1992
1993     hdcMf = CreateMetaFile(NULL);
1994     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1995     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1996     ok(ret, "LineTo failed with error %d\n", GetLastError());
1997     hmf = CloseMetaFile(hdcMf);
1998     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1999
2000     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2001     {
2002         dump_mf_bits(hmf, "mf_LineTo");
2003         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2004     }
2005
2006     size = GetMetaFileBitsEx(hmf, 0, NULL);
2007     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2008     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2009     GetMetaFileBitsEx(hmf, size, pBits);
2010     DeleteMetaFile(hmf);
2011     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2012     HeapFree(GetProcessHeap(), 0, pBits);
2013     return hemf;
2014 }
2015
2016 static void test_mf_conversions(void)
2017 {
2018     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2019     {
2020         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2021         HENHMETAFILE hemf;
2022         METAFILEPICT mfp;
2023         RECT rect = { 0, 0, 100, 100 };
2024         mfp.mm = MM_ANISOTROPIC;
2025         mfp.xExt = 100;
2026         mfp.yExt = 100;
2027         mfp.hMF = NULL;
2028         hemf = create_converted_emf(&mfp);
2029
2030         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2031                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2032         {
2033             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2034             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2035         }
2036
2037         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2038
2039         DeleteEnhMetaFile(hemf);
2040         DeleteDC(hdcOffscreen);
2041     }
2042
2043     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2044     {
2045         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2046         HENHMETAFILE hemf;
2047         METAFILEPICT mfp;
2048         RECT rect = { 0, 0, 100, 100 };
2049         mfp.mm = MM_TEXT;
2050         mfp.xExt = 0;
2051         mfp.yExt = 0;
2052         mfp.hMF = NULL;
2053         hemf = create_converted_emf(&mfp);
2054
2055         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2056                              "emf_LineTo MM_TEXT", TRUE) != 0)
2057         {
2058             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2059             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2060         }
2061
2062         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2063
2064         DeleteEnhMetaFile(hemf);
2065         DeleteDC(hdcOffscreen);
2066     }
2067
2068     trace("Testing MF->EMF conversion (NULL mfp)\n");
2069     {
2070         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2071         HENHMETAFILE hemf;
2072         RECT rect = { 0, 0, 100, 100 };
2073         hemf = create_converted_emf(NULL);
2074
2075         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2076                              "emf_LineTo NULL", TRUE) != 0)
2077         {
2078             dump_emf_bits(hemf, "emf_LineTo NULL");
2079             dump_emf_records(hemf, "emf_LineTo NULL");
2080         }
2081
2082         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2083
2084         DeleteEnhMetaFile(hemf);
2085         DeleteDC(hdcOffscreen);
2086     }
2087 }
2088
2089 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2090                                        LONG mm, LONG xExt, LONG yExt,
2091                                        RECTL * rclBounds, RECTL * rclFrame)
2092 {
2093   METAFILEPICT mfp;
2094   METAFILEPICT * mfpPtr = NULL;
2095   HENHMETAFILE emf;
2096   ENHMETAHEADER header;
2097   UINT res;
2098
2099   if (!mfpIsNull)
2100   {
2101     mfp.mm = mm;
2102     mfp.xExt = xExt;
2103     mfp.yExt = yExt;
2104     mfpPtr = &mfp;
2105   }
2106
2107   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2108   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2109   if (!emf) return FALSE;
2110   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2111   ok(res != 0, "GetEnhMetaHeader failed\n");
2112   DeleteEnhMetaFile(emf);
2113   if (!res) return FALSE;
2114
2115   *rclBounds = header.rclBounds;
2116   *rclFrame = header.rclFrame;
2117   return TRUE;
2118 }
2119
2120 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2121                                          LONG mm, LONG xExt, LONG yExt,
2122                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2123 {
2124   RECTL rclBounds, rclFrame;
2125
2126   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2127   {
2128     const char * msg;
2129     char buf[64];
2130
2131     if (mfpIsNull)
2132     {
2133        msg = "mfp == NULL";
2134     }
2135     else
2136     {
2137       const char * mm_str;
2138       switch (mm)
2139       {
2140          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2141          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2142          default:             mm_str = "Unexpected";
2143       }
2144       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2145       msg = buf;
2146     }
2147
2148     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2149     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2150     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2151     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2152     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2153     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2154     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2155     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2156   }
2157 }
2158
2159 static void test_SetWinMetaFileBits(void)
2160 {
2161   HMETAFILE wmf;
2162   HDC wmfDC;
2163   BYTE * buffer;
2164   UINT buffer_size;
2165   RECT rect;
2166   UINT res;
2167   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2168   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2169   RECTL rclBounds, rclFrame;
2170   HDC dc;
2171   LONG diffx, diffy;
2172
2173   wmfDC = CreateMetaFile(NULL);
2174   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2175   if (!wmfDC) return;
2176
2177   SetWindowExtEx(wmfDC, 100, 100, NULL);
2178   rect.left = rect.top = 0;
2179   rect.right = rect.bottom = 50;
2180   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2181   wmf = CloseMetaFile(wmfDC);
2182   ok(wmf != NULL, "Metafile creation failed\n");
2183   if (!wmf) return;
2184
2185   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2186   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2187   if (buffer_size == 0)
2188   {
2189     DeleteMetaFile(wmf);
2190     return;
2191   }
2192
2193   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2194   ok(buffer != NULL, "HeapAlloc failed\n");
2195   if (!buffer)
2196   {
2197     DeleteMetaFile(wmf);
2198     return;
2199   }
2200
2201   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2202   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2203   DeleteMetaFile(wmf);
2204   if (res != buffer_size)
2205   {
2206      HeapFree(GetProcessHeap(), 0, buffer);
2207      return;
2208   }
2209
2210   /* Get the reference bounds and frame */
2211   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2212   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2213
2214   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2215      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2216      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2217
2218   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2219   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2220   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2221   if (diffx < 0) diffx = -diffx;
2222   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2223
2224   dc = CreateCompatibleDC(NULL);
2225
2226   /* Allow 1 mm difference (rounding errors) */
2227   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2228   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2229   if (diffx < 0) diffx = -diffx;
2230   if (diffy < 0) diffy = -diffy;
2231   todo_wine
2232   {
2233   ok(diffx <= 1 && diffy <= 1,
2234      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2235      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2236   }
2237
2238   /* Allow 1 mm difference (rounding errors) */
2239   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2240   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2241   if (diffx < 0) diffx = -diffx;
2242   if (diffy < 0) diffy = -diffy;
2243   todo_wine
2244   {
2245   ok(diffx <= 1 && diffy <= 1,
2246      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2247      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2248   }
2249   DeleteDC(dc);
2250
2251   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2252   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2253
2254   /* If xExt or yExt is zero or negative, the whole device surface is used */
2255   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2256   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2257   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2258   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2259   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2260   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2261   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2262   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2263   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2264   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2265   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2266   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2267
2268   /* MSDN says that negative xExt and yExt values specify a ratio.
2269      Check that this is wrong and the whole device surface is used */
2270   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2271   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2272
2273   /* Ordinary conversions */
2274
2275   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2276   {
2277     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2278        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2279     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2280        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2281   }
2282
2283   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2284   {
2285     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2286        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2287     ok(rclBounds.left == 0 && rclBounds.top == 0,
2288        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2289
2290     /* Wine has a rounding error */
2291     diffx = rclBounds.right - rclBounds.bottom;
2292     if (diffx < 0) diffx = -diffx;
2293     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2294   }
2295
2296   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2297   {
2298     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2299        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2300   }
2301
2302   HeapFree(GetProcessHeap(), 0, buffer);
2303 }
2304
2305 static void getwinmetafilebits(UINT mode, int scale)
2306 {
2307     HENHMETAFILE emf;
2308     HDC display_dc, emf_dc;
2309     RECT rc;
2310     ENHMETAHEADER *enh_header;
2311     UINT size, emf_size, i;
2312     WORD check = 0;
2313     DWORD rec_num = 0;
2314     METAHEADER *mh;
2315     METARECORD *rec;
2316     INT horz_res, vert_res, horz_size, vert_size;
2317
2318     display_dc = GetDC(NULL);
2319
2320     horz_res = GetDeviceCaps(display_dc, HORZRES);
2321     vert_res = GetDeviceCaps(display_dc, VERTRES);
2322     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2323     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2324
2325     SetRect(&rc, 1000, 2000, 3000, 6000);
2326     emf_dc = CreateEnhMetaFileA(display_dc, NULL, &rc, NULL);
2327     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2328         Rectangle(emf_dc, 0, 0, 1000, 20);
2329     emf = CloseEnhMetaFile(emf_dc);
2330
2331     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2332     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2333     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2334     DeleteEnhMetaFile(emf);
2335     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2336        have different resolutions */
2337     enh_header->szlDevice.cx *= scale;
2338     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2339
2340     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2341     ok(size, "GetWinMetaFileBits returns 0\n");
2342     mh = HeapAlloc(GetProcessHeap(), 0, size);
2343     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2344
2345     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2346     ok(check == 0, "check %04x\n", check);
2347
2348     rec = (METARECORD*)(mh + 1);
2349
2350     while(rec->rdSize && rec->rdFunction)
2351     {
2352         const DWORD chunk_size = 0x2000;
2353         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2354
2355         if(rec_num < mfcomment_chunks)
2356         {
2357             DWORD this_chunk_size = chunk_size;
2358
2359             if(rec_num == mfcomment_chunks - 1)
2360                 this_chunk_size = emf_size - rec_num * chunk_size;
2361
2362             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2363             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2364             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2365             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2366             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2367             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2368             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
2369             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2370             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2371             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2372             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2373             /* parm[8] is the checksum, tested above */
2374             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2375             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2376             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2377             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2378             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2379             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2380             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2381             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 */
2382             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2383             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2384         }
2385
2386         else if(rec_num == mfcomment_chunks)
2387         {
2388             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2389             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2390         }
2391         else if(rec_num == mfcomment_chunks + 1)
2392         {
2393             POINT pt;
2394             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2395             switch(mode)
2396             {
2397             case MM_TEXT:
2398             case MM_ISOTROPIC:
2399             case MM_ANISOTROPIC:
2400                 pt.y = MulDiv(rc.top, vert_res, vert_size * 100);
2401                 pt.x = MulDiv(rc.left, horz_res, horz_size * 100);
2402                 break;
2403             case MM_LOMETRIC:
2404                 pt.y = MulDiv(-rc.top, 1, 10) + 1;
2405                 pt.x = MulDiv(rc.left, 1, 10);
2406                 break;
2407             case MM_HIMETRIC:
2408                 pt.y = -rc.top + 1;
2409                 pt.x = rc.left;
2410                 break;
2411             case MM_LOENGLISH:
2412                 pt.y = MulDiv(-rc.top, 10, 254) + 1;
2413                 pt.x = MulDiv( rc.left, 10, 254);
2414                 break;
2415             case MM_HIENGLISH:
2416                 pt.y = MulDiv(-rc.top, 100, 254) + 1;
2417                 pt.x = MulDiv( rc.left, 100, 254);
2418                 break;
2419             case MM_TWIPS:
2420                 pt.y = MulDiv(-rc.top, 72 * 20, 2540) + 1;
2421                 pt.x = MulDiv( rc.left, 72 * 20, 2540);
2422                 break;
2423             default:
2424                 pt.x = pt.y = 0;
2425             }
2426             ok((short)rec->rdParm[0] == pt.y, "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2427             ok((short)rec->rdParm[1] == pt.x, "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2428         }
2429         if(rec_num == mfcomment_chunks + 2)
2430         {
2431             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2432             ok((short)rec->rdParm[0] == MulDiv(rc.bottom - rc.top, vert_res, vert_size * 100), "got %d\n", (short)rec->rdParm[0]);
2433             ok((short)rec->rdParm[1] == MulDiv(rc.right - rc.left, horz_res, horz_size * 100), "got %d\n", (short)rec->rdParm[1]);
2434         }
2435
2436         rec_num++;
2437         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2438     }
2439
2440     HeapFree(GetProcessHeap(), 0, mh);
2441     HeapFree(GetProcessHeap(), 0, enh_header);
2442     DeleteEnhMetaFile(emf);
2443
2444     ReleaseDC(NULL, display_dc);
2445 }
2446
2447 static void test_GetWinMetaFileBits(void)
2448 {
2449     UINT mode;
2450
2451     for(mode = MM_MIN; mode <= MM_MAX; mode++)
2452     {
2453         getwinmetafilebits(mode, 1);
2454         getwinmetafilebits(mode, 2);
2455     }
2456 }
2457
2458 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2459 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2460 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2461
2462 static void test_gdiis(void)
2463 {
2464     RECT rect = {0,0,100,100};
2465     HDC hdc, hemfDC, hmfDC;
2466     HENHMETAFILE hemf;
2467     HMODULE hgdi32;
2468
2469     /* resolve all the functions */
2470     hgdi32 = GetModuleHandle("gdi32");
2471     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2472     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2473     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2474
2475     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2476     {
2477         win_skip("Needed GdiIs* functions are not available\n");
2478         return;
2479     }
2480
2481     /* try with nothing */
2482     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2483     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2484     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2485
2486     /* try with a metafile */
2487     hmfDC = CreateMetaFile(NULL);
2488     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2489     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2490     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2491     DeleteMetaFile(CloseMetaFile(hmfDC));
2492
2493     /* try with an enhanced metafile */
2494     hdc = GetDC(NULL);
2495     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2496     ok(hemfDC != NULL, "failed to create emf\n");
2497
2498     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2499     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2500     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2501
2502     hemf = CloseEnhMetaFile(hemfDC);
2503     ok(hemf != NULL, "failed to close EMF\n");
2504     DeleteEnhMetaFile(hemf);
2505     ReleaseDC(NULL,hdc);
2506 }
2507
2508 static void test_SetEnhMetaFileBits(void)
2509 {
2510     BYTE data[256];
2511     HENHMETAFILE hemf;
2512     ENHMETAHEADER *emh;
2513
2514     memset(data, 0xAA, sizeof(data));
2515     SetLastError(0xdeadbeef);
2516     hemf = SetEnhMetaFileBits(sizeof(data), data);
2517     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2518     ok(GetLastError() == ERROR_INVALID_DATA ||
2519        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2520        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2521
2522     emh = (ENHMETAHEADER *)data;
2523     memset(emh, 0, sizeof(*emh));
2524
2525     emh->iType = EMR_HEADER;
2526     emh->nSize = sizeof(*emh);
2527     emh->dSignature = ENHMETA_SIGNATURE;
2528     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2529     emh->nBytes = sizeof(*emh);
2530     /* emh->nRecords = 1; XP doesn't care about records */
2531     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2532
2533     SetLastError(0xdeadbeef);
2534     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2535     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2536     DeleteEnhMetaFile(hemf);
2537
2538     /* XP refuses to load unaligned EMF */
2539     emh->nBytes++;
2540     SetLastError(0xdeadbeef);
2541     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2542     ok(!hemf ||
2543        broken(hemf != NULL), /* Win9x, WinMe */
2544        "SetEnhMetaFileBits should fail\n");
2545     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2546     DeleteEnhMetaFile(hemf);
2547
2548     emh->dSignature = 0;
2549     emh->nBytes--;
2550     SetLastError(0xdeadbeef);
2551     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2552     ok(!hemf ||
2553        broken(hemf != NULL), /* Win9x, WinMe */
2554        "SetEnhMetaFileBits should fail\n");
2555     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2556     DeleteEnhMetaFile(hemf);
2557 }
2558
2559 START_TEST(metafile)
2560 {
2561     init_function_pointers();
2562
2563     /* For enhanced metafiles (enhmfdrv) */
2564     test_ExtTextOut();
2565     test_SaveDC();
2566
2567     /* For win-format metafiles (mfdrv) */
2568     test_mf_SaveDC();
2569     test_mf_Blank();
2570     test_mf_Graphics();
2571     test_mf_PatternBrush();
2572     test_CopyMetaFile();
2573     test_SetMetaFileBits();
2574     test_mf_ExtTextOut_on_path();
2575     test_emf_ExtTextOut_on_path();
2576     test_emf_clipping();
2577
2578     /* For metafile conversions */
2579     test_mf_conversions();
2580     test_SetWinMetaFileBits();
2581     test_GetWinMetaFileBits();
2582
2583     test_gdiis();
2584     test_SetEnhMetaFileBits();
2585 }