crypt32: Constify some variables.
[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
1281         diff = memcmp(emr1, emr2, emr1->nSize);
1282
1283     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1284
1285     if (diff)
1286     {
1287         dump_emf_record(emr1, "expected bits");
1288         dump_emf_record(emr2, "actual bits");
1289     }
1290
1291     return diff == 0; /* report all non-fatal record mismatches */
1292 }
1293
1294 /* Compare the EMF produced by a test function with the
1295  * expected raw EMF data in "bits".
1296  * Return value is 0 for a perfect match,
1297  * -1 if lengths aren't equal,
1298  * otherwise returns the number of non-matching bytes.
1299  */
1300 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1301                             UINT bsize, const char *desc,
1302                             BOOL ignore_scaling)
1303 {
1304     unsigned char buf[MF_BUFSIZE];
1305     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1306     const ENHMETAHEADER *emh1, *emh2;
1307
1308     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1309     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1310
1311     /* ENHMETAHEADER size could differ, depending on platform */
1312     diff_nt4 = sizeof(SIZEL);
1313     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1314
1315     if (mfsize < MF_BUFSIZE)
1316     {
1317         ok(mfsize == bsize ||
1318            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1319            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1320            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1321     }
1322     else
1323         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1324            desc, mfsize, bsize);
1325
1326     /* basic things must match */
1327     emh1 = (const ENHMETAHEADER *)bits;
1328     emh2 = (const ENHMETAHEADER *)buf;
1329     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1330     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1331     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1332     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1333
1334     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1335     ok(emh1->nSize == emh2->nSize ||
1336        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1337        broken(emh1->nSize - diff_9x == emh2->nSize),
1338        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1339     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1340     ok(emh1->nBytes == emh2->nBytes ||
1341        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1342        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1343        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1344     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1345
1346     offset1 = emh1->nSize;
1347     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1348     while (offset1 < emh1->nBytes)
1349     {
1350         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1351         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1352
1353         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1354               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1355
1356         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1357
1358         /* We have already bailed out if iType or nSize don't match */
1359         offset1 += emr1->nSize;
1360         offset2 += emr2->nSize;
1361     }
1362     return 0;
1363 }
1364
1365 /* Test a blank metafile.  May be used as a template for new tests. */
1366
1367 static void test_mf_Blank(void)
1368 {
1369     HDC hdcMetafile;
1370     HMETAFILE hMetafile;
1371     INT caps;
1372     BOOL ret;
1373     INT type;
1374
1375     hdcMetafile = CreateMetaFileA(NULL);
1376     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1377     trace("hdcMetafile %p\n", hdcMetafile);
1378
1379 /* Tests on metafile initialization */
1380     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1381     ok (caps == DT_METAFILE,
1382         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1383
1384     hMetafile = CloseMetaFile(hdcMetafile);
1385     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1386     type = GetObjectType(hMetafile);
1387     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1388     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1389
1390     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1391         "mf_blank") != 0)
1392     {
1393         dump_mf_bits(hMetafile, "mf_Blank");
1394         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1395     }
1396
1397     ret = DeleteMetaFile(hMetafile);
1398     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1399 }
1400
1401 static void test_CopyMetaFile(void)
1402 {
1403     HDC hdcMetafile;
1404     HMETAFILE hMetafile, hmf_copy;
1405     BOOL ret;
1406     char temp_path[MAX_PATH];
1407     char mf_name[MAX_PATH];
1408     INT type;
1409
1410     hdcMetafile = CreateMetaFileA(NULL);
1411     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1412     trace("hdcMetafile %p\n", hdcMetafile);
1413
1414     hMetafile = CloseMetaFile(hdcMetafile);
1415     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1416     type = GetObjectType(hMetafile);
1417     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1418
1419     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1420         "mf_blank") != 0)
1421     {
1422         dump_mf_bits(hMetafile, "mf_Blank");
1423         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1424     }
1425
1426     GetTempPathA(MAX_PATH, temp_path);
1427     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1428
1429     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1430     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1431
1432     type = GetObjectType(hmf_copy);
1433     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1434
1435     ret = DeleteMetaFile(hMetafile);
1436     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1437
1438     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1439     {
1440         dump_mf_bits(hMetafile, "mf_Blank");
1441         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1442     }
1443
1444     ret = DeleteMetaFile(hmf_copy);
1445     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1446
1447     DeleteFileA(mf_name);
1448 }
1449
1450 static void test_SetMetaFileBits(void)
1451 {
1452     HMETAFILE hmf;
1453     INT type;
1454     BOOL ret;
1455     BYTE buf[256];
1456     METAHEADER *mh;
1457
1458     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1459     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1460     type = GetObjectType(hmf);
1461     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1462
1463     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1464     {
1465         dump_mf_bits(hmf, "mf_Graphics");
1466         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1467     }
1468
1469     ret = DeleteMetaFile(hmf);
1470     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1471
1472     /* NULL data crashes XP SP1 */
1473     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1474
1475     /* Now with not zero size */
1476     SetLastError(0xdeadbeef);
1477     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1478     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1479     ok(GetLastError() == ERROR_INVALID_DATA ||
1480        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1481        "wrong error %d\n", GetLastError());
1482
1483     /* Now with not even size */
1484     SetLastError(0xdeadbeef);
1485     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1486     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1487     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1488
1489     /* Now with zeroed out or faked some header fields */
1490     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1491     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1492     mh = (METAHEADER *)buf;
1493     /* corruption of any of the below fields leads to a failure */
1494     mh->mtType = 0;
1495     mh->mtVersion = 0;
1496     mh->mtHeaderSize = 0;
1497     SetLastError(0xdeadbeef);
1498     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1499     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1500     ok(GetLastError() == ERROR_INVALID_DATA ||
1501        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1502        "wrong error %d\n", GetLastError());
1503
1504     /* Now with corrupted mtSize field */
1505     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1506     mh = (METAHEADER *)buf;
1507     /* corruption of mtSize doesn't lead to a failure */
1508     mh->mtSize *= 2;
1509     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1510     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1511
1512     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1513     {
1514         dump_mf_bits(hmf, "mf_Graphics");
1515         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1516     }
1517
1518     ret = DeleteMetaFile(hmf);
1519     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1520
1521     /* Now with zeroed out mtSize field */
1522     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1523     mh = (METAHEADER *)buf;
1524     /* zeroing mtSize doesn't lead to a failure */
1525     mh->mtSize = 0;
1526     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1527     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1528
1529     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1530     {
1531         dump_mf_bits(hmf, "mf_Graphics");
1532         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1533     }
1534
1535     ret = DeleteMetaFile(hmf);
1536     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1537 }
1538
1539 /* Simple APIs from mfdrv/graphics.c
1540  */
1541
1542 static void test_mf_Graphics(void)
1543 {
1544     HDC hdcMetafile;
1545     HMETAFILE hMetafile;
1546     POINT oldpoint;
1547     BOOL ret;
1548
1549     hdcMetafile = CreateMetaFileA(NULL);
1550     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1551     trace("hdcMetafile %p\n", hdcMetafile);
1552
1553     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1554     ok( ret, "MoveToEx error %d.\n", GetLastError());
1555     ret = LineTo(hdcMetafile, 2, 2);
1556     ok( ret, "LineTo error %d.\n", GetLastError());
1557     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1558     ok( ret, "MoveToEx error %d.\n", GetLastError());
1559
1560 /* oldpoint gets garbage under Win XP, so the following test would
1561  * work under Wine but fails under Windows:
1562  *
1563  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1564  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1565  *       oldpoint.x, oldpoint.y);
1566  */
1567
1568     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1569     ok( ret, "Ellipse error %d.\n", GetLastError());
1570
1571     hMetafile = CloseMetaFile(hdcMetafile);
1572     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1573     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1574
1575     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1576         "mf_Graphics") != 0)
1577     {
1578         dump_mf_bits(hMetafile, "mf_Graphics");
1579         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1580     }
1581
1582     ret = DeleteMetaFile(hMetafile);
1583     ok( ret, "DeleteMetaFile(%p) error %d\n",
1584         hMetafile, GetLastError());
1585 }
1586
1587 static void test_mf_PatternBrush(void)
1588 {
1589     HDC hdcMetafile;
1590     HMETAFILE hMetafile;
1591     LOGBRUSH *orig_lb;
1592     HBRUSH hBrush;
1593     BOOL ret;
1594
1595     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1596
1597     orig_lb->lbStyle = BS_PATTERN;
1598     orig_lb->lbColor = RGB(0, 0, 0);
1599     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1600     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1601
1602     hBrush = CreateBrushIndirect (orig_lb);
1603     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1604
1605     hdcMetafile = CreateMetaFileA(NULL);
1606     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1607     trace("hdcMetafile %p\n", hdcMetafile);
1608
1609     hBrush = SelectObject(hdcMetafile, hBrush);
1610     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1611
1612     hMetafile = CloseMetaFile(hdcMetafile);
1613     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1614     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1615
1616     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1617         "mf_Pattern_Brush") != 0)
1618     {
1619         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1620         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1621     }
1622
1623     ret = DeleteMetaFile(hMetafile);
1624     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1625     ret = DeleteObject(hBrush);
1626     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1627     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1628     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1629         GetLastError());
1630     HeapFree (GetProcessHeap(), 0, orig_lb);
1631 }
1632
1633 static void test_mf_ExtTextOut_on_path(void)
1634 {
1635     HDC hdcMetafile;
1636     HMETAFILE hMetafile;
1637     BOOL ret;
1638     static const INT dx[4] = { 3, 5, 8, 12 };
1639
1640     hdcMetafile = CreateMetaFileA(NULL);
1641     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1642     trace("hdcMetafile %p\n", hdcMetafile);
1643
1644     ret = BeginPath(hdcMetafile);
1645     ok(!ret, "BeginPath on metafile DC should fail\n");
1646
1647     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1648     ok(ret, "ExtTextOut error %d\n", GetLastError());
1649
1650     ret = EndPath(hdcMetafile);
1651     ok(!ret, "EndPath on metafile DC should fail\n");
1652
1653     hMetafile = CloseMetaFile(hdcMetafile);
1654     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1655
1656     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1657         "mf_TextOut_on_path") != 0)
1658     {
1659         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1660         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1661     }
1662
1663     ret = DeleteMetaFile(hMetafile);
1664     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1665 }
1666
1667 static void test_emf_ExtTextOut_on_path(void)
1668 {
1669     HWND hwnd;
1670     HDC hdcDisplay, hdcMetafile;
1671     HENHMETAFILE hMetafile;
1672     BOOL ret;
1673     static const INT dx[4] = { 3, 5, 8, 12 };
1674
1675     /* Win9x doesn't play EMFs on invisible windows */
1676     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1677                            0, 0, 200, 200, 0, 0, 0, NULL);
1678     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1679
1680     hdcDisplay = GetDC(hwnd);
1681     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1682
1683     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1684     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1685
1686     ret = BeginPath(hdcMetafile);
1687     ok(ret, "BeginPath error %d\n", GetLastError());
1688
1689     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1690     ok(ret, "ExtTextOut error %d\n", GetLastError());
1691
1692     ret = EndPath(hdcMetafile);
1693     ok(ret, "EndPath error %d\n", GetLastError());
1694
1695     hMetafile = CloseEnhMetaFile(hdcMetafile);
1696     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1697
1698     /* this doesn't succeed yet: EMF has correct size, all EMF records
1699      * are there, but their contents don't match for different reasons.
1700      */
1701     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1702         "emf_TextOut_on_path", FALSE) != 0)
1703     {
1704         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1705         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1706     }
1707
1708     ret = DeleteEnhMetaFile(hMetafile);
1709     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1710     ret = ReleaseDC(hwnd, hdcDisplay);
1711     ok(ret, "ReleaseDC error %d\n", GetLastError());
1712     DestroyWindow(hwnd);
1713 }
1714
1715 static const unsigned char EMF_CLIPPING[] =
1716 {
1717     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1718     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1719     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1720     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1721     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1722     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1723     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1724     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1725     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1726     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1727     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1728     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1729     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1730     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1731     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1732     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1733     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1734     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1735     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1736     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1737     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1738     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1739     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1740     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1741     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1742     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1743 };
1744
1745 static void translate( POINT *pt, UINT count, const XFORM *xform )
1746 {
1747     while (count--)
1748     {
1749         FLOAT x = (FLOAT)pt->x;
1750         FLOAT y = (FLOAT)pt->y;
1751         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1752         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1753         pt++;
1754     }
1755 }
1756
1757 /* Compare rectangles allowing rounding errors */
1758 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1759 {
1760     return abs(rc1->left - rc2->left) <= 1 &&
1761            abs(rc1->top - rc2->top) <= 1 &&
1762            abs(rc1->right - rc2->right) <= 1 &&
1763            abs(rc1->bottom - rc2->bottom) <= 1;
1764 }
1765
1766 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1767                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1768 {
1769     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1770     {
1771         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1772         union _rgn
1773         {
1774             RGNDATA data;
1775             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1776         };
1777         const union _rgn *rgn1;
1778         union _rgn rgn2;
1779         RECT rect, rc_transformed;
1780         const RECT *rc = (const RECT *)param;
1781         HRGN hrgn;
1782         XFORM xform;
1783         INT ret;
1784         BOOL is_win9x;
1785
1786         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1787                clip->cbRgnData, clip->iMode);
1788
1789         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1790         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1791            "too small data block: %u bytes\n", clip->cbRgnData);
1792         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1793             return 0;
1794
1795         rgn1 = (const union _rgn *)clip->RgnData;
1796
1797         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1798               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1799               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1800               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1801               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1802
1803         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1804
1805         rect = *(const RECT *)rgn1->data.Buffer;
1806         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1807         ok(EqualRect(&rect, rc), "rects don't match\n");
1808
1809         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1810         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1811         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1812         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1813
1814         hrgn = CreateRectRgn(0, 0, 0, 0);
1815
1816         memset(&xform, 0, sizeof(xform));
1817         SetLastError(0xdeadbeef);
1818         ret = GetWorldTransform(hdc, &xform);
1819         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1820         if (!is_win9x)
1821             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1822
1823         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1824
1825         ret = GetClipRgn(hdc, hrgn);
1826         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1827
1828         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1829
1830         ret = GetClipRgn(hdc, hrgn);
1831         ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1832
1833         /* Win9x returns empty clipping region */
1834         if (is_win9x) return 1;
1835
1836         ret = GetRegionData(hrgn, 0, NULL);
1837         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1838
1839         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1840
1841         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1842               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1843               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1844               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1845               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1846
1847         rect = rgn2.data.rdh.rcBound;
1848         rc_transformed = *rc;
1849         translate((POINT *)&rc_transformed, 2, &xform);
1850         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1851               rc_transformed.right, rc_transformed.bottom);
1852         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1853
1854         rect = *(const RECT *)rgn2.data.Buffer;
1855         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1856         rc_transformed = *rc;
1857         translate((POINT *)&rc_transformed, 2, &xform);
1858         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1859               rc_transformed.right, rc_transformed.bottom);
1860         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1861
1862         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1863         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1864         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1865         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1866
1867         DeleteObject(hrgn);
1868     }
1869     return 1;
1870 }
1871
1872 static void test_emf_clipping(void)
1873 {
1874     static const RECT rc = { 0, 0, 100, 100 };
1875     RECT rc_clip = { 100, 100, 1024, 1024 };
1876     HWND hwnd;
1877     HDC hdc;
1878     HENHMETAFILE hemf;
1879     HRGN hrgn;
1880     INT ret;
1881
1882     SetLastError(0xdeadbeef);
1883     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1884     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1885
1886     /* Need to write something to the emf, otherwise Windows won't play it back */
1887     LineTo(hdc, 1, 1);
1888
1889     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1890     ret = SelectClipRgn(hdc, hrgn);
1891     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1892
1893     SetLastError(0xdeadbeef);
1894     hemf = CloseEnhMetaFile(hdc);
1895     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1896
1897     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1898         "emf_clipping", FALSE) != 0)
1899     {
1900         dump_emf_bits(hemf, "emf_clipping");
1901         dump_emf_records(hemf, "emf_clipping");
1902     }
1903
1904     DeleteObject(hrgn);
1905
1906     /* Win9x doesn't play EMFs on invisible windows */
1907     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1908                            0, 0, 200, 200, 0, 0, 0, NULL);
1909     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1910
1911     hdc = GetDC(hwnd);
1912
1913     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1914     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1915
1916     DeleteEnhMetaFile(hemf);
1917     ReleaseDC(hwnd, hdc);
1918     DestroyWindow(hwnd);
1919 }
1920
1921 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1922 {
1923     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1924     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1925     /* When using MM_TEXT Win9x does not update the mapping mode 
1926      * until a record is played which actually outputs something */
1927     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1928     LPtoDP(hdc, mapping, 2);
1929     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1930            lpEMFR->iType, lpEMFR->nSize,
1931            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1932
1933     if (lpEMFR->iType == EMR_LINETO)
1934     {
1935         INT x0, y0, x1, y1;
1936         if (!lpMFP || lpMFP->mm == MM_TEXT)
1937         {
1938             x0 = 0;
1939             y0 = 0;
1940             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1941             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1942         }
1943         else
1944         {
1945             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1946             
1947             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1948             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1949             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1950             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1951         }
1952         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1953             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1954             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1955             x0, y0, x1, y1);
1956     }
1957     return TRUE;
1958 }
1959
1960 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1961 {
1962     HDC hdcMf;
1963     HMETAFILE hmf;
1964     HENHMETAFILE hemf;
1965     BOOL ret;
1966     UINT size;
1967     LPBYTE pBits;
1968
1969     hdcMf = CreateMetaFile(NULL);
1970     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1971     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1972     ok(ret, "LineTo failed with error %d\n", GetLastError());
1973     hmf = CloseMetaFile(hdcMf);
1974     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1975
1976     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1977     {
1978         dump_mf_bits(hmf, "mf_LineTo");
1979         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1980     }
1981
1982     size = GetMetaFileBitsEx(hmf, 0, NULL);
1983     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1984     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1985     GetMetaFileBitsEx(hmf, size, pBits);
1986     DeleteMetaFile(hmf);
1987     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1988     HeapFree(GetProcessHeap(), 0, pBits);
1989     return hemf;
1990 }
1991
1992 static void test_mf_conversions(void)
1993 {
1994     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1995     {
1996         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1997         HENHMETAFILE hemf;
1998         METAFILEPICT mfp;
1999         RECT rect = { 0, 0, 100, 100 };
2000         mfp.mm = MM_ANISOTROPIC;
2001         mfp.xExt = 100;
2002         mfp.yExt = 100;
2003         mfp.hMF = NULL;
2004         hemf = create_converted_emf(&mfp);
2005
2006         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2007                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2008         {
2009             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2010             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2011         }
2012
2013         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2014
2015         DeleteEnhMetaFile(hemf);
2016         DeleteDC(hdcOffscreen);
2017     }
2018
2019     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2020     {
2021         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2022         HENHMETAFILE hemf;
2023         METAFILEPICT mfp;
2024         RECT rect = { 0, 0, 100, 100 };
2025         mfp.mm = MM_TEXT;
2026         mfp.xExt = 0;
2027         mfp.yExt = 0;
2028         mfp.hMF = NULL;
2029         hemf = create_converted_emf(&mfp);
2030
2031         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2032                              "emf_LineTo MM_TEXT", TRUE) != 0)
2033         {
2034             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2035             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2036         }
2037
2038         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2039
2040         DeleteEnhMetaFile(hemf);
2041         DeleteDC(hdcOffscreen);
2042     }
2043
2044     trace("Testing MF->EMF conversion (NULL mfp)\n");
2045     {
2046         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2047         HENHMETAFILE hemf;
2048         RECT rect = { 0, 0, 100, 100 };
2049         hemf = create_converted_emf(NULL);
2050
2051         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2052                              "emf_LineTo NULL", TRUE) != 0)
2053         {
2054             dump_emf_bits(hemf, "emf_LineTo NULL");
2055             dump_emf_records(hemf, "emf_LineTo NULL");
2056         }
2057
2058         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2059
2060         DeleteEnhMetaFile(hemf);
2061         DeleteDC(hdcOffscreen);
2062     }
2063 }
2064
2065 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2066                                        LONG mm, LONG xExt, LONG yExt,
2067                                        RECTL * rclBounds, RECTL * rclFrame)
2068 {
2069   METAFILEPICT mfp;
2070   METAFILEPICT * mfpPtr = NULL;
2071   HENHMETAFILE emf;
2072   ENHMETAHEADER header;
2073   UINT res;
2074
2075   if (!mfpIsNull)
2076   {
2077     mfp.mm = mm;
2078     mfp.xExt = xExt;
2079     mfp.yExt = yExt;
2080     mfpPtr = &mfp;
2081   }
2082
2083   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2084   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2085   if (!emf) return FALSE;
2086   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2087   ok(res != 0, "GetEnhMetaHeader failed\n");
2088   DeleteEnhMetaFile(emf);
2089   if (!res) return FALSE;
2090
2091   *rclBounds = header.rclBounds;
2092   *rclFrame = header.rclFrame;
2093   return TRUE;
2094 }
2095
2096 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2097                                          LONG mm, LONG xExt, LONG yExt,
2098                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2099 {
2100   RECTL rclBounds, rclFrame;
2101
2102   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2103   {
2104     const char * msg;
2105     char buf[64];
2106
2107     if (mfpIsNull)
2108     {
2109        msg = "mfp == NULL";
2110     }
2111     else
2112     {
2113       const char * mm_str;
2114       switch (mm)
2115       {
2116          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2117          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2118          default:             mm_str = "Unexpected";
2119       }
2120       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2121       msg = buf;
2122     }
2123
2124     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2125     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2126     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2127     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2128     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2129     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2130     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2131     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2132   }
2133 }
2134
2135 static void test_SetWinMetaFileBits(void)
2136 {
2137   HMETAFILE wmf;
2138   HDC wmfDC;
2139   BYTE * buffer;
2140   UINT buffer_size;
2141   RECT rect;
2142   UINT res;
2143   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2144   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2145   RECTL rclBounds, rclFrame;
2146   HDC dc;
2147   LONG diffx, diffy;
2148
2149   wmfDC = CreateMetaFile(NULL);
2150   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2151   if (!wmfDC) return;
2152
2153   SetWindowExtEx(wmfDC, 100, 100, NULL);
2154   rect.left = rect.top = 0;
2155   rect.right = rect.bottom = 50;
2156   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2157   wmf = CloseMetaFile(wmfDC);
2158   ok(wmf != NULL, "Metafile creation failed\n");
2159   if (!wmf) return;
2160
2161   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2162   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2163   if (buffer_size == 0)
2164   {
2165     DeleteMetaFile(wmf);
2166     return;
2167   }
2168
2169   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2170   ok(buffer != NULL, "HeapAlloc failed\n");
2171   if (!buffer)
2172   {
2173     DeleteMetaFile(wmf);
2174     return;
2175   }
2176
2177   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2178   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2179   DeleteMetaFile(wmf);
2180   if (res != buffer_size)
2181   {
2182      HeapFree(GetProcessHeap(), 0, buffer);
2183      return;
2184   }
2185
2186   /* Get the reference bounds and frame */
2187   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2188   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2189
2190   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2191      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2192      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2193
2194   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2195   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2196   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2197   if (diffx < 0) diffx = -diffx;
2198   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2199
2200   dc = CreateCompatibleDC(NULL);
2201
2202   /* Allow 1 mm difference (rounding errors) */
2203   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2204   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2205   if (diffx < 0) diffx = -diffx;
2206   if (diffy < 0) diffy = -diffy;
2207   todo_wine
2208   {
2209   ok(diffx <= 1 && diffy <= 1,
2210      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2211      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2212   }
2213
2214   /* Allow 1 mm difference (rounding errors) */
2215   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2216   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2217   if (diffx < 0) diffx = -diffx;
2218   if (diffy < 0) diffy = -diffy;
2219   todo_wine
2220   {
2221   ok(diffx <= 1 && diffy <= 1,
2222      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2223      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2224   }
2225   DeleteDC(dc);
2226
2227   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2228   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2229
2230   /* If xExt or yExt is zero or negative, the whole device surface is used */
2231   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2232   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2233   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2234   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2235   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2236   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2237   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2238   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2239   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2240   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2241   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2242   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2243
2244   /* MSDN says that negative xExt and yExt values specify a ratio.
2245      Check that this is wrong and the whole device surface is used */
2246   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2247   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2248
2249   /* Ordinary conversions */
2250
2251   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2252   {
2253     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2254        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2255     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2256        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2257   }
2258
2259   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2260   {
2261     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2262        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2263     ok(rclBounds.left == 0 && rclBounds.top == 0,
2264        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2265
2266     /* Wine has a rounding error */
2267     diffx = rclBounds.right - rclBounds.bottom;
2268     if (diffx < 0) diffx = -diffx;
2269     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2270   }
2271
2272   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2273   {
2274     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2275        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2276   }
2277
2278   HeapFree(GetProcessHeap(), 0, buffer);
2279 }
2280
2281 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2282 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2283 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2284
2285 static void test_gdiis(void)
2286 {
2287     RECT rect = {0,0,100,100};
2288     HDC hdc, hemfDC, hmfDC;
2289     HENHMETAFILE hemf;
2290     HMODULE hgdi32;
2291
2292     /* resolve all the functions */
2293     hgdi32 = GetModuleHandle("gdi32");
2294     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2295     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2296     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2297
2298     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2299     {
2300         win_skip("Needed GdiIs* functions are not available\n");
2301         return;
2302     }
2303
2304     /* try with nothing */
2305     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2306     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2307     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2308
2309     /* try with a metafile */
2310     hmfDC = CreateMetaFile(NULL);
2311     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2312     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2313     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2314     DeleteMetaFile(CloseMetaFile(hmfDC));
2315
2316     /* try with an enhanced metafile */
2317     hdc = GetDC(NULL);
2318     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2319     ok(hemfDC != NULL, "failed to create emf\n");
2320
2321     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2322     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2323     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2324
2325     hemf = CloseEnhMetaFile(hemfDC);
2326     ok(hemf != NULL, "failed to close EMF\n");
2327     DeleteEnhMetaFile(hemf);
2328     ReleaseDC(NULL,hdc);
2329 }
2330
2331 static void test_SetEnhMetaFileBits(void)
2332 {
2333     BYTE data[256];
2334     HENHMETAFILE hemf;
2335     ENHMETAHEADER *emh;
2336
2337     memset(data, 0xAA, sizeof(data));
2338     SetLastError(0xdeadbeef);
2339     hemf = SetEnhMetaFileBits(sizeof(data), data);
2340     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2341     ok(GetLastError() == ERROR_INVALID_DATA ||
2342        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2343        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2344
2345     emh = (ENHMETAHEADER *)data;
2346     memset(emh, 0, sizeof(*emh));
2347
2348     emh->iType = EMR_HEADER;
2349     emh->nSize = sizeof(*emh);
2350     emh->dSignature = ENHMETA_SIGNATURE;
2351     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2352     emh->nBytes = sizeof(*emh);
2353     /* emh->nRecords = 1; XP doesn't care about records */
2354     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2355
2356     SetLastError(0xdeadbeef);
2357     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2358     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2359     DeleteEnhMetaFile(hemf);
2360
2361     /* XP refuses to load unaligned EMF */
2362     emh->nBytes++;
2363     SetLastError(0xdeadbeef);
2364     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2365     ok(!hemf ||
2366        broken(hemf != NULL), /* Win9x, WinMe */
2367        "SetEnhMetaFileBits should fail\n");
2368     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2369     DeleteEnhMetaFile(hemf);
2370
2371     emh->dSignature = 0;
2372     emh->nBytes--;
2373     SetLastError(0xdeadbeef);
2374     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2375     ok(!hemf ||
2376        broken(hemf != NULL), /* Win9x, WinMe */
2377        "SetEnhMetaFileBits should fail\n");
2378     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2379     DeleteEnhMetaFile(hemf);
2380 }
2381
2382 START_TEST(metafile)
2383 {
2384     init_function_pointers();
2385
2386     /* For enhanced metafiles (enhmfdrv) */
2387     test_ExtTextOut();
2388     test_SaveDC();
2389
2390     /* For win-format metafiles (mfdrv) */
2391     test_mf_SaveDC();
2392     test_mf_Blank();
2393     test_mf_Graphics();
2394     test_mf_PatternBrush();
2395     test_CopyMetaFile();
2396     test_SetMetaFileBits();
2397     test_mf_ExtTextOut_on_path();
2398     test_emf_ExtTextOut_on_path();
2399     test_emf_clipping();
2400
2401     /* For metafile conversions */
2402     test_mf_conversions();
2403     test_SetWinMetaFileBits();
2404
2405     test_gdiis();
2406     test_SetEnhMetaFileBits();
2407 }