crypt32/tests: Fix some test failures on Win9x.
[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
334     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
335            hdc, emr->iType, emr->nSize, (void *)param);
336
337     trace("BEFORE:\n");
338     SetLastError(0xdeadbeef);
339     ret = GetWorldTransform(hdc, &xform);
340     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
341     {
342         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
343         trace("window org (%d,%d)\n", pt.x, pt.y);
344         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
345         trace("vport org (%d,%d)\n", pt.x, pt.y);
346         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
347         trace("window ext (%d,%d)\n", size.cx, size.cy);
348         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
349         trace("vport ext (%d,%d)\n", size.cx, size.cy);
350     }
351     else
352     {
353         ok(ret, "GetWorldTransform error %u\n", GetLastError());
354         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
355     }
356
357     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
358
359     switch (emr->iType)
360     {
361     case EMR_HEADER:
362     {
363         static RECT exp_bounds = { 0, 0, 150, 150 };
364         RECT bounds;
365         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
366
367         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
368                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
369                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
370         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
371                emf->szlDevice.cx, emf->szlDevice.cy);
372
373         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
374         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
375
376         save_state = 0;
377         restore_no = 0;
378         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
379         break;
380     }
381
382     case EMR_LINETO:
383         {
384             const EMRLINETO *line = (const EMRLINETO *)emr;
385             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
386             break;
387         }
388     case EMR_SETWINDOWORGEX:
389         {
390             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
391             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
392             break;
393         }
394     case EMR_SETWINDOWEXTEX:
395         {
396             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
397             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
398             break;
399         }
400     case EMR_SETVIEWPORTORGEX:
401         {
402             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
403             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
404             break;
405         }
406     case EMR_SETVIEWPORTEXTEX:
407         {
408             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
409             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
410             break;
411         }
412     case EMR_SAVEDC:
413         save_state++;
414         trace("EMR_SAVEDC\n");
415         break;
416
417     case EMR_RESTOREDC:
418         {
419             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
420             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
421
422             switch(++restore_no)
423             {
424             case 1:
425                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
426                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
427                 break;
428             case 2:
429                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
430                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
431                 break;
432             case 3:
433                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
434                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
435                 break;
436             }
437             ok(restore_no <= 3, "restore_no %d\n", restore_no);
438             save_state += restoredc->iRelative;
439             break;
440         }
441     case EMR_EOF:
442         ok(save_state == 0, "EOF save_state %d\n", save_state);
443         break;
444     }
445
446     trace("AFTER:\n");
447     SetLastError(0xdeadbeef);
448     ret = GetWorldTransform(hdc, &xform);
449     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
450     {
451         ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
452         trace("window org (%d,%d)\n", pt.x, pt.y);
453         ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
454         trace("vport org (%d,%d)\n", pt.x, pt.y);
455         ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
456         trace("window ext (%d,%d)\n", size.cx, size.cy);
457         ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
458         trace("vport ext (%d,%d)\n", size.cx, size.cy);
459     }
460     else
461     {
462         ok(ret, "GetWorldTransform error %u\n", GetLastError());
463         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
464     }
465
466     return 1;
467 }
468
469 static void test_SaveDC(void)
470 {
471     HDC hdcMetafile, hdcDisplay;
472     HENHMETAFILE hMetafile;
473     HWND hwnd;
474     int ret;
475     static const RECT rc = { 0, 0, 150, 150 };
476
477     /* Win9x doesn't play EMFs on invisible windows */
478     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
479                            0, 0, 200, 200, 0, 0, 0, NULL);
480     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
481
482     hdcDisplay = GetDC(hwnd);
483     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
484
485     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
486     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
487
488     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
489
490     /* Need to write something to the emf, otherwise Windows won't play it back */
491     LineTo(hdcMetafile, 150, 150);
492
493     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
494     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
495     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
496     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
497
498     /* Force Win9x to update DC state */
499     SetPixelV(hdcMetafile, 50, 50, 0);
500
501     ret = SaveDC(hdcMetafile);
502     ok(ret == 1, "ret = %d\n", ret);
503
504     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
505     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
506     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
507     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
508
509     /* Force Win9x to update DC state */
510     SetPixelV(hdcMetafile, 50, 50, 0);
511
512     ret = SaveDC(hdcMetafile);
513     ok(ret == 2, "ret = %d\n", ret);
514
515     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
516     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
517     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
518     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
519
520     /* Force Win9x to update DC state */
521     SetPixelV(hdcMetafile, 50, 50, 0);
522
523     ret = SaveDC(hdcMetafile);
524     ok(ret == 3, "ret = %d\n", ret);
525
526     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
527     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
528     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
529     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
530
531     /* Force Win9x to update DC state */
532     SetPixelV(hdcMetafile, 50, 50, 0);
533
534     ret = RestoreDC(hdcMetafile, -1);
535     ok(ret, "ret = %d\n", ret);
536
537     ret = SaveDC(hdcMetafile);
538     ok(ret == 3, "ret = %d\n", ret);
539
540     ret = RestoreDC(hdcMetafile, 1);
541     ok(ret, "ret = %d\n", ret);
542
543     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
544     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
545     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
546     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
547
548     /* Force Win9x to update DC state */
549     SetPixelV(hdcMetafile, 50, 50, 0);
550
551     ret = SaveDC(hdcMetafile);
552     ok(ret == 1, "ret = %d\n", ret);
553
554     ret = SaveDC(hdcMetafile);
555     ok(ret == 2, "ret = %d\n", ret);
556
557     hMetafile = CloseEnhMetaFile(hdcMetafile);
558     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
559
560     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
561     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
562
563     ret = DeleteEnhMetaFile(hMetafile);
564     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
565     ret = ReleaseDC(hwnd, hdcDisplay);
566     ok( ret, "ReleaseDC error %d\n", GetLastError());
567     DestroyWindow(hwnd);
568 }
569
570 /* Win-format metafile (mfdrv) tests */
571 /* These tests compare the generated metafiles byte-by-byte */
572 /* with the nominal results. */
573
574 /* Maximum size of sample metafiles in bytes. */
575 #define MF_BUFSIZE 512
576
577 /* 8x8 bitmap data for a pattern brush */
578 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
579     0x01, 0x00, 0x02, 0x00,
580     0x03, 0x00, 0x04, 0x00,
581     0x05, 0x00, 0x06, 0x00,
582     0x07, 0x00, 0x08, 0x00
583 };
584
585 /* Sample metafiles to be compared to the outputs of the
586  * test functions.
587  */
588
589 static const unsigned char MF_BLANK_BITS[] = {
590     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
591     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
592     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
593 };
594
595 static const unsigned char MF_GRAPHICS_BITS[] = {
596     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
597     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
598     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
599     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
600     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
601     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
602     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
603     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
604     0x00, 0x00, 0x00, 0x00
605 };
606
607 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
608     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
609     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
610     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
611     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
612     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
613     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
614     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
618     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
619     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
620     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
621     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
622     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
623     0x00, 0x00
624 };
625
626 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
627 {
628     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
629     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
630     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
631     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
632     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
633     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
634     0x00, 0x00
635 };
636
637 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
638 {
639     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
640     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
642     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
644     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
645     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
646     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
649     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
650     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
652     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
653     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
654     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
656     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
657     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
658     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
659     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
660     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
662     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
663     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
664     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
665     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
666     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
667     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
668     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
669     0x14, 0x00, 0x00, 0x00
670 };
671
672 static const unsigned char MF_LINETO_BITS[] = {
673     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
674     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
675     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
676     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
677     0x00, 0x00
678 };
679
680 static const unsigned char EMF_LINETO_BITS[] = {
681     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
682     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
684     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
686     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
687     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
688     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
691     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
692     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
694     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
695     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
696     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
697     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
698     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
699     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
700     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
701     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
702     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
703     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
704     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
705     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
706     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
707     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
708     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
709     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
710     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
711     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
712     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
713     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
714     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
715     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
716     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
718     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
719     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
720 };
721
722 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
723     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
724     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
725     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
726     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
727     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
728     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
729     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
730     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
733     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
734     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
736     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
737     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
738     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
739     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
740     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
741     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
742     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
743     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
744     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
745     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
746     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
747     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
748     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
749     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
750     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
751     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
752     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
753     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
754     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
755     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
756     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
757     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
758     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
760     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
762 };
763
764 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
765     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
766     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
768     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
770     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
771     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
772     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
775     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
776     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
778     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
779     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
780     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
781     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
782     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
783     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
784     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
785     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
786     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
787     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
788     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
789     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
790     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
791     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
792     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
793     0x14, 0x00, 0x00, 0x00
794 };
795
796 /* For debugging or dumping the raw metafiles produced by
797  * new test functions.
798  */
799 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
800                                  INT nobj, LPARAM param)
801 {
802     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
803            hdc, mr->rdFunction, mr->rdSize, (void *)param);
804     return TRUE;
805 }
806
807 /* For debugging or dumping the raw metafiles produced by
808  * new test functions.
809  */
810
811 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
812 {
813     BYTE buf[MF_BUFSIZE];
814     UINT mfsize, i;
815
816     if (!winetest_debug) return;
817
818     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
819     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
820
821     printf ("MetaFile %s has bits:\n{\n    ", desc);
822     for (i=0; i<mfsize; i++)
823     {
824         printf ("0x%02x", buf[i]);
825         if (i == mfsize-1)
826             printf ("\n");
827         else if (i % 8 == 7)
828             printf (",\n    ");
829         else
830             printf (", ");
831     }
832     printf ("};\n");
833 }
834
835 /* Compare the metafile produced by a test function with the
836  * expected raw metafile data in "bits".
837  * Return value is 0 for a perfect match,
838  * -1 if lengths aren't equal,
839  * otherwise returns the number of non-matching bytes.
840  */
841
842 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
843     const char *desc)
844 {
845     unsigned char buf[MF_BUFSIZE];
846     UINT mfsize, i;
847     int diff;
848
849     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
850     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
851     if (mfsize < MF_BUFSIZE)
852         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
853             desc, mfsize, bsize);
854     else
855         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
856             desc, mfsize, bsize);
857     if (mfsize != bsize)
858         return -1;
859
860     diff = 0;
861     for (i=0; i<bsize; i++)
862     {
863        if (buf[i] !=  bits[i])
864            diff++;
865     }
866     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
867         desc, mfsize, bsize, diff);
868
869     return diff; 
870 }
871
872 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
873 {
874     unsigned char buf[MF_BUFSIZE];
875     DWORD mfsize, rd_size, i;
876     int diff;
877     HANDLE hfile;
878     BOOL ret;
879
880     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
881     assert(hfile != INVALID_HANDLE_VALUE);
882
883     mfsize = GetFileSize(hfile, NULL);
884     assert(mfsize <= MF_BUFSIZE);
885
886     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
887     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
888
889     CloseHandle(hfile);
890
891     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
892
893     if (mfsize != bsize)
894         return -1;
895
896     diff = 0;
897     for (i=0; i<bsize; i++)
898     {
899         if (buf[i] != bits[i])
900             diff++;
901     }
902     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
903         desc, mfsize, bsize, diff);
904
905     return diff; 
906 }
907
908 /* For debugging or dumping the raw EMFs produced by
909  * new test functions.
910  */
911 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
912 {
913     BYTE buf[MF_BUFSIZE];
914     UINT mfsize, i;
915
916     if (!winetest_debug) return;
917
918     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
919     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
920
921     printf("EMF %s has bits:\n{\n    ", desc);
922     for (i = 0; i < mfsize; i++)
923     {
924         printf ("0x%02x", buf[i]);
925         if (i == mfsize-1)
926             printf ("\n");
927         else if (i % 8 == 7)
928             printf (",\n    ");
929         else
930             printf (", ");
931     }
932     printf ("};\n");
933 }
934
935 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
936 {
937     BYTE *emf;
938     BYTE buf[MF_BUFSIZE];
939     UINT mfsize, offset;
940
941     if (!winetest_debug) return;
942
943     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
944     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
945
946     printf("EMF %s has records:\n", desc);
947
948     emf = buf;
949     offset = 0;
950     while(offset < mfsize)
951     {
952         EMR *emr = (EMR *)(emf + offset);
953         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
954         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
955         offset += emr->nSize;
956     }
957 }
958
959 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
960 {
961     const BYTE *buf;
962     DWORD i;
963
964     if (!winetest_debug) return;
965
966     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
967     buf = (const BYTE *)emr;
968     for (i = 0; i < emr->nSize; i++)
969     {
970         printf ("0x%02x", buf[i]);
971         if (i == emr->nSize - 1)
972             printf ("\n");
973         else if (i % 8 == 7)
974             printf (",\n");
975         else
976             printf (", ");
977     }
978     printf ("};\n");
979 }
980
981 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
982 {
983     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
984           eto->rclBounds.right, eto->rclBounds.bottom);
985     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
986     trace("exScale: %f\n", eto->exScale);
987     trace("eyScale: %f\n", eto->eyScale);
988     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
989     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
990     trace("emrtext.offString %#x\n", eto->emrtext.offString);
991     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
992     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
993           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
994     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
995 }
996
997 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
998                              const char *desc, BOOL ignore_scaling)
999 {
1000     int diff;
1001
1002     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1003        desc, emr1->iType, emr2->iType);
1004
1005     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1006        desc, emr1->nSize, emr2->nSize);
1007
1008     /* iType and nSize mismatches are fatal */
1009     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1010
1011     /* contents of EMR_GDICOMMENT are not interesting */
1012     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1013
1014     /* different Windows versions setup DC scaling differently when
1015      * converting an old style metafile to an EMF.
1016      */
1017     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1018                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1019         return TRUE;
1020
1021     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1022     {
1023         EMREXTTEXTOUTW *eto1, *eto2;
1024
1025         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1026         memcpy(eto1, emr1, emr1->nSize);
1027         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1028         memcpy(eto2, emr2, emr2->nSize);
1029
1030         /* different Windows versions setup DC scaling differently */
1031         eto1->exScale = eto1->eyScale = 0.0;
1032         eto2->exScale = eto2->eyScale = 0.0;
1033
1034         diff = memcmp(eto1, eto2, emr1->nSize);
1035         if (diff)
1036         {
1037             dump_EMREXTTEXTOUT(eto1);
1038             dump_EMREXTTEXTOUT(eto2);
1039         }
1040         HeapFree(GetProcessHeap(), 0, eto1);
1041         HeapFree(GetProcessHeap(), 0, eto2);
1042     }
1043     else
1044         diff = memcmp(emr1, emr2, emr1->nSize);
1045
1046     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1047
1048     if (diff)
1049     {
1050         dump_emf_record(emr1, "expected bits");
1051         dump_emf_record(emr2, "actual bits");
1052     }
1053
1054     return diff == 0; /* report all non-fatal record mismatches */
1055 }
1056
1057 /* Compare the EMF produced by a test function with the
1058  * expected raw EMF data in "bits".
1059  * Return value is 0 for a perfect match,
1060  * -1 if lengths aren't equal,
1061  * otherwise returns the number of non-matching bytes.
1062  */
1063 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1064                             UINT bsize, const char *desc,
1065                             BOOL ignore_scaling)
1066 {
1067     unsigned char buf[MF_BUFSIZE];
1068     UINT mfsize, offset;
1069     const ENHMETAHEADER *emh1, *emh2;
1070
1071     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1072     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1073
1074     if (mfsize < MF_BUFSIZE)
1075     {
1076         ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1077     }
1078     else
1079         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1080            desc, mfsize, bsize);
1081
1082     /* basic things must match */
1083     emh1 = (const ENHMETAHEADER *)bits;
1084     emh2 = (const ENHMETAHEADER *)buf;
1085     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1086     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1087     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1088     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1089
1090     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1091     ok(emh1->nSize == emh2->nSize, "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1092     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1093     ok(emh1->nBytes == emh2->nBytes, "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1094     ok(emh1->nRecords == emh2->nRecords, "expected nBytes %u, got %u\n", emh1->nRecords, emh2->nRecords);
1095
1096     offset = emh1->nSize;
1097     while (offset < emh1->nBytes)
1098     {
1099         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset);
1100         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset);
1101
1102         trace("EMF record %u, size %u/record %u, size %u\n",
1103               emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1104
1105         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1106
1107         offset += emr1->nSize;
1108     }
1109     return 0;
1110 }
1111
1112 /* Test a blank metafile.  May be used as a template for new tests. */
1113
1114 static void test_mf_Blank(void)
1115 {
1116     HDC hdcMetafile;
1117     HMETAFILE hMetafile;
1118     INT caps;
1119     BOOL ret;
1120     INT type;
1121
1122     hdcMetafile = CreateMetaFileA(NULL);
1123     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1124     trace("hdcMetafile %p\n", hdcMetafile);
1125
1126 /* Tests on metafile initialization */
1127     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1128     ok (caps == DT_METAFILE,
1129         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1130
1131     hMetafile = CloseMetaFile(hdcMetafile);
1132     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1133     type = GetObjectType(hMetafile);
1134     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1135     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1136
1137     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1138         "mf_blank") != 0)
1139     {
1140         dump_mf_bits(hMetafile, "mf_Blank");
1141         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1142     }
1143
1144     ret = DeleteMetaFile(hMetafile);
1145     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1146 }
1147
1148 static void test_CopyMetaFile(void)
1149 {
1150     HDC hdcMetafile;
1151     HMETAFILE hMetafile, hmf_copy;
1152     BOOL ret;
1153     char temp_path[MAX_PATH];
1154     char mf_name[MAX_PATH];
1155     INT type;
1156
1157     hdcMetafile = CreateMetaFileA(NULL);
1158     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1159     trace("hdcMetafile %p\n", hdcMetafile);
1160
1161     hMetafile = CloseMetaFile(hdcMetafile);
1162     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1163     type = GetObjectType(hMetafile);
1164     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1165
1166     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1167         "mf_blank") != 0)
1168     {
1169         dump_mf_bits(hMetafile, "mf_Blank");
1170         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1171     }
1172
1173     GetTempPathA(MAX_PATH, temp_path);
1174     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1175
1176     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1177     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1178
1179     type = GetObjectType(hmf_copy);
1180     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1181
1182     ret = DeleteMetaFile(hMetafile);
1183     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1184
1185     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1186     {
1187         dump_mf_bits(hMetafile, "mf_Blank");
1188         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1189     }
1190
1191     ret = DeleteMetaFile(hmf_copy);
1192     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1193
1194     DeleteFileA(mf_name);
1195 }
1196
1197 static void test_SetMetaFileBits(void)
1198 {
1199     HMETAFILE hmf;
1200     INT type;
1201     BOOL ret;
1202     BYTE buf[256];
1203     METAHEADER *mh;
1204
1205     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1206     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1207     type = GetObjectType(hmf);
1208     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1209
1210     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1211     {
1212         dump_mf_bits(hmf, "mf_Graphics");
1213         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1214     }
1215
1216     ret = DeleteMetaFile(hmf);
1217     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1218
1219     /* NULL data crashes XP SP1 */
1220     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1221
1222     /* Now with not zero size */
1223     SetLastError(0xdeadbeef);
1224     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1225     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1226     ok(GetLastError() == ERROR_INVALID_DATA ||
1227        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1228        "wrong error %d\n", GetLastError());
1229
1230     /* Now with not even size */
1231     SetLastError(0xdeadbeef);
1232     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1233     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1234     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1235
1236     /* Now with zeroed out or faked some header fields */
1237     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1238     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1239     mh = (METAHEADER *)buf;
1240     /* corruption of any of the below fields leads to a failure */
1241     mh->mtType = 0;
1242     mh->mtVersion = 0;
1243     mh->mtHeaderSize = 0;
1244     SetLastError(0xdeadbeef);
1245     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1246     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1247     ok(GetLastError() == ERROR_INVALID_DATA ||
1248        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1249        "wrong error %d\n", GetLastError());
1250
1251     /* Now with corrupted mtSize field */
1252     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1253     mh = (METAHEADER *)buf;
1254     /* corruption of mtSize doesn't lead to a failure */
1255     mh->mtSize *= 2;
1256     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1257     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1258
1259     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1260     {
1261         dump_mf_bits(hmf, "mf_Graphics");
1262         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1263     }
1264
1265     ret = DeleteMetaFile(hmf);
1266     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1267
1268     /* Now with zeroed out mtSize field */
1269     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1270     mh = (METAHEADER *)buf;
1271     /* zeroing mtSize doesn't lead to a failure */
1272     mh->mtSize = 0;
1273     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1274     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1275
1276     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1277     {
1278         dump_mf_bits(hmf, "mf_Graphics");
1279         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1280     }
1281
1282     ret = DeleteMetaFile(hmf);
1283     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1284 }
1285
1286 /* Simple APIs from mfdrv/graphics.c
1287  */
1288
1289 static void test_mf_Graphics(void)
1290 {
1291     HDC hdcMetafile;
1292     HMETAFILE hMetafile;
1293     POINT oldpoint;
1294     BOOL ret;
1295
1296     hdcMetafile = CreateMetaFileA(NULL);
1297     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1298     trace("hdcMetafile %p\n", hdcMetafile);
1299
1300     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1301     ok( ret, "MoveToEx error %d.\n", GetLastError());
1302     ret = LineTo(hdcMetafile, 2, 2);
1303     ok( ret, "LineTo error %d.\n", GetLastError());
1304     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1305     ok( ret, "MoveToEx error %d.\n", GetLastError());
1306
1307 /* oldpoint gets garbage under Win XP, so the following test would
1308  * work under Wine but fails under Windows:
1309  *
1310  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1311  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1312  *       oldpoint.x, oldpoint.y);
1313  */
1314
1315     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1316     ok( ret, "Ellipse error %d.\n", GetLastError());
1317
1318     hMetafile = CloseMetaFile(hdcMetafile);
1319     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1320     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1321
1322     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1323         "mf_Graphics") != 0)
1324     {
1325         dump_mf_bits(hMetafile, "mf_Graphics");
1326         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1327     }
1328
1329     ret = DeleteMetaFile(hMetafile);
1330     ok( ret, "DeleteMetaFile(%p) error %d\n",
1331         hMetafile, GetLastError());
1332 }
1333
1334 static void test_mf_PatternBrush(void)
1335 {
1336     HDC hdcMetafile;
1337     HMETAFILE hMetafile;
1338     LOGBRUSH *orig_lb;
1339     HBRUSH hBrush;
1340     BOOL ret;
1341
1342     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1343
1344     orig_lb->lbStyle = BS_PATTERN;
1345     orig_lb->lbColor = RGB(0, 0, 0);
1346     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1347     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1348
1349     hBrush = CreateBrushIndirect (orig_lb);
1350     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1351
1352     hdcMetafile = CreateMetaFileA(NULL);
1353     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1354     trace("hdcMetafile %p\n", hdcMetafile);
1355
1356     hBrush = SelectObject(hdcMetafile, hBrush);
1357     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1358
1359     hMetafile = CloseMetaFile(hdcMetafile);
1360     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1361     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1362
1363     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1364         "mf_Pattern_Brush") != 0)
1365     {
1366         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1367         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1368     }
1369
1370     ret = DeleteMetaFile(hMetafile);
1371     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1372     ret = DeleteObject(hBrush);
1373     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1374     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1375     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1376         GetLastError());
1377     HeapFree (GetProcessHeap(), 0, orig_lb);
1378 }
1379
1380 static void test_mf_ExtTextOut_on_path(void)
1381 {
1382     HDC hdcMetafile;
1383     HMETAFILE hMetafile;
1384     BOOL ret;
1385     static const INT dx[4] = { 3, 5, 8, 12 };
1386
1387     hdcMetafile = CreateMetaFileA(NULL);
1388     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1389     trace("hdcMetafile %p\n", hdcMetafile);
1390
1391     ret = BeginPath(hdcMetafile);
1392     ok(!ret, "BeginPath on metafile DC should fail\n");
1393
1394     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1395     ok(ret, "ExtTextOut error %d\n", GetLastError());
1396
1397     ret = EndPath(hdcMetafile);
1398     ok(!ret, "EndPath on metafile DC should fail\n");
1399
1400     hMetafile = CloseMetaFile(hdcMetafile);
1401     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1402
1403     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1404         "mf_TextOut_on_path") != 0)
1405     {
1406         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1407         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1408     }
1409
1410     ret = DeleteMetaFile(hMetafile);
1411     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1412 }
1413
1414 static void test_emf_ExtTextOut_on_path(void)
1415 {
1416     HWND hwnd;
1417     HDC hdcDisplay, hdcMetafile;
1418     HENHMETAFILE hMetafile;
1419     BOOL ret;
1420     static const INT dx[4] = { 3, 5, 8, 12 };
1421
1422     /* Win9x doesn't play EMFs on invisible windows */
1423     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1424                            0, 0, 200, 200, 0, 0, 0, NULL);
1425     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1426
1427     hdcDisplay = GetDC(hwnd);
1428     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1429
1430     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1431     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1432
1433     ret = BeginPath(hdcMetafile);
1434     ok(ret, "BeginPath error %d\n", GetLastError());
1435
1436     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1437     ok(ret, "ExtTextOut error %d\n", GetLastError());
1438
1439     ret = EndPath(hdcMetafile);
1440     ok(ret, "EndPath error %d\n", GetLastError());
1441
1442     hMetafile = CloseEnhMetaFile(hdcMetafile);
1443     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1444
1445     /* this doesn't succeed yet: EMF has correct size, all EMF records
1446      * are there, but their contents don't match for different reasons.
1447      */
1448     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1449         "emf_TextOut_on_path", FALSE) != 0)
1450     {
1451         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1452         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1453     }
1454
1455     ret = DeleteEnhMetaFile(hMetafile);
1456     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1457     ret = ReleaseDC(hwnd, hdcDisplay);
1458     ok(ret, "ReleaseDC error %d\n", GetLastError());
1459     DestroyWindow(hwnd);
1460 }
1461
1462 static const unsigned char EMF_CLIPPING[] =
1463 {
1464     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1465     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1467     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1469     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1470     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1471     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1473     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1474     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1475     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1476     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1477     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1478     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1479     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1480     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1481     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1482     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1483     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1484     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1485     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1486     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1487     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1488     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1489     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1490 };
1491
1492 static void translate( POINT *pt, UINT count, const XFORM *xform )
1493 {
1494     while (count--)
1495     {
1496         FLOAT x = (FLOAT)pt->x;
1497         FLOAT y = (FLOAT)pt->y;
1498         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1499         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1500         pt++;
1501     }
1502 }
1503
1504 /* Compare rectangles allowing rounding errors */
1505 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1506 {
1507     return abs(rc1->left - rc2->left) <= 1 &&
1508            abs(rc1->top - rc2->top) <= 1 &&
1509            abs(rc1->right - rc2->right) <= 1 &&
1510            abs(rc1->bottom - rc2->bottom) <= 1;
1511 }
1512
1513 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1514                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1515 {
1516     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1517     {
1518         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1519         union _rgn
1520         {
1521             RGNDATA data;
1522             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1523         };
1524         const union _rgn *rgn1;
1525         union _rgn rgn2;
1526         RECT rect, rc_transformed;
1527         const RECT *rc = (const RECT *)param;
1528         HRGN hrgn;
1529         XFORM xform;
1530         INT ret;
1531         BOOL is_win9x;
1532
1533         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1534                clip->cbRgnData, clip->iMode);
1535
1536         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1537         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1538            "too small data block: %u bytes\n", clip->cbRgnData);
1539         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1540             return 0;
1541
1542         rgn1 = (const union _rgn *)clip->RgnData;
1543
1544         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1545               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1546               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1547               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1548               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1549
1550         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1551
1552         rect = *(const RECT *)rgn1->data.Buffer;
1553         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1554         ok(EqualRect(&rect, rc), "rects don't match\n");
1555
1556         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1557         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1558         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1559         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1560
1561         hrgn = CreateRectRgn(0, 0, 0, 0);
1562
1563         memset(&xform, 0, sizeof(xform));
1564         SetLastError(0xdeadbeef);
1565         ret = GetWorldTransform(hdc, &xform);
1566         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1567         if (!is_win9x)
1568             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1569
1570         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1571
1572         ret = GetClipRgn(hdc, hrgn);
1573         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1574
1575         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1576
1577         ret = GetClipRgn(hdc, hrgn);
1578         ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1579
1580         /* Win9x returns empty clipping region */
1581         if (is_win9x) return 1;
1582
1583         ret = GetRegionData(hrgn, 0, NULL);
1584         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1585
1586         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1587
1588         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1589               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1590               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1591               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1592               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1593
1594         rect = rgn2.data.rdh.rcBound;
1595         rc_transformed = *rc;
1596         translate((POINT *)&rc_transformed, 2, &xform);
1597         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1598               rc_transformed.right, rc_transformed.bottom);
1599         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1600
1601         rect = *(const RECT *)rgn2.data.Buffer;
1602         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1603         rc_transformed = *rc;
1604         translate((POINT *)&rc_transformed, 2, &xform);
1605         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1606               rc_transformed.right, rc_transformed.bottom);
1607         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1608
1609         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1610         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1611         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1612         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1613
1614         DeleteObject(hrgn);
1615     }
1616     return 1;
1617 }
1618
1619 static void test_emf_clipping(void)
1620 {
1621     static const RECT rc = { 0, 0, 100, 100 };
1622     RECT rc_clip = { 100, 100, 1024, 1024 };
1623     HWND hwnd;
1624     HDC hdc;
1625     HENHMETAFILE hemf;
1626     HRGN hrgn;
1627     INT ret;
1628
1629     SetLastError(0xdeadbeef);
1630     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1631     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1632
1633     /* Need to write something to the emf, otherwise Windows won't play it back */
1634     LineTo(hdc, 1, 1);
1635
1636     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1637     ret = SelectClipRgn(hdc, hrgn);
1638     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1639
1640     SetLastError(0xdeadbeef);
1641     hemf = CloseEnhMetaFile(hdc);
1642     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1643
1644     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1645         "emf_clipping", FALSE) != 0)
1646     {
1647         dump_emf_bits(hemf, "emf_clipping");
1648         dump_emf_records(hemf, "emf_clipping");
1649     }
1650
1651     DeleteObject(hrgn);
1652
1653     /* Win9x doesn't play EMFs on invisible windows */
1654     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1655                            0, 0, 200, 200, 0, 0, 0, NULL);
1656     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1657
1658     hdc = GetDC(hwnd);
1659
1660     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1661     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1662
1663     DeleteEnhMetaFile(hemf);
1664     ReleaseDC(hwnd, hdc);
1665     DestroyWindow(hwnd);
1666 }
1667
1668 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1669 {
1670     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1671     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1672     /* When using MM_TEXT Win9x does not update the mapping mode 
1673      * until a record is played which actually outputs something */
1674     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1675     LPtoDP(hdc, mapping, 2);
1676     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1677            lpEMFR->iType, lpEMFR->nSize,
1678            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1679
1680     if (lpEMFR->iType == EMR_LINETO)
1681     {
1682         INT x0, y0, x1, y1;
1683         if (!lpMFP || lpMFP->mm == MM_TEXT)
1684         {
1685             x0 = 0;
1686             y0 = 0;
1687             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1688             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1689         }
1690         else
1691         {
1692             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1693             
1694             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1695             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1696             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1697             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1698         }
1699         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1700             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1701             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1702             x0, y0, x1, y1);
1703     }
1704     return TRUE;
1705 }
1706
1707 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1708 {
1709     HDC hdcMf;
1710     HMETAFILE hmf;
1711     HENHMETAFILE hemf;
1712     BOOL ret;
1713     UINT size;
1714     LPBYTE pBits;
1715
1716     hdcMf = CreateMetaFile(NULL);
1717     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1718     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1719     ok(ret, "LineTo failed with error %d\n", GetLastError());
1720     hmf = CloseMetaFile(hdcMf);
1721     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1722
1723     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1724     {
1725         dump_mf_bits(hmf, "mf_LineTo");
1726         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1727     }
1728
1729     size = GetMetaFileBitsEx(hmf, 0, NULL);
1730     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1731     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1732     GetMetaFileBitsEx(hmf, size, pBits);
1733     DeleteMetaFile(hmf);
1734     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1735     HeapFree(GetProcessHeap(), 0, pBits);
1736     return hemf;
1737 }
1738
1739 static void test_mf_conversions(void)
1740 {
1741     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1742     {
1743         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1744         HENHMETAFILE hemf;
1745         METAFILEPICT mfp;
1746         RECT rect = { 0, 0, 100, 100 };
1747         mfp.mm = MM_ANISOTROPIC;
1748         mfp.xExt = 100;
1749         mfp.yExt = 100;
1750         mfp.hMF = NULL;
1751         hemf = create_converted_emf(&mfp);
1752
1753         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1754                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1755         {
1756             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1757             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1758         }
1759
1760         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1761
1762         DeleteEnhMetaFile(hemf);
1763         DeleteDC(hdcOffscreen);
1764     }
1765
1766     trace("Testing MF->EMF conversion (MM_TEXT)\n");
1767     {
1768         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1769         HENHMETAFILE hemf;
1770         METAFILEPICT mfp;
1771         RECT rect = { 0, 0, 100, 100 };
1772         mfp.mm = MM_TEXT;
1773         mfp.xExt = 0;
1774         mfp.yExt = 0;
1775         mfp.hMF = NULL;
1776         hemf = create_converted_emf(&mfp);
1777
1778         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1779                              "emf_LineTo MM_TEXT", TRUE) != 0)
1780         {
1781             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1782             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1783         }
1784
1785         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1786
1787         DeleteEnhMetaFile(hemf);
1788         DeleteDC(hdcOffscreen);
1789     }
1790
1791     trace("Testing MF->EMF conversion (NULL mfp)\n");
1792     {
1793         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1794         HENHMETAFILE hemf;
1795         RECT rect = { 0, 0, 100, 100 };
1796         hemf = create_converted_emf(NULL);
1797
1798         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1799                              "emf_LineTo NULL", TRUE) != 0)
1800         {
1801             dump_emf_bits(hemf, "emf_LineTo NULL");
1802             dump_emf_records(hemf, "emf_LineTo NULL");
1803         }
1804
1805         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1806
1807         DeleteEnhMetaFile(hemf);
1808         DeleteDC(hdcOffscreen);
1809     }
1810 }
1811
1812 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1813                                        LONG mm, LONG xExt, LONG yExt,
1814                                        RECTL * rclBounds, RECTL * rclFrame)
1815 {
1816   METAFILEPICT mfp;
1817   METAFILEPICT * mfpPtr = NULL;
1818   HENHMETAFILE emf;
1819   ENHMETAHEADER header;
1820   UINT res;
1821
1822   if (!mfpIsNull)
1823   {
1824     mfp.mm = mm;
1825     mfp.xExt = xExt;
1826     mfp.yExt = yExt;
1827     mfpPtr = &mfp;
1828   }
1829
1830   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1831   ok(emf != NULL, "SetWinMetaFileBits failed\n");
1832   if (!emf) return FALSE;
1833   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1834   ok(res != 0, "GetEnhMetaHeader failed\n");
1835   DeleteEnhMetaFile(emf);
1836   if (!res) return FALSE;
1837
1838   *rclBounds = header.rclBounds;
1839   *rclFrame = header.rclFrame;
1840   return TRUE;
1841 }
1842
1843 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1844                                          LONG mm, LONG xExt, LONG yExt,
1845                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1846 {
1847   RECTL rclBounds, rclFrame;
1848
1849   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1850   {
1851     const char * msg;
1852     char buf[64];
1853
1854     if (mfpIsNull)
1855     {
1856        msg = "mfp == NULL";
1857     }
1858     else
1859     {
1860       const char * mm_str;
1861       switch (mm)
1862       {
1863          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1864          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
1865          default:             mm_str = "Unexpected";
1866       }
1867       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1868       msg = buf;
1869     }
1870
1871     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1872     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1873     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1874     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1875     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1876     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1877     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1878     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1879   }
1880 }
1881
1882 static void test_SetWinMetaFileBits(void)
1883 {
1884   HMETAFILE wmf;
1885   HDC wmfDC;
1886   BYTE * buffer;
1887   UINT buffer_size;
1888   RECT rect;
1889   UINT res;
1890   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1891   RECTL rclBoundsIsotropic, rclFrameIsotropic;
1892   RECTL rclBounds, rclFrame;
1893   HDC dc;
1894   LONG diffx, diffy;
1895
1896   wmfDC = CreateMetaFile(NULL);
1897   ok(wmfDC != NULL, "CreateMetaFile failed\n");
1898   if (!wmfDC) return;
1899
1900   SetWindowExtEx(wmfDC, 100, 100, NULL);
1901   rect.left = rect.top = 0;
1902   rect.right = rect.bottom = 50;
1903   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1904   wmf = CloseMetaFile(wmfDC);
1905   ok(wmf != NULL, "Metafile creation failed\n");
1906   if (!wmf) return;
1907
1908   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1909   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1910   if (buffer_size == 0)
1911   {
1912     DeleteMetaFile(wmf);
1913     return;
1914   }
1915
1916   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1917   ok(buffer != NULL, "HeapAlloc failed\n");
1918   if (!buffer)
1919   {
1920     DeleteMetaFile(wmf);
1921     return;
1922   }
1923
1924   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1925   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1926   DeleteMetaFile(wmf);
1927   if (res != buffer_size)
1928   {
1929      HeapFree(GetProcessHeap(), 0, buffer);
1930      return;
1931   }
1932
1933   /* Get the reference bounds and frame */
1934   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1935   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
1936
1937   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1938      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1939      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1940
1941   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1942   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1943   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1944   if (diffx < 0) diffx = -diffx;
1945   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1946
1947   dc = CreateCompatibleDC(NULL);
1948
1949   /* Allow 1 mm difference (rounding errors) */
1950   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
1951   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
1952   if (diffx < 0) diffx = -diffx;
1953   if (diffy < 0) diffy = -diffy;
1954   todo_wine
1955   {
1956   ok(diffx <= 1 && diffy <= 1,
1957      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1958      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1959   }
1960
1961   /* Allow 1 mm difference (rounding errors) */
1962   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1963   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1964   if (diffx < 0) diffx = -diffx;
1965   if (diffy < 0) diffy = -diffy;
1966   todo_wine
1967   {
1968   ok(diffx <= 1 && diffy <= 1,
1969      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1970      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1971   }
1972   DeleteDC(dc);
1973
1974   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1975   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1976
1977   /* If xExt or yExt is zero or negative, the whole device surface is used */
1978   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1979   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1980   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1981   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1982   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1983   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1984   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1985   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1986   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1987   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1988   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1989   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1990
1991   /* MSDN says that negative xExt and yExt values specify a ratio.
1992      Check that this is wrong and the whole device surface is used */
1993   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1994   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1995
1996   /* Ordinary conversions */
1997
1998   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1999   {
2000     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2001        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2002     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2003        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2004   }
2005
2006   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2007   {
2008     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2009        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2010     ok(rclBounds.left == 0 && rclBounds.top == 0,
2011        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2012
2013     /* Wine has a rounding error */
2014     diffx = rclBounds.right - rclBounds.bottom;
2015     if (diffx < 0) diffx = -diffx;
2016     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2017   }
2018
2019   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2020   {
2021     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2022        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2023   }
2024
2025   HeapFree(GetProcessHeap(), 0, buffer);
2026 }
2027
2028 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2029 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2030 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2031
2032 static void test_gdiis(void)
2033 {
2034     RECT rect = {0,0,100,100};
2035     HDC hdc, hemfDC, hmfDC;
2036     HENHMETAFILE hemf;
2037     HMODULE hgdi32;
2038
2039     /* resolve all the functions */
2040     hgdi32 = GetModuleHandle("gdi32");
2041     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2042     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2043     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2044
2045     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2046     {
2047         win_skip("Needed GdiIs* functions are not available\n");
2048         return;
2049     }
2050
2051     /* try with nothing */
2052     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2053     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2054     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2055
2056     /* try with a metafile */
2057     hmfDC = CreateMetaFile(NULL);
2058     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2059     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2060     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2061     DeleteMetaFile(CloseMetaFile(hmfDC));
2062
2063     /* try with an enhanced metafile */
2064     hdc = GetDC(NULL);
2065     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2066     ok(hemfDC != NULL, "failed to create emf\n");
2067
2068     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2069     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2070     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2071
2072     hemf = CloseEnhMetaFile(hemfDC);
2073     ok(hemf != NULL, "failed to close EMF\n");
2074     DeleteEnhMetaFile(hemf);
2075     ReleaseDC(NULL,hdc);
2076 }
2077
2078 static void test_SetEnhMetaFileBits(void)
2079 {
2080     BYTE data[256];
2081     HENHMETAFILE hemf;
2082     ENHMETAHEADER *emh;
2083
2084     memset(data, 0xAA, sizeof(data));
2085     SetLastError(0xdeadbeef);
2086     hemf = SetEnhMetaFileBits(sizeof(data), data);
2087     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2088     ok(GetLastError() == ERROR_INVALID_DATA ||
2089        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2090        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2091
2092     emh = (ENHMETAHEADER *)data;
2093     memset(emh, 0, sizeof(*emh));
2094
2095     emh->iType = EMR_HEADER;
2096     emh->nSize = sizeof(*emh);
2097     emh->dSignature = ENHMETA_SIGNATURE;
2098     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2099     emh->nBytes = sizeof(*emh);
2100     /* emh->nRecords = 1; XP doesn't care about records */
2101     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2102
2103     SetLastError(0xdeadbeef);
2104     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2105     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2106     DeleteEnhMetaFile(hemf);
2107
2108     /* XP refuses to load unaligned EMF */
2109     emh->nBytes++;
2110     SetLastError(0xdeadbeef);
2111     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2112     ok(!hemf ||
2113        broken(hemf != NULL), /* Win9x, WinMe */
2114        "SetEnhMetaFileBits should fail\n");
2115     todo_wine
2116     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2117     DeleteEnhMetaFile(hemf);
2118
2119     emh->dSignature = 0;
2120     emh->nBytes--;
2121     SetLastError(0xdeadbeef);
2122     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2123     ok(!hemf ||
2124        broken(hemf != NULL), /* Win9x, WinMe */
2125        "SetEnhMetaFileBits should fail\n");
2126     todo_wine
2127     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2128     DeleteEnhMetaFile(hemf);
2129 }
2130
2131 START_TEST(metafile)
2132 {
2133     init_function_pointers();
2134
2135     /* For enhanced metafiles (enhmfdrv) */
2136     test_ExtTextOut();
2137     test_SaveDC();
2138
2139     /* For win-format metafiles (mfdrv) */
2140     test_mf_Blank();
2141     test_mf_Graphics();
2142     test_mf_PatternBrush();
2143     test_CopyMetaFile();
2144     test_SetMetaFileBits();
2145     test_mf_ExtTextOut_on_path();
2146     test_emf_ExtTextOut_on_path();
2147     test_emf_clipping();
2148
2149     /* For metafile conversions */
2150     test_mf_conversions();
2151     test_SetWinMetaFileBits();
2152
2153     test_gdiis();
2154     test_SetEnhMetaFileBits();
2155 }