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