ReactOS  0.4.14-dev-606-g14ebc0b
metafile.c
Go to the documentation of this file.
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 
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);
65 }
66 
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;
76  size = data->rdh.nCount;
78  return size;
79 }
80 
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));
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++;
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++;
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 
209  orig_lf.lfHeight = 7;
211  lstrcpyA(orig_lf.lfFaceName, "Arial");
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);
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 
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 
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 
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());
305 }
306 
308 {
311  double ex_scale;
312  double ey_scale;
314 };
315 
317  const ENHMETARECORD *emr, int n_objs, LPARAM param)
318 {
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 };
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");
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 
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);
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);
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  }
577  {
578  const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
579  trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
580  break;
581  }
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);
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);
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));
814  orig_lf.lfHeight = 7;
816  lstrcpyA(orig_lf.lfFaceName, "Arial");
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 
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());
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));
970  orig_lf.lfHeight = 7;
972  lstrcpyA(orig_lf.lfFaceName, "Arial");
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  */
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 
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);
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 
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 
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);
2180  trace("hmf %p\n", hmf);
2181  ok(!hmf, "SetMetaFileBitsEx should fail\n");
2183  broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2184  "wrong error %d\n", GetLastError());
2185 
2186  /* Now with odd size */
2187  SetLastError(0xdeadbeef);
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));
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");
2206  broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2207  "wrong error %d\n", GetLastError());
2208 
2209  /* Now with corrupted mtSize field */
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 */
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 
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 
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 
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 
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  */
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;
2489  lf.lfWeight = FW_DONTCARE;
2490  lf.lfHeight = 7;
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);
2530 
2531  hMetafile = CloseEnhMetaFile(hdcMetafile);
2532  ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2533 
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());
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 
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);
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);
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);
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);
2767 
2769 
2771  hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
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 
2874 
2876  METARECORD *mr, int n_objs, LPARAM param)
2877 {
2878  switch (mr->rdFunction) {
2879  case META_SELECTCLIPREGION:
2881  break;
2882  case META_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);
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 */
2935  "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2937  "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2938 
2939  DeleteMetaFile(hmf);
2940  ReleaseDC(hwnd, hdc);
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);
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 
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  {
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 
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);
3097  }
3098 
3099  trace("Testing MF->EMF conversion (MM_TEXT)\n");
3100  {
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 
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);
3122  }
3123 
3124  trace("Testing MF->EMF conversion (NULL mfp)\n");
3125  {
3127  HENHMETAFILE hemf;
3128  RECT rect = { 0, 0, 100, 100 };
3129  hemf = create_converted_emf(NULL);
3130 
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 
3139 
3140  DeleteEnhMetaFile(hemf);
3142  }
3143 }
3144 
3146  LONG mm, LONG xExt, LONG yExt,
3147  RECTL * rclBounds, RECTL * rclFrame)
3148 {
3149  METAFILEPICT mfp;
3150  METAFILEPICT * mfpPtr = NULL;
3151  HENHMETAFILE emf;
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 
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);
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 
3249  ok(buffer != NULL, "HeapAlloc failed\n");
3250  if (!buffer)
3251  {
3252  DeleteMetaFile(wmf);
3253  return;
3254  }
3255 
3257  ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
3258  DeleteMetaFile(wmf);
3259  if (res != buffer_size)
3260  {
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 
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 
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 
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 
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");
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);
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 
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};
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 
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 ),