winhttp, wininet: Load i2d_X509 from libcrypto.so.
[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, "wrong error %d\n", GetLastError());
1227
1228     /* Now with not even size */
1229     SetLastError(0xdeadbeef);
1230     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1231     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1232     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1233
1234     /* Now with zeroed out or faked some header fields */
1235     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1236     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1237     mh = (METAHEADER *)buf;
1238     /* corruption of any of the below fields leads to a failure */
1239     mh->mtType = 0;
1240     mh->mtVersion = 0;
1241     mh->mtHeaderSize = 0;
1242     SetLastError(0xdeadbeef);
1243     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1244     ok(!hmf, "SetMetaFileBitsEx should fail\n");
1245     ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %d\n", GetLastError());
1246
1247     /* Now with corrupted mtSize field */
1248     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1249     mh = (METAHEADER *)buf;
1250     /* corruption of mtSize doesn't lead to a failure */
1251     mh->mtSize *= 2;
1252     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1253     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1254
1255     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1256     {
1257         dump_mf_bits(hmf, "mf_Graphics");
1258         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1259     }
1260
1261     ret = DeleteMetaFile(hmf);
1262     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1263
1264     /* Now with zeroed out mtSize field */
1265     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1266     mh = (METAHEADER *)buf;
1267     /* zeroing mtSize doesn't lead to a failure */
1268     mh->mtSize = 0;
1269     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1270     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1271
1272     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1273     {
1274         dump_mf_bits(hmf, "mf_Graphics");
1275         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1276     }
1277
1278     ret = DeleteMetaFile(hmf);
1279     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1280 }
1281
1282 /* Simple APIs from mfdrv/graphics.c
1283  */
1284
1285 static void test_mf_Graphics(void)
1286 {
1287     HDC hdcMetafile;
1288     HMETAFILE hMetafile;
1289     POINT oldpoint;
1290     BOOL ret;
1291
1292     hdcMetafile = CreateMetaFileA(NULL);
1293     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1294     trace("hdcMetafile %p\n", hdcMetafile);
1295
1296     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1297     ok( ret, "MoveToEx error %d.\n", GetLastError());
1298     ret = LineTo(hdcMetafile, 2, 2);
1299     ok( ret, "LineTo error %d.\n", GetLastError());
1300     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1301     ok( ret, "MoveToEx error %d.\n", GetLastError());
1302
1303 /* oldpoint gets garbage under Win XP, so the following test would
1304  * work under Wine but fails under Windows:
1305  *
1306  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
1307  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1308  *       oldpoint.x, oldpoint.y);
1309  */
1310
1311     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1312     ok( ret, "Ellipse error %d.\n", GetLastError());
1313
1314     hMetafile = CloseMetaFile(hdcMetafile);
1315     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1316     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1317
1318     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1319         "mf_Graphics") != 0)
1320     {
1321         dump_mf_bits(hMetafile, "mf_Graphics");
1322         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1323     }
1324
1325     ret = DeleteMetaFile(hMetafile);
1326     ok( ret, "DeleteMetaFile(%p) error %d\n",
1327         hMetafile, GetLastError());
1328 }
1329
1330 static void test_mf_PatternBrush(void)
1331 {
1332     HDC hdcMetafile;
1333     HMETAFILE hMetafile;
1334     LOGBRUSH *orig_lb;
1335     HBRUSH hBrush;
1336     BOOL ret;
1337
1338     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1339
1340     orig_lb->lbStyle = BS_PATTERN;
1341     orig_lb->lbColor = RGB(0, 0, 0);
1342     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1343     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
1344
1345     hBrush = CreateBrushIndirect (orig_lb);
1346     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1347
1348     hdcMetafile = CreateMetaFileA(NULL);
1349     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1350     trace("hdcMetafile %p\n", hdcMetafile);
1351
1352     hBrush = SelectObject(hdcMetafile, hBrush);
1353     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1354
1355     hMetafile = CloseMetaFile(hdcMetafile);
1356     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1357     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1358
1359     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1360         "mf_Pattern_Brush") != 0)
1361     {
1362         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1363         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1364     }
1365
1366     ret = DeleteMetaFile(hMetafile);
1367     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1368     ret = DeleteObject(hBrush);
1369     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1370     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1371     ok( ret, "DeleteObject(HBITMAP) error %d\n",
1372         GetLastError());
1373     HeapFree (GetProcessHeap(), 0, orig_lb);
1374 }
1375
1376 static void test_mf_ExtTextOut_on_path(void)
1377 {
1378     HDC hdcMetafile;
1379     HMETAFILE hMetafile;
1380     BOOL ret;
1381     static const INT dx[4] = { 3, 5, 8, 12 };
1382
1383     hdcMetafile = CreateMetaFileA(NULL);
1384     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1385     trace("hdcMetafile %p\n", hdcMetafile);
1386
1387     ret = BeginPath(hdcMetafile);
1388     ok(!ret, "BeginPath on metafile DC should fail\n");
1389
1390     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1391     ok(ret, "ExtTextOut error %d\n", GetLastError());
1392
1393     ret = EndPath(hdcMetafile);
1394     ok(!ret, "EndPath on metafile DC should fail\n");
1395
1396     hMetafile = CloseMetaFile(hdcMetafile);
1397     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1398
1399     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1400         "mf_TextOut_on_path") != 0)
1401     {
1402         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1403         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1404     }
1405
1406     ret = DeleteMetaFile(hMetafile);
1407     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1408 }
1409
1410 static void test_emf_ExtTextOut_on_path(void)
1411 {
1412     HWND hwnd;
1413     HDC hdcDisplay, hdcMetafile;
1414     HENHMETAFILE hMetafile;
1415     BOOL ret;
1416     static const INT dx[4] = { 3, 5, 8, 12 };
1417
1418     /* Win9x doesn't play EMFs on invisible windows */
1419     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1420                            0, 0, 200, 200, 0, 0, 0, NULL);
1421     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1422
1423     hdcDisplay = GetDC(hwnd);
1424     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1425
1426     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1427     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1428
1429     ret = BeginPath(hdcMetafile);
1430     ok(ret, "BeginPath error %d\n", GetLastError());
1431
1432     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1433     ok(ret, "ExtTextOut error %d\n", GetLastError());
1434
1435     ret = EndPath(hdcMetafile);
1436     ok(ret, "EndPath error %d\n", GetLastError());
1437
1438     hMetafile = CloseEnhMetaFile(hdcMetafile);
1439     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1440
1441     /* this doesn't succeed yet: EMF has correct size, all EMF records
1442      * are there, but their contents don't match for different reasons.
1443      */
1444     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1445         "emf_TextOut_on_path", FALSE) != 0)
1446     {
1447         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1448         dump_emf_records(hMetafile, "emf_TextOut_on_path");
1449     }
1450
1451     ret = DeleteEnhMetaFile(hMetafile);
1452     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1453     ret = ReleaseDC(hwnd, hdcDisplay);
1454     ok(ret, "ReleaseDC error %d\n", GetLastError());
1455     DestroyWindow(hwnd);
1456 }
1457
1458 static const unsigned char EMF_CLIPPING[] =
1459 {
1460     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1461     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1462     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1463     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1464     0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
1465     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1466     0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1467     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1470     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1471     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1472     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1473     0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
1474     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1475     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
1476     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1477     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1478     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1479     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1480     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1481     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1482     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1483     0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1484     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1485     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1486 };
1487
1488 static void translate( POINT *pt, UINT count, const XFORM *xform )
1489 {
1490     while (count--)
1491     {
1492         FLOAT x = (FLOAT)pt->x;
1493         FLOAT y = (FLOAT)pt->y;
1494         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
1495         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
1496         pt++;
1497     }
1498 }
1499
1500 /* Compare rectangles allowing rounding errors */
1501 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
1502 {
1503     return abs(rc1->left - rc2->left) <= 1 &&
1504            abs(rc1->top - rc2->top) <= 1 &&
1505            abs(rc1->right - rc2->right) <= 1 &&
1506            abs(rc1->bottom - rc2->bottom) <= 1;
1507 }
1508
1509 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
1510                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
1511 {
1512     if (emr->iType == EMR_EXTSELECTCLIPRGN)
1513     {
1514         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
1515         union _rgn
1516         {
1517             RGNDATA data;
1518             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
1519         };
1520         const union _rgn *rgn1;
1521         union _rgn rgn2;
1522         RECT rect, rc_transformed;
1523         const RECT *rc = (const RECT *)param;
1524         HRGN hrgn;
1525         XFORM xform;
1526         INT ret;
1527         BOOL is_win9x;
1528
1529         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
1530                clip->cbRgnData, clip->iMode);
1531
1532         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
1533         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
1534            "too small data block: %u bytes\n", clip->cbRgnData);
1535         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
1536             return 0;
1537
1538         rgn1 = (const union _rgn *)clip->RgnData;
1539
1540         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1541               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
1542               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
1543               rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
1544               rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
1545
1546         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
1547
1548         rect = *(const RECT *)rgn1->data.Buffer;
1549         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1550         ok(EqualRect(&rect, rc), "rects don't match\n");
1551
1552         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
1553         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
1554         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
1555         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
1556
1557         hrgn = CreateRectRgn(0, 0, 0, 0);
1558
1559         memset(&xform, 0, sizeof(xform));
1560         SetLastError(0xdeadbeef);
1561         ret = GetWorldTransform(hdc, &xform);
1562         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
1563         if (!is_win9x)
1564             ok(ret, "GetWorldTransform error %u\n", GetLastError());
1565
1566         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
1567
1568         ret = GetClipRgn(hdc, hrgn);
1569         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
1570
1571         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
1572
1573         ret = GetClipRgn(hdc, hrgn);
1574         ok(ret == 1, "GetClipRgn returned %d, expected 0\n", ret);
1575
1576         /* Win9x returns empty clipping region */
1577         if (is_win9x) return 1;
1578
1579         ret = GetRegionData(hrgn, 0, NULL);
1580         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
1581
1582         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
1583
1584         trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
1585               rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
1586               rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
1587               rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
1588               rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
1589
1590         rect = rgn2.data.rdh.rcBound;
1591         rc_transformed = *rc;
1592         translate((POINT *)&rc_transformed, 2, &xform);
1593         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1594               rc_transformed.right, rc_transformed.bottom);
1595         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1596
1597         rect = *(const RECT *)rgn2.data.Buffer;
1598         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
1599         rc_transformed = *rc;
1600         translate((POINT *)&rc_transformed, 2, &xform);
1601         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
1602               rc_transformed.right, rc_transformed.bottom);
1603         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
1604
1605         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
1606         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
1607         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
1608         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT),  "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
1609
1610         DeleteObject(hrgn);
1611     }
1612     return 1;
1613 }
1614
1615 static void test_emf_clipping(void)
1616 {
1617     static const RECT rc = { 0, 0, 100, 100 };
1618     RECT rc_clip = { 100, 100, 1024, 1024 };
1619     HWND hwnd;
1620     HDC hdc;
1621     HENHMETAFILE hemf;
1622     HRGN hrgn;
1623     INT ret;
1624
1625     SetLastError(0xdeadbeef);
1626     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
1627     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1628
1629     /* Need to write something to the emf, otherwise Windows won't play it back */
1630     LineTo(hdc, 1, 1);
1631
1632     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
1633     ret = SelectClipRgn(hdc, hrgn);
1634     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
1635
1636     SetLastError(0xdeadbeef);
1637     hemf = CloseEnhMetaFile(hdc);
1638     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
1639
1640     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
1641         "emf_clipping", FALSE) != 0)
1642     {
1643         dump_emf_bits(hemf, "emf_clipping");
1644         dump_emf_records(hemf, "emf_clipping");
1645     }
1646
1647     DeleteObject(hrgn);
1648
1649     /* Win9x doesn't play EMFs on invisible windows */
1650     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1651                            0, 0, 200, 200, 0, 0, 0, NULL);
1652     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
1653
1654     hdc = GetDC(hwnd);
1655
1656     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
1657     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
1658
1659     DeleteEnhMetaFile(hemf);
1660     ReleaseDC(hwnd, hdc);
1661     DestroyWindow(hwnd);
1662 }
1663
1664 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1665 {
1666     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1667     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1668     /* When using MM_TEXT Win9x does not update the mapping mode 
1669      * until a record is played which actually outputs something */
1670     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1671     LPtoDP(hdc, mapping, 2);
1672     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
1673            lpEMFR->iType, lpEMFR->nSize,
1674            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1675
1676     if (lpEMFR->iType == EMR_LINETO)
1677     {
1678         INT x0, y0, x1, y1;
1679         if (!lpMFP || lpMFP->mm == MM_TEXT)
1680         {
1681             x0 = 0;
1682             y0 = 0;
1683             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1684             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1685         }
1686         else
1687         {
1688             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
1689             
1690             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1691             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1692             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1693             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1694         }
1695         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1696             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1697             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1698             x0, y0, x1, y1);
1699     }
1700     return TRUE;
1701 }
1702
1703 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1704 {
1705     HDC hdcMf;
1706     HMETAFILE hmf;
1707     HENHMETAFILE hemf;
1708     BOOL ret;
1709     UINT size;
1710     LPBYTE pBits;
1711
1712     hdcMf = CreateMetaFile(NULL);
1713     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1714     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1715     ok(ret, "LineTo failed with error %d\n", GetLastError());
1716     hmf = CloseMetaFile(hdcMf);
1717     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1718
1719     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1720     {
1721         dump_mf_bits(hmf, "mf_LineTo");
1722         EnumMetaFile(0, hmf, mf_enum_proc, 0);
1723     }
1724
1725     size = GetMetaFileBitsEx(hmf, 0, NULL);
1726     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1727     pBits = HeapAlloc(GetProcessHeap(), 0, size);
1728     GetMetaFileBitsEx(hmf, size, pBits);
1729     DeleteMetaFile(hmf);
1730     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
1731     HeapFree(GetProcessHeap(), 0, pBits);
1732     return hemf;
1733 }
1734
1735 static void test_mf_conversions(void)
1736 {
1737     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1738     {
1739         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1740         HENHMETAFILE hemf;
1741         METAFILEPICT mfp;
1742         RECT rect = { 0, 0, 100, 100 };
1743         mfp.mm = MM_ANISOTROPIC;
1744         mfp.xExt = 100;
1745         mfp.yExt = 100;
1746         mfp.hMF = NULL;
1747         hemf = create_converted_emf(&mfp);
1748
1749         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1750                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1751         {
1752             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1753             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1754         }
1755
1756         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1757
1758         DeleteEnhMetaFile(hemf);
1759         DeleteDC(hdcOffscreen);
1760     }
1761
1762     trace("Testing MF->EMF conversion (MM_TEXT)\n");
1763     {
1764         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1765         HENHMETAFILE hemf;
1766         METAFILEPICT mfp;
1767         RECT rect = { 0, 0, 100, 100 };
1768         mfp.mm = MM_TEXT;
1769         mfp.xExt = 0;
1770         mfp.yExt = 0;
1771         mfp.hMF = NULL;
1772         hemf = create_converted_emf(&mfp);
1773
1774         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1775                              "emf_LineTo MM_TEXT", TRUE) != 0)
1776         {
1777             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1778             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1779         }
1780
1781         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1782
1783         DeleteEnhMetaFile(hemf);
1784         DeleteDC(hdcOffscreen);
1785     }
1786
1787     trace("Testing MF->EMF conversion (NULL mfp)\n");
1788     {
1789         HDC hdcOffscreen = CreateCompatibleDC(NULL);
1790         HENHMETAFILE hemf;
1791         RECT rect = { 0, 0, 100, 100 };
1792         hemf = create_converted_emf(NULL);
1793
1794         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1795                              "emf_LineTo NULL", TRUE) != 0)
1796         {
1797             dump_emf_bits(hemf, "emf_LineTo NULL");
1798             dump_emf_records(hemf, "emf_LineTo NULL");
1799         }
1800
1801         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1802
1803         DeleteEnhMetaFile(hemf);
1804         DeleteDC(hdcOffscreen);
1805     }
1806 }
1807
1808 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1809                                        LONG mm, LONG xExt, LONG yExt,
1810                                        RECTL * rclBounds, RECTL * rclFrame)
1811 {
1812   METAFILEPICT mfp;
1813   METAFILEPICT * mfpPtr = NULL;
1814   HENHMETAFILE emf;
1815   ENHMETAHEADER header;
1816   UINT res;
1817
1818   if (!mfpIsNull)
1819   {
1820     mfp.mm = mm;
1821     mfp.xExt = xExt;
1822     mfp.yExt = yExt;
1823     mfpPtr = &mfp;
1824   }
1825
1826   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1827   ok(emf != NULL, "SetWinMetaFileBits failed\n");
1828   if (!emf) return FALSE;
1829   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1830   ok(res != 0, "GetEnhMetaHeader failed\n");
1831   DeleteEnhMetaFile(emf);
1832   if (!res) return FALSE;
1833
1834   *rclBounds = header.rclBounds;
1835   *rclFrame = header.rclFrame;
1836   return TRUE;
1837 }
1838
1839 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1840                                          LONG mm, LONG xExt, LONG yExt,
1841                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1842 {
1843   RECTL rclBounds, rclFrame;
1844
1845   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1846   {
1847     const char * msg;
1848     char buf[64];
1849
1850     if (mfpIsNull)
1851     {
1852        msg = "mfp == NULL";
1853     }
1854     else
1855     {
1856       const char * mm_str;
1857       switch (mm)
1858       {
1859          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1860          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
1861          default:             mm_str = "Unexpected";
1862       }
1863       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1864       msg = buf;
1865     }
1866
1867     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1868     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1869     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1870     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1871     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1872     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1873     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1874     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1875   }
1876 }
1877
1878 static void test_SetWinMetaFileBits(void)
1879 {
1880   HMETAFILE wmf;
1881   HDC wmfDC;
1882   BYTE * buffer;
1883   UINT buffer_size;
1884   RECT rect;
1885   UINT res;
1886   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1887   RECTL rclBoundsIsotropic, rclFrameIsotropic;
1888   RECTL rclBounds, rclFrame;
1889   HDC dc;
1890   LONG diffx, diffy;
1891
1892   wmfDC = CreateMetaFile(NULL);
1893   ok(wmfDC != NULL, "CreateMetaFile failed\n");
1894   if (!wmfDC) return;
1895
1896   SetWindowExtEx(wmfDC, 100, 100, NULL);
1897   rect.left = rect.top = 0;
1898   rect.right = rect.bottom = 50;
1899   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1900   wmf = CloseMetaFile(wmfDC);
1901   ok(wmf != NULL, "Metafile creation failed\n");
1902   if (!wmf) return;
1903
1904   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1905   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1906   if (buffer_size == 0)
1907   {
1908     DeleteMetaFile(wmf);
1909     return;
1910   }
1911
1912   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
1913   ok(buffer != NULL, "HeapAlloc failed\n");
1914   if (!buffer)
1915   {
1916     DeleteMetaFile(wmf);
1917     return;
1918   }
1919
1920   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1921   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1922   DeleteMetaFile(wmf);
1923   if (res != buffer_size)
1924   {
1925      HeapFree(GetProcessHeap(), 0, buffer);
1926      return;
1927   }
1928
1929   /* Get the reference bounds and frame */
1930   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1931   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
1932
1933   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1934      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1935      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1936
1937   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1938   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1939   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1940   if (diffx < 0) diffx = -diffx;
1941   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1942
1943   dc = CreateCompatibleDC(NULL);
1944
1945   /* Allow 1 mm difference (rounding errors) */
1946   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
1947   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
1948   if (diffx < 0) diffx = -diffx;
1949   if (diffy < 0) diffy = -diffy;
1950   todo_wine
1951   {
1952   ok(diffx <= 1 && diffy <= 1,
1953      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1954      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1955   }
1956
1957   /* Allow 1 mm difference (rounding errors) */
1958   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1959   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1960   if (diffx < 0) diffx = -diffx;
1961   if (diffy < 0) diffy = -diffy;
1962   todo_wine
1963   {
1964   ok(diffx <= 1 && diffy <= 1,
1965      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1966      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1967   }
1968   DeleteDC(dc);
1969
1970   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1971   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1972
1973   /* If xExt or yExt is zero or negative, the whole device surface is used */
1974   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1975   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1976   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1977   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
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, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1983   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1984   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1985   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1986
1987   /* MSDN says that negative xExt and yExt values specify a ratio.
1988      Check that this is wrong and the whole device surface is used */
1989   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1990   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1991
1992   /* Ordinary conversions */
1993
1994   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1995   {
1996     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1997        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
1998     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
1999        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2000   }
2001
2002   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2003   {
2004     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2005        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2006     ok(rclBounds.left == 0 && rclBounds.top == 0,
2007        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2008
2009     /* Wine has a rounding error */
2010     diffx = rclBounds.right - rclBounds.bottom;
2011     if (diffx < 0) diffx = -diffx;
2012     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2013   }
2014
2015   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2016   {
2017     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2018        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2019   }
2020
2021   HeapFree(GetProcessHeap(), 0, buffer);
2022 }
2023
2024 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
2025 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
2026 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
2027
2028 static void test_gdiis(void)
2029 {
2030     RECT rect = {0,0,100,100};
2031     HDC hdc, hemfDC, hmfDC;
2032     HENHMETAFILE hemf;
2033     HMODULE hgdi32;
2034
2035     /* resolve all the functions */
2036     hgdi32 = GetModuleHandle("gdi32");
2037     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
2038     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
2039     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
2040
2041     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
2042     {
2043         win_skip("Needed GdiIs* functions are not available\n");
2044         return;
2045     }
2046
2047     /* try with nothing */
2048     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
2049     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
2050     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
2051
2052     /* try with a metafile */
2053     hmfDC = CreateMetaFile(NULL);
2054     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
2055     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
2056     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
2057     DeleteMetaFile(CloseMetaFile(hmfDC));
2058
2059     /* try with an enhanced metafile */
2060     hdc = GetDC(NULL);
2061     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
2062     ok(hemfDC != NULL, "failed to create emf\n");
2063
2064     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
2065     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
2066     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
2067
2068     hemf = CloseEnhMetaFile(hemfDC);
2069     ok(hemf != NULL, "failed to close EMF\n");
2070     DeleteEnhMetaFile(hemf);
2071     ReleaseDC(NULL,hdc);
2072 }
2073
2074 static void test_SetEnhMetaFileBits(void)
2075 {
2076     BYTE data[256];
2077     HENHMETAFILE hemf;
2078     ENHMETAHEADER *emh;
2079
2080     memset(data, 0xAA, sizeof(data));
2081     SetLastError(0xdeadbeef);
2082     hemf = SetEnhMetaFileBits(sizeof(data), data);
2083     ok(!hemf, "SetEnhMetaFileBits should fail\n");
2084     ok(GetLastError() == ERROR_INVALID_DATA ||
2085        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
2086        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2087
2088     emh = (ENHMETAHEADER *)data;
2089     memset(emh, 0, sizeof(*emh));
2090
2091     emh->iType = EMR_HEADER;
2092     emh->nSize = sizeof(*emh);
2093     emh->dSignature = ENHMETA_SIGNATURE;
2094     /* emh->nVersion  = 0x10000; XP doesn't care about version */
2095     emh->nBytes = sizeof(*emh);
2096     /* emh->nRecords = 1; XP doesn't care about records */
2097     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
2098
2099     SetLastError(0xdeadbeef);
2100     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2101     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
2102     DeleteEnhMetaFile(hemf);
2103
2104     /* XP refuses to load unaligned EMF */
2105     emh->nBytes++;
2106     SetLastError(0xdeadbeef);
2107     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2108     ok(!hemf ||
2109        broken(hemf != NULL), /* Win9x, WinMe */
2110        "SetEnhMetaFileBits should fail\n");
2111     todo_wine
2112     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2113     DeleteEnhMetaFile(hemf);
2114
2115     emh->dSignature = 0;
2116     emh->nBytes--;
2117     SetLastError(0xdeadbeef);
2118     hemf = SetEnhMetaFileBits(emh->nBytes, data);
2119     ok(!hemf ||
2120        broken(hemf != NULL), /* Win9x, WinMe */
2121        "SetEnhMetaFileBits should fail\n");
2122     todo_wine
2123     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
2124     DeleteEnhMetaFile(hemf);
2125 }
2126
2127 START_TEST(metafile)
2128 {
2129     init_function_pointers();
2130
2131     /* For enhanced metafiles (enhmfdrv) */
2132     test_ExtTextOut();
2133     test_SaveDC();
2134
2135     /* For win-format metafiles (mfdrv) */
2136     test_mf_Blank();
2137     test_mf_Graphics();
2138     test_mf_PatternBrush();
2139     test_CopyMetaFile();
2140     test_SetMetaFileBits();
2141     test_mf_ExtTextOut_on_path();
2142     test_emf_ExtTextOut_on_path();
2143     test_emf_clipping();
2144
2145     /* For metafile conversions */
2146     test_mf_conversions();
2147     test_SetWinMetaFileBits();
2148
2149     test_gdiis();
2150     test_SetEnhMetaFileBits();
2151 }