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