d3dx9: Implement D3DXAssembleShaderFromFile.
[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 static const unsigned char EMF_BITBLT[] =
1034 {
1035     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1036     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1037     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1038     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1039     0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1040     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1041     0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1042     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1044     0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1045     0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1046     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047     0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1048     0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1049     0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1050     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1051     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1052     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1053     0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1054     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1056     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1057     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1058     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1059     0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1060     0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1061     0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1062     0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1063     0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1064     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1065     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1066     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1067     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1069     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1071     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1072     0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1073     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1074     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1075     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1076     0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1077     0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1078     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1079     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1081     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1083     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1084     0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1085     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1086     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1087 };
1088
1089
1090 /* For debugging or dumping the raw metafiles produced by
1091  * new test functions.
1092  */
1093 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1094                                  INT nobj, LPARAM param)
1095 {
1096     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1097            hdc, mr->rdFunction, mr->rdSize, (void *)param);
1098     return TRUE;
1099 }
1100
1101 /* For debugging or dumping the raw metafiles produced by
1102  * new test functions.
1103  */
1104
1105 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1106 {
1107     BYTE buf[MF_BUFSIZE];
1108     UINT mfsize, i;
1109
1110     if (!winetest_debug) return;
1111
1112     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1113     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1114
1115     printf ("MetaFile %s has bits:\n{\n    ", desc);
1116     for (i=0; i<mfsize; i++)
1117     {
1118         printf ("0x%02x", buf[i]);
1119         if (i == mfsize-1)
1120             printf ("\n");
1121         else if (i % 8 == 7)
1122             printf (",\n    ");
1123         else
1124             printf (", ");
1125     }
1126     printf ("};\n");
1127 }
1128
1129 /* Compare the metafile produced by a test function with the
1130  * expected raw metafile data in "bits".
1131  * Return value is 0 for a perfect match,
1132  * -1 if lengths aren't equal,
1133  * otherwise returns the number of non-matching bytes.
1134  */
1135
1136 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1137     const char *desc)
1138 {
1139     unsigned char buf[MF_BUFSIZE];
1140     UINT mfsize, i;
1141     int diff;
1142
1143     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1144     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1145     if (mfsize < MF_BUFSIZE)
1146         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1147             desc, mfsize, bsize);
1148     else
1149         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1150             desc, mfsize, bsize);
1151     if (mfsize != bsize)
1152         return -1;
1153
1154     diff = 0;
1155     for (i=0; i<bsize; i++)
1156     {
1157        if (buf[i] !=  bits[i])
1158            diff++;
1159     }
1160     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1161         desc, mfsize, bsize, diff);
1162
1163     return diff; 
1164 }
1165
1166 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1167 {
1168     unsigned char buf[MF_BUFSIZE];
1169     DWORD mfsize, rd_size, i;
1170     int diff;
1171     HANDLE hfile;
1172     BOOL ret;
1173
1174     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1175     assert(hfile != INVALID_HANDLE_VALUE);
1176
1177     mfsize = GetFileSize(hfile, NULL);
1178     assert(mfsize <= MF_BUFSIZE);
1179
1180     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1181     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1182
1183     CloseHandle(hfile);
1184
1185     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1186
1187     if (mfsize != bsize)
1188         return -1;
1189
1190     diff = 0;
1191     for (i=0; i<bsize; i++)
1192     {
1193         if (buf[i] != bits[i])
1194             diff++;
1195     }
1196     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1197         desc, mfsize, bsize, diff);
1198
1199     return diff; 
1200 }
1201
1202 /* For debugging or dumping the raw EMFs produced by
1203  * new test functions.
1204  */
1205 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1206 {
1207     BYTE buf[MF_BUFSIZE];
1208     UINT mfsize, i;
1209
1210     if (!winetest_debug) return;
1211
1212     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1213     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1214
1215     printf("EMF %s has bits:\n{\n    ", desc);
1216     for (i = 0; i < mfsize; i++)
1217     {
1218         printf ("0x%02x", buf[i]);
1219         if (i == mfsize-1)
1220             printf ("\n");
1221         else if (i % 8 == 7)
1222             printf (",\n    ");
1223         else
1224             printf (", ");
1225     }
1226     printf ("};\n");
1227 }
1228
1229 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1230 {
1231     BYTE *emf;
1232     BYTE buf[MF_BUFSIZE];
1233     UINT mfsize, offset;
1234
1235     if (!winetest_debug) return;
1236
1237     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1238     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1239
1240     printf("EMF %s has records:\n", desc);
1241
1242     emf = buf;
1243     offset = 0;
1244     while(offset < mfsize)
1245     {
1246         EMR *emr = (EMR *)(emf + offset);
1247         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1248         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1249         offset += emr->nSize;
1250     }
1251 }
1252
1253 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1254 {
1255     const BYTE *buf;
1256     DWORD i;
1257
1258     if (!winetest_debug) return;
1259
1260     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1261     buf = (const BYTE *)emr;
1262     for (i = 0; i < emr->nSize; i++)
1263     {
1264         printf ("0x%02x", buf[i]);
1265         if (i == emr->nSize - 1)
1266             printf ("\n");
1267         else if (i % 8 == 7)
1268             printf (",\n");
1269         else
1270             printf (", ");
1271     }
1272     printf ("};\n");
1273 }
1274
1275 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1276 {
1277     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1278           eto->rclBounds.right, eto->rclBounds.bottom);
1279     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1280     trace("exScale: %f\n", eto->exScale);
1281     trace("eyScale: %f\n", eto->eyScale);
1282     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1283     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1284     trace("emrtext.offString %#x\n", eto->emrtext.offString);
1285     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1286     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1287           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1288     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1289 }
1290
1291 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1292                              const char *desc, BOOL ignore_scaling)
1293 {
1294     int diff;
1295
1296     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1297        desc, emr1->iType, emr2->iType);
1298
1299     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1300        desc, emr1->nSize, emr2->nSize);
1301
1302     /* iType and nSize mismatches are fatal */
1303     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1304
1305     /* contents of EMR_GDICOMMENT are not interesting */
1306     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1307
1308     /* different Windows versions setup DC scaling differently when
1309      * converting an old style metafile to an EMF.
1310      */
1311     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1312                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1313         return TRUE;
1314
1315     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1316     {
1317         EMREXTTEXTOUTW *eto1, *eto2;
1318
1319         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1320         memcpy(eto1, emr1, emr1->nSize);
1321         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1322         memcpy(eto2, emr2, emr2->nSize);
1323
1324         /* different Windows versions setup DC scaling differently */
1325         eto1->exScale = eto1->eyScale = 0.0;
1326         eto2->exScale = eto2->eyScale = 0.0;
1327
1328         diff = memcmp(eto1, eto2, emr1->nSize);
1329         if (diff)
1330         {
1331             dump_EMREXTTEXTOUT(eto1);
1332             dump_EMREXTTEXTOUT(eto2);
1333         }
1334         HeapFree(GetProcessHeap(), 0, eto1);
1335         HeapFree(GetProcessHeap(), 0, eto2);
1336     }
1337     else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1338     {
1339         /* We have to take care of NT4 differences here */
1340         diff = memcmp(emr1, emr2, emr1->nSize);
1341         if (diff)
1342         {
1343             ENHMETARECORD *emr_nt4;
1344
1345             emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1346             memcpy(emr_nt4, emr2, emr2->nSize);
1347             /* Correct the nRgnSize field */
1348             emr_nt4->dParm[5] = sizeof(RECT);
1349
1350             diff = memcmp(emr1, emr_nt4, emr1->nSize);
1351             if (!diff)
1352                 win_skip("Catered for NT4 differences\n");
1353
1354             HeapFree(GetProcessHeap(), 0, emr_nt4);
1355         }
1356     }
1357     else
1358         diff = memcmp(emr1, emr2, emr1->nSize);
1359
1360     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1361
1362     if (diff)
1363     {
1364         dump_emf_record(emr1, "expected bits");
1365         dump_emf_record(emr2, "actual bits");
1366     }
1367
1368     return diff == 0; /* report all non-fatal record mismatches */
1369 }
1370
1371 /* Compare the EMF produced by a test function with the
1372  * expected raw EMF data in "bits".
1373  * Return value is 0 for a perfect match,
1374  * -1 if lengths aren't equal,
1375  * otherwise returns the number of non-matching bytes.
1376  */
1377 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1378                             UINT bsize, const char *desc,
1379                             BOOL ignore_scaling)
1380 {
1381     unsigned char buf[MF_BUFSIZE];
1382     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1383     const ENHMETAHEADER *emh1, *emh2;
1384
1385     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1386     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1387
1388     /* ENHMETAHEADER size could differ, depending on platform */
1389     diff_nt4 = sizeof(SIZEL);
1390     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1391
1392     if (mfsize < MF_BUFSIZE)
1393     {
1394         ok(mfsize == bsize ||
1395            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1396            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1397            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1398     }
1399     else
1400         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1401            desc, mfsize, bsize);
1402
1403     /* basic things must match */
1404     emh1 = (const ENHMETAHEADER *)bits;
1405     emh2 = (const ENHMETAHEADER *)buf;
1406     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1407     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1408     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1409     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1410
1411     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1412     ok(emh1->nSize == emh2->nSize ||
1413        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1414        broken(emh1->nSize - diff_9x == emh2->nSize),
1415        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1416     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1417     ok(emh1->nBytes == emh2->nBytes ||
1418        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1419        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1420        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1421     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1422
1423     offset1 = emh1->nSize;
1424     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1425     while (offset1 < emh1->nBytes)
1426     {
1427         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1428         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1429
1430         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1431               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1432
1433         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1434
1435         /* We have already bailed out if iType or nSize don't match */
1436         offset1 += emr1->nSize;
1437         offset2 += emr2->nSize;
1438     }
1439     return 0;
1440 }
1441
1442
1443 /* tests blitting to an EMF */
1444 static void test_emf_BitBlt(void)
1445 {
1446     HDC hdcDisplay, hdcMetafile, hdcBitmap;
1447     HBITMAP hBitmap, hOldBitmap;
1448     HENHMETAFILE hMetafile;
1449 #define BMP_DIM 4
1450     BITMAPINFOHEADER bmih =
1451     {
1452         sizeof(BITMAPINFOHEADER),
1453         BMP_DIM,/* biWidth */
1454         BMP_DIM,/* biHeight */
1455         1,      /* biPlanes */
1456         24,     /* biBitCount */
1457         BI_RGB, /* biCompression */
1458         0,      /* biXPelsPerMeter */
1459         0,      /* biYPelsPerMeter */
1460         0,      /* biClrUsed */
1461         0,      /* biClrImportant */
1462     };
1463     void *bits;
1464     BOOL ret;
1465
1466     hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1467     ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1468
1469     hdcBitmap = CreateCompatibleDC(hdcDisplay);
1470     ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1471     bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1472     bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1473     hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1474                                DIB_RGB_COLORS, &bits, NULL, 0);
1475     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1476
1477     hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1478     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1479
1480     /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1481     ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1482     ok( ret, "BitBlt(BLACKNESS) failed\n" );
1483
1484     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1485     ok( ret, "BitBlt(SRCCOPY) failed\n" );
1486     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1487     ok( ret, "BitBlt(WHITENESS) failed\n" );
1488
1489     hMetafile = CloseEnhMetaFile(hdcMetafile);
1490     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1491
1492     if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1493         "emf_BitBlt", FALSE) != 0)
1494     {
1495         dump_emf_bits(hMetafile, "emf_BitBlt");
1496         dump_emf_records(hMetafile, "emf_BitBlt");
1497     }
1498
1499     SelectObject(hdcBitmap, hOldBitmap);
1500     DeleteObject(hBitmap);
1501     DeleteDC(hdcBitmap);
1502     DeleteDC(hdcDisplay);
1503 #undef BMP_DIM
1504 }
1505
1506 /* Test a blank metafile.  May be used as a template for new tests. */
1507
1508 static void test_mf_Blank(void)
1509 {
1510     HDC hdcMetafile;
1511     HMETAFILE hMetafile;
1512     INT caps;
1513     BOOL ret;
1514     INT type;
1515
1516     hdcMetafile = CreateMetaFileA(NULL);
1517     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1518     trace("hdcMetafile %p\n", hdcMetafile);
1519
1520 /* Tests on metafile initialization */
1521     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1522     ok (caps == DT_METAFILE,
1523         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1524
1525     hMetafile = CloseMetaFile(hdcMetafile);
1526     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1527     type = GetObjectType(hMetafile);
1528     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1529     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1530
1531     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1532         "mf_blank") != 0)
1533     {
1534         dump_mf_bits(hMetafile, "mf_Blank");
1535         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1536     }
1537
1538     ret = DeleteMetaFile(hMetafile);
1539     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1540 }
1541
1542 static void test_CopyMetaFile(void)
1543 {
1544     HDC hdcMetafile;
1545     HMETAFILE hMetafile, hmf_copy;
1546     BOOL ret;
1547     char temp_path[MAX_PATH];
1548     char mf_name[MAX_PATH];
1549     INT type;
1550
1551     hdcMetafile = CreateMetaFileA(NULL);
1552     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1553     trace("hdcMetafile %p\n", hdcMetafile);
1554
1555     hMetafile = CloseMetaFile(hdcMetafile);
1556     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1557     type = GetObjectType(hMetafile);
1558     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1559
1560     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1561         "mf_blank") != 0)
1562     {
1563         dump_mf_bits(hMetafile, "mf_Blank");
1564         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1565     }
1566
1567     GetTempPathA(MAX_PATH, temp_path);
1568     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1569
1570     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1571     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1572
1573     type = GetObjectType(hmf_copy);
1574     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1575
1576     ret = DeleteMetaFile(hMetafile);
1577     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1578
1579     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1580     {
1581         dump_mf_bits(hmf_copy, "mf_Blank");
1582         EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1583     }
1584
1585     ret = DeleteMetaFile(hmf_copy);
1586     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1587
1588     DeleteFileA(mf_name);
1589 }
1590
1591 static void test_SetMetaFileBits(void)
1592 {
1593     HMETAFILE hmf;
1594     INT type;
1595     BOOL ret;
1596     BYTE buf[256];
1597     METAHEADER *mh;
1598
1599     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1600     trace("hmf %p\n", hmf);
1601     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1602     type = GetObjectType(hmf);
1603     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1604
1605     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1606     {
1607         dump_mf_bits(hmf, "mf_Graphics");
1608         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1609     }
1610
1611     ret = DeleteMetaFile(hmf);
1612     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1613
1614     /* NULL data crashes XP SP1 */
1615     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1616
1617     /* Now with zero size */
1618     SetLastError(0xdeadbeef);
1619     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1620     trace("hmf %p\n", hmf);
1621     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1622     ok(GetLastError() == ERROR_INVALID_DATA ||
1623        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1624        "wrong error %d\n", GetLastError());
1625
1626     /* Now with odd size */
1627     SetLastError(0xdeadbeef);
1628     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1629     trace("hmf %p\n", hmf);
1630     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1631     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1632
1633     /* Now with zeroed out header fields */
1634     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1635     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1636     mh = (METAHEADER *)buf;
1637     /* corruption of any of the below fields leads to a failure */
1638     mh->mtType = 0;
1639     mh->mtVersion = 0;
1640     mh->mtHeaderSize = 0;
1641     SetLastError(0xdeadbeef);
1642     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1643     trace("hmf %p\n", hmf);
1644     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1645     ok(GetLastError() == ERROR_INVALID_DATA ||
1646        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1647        "wrong error %d\n", GetLastError());
1648
1649     /* Now with corrupted mtSize field */
1650     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1651     mh = (METAHEADER *)buf;
1652     /* corruption of mtSize doesn't lead to a failure */
1653     mh->mtSize *= 2;
1654     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1655     trace("hmf %p\n", hmf);
1656     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1657
1658     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1659     {
1660         dump_mf_bits(hmf, "mf_Graphics");
1661         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1662     }
1663
1664     ret = DeleteMetaFile(hmf);
1665     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1666
1667     /* Now with zeroed out mtSize field */
1668     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1669     mh = (METAHEADER *)buf;
1670     /* zeroing mtSize doesn't lead to a failure */
1671     mh->mtSize = 0;
1672     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1673     trace("hmf %p\n", hmf);
1674     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1675
1676     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1677     {
1678         dump_mf_bits(hmf, "mf_Graphics");
1679         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1680     }
1681
1682     ret = DeleteMetaFile(hmf);
1683     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1684 }
1685
1686 /* Simple APIs from mfdrv/graphics.c
1687  */
1688
1689 static void test_mf_Graphics(void)
1690 {
1691     HDC hdcMetafile;
1692     HMETAFILE hMetafile;
1693     POINT oldpoint;
1694     BOOL ret;
1695
1696     hdcMetafile = CreateMetaFileA(NULL);
1697     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1698     trace("hdcMetafile %p\n", hdcMetafile);
1699
1700     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1701     ok( ret, "MoveToEx error %d.\n", GetLastError());
1702     ret = LineTo(hdcMetafile, 2, 2);
1703     ok( ret, "LineTo error %d.\n", GetLastError());
1704     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1705     ok( ret, "MoveToEx error %d.\n", GetLastError());
1706
1707 /* oldpoint gets garbage under Win XP, so the following test would
1708  * work under Wine but fails under Windows:
1709  *
1710  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1711  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1712  *       oldpoint.x, oldpoint.y);
1713  */
1714
1715     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1716     ok( ret, "Ellipse error %d.\n", GetLastError());
1717
1718     hMetafile = CloseMetaFile(hdcMetafile);
1719     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1720     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1721
1722     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1723         "mf_Graphics") != 0)
1724     {
1725         dump_mf_bits(hMetafile, "mf_Graphics");
1726         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1727     }
1728
1729     ret = DeleteMetaFile(hMetafile);
1730     ok( ret, "DeleteMetaFile(%p) error %d\n",
1731         hMetafile, GetLastError());
1732 }
1733
1734 static void test_mf_PatternBrush(void)
1735 {
1736     HDC hdcMetafile;
1737     HMETAFILE hMetafile;
1738     LOGBRUSH *orig_lb;
1739     HBRUSH hBrush;
1740     BOOL ret;
1741
1742     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1743
1744     orig_lb->lbStyle = BS_PATTERN;
1745     orig_lb->lbColor = RGB(0, 0, 0);
1746     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1747     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1748
1749     hBrush = CreateBrushIndirect (orig_lb);
1750     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1751
1752     hdcMetafile = CreateMetaFileA(NULL);
1753     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1754     trace("hdcMetafile %p\n", hdcMetafile);
1755
1756     hBrush = SelectObject(hdcMetafile, hBrush);
1757     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1758
1759     hMetafile = CloseMetaFile(hdcMetafile);
1760     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1761     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1762
1763     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1764         "mf_Pattern_Brush") != 0)
1765     {
1766         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1767         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1768     }
1769
1770     ret = DeleteMetaFile(hMetafile);
1771     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1772     ret = DeleteObject(hBrush);
1773     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1774     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1775     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1776         GetLastError());
1777     HeapFree (GetProcessHeap(), 0, orig_lb);
1778 }
1779
1780 static void test_mf_ExtTextOut_on_path(void)
1781 {
1782     HDC hdcMetafile;
1783     HMETAFILE hMetafile;
1784     BOOL ret;
1785     static const INT dx[4] = { 3, 5, 8, 12 };
1786
1787     hdcMetafile = CreateMetaFileA(NULL);
1788     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1789     trace("hdcMetafile %p\n", hdcMetafile);
1790
1791     ret = BeginPath(hdcMetafile);
1792     ok(!ret, "BeginPath on metafile DC should fail\n");
1793
1794     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1795     ok(ret, "ExtTextOut error %d\n", GetLastError());
1796
1797     ret = EndPath(hdcMetafile);
1798     ok(!ret, "EndPath on metafile DC should fail\n");
1799
1800     hMetafile = CloseMetaFile(hdcMetafile);
1801     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1802
1803     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1804         "mf_TextOut_on_path") != 0)
1805     {
1806         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1807         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1808     }
1809
1810     ret = DeleteMetaFile(hMetafile);
1811     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1812 }
1813
1814 static void test_emf_ExtTextOut_on_path(void)
1815 {
1816     HWND hwnd;
1817     HDC hdcDisplay, hdcMetafile;
1818     HENHMETAFILE hMetafile;
1819     BOOL ret;
1820     static const INT dx[4] = { 3, 5, 8, 12 };
1821
1822     /* Win9x doesn't play EMFs on invisible windows */
1823     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1824                            0, 0, 200, 200, 0, 0, 0, NULL);
1825     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1826
1827     hdcDisplay = GetDC(hwnd);
1828     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1829
1830     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1831     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1832
1833     ret = BeginPath(hdcMetafile);
1834     ok(ret, "BeginPath error %d\n", GetLastError());
1835
1836     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1837     ok(ret, "ExtTextOut error %d\n", GetLastError());
1838
1839     ret = EndPath(hdcMetafile);
1840     ok(ret, "EndPath error %d\n", GetLastError());
1841
1842     hMetafile = CloseEnhMetaFile(hdcMetafile);
1843     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1844
1845     /* this doesn't succeed yet: EMF has correct size, all EMF records
1846      * are there, but their contents don't match for different reasons.
1847      */
1848     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1849         "emf_TextOut_on_path", FALSE) != 0)
1850     {
1851         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1852         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1853     }
1854
1855     ret = DeleteEnhMetaFile(hMetafile);
1856     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1857     ret = ReleaseDC(hwnd, hdcDisplay);
1858     ok(ret, "ReleaseDC error %d\n", GetLastError());
1859     DestroyWindow(hwnd);
1860 }
1861
1862 static const unsigned char EMF_CLIPPING[] =
1863 {
1864     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1865     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1866     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1867     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1868     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1869     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1870     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1871     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1872     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1873     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1874     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1875     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1876     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1877     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1878     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1879     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1880     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1881     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1882     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1883     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1884     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1885     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1886     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1887     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1888     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1889     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1890 };
1891
1892 static void translate( POINT *pt, UINT count, const XFORM *xform )
1893 {
1894     while (count--)
1895     {
1896         FLOAT x = (FLOAT)pt->x;
1897         FLOAT y = (FLOAT)pt->y;
1898         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1899         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1900         pt++;
1901     }
1902 }
1903
1904 /* Compare rectangles allowing rounding errors */
1905 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1906 {
1907     return abs(rc1->left - rc2->left) <= 1 &&
1908            abs(rc1->top - rc2->top) <= 1 &&
1909            abs(rc1->right - rc2->right) <= 1 &&
1910            abs(rc1->bottom - rc2->bottom) <= 1;
1911 }
1912
1913 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1914                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1915 {
1916     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1917     {
1918         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1919         union _rgn
1920         {
1921             RGNDATA data;
1922             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1923         };
1924         const union _rgn *rgn1;
1925         union _rgn rgn2;
1926         RECT rect, rc_transformed;
1927         const RECT *rc = (const RECT *)param;
1928         HRGN hrgn;
1929         XFORM xform;
1930         INT ret;
1931         BOOL is_win9x;
1932
1933         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1934                clip->cbRgnData, clip->iMode);
1935
1936         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1937         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1938            "too small data block: %u bytes\n", clip->cbRgnData);
1939         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1940             return 0;
1941
1942         rgn1 = (const union _rgn *)clip->RgnData;
1943
1944         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1945               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1946               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1947               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1948               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1949
1950         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1951
1952         rect = *(const RECT *)rgn1->data.Buffer;
1953         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1954         ok(EqualRect(&rect, rc), "rects don't match\n");
1955
1956         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1957         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1958         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1959         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
1960            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
1961            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1962
1963         hrgn = CreateRectRgn(0, 0, 0, 0);
1964
1965         memset(&xform, 0, sizeof(xform));
1966         SetLastError(0xdeadbeef);
1967         ret = GetWorldTransform(hdc, &xform);
1968         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1969         if (!is_win9x)
1970             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1971
1972         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1973
1974         ret = GetClipRgn(hdc, hrgn);
1975         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1976
1977         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1978
1979         ret = GetClipRgn(hdc, hrgn);
1980         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
1981
1982         /* Win9x returns empty clipping region */
1983         if (is_win9x) return 1;
1984
1985         ret = GetRegionData(hrgn, 0, NULL);
1986         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1987
1988         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1989
1990         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1991               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1992               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1993               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1994               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1995
1996         rect = rgn2.data.rdh.rcBound;
1997         rc_transformed = *rc;
1998         translate((POINT *)&rc_transformed, 2, &xform);
1999         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2000               rc_transformed.right, rc_transformed.bottom);
2001         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2002
2003         rect = *(const RECT *)rgn2.data.Buffer;
2004         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2005         rc_transformed = *rc;
2006         translate((POINT *)&rc_transformed, 2, &xform);
2007         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2008               rc_transformed.right, rc_transformed.bottom);
2009         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2010
2011         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2012         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2013         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2014         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2015            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2016            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2017
2018         DeleteObject(hrgn);
2019     }
2020     return 1;
2021 }
2022
2023 static void test_emf_clipping(void)
2024 {
2025     static const RECT rc = { 0, 0, 100, 100 };
2026     RECT rc_clip = { 100, 100, 1024, 1024 };
2027     HWND hwnd;
2028     HDC hdc;
2029     HENHMETAFILE hemf;
2030     HRGN hrgn;
2031     INT ret;
2032     RECT rc_res, rc_sclip;
2033
2034     SetLastError(0xdeadbeef);
2035     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2036     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2037
2038     /* Need to write something to the emf, otherwise Windows won't play it back */
2039     LineTo(hdc, 1, 1);
2040
2041     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2042     ret = SelectClipRgn(hdc, hrgn);
2043     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2044
2045     SetLastError(0xdeadbeef);
2046     hemf = CloseEnhMetaFile(hdc);
2047     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2048
2049     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2050         "emf_clipping", FALSE) != 0)
2051     {
2052         dump_emf_bits(hemf, "emf_clipping");
2053         dump_emf_records(hemf, "emf_clipping");
2054     }
2055
2056     DeleteObject(hrgn);
2057
2058     /* Win9x doesn't play EMFs on invisible windows */
2059     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2060                            0, 0, 200, 200, 0, 0, 0, NULL);
2061     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2062
2063     hdc = GetDC(hwnd);
2064
2065     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2066     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2067
2068     DeleteEnhMetaFile(hemf);
2069     ReleaseDC(hwnd, hdc);
2070     DestroyWindow(hwnd);
2071
2072     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2073
2074     SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2075     hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2076     SelectClipRgn(hdc, hrgn);
2077     ret = GetClipBox(hdc, &rc_res);
2078 todo_wine
2079     ok(ret == SIMPLEREGION, "got %d\n", ret);
2080     if(ret == SIMPLEREGION)
2081         ok(EqualRect(&rc_res, &rc_sclip),
2082                  "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2083                  rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2084                  rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2085
2086     hemf = CloseEnhMetaFile(hdc);
2087     DeleteEnhMetaFile(hemf);
2088     DeleteObject(hrgn);
2089     DeleteDC(hdc);
2090 }
2091
2092 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2093 {
2094     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2095     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2096     /* When using MM_TEXT Win9x does not update the mapping mode 
2097      * until a record is played which actually outputs something */
2098     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2099     LPtoDP(hdc, mapping, 2);
2100     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2101            lpEMFR->iType, lpEMFR->nSize,
2102            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2103
2104     if (lpEMFR->iType == EMR_LINETO)
2105     {
2106         INT x0, y0, x1, y1;
2107         if (!lpMFP || lpMFP->mm == MM_TEXT)
2108         {
2109             x0 = 0;
2110             y0 = 0;
2111             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2112             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2113         }
2114         else
2115         {
2116             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2117             
2118             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2119             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2120             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2121             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2122         }
2123         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2124             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2125             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2126             x0, y0, x1, y1);
2127     }
2128     return TRUE;
2129 }
2130
2131 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2132 {
2133     HDC hdcMf;
2134     HMETAFILE hmf;
2135     HENHMETAFILE hemf;
2136     BOOL ret;
2137     UINT size;
2138     LPBYTE pBits;
2139
2140     hdcMf = CreateMetaFile(NULL);
2141     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2142     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2143     ok(ret, "LineTo failed with error %d\n", GetLastError());
2144     hmf = CloseMetaFile(hdcMf);
2145     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2146
2147     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2148     {
2149         dump_mf_bits(hmf, "mf_LineTo");
2150         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2151     }
2152
2153     size = GetMetaFileBitsEx(hmf, 0, NULL);
2154     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2155     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2156     GetMetaFileBitsEx(hmf, size, pBits);
2157     DeleteMetaFile(hmf);
2158     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2159     HeapFree(GetProcessHeap(), 0, pBits);
2160     return hemf;
2161 }
2162
2163 static void test_mf_conversions(void)
2164 {
2165     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2166     {
2167         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2168         HENHMETAFILE hemf;
2169         METAFILEPICT mfp;
2170         RECT rect = { 0, 0, 100, 100 };
2171         mfp.mm = MM_ANISOTROPIC;
2172         mfp.xExt = 100;
2173         mfp.yExt = 100;
2174         mfp.hMF = NULL;
2175         hemf = create_converted_emf(&mfp);
2176
2177         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2178                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2179         {
2180             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2181             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2182         }
2183
2184         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2185
2186         DeleteEnhMetaFile(hemf);
2187         DeleteDC(hdcOffscreen);
2188     }
2189
2190     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2191     {
2192         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2193         HENHMETAFILE hemf;
2194         METAFILEPICT mfp;
2195         RECT rect = { 0, 0, 100, 100 };
2196         mfp.mm = MM_TEXT;
2197         mfp.xExt = 0;
2198         mfp.yExt = 0;
2199         mfp.hMF = NULL;
2200         hemf = create_converted_emf(&mfp);
2201
2202         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2203                              "emf_LineTo MM_TEXT", TRUE) != 0)
2204         {
2205             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2206             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2207         }
2208
2209         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2210
2211         DeleteEnhMetaFile(hemf);
2212         DeleteDC(hdcOffscreen);
2213     }
2214
2215     trace("Testing MF->EMF conversion (NULL mfp)\n");
2216     {
2217         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2218         HENHMETAFILE hemf;
2219         RECT rect = { 0, 0, 100, 100 };
2220         hemf = create_converted_emf(NULL);
2221
2222         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2223                              "emf_LineTo NULL", TRUE) != 0)
2224         {
2225             dump_emf_bits(hemf, "emf_LineTo NULL");
2226             dump_emf_records(hemf, "emf_LineTo NULL");
2227         }
2228
2229         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2230
2231         DeleteEnhMetaFile(hemf);
2232         DeleteDC(hdcOffscreen);
2233     }
2234 }
2235
2236 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2237                                        LONG mm, LONG xExt, LONG yExt,
2238                                        RECTL * rclBounds, RECTL * rclFrame)
2239 {
2240   METAFILEPICT mfp;
2241   METAFILEPICT * mfpPtr = NULL;
2242   HENHMETAFILE emf;
2243   ENHMETAHEADER header;
2244   UINT res;
2245
2246   if (!mfpIsNull)
2247   {
2248     mfp.mm = mm;
2249     mfp.xExt = xExt;
2250     mfp.yExt = yExt;
2251     mfpPtr = &mfp;
2252   }
2253
2254   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2255   ok(emf != NULL, "SetWinMetaFileBits failed\n");
2256   if (!emf) return FALSE;
2257   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2258   ok(res != 0, "GetEnhMetaHeader failed\n");
2259   DeleteEnhMetaFile(emf);
2260   if (!res) return FALSE;
2261
2262   *rclBounds = header.rclBounds;
2263   *rclFrame = header.rclFrame;
2264   return TRUE;
2265 }
2266
2267 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2268                                          LONG mm, LONG xExt, LONG yExt,
2269                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2270 {
2271   RECTL rclBounds, rclFrame;
2272
2273   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2274   {
2275     const char * msg;
2276     char buf[64];
2277
2278     if (mfpIsNull)
2279     {
2280        msg = "mfp == NULL";
2281     }
2282     else
2283     {
2284       const char * mm_str;
2285       switch (mm)
2286       {
2287          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2288          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
2289          default:             mm_str = "Unexpected";
2290       }
2291       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2292       msg = buf;
2293     }
2294
2295     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2296     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2297     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2298     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2299     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2300     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2301     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2302     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2303   }
2304 }
2305
2306 static void test_SetWinMetaFileBits(void)
2307 {
2308   HMETAFILE wmf;
2309   HDC wmfDC;
2310   BYTE * buffer;
2311   UINT buffer_size;
2312   RECT rect;
2313   UINT res;
2314   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2315   RECTL rclBoundsIsotropic, rclFrameIsotropic;
2316   RECTL rclBounds, rclFrame;
2317   HDC dc;
2318   LONG diffx, diffy;
2319
2320   wmfDC = CreateMetaFile(NULL);
2321   ok(wmfDC != NULL, "CreateMetaFile failed\n");
2322   if (!wmfDC) return;
2323
2324   SetWindowExtEx(wmfDC, 100, 100, NULL);
2325   rect.left = rect.top = 0;
2326   rect.right = rect.bottom = 50;
2327   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2328   wmf = CloseMetaFile(wmfDC);
2329   ok(wmf != NULL, "Metafile creation failed\n");
2330   if (!wmf) return;
2331
2332   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2333   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2334   if (buffer_size == 0)
2335   {
2336     DeleteMetaFile(wmf);
2337     return;
2338   }
2339
2340   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2341   ok(buffer != NULL, "HeapAlloc failed\n");
2342   if (!buffer)
2343   {
2344     DeleteMetaFile(wmf);
2345     return;
2346   }
2347
2348   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2349   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2350   DeleteMetaFile(wmf);
2351   if (res != buffer_size)
2352   {
2353      HeapFree(GetProcessHeap(), 0, buffer);
2354      return;
2355   }
2356
2357   /* Get the reference bounds and frame */
2358   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2359   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
2360
2361   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2362      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2363      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2364
2365   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2366   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2367   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2368   if (diffx < 0) diffx = -diffx;
2369   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2370
2371   dc = CreateCompatibleDC(NULL);
2372
2373   /* Allow 1 mm difference (rounding errors) */
2374   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2375   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2376   if (diffx < 0) diffx = -diffx;
2377   if (diffy < 0) diffy = -diffy;
2378   todo_wine
2379   {
2380   ok(diffx <= 1 && diffy <= 1,
2381      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2382      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2383   }
2384
2385   /* Allow 1 mm difference (rounding errors) */
2386   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2387   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2388   if (diffx < 0) diffx = -diffx;
2389   if (diffy < 0) diffy = -diffy;
2390   todo_wine
2391   {
2392   ok(diffx <= 1 && diffy <= 1,
2393      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2394      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2395   }
2396   DeleteDC(dc);
2397
2398   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2399   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2400
2401   /* If xExt or yExt is zero or negative, the whole device surface is used */
2402   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2403   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2404   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2405   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2406   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2407   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2408   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2409   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2410   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2411   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2412   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2413   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2414
2415   /* MSDN says that negative xExt and yExt values specify a ratio.
2416      Check that this is wrong and the whole device surface is used */
2417   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2418   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2419
2420   /* Ordinary conversions */
2421
2422   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2423   {
2424     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2425        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2426     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2427        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2428   }
2429
2430   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2431   {
2432     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2433        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2434     ok(rclBounds.left == 0 && rclBounds.top == 0,
2435        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2436
2437     /* Wine has a rounding error */
2438     diffx = rclBounds.right - rclBounds.bottom;
2439     if (diffx < 0) diffx = -diffx;
2440     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2441   }
2442
2443   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2444   {
2445     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2446        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2447   }
2448
2449   HeapFree(GetProcessHeap(), 0, buffer);
2450 }
2451
2452 static BOOL near_match(int x, int y)
2453 {
2454     int epsilon = min(abs(x), abs(y));
2455
2456     epsilon = max(epsilon/100, 2);
2457
2458     if(x < y - epsilon || x > y + epsilon) return FALSE;
2459     return TRUE;
2460 }
2461
2462 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2463 {
2464     HENHMETAFILE emf;
2465     HDC display_dc, emf_dc;
2466     ENHMETAHEADER *enh_header;
2467     UINT size, emf_size, i;
2468     WORD check = 0;
2469     DWORD rec_num = 0;
2470     METAHEADER *mh = NULL;
2471     METARECORD *rec;
2472     INT horz_res, vert_res, horz_size, vert_size;
2473
2474     display_dc = GetDC(NULL);
2475     ok(display_dc != NULL, "display_dc is NULL\n");
2476
2477     horz_res = GetDeviceCaps(display_dc, HORZRES);
2478     vert_res = GetDeviceCaps(display_dc, VERTRES);
2479     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2480     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2481
2482     emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2483     ok(emf_dc != NULL, "emf_dc is NULL\n");
2484     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2485         Rectangle(emf_dc, 0, 0, 1000, 20);
2486     emf = CloseEnhMetaFile(emf_dc);
2487     ok(emf != NULL, "emf is NULL\n");
2488
2489     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2490     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2491     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2492     DeleteEnhMetaFile(emf);
2493     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2494        have different resolutions */
2495     enh_header->szlDevice.cx *= scale;
2496     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2497     ok(emf != NULL, "emf is NULL\n");
2498     ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2499
2500     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2501     ok(size ||
2502        broken(size == 0), /* some versions of winxp fail for some reason */
2503        "GetWinMetaFileBits returns 0\n");
2504     if(!size) goto end;
2505     mh = HeapAlloc(GetProcessHeap(), 0, size);
2506     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2507
2508     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2509     ok(check == 0, "check %04x\n", check);
2510
2511     rec = (METARECORD*)(mh + 1);
2512
2513     while(rec->rdSize && rec->rdFunction)
2514     {
2515         const DWORD chunk_size = 0x2000;
2516         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2517
2518         if(rec_num < mfcomment_chunks)
2519         {
2520             DWORD this_chunk_size = chunk_size;
2521
2522             if(rec_num == mfcomment_chunks - 1)
2523                 this_chunk_size = emf_size - rec_num * chunk_size;
2524
2525             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2526             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2527             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2528             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2529             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2530             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2531             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
2532             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2533             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2534             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2535             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2536             /* parm[8] is the checksum, tested above */
2537             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2538             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2539             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2540             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2541             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2542             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2543             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2544             ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15));  /* DWORD size remaining after current chunk */
2545             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2546             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2547         }
2548
2549         else if(rec_num == mfcomment_chunks)
2550         {
2551             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2552             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2553         }
2554         else if(rec_num == mfcomment_chunks + 1)
2555         {
2556             POINT pt;
2557             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2558             switch(mode)
2559             {
2560             case MM_TEXT:
2561             case MM_ISOTROPIC:
2562             case MM_ANISOTROPIC:
2563                 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2564                 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2565                 break;
2566             case MM_LOMETRIC:
2567                 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2568                 pt.x = MulDiv( rc->left, 1, 10);
2569                 break;
2570             case MM_HIMETRIC:
2571                 pt.y = -rc->top + 1;
2572                 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2573                 break;
2574             case MM_LOENGLISH:
2575                 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2576                 pt.x = MulDiv( rc->left, 10, 254);
2577                 break;
2578             case MM_HIENGLISH:
2579                 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2580                 pt.x = MulDiv( rc->left, 100, 254);
2581                 break;
2582             case MM_TWIPS:
2583                 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2584                 pt.x = MulDiv( rc->left, 72 * 20, 2540);
2585                 break;
2586             default:
2587                 pt.x = pt.y = 0;
2588             }
2589             ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
2590             ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
2591         }
2592         if(rec_num == mfcomment_chunks + 2)
2593         {
2594             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
2595             ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
2596                "got %d\n", (short)rec->rdParm[0]);
2597             ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
2598                "got %d\n", (short)rec->rdParm[1]);
2599         }
2600
2601         rec_num++;
2602         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
2603     }
2604
2605 end:
2606     HeapFree(GetProcessHeap(), 0, mh);
2607     HeapFree(GetProcessHeap(), 0, enh_header);
2608     DeleteEnhMetaFile(emf);
2609
2610     ReleaseDC(NULL, display_dc);
2611 }
2612
2613 static void test_GetWinMetaFileBits(void)
2614 {
2615     UINT mode;
2616     RECT frames[] =
2617     {
2618         { 1000,  2000, 3000, 6000},
2619         {-1000,  2000, 3000, 6000},
2620         { 1000, -2000, 3000, 6000},
2621         { 1005,  2005, 3000, 6000},
2622         {-1005, -2005, 3000, 6000},
2623         {-1005, -2010, 3000, 6000},
2624         {-1005,  2010, 3000, 6000},
2625         {    0,     0,    1,    1},
2626         {   -1,    -1,    1,    1},
2627         {    0,     0,    0,    0}
2628     };
2629
2630     for(mode = MM_MIN; mode <= MM_MAX; mode++)
2631     {
2632         RECT *rc;
2633         trace("mode %d\n", mode);
2634
2635         for(rc = frames; rc->right - rc->left > 0; rc++)
2636         {
2637             trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
2638             getwinmetafilebits(mode, 1, rc);
2639             getwinmetafilebits(mode, 2, rc);
2640         }
2641     }
2642 }
2643
2644 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2645 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2646 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2647
2648 static void test_gdiis(void)
2649 {
2650     RECT rect = {0,0,100,100};
2651     HDC hdc, hemfDC, hmfDC;
2652     HENHMETAFILE hemf;
2653     HMODULE hgdi32;
2654
2655     /* resolve all the functions */
2656     hgdi32 = GetModuleHandle("gdi32");
2657     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2658     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2659     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2660
2661     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2662     {
2663         win_skip("Needed GdiIs* functions are not available\n");
2664         return;
2665     }
2666
2667     /* try with nothing */
2668     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2669     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2670     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2671
2672     /* try with a metafile */
2673     hmfDC = CreateMetaFile(NULL);
2674     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2675     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2676     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2677     DeleteMetaFile(CloseMetaFile(hmfDC));
2678
2679     /* try with an enhanced metafile */
2680     hdc = GetDC(NULL);
2681     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2682     ok(hemfDC != NULL, "failed to create emf\n");
2683
2684     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2685     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2686     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2687
2688     hemf = CloseEnhMetaFile(hemfDC);
2689     ok(hemf != NULL, "failed to close EMF\n");
2690     DeleteEnhMetaFile(hemf);
2691     ReleaseDC(NULL,hdc);
2692 }
2693
2694 static void test_SetEnhMetaFileBits(void)
2695 {
2696     BYTE data[256];
2697     HENHMETAFILE hemf;
2698     ENHMETAHEADER *emh;
2699
2700     memset(data, 0xAA, sizeof(data));
2701     SetLastError(0xdeadbeef);
2702     hemf = SetEnhMetaFileBits(sizeof(data), data);
2703     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2704     ok(GetLastError() == ERROR_INVALID_DATA ||
2705        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2706        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2707
2708     emh = (ENHMETAHEADER *)data;
2709     memset(emh, 0, sizeof(*emh));
2710
2711     emh->iType = EMR_HEADER;
2712     emh->nSize = sizeof(*emh);
2713     emh->dSignature = ENHMETA_SIGNATURE;
2714     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2715     emh->nBytes = sizeof(*emh);
2716     /* emh->nRecords = 1; XP doesn't care about records */
2717     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2718
2719     SetLastError(0xdeadbeef);
2720     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2721     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2722     DeleteEnhMetaFile(hemf);
2723
2724     /* XP refuses to load unaligned EMF */
2725     emh->nBytes++;
2726     SetLastError(0xdeadbeef);
2727     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2728     ok(!hemf ||
2729        broken(hemf != NULL), /* Win9x, WinMe */
2730        "SetEnhMetaFileBits should fail\n");
2731     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2732     DeleteEnhMetaFile(hemf);
2733
2734     emh->dSignature = 0;
2735     emh->nBytes--;
2736     SetLastError(0xdeadbeef);
2737     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2738     ok(!hemf ||
2739        broken(hemf != NULL), /* Win9x, WinMe */
2740        "SetEnhMetaFileBits should fail\n");
2741     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2742     DeleteEnhMetaFile(hemf);
2743 }
2744
2745 START_TEST(metafile)
2746 {
2747     init_function_pointers();
2748
2749     /* For enhanced metafiles (enhmfdrv) */
2750     test_ExtTextOut();
2751     test_SaveDC();
2752     test_emf_BitBlt();
2753
2754     /* For win-format metafiles (mfdrv) */
2755     test_mf_SaveDC();
2756     test_mf_Blank();
2757     test_mf_Graphics();
2758     test_mf_PatternBrush();
2759     test_CopyMetaFile();
2760     test_SetMetaFileBits();
2761     test_mf_ExtTextOut_on_path();
2762     test_emf_ExtTextOut_on_path();
2763     test_emf_clipping();
2764
2765     /* For metafile conversions */
2766     test_mf_conversions();
2767     test_SetWinMetaFileBits();
2768     test_GetWinMetaFileBits();
2769
2770     test_gdiis();
2771     test_SetEnhMetaFileBits();
2772 }