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