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 "precomp.h"
22 
23 static LOGFONTA orig_lf;
24 static BOOL emr_processed = FALSE;
25 
26 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
27 #define LINE_X 55.0f
28 #define LINE_Y 15.0f
29 
30 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
31 static INT (WINAPI * pSetRelAbs)(HDC, INT);
32 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
33 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
34 
35 #define GDI_GET_PROC(func)                                     \
36     p ## func = (void *)GetProcAddress(hGDI, #func);           \
37     if(!p ## func)                                             \
38         trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
39 
40 static void init_function_pointers(void)
41 {
42     HMODULE hGDI;
43 
44     pGetRelAbs = NULL;
45     pSetRelAbs = NULL;
46 
47     hGDI = GetModuleHandleA("gdi32.dll");
48     assert(hGDI);
49     GDI_GET_PROC(GetRelAbs);
50     GDI_GET_PROC(SetRelAbs);
51     GDI_GET_PROC(SetDCBrushColor);
52     GDI_GET_PROC(SetDCPenColor);
53 }
54 
55 static DWORD rgn_rect_count(HRGN hrgn)
56 {
57     DWORD size;
58     RGNDATA *data;
59 
60     if (!hrgn) return 0;
61     if (!(size = GetRegionData(hrgn, 0, NULL))) return 0;
62     if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0;
63     GetRegionData(hrgn, size, data);
64     size = data->rdh.nCount;
65     HeapFree(GetProcessHeap(), 0, data);
66     return size;
67 }
68 
69 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
70     const ENHMETARECORD *emr, int n_objs, LPARAM param)
71 {
72     static int n_record;
73     DWORD i;
74     const INT *dx;
75     INT *orig_dx = (INT *)param;
76     LOGFONTA device_lf;
77     INT ret;
78 
79     if(!hdc) return 1;
80 
81     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
82 
83     switch (emr->iType)
84     {
85     case EMR_HEADER:
86         ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
87         ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
88         ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
89         ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
90         ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
91         ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
92         ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
93 
94         /* GetBkMode, GetRelAbs do not get reset to the default value */
95         ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
96         if(pSetRelAbs && pGetRelAbs)
97             ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
98 
99         n_record = 0;
100         break;
101 
102     case EMR_EXTTEXTOUTA:
103     {
104         const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
105         dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
106 
107         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
108         ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
109 
110         /* compare up to lfOutPrecision, other values are not interesting,
111          * and in fact sometimes arbitrary adapted by Win9x.
112          */
113         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
114         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
115 
116         for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
117         {
118             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
119                                      n_record, i, dx[i], orig_dx[i]);
120         }
121         n_record++;
122         emr_processed = TRUE;
123         break;
124     }
125 
126     case EMR_EXTTEXTOUTW:
127     {
128         const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
129         dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
130 
131         SetLastError(0xdeadbeef);
132         ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
133         ok( ret == sizeof(device_lf) ||
134             broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
135             "GetObjectA error %d\n", GetLastError());
136 
137         /* compare up to lfOutPrecision, other values are not interesting,
138          * and in fact sometimes arbitrary adapted by Win9x.
139          */
140         ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
141         ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
142 
143         ok(!emr_ExtTextOutW->rclBounds.left, "emr_ExtTextOutW->rclBounds.left = %d\n",
144                 emr_ExtTextOutW->rclBounds.left);
145         ok(emr_ExtTextOutW->rclBounds.right != -1, "emr_ExtTextOutW->rclBounds.right = %d\n",
146                 emr_ExtTextOutW->rclBounds.right);
147         ok(emr_ExtTextOutW->rclBounds.bottom != -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n",
148                 emr_ExtTextOutW->rclBounds.bottom);
149 
150         for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
151         {
152             ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
153                                      n_record, i, dx[i], orig_dx[i]);
154         }
155         n_record++;
156         emr_processed = TRUE;
157         break;
158     }
159 
160     default:
161         break;
162     }
163 
164     return 1;
165 }
166 
167 static void test_ExtTextOut(void)
168 {
169     HWND hwnd;
170     HDC hdcDisplay, hdcMetafile;
171     HENHMETAFILE hMetafile;
172     HFONT hFont;
173     static const char text[] = "Simple text to test ExtTextOut on metafiles";
174     INT i, len, dx[256];
175     static const RECT rc = { 0, 0, 100, 100 };
176     BOOL ret;
177 
178     assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
179 
180     /* Win9x doesn't play EMFs on invisible windows */
181     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
182                            0, 0, 200, 200, 0, 0, 0, NULL);
183     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
184 
185     hdcDisplay = GetDC(hwnd);
186     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
187 
188     trace("hdcDisplay %p\n", hdcDisplay);
189 
190     SetMapMode(hdcDisplay, MM_TEXT);
191 
192     memset(&orig_lf, 0, sizeof(orig_lf));
193 
194     orig_lf.lfCharSet = ANSI_CHARSET;
195     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
196     orig_lf.lfWeight = FW_DONTCARE;
197     orig_lf.lfHeight = 7;
198     orig_lf.lfQuality = DEFAULT_QUALITY;
199     lstrcpyA(orig_lf.lfFaceName, "Arial");
200     hFont = CreateFontIndirectA(&orig_lf);
201     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
202 
203     hFont = SelectObject(hdcDisplay, hFont);
204 
205     len = lstrlenA(text);
206     for (i = 0; i < len; i++)
207     {
208         ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
209         ok( ret, "GetCharWidthA error %d\n", GetLastError());
210     }
211     hFont = SelectObject(hdcDisplay, hFont);
212 
213     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
214     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
215 
216     trace("hdcMetafile %p\n", hdcMetafile);
217 
218     ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
219        "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
220 
221     hFont = SelectObject(hdcMetafile, hFont);
222 
223     /* 1. pass NULL lpDx */
224     ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
225     ok( ret, "ExtTextOutA error %d\n", GetLastError());
226 
227     /* 2. pass custom lpDx */
228     ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
229     ok( ret, "ExtTextOutA error %d\n", GetLastError());
230 
231     /* 3. pass NULL lprc */
232     ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL);
233     ok( ret, "ExtTextOutA error %d\n", GetLastError());
234 
235     /* 4. test with unmatched BeginPath/EndPath calls */
236     ret = BeginPath(hdcMetafile);
237     ok( ret, "BeginPath error %d\n", GetLastError());
238     ret = BeginPath(hdcMetafile);
239     ok( ret, "BeginPath error %d\n", GetLastError());
240     ret = EndPath(hdcMetafile);
241     ok( ret, "BeginPath error %d\n", GetLastError());
242     ret = ExtTextOutA(hdcMetafile, 0, 60, 0, NULL, text, lstrlenA(text), NULL);
243     ok( ret, "ExtTextOutA error %d\n", GetLastError());
244 
245     hFont = SelectObject(hdcMetafile, hFont);
246     ret = DeleteObject(hFont);
247     ok( ret, "DeleteObject error %d\n", GetLastError());
248 
249     hMetafile = CloseEnhMetaFile(hdcMetafile);
250     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
251 
252     ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
253 
254     ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
255     ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
256 
257     SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
258     SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
259     SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
260     SetROP2(hdcDisplay, R2_NOT);
261     SetArcDirection(hdcDisplay, AD_CLOCKWISE);
262     SetPolyFillMode(hdcDisplay, WINDING);
263     SetStretchBltMode(hdcDisplay, HALFTONE);
264 
265     if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
266     SetBkMode(hdcDisplay, OPAQUE);
267 
268     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
269     ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
270 
271     ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
272         "text align %08x\n", GetTextAlign(hdcDisplay));
273     ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
274     ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
275     ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
276     ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir  %d\n", GetArcDirection(hdcDisplay));
277     ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
278     ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
279 
280     ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
281 
282     ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
283        "A valid hdc has to require a valid rc\n");
284 
285     ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
286        "A null hdc does not require a valid rc\n");
287 
288     ret = DeleteEnhMetaFile(hMetafile);
289     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
290     ret = ReleaseDC(hwnd, hdcDisplay);
291     ok( ret, "ReleaseDC error %d\n", GetLastError());
292     DestroyWindow(hwnd);
293 }
294 
295 struct eto_scale_test_record
296 {
297     INT graphics_mode;
298     INT map_mode;
299     double ex_scale;
300     double ey_scale;
301     BOOL processed;
302 };
303 
304 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
305     const ENHMETARECORD *emr, int n_objs, LPARAM param)
306 {
307     struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
308 
309     if (emr->iType == EMR_EXTTEXTOUTW)
310     {
311         const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
312         ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
313            "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
314         ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
315            "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
316         test->processed = TRUE;
317     }
318 
319     return 1;
320 }
321 
322 static void test_ExtTextOutScale(void)
323 {
324     const RECT rc = { 0, 0, 100, 100 };
325     const WCHAR str[] = {'a',0 };
326     struct eto_scale_test_record test;
327     HDC hdcDisplay, hdcMetafile;
328     HENHMETAFILE hMetafile;
329     HWND hwnd;
330     SIZE wndext, vportext;
331     int horzSize, vertSize, horzRes, vertRes;
332     int ret;
333     int i;
334 
335     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
336                            0, 0, 200, 200, 0, 0, 0, NULL);
337     ok(hwnd != 0, "CreateWindowExA failed\n");
338 
339     hdcDisplay = GetDC(hwnd);
340     ok(hdcDisplay != 0, "GetDC failed\n");
341 
342     horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
343     horzRes  = GetDeviceCaps(hdcDisplay, HORZRES);
344     vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
345     vertRes  = GetDeviceCaps(hdcDisplay, VERTRES);
346     ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
347 
348     for (i = 0; i < 16; i++)
349     {
350         test.graphics_mode = i / 8 + 1;
351         test.map_mode      = i % 8 + 1;
352 
353         ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
354         ok(ret, "SetGraphicsMode failed\n");
355         ret = SetMapMode(hdcDisplay, test.map_mode);
356         ok(ret, "SetMapMode failed\n");
357 
358         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
359         {
360             ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
361             ok(ret, "SetWindowExtEx failed\n");
362             ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
363             ok(ret, "SetViewportExtEx failed\n");
364         }
365 
366         ret = GetViewportExtEx(hdcDisplay, &vportext);
367         ok(ret, "GetViewportExtEx failed\n");
368         ret = GetWindowExtEx(hdcDisplay, &wndext);
369         ok(ret, "GetWindowExtEx failed\n");
370 
371         trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
372                test.graphics_mode, test.map_mode,
373                wndext.cx, wndext.cy, vportext.cx, vportext.cy,
374                horzSize, horzRes, vertSize, vertRes);
375 
376         if (test.graphics_mode == GM_COMPATIBLE)
377         {
378             test.ex_scale = 100.0 * ((FLOAT)horzSize  / (FLOAT)horzRes) /
379                                     ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
380             test.ey_scale = 100.0 * ((FLOAT)vertSize  / (FLOAT)vertRes) /
381                                     ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
382         }
383         else
384         {
385             test.ex_scale = 0.0;
386             test.ey_scale = 0.0;
387         }
388 
389         hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
390         ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
391 
392         ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
393         ok(ret, "SetGraphicsMode failed\n");
394         ret = SetMapMode(hdcMetafile, test.map_mode);
395         ok(ret, "SetMapMode failed\n");
396 
397         if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
398         {
399             ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
400             ok(ret, "SetWindowExtEx failed\n");
401             ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
402             ok(ret, "SetViewportExtEx failed\n");
403         }
404 
405         ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
406         ok(ret, "ExtTextOutW failed\n");
407 
408         hMetafile = CloseEnhMetaFile(hdcMetafile);
409         ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
410 
411         test.processed = 0;
412         ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
413         ok(ret, "EnumEnhMetaFile failed\n");
414         ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
415 
416         ret = DeleteEnhMetaFile(hMetafile);
417         ok(ret, "DeleteEnhMetaFile failed\n");
418     }
419 
420     ret = ReleaseDC(hwnd, hdcDisplay);
421     ok(ret, "ReleaseDC failed\n");
422     DestroyWindow(hwnd);
423 }
424 
425 
426 static void check_dc_state(HDC hdc, int restore_no,
427                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
428                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
429 {
430     BOOL ret;
431     XFORM xform;
432     POINT vp_org, win_org;
433     SIZE vp_size, win_size;
434     FLOAT xscale, yscale, edx, edy;
435 
436     SetLastError(0xdeadbeef);
437     ret = GetWorldTransform(hdc, &xform);
438     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
439     ok(ret, "GetWorldTransform error %u\n", GetLastError());
440 
441     trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
442 
443     ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
444     ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
445 
446     xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
447     trace("x scale %f\n", xscale);
448     ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
449        restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
450 
451     yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
452     trace("y scale %f\n", yscale);
453     ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
454        restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
455 
456     edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
457     ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
458     edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
459     ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
460 
461     return;
462 
463 win9x_here:
464 
465     GetWindowOrgEx(hdc, &win_org);
466     GetViewportOrgEx(hdc, &vp_org);
467     GetWindowExtEx(hdc, &win_size);
468     GetViewportExtEx(hdc, &vp_size);
469 
470     ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
471     ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
472 
473     ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
474     ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
475 
476     ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
477     ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
478 
479     ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
480     ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
481 }
482 
483 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
484                                          const ENHMETARECORD *emr, int n_objs, LPARAM param)
485 {
486     BOOL ret;
487     XFORM xform;
488     POINT pt;
489     SIZE size;
490     static int save_state;
491     static int restore_no;
492     static int select_no;
493 
494     trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
495            hdc, emr->iType, emr->nSize, (void *)param);
496 
497     SetLastError(0xdeadbeef);
498     ret = GetWorldTransform(hdc, &xform);
499     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
500     {
501         ret = GetWindowOrgEx(hdc, &pt);
502         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
503         trace("window org (%d,%d)\n", pt.x, pt.y);
504         ret = GetViewportOrgEx(hdc, &pt);
505         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
506         trace("vport org (%d,%d)\n", pt.x, pt.y);
507         ret = GetWindowExtEx(hdc, &size);
508         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
509         trace("window ext (%d,%d)\n", size.cx, size.cy);
510         ret = GetViewportExtEx(hdc, &size);
511         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
512         trace("vport ext (%d,%d)\n", size.cx, size.cy);
513     }
514     else
515     {
516         ok(ret, "GetWorldTransform error %u\n", GetLastError());
517         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
518     }
519 
520     PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
521 
522     switch (emr->iType)
523     {
524     case EMR_HEADER:
525     {
526         static RECT exp_bounds = { 0, 0, 150, 150 };
527         RECT bounds;
528         const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
529 
530         trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
531                emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
532                emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
533         trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
534                emf->szlDevice.cx, emf->szlDevice.cy);
535 
536         SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
537         ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
538 
539         save_state = 0;
540         restore_no = 0;
541         select_no = 0;
542         check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
543         break;
544     }
545 
546     case EMR_LINETO:
547         {
548             const EMRLINETO *line = (const EMRLINETO *)emr;
549             trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
550             break;
551         }
552     case EMR_SETWINDOWORGEX:
553         {
554             const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
555             trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
556             break;
557         }
558     case EMR_SETWINDOWEXTEX:
559         {
560             const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
561             trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
562             break;
563         }
564     case EMR_SETVIEWPORTORGEX:
565         {
566             const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
567             trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
568             break;
569         }
570     case EMR_SETVIEWPORTEXTEX:
571         {
572             const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
573             trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
574             break;
575         }
576     case EMR_SAVEDC:
577         save_state++;
578         trace("EMR_SAVEDC\n");
579         break;
580 
581     case EMR_RESTOREDC:
582         {
583             const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
584             trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
585 
586             switch(++restore_no)
587             {
588             case 1:
589                 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
590                 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
591                 break;
592             case 2:
593                 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
594                 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
595                 break;
596             case 3:
597                 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
598                 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
599                 break;
600             }
601             ok(restore_no <= 3, "restore_no %d\n", restore_no);
602             save_state += restoredc->iRelative;
603             break;
604         }
605     case EMR_SELECTOBJECT:
606         {
607             const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
608             trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
609             select_no ++;
610             break;
611         }
612     case EMR_EOF:
613         ok(save_state == 0, "EOF save_state %d\n", save_state);
614         ok(select_no == 3, "Too many/few selects  %i\n",select_no);
615         break;
616     }
617 
618     SetLastError(0xdeadbeef);
619     ret = GetWorldTransform(hdc, &xform);
620     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
621     {
622         ret = GetWindowOrgEx(hdc, &pt);
623         ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
624         trace("window org (%d,%d)\n", pt.x, pt.y);
625         ret = GetViewportOrgEx(hdc, &pt);
626         ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
627         trace("vport org (%d,%d)\n", pt.x, pt.y);
628         ret = GetWindowExtEx(hdc, &size);
629         ok(ret, "GetWindowExtEx error %u\n", GetLastError());
630         trace("window ext (%d,%d)\n", size.cx, size.cy);
631         ret = GetViewportExtEx(hdc, &size);
632         ok(ret, "GetViewportExtEx error %u\n", GetLastError());
633         trace("vport ext (%d,%d)\n", size.cx, size.cy);
634     }
635     else
636     {
637         ok(ret, "GetWorldTransform error %u\n", GetLastError());
638         trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
639     }
640 
641     return 1;
642 }
643 
644 static void test_SaveDC(void)
645 {
646     HDC hdcMetafile, hdcDisplay;
647     HENHMETAFILE hMetafile;
648     HWND hwnd;
649     int ret;
650     POINT pt;
651     SIZE size;
652     HFONT hFont,hFont2,hFontOld,hFontCheck;
653     static const RECT rc = { 0, 0, 150, 150 };
654 
655     /* Win9x doesn't play EMFs on invisible windows */
656     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
657                            0, 0, 200, 200, 0, 0, 0, NULL);
658     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
659 
660     hdcDisplay = GetDC(hwnd);
661     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
662 
663     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
664     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
665 
666     SetMapMode(hdcMetafile, MM_ANISOTROPIC);
667 
668     /* Need to write something to the emf, otherwise Windows won't play it back */
669     LineTo(hdcMetafile, 150, 150);
670 
671     SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
672     SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
673     SetWindowExtEx(hdcMetafile, 110, 110, NULL );
674     SetViewportExtEx(hdcMetafile, 120, 120, NULL );
675 
676     /* Force Win9x to update DC state */
677     SetPixelV(hdcMetafile, 50, 50, 0);
678 
679     ret = GetViewportOrgEx(hdcMetafile, &pt);
680     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
681     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
682     ret = GetViewportExtEx(hdcMetafile, &size);
683     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
684     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
685     ret = SaveDC(hdcMetafile);
686     ok(ret == 1, "ret = %d\n", ret);
687 
688     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
689     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
690     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
691     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
692 
693     /* Force Win9x to update DC state */
694     SetPixelV(hdcMetafile, 50, 50, 0);
695 
696     ret = GetViewportOrgEx(hdcMetafile, &pt);
697     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
698     ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
699     ret = GetViewportExtEx(hdcMetafile, &size);
700     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
701     ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
702     ret = SaveDC(hdcMetafile);
703     ok(ret == 2, "ret = %d\n", ret);
704 
705     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
706     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
707     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
708     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
709     SetPolyFillMode( hdcMetafile, ALTERNATE );
710     SetBkColor( hdcMetafile, 0 );
711 
712     /* Force Win9x to update DC state */
713     SetPixelV(hdcMetafile, 50, 50, 0);
714 
715     ret = GetViewportOrgEx(hdcMetafile, &pt);
716     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
717     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
718     ret = GetViewportExtEx(hdcMetafile, &size);
719     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
720     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
721     ret = SaveDC(hdcMetafile);
722     ok(ret == 3, "ret = %d\n", ret);
723 
724     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
725     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
726     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
727     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
728 
729     SetPolyFillMode( hdcMetafile, WINDING );
730     SetBkColor( hdcMetafile, 0x123456 );
731     ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
732     ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
733 
734     /* Force Win9x to update DC state */
735     SetPixelV(hdcMetafile, 50, 50, 0);
736 
737     ret = GetViewportOrgEx(hdcMetafile, &pt);
738     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
739     ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
740     ret = GetViewportExtEx(hdcMetafile, &size);
741     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
742     ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
743     ret = RestoreDC(hdcMetafile, -1);
744     ok(ret, "ret = %d\n", ret);
745 
746     ret = GetViewportOrgEx(hdcMetafile, &pt);
747     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
748     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
749     ret = GetViewportExtEx(hdcMetafile, &size);
750     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
751     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
752     ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
753     ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
754     ret = SaveDC(hdcMetafile);
755     ok(ret == 3, "ret = %d\n", ret);
756 
757     ret = GetViewportOrgEx(hdcMetafile, &pt);
758     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
759     ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
760     ret = GetViewportExtEx(hdcMetafile, &size);
761     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
762     ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
763     ret = RestoreDC(hdcMetafile, 1);
764     ok(ret, "ret = %d\n", ret);
765     ret = GetViewportOrgEx(hdcMetafile, &pt);
766     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
767     ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
768     ret = GetViewportExtEx(hdcMetafile, &size);
769     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
770     ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
771 
772     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
773     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
774     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
775     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
776 
777     /* Force Win9x to update DC state */
778     SetPixelV(hdcMetafile, 50, 50, 0);
779 
780     ret = GetViewportOrgEx(hdcMetafile, &pt);
781     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
782     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
783     ret = GetViewportExtEx(hdcMetafile, &size);
784     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
785     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
786     ret = SaveDC(hdcMetafile);
787     ok(ret == 1, "ret = %d\n", ret);
788 
789     ret = GetViewportOrgEx(hdcMetafile, &pt);
790     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
791     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
792     ret = GetViewportExtEx(hdcMetafile, &size);
793     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
794     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
795     ret = SaveDC(hdcMetafile);
796     ok(ret == 2, "ret = %d\n", ret);
797 
798     memset(&orig_lf, 0, sizeof(orig_lf));
799     orig_lf.lfCharSet = ANSI_CHARSET;
800     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
801     orig_lf.lfWeight = FW_DONTCARE;
802     orig_lf.lfHeight = 7;
803     orig_lf.lfQuality = DEFAULT_QUALITY;
804     lstrcpyA(orig_lf.lfFaceName, "Arial");
805     hFont = CreateFontIndirectA(&orig_lf);
806     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
807 
808     hFontOld = SelectObject(hdcMetafile, hFont);
809 
810     hFont2 = CreateFontIndirectA(&orig_lf);
811     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
812     hFontCheck = SelectObject(hdcMetafile, hFont2);
813     ok(hFontCheck == hFont, "Font not selected\n");
814 
815     /* Force Win9x to update DC state */
816     SetPixelV(hdcMetafile, 50, 50, 0);
817 
818     ret = RestoreDC(hdcMetafile, 1);
819     ok(ret, "ret = %d\n", ret);
820     ret = GetViewportOrgEx(hdcMetafile, &pt);
821     ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
822     ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
823     ret = GetViewportExtEx(hdcMetafile, &size);
824     ok(ret, "GetViewportExtEx error %u\n", GetLastError());
825     ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
826 
827     hFontCheck = SelectObject(hdcMetafile, hFontOld);
828     ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
829        "Font not reverted with DC Restore\n");
830 
831     ret = RestoreDC(hdcMetafile, -20);
832     ok(!ret, "ret = %d\n", ret);
833     ret = RestoreDC(hdcMetafile, 20);
834     ok(!ret, "ret = %d\n", ret);
835 
836     hMetafile = CloseEnhMetaFile(hdcMetafile);
837     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
838 
839     ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
840     ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
841 
842     ret = DeleteObject(hFont);
843     ok( ret, "DeleteObject error %d\n", GetLastError());
844     ret = DeleteObject(hFont2);
845     ok( ret, "DeleteObject error %d\n", GetLastError());
846     ret = DeleteEnhMetaFile(hMetafile);
847     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
848     ret = ReleaseDC(hwnd, hdcDisplay);
849     ok( ret, "ReleaseDC error %d\n", GetLastError());
850     DestroyWindow(hwnd);
851 }
852 
853 static void test_mf_SaveDC(void)
854 {
855     HDC hdcMetafile;
856     HMETAFILE hMetafile;
857     int ret;
858     POINT pt;
859     SIZE size;
860     HFONT hFont,hFont2,hFontOld,hFontCheck;
861 
862     hdcMetafile = CreateMetaFileA(NULL);
863     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
864 
865     ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
866     ok (ret, "SetMapMode should not fail\n");
867 
868     /* Need to write something to the emf, otherwise Windows won't play it back */
869     LineTo(hdcMetafile, 150, 150);
870 
871     pt.x = pt.y = 5555;
872     SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
873     ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
874     pt.x = pt.y = 5555;
875     SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
876     ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
877     size.cx = size.cy = 5555;
878     SetWindowExtEx(hdcMetafile, 110, 110, &size );
879     ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
880     size.cx = size.cy = 5555;
881     SetViewportExtEx(hdcMetafile, 120, 120, &size );
882     ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
883 
884     /* Force Win9x to update DC state */
885     SetPixelV(hdcMetafile, 50, 50, 0);
886 
887     ret = GetViewportOrgEx(hdcMetafile, &pt);
888     todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
889     ret = GetViewportExtEx(hdcMetafile, &size);
890     todo_wine ok (!ret, "GetViewportExtEx should fail\n");
891     ret = SaveDC(hdcMetafile);
892     ok(ret == 1, "ret = %d\n", ret);
893 
894     SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
895     SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
896     SetWindowExtEx(hdcMetafile, 150, 150, NULL );
897     SetViewportExtEx(hdcMetafile, 200, 200, NULL );
898 
899     /* Force Win9x to update DC state */
900     SetPixelV(hdcMetafile, 50, 50, 0);
901 
902     ret = SaveDC(hdcMetafile);
903     ok(ret == 1, "ret = %d\n", ret);
904 
905     SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
906     SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
907     SetWindowExtEx(hdcMetafile, 120, 120, NULL );
908     SetViewportExtEx(hdcMetafile, 300, 300, NULL );
909 
910     /* Force Win9x to update DC state */
911     SetPixelV(hdcMetafile, 50, 50, 0);
912     SetPolyFillMode( hdcMetafile, ALTERNATE );
913     SetBkColor( hdcMetafile, 0 );
914 
915     ret = SaveDC(hdcMetafile);
916     ok(ret == 1, "ret = %d\n", ret);
917 
918     SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
919     SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
920     SetWindowExtEx(hdcMetafile, 200, 200, NULL );
921     SetViewportExtEx(hdcMetafile, 400, 400, NULL );
922 
923     SetPolyFillMode( hdcMetafile, WINDING );
924     SetBkColor( hdcMetafile, 0x123456 );
925     todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
926     todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
927 
928     /* Force Win9x to update DC state */
929     SetPixelV(hdcMetafile, 50, 50, 0);
930 
931     ret = RestoreDC(hdcMetafile, -1);
932     ok(ret, "ret = %d\n", ret);
933 
934     ret = SaveDC(hdcMetafile);
935     ok(ret == 1, "ret = %d\n", ret);
936 
937     ret = RestoreDC(hdcMetafile, 1);
938     ok(ret, "ret = %d\n", ret);
939 
940     SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
941     SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
942     SetWindowExtEx(hdcMetafile, 500, 500, NULL );
943     SetViewportExtEx(hdcMetafile, 50, 50, NULL );
944 
945     /* Force Win9x to update DC state */
946     SetPixelV(hdcMetafile, 50, 50, 0);
947 
948     ret = SaveDC(hdcMetafile);
949     ok(ret == 1, "ret = %d\n", ret);
950 
951     ret = SaveDC(hdcMetafile);
952     ok(ret == 1, "ret = %d\n", ret);
953 
954     memset(&orig_lf, 0, sizeof(orig_lf));
955     orig_lf.lfCharSet = ANSI_CHARSET;
956     orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
957     orig_lf.lfWeight = FW_DONTCARE;
958     orig_lf.lfHeight = 7;
959     orig_lf.lfQuality = DEFAULT_QUALITY;
960     lstrcpyA(orig_lf.lfFaceName, "Arial");
961     hFont = CreateFontIndirectA(&orig_lf);
962     ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
963 
964     hFontOld = SelectObject(hdcMetafile, hFont);
965 
966     hFont2 = CreateFontIndirectA(&orig_lf);
967     ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
968     hFontCheck = SelectObject(hdcMetafile, hFont2);
969     ok(hFontCheck == hFont, "Font not selected\n");
970 
971     /* Force Win9x to update DC state */
972     SetPixelV(hdcMetafile, 50, 50, 0);
973 
974     ret = RestoreDC(hdcMetafile, 1);
975     ok(ret, "ret = %d\n", ret);
976 
977     hFontCheck = SelectObject(hdcMetafile, hFontOld);
978     ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
979 
980     /* restore level is ignored */
981     ret = RestoreDC(hdcMetafile, -20);
982     ok(ret, "ret = %d\n", ret);
983     ret = RestoreDC(hdcMetafile, 20);
984     ok(ret, "ret = %d\n", ret);
985     ret = RestoreDC(hdcMetafile, 0);
986     ok(ret, "ret = %d\n", ret);
987 
988     hMetafile = CloseMetaFile(hdcMetafile);
989     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
990 
991     ret = DeleteMetaFile(hMetafile);
992     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
993     ret = DeleteObject(hFont);
994     ok( ret, "DeleteObject error %d\n", GetLastError());
995     ret = DeleteObject(hFont2);
996     ok( ret, "DeleteObject error %d\n", GetLastError());
997 }
998 
999 
1000 /* Win-format metafile (mfdrv) tests */
1001 /* These tests compare the generated metafiles byte-by-byte */
1002 /* with the nominal results. */
1003 
1004 /* Maximum size of sample metafiles in bytes. */
1005 #define MF_BUFSIZE 1024
1006 
1007 /* 8x8 bitmap data for a pattern brush */
1008 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
1009     0x01, 0x00, 0x02, 0x00,
1010     0x03, 0x00, 0x04, 0x00,
1011     0x05, 0x00, 0x06, 0x00,
1012     0x07, 0x00, 0x08, 0x00
1013 };
1014 
1015 /* Sample metafiles to be compared to the outputs of the
1016  * test functions.
1017  */
1018 
1019 static const unsigned char MF_BLANK_BITS[] = {
1020     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1021     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1022     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 };
1024 
1025 static const unsigned char MF_GRAPHICS_BITS[] = {
1026     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1027     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1028     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1029     0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1030     0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1031     0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1032     0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1033     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1034     0x00, 0x00, 0x00, 0x00
1035 };
1036 
1037 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1038     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1039     0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1040     0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1041     0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1042     0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1043     0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1044     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1045     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1046     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047     0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1048     0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1049     0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1050     0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1051     0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1052     0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1053     0x00, 0x00
1054 };
1055 
1056 static const unsigned char MF_DCBRUSH_BITS[] =
1057 {
1058     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1059     0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1060     0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1061     0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1062     0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1063     0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1064     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1065     0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1066     0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1067     0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1068     0x00, 0x00, 0x00, 0x00
1069 };
1070 
1071 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1072 {
1073     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1074     0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1075     0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1076     0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1077     0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1078     0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1079     0x00, 0x00
1080 };
1081 
1082 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1083 {
1084     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1085     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1086     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1087     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088     0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1089     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1090     0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1091     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1092     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1094     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1095     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1097     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1098     0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1099     0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1101     0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1102     0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1103     0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1104     0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1105     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1106     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1107     0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1108     0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1109     0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1110     0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1111     0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1112     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1113     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1114     0x14, 0x00, 0x00, 0x00
1115 };
1116 
1117 static const unsigned char MF_LINETO_BITS[] = {
1118     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1119     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1120     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1121     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1122     0x00, 0x00
1123 };
1124 
1125 static const unsigned char EMF_LINETO_BITS[] = {
1126     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1127     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1128     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1129     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1131     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1132     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1133     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1136     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1137     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1139     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1140     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1141     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1142     0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1143     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1144     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1145     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1146     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1147     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1148     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1149     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1150     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1151     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1152     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1153     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1154     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1155     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1156     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1157     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1158     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1159     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1160     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1161     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1163     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1165 };
1166 
1167 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1168     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1169     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1170     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1171     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172     0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1173     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1174     0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1175     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1178     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1179     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1180     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1181     0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1182     0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1183     0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1184     0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1185     0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1186     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1187     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1188     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1189     0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1190     0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1191     0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1192     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1194     0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1195     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1196     0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1197     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1198     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1199     0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1200     0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1201     0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1202     0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1203     0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204     0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1205     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1207 };
1208 
1209 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1210     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1211     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212     0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1213     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214     0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1215     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1216     0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1217     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1219     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1220     0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1221     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222     0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1223     0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1224     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1225     0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1226     0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1227     0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1228     0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1229     0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1230     0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1231     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1232     0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1233     0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1234     0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1235     0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1236     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1237     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1238     0x14, 0x00, 0x00, 0x00
1239 };
1240 
1241 static const unsigned char EMF_BITBLT[] =
1242 {
1243     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1244     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1246     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247     0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1248     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1249     0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1250     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1251     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1252     0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1253     0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1254     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255     0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1256     0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1257     0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1259     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1261     0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1262     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1264     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1265     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1267     0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1268     0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1269     0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1270     0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1271     0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1272     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1279     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280     0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1281     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282     0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1283     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284     0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1285     0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1286     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1287     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288     0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1289     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292     0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1293     0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1295     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1296     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1297     0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1298     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299     0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1300     0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1301     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1303     0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1304     0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1305     0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1306     0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1307     0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1308     0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1309     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1311     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1312     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1313     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1314     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1315     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1316     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1318     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1319     0x14, 0x00, 0x00, 0x00
1320 };
1321 
1322 static const unsigned char EMF_DCBRUSH_BITS[] =
1323 {
1324     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1325     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1326     0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1327     0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1328     0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1329     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1330     0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1331     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1332     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333     0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1334     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1335     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1336     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1337     0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1338     0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1339     0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1340     0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1341     0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1342     0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1343     0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1344     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1345     0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1346     0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348     0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1349     0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1350     0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1351     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1352     0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1353     0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1354     0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1355     0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1356     0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1357     0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1358     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1359     0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1360     0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1361     0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1362     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1363     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1364     0x14, 0x00, 0x00, 0x00
1365 };
1366 
1367 static const unsigned char EMF_BEZIER_BITS[] =
1368 {
1369     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1370     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371     0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1372     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1373     0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1374     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1375     0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1376     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1377     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1378     0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1379     0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1380     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381     0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1382     0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1383     0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1384     0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1385     0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1386     0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1387     0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1388     0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1389     0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1390     0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1391     0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1392     0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1393     0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1394     0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1395     0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1396     0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1397     0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1398     0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1399     0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1400     0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1401     0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1402     0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1403     0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1404     0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1405     0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406     0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1407     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1408     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1409     0x14, 0x00, 0x00, 0x00
1410 };
1411 
1412 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1413 {
1414     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1415     0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1416     0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1417     0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1418     0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1419     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1420     0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1421     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1422     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423     0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1424     0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1425     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1426     0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1427     0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1428     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1429     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1430     0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1431     0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1432     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1433     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1434     0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1435     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1436     0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1437     0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1438     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1439     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1440     0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1441     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1442     0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1443     0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1444     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1445     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1446     0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1447     0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1448     0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1449     0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1450     0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1451     0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1452     0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1453     0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1454     0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1455     0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1456     0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1457     0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1458     0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1459     0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1460     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1461     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1462     0x14, 0x00, 0x00, 0x00
1463 };
1464 
1465 static const unsigned char EMF_GRADIENTFILL_BITS[] =
1466 {
1467     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1468     0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1469     0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1470     0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1471     0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1472     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1473     0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1474     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1475     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1476     0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1477     0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1478     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1479     0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1480     0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1481     0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1482     0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1483     0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1484     0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1485     0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1486     0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1487     0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1488     0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1489     0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1490     0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1491     0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1492     0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1493     0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1494     0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1495     0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1496     0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1497     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1498     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1499     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1500     0x14, 0x00, 0x00, 0x00
1501 };
1502 
1503 /* For debugging or dumping the raw metafiles produced by
1504  * new test functions.
1505  */
1506 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1507                                  INT nobj, LPARAM param)
1508 {
1509     trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1510            hdc, mr->rdFunction, mr->rdSize, (void *)param);
1511     return TRUE;
1512 }
1513 
1514 /* For debugging or dumping the raw metafiles produced by
1515  * new test functions.
1516  */
1517 
1518 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1519 {
1520     BYTE buf[MF_BUFSIZE];
1521     UINT mfsize, i;
1522 
1523     if (!winetest_debug) return;
1524 
1525     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1526     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1527 
1528     printf ("MetaFile %s has bits:\n{\n    ", desc);
1529     for (i=0; i<mfsize; i++)
1530     {
1531         printf ("0x%02x", buf[i]);
1532         if (i == mfsize-1)
1533             printf ("\n");
1534         else if (i % 8 == 7)
1535             printf (",\n    ");
1536         else
1537             printf (", ");
1538     }
1539     printf ("};\n");
1540 }
1541 
1542 /* Compare the metafile produced by a test function with the
1543  * expected raw metafile data in "bits".
1544  * Return value is 0 for a perfect match,
1545  * -1 if lengths aren't equal,
1546  * otherwise returns the number of non-matching bytes.
1547  */
1548 
1549 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1550     const char *desc)
1551 {
1552     unsigned char buf[MF_BUFSIZE];
1553     UINT mfsize, i;
1554     int diff;
1555 
1556     mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1557     ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1558     if (mfsize < MF_BUFSIZE)
1559         ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1560             desc, mfsize, bsize);
1561     else
1562         ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1563             desc, mfsize, bsize);
1564     if (mfsize != bsize)
1565         return -1;
1566 
1567     diff = 0;
1568     for (i=0; i<bsize; i++)
1569     {
1570        if (buf[i] !=  bits[i])
1571            diff++;
1572     }
1573     ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1574         desc, mfsize, bsize, diff);
1575 
1576     return diff;
1577 }
1578 
1579 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1580 {
1581     unsigned char buf[MF_BUFSIZE];
1582     DWORD mfsize, rd_size, i;
1583     int diff;
1584     HANDLE hfile;
1585     BOOL ret;
1586 
1587     hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1588     assert(hfile != INVALID_HANDLE_VALUE);
1589 
1590     mfsize = GetFileSize(hfile, NULL);
1591     assert(mfsize <= MF_BUFSIZE);
1592 
1593     ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1594     ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1595 
1596     CloseHandle(hfile);
1597 
1598     ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1599 
1600     if (mfsize != bsize)
1601         return -1;
1602 
1603     diff = 0;
1604     for (i=0; i<bsize; i++)
1605     {
1606         if (buf[i] != bits[i])
1607             diff++;
1608     }
1609     ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1610         desc, mfsize, bsize, diff);
1611 
1612     return diff;
1613 }
1614 
1615 /* For debugging or dumping the raw EMFs produced by
1616  * new test functions.
1617  */
1618 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1619 {
1620     BYTE buf[MF_BUFSIZE];
1621     UINT mfsize, i;
1622 
1623     if (!winetest_debug) return;
1624 
1625     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1626     ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1627 
1628     printf("EMF %s has bits:\n{\n    ", desc);
1629     for (i = 0; i < mfsize; i++)
1630     {
1631         printf ("0x%02x", buf[i]);
1632         if (i == mfsize-1)
1633             printf ("\n");
1634         else if (i % 8 == 7)
1635             printf (",\n    ");
1636         else
1637             printf (", ");
1638     }
1639     printf ("};\n");
1640 }
1641 
1642 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1643 {
1644     BYTE *emf;
1645     BYTE buf[MF_BUFSIZE];
1646     UINT mfsize, offset;
1647 
1648     if (!winetest_debug) return;
1649 
1650     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1651     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1652 
1653     printf("EMF %s has records:\n", desc);
1654 
1655     emf = buf;
1656     offset = 0;
1657     while(offset < mfsize)
1658     {
1659         EMR *emr = (EMR *)(emf + offset);
1660         printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1661         /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1662         offset += emr->nSize;
1663     }
1664 }
1665 
1666 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1667 {
1668     const BYTE *buf;
1669     DWORD i;
1670 
1671     if (!winetest_debug) return;
1672 
1673     printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1674     buf = (const BYTE *)emr;
1675     for (i = 0; i < emr->nSize; i++)
1676     {
1677         printf ("0x%02x", buf[i]);
1678         if (i == emr->nSize - 1)
1679             printf ("\n");
1680         else if (i % 8 == 7)
1681             printf (",\n");
1682         else
1683             printf (", ");
1684     }
1685     printf ("};\n");
1686 }
1687 
1688 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1689 {
1690     trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1691           eto->rclBounds.right, eto->rclBounds.bottom);
1692     trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1693     trace("exScale: %f\n", eto->exScale);
1694     trace("eyScale: %f\n", eto->eyScale);
1695     trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1696     trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1697     trace("emrtext.offString %#x\n", eto->emrtext.offString);
1698     trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1699     trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1700           eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1701     trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1702 }
1703 
1704 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1705                              const char *desc, BOOL ignore_scaling)
1706 {
1707     int diff;
1708 
1709     ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1710        desc, emr1->iType, emr2->iType);
1711 
1712     ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1713        desc, emr1->nSize, emr2->nSize);
1714 
1715     /* iType and nSize mismatches are fatal */
1716     if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1717 
1718     /* contents of EMR_GDICOMMENT are not interesting */
1719     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1720 
1721     /* different Windows versions setup DC scaling differently when
1722      * converting an old style metafile to an EMF.
1723      */
1724     if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1725                            emr1->iType == EMR_SETVIEWPORTEXTEX))
1726         return TRUE;
1727 
1728     if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1729     {
1730         EMREXTTEXTOUTW *eto1, *eto2;
1731 
1732         eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1733         memcpy(eto1, emr1, emr1->nSize);
1734         eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1735         memcpy(eto2, emr2, emr2->nSize);
1736 
1737         /* different Windows versions setup DC scaling differently */
1738         eto1->exScale = eto1->eyScale = 0.0;
1739         eto2->exScale = eto2->eyScale = 0.0;
1740 
1741         diff = memcmp(eto1, eto2, emr1->nSize);
1742         if (diff)
1743         {
1744             dump_EMREXTTEXTOUT(eto1);
1745             dump_EMREXTTEXTOUT(eto2);
1746         }
1747         HeapFree(GetProcessHeap(), 0, eto1);
1748         HeapFree(GetProcessHeap(), 0, eto2);
1749     }
1750     else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1751     {
1752         /* We have to take care of NT4 differences here */
1753         diff = memcmp(emr1, emr2, emr1->nSize);
1754         if (diff)
1755         {
1756             ENHMETARECORD *emr_nt4;
1757 
1758             emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1759             memcpy(emr_nt4, emr2, emr2->nSize);
1760             /* Correct the nRgnSize field */
1761             emr_nt4->dParm[5] = sizeof(RECT);
1762 
1763             diff = memcmp(emr1, emr_nt4, emr1->nSize);
1764             if (!diff)
1765                 win_skip("Catered for NT4 differences\n");
1766 
1767             HeapFree(GetProcessHeap(), 0, emr_nt4);
1768         }
1769     }
1770     else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1771     {
1772         EMRPOLYBEZIER16 *eto1, *eto2;
1773 
1774         eto1 = (EMRPOLYBEZIER16*)emr1;
1775         eto2 = (EMRPOLYBEZIER16*)emr2;
1776 
1777         diff = eto1->cpts != eto2->cpts;
1778         if(!diff)
1779             diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1780     }
1781     else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1782     {
1783         EMRPOLYBEZIER *eto1, *eto2;
1784 
1785         eto1 = (EMRPOLYBEZIER*)emr1;
1786         eto2 = (EMRPOLYBEZIER*)emr2;
1787 
1788         diff = eto1->cptl != eto2->cptl;
1789         if(!diff)
1790             diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1791     }
1792     else
1793         diff = memcmp(emr1, emr2, emr1->nSize);
1794 
1795     ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1796 
1797     if (diff)
1798     {
1799         dump_emf_record(emr1, "expected bits");
1800         dump_emf_record(emr2, "actual bits");
1801     }
1802 
1803     return diff == 0; /* report all non-fatal record mismatches */
1804 }
1805 
1806 /* Compare the EMF produced by a test function with the
1807  * expected raw EMF data in "bits".
1808  * Return value is 0 for a perfect match,
1809  * -1 if lengths aren't equal,
1810  * otherwise returns the number of non-matching bytes.
1811  */
1812 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1813                             UINT bsize, const char *desc,
1814                             BOOL ignore_scaling)
1815 {
1816     unsigned char buf[MF_BUFSIZE];
1817     UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1818     const ENHMETAHEADER *emh1, *emh2;
1819 
1820     mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1821     ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1822 
1823     /* ENHMETAHEADER size could differ, depending on platform */
1824     diff_nt4 = sizeof(SIZEL);
1825     diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1826 
1827     if (mfsize < MF_BUFSIZE)
1828     {
1829         ok(mfsize == bsize ||
1830            broken(mfsize == bsize - diff_nt4) ||  /* NT4 */
1831            broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1832            "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1833     }
1834     else
1835         ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1836            desc, mfsize, bsize);
1837 
1838     /* basic things must match */
1839     emh1 = (const ENHMETAHEADER *)bits;
1840     emh2 = (const ENHMETAHEADER *)buf;
1841     ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1842     ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1843     ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1844     ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1845 
1846     ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1847     ok(emh1->nSize == emh2->nSize ||
1848        broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1849        broken(emh1->nSize - diff_9x == emh2->nSize),
1850        "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1851     ok(emh1->rclBounds.left == emh2->rclBounds.left, "%s: expected rclBounds.left = %d, got %d\n",
1852             desc, emh1->rclBounds.left, emh2->rclBounds.left);
1853     ok(emh1->rclBounds.top == emh2->rclBounds.top, "%s: expected rclBounds.top = %d, got %d\n",
1854             desc, emh1->rclBounds.top, emh2->rclBounds.top);
1855     ok(emh1->rclBounds.right == emh2->rclBounds.right, "%s: expected rclBounds.right = %d, got %d\n",
1856             desc, emh1->rclBounds.right, emh2->rclBounds.right);
1857     ok(emh1->rclBounds.bottom == emh2->rclBounds.bottom, "%s: expected rclBounds.bottom = %d, got %d\n",
1858             desc, emh1->rclBounds.bottom, emh2->rclBounds.bottom);
1859     ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1860     ok(emh1->nBytes == emh2->nBytes ||
1861        broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1862        broken(emh1->nBytes - diff_9x == emh2->nBytes),
1863        "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1864     ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1865 
1866     offset1 = emh1->nSize;
1867     offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1868     while (offset1 < emh1->nBytes)
1869     {
1870         const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1871         const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1872 
1873         trace("%s: EMF record %u, size %u/record %u, size %u\n",
1874               desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1875 
1876         if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1877 
1878         /* We have already bailed out if iType or nSize don't match */
1879         offset1 += emr1->nSize;
1880         offset2 += emr2->nSize;
1881     }
1882     return 0;
1883 }
1884 
1885 
1886 /* tests blitting to an EMF */
1887 static void test_emf_BitBlt(void)
1888 {
1889     HDC hdcDisplay, hdcMetafile, hdcBitmap;
1890     HBITMAP hBitmap, hOldBitmap;
1891     HENHMETAFILE hMetafile;
1892 #define BMP_DIM 4
1893     BITMAPINFOHEADER bmih =
1894     {
1895         sizeof(BITMAPINFOHEADER),
1896         BMP_DIM,/* biWidth */
1897         BMP_DIM,/* biHeight */
1898         1,      /* biPlanes */
1899         24,     /* biBitCount */
1900         BI_RGB, /* biCompression */
1901         0,      /* biXPelsPerMeter */
1902         0,      /* biYPelsPerMeter */
1903         0,      /* biClrUsed */
1904         0,      /* biClrImportant */
1905     };
1906     void *bits;
1907     XFORM xform;
1908     BOOL ret;
1909 
1910     hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1911     ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1912 
1913     hdcBitmap = CreateCompatibleDC(hdcDisplay);
1914     ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1915     ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
1916     bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1917     bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1918     hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1919                                DIB_RGB_COLORS, &bits, NULL, 0);
1920     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1921 
1922     hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1923     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1924 
1925     /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1926     ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1927     ok( ret, "BitBlt(BLACKNESS) failed\n" );
1928 
1929     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1930     ok( ret, "BitBlt(SRCCOPY) failed\n" );
1931     ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1932     ok( ret, "BitBlt(WHITENESS) failed\n" );
1933 
1934     ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
1935     ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
1936     ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
1937     ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
1938     ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
1939     memset(&xform, 0, sizeof(xform));
1940     xform.eM11 = 0.5;
1941     xform.eM22 = 1.0;
1942     ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
1943 
1944     ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
1945     ok( ret, "StretchBlt(SRCCOPY) failed\n" );
1946 
1947     hMetafile = CloseEnhMetaFile(hdcMetafile);
1948     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1949 
1950     if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1951         "emf_BitBlt", FALSE) != 0)
1952     {
1953         dump_emf_bits(hMetafile, "emf_BitBlt");
1954         dump_emf_records(hMetafile, "emf_BitBlt");
1955     }
1956 
1957     SelectObject(hdcBitmap, hOldBitmap);
1958     DeleteObject(hBitmap);
1959     DeleteDC(hdcBitmap);
1960     DeleteDC(hdcDisplay);
1961 #undef BMP_DIM
1962 }
1963 
1964 static void test_emf_DCBrush(void)
1965 {
1966     HDC hdcMetafile;
1967     HENHMETAFILE hMetafile;
1968     HBRUSH hBrush;
1969     HPEN hPen;
1970     BOOL ret;
1971     COLORREF color;
1972 
1973     if (!pSetDCBrushColor || !pSetDCPenColor)
1974     {
1975         win_skip( "SetDCBrush/PenColor not supported\n" );
1976         return;
1977     }
1978 
1979     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1980     ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1981 
1982     hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1983     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1984 
1985     hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1986     ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1987 
1988     color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1989     ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1990 
1991     color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1992     ok( color == 0, "SetDCPenColor returned %x\n", color );
1993 
1994     Rectangle( hdcMetafile, 10, 10, 20, 20 );
1995 
1996     color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1997     ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1998 
1999     hMetafile = CloseEnhMetaFile(hdcMetafile);
2000     ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
2001 
2002     if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
2003                           "emf_DC_Brush", FALSE ) != 0)
2004     {
2005         dump_emf_bits(hMetafile, "emf_DC_Brush");
2006         dump_emf_records(hMetafile, "emf_DC_Brush");
2007     }
2008     ret = DeleteEnhMetaFile(hMetafile);
2009     ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2010     ret = DeleteObject(hBrush);
2011     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2012     ret = DeleteObject(hPen);
2013     ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
2014 }
2015 
2016 /* Test a blank metafile.  May be used as a template for new tests. */
2017 
2018 static void test_mf_Blank(void)
2019 {
2020     HDC hdcMetafile;
2021     HMETAFILE hMetafile;
2022     INT caps;
2023     BOOL ret;
2024     INT type;
2025 
2026     hdcMetafile = CreateMetaFileA(NULL);
2027     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2028     trace("hdcMetafile %p\n", hdcMetafile);
2029 
2030 /* Tests on metafile initialization */
2031     caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
2032     ok (caps == DT_METAFILE,
2033         "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
2034 
2035     hMetafile = CloseMetaFile(hdcMetafile);
2036     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2037     type = GetObjectType(hMetafile);
2038     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2039     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2040 
2041     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2042         "mf_blank") != 0)
2043     {
2044         dump_mf_bits(hMetafile, "mf_Blank");
2045         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2046     }
2047 
2048     ret = DeleteMetaFile(hMetafile);
2049     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2050 }
2051 
2052 static void test_CopyMetaFile(void)
2053 {
2054     HDC hdcMetafile;
2055     HMETAFILE hMetafile, hmf_copy;
2056     BOOL ret;
2057     char temp_path[MAX_PATH];
2058     char mf_name[MAX_PATH];
2059     INT type;
2060 
2061     hdcMetafile = CreateMetaFileA(NULL);
2062     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2063     trace("hdcMetafile %p\n", hdcMetafile);
2064 
2065     hMetafile = CloseMetaFile(hdcMetafile);
2066     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2067     type = GetObjectType(hMetafile);
2068     ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2069 
2070     if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2071         "mf_blank") != 0)
2072     {
2073         dump_mf_bits(hMetafile, "mf_Blank");
2074         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2075     }
2076 
2077     GetTempPathA(MAX_PATH, temp_path);
2078     GetTempFileNameA(temp_path, "wmf", 0, mf_name);
2079 
2080     hmf_copy = CopyMetaFileA(hMetafile, mf_name);
2081     ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
2082 
2083     type = GetObjectType(hmf_copy);
2084     ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
2085 
2086     ret = DeleteMetaFile(hMetafile);
2087     ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2088 
2089     if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
2090     {
2091         dump_mf_bits(hmf_copy, "mf_Blank");
2092         EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
2093     }
2094 
2095     ret = DeleteMetaFile(hmf_copy);
2096     ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
2097 
2098     DeleteFileA(mf_name);
2099 }
2100 
2101 static void test_SetMetaFileBits(void)
2102 {
2103     HMETAFILE hmf;
2104     INT type;
2105     BOOL ret;
2106     BYTE buf[256];
2107     METAHEADER *mh;
2108 
2109     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2110     trace("hmf %p\n", hmf);
2111     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2112     type = GetObjectType(hmf);
2113     ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
2114 
2115     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2116     {
2117         dump_mf_bits(hmf, "mf_Graphics");
2118         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2119     }
2120 
2121     ret = DeleteMetaFile(hmf);
2122     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2123 
2124     /* NULL data crashes XP SP1 */
2125     /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2126 
2127     /* Now with zero size */
2128     SetLastError(0xdeadbeef);
2129     hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2130     trace("hmf %p\n", hmf);
2131     ok(!hmf, "SetMetaFileBitsEx should fail\n");
2132     ok(GetLastError() == ERROR_INVALID_DATA ||
2133        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2134        "wrong error %d\n", GetLastError());
2135 
2136     /* Now with odd size */
2137     SetLastError(0xdeadbeef);
2138     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2139     trace("hmf %p\n", hmf);
2140     ok(!hmf, "SetMetaFileBitsEx should fail\n");
2141     ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2142 
2143     /* Now with zeroed out header fields */
2144     assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2145     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2146     mh = (METAHEADER *)buf;
2147     /* corruption of any of the below fields leads to a failure */
2148     mh->mtType = 0;
2149     mh->mtVersion = 0;
2150     mh->mtHeaderSize = 0;
2151     SetLastError(0xdeadbeef);
2152     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2153     trace("hmf %p\n", hmf);
2154     ok(!hmf, "SetMetaFileBitsEx should fail\n");
2155     ok(GetLastError() == ERROR_INVALID_DATA ||
2156        broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2157        "wrong error %d\n", GetLastError());
2158 
2159     /* Now with corrupted mtSize field */
2160     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2161     mh = (METAHEADER *)buf;
2162     /* corruption of mtSize doesn't lead to a failure */
2163     mh->mtSize *= 2;
2164     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2165     trace("hmf %p\n", hmf);
2166     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2167 
2168     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2169     {
2170         dump_mf_bits(hmf, "mf_Graphics");
2171         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2172     }
2173 
2174     ret = DeleteMetaFile(hmf);
2175     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2176 
2177 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2178     /* Now with zeroed out mtSize field */
2179     memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2180     mh = (METAHEADER *)buf;
2181     /* zeroing mtSize doesn't lead to a failure */
2182     mh->mtSize = 0;
2183     hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2184     trace("hmf %p\n", hmf);
2185     ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2186 
2187     if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2188     {
2189         dump_mf_bits(hmf, "mf_Graphics");
2190         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2191     }
2192 
2193     ret = DeleteMetaFile(hmf);
2194     ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2195 #endif
2196 }
2197 
2198 /* Simple APIs from mfdrv/graphics.c
2199  */
2200 
2201 static void test_mf_Graphics(void)
2202 {
2203     HDC hdcMetafile;
2204     HMETAFILE hMetafile;
2205     POINT oldpoint;
2206     BOOL ret;
2207 
2208     hdcMetafile = CreateMetaFileA(NULL);
2209     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2210     trace("hdcMetafile %p\n", hdcMetafile);
2211 
2212     ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2213     ok( ret, "MoveToEx error %d.\n", GetLastError());
2214     ret = LineTo(hdcMetafile, 2, 2);
2215     ok( ret, "LineTo error %d.\n", GetLastError());
2216     ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2217     ok( ret, "MoveToEx error %d.\n", GetLastError());
2218 
2219 /* oldpoint gets garbage under Win XP, so the following test would
2220  * work under Wine but fails under Windows:
2221  *
2222  *   ok((oldpoint.x == 2) && (oldpoint.y == 2),
2223  *       "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2224  *       oldpoint.x, oldpoint.y);
2225  */
2226 
2227     ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2228     ok( ret, "Ellipse error %d.\n", GetLastError());
2229 
2230     hMetafile = CloseMetaFile(hdcMetafile);
2231     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2232     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2233 
2234     if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2235         "mf_Graphics") != 0)
2236     {
2237         dump_mf_bits(hMetafile, "mf_Graphics");
2238         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2239     }
2240 
2241     ret = DeleteMetaFile(hMetafile);
2242     ok( ret, "DeleteMetaFile(%p) error %d\n",
2243         hMetafile, GetLastError());
2244 }
2245 
2246 static void test_mf_PatternBrush(void)
2247 {
2248     HDC hdcMetafile;
2249     HMETAFILE hMetafile;
2250     LOGBRUSH *orig_lb;
2251     HBRUSH hBrush;
2252     BOOL ret;
2253 
2254     orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2255 
2256     orig_lb->lbStyle = BS_PATTERN;
2257     orig_lb->lbColor = RGB(0, 0, 0);
2258     orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2259     ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2260 
2261     hBrush = CreateBrushIndirect (orig_lb);
2262     ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2263 
2264     hdcMetafile = CreateMetaFileA(NULL);
2265     ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2266     trace("hdcMetafile %p\n", hdcMetafile);
2267 
2268     hBrush = SelectObject(hdcMetafile, hBrush);
2269     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2270 
2271     hMetafile = CloseMetaFile(hdcMetafile);
2272     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2273     ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2274 
2275     if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2276         "mf_Pattern_Brush") != 0)
2277     {
2278         dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2279         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2280     }
2281 
2282     ret = DeleteMetaFile(hMetafile);
2283     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2284     ret = DeleteObject(hBrush);
2285     ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2286     ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2287     ok( ret, "DeleteObject(HBITMAP) error %d\n",
2288         GetLastError());
2289     HeapFree (GetProcessHeap(), 0, orig_lb);
2290 }
2291 
2292 static void test_mf_DCBrush(void)
2293 {
2294     HDC hdcMetafile;
2295     HMETAFILE hMetafile;
2296     HBRUSH hBrush;
2297     HPEN hPen;
2298     BOOL ret;
2299     COLORREF color;
2300 
2301     if (!pSetDCBrushColor || !pSetDCPenColor)
2302     {
2303         win_skip( "SetDCBrush/PenColor not supported\n" );
2304         return;
2305     }
2306 
2307     hdcMetafile = CreateMetaFileA(NULL);
2308     ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2309 
2310     hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2311     ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2312 
2313     hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2314     ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2315 
2316     color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2317     ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2318 
2319     color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2320     ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2321 
2322     Rectangle( hdcMetafile, 10, 10, 20, 20 );
2323 
2324     color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2325     ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2326 
2327     hMetafile = CloseMetaFile(hdcMetafile);
2328     ok( hMetafile != 0, "CloseMetaFile failed\n" );
2329 
2330     if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2331     {
2332         dump_mf_bits(hMetafile, "mf_DCBrush");
2333         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2334     }
2335     ret = DeleteMetaFile(hMetafile);
2336     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2337 }
2338 
2339 static void test_mf_ExtTextOut_on_path(void)
2340 {
2341     HDC hdcMetafile;
2342     HMETAFILE hMetafile;
2343     BOOL ret;
2344     static const INT dx[4] = { 3, 5, 8, 12 };
2345 
2346     hdcMetafile = CreateMetaFileA(NULL);
2347     ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2348     trace("hdcMetafile %p\n", hdcMetafile);
2349 
2350     ret = BeginPath(hdcMetafile);
2351     ok(!ret, "BeginPath on metafile DC should fail\n");
2352 
2353     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2354     ok(ret, "ExtTextOut error %d\n", GetLastError());
2355 
2356     ret = EndPath(hdcMetafile);
2357     ok(!ret, "EndPath on metafile DC should fail\n");
2358 
2359     hMetafile = CloseMetaFile(hdcMetafile);
2360     ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2361 
2362     if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2363         "mf_TextOut_on_path") != 0)
2364     {
2365         dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2366         EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2367     }
2368 
2369     ret = DeleteMetaFile(hMetafile);
2370     ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2371 }
2372 
2373 static void test_emf_ExtTextOut_on_path(void)
2374 {
2375     HWND hwnd;
2376     HDC hdcDisplay, hdcMetafile;
2377     HENHMETAFILE hMetafile;
2378     BOOL ret;
2379     static const INT dx[4] = { 3, 5, 8, 12 };
2380 
2381     /* Win9x doesn't play EMFs on invisible windows */
2382     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2383                            0, 0, 200, 200, 0, 0, 0, NULL);
2384     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2385 
2386     hdcDisplay = GetDC(hwnd);
2387     ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2388 
2389     hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2390     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2391 
2392     ret = BeginPath(hdcMetafile);
2393     ok(ret, "BeginPath error %d\n", GetLastError());
2394 
2395     ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2396     todo_wine ok(ret, "ExtTextOut error %d\n", GetLastError());
2397 
2398     ret = EndPath(hdcMetafile);
2399     ok(ret, "EndPath error %d\n", GetLastError());
2400 
2401     hMetafile = CloseEnhMetaFile(hdcMetafile);
2402     ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2403 
2404     /* this doesn't succeed yet: EMF has correct size, all EMF records
2405      * are there, but their contents don't match for different reasons.
2406      */
2407     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2408         "emf_TextOut_on_path", FALSE) != 0)
2409     {
2410         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2411         dump_emf_records(hMetafile, "emf_TextOut_on_path");
2412     }
2413 
2414     ret = DeleteEnhMetaFile(hMetafile);
2415     ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2416     ret = ReleaseDC(hwnd, hdcDisplay);
2417     ok(ret, "ReleaseDC error %d\n", GetLastError());
2418     DestroyWindow(hwnd);
2419 }
2420 
2421 static const unsigned char EMF_CLIPPING[] =
2422 {
2423     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2424     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2425     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2426     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2427     0x1a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2428     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2429     0x04, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2430     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2431     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2432     0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
2433     0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
2434     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2435     0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
2436     0x30, 0xda, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2437     0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2438     0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2439     0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2440     0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2441     0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2442     0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2443     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2444     0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2445     0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2446     0x00, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
2447     0x08, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
2448     0x18, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2449     0x64, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00,
2450     0xff, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
2451     0x08, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
2452     0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2453     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
2454     0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2455     0x14, 0x00, 0x00, 0x00
2456 };
2457 
2458 static void translate( POINT *pt, UINT count, const XFORM *xform )
2459 {
2460     while (count--)
2461     {
2462         FLOAT x = (FLOAT)pt->x;
2463         FLOAT y = (FLOAT)pt->y;
2464         pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2465         pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2466         pt++;
2467     }
2468 }
2469 
2470 /* Compare rectangles allowing rounding errors */
2471 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2472 {
2473     return abs(rc1->left - rc2->left) <= 1 &&
2474            abs(rc1->top - rc2->top) <= 1 &&
2475            abs(rc1->right - rc2->right) <= 1 &&
2476            abs(rc1->bottom - rc2->bottom) <= 1;
2477 }
2478 
2479 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2480                                        const ENHMETARECORD *emr, int n_objs, LPARAM param)
2481 {
2482     if (emr->iType == EMR_EXTSELECTCLIPRGN)
2483     {
2484         const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2485         union _rgn
2486         {
2487             RGNDATA data;
2488             char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2489         };
2490         const union _rgn *rgn1;
2491         union _rgn rgn2;
2492         RECT rect, rc_transformed;
2493         const RECT *rc = (const RECT *)param;
2494         HRGN hrgn;
2495         XFORM xform;
2496         INT ret;
2497         BOOL is_win9x;
2498 
2499         trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2500                clip->cbRgnData, clip->iMode);
2501 
2502         ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2503         ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2504            "too small data block: %u bytes\n", clip->cbRgnData);
2505         if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2506             return 0;
2507 
2508         rgn1 = (const union _rgn *)clip->RgnData;
2509 
2510         trace("size %u, type %u, count %u, rgn size %u, bound %s\n",
2511               rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2512               rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2513               wine_dbgstr_rect(&rgn1->data.rdh.rcBound));
2514 
2515         ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2516 
2517         rect = *(const RECT *)rgn1->data.Buffer;
2518         trace("rect %s\n", wine_dbgstr_rect(&rect));
2519         ok(EqualRect(&rect, rc), "rects don't match\n");
2520 
2521         ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2522         ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2523         ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2524         ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2525            broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2526            "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2527 
2528         hrgn = CreateRectRgn(0, 0, 0, 0);
2529 
2530         memset(&xform, 0, sizeof(xform));
2531         SetLastError(0xdeadbeef);
2532         ret = GetWorldTransform(hdc, &xform);
2533         is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2534         if (!is_win9x)
2535             ok(ret, "GetWorldTransform error %u\n", GetLastError());
2536 
2537         trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2538 
2539         ret = GetClipRgn(hdc, hrgn);
2540         ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2541 
2542         PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2543 
2544         ret = GetClipRgn(hdc, hrgn);
2545         ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2546 
2547         /* Win9x returns empty clipping region */
2548         if (is_win9x) return 1;
2549 
2550         ret = GetRegionData(hrgn, 0, NULL);
2551         ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2552 
2553         ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2554         ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2555 
2556         trace("size %u, type %u, count %u, rgn size %u, bound %s\n", rgn2.data.rdh.dwSize,
2557               rgn2.data.rdh.iType, rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2558               wine_dbgstr_rect(&rgn2.data.rdh.rcBound));
2559 
2560         rect = rgn2.data.rdh.rcBound;
2561         rc_transformed = *rc;
2562         translate((POINT *)&rc_transformed, 2, &xform);
2563         trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed));
2564         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2565 
2566         rect = *(const RECT *)rgn2.data.Buffer;
2567         trace("rect %s\n", wine_dbgstr_rect(&rect));
2568         rc_transformed = *rc;
2569         translate((POINT *)&rc_transformed, 2, &xform);
2570         trace("transformed %s\n", wine_dbgstr_rect(&rc_transformed));
2571         ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2572 
2573         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2574         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2575         ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2576         ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2577            broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2578            "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2579 
2580         DeleteObject(hrgn);
2581     }
2582     return 1;
2583 }
2584 
2585 static void test_emf_clipping(void)
2586 {
2587     static const RECT rc = { 0, 0, 100, 100 };
2588     RECT rc_clip = { 100, 100, 1024, 1024 };
2589     HWND hwnd;
2590     HDC hdc;
2591     HENHMETAFILE hemf;
2592     HRGN hrgn;
2593     INT ret;
2594     RECT rc_res, rc_sclip;
2595 
2596     SetLastError(0xdeadbeef);
2597     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2598     ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2599 
2600     /* Need to write something to the emf, otherwise Windows won't play it back */
2601     LineTo(hdc, 1, 1);
2602 
2603     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2604     ret = SelectClipRgn(hdc, hrgn);
2605     ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2606 
2607     BeginPath(hdc);
2608     Rectangle(hdc, rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2609     EndPath(hdc);
2610     ret = SelectClipPath(hdc, RGN_AND);
2611     ok(ret, "SelectClipPath error %d\n", GetLastError());
2612 
2613     SetLastError(0xdeadbeef);
2614     hemf = CloseEnhMetaFile(hdc);
2615     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2616 
2617     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2618         "emf_clipping", FALSE) != 0)
2619     {
2620         dump_emf_bits(hemf, "emf_clipping");
2621         dump_emf_records(hemf, "emf_clipping");
2622     }
2623 
2624     DeleteObject(hrgn);
2625 
2626     /* Win9x doesn't play EMFs on invisible windows */
2627     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2628                            0, 0, 200, 200, 0, 0, 0, NULL);
2629     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2630 
2631     hdc = GetDC(hwnd);
2632 
2633     ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2634     ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2635 
2636     DeleteEnhMetaFile(hemf);
2637     ReleaseDC(hwnd, hdc);
2638     DestroyWindow(hwnd);
2639 
2640     hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2641 
2642     SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2643     hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2644     SelectClipRgn(hdc, hrgn);
2645     SetRect(&rc_res, -1, -1, -1, -1);
2646     ret = GetClipBox(hdc, &rc_res);
2647     ok(ret == SIMPLEREGION, "got %d\n", ret);
2648     ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip),
2649        wine_dbgstr_rect(&rc_res));
2650 
2651     OffsetRect(&rc_sclip, -100, -100);
2652     ret = OffsetClipRgn(hdc, -100, -100);
2653     ok(ret == SIMPLEREGION, "got %d\n", ret);
2654     SetRect(&rc_res, -1, -1, -1, -1);
2655     ret = GetClipBox(hdc, &rc_res);
2656     ok(ret == SIMPLEREGION, "got %d\n", ret);
2657     ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip),
2658        wine_dbgstr_rect(&rc_res));
2659 
2660     ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2661     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2662     if (ret == COMPLEXREGION)
2663     {
2664         /* XP returns COMPLEXREGION although region contains only 1 rect */
2665         ret = GetClipRgn(hdc, hrgn);
2666         ok(ret == 1, "expected 1, got %d\n", ret);
2667         ret = rgn_rect_count(hrgn);
2668         ok(ret == 1, "expected 1, got %d\n", ret);
2669     }
2670     SetRect(&rc_res, -1, -1, -1, -1);
2671     ret = GetClipBox(hdc, &rc_res);
2672     ok(ret == SIMPLEREGION, "got %d\n", ret);
2673     ok(EqualRect(&rc_res, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rc),
2674        wine_dbgstr_rect(&rc_res));
2675 
2676     SetRect(&rc_sclip, 0, 0, 100, 50);
2677     ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2678     ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2679     if (ret == COMPLEXREGION)
2680     {
2681         /* XP returns COMPLEXREGION although region contains only 1 rect */
2682         ret = GetClipRgn(hdc, hrgn);
2683         ok(ret == 1, "expected 1, got %d\n", ret);
2684         ret = rgn_rect_count(hrgn);
2685         ok(ret == 1, "expected 1, got %d\n", ret);
2686     }
2687     SetRect(&rc_res, -1, -1, -1, -1);
2688     ret = GetClipBox(hdc, &rc_res);
2689     ok(ret == SIMPLEREGION, "got %d\n", ret);
2690     ok(EqualRect(&rc_res, &rc_sclip), "expected %s, got %s\n", wine_dbgstr_rect(&rc_sclip),
2691        wine_dbgstr_rect(&rc_res));
2692 
2693     hemf = CloseEnhMetaFile(hdc);
2694     DeleteEnhMetaFile(hemf);
2695     DeleteObject(hrgn);
2696 }
2697 
2698 static const unsigned char MF_CLIP_BITS[] = {
2699     /* METAHEADER */
2700     0x01, 0x00,             /* mtType */
2701     0x09, 0x00,             /* mtHeaderSize */
2702     0x00, 0x03,             /* mtVersion */
2703     0x32, 0x00, 0x00, 0x00, /* mtSize */
2704     0x01, 0x00,             /* mtNoObjects */
2705     0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2706     0x00, 0x00,             /* reserved */
2707 
2708     /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2709     0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2710     0xff, 0x06,             /* META_CREATEREGION */
2711     0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2712     0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2713     0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2714     0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2715     0x02, 0x00,
2716 
2717     /* METARECORD for SelectObject */
2718     0x04, 0x00, 0x00, 0x00,
2719     0x2d, 0x01,             /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2720     0x00, 0x00,
2721 
2722     /* METARECORD */
2723     0x04, 0x00, 0x00, 0x00,
2724     0xf0, 0x01,             /* META_DELETEOBJECT */
2725     0x00, 0x00,
2726 
2727     /* METARECORD for MoveTo(1,0x30) */
2728     0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2729     0x14, 0x02,             /* META_MOVETO */
2730     0x30, 0x00,             /* y */
2731     0x01, 0x00,             /* x */
2732 
2733     /* METARECORD for LineTo(0x20, 0x30) */
2734     0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2735     0x13, 0x02,             /* META_LINETO */
2736     0x30, 0x00,             /* y */
2737     0x20, 0x00,             /* x */
2738 
2739     /* EOF */
2740     0x03, 0x00, 0x00, 0x00,
2741     0x00, 0x00
2742 };
2743 
2744 static int clip_mf_enum_proc_seen_selectclipregion;
2745 static int clip_mf_enum_proc_seen_selectobject;
2746 
2747 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2748                                        METARECORD *mr, int n_objs, LPARAM param)
2749 {
2750     switch (mr->rdFunction) {
2751     case META_SELECTCLIPREGION:
2752         clip_mf_enum_proc_seen_selectclipregion++;
2753         break;
2754     case META_SELECTOBJECT:
2755         clip_mf_enum_proc_seen_selectobject++;
2756         break;
2757     }
2758     return 1;
2759 }
2760 
2761 static void test_mf_clipping(void)
2762 {
2763                           /* left top right bottom */
2764     static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2765     HWND hwnd;
2766     HDC hdc;
2767     HMETAFILE hmf;
2768     HRGN hrgn;
2769     INT ret;
2770 
2771     SetLastError(0xdeadbeef);
2772     hdc = CreateMetaFileA(NULL);
2773     ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2774 
2775     hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2776     ret = SelectClipRgn(hdc, hrgn);
2777     /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2778     ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2779 
2780     /* Draw a line that starts off left of the clip region and ends inside it */
2781     MoveToEx(hdc, 0x1, 0x30, NULL);
2782     LineTo(hdc,  0x20, 0x30);
2783 
2784     SetLastError(0xdeadbeef);
2785     hmf = CloseMetaFile(hdc);
2786     ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2787 
2788     if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2789         "mf_clipping") != 0)
2790     {
2791         dump_mf_bits(hmf, "mf_clipping");
2792     }
2793 
2794     DeleteObject(hrgn);
2795 
2796     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2797                            0, 0, 200, 200, 0, 0, 0, NULL);
2798     ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2799 
2800     hdc = GetDC(hwnd);
2801 
2802     ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2803     ok(ret, "EnumMetaFile error %d\n", GetLastError());
2804 
2805     /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2806     ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2807        "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2808     ok(clip_mf_enum_proc_seen_selectobject == 1,
2809        "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2810 
2811     DeleteMetaFile(hmf);
2812     ReleaseDC(hwnd, hdc);
2813     DestroyWindow(hwnd);
2814 }
2815 
2816 static const unsigned char MF_PATH_BITS[] =
2817 {
2818     0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2c, 0x00,
2819     0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
2820     0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
2821     0x32, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00,
2822     0x13, 0x02, 0x96, 0x00, 0x32, 0x00, 0x05, 0x00,
2823     0x00, 0x00, 0x13, 0x02, 0x96, 0x00, 0x96, 0x00,
2824     0x05, 0x00, 0x00, 0x00, 0x13, 0x02, 0x32, 0x00,
2825     0x96, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
2826     0x32, 0x00, 0x32, 0x00, 0x07, 0x00, 0x00, 0x00,
2827     0x1b, 0x04, 0x14, 0x00, 0x14, 0x00, 0x0a, 0x00,
2828     0x0a, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
2829 };
2830 
2831 static void test_mf_GetPath(void)
2832 {
2833     HDC hdc;
2834     HMETAFILE hmf;
2835     BOOL ret;
2836     int size;
2837 
2838     SetLastError(0xdeadbeef);
2839     hdc = CreateMetaFileA(NULL);
2840     ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2841 
2842     BeginPath(hdc);
2843     ret = MoveToEx(hdc, 50, 50, NULL);
2844     ok( ret, "MoveToEx error %d.\n", GetLastError());
2845     ret = LineTo(hdc, 50, 150);
2846     ok( ret, "LineTo error %d.\n", GetLastError());
2847     ret = LineTo(hdc, 150, 150);
2848     ok( ret, "LineTo error %d.\n", GetLastError());
2849     ret = LineTo(hdc, 150, 50);
2850     ok( ret, "LineTo error %d.\n", GetLastError());
2851     ret = LineTo(hdc, 50, 50);
2852     ok( ret, "LineTo error %d.\n", GetLastError());
2853     Rectangle(hdc, 10, 10, 20, 20);
2854     EndPath(hdc);
2855 
2856     size = GetPath(hdc, NULL, NULL, 0);
2857     ok( size == -1, "GetPath returned %d.\n", size);
2858 
2859     hmf = CloseMetaFile(hdc);
2860     ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2861 
2862     if (compare_mf_bits (hmf, MF_PATH_BITS, sizeof(MF_PATH_BITS), "mf_GetPath") != 0)
2863     {
2864         dump_mf_bits(hmf, "mf_GetPath");
2865         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2866     }
2867 
2868     ret = DeleteMetaFile(hmf);
2869     ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2870 }
2871 
2872 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2873 {
2874     LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2875     POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2876     /* When using MM_TEXT Win9x does not update the mapping mode
2877      * until a record is played which actually outputs something */
2878     PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2879     LPtoDP(hdc, mapping, 2);
2880     trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2881            lpEMFR->iType, lpEMFR->nSize,
2882            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2883 
2884     if (lpEMFR->iType == EMR_LINETO)
2885     {
2886         INT x0, y0, x1, y1;
2887         if (!lpMFP || lpMFP->mm == MM_TEXT)
2888         {
2889             x0 = 0;
2890             y0 = 0;
2891             x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2892             y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2893         }
2894         else
2895         {
2896             ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2897 
2898             x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2899             y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2900             x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2901             y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2902         }
2903         ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2904             "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2905             mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2906             x0, y0, x1, y1);
2907     }
2908     return TRUE;
2909 }
2910 
2911 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2912 {
2913     HDC hdcMf;
2914     HMETAFILE hmf;
2915     HENHMETAFILE hemf;
2916     BOOL ret;
2917     UINT size;
2918     LPBYTE pBits;
2919 
2920     hdcMf = CreateMetaFileA(NULL);
2921     ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2922     ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2923     ok(ret, "LineTo failed with error %d\n", GetLastError());
2924     hmf = CloseMetaFile(hdcMf);
2925     ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2926 
2927     if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2928     {
2929         dump_mf_bits(hmf, "mf_LineTo");
2930         EnumMetaFile(0, hmf, mf_enum_proc, 0);
2931     }
2932 
2933     size = GetMetaFileBitsEx(hmf, 0, NULL);
2934     ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2935     pBits = HeapAlloc(GetProcessHeap(), 0, size);
2936     GetMetaFileBitsEx(hmf, size, pBits);
2937     DeleteMetaFile(hmf);
2938     hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2939     HeapFree(GetProcessHeap(), 0, pBits);
2940     return hemf;
2941 }
2942 
2943 static void test_mf_conversions(void)
2944 {
2945     trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2946     {
2947         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2948         HENHMETAFILE hemf;
2949         METAFILEPICT mfp;
2950         RECT rect = { 0, 0, 100, 100 };
2951         mfp.mm = MM_ANISOTROPIC;
2952         mfp.xExt = 100;
2953         mfp.yExt = 100;
2954         mfp.hMF = NULL;
2955         hemf = create_converted_emf(&mfp);
2956 
2957         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2958                              "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2959         {
2960             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2961             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2962         }
2963 
2964         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2965 
2966         DeleteEnhMetaFile(hemf);
2967         DeleteDC(hdcOffscreen);
2968     }
2969 
2970     trace("Testing MF->EMF conversion (MM_TEXT)\n");
2971     {
2972         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2973         HENHMETAFILE hemf;
2974         METAFILEPICT mfp;
2975         RECT rect = { 0, 0, 100, 100 };
2976         mfp.mm = MM_TEXT;
2977         mfp.xExt = 0;
2978         mfp.yExt = 0;
2979         mfp.hMF = NULL;
2980         hemf = create_converted_emf(&mfp);
2981 
2982         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2983                              "emf_LineTo MM_TEXT", TRUE) != 0)
2984         {
2985             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2986             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2987         }
2988 
2989         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2990 
2991         DeleteEnhMetaFile(hemf);
2992         DeleteDC(hdcOffscreen);
2993     }
2994 
2995     trace("Testing MF->EMF conversion (NULL mfp)\n");
2996     {
2997         HDC hdcOffscreen = CreateCompatibleDC(NULL);
2998         HENHMETAFILE hemf;
2999         RECT rect = { 0, 0, 100, 100 };
3000         hemf = create_converted_emf(NULL);
3001 
3002         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
3003                              "emf_LineTo NULL", TRUE) != 0)
3004         {
3005             dump_emf_bits(hemf, "emf_LineTo NULL");
3006             dump_emf_records(hemf, "emf_LineTo NULL");
3007         }
3008 
3009         EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
3010 
3011         DeleteEnhMetaFile(hemf);
3012         DeleteDC(hdcOffscreen);
3013     }
3014 }
3015 
3016 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3017                                        LONG mm, LONG xExt, LONG yExt,
3018                                        RECTL * rclBounds, RECTL * rclFrame)
3019 {
3020   METAFILEPICT mfp;
3021   METAFILEPICT * mfpPtr = NULL;
3022   HENHMETAFILE emf;
3023   ENHMETAHEADER header;
3024   UINT res;
3025 
3026   if (!mfpIsNull)
3027   {
3028     mfp.mm = mm;
3029     mfp.xExt = xExt;
3030     mfp.yExt = yExt;
3031     mfpPtr = &mfp;
3032   }
3033 
3034   emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
3035   ok(emf != NULL, "SetWinMetaFileBits failed\n");
3036   if (!emf) return FALSE;
3037   res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
3038   ok(res != 0, "GetEnhMetaHeader failed\n");
3039   DeleteEnhMetaFile(emf);
3040   if (!res) return FALSE;
3041 
3042   *rclBounds = header.rclBounds;
3043   *rclFrame = header.rclFrame;
3044   return TRUE;
3045 }
3046 
3047 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
3048                                          LONG mm, LONG xExt, LONG yExt,
3049                                          RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
3050 {
3051   RECTL rclBounds, rclFrame;
3052 
3053   if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
3054   {
3055     const char * msg;
3056     char buf[64];
3057 
3058     if (mfpIsNull)
3059     {
3060        msg = "mfp == NULL";
3061     }
3062     else
3063     {
3064       const char * mm_str;
3065       switch (mm)
3066       {
3067          case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
3068          case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
3069          default:             mm_str = "Unexpected";
3070       }
3071       sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
3072       msg = buf;
3073     }
3074 
3075     ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
3076     ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
3077     ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
3078     ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
3079     ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
3080     ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
3081     ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
3082     ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
3083   }
3084 }
3085 
3086 static void test_SetWinMetaFileBits(void)
3087 {
3088   HMETAFILE wmf;
3089   HDC wmfDC;
3090   BYTE * buffer;
3091   UINT buffer_size;
3092   RECT rect;
3093   UINT res;
3094   RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
3095   RECTL rclBoundsIsotropic, rclFrameIsotropic;
3096   RECTL rclBounds, rclFrame;
3097   HDC dc;
3098   LONG diffx, diffy;
3099 
3100   wmfDC = CreateMetaFileA(NULL);
3101   ok(wmfDC != NULL, "CreateMetaFile failed\n");
3102   if (!wmfDC) return;
3103 
3104   SetWindowExtEx(wmfDC, 100, 100, NULL);
3105   SetRect(&rect, 0, 0, 50, 50);
3106   FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
3107   wmf = CloseMetaFile(wmfDC);
3108   ok(wmf != NULL, "Metafile creation failed\n");
3109   if (!wmf) return;
3110 
3111   buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
3112   ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
3113   if (buffer_size == 0)
3114   {
3115     DeleteMetaFile(wmf);
3116     return;
3117   }
3118 
3119   buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
3120   ok(buffer != NULL, "HeapAlloc failed\n");
3121   if (!buffer)
3122   {
3123     DeleteMetaFile(wmf);
3124     return;
3125   }
3126 
3127   res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
3128   ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3129   DeleteMetaFile(wmf);
3130   if (res != buffer_size)
3131   {
3132      HeapFree(GetProcessHeap(), 0, buffer);
3133      return;
3134   }
3135 
3136   /* Get the reference bounds and frame */
3137   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3138   getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);
3139 
3140   ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
3141      rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
3142      "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
3143 
3144   ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
3145   ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
3146   diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
3147   if (diffx < 0) diffx = -diffx;
3148   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
3149 
3150   dc = CreateCompatibleDC(NULL);
3151 
3152   /* Allow 1 mm difference (rounding errors) */
3153   diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
3154   diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
3155   if (diffx < 0) diffx = -diffx;
3156   if (diffy < 0) diffy = -diffy;
3157   todo_wine
3158   {
3159   ok(diffx <= 1 && diffy <= 1,
3160      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3161      GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
3162   }
3163 
3164   /* Allow 1 mm difference (rounding errors) */
3165   diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
3166   diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
3167   if (diffx < 0) diffx = -diffx;
3168   if (diffy < 0) diffy = -diffy;
3169   todo_wine
3170   {
3171   ok(diffx <= 1 && diffy <= 1,
3172      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
3173      GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
3174   }
3175   DeleteDC(dc);
3176 
3177   /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
3178   checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3179 
3180   /* If xExt or yExt is zero or negative, the whole device surface is used */
3181   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3182   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3183   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3184   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3185   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3186   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
3187   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3188   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3189   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3190   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3191   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3192   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
3193 
3194   /* MSDN says that negative xExt and yExt values specify a ratio.
3195      Check that this is wrong and the whole device surface is used */
3196   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
3197   checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3198 
3199   /* Ordinary conversions */
3200 
3201   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3202   {
3203     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3204        "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3205     ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3206        "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3207   }
3208 
3209   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3210   {
3211     ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3212        "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3213     ok(rclBounds.left == 0 && rclBounds.top == 0,
3214        "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3215 
3216     /* Wine has a rounding error */
3217     diffx = rclBounds.right - rclBounds.bottom;
3218     if (diffx < 0) diffx = -diffx;
3219     ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3220   }
3221 
3222   if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3223   {
3224     ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3225        "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3226   }
3227 
3228   HeapFree(GetProcessHeap(), 0, buffer);
3229 }
3230 
3231 static BOOL near_match(int x, int y)
3232 {
3233     int epsilon = min(abs(x), abs(y));
3234 
3235     epsilon = max(epsilon/100, 2);
3236 
3237     if(x < y - epsilon || x > y + epsilon) return FALSE;
3238     return TRUE;
3239 }
3240 
3241 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3242 {
3243     HENHMETAFILE emf, emf2;
3244     HDC display_dc, emf_dc;
3245     ENHMETAHEADER *enh_header, *enh2_header;
3246     UINT size, emf_size, i, emf2_size;
3247     WORD check = 0;
3248     DWORD rec_num = 0;
3249     METAHEADER *mh = NULL;
3250     METARECORD *rec;
3251     INT horz_res, vert_res, horz_size, vert_size;
3252     INT curve_caps, line_caps, poly_caps;
3253     METAFILEPICT mfp;
3254 
3255     display_dc = GetDC(NULL);
3256     ok(display_dc != NULL, "display_dc is NULL\n");
3257 
3258     horz_res = GetDeviceCaps(display_dc, HORZRES);
3259     vert_res = GetDeviceCaps(display_dc, VERTRES);
3260     horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3261     vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3262 
3263     emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3264     ok(emf_dc != NULL, "emf_dc is NULL\n");
3265 
3266     curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3267     ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3268 
3269     line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3270     ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3271 
3272     poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3273     ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3274 
3275     for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3276         Rectangle(emf_dc, 0, 0, 1000, 20);
3277     emf = CloseEnhMetaFile(emf_dc);
3278     ok(emf != NULL, "emf is NULL\n");
3279 
3280     emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3281     enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3282     emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3283     DeleteEnhMetaFile(emf);
3284     /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3285        have different resolutions */
3286     enh_header->szlDevice.cx *= scale;
3287     emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3288     ok(emf != NULL, "emf is NULL\n");
3289     ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3290 
3291     size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3292     ok(size ||
3293        broken(size == 0), /* some versions of winxp fail for some reason */
3294        "GetWinMetaFileBits returns 0\n");
3295     if(!size) goto end;
3296     mh = HeapAlloc(GetProcessHeap(), 0, size);
3297     GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3298 
3299     for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3300     ok(check == 0, "check %04x\n", check);
3301 
3302     rec = (METARECORD*)(mh + 1);
3303 
3304     while(rec->rdSize && rec->rdFunction)
3305     {
3306         const DWORD chunk_size = 0x2000;
3307         DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3308 
3309         if(rec_num < mfcomment_chunks)
3310         {
3311             DWORD this_chunk_size = chunk_size;
3312 
3313             if(rec_num == mfcomment_chunks - 1)
3314                 this_chunk_size = emf_size - rec_num * chunk_size;
3315 
3316             ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3317             ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3318             if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3319             ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3320             ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3321             ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3322             ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /*  "   */
3323             ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3324             ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3325             ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3326             ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3327             /* parm[8] is the checksum, tested above */
3328             if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3329             ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3330             ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3331             ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3332             ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3333             ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3334             ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3335             ok(*(DWORD*)(rec->rdParm + 15) == emf_size - this_chunk_size - rec_num * chunk_size, "got %08x\n", *(DWORD*)(rec->rdParm + 15));  /* DWORD size remaining after current chunk */
3336             ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3337             ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3338         }
3339 
3340         else if(rec_num == mfcomment_chunks)
3341         {
3342             ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3343             ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3344         }
3345         else if(rec_num == mfcomment_chunks + 1)
3346         {
3347             POINT pt;
3348             ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3349             switch(mode)
3350             {
3351             case MM_TEXT:
3352             case MM_ISOTROPIC:
3353             case MM_ANISOTROPIC:
3354                 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3355                 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3356                 break;
3357             case MM_LOMETRIC:
3358                 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3359                 pt.x = MulDiv( rc->left, 1, 10);
3360                 break;
3361             case MM_HIMETRIC:
3362                 pt.y = -rc->top + 1;
3363                 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3364                 break;
3365             case MM_LOENGLISH:
3366                 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3367                 pt.x = MulDiv( rc->left, 10, 254);
3368                 break;
3369             case MM_HIENGLISH:
3370                 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3371                 pt.x = MulDiv( rc->left, 100, 254);
3372                 break;
3373             case MM_TWIPS:
3374                 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3375                 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3376                 break;
3377             default:
3378                 pt.x = pt.y = 0;
3379             }
3380             ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3381             ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3382         }
3383         if(rec_num == mfcomment_chunks + 2)
3384         {
3385             ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3386             ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3387                "got %d\n", (short)rec->rdParm[0]);
3388             ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3389                "got %d\n", (short)rec->rdParm[1]);
3390         }
3391 
3392         rec_num++;
3393         rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3394     }
3395 
3396     /* Show that we get the original back when we do the reverse conversion.
3397        mfp is ignored in this case. */
3398     mfp.mm = MM_ISOTROPIC;
3399     mfp.xExt = 0xcafe;
3400     mfp.yExt = 0xbeef;
3401     emf2 = SetWinMetaFileBits( size, (BYTE*)mh, NULL, &mfp );
3402     ok( !!emf2, "got NULL\n" );
3403     emf2_size = GetEnhMetaFileBits( emf2, 0, NULL );
3404     enh2_header = HeapAlloc( GetProcessHeap(), 0, emf2_size );
3405     emf2_size = GetEnhMetaFileBits( emf2, emf2_size, (BYTE*)enh2_header );
3406     ok( emf_size == emf2_size, "%d %d\n", emf_size, emf2_size );
3407     ok( !memcmp( enh_header, enh2_header, emf_size ), "mismatch\n" );
3408     HeapFree( GetProcessHeap(), 0, enh2_header );
3409     DeleteEnhMetaFile( emf2 );
3410 
3411 end:
3412     HeapFree(GetProcessHeap(), 0, mh);
3413     HeapFree(GetProcessHeap(), 0, enh_header);
3414     DeleteEnhMetaFile(emf);
3415 
3416     ReleaseDC(NULL, display_dc);
3417 }
3418 
3419 static void test_GetWinMetaFileBits(void)
3420 {
3421     UINT mode;
3422     RECT frames[] =
3423     {
3424         { 1000,  2000, 3000, 6000},
3425         {-1000,  2000, 3000, 6000},
3426         { 1000, -2000, 3000, 6000},
3427         { 1005,  2005, 3000, 6000},
3428         {-1005, -2005, 3000, 6000},
3429         {-1005, -2010, 3000, 6000},
3430         {-1005,  2010, 3000, 6000},
3431         {    0,     0,    1,    1},
3432         {   -1,    -1,    1,    1},
3433         {    0,     0,    0,    0}
3434     };
3435 
3436     for(mode = MM_MIN; mode <= MM_MAX; mode++)
3437     {
3438         RECT *rc;
3439         for(rc = frames; rc->right - rc->left > 0; rc++)
3440         {
3441             getwinmetafilebits(mode, 1, rc);
3442             getwinmetafilebits(mode, 2, rc);
3443         }
3444     }
3445 }
3446 
3447 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3448 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3449 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3450 
3451 static void test_gdiis(void)
3452 {
3453     RECT rect = {0,0,100,100};
3454     HDC hdc, hemfDC, hmfDC;
3455     HENHMETAFILE hemf;
3456     HMODULE hgdi32;
3457 
3458     /* resolve all the functions */
3459     hgdi32 = GetModuleHandleA("gdi32.dll");
3460     pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3461     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3462     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3463 
3464     if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3465     {
3466         win_skip("Needed GdiIs* functions are not available\n");
3467         return;
3468     }
3469 
3470     /* try with nothing */
3471     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3472     ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3473     ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3474 
3475     /* try with a metafile */
3476     hmfDC = CreateMetaFileA(NULL);
3477     ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3478     ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3479     ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3480     DeleteMetaFile(CloseMetaFile(hmfDC));
3481 
3482     /* try with an enhanced metafile */
3483     hdc = GetDC(NULL);
3484     hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3485     ok(hemfDC != NULL, "failed to create emf\n");
3486 
3487     ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3488     ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3489     ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3490 
3491     hemf = CloseEnhMetaFile(hemfDC);
3492     ok(hemf != NULL, "failed to close EMF\n");
3493     DeleteEnhMetaFile(hemf);
3494     ReleaseDC(NULL,hdc);
3495 }
3496 
3497 static void test_SetEnhMetaFileBits(void)
3498 {
3499     BYTE data[256];
3500     HENHMETAFILE hemf;
3501     ENHMETAHEADER *emh;
3502 
3503     memset(data, 0xAA, sizeof(data));
3504     SetLastError(0xdeadbeef);
3505     hemf = SetEnhMetaFileBits(sizeof(data), data);
3506     ok(!hemf, "SetEnhMetaFileBits should fail\n");
3507     ok(GetLastError() == ERROR_INVALID_DATA ||
3508        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3509        "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3510 
3511     emh = (ENHMETAHEADER *)data;
3512     memset(emh, 0, sizeof(*emh));
3513 
3514     emh->iType = EMR_HEADER;
3515     emh->nSize = sizeof(*emh);
3516     emh->dSignature = ENHMETA_SIGNATURE;
3517     /* emh->nVersion  = 0x10000; XP doesn't care about version */
3518     emh->nBytes = sizeof(*emh);
3519     /* emh->nRecords = 1; XP doesn't care about records */
3520     emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3521 
3522     SetLastError(0xdeadbeef);
3523     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3524     ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3525     DeleteEnhMetaFile(hemf);
3526 
3527     /* XP refuses to load unaligned EMF */
3528     emh->nBytes++;
3529     SetLastError(0xdeadbeef);
3530     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3531     ok(!hemf ||
3532        broken(hemf != NULL), /* Win9x, WinMe */
3533        "SetEnhMetaFileBits should fail\n");
3534     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3535     DeleteEnhMetaFile(hemf);
3536 
3537     emh->dSignature = 0;
3538     emh->nBytes--;
3539     SetLastError(0xdeadbeef);
3540     hemf = SetEnhMetaFileBits(emh->nBytes, data);
3541     ok(!hemf ||
3542        broken(hemf != NULL), /* Win9x, WinMe */
3543        "SetEnhMetaFileBits should fail\n");
3544     ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3545     DeleteEnhMetaFile(hemf);
3546 }
3547 
3548 static void test_emf_polybezier(void)
3549 {
3550     HDC hdcMetafile;
3551     HENHMETAFILE hemf;
3552     POINT pts[4];
3553     BOOL ret;
3554 
3555     SetLastError(0xdeadbeef);
3556     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3557     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3558 
3559     pts[0].x = pts[0].y = 10;
3560     pts[1].x = pts[1].y = 20;
3561     pts[2].x = pts[2].y = 15;
3562     pts[3].x = pts[3].y = 25;
3563     ret = PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO16 */
3564     ok( ret, "PolyBezierTo failed\n" );
3565     ret = PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER16   */
3566     ok( ret, "PolyBezier failed\n" );
3567 
3568     pts[0].x = pts[0].y = 32769;
3569     ret = PolyBezier(hdcMetafile, pts, 4);    /* EMR_POLYBEZIER   */
3570     ok( ret, "PolyBezier failed\n" );
3571     ret = PolyBezierTo(hdcMetafile, pts, 3);  /* EMR_POLYBEZIERTO */
3572     ok( ret, "PolyBezierTo failed\n" );
3573 
3574     hemf = CloseEnhMetaFile(hdcMetafile);
3575     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3576 
3577     if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3578         "emf_Bezier", FALSE) != 0)
3579     {
3580         dump_emf_bits(hemf, "emf_Bezier");
3581         dump_emf_records(hemf, "emf_Bezier");
3582     }
3583 
3584     DeleteEnhMetaFile(hemf);
3585 }
3586 
3587 static const unsigned char EMF_PATH_BITS[] =
3588 {
3589     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3590     0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3591     0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3592     0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
3593     0x70, 0x17, 0x00, 0x00, 0x70, 0x17, 0x00, 0x00,
3594     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3595     0xf8, 0x02, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3596     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3597     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3598     0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3599     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3600     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3601     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3602     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3603     0x08, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
3604     0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3605     0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3606     0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3607     0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3608     0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3609     0x96, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3610     0x10, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3611     0x32, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
3612     0x10, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00,
3613     0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
3614     0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3615     0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3616     0x13, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
3617     0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3618     0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3619     0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3620     0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3621     0x15, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
3622     0x28, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3623     0x17, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3624     0x1a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
3625     0x1b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
3626     0x17, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
3627     0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3628     0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3629     0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3630     0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3631     0x15, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
3632     0x28, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3633     0x15, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
3634     0x1c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
3635     0x1d, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
3636     0x15, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
3637     0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3638     0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3639     0x13, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3640     0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3641     0x0a, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
3642     0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
3643     0x05, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
3644     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3645     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3646     0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
3647     0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3648     0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3649     0x59, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
3650     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3651     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3652     0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
3653     0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00,
3654     0x14, 0x00, 0x14, 0x00, 0x5a, 0x00, 0x00, 0x00,
3655     0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3656     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3657     0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
3658     0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
3659     0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
3660     0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00,
3661     0x14, 0x00, 0x14, 0x00, 0x5c, 0x00, 0x00, 0x00,
3662     0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3663     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3664     0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00,
3665     0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0a, 0x00,
3666     0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00,
3667     0x1e, 0x00, 0x1e, 0x00, 0x28, 0x00, 0x14, 0x00,
3668     0x14, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x14, 0x00,
3669     0x14, 0x00, 0x0a, 0x00, 0x06, 0x02, 0x04, 0x04,
3670     0x04, 0x02, 0x03, 0x06, 0x02, 0x00, 0x00, 0x00,
3671     0x29, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
3672     0x25, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
3673     0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x42,
3674     0x00, 0x00, 0x34, 0x43, 0x3c, 0x00, 0x00, 0x00,
3675     0x08, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
3676     0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
3677     0x0a, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
3678     0x96, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
3679     0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3680     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3681     0xff, 0xff, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00,
3682     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3683     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3684 };
3685 
3686 static const unsigned char EMF_EMPTY_PATH_BITS[] =
3687 {
3688     0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
3689     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3690     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3691     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3692     0xd8, 0xff, 0xff, 0xff, 0xd8, 0xff, 0xff, 0xff,
3693     0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
3694     0xc8, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
3695     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3696     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3697     0x20, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
3698     0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
3699     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3700     0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
3701     0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
3702     0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
3703     0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
3704     0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3705     0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
3706     0x08, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00,
3707     0x08, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
3708     0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
3709     0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
3710     0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
3711     0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3712     0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
3713 };
3714 
3715 static void test_emf_paths(void)
3716 {
3717     POINT pts[9] = {{10, 10}, {20, 10}, {10, 20}, {20, 20}, {30, 30}, {40, 20}, {20, 30}, {20, 20}, {20, 10}};
3718     DWORD counts[2] = {2, 2};
3719     BYTE types[9] = { PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO,
3720                       PT_LINETO | PT_CLOSEFIGURE, PT_MOVETO, PT_LINETO };
3721     HDC hdcMetafile;
3722     HENHMETAFILE hemf;
3723     BOOL ret;
3724     int size;
3725 
3726     SetLastError(0xdeadbeef);
3727     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3728     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3729 
3730     BeginPath(hdcMetafile);
3731     ret = MoveToEx(hdcMetafile, 50, 50, NULL);
3732     ok( ret, "MoveToEx error %d.\n", GetLastError());
3733     ret = LineTo(hdcMetafile, 50, 150);
3734     ok( ret, "LineTo error %d.\n", GetLastError());
3735     ret = LineTo(hdcMetafile, 150, 150);
3736     ok( ret, "LineTo error %d.\n", GetLastError());
3737     ret = LineTo(hdcMetafile, 150, 50);
3738     ok( ret, "LineTo error %d.\n", GetLastError());
3739     ret = LineTo(hdcMetafile, 50, 50);
3740     ok( ret, "LineTo error %d.\n", GetLastError());
3741     Rectangle(hdcMetafile, 10, 10, 20, 20);
3742     Arc(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3743     ArcTo(hdcMetafile, 23, 23, 37, 27, 37, 27, 23, 23);
3744     Chord(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3745     Pie(hdcMetafile, 21, 21, 39, 29, 39, 29, 21, 21);
3746     Ellipse(hdcMetafile, 10, 10, 20, 20);
3747     RoundRect(hdcMetafile, 10, 10, 20, 20, 3, 5);
3748     Polyline(hdcMetafile, pts, 4);
3749     PolylineTo(hdcMetafile, pts, 4);
3750     PolyPolyline(hdcMetafile, pts, counts, 2);
3751     PolyDraw(hdcMetafile, pts, types, 9);
3752     AngleArc(hdcMetafile, 37, 36, 23, 90, 180);
3753     EndPath(hdcMetafile);
3754 
3755     size = GetPath(hdcMetafile, NULL, NULL, 0);
3756     ok( size == 112, "GetPath returned %d.\n", size);
3757 
3758     ret = StrokeAndFillPath( hdcMetafile );
3759     ok( ret, "StrokeAndFillPath failed err %d\n", GetLastError() );
3760     ret = StrokeAndFillPath( hdcMetafile );
3761     ok( !ret, "StrokeAndFillPath succeeded\n" );
3762 
3763     hemf = CloseEnhMetaFile(hdcMetafile);
3764     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3765 
3766     if (compare_emf_bits(hemf, EMF_PATH_BITS, sizeof(EMF_PATH_BITS), "test_emf_paths", FALSE) != 0)
3767     {
3768         dump_emf_bits(hemf, "test_emf_paths");
3769         dump_emf_records(hemf, "test_emf_paths");
3770     }
3771 
3772     DeleteEnhMetaFile(hemf);
3773 
3774     SetLastError(0xdeadbeef);
3775     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3776     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3777 
3778     ret = BeginPath(hdcMetafile);
3779     ok( ret, "BeginPath failed error %d\n", GetLastError() );
3780     ret = CloseFigure(hdcMetafile);
3781     ok( ret, "CloseFigure failed error %d\n", GetLastError() );
3782     ret = BeginPath(hdcMetafile);
3783     ok( ret, "BeginPath failed error %d\n", GetLastError() );
3784     ret = EndPath(hdcMetafile);
3785     ok( ret, "EndPath failed error %d\n", GetLastError() );
3786     ret = EndPath(hdcMetafile);
3787     ok( !ret, "EndPath succeeded\n" );
3788     ret = CloseFigure(hdcMetafile);
3789     ok( !ret, "CloseFigure succeeded\n" );
3790     ret = BeginPath(hdcMetafile);
3791     ok( ret, "BeginPath failed error %d\n", GetLastError() );
3792     ret = AbortPath(hdcMetafile);
3793     ok( ret, "AbortPath failed error %d\n", GetLastError() );
3794     ret = AbortPath(hdcMetafile);
3795     ok( ret, "AbortPath failed error %d\n", GetLastError() );
3796 
3797     hemf = CloseEnhMetaFile(hdcMetafile);
3798     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3799 
3800     if (compare_emf_bits(hemf, EMF_EMPTY_PATH_BITS, sizeof(EMF_EMPTY_PATH_BITS), "empty path", FALSE) != 0)
3801     {
3802         dump_emf_bits(hemf, "empty path");
3803         dump_emf_records(hemf, "empty path");
3804     }
3805 
3806     DeleteEnhMetaFile(hemf);
3807 }
3808 
3809 static void test_emf_PolyPolyline(void)
3810 {
3811     HDC hdcMetafile;
3812     HENHMETAFILE hemf;
3813     POINT pts[4] = {{10, 20}, {100, 200}, {0x9000,300}, {400, 500}};
3814     DWORD counts[2];
3815     BOOL ret;
3816 
3817     SetLastError(0xdeadbeef);
3818     hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3819     ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3820 
3821     ret = PolyPolyline(hdcMetafile, NULL, NULL, 0);
3822     ok( !ret, "PolyPolyline\n" );
3823 
3824     SetLastError( 0xdeadbeef );
3825     counts[0] = 0;
3826     counts[1] = 1;
3827     ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3828     ok( !ret, "PolyPolyline\n" );
3829     ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3830 
3831     SetLastError( 0xdeadbeef );
3832     counts[0] = 1;
3833     counts[1] = 1;
3834     ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3835     ok( !ret, "PolyPolyline\n" );
3836     ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3837 
3838     SetLastError( 0xdeadbeef );
3839     counts[0] = 2;
3840     counts[1] = 1;
3841     ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3842     ok( !ret, "PolyPolyline\n" );
3843     ok( GetLastError() == ERROR_INVALID_PARAMETER, "gle %d\n", GetLastError() );
3844 
3845     counts[0] = 2;
3846     counts[1] = 2;
3847     ret = PolyPolyline(hdcMetafile, pts, counts, 2);
3848     ok( ret, "PolyPolyline\n" );
3849 
3850     hemf = CloseEnhMetaFile(hdcMetafile);
3851     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3852 
3853     if(compare_emf_bits(hemf, EMF_POLYPOLYLINE_BITS, sizeof(EMF_POLYPOLYLINE_BITS),
3854         "emf_PolyPolyline", FALSE) != 0)
3855     {
3856         dump_emf_bits(hemf, "emf_PolyPolyline");
3857         dump_emf_records(hemf, "emf_PolyPolyline");
3858     }
3859 
3860     DeleteEnhMetaFile(hemf);
3861 }
3862 
3863 static void test_emf_GradientFill(void)
3864 {
3865     HDC mf;
3866     HENHMETAFILE hemf;
3867     TRIVERTEX v[] =
3868     {
3869         {   1,  10, 0xff00, 0x8000, 0x0000, 0x8001 },
3870         { 200, 210, 0x0000, 0x0000, 0xff00, 0xff00 },
3871         { 180, 190, 0x1234, 0x5678, 0x9abc, 0xdef0 },
3872         { 300, 310, 0xff00, 0xff00, 0xff00, 0x0000 },
3873         { 400, 410, 0xff00, 0xff00, 0xff00, 0x0000 }
3874     };
3875     GRADIENT_TRIANGLE tri[] = { { 0, 1, 2 }, { 3, 1, 0 } };
3876     BOOL ret;
3877 
3878     mf = CreateEnhMetaFileA( GetDC( 0 ), NULL, NULL, NULL );
3879     ok( mf != 0, "CreateEnhMetaFileA error %d\n", GetLastError() );
3880 
3881     /* Don't test the GRADIENT_FILL_RECT_ modes since a Windows bug
3882      * means it allocates three mesh indices rather than two per
3883      * rectangle.  This results in uninitialised values being written
3884      * to the EMF which is rather difficult to test against.
3885      *
3886      * Note also that the final vertex here is not required, yet it is
3887      * written to the EMF, but is not considered in the bounds
3888      * calculation.
3889      */
3890     ret = GdiGradientFill( mf, v, sizeof(v) / sizeof(v[0]), tri, sizeof(tri) / sizeof(tri[0]),
3891                            GRADIENT_FILL_TRIANGLE );
3892     ok( ret, "GradientFill\n" );
3893 
3894     hemf = CloseEnhMetaFile( mf );
3895     ok( hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError() );
3896 
3897     if (compare_emf_bits( hemf, EMF_GRADIENTFILL_BITS, sizeof(EMF_GRADIENTFILL_BITS),
3898                           "emf_GradientFill", FALSE ) != 0)
3899     {
3900         dump_emf_bits( hemf, "emf_GradientFill" );
3901         dump_emf_records( hemf, "emf_GradientFill" );
3902     }
3903 
3904     DeleteEnhMetaFile( hemf );
3905 }
3906 
3907 START_TEST(metafile)
3908 {
3909     init_function_pointers();
3910 
3911     /* For enhanced metafiles (enhmfdrv) */
3912     test_ExtTextOut();
3913     test_ExtTextOutScale();
3914     test_SaveDC();
3915     test_emf_BitBlt();
3916     test_emf_DCBrush();
3917     test_emf_ExtTextOut_on_path();
3918     test_emf_clipping();
3919     test_emf_polybezier();
3920     test_emf_paths();
3921     test_emf_PolyPolyline();
3922     test_emf_GradientFill();
3923 
3924     /* For win-format metafiles (mfdrv) */
3925     test_mf_SaveDC();
3926     test_mf_Blank();
3927     test_mf_Graphics();
3928     test_mf_PatternBrush();
3929     test_mf_DCBrush();
3930     test_CopyMetaFile();
3931     test_SetMetaFileBits();
3932     test_mf_ExtTextOut_on_path();
3933     test_mf_clipping();
3934     test_mf_GetPath();
3935 
3936     /* For metafile conversions */
3937     test_mf_conversions();
3938     test_SetWinMetaFileBits();
3939     test_GetWinMetaFileBits();
3940 
3941     test_gdiis();
3942     test_SetEnhMetaFileBits();
3943 }
3944