2 * Unit tests for metafile functions
4 * Copyright (c) 2002 Dmitry Timoshkov
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.
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.
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
25 #include "wine/test.h"
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
40 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
41 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
43 #define GDI_GET_PROC(func) \
44 p ## func = (void *)GetProcAddress(hGDI, #func); \
46 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
48 static void init_function_pointers(void)
55 hGDI = GetModuleHandleA("gdi32.dll");
57 GDI_GET_PROC(GetRelAbs);
58 GDI_GET_PROC(SetRelAbs);
59 GDI_GET_PROC(SetDCBrushColor);
60 GDI_GET_PROC(SetDCPenColor);
63 static DWORD rgn_rect_count(HRGN hrgn)
69 if (!(size = GetRegionData(hrgn, 0, NULL))) return 0;
70 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0;
71 GetRegionData(hrgn, size, data);
72 size = data->rdh.nCount;
73 HeapFree(GetProcessHeap(), 0, data);
77 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
78 const ENHMETARECORD *emr, int n_objs, LPARAM param)
83 INT *orig_dx = (INT *)param;
87 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
88 hdc, emr->iType, emr->nSize, (void *)param);
92 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
97 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
98 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
99 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
100 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
101 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
102 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
103 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
105 /* GetBkMode, GetRelAbs do not get reset to the default value */
106 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
107 if(pSetRelAbs && pGetRelAbs)
108 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
113 case EMR_EXTTEXTOUTA:
115 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
116 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
118 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
119 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
121 /* compare up to lfOutPrecision, other values are not interesting,
122 * and in fact sometimes arbitrary adapted by Win9x.
124 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
125 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
127 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
129 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
130 n_record, i, dx[i], orig_dx[i]);
133 emr_processed = TRUE;
137 case EMR_EXTTEXTOUTW:
139 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
140 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
142 SetLastError(0xdeadbeef);
143 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
144 ok( ret == sizeof(device_lf) ||
145 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
146 "GetObjectA error %d\n", GetLastError());
148 /* compare up to lfOutPrecision, other values are not interesting,
149 * and in fact sometimes arbitrary adapted by Win9x.
151 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
152 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
154 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
156 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
157 n_record, i, dx[i], orig_dx[i]);
160 emr_processed = TRUE;
171 static void test_ExtTextOut(void)
174 HDC hdcDisplay, hdcMetafile;
175 HENHMETAFILE hMetafile;
177 static const char text[] = "Simple text to test ExtTextOut on metafiles";
179 static const RECT rc = { 0, 0, 100, 100 };
182 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
184 /* Win9x doesn't play EMFs on invisible windows */
185 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
186 0, 0, 200, 200, 0, 0, 0, NULL);
187 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
189 hdcDisplay = GetDC(hwnd);
190 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
192 trace("hdcDisplay %p\n", hdcDisplay);
194 SetMapMode(hdcDisplay, MM_TEXT);
196 memset(&orig_lf, 0, sizeof(orig_lf));
198 orig_lf.lfCharSet = ANSI_CHARSET;
199 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
200 orig_lf.lfWeight = FW_DONTCARE;
201 orig_lf.lfHeight = 7;
202 orig_lf.lfQuality = DEFAULT_QUALITY;
203 lstrcpyA(orig_lf.lfFaceName, "Arial");
204 hFont = CreateFontIndirectA(&orig_lf);
205 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
207 hFont = SelectObject(hdcDisplay, hFont);
209 len = lstrlenA(text);
210 for (i = 0; i < len; i++)
212 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
213 ok( ret, "GetCharWidthA error %d\n", GetLastError());
215 hFont = SelectObject(hdcDisplay, hFont);
217 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
218 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
220 trace("hdcMetafile %p\n", hdcMetafile);
222 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
223 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
225 hFont = SelectObject(hdcMetafile, hFont);
227 /* 1. pass NULL lpDx */
228 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
229 ok( ret, "ExtTextOutA error %d\n", GetLastError());
231 /* 2. pass custom lpDx */
232 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
233 ok( ret, "ExtTextOutA error %d\n", GetLastError());
235 hFont = SelectObject(hdcMetafile, hFont);
236 ret = DeleteObject(hFont);
237 ok( ret, "DeleteObject error %d\n", GetLastError());
239 hMetafile = CloseEnhMetaFile(hdcMetafile);
240 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
242 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
244 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
245 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
247 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
248 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
249 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
250 SetROP2(hdcDisplay, R2_NOT);
251 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
252 SetPolyFillMode(hdcDisplay, WINDING);
253 SetStretchBltMode(hdcDisplay, HALFTONE);
255 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
256 SetBkMode(hdcDisplay, OPAQUE);
258 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
259 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
261 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
262 "text align %08x\n", GetTextAlign(hdcDisplay));
263 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
264 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
265 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
266 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
267 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
268 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
270 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
272 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
273 "A valid hdc has to require a valid rc\n");
275 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
276 "A null hdc does not require a valid rc\n");
278 ret = DeleteEnhMetaFile(hMetafile);
279 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
280 ret = ReleaseDC(hwnd, hdcDisplay);
281 ok( ret, "ReleaseDC error %d\n", GetLastError());
285 struct eto_scale_test_record
294 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
295 const ENHMETARECORD *emr, int n_objs, LPARAM param)
297 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
299 if (emr->iType == EMR_EXTTEXTOUTW)
301 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
302 trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
303 test->graphics_mode, test->map_mode,
304 pExtTextOutW->exScale, pExtTextOutW->eyScale,
305 test->ex_scale, test->ey_scale);
306 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
307 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
308 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
309 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
310 test->processed = TRUE;
316 static void test_ExtTextOutScale(void)
318 const RECT rc = { 0, 0, 100, 100 };
319 const WCHAR str[] = {'a',0 };
320 struct eto_scale_test_record test;
321 HDC hdcDisplay, hdcMetafile;
322 HENHMETAFILE hMetafile;
324 SIZE wndext, vportext;
325 int horzSize, vertSize, horzRes, vertRes;
329 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
330 0, 0, 200, 200, 0, 0, 0, NULL);
331 ok(hwnd != 0, "CreateWindowExA failed\n");
333 hdcDisplay = GetDC(hwnd);
334 ok(hdcDisplay != 0, "GetDC failed\n");
336 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
337 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
338 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
339 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
340 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
342 for (i = 0; i < 16; i++)
344 test.graphics_mode = i / 8 + 1;
345 test.map_mode = i % 8 + 1;
347 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
348 ok(ret, "SetGraphicsMode failed\n");
349 ret = SetMapMode(hdcDisplay, test.map_mode);
350 ok(ret, "SetMapMode failed\n");
352 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
354 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
355 ok(ret, "SetWindowExtEx failed\n");
356 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
357 ok(ret, "SetViewportExtEx failed\n");
360 ret = GetViewportExtEx(hdcDisplay, &vportext);
361 ok(ret, "GetViewportExtEx failed\n");
362 ret = GetWindowExtEx(hdcDisplay, &wndext);
363 ok(ret, "GetWindowExtEx failed\n");
365 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
366 test.graphics_mode, test.map_mode,
367 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
368 horzSize, horzRes, vertSize, vertRes);
370 if (test.graphics_mode == GM_COMPATIBLE)
372 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
373 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
374 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
375 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
383 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
384 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
386 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
387 ok(ret, "SetGraphicsMode failed\n");
388 ret = SetMapMode(hdcMetafile, test.map_mode);
389 ok(ret, "SetMapMode failed\n");
391 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
393 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
394 ok(ret, "SetWindowExtEx failed\n");
395 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
396 ok(ret, "SetViewportExtEx failed\n");
399 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
400 ok(ret, "ExtTextOutW failed\n");
402 hMetafile = CloseEnhMetaFile(hdcMetafile);
403 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
406 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
407 ok(ret, "EnumEnhMetaFile failed\n");
408 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
410 ret = DeleteEnhMetaFile(hMetafile);
411 ok(ret, "DeleteEnhMetaFile failed\n");
414 ret = ReleaseDC(hwnd, hdcDisplay);
415 ok(ret, "ReleaseDC failed\n");
420 static void check_dc_state(HDC hdc, int restore_no,
421 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
422 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
426 POINT vp_org, win_org;
427 SIZE vp_size, win_size;
428 FLOAT xscale, yscale, edx, edy;
430 SetLastError(0xdeadbeef);
431 ret = GetWorldTransform(hdc, &xform);
432 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
433 ok(ret, "GetWorldTransform error %u\n", GetLastError());
435 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
437 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
438 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
440 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
441 trace("x scale %f\n", xscale);
442 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
443 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
445 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
446 trace("y scale %f\n", yscale);
447 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
448 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
450 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
451 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
452 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
453 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
459 GetWindowOrgEx(hdc, &win_org);
460 GetViewportOrgEx(hdc, &vp_org);
461 GetWindowExtEx(hdc, &win_size);
462 GetViewportExtEx(hdc, &vp_size);
464 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
465 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
467 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
468 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
470 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
471 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
473 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
474 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
477 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
478 const ENHMETARECORD *emr, int n_objs, LPARAM param)
484 static int save_state;
485 static int restore_no;
486 static int select_no;
488 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
489 hdc, emr->iType, emr->nSize, (void *)param);
492 SetLastError(0xdeadbeef);
493 ret = GetWorldTransform(hdc, &xform);
494 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
496 ret = GetWindowOrgEx(hdc, &pt);
497 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
498 trace("window org (%d,%d)\n", pt.x, pt.y);
499 ret = GetViewportOrgEx(hdc, &pt);
500 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
501 trace("vport org (%d,%d)\n", pt.x, pt.y);
502 ret = GetWindowExtEx(hdc, &size);
503 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
504 trace("window ext (%d,%d)\n", size.cx, size.cy);
505 ret = GetViewportExtEx(hdc, &size);
506 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
507 trace("vport ext (%d,%d)\n", size.cx, size.cy);
511 ok(ret, "GetWorldTransform error %u\n", GetLastError());
512 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
515 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
521 static RECT exp_bounds = { 0, 0, 150, 150 };
523 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
525 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
526 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
527 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
528 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
529 emf->szlDevice.cx, emf->szlDevice.cy);
531 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
532 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
537 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
543 const EMRLINETO *line = (const EMRLINETO *)emr;
544 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
547 case EMR_SETWINDOWORGEX:
549 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
550 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
553 case EMR_SETWINDOWEXTEX:
555 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
556 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
559 case EMR_SETVIEWPORTORGEX:
561 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
562 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
565 case EMR_SETVIEWPORTEXTEX:
567 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
568 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
573 trace("EMR_SAVEDC\n");
578 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
579 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
584 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
585 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
588 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
589 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
592 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
593 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
596 ok(restore_no <= 3, "restore_no %d\n", restore_no);
597 save_state += restoredc->iRelative;
600 case EMR_SELECTOBJECT:
602 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
603 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
608 ok(save_state == 0, "EOF save_state %d\n", save_state);
609 ok(select_no == 3, "Too many/few selects %i\n",select_no);
614 SetLastError(0xdeadbeef);
615 ret = GetWorldTransform(hdc, &xform);
616 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
618 ret = GetWindowOrgEx(hdc, &pt);
619 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
620 trace("window org (%d,%d)\n", pt.x, pt.y);
621 ret = GetViewportOrgEx(hdc, &pt);
622 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
623 trace("vport org (%d,%d)\n", pt.x, pt.y);
624 ret = GetWindowExtEx(hdc, &size);
625 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
626 trace("window ext (%d,%d)\n", size.cx, size.cy);
627 ret = GetViewportExtEx(hdc, &size);
628 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
629 trace("vport ext (%d,%d)\n", size.cx, size.cy);
633 ok(ret, "GetWorldTransform error %u\n", GetLastError());
634 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
640 static void test_SaveDC(void)
642 HDC hdcMetafile, hdcDisplay;
643 HENHMETAFILE hMetafile;
648 HFONT hFont,hFont2,hFontOld,hFontCheck;
649 static const RECT rc = { 0, 0, 150, 150 };
651 /* Win9x doesn't play EMFs on invisible windows */
652 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
653 0, 0, 200, 200, 0, 0, 0, NULL);
654 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
656 hdcDisplay = GetDC(hwnd);
657 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
659 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
660 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
662 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
664 /* Need to write something to the emf, otherwise Windows won't play it back */
665 LineTo(hdcMetafile, 150, 150);
667 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
668 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
669 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
670 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
672 /* Force Win9x to update DC state */
673 SetPixelV(hdcMetafile, 50, 50, 0);
675 ret = GetViewportOrgEx(hdcMetafile, &pt);
676 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
677 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
678 ret = GetViewportExtEx(hdcMetafile, &size);
679 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
680 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
681 ret = SaveDC(hdcMetafile);
682 ok(ret == 1, "ret = %d\n", ret);
684 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
685 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
686 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
687 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
689 /* Force Win9x to update DC state */
690 SetPixelV(hdcMetafile, 50, 50, 0);
692 ret = GetViewportOrgEx(hdcMetafile, &pt);
693 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
694 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
695 ret = GetViewportExtEx(hdcMetafile, &size);
696 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
697 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
698 ret = SaveDC(hdcMetafile);
699 ok(ret == 2, "ret = %d\n", ret);
701 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
702 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
703 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
704 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
705 SetPolyFillMode( hdcMetafile, ALTERNATE );
706 SetBkColor( hdcMetafile, 0 );
708 /* Force Win9x to update DC state */
709 SetPixelV(hdcMetafile, 50, 50, 0);
711 ret = GetViewportOrgEx(hdcMetafile, &pt);
712 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
713 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
714 ret = GetViewportExtEx(hdcMetafile, &size);
715 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
716 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
717 ret = SaveDC(hdcMetafile);
718 ok(ret == 3, "ret = %d\n", ret);
720 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
721 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
722 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
723 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
725 SetPolyFillMode( hdcMetafile, WINDING );
726 SetBkColor( hdcMetafile, 0x123456 );
727 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
728 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
730 /* Force Win9x to update DC state */
731 SetPixelV(hdcMetafile, 50, 50, 0);
733 ret = GetViewportOrgEx(hdcMetafile, &pt);
734 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
735 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
736 ret = GetViewportExtEx(hdcMetafile, &size);
737 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
738 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
739 ret = RestoreDC(hdcMetafile, -1);
740 ok(ret, "ret = %d\n", ret);
742 ret = GetViewportOrgEx(hdcMetafile, &pt);
743 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
744 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
745 ret = GetViewportExtEx(hdcMetafile, &size);
746 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
747 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
748 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
749 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
750 ret = SaveDC(hdcMetafile);
751 ok(ret == 3, "ret = %d\n", ret);
753 ret = GetViewportOrgEx(hdcMetafile, &pt);
754 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
755 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
756 ret = GetViewportExtEx(hdcMetafile, &size);
757 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
758 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
759 ret = RestoreDC(hdcMetafile, 1);
760 ok(ret, "ret = %d\n", ret);
761 ret = GetViewportOrgEx(hdcMetafile, &pt);
762 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
763 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
764 ret = GetViewportExtEx(hdcMetafile, &size);
765 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
766 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
768 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
769 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
770 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
771 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
773 /* Force Win9x to update DC state */
774 SetPixelV(hdcMetafile, 50, 50, 0);
776 ret = GetViewportOrgEx(hdcMetafile, &pt);
777 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
778 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
779 ret = GetViewportExtEx(hdcMetafile, &size);
780 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
781 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
782 ret = SaveDC(hdcMetafile);
783 ok(ret == 1, "ret = %d\n", ret);
785 ret = GetViewportOrgEx(hdcMetafile, &pt);
786 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
787 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
788 ret = GetViewportExtEx(hdcMetafile, &size);
789 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
790 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
791 ret = SaveDC(hdcMetafile);
792 ok(ret == 2, "ret = %d\n", ret);
794 memset(&orig_lf, 0, sizeof(orig_lf));
795 orig_lf.lfCharSet = ANSI_CHARSET;
796 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
797 orig_lf.lfWeight = FW_DONTCARE;
798 orig_lf.lfHeight = 7;
799 orig_lf.lfQuality = DEFAULT_QUALITY;
800 lstrcpyA(orig_lf.lfFaceName, "Arial");
801 hFont = CreateFontIndirectA(&orig_lf);
802 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
804 hFontOld = SelectObject(hdcMetafile, hFont);
806 hFont2 = CreateFontIndirectA(&orig_lf);
807 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
808 hFontCheck = SelectObject(hdcMetafile, hFont2);
809 ok(hFontCheck == hFont, "Font not selected\n");
811 /* Force Win9x to update DC state */
812 SetPixelV(hdcMetafile, 50, 50, 0);
814 ret = RestoreDC(hdcMetafile, 1);
815 ok(ret, "ret = %d\n", ret);
816 ret = GetViewportOrgEx(hdcMetafile, &pt);
817 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
818 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
819 ret = GetViewportExtEx(hdcMetafile, &size);
820 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
821 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
823 hFontCheck = SelectObject(hdcMetafile, hFontOld);
824 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
825 "Font not reverted with DC Restore\n");
827 ret = RestoreDC(hdcMetafile, -20);
828 ok(!ret, "ret = %d\n", ret);
829 ret = RestoreDC(hdcMetafile, 20);
830 ok(!ret, "ret = %d\n", ret);
832 hMetafile = CloseEnhMetaFile(hdcMetafile);
833 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
835 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
836 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
838 ret = DeleteObject(hFont);
839 ok( ret, "DeleteObject error %d\n", GetLastError());
840 ret = DeleteObject(hFont2);
841 ok( ret, "DeleteObject error %d\n", GetLastError());
842 ret = DeleteEnhMetaFile(hMetafile);
843 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
844 ret = ReleaseDC(hwnd, hdcDisplay);
845 ok( ret, "ReleaseDC error %d\n", GetLastError());
849 static void test_mf_SaveDC(void)
856 HFONT hFont,hFont2,hFontOld,hFontCheck;
858 hdcMetafile = CreateMetaFileA(NULL);
859 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
861 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
862 ok (ret, "SetMapMode should not fail\n");
864 /* Need to write something to the emf, otherwise Windows won't play it back */
865 LineTo(hdcMetafile, 150, 150);
868 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
869 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
871 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
872 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
873 size.cx = size.cy = 5555;
874 SetWindowExtEx(hdcMetafile, 110, 110, &size );
875 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
876 size.cx = size.cy = 5555;
877 SetViewportExtEx(hdcMetafile, 120, 120, &size );
878 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
880 /* Force Win9x to update DC state */
881 SetPixelV(hdcMetafile, 50, 50, 0);
883 ret = GetViewportOrgEx(hdcMetafile, &pt);
884 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
885 ret = GetViewportExtEx(hdcMetafile, &size);
886 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
887 ret = SaveDC(hdcMetafile);
888 ok(ret == 1, "ret = %d\n", ret);
890 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
891 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
892 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
893 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
895 /* Force Win9x to update DC state */
896 SetPixelV(hdcMetafile, 50, 50, 0);
898 ret = SaveDC(hdcMetafile);
899 ok(ret == 1, "ret = %d\n", ret);
901 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
902 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
903 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
904 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
906 /* Force Win9x to update DC state */
907 SetPixelV(hdcMetafile, 50, 50, 0);
908 SetPolyFillMode( hdcMetafile, ALTERNATE );
909 SetBkColor( hdcMetafile, 0 );
911 ret = SaveDC(hdcMetafile);
912 ok(ret == 1, "ret = %d\n", ret);
914 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
915 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
916 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
917 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
919 SetPolyFillMode( hdcMetafile, WINDING );
920 SetBkColor( hdcMetafile, 0x123456 );
921 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
922 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
924 /* Force Win9x to update DC state */
925 SetPixelV(hdcMetafile, 50, 50, 0);
927 ret = RestoreDC(hdcMetafile, -1);
928 ok(ret, "ret = %d\n", ret);
930 ret = SaveDC(hdcMetafile);
931 ok(ret == 1, "ret = %d\n", ret);
933 ret = RestoreDC(hdcMetafile, 1);
934 ok(ret, "ret = %d\n", ret);
936 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
937 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
938 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
939 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
941 /* Force Win9x to update DC state */
942 SetPixelV(hdcMetafile, 50, 50, 0);
944 ret = SaveDC(hdcMetafile);
945 ok(ret == 1, "ret = %d\n", ret);
947 ret = SaveDC(hdcMetafile);
948 ok(ret == 1, "ret = %d\n", ret);
950 memset(&orig_lf, 0, sizeof(orig_lf));
951 orig_lf.lfCharSet = ANSI_CHARSET;
952 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
953 orig_lf.lfWeight = FW_DONTCARE;
954 orig_lf.lfHeight = 7;
955 orig_lf.lfQuality = DEFAULT_QUALITY;
956 lstrcpyA(orig_lf.lfFaceName, "Arial");
957 hFont = CreateFontIndirectA(&orig_lf);
958 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
960 hFontOld = SelectObject(hdcMetafile, hFont);
962 hFont2 = CreateFontIndirectA(&orig_lf);
963 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
964 hFontCheck = SelectObject(hdcMetafile, hFont2);
965 ok(hFontCheck == hFont, "Font not selected\n");
967 /* Force Win9x to update DC state */
968 SetPixelV(hdcMetafile, 50, 50, 0);
970 ret = RestoreDC(hdcMetafile, 1);
971 ok(ret, "ret = %d\n", ret);
973 hFontCheck = SelectObject(hdcMetafile, hFontOld);
974 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
976 /* restore level is ignored */
977 ret = RestoreDC(hdcMetafile, -20);
978 ok(ret, "ret = %d\n", ret);
979 ret = RestoreDC(hdcMetafile, 20);
980 ok(ret, "ret = %d\n", ret);
981 ret = RestoreDC(hdcMetafile, 0);
982 ok(ret, "ret = %d\n", ret);
984 hMetafile = CloseMetaFile(hdcMetafile);
985 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
987 ret = DeleteMetaFile(hMetafile);
988 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
989 ret = DeleteObject(hFont);
990 ok( ret, "DeleteObject error %d\n", GetLastError());
991 ret = DeleteObject(hFont2);
992 ok( ret, "DeleteObject error %d\n", GetLastError());
996 /* Win-format metafile (mfdrv) tests */
997 /* These tests compare the generated metafiles byte-by-byte */
998 /* with the nominal results. */
1000 /* Maximum size of sample metafiles in bytes. */
1001 #define MF_BUFSIZE 512
1003 /* 8x8 bitmap data for a pattern brush */
1004 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
1005 0x01, 0x00, 0x02, 0x00,
1006 0x03, 0x00, 0x04, 0x00,
1007 0x05, 0x00, 0x06, 0x00,
1008 0x07, 0x00, 0x08, 0x00
1011 /* Sample metafiles to be compared to the outputs of the
1015 static const unsigned char MF_BLANK_BITS[] = {
1016 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1018 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1021 static const unsigned char MF_GRAPHICS_BITS[] = {
1022 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1023 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1025 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1026 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1027 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1028 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1029 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1030 0x00, 0x00, 0x00, 0x00
1033 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1034 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1035 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1036 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1037 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1038 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1039 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1040 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1044 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1045 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1046 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1047 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1048 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1052 static const unsigned char MF_DCBRUSH_BITS[] =
1054 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1055 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1056 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1057 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1058 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1059 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1062 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1063 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1064 0x00, 0x00, 0x00, 0x00
1067 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1069 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1070 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1071 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1072 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1073 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1074 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1078 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1080 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1084 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1085 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1086 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1087 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1089 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1090 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1093 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1094 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1095 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1097 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1099 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1100 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1102 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1103 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1104 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1105 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1106 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1107 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1108 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1110 0x14, 0x00, 0x00, 0x00
1113 static const unsigned char MF_LINETO_BITS[] = {
1114 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1115 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1117 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1121 static const unsigned char EMF_LINETO_BITS[] = {
1122 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1124 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1126 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1127 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1128 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1129 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1132 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1135 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1136 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1137 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1138 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1139 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1140 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1141 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1142 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1143 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1144 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1145 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1146 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1147 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1148 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1149 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1150 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1151 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1152 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1153 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1154 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1155 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1156 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1157 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1159 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1163 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1164 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1166 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1168 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1169 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1170 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1171 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1174 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1177 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1178 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1179 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1180 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1181 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1182 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1183 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1184 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1185 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1186 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1187 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1188 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1189 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1190 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1191 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1192 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1194 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1195 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1196 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1197 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1198 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1199 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1201 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1205 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1206 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1208 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1211 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1212 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1213 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1215 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1216 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1219 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1220 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1221 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1222 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1223 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1224 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1225 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1226 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1227 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1229 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1230 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1232 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1234 0x14, 0x00, 0x00, 0x00
1237 static const unsigned char EMF_BITBLT[] =
1239 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1244 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1245 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1246 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1249 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1252 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1253 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1255 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1257 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1264 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1265 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1266 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1267 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1281 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1289 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1293 static const unsigned char EMF_DCBRUSH_BITS[] =
1295 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1296 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1297 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1298 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1299 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1300 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1301 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1302 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1305 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1307 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1308 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1309 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1310 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1311 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1312 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1315 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1316 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1317 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1319 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1320 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1321 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1322 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1323 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1324 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1325 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1326 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1327 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1328 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1329 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1330 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1331 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1332 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1333 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1335 0x14, 0x00, 0x00, 0x00
1338 static const unsigned char EMF_BEZIER_BITS[] =
1340 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1342 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1345 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1346 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1347 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1349 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1350 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1352 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1353 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1354 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1356 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1357 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1358 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1359 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1360 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1361 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1362 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1363 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1364 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1365 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1366 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1367 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1368 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1369 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1370 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1371 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1372 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1373 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1374 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1375 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1376 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1377 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1378 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1380 0x14, 0x00, 0x00, 0x00
1383 /* For debugging or dumping the raw metafiles produced by
1384 * new test functions.
1386 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1387 INT nobj, LPARAM param)
1389 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1390 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1394 /* For debugging or dumping the raw metafiles produced by
1395 * new test functions.
1398 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1400 BYTE buf[MF_BUFSIZE];
1403 if (!winetest_debug) return;
1405 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1406 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1408 printf ("MetaFile %s has bits:\n{\n ", desc);
1409 for (i=0; i<mfsize; i++)
1411 printf ("0x%02x", buf[i]);
1414 else if (i % 8 == 7)
1422 /* Compare the metafile produced by a test function with the
1423 * expected raw metafile data in "bits".
1424 * Return value is 0 for a perfect match,
1425 * -1 if lengths aren't equal,
1426 * otherwise returns the number of non-matching bytes.
1429 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1432 unsigned char buf[MF_BUFSIZE];
1436 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1437 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1438 if (mfsize < MF_BUFSIZE)
1439 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1440 desc, mfsize, bsize);
1442 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1443 desc, mfsize, bsize);
1444 if (mfsize != bsize)
1448 for (i=0; i<bsize; i++)
1450 if (buf[i] != bits[i])
1453 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1454 desc, mfsize, bsize, diff);
1459 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1461 unsigned char buf[MF_BUFSIZE];
1462 DWORD mfsize, rd_size, i;
1467 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1468 assert(hfile != INVALID_HANDLE_VALUE);
1470 mfsize = GetFileSize(hfile, NULL);
1471 assert(mfsize <= MF_BUFSIZE);
1473 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1474 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1478 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1480 if (mfsize != bsize)
1484 for (i=0; i<bsize; i++)
1486 if (buf[i] != bits[i])
1489 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1490 desc, mfsize, bsize, diff);
1495 /* For debugging or dumping the raw EMFs produced by
1496 * new test functions.
1498 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1500 BYTE buf[MF_BUFSIZE];
1503 if (!winetest_debug) return;
1505 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1506 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1508 printf("EMF %s has bits:\n{\n ", desc);
1509 for (i = 0; i < mfsize; i++)
1511 printf ("0x%02x", buf[i]);
1514 else if (i % 8 == 7)
1522 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1525 BYTE buf[MF_BUFSIZE];
1526 UINT mfsize, offset;
1528 if (!winetest_debug) return;
1530 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1531 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1533 printf("EMF %s has records:\n", desc);
1537 while(offset < mfsize)
1539 EMR *emr = (EMR *)(emf + offset);
1540 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1541 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1542 offset += emr->nSize;
1546 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1551 if (!winetest_debug) return;
1553 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1554 buf = (const BYTE *)emr;
1555 for (i = 0; i < emr->nSize; i++)
1557 printf ("0x%02x", buf[i]);
1558 if (i == emr->nSize - 1)
1560 else if (i % 8 == 7)
1568 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1570 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1571 eto->rclBounds.right, eto->rclBounds.bottom);
1572 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1573 trace("exScale: %f\n", eto->exScale);
1574 trace("eyScale: %f\n", eto->eyScale);
1575 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1576 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1577 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1578 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1579 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1580 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1581 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1584 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1585 const char *desc, BOOL ignore_scaling)
1589 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1590 desc, emr1->iType, emr2->iType);
1592 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1593 desc, emr1->nSize, emr2->nSize);
1595 /* iType and nSize mismatches are fatal */
1596 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1598 /* contents of EMR_GDICOMMENT are not interesting */
1599 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1601 /* different Windows versions setup DC scaling differently when
1602 * converting an old style metafile to an EMF.
1604 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1605 emr1->iType == EMR_SETVIEWPORTEXTEX))
1608 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1610 EMREXTTEXTOUTW *eto1, *eto2;
1612 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1613 memcpy(eto1, emr1, emr1->nSize);
1614 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1615 memcpy(eto2, emr2, emr2->nSize);
1617 /* different Windows versions setup DC scaling differently */
1618 eto1->exScale = eto1->eyScale = 0.0;
1619 eto2->exScale = eto2->eyScale = 0.0;
1621 diff = memcmp(eto1, eto2, emr1->nSize);
1624 dump_EMREXTTEXTOUT(eto1);
1625 dump_EMREXTTEXTOUT(eto2);
1627 HeapFree(GetProcessHeap(), 0, eto1);
1628 HeapFree(GetProcessHeap(), 0, eto2);
1630 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1632 /* We have to take care of NT4 differences here */
1633 diff = memcmp(emr1, emr2, emr1->nSize);
1636 ENHMETARECORD *emr_nt4;
1638 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1639 memcpy(emr_nt4, emr2, emr2->nSize);
1640 /* Correct the nRgnSize field */
1641 emr_nt4->dParm[5] = sizeof(RECT);
1643 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1645 win_skip("Catered for NT4 differences\n");
1647 HeapFree(GetProcessHeap(), 0, emr_nt4);
1650 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1652 EMRPOLYBEZIER16 *eto1, *eto2;
1654 eto1 = (EMRPOLYBEZIER16*)emr1;
1655 eto2 = (EMRPOLYBEZIER16*)emr2;
1657 diff = eto1->cpts != eto2->cpts;
1659 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1661 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1663 EMRPOLYBEZIER *eto1, *eto2;
1665 eto1 = (EMRPOLYBEZIER*)emr1;
1666 eto2 = (EMRPOLYBEZIER*)emr2;
1668 diff = eto1->cptl != eto2->cptl;
1670 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1673 diff = memcmp(emr1, emr2, emr1->nSize);
1675 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1679 dump_emf_record(emr1, "expected bits");
1680 dump_emf_record(emr2, "actual bits");
1683 return diff == 0; /* report all non-fatal record mismatches */
1686 /* Compare the EMF produced by a test function with the
1687 * expected raw EMF data in "bits".
1688 * Return value is 0 for a perfect match,
1689 * -1 if lengths aren't equal,
1690 * otherwise returns the number of non-matching bytes.
1692 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1693 UINT bsize, const char *desc,
1694 BOOL ignore_scaling)
1696 unsigned char buf[MF_BUFSIZE];
1697 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1698 const ENHMETAHEADER *emh1, *emh2;
1700 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1701 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1703 /* ENHMETAHEADER size could differ, depending on platform */
1704 diff_nt4 = sizeof(SIZEL);
1705 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1707 if (mfsize < MF_BUFSIZE)
1709 ok(mfsize == bsize ||
1710 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1711 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1712 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1715 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1716 desc, mfsize, bsize);
1718 /* basic things must match */
1719 emh1 = (const ENHMETAHEADER *)bits;
1720 emh2 = (const ENHMETAHEADER *)buf;
1721 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1722 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1723 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1724 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1726 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1727 ok(emh1->nSize == emh2->nSize ||
1728 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1729 broken(emh1->nSize - diff_9x == emh2->nSize),
1730 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1731 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1732 ok(emh1->nBytes == emh2->nBytes ||
1733 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1734 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1735 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1736 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1738 offset1 = emh1->nSize;
1739 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1740 while (offset1 < emh1->nBytes)
1742 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1743 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1745 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1746 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1748 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1750 /* We have already bailed out if iType or nSize don't match */
1751 offset1 += emr1->nSize;
1752 offset2 += emr2->nSize;
1758 /* tests blitting to an EMF */
1759 static void test_emf_BitBlt(void)
1761 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1762 HBITMAP hBitmap, hOldBitmap;
1763 HENHMETAFILE hMetafile;
1765 BITMAPINFOHEADER bmih =
1767 sizeof(BITMAPINFOHEADER),
1768 BMP_DIM,/* biWidth */
1769 BMP_DIM,/* biHeight */
1771 24, /* biBitCount */
1772 BI_RGB, /* biCompression */
1773 0, /* biXPelsPerMeter */
1774 0, /* biYPelsPerMeter */
1776 0, /* biClrImportant */
1781 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1782 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1784 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1785 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1786 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1787 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1788 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1789 DIB_RGB_COLORS, &bits, NULL, 0);
1790 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1792 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1793 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1795 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1796 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1797 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1799 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1800 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1801 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1802 ok( ret, "BitBlt(WHITENESS) failed\n" );
1804 hMetafile = CloseEnhMetaFile(hdcMetafile);
1805 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1807 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1808 "emf_BitBlt", FALSE) != 0)
1810 dump_emf_bits(hMetafile, "emf_BitBlt");
1811 dump_emf_records(hMetafile, "emf_BitBlt");
1814 SelectObject(hdcBitmap, hOldBitmap);
1815 DeleteObject(hBitmap);
1816 DeleteDC(hdcBitmap);
1817 DeleteDC(hdcDisplay);
1821 static void test_emf_DCBrush(void)
1824 HENHMETAFILE hMetafile;
1830 if (!pSetDCBrushColor || !pSetDCPenColor)
1832 win_skip( "SetDCBrush/PenColor not supported\n" );
1836 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1837 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1839 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1840 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1842 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1843 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1845 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1846 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1848 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1849 ok( color == 0, "SetDCPenColor returned %x\n", color );
1851 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1853 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1854 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1856 hMetafile = CloseEnhMetaFile(hdcMetafile);
1857 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1859 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1860 "emf_DC_Brush", FALSE ) != 0)
1862 dump_emf_bits(hMetafile, "emf_DC_Brush");
1863 dump_emf_records(hMetafile, "emf_DC_Brush");
1865 ret = DeleteEnhMetaFile(hMetafile);
1866 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1867 ret = DeleteObject(hBrush);
1868 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1869 ret = DeleteObject(hPen);
1870 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1873 /* Test a blank metafile. May be used as a template for new tests. */
1875 static void test_mf_Blank(void)
1878 HMETAFILE hMetafile;
1883 hdcMetafile = CreateMetaFileA(NULL);
1884 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1885 trace("hdcMetafile %p\n", hdcMetafile);
1887 /* Tests on metafile initialization */
1888 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1889 ok (caps == DT_METAFILE,
1890 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1892 hMetafile = CloseMetaFile(hdcMetafile);
1893 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1894 type = GetObjectType(hMetafile);
1895 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1896 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1898 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1901 dump_mf_bits(hMetafile, "mf_Blank");
1902 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1905 ret = DeleteMetaFile(hMetafile);
1906 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1909 static void test_CopyMetaFile(void)
1912 HMETAFILE hMetafile, hmf_copy;
1914 char temp_path[MAX_PATH];
1915 char mf_name[MAX_PATH];
1918 hdcMetafile = CreateMetaFileA(NULL);
1919 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1920 trace("hdcMetafile %p\n", hdcMetafile);
1922 hMetafile = CloseMetaFile(hdcMetafile);
1923 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1924 type = GetObjectType(hMetafile);
1925 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1927 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1930 dump_mf_bits(hMetafile, "mf_Blank");
1931 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1934 GetTempPathA(MAX_PATH, temp_path);
1935 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1937 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1938 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1940 type = GetObjectType(hmf_copy);
1941 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1943 ret = DeleteMetaFile(hMetafile);
1944 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1946 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1948 dump_mf_bits(hmf_copy, "mf_Blank");
1949 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1952 ret = DeleteMetaFile(hmf_copy);
1953 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1955 DeleteFileA(mf_name);
1958 static void test_SetMetaFileBits(void)
1966 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1967 trace("hmf %p\n", hmf);
1968 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1969 type = GetObjectType(hmf);
1970 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1972 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1974 dump_mf_bits(hmf, "mf_Graphics");
1975 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1978 ret = DeleteMetaFile(hmf);
1979 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1981 /* NULL data crashes XP SP1 */
1982 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1984 /* Now with zero size */
1985 SetLastError(0xdeadbeef);
1986 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1987 trace("hmf %p\n", hmf);
1988 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1989 ok(GetLastError() == ERROR_INVALID_DATA ||
1990 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1991 "wrong error %d\n", GetLastError());
1993 /* Now with odd size */
1994 SetLastError(0xdeadbeef);
1995 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1996 trace("hmf %p\n", hmf);
1997 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1998 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2000 /* Now with zeroed out header fields */
2001 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2002 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2003 mh = (METAHEADER *)buf;
2004 /* corruption of any of the below fields leads to a failure */
2007 mh->mtHeaderSize = 0;
2008 SetLastError(0xdeadbeef);
2009 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2010 trace("hmf %p\n", hmf);
2011 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2012 ok(GetLastError() == ERROR_INVALID_DATA ||
2013 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2014 "wrong error %d\n", GetLastError());
2016 /* Now with corrupted mtSize field */
2017 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2018 mh = (METAHEADER *)buf;
2019 /* corruption of mtSize doesn't lead to a failure */
2021 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2022 trace("hmf %p\n", hmf);
2023 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2025 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2027 dump_mf_bits(hmf, "mf_Graphics");
2028 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2031 ret = DeleteMetaFile(hmf);
2032 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2034 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2035 /* Now with zeroed out mtSize field */
2036 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2037 mh = (METAHEADER *)buf;
2038 /* zeroing mtSize doesn't lead to a failure */
2040 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2041 trace("hmf %p\n", hmf);
2042 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2044 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2046 dump_mf_bits(hmf, "mf_Graphics");
2047 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2050 ret = DeleteMetaFile(hmf);
2051 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2055 /* Simple APIs from mfdrv/graphics.c
2058 static void test_mf_Graphics(void)
2061 HMETAFILE hMetafile;
2065 hdcMetafile = CreateMetaFileA(NULL);
2066 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2067 trace("hdcMetafile %p\n", hdcMetafile);
2069 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2070 ok( ret, "MoveToEx error %d.\n", GetLastError());
2071 ret = LineTo(hdcMetafile, 2, 2);
2072 ok( ret, "LineTo error %d.\n", GetLastError());
2073 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2074 ok( ret, "MoveToEx error %d.\n", GetLastError());
2076 /* oldpoint gets garbage under Win XP, so the following test would
2077 * work under Wine but fails under Windows:
2079 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2080 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2081 * oldpoint.x, oldpoint.y);
2084 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2085 ok( ret, "Ellipse error %d.\n", GetLastError());
2087 hMetafile = CloseMetaFile(hdcMetafile);
2088 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2089 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2091 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2092 "mf_Graphics") != 0)
2094 dump_mf_bits(hMetafile, "mf_Graphics");
2095 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2098 ret = DeleteMetaFile(hMetafile);
2099 ok( ret, "DeleteMetaFile(%p) error %d\n",
2100 hMetafile, GetLastError());
2103 static void test_mf_PatternBrush(void)
2106 HMETAFILE hMetafile;
2111 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2113 orig_lb->lbStyle = BS_PATTERN;
2114 orig_lb->lbColor = RGB(0, 0, 0);
2115 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2116 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2118 hBrush = CreateBrushIndirect (orig_lb);
2119 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2121 hdcMetafile = CreateMetaFileA(NULL);
2122 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2123 trace("hdcMetafile %p\n", hdcMetafile);
2125 hBrush = SelectObject(hdcMetafile, hBrush);
2126 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2128 hMetafile = CloseMetaFile(hdcMetafile);
2129 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2130 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2132 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2133 "mf_Pattern_Brush") != 0)
2135 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2136 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2139 ret = DeleteMetaFile(hMetafile);
2140 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2141 ret = DeleteObject(hBrush);
2142 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2143 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2144 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2146 HeapFree (GetProcessHeap(), 0, orig_lb);
2149 static void test_mf_DCBrush(void)
2152 HMETAFILE hMetafile;
2158 if (!pSetDCBrushColor || !pSetDCPenColor)
2160 win_skip( "SetDCBrush/PenColor not supported\n" );
2164 hdcMetafile = CreateMetaFileA(NULL);
2165 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2167 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2168 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2170 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2171 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2173 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2174 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2176 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2177 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2179 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2181 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2182 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2184 hMetafile = CloseMetaFile(hdcMetafile);
2185 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2187 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2189 dump_mf_bits(hMetafile, "mf_DCBrush");
2190 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2192 ret = DeleteMetaFile(hMetafile);
2193 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2196 static void test_mf_ExtTextOut_on_path(void)
2199 HMETAFILE hMetafile;
2201 static const INT dx[4] = { 3, 5, 8, 12 };
2203 hdcMetafile = CreateMetaFileA(NULL);
2204 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2205 trace("hdcMetafile %p\n", hdcMetafile);
2207 ret = BeginPath(hdcMetafile);
2208 ok(!ret, "BeginPath on metafile DC should fail\n");
2210 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2211 ok(ret, "ExtTextOut error %d\n", GetLastError());
2213 ret = EndPath(hdcMetafile);
2214 ok(!ret, "EndPath on metafile DC should fail\n");
2216 hMetafile = CloseMetaFile(hdcMetafile);
2217 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2219 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2220 "mf_TextOut_on_path") != 0)
2222 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2223 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2226 ret = DeleteMetaFile(hMetafile);
2227 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2230 static void test_emf_ExtTextOut_on_path(void)
2233 HDC hdcDisplay, hdcMetafile;
2234 HENHMETAFILE hMetafile;
2236 static const INT dx[4] = { 3, 5, 8, 12 };
2238 /* Win9x doesn't play EMFs on invisible windows */
2239 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2240 0, 0, 200, 200, 0, 0, 0, NULL);
2241 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2243 hdcDisplay = GetDC(hwnd);
2244 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2246 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2247 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2249 ret = BeginPath(hdcMetafile);
2250 ok(ret, "BeginPath error %d\n", GetLastError());
2252 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2253 ok(ret, "ExtTextOut error %d\n", GetLastError());
2255 ret = EndPath(hdcMetafile);
2256 ok(ret, "EndPath error %d\n", GetLastError());
2258 hMetafile = CloseEnhMetaFile(hdcMetafile);
2259 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2261 /* this doesn't succeed yet: EMF has correct size, all EMF records
2262 * are there, but their contents don't match for different reasons.
2264 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2265 "emf_TextOut_on_path", FALSE) != 0)
2267 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2268 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2271 ret = DeleteEnhMetaFile(hMetafile);
2272 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2273 ret = ReleaseDC(hwnd, hdcDisplay);
2274 ok(ret, "ReleaseDC error %d\n", GetLastError());
2275 DestroyWindow(hwnd);
2278 static const unsigned char EMF_CLIPPING[] =
2280 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2282 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2284 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2285 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2286 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2287 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2289 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2290 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2292 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2293 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2294 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2295 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2296 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2297 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2298 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2299 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2300 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2301 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2302 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2303 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2304 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2305 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2308 static void translate( POINT *pt, UINT count, const XFORM *xform )
2312 FLOAT x = (FLOAT)pt->x;
2313 FLOAT y = (FLOAT)pt->y;
2314 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2315 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2320 /* Compare rectangles allowing rounding errors */
2321 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2323 return abs(rc1->left - rc2->left) <= 1 &&
2324 abs(rc1->top - rc2->top) <= 1 &&
2325 abs(rc1->right - rc2->right) <= 1 &&
2326 abs(rc1->bottom - rc2->bottom) <= 1;
2329 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2330 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2332 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2334 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2338 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2340 const union _rgn *rgn1;
2342 RECT rect, rc_transformed;
2343 const RECT *rc = (const RECT *)param;
2349 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2350 clip->cbRgnData, clip->iMode);
2352 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2353 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2354 "too small data block: %u bytes\n", clip->cbRgnData);
2355 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2358 rgn1 = (const union _rgn *)clip->RgnData;
2360 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2361 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2362 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2363 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2364 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2366 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2368 rect = *(const RECT *)rgn1->data.Buffer;
2369 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2370 ok(EqualRect(&rect, rc), "rects don't match\n");
2372 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2373 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2374 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2375 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2376 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2377 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2379 hrgn = CreateRectRgn(0, 0, 0, 0);
2381 memset(&xform, 0, sizeof(xform));
2382 SetLastError(0xdeadbeef);
2383 ret = GetWorldTransform(hdc, &xform);
2384 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2386 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2388 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2390 ret = GetClipRgn(hdc, hrgn);
2391 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2393 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2395 ret = GetClipRgn(hdc, hrgn);
2396 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2398 /* Win9x returns empty clipping region */
2399 if (is_win9x) return 1;
2401 ret = GetRegionData(hrgn, 0, NULL);
2402 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2404 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2405 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2407 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2408 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2409 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2410 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2411 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2413 rect = rgn2.data.rdh.rcBound;
2414 rc_transformed = *rc;
2415 translate((POINT *)&rc_transformed, 2, &xform);
2416 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2417 rc_transformed.right, rc_transformed.bottom);
2418 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2420 rect = *(const RECT *)rgn2.data.Buffer;
2421 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2422 rc_transformed = *rc;
2423 translate((POINT *)&rc_transformed, 2, &xform);
2424 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2425 rc_transformed.right, rc_transformed.bottom);
2426 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2428 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2429 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2430 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2431 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2432 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2433 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2440 static void test_emf_clipping(void)
2442 static const RECT rc = { 0, 0, 100, 100 };
2443 RECT rc_clip = { 100, 100, 1024, 1024 };
2449 RECT rc_res, rc_sclip;
2451 SetLastError(0xdeadbeef);
2452 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2453 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2455 /* Need to write something to the emf, otherwise Windows won't play it back */
2458 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2459 ret = SelectClipRgn(hdc, hrgn);
2460 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2462 SetLastError(0xdeadbeef);
2463 hemf = CloseEnhMetaFile(hdc);
2464 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2466 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2467 "emf_clipping", FALSE) != 0)
2469 dump_emf_bits(hemf, "emf_clipping");
2470 dump_emf_records(hemf, "emf_clipping");
2475 /* Win9x doesn't play EMFs on invisible windows */
2476 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2477 0, 0, 200, 200, 0, 0, 0, NULL);
2478 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2482 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2483 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2485 DeleteEnhMetaFile(hemf);
2486 ReleaseDC(hwnd, hdc);
2487 DestroyWindow(hwnd);
2489 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2491 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2492 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2493 SelectClipRgn(hdc, hrgn);
2494 SetRect(&rc_res, -1, -1, -1, -1);
2495 ret = GetClipBox(hdc, &rc_res);
2496 ok(ret == SIMPLEREGION, "got %d\n", ret);
2497 ok(EqualRect(&rc_res, &rc_sclip),
2498 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2499 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2500 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2502 OffsetRect(&rc_sclip, -100, -100);
2503 ret = OffsetClipRgn(hdc, -100, -100);
2504 ok(ret == SIMPLEREGION, "got %d\n", ret);
2505 SetRect(&rc_res, -1, -1, -1, -1);
2506 ret = GetClipBox(hdc, &rc_res);
2507 ok(ret == SIMPLEREGION, "got %d\n", ret);
2508 ok(EqualRect(&rc_res, &rc_sclip),
2509 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2510 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2511 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2513 ret = IntersectClipRect(hdc, 0, 0, 100, 100);
2514 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2515 if (ret == COMPLEXREGION)
2517 /* XP returns COMPLEXREGION although region contains only 1 rect */
2518 ret = GetClipRgn(hdc, hrgn);
2519 ok(ret == 1, "expected 1, got %d\n", ret);
2520 ret = rgn_rect_count(hrgn);
2521 ok(ret == 1, "expected 1, got %d\n", ret);
2523 SetRect(&rc_res, -1, -1, -1, -1);
2524 ret = GetClipBox(hdc, &rc_res);
2525 ok(ret == SIMPLEREGION, "got %d\n", ret);
2526 ok(EqualRect(&rc_res, &rc),
2527 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2528 rc.left, rc.top, rc.right, rc.bottom,
2529 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2531 SetRect(&rc_sclip, 0, 0, 100, 50);
2532 ret = ExcludeClipRect(hdc, 0, 50, 100, 100);
2533 ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION) /* XP */, "got %d\n", ret);
2534 if (ret == COMPLEXREGION)
2536 /* XP returns COMPLEXREGION although region contains only 1 rect */
2537 ret = GetClipRgn(hdc, hrgn);
2538 ok(ret == 1, "expected 1, got %d\n", ret);
2539 ret = rgn_rect_count(hrgn);
2540 ok(ret == 1, "expected 1, got %d\n", ret);
2542 SetRect(&rc_res, -1, -1, -1, -1);
2543 ret = GetClipBox(hdc, &rc_res);
2544 ok(ret == SIMPLEREGION, "got %d\n", ret);
2545 ok(EqualRect(&rc_res, &rc_sclip),
2546 "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
2547 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2548 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2550 hemf = CloseEnhMetaFile(hdc);
2551 DeleteEnhMetaFile(hemf);
2555 static const unsigned char MF_CLIP_BITS[] = {
2557 0x01, 0x00, /* mtType */
2558 0x09, 0x00, /* mtHeaderSize */
2559 0x00, 0x03, /* mtVersion */
2560 0x32, 0x00, 0x00, 0x00, /* mtSize */
2561 0x01, 0x00, /* mtNoObjects */
2562 0x14, 0x00, 0x00, 0x00, /* mtMaxRecord (size in words of longest record) */
2563 0x00, 0x00, /* reserved */
2565 /* METARECORD for CreateRectRgn(0x11, 0x22, 0x33, 0x44) */
2566 0x14, 0x00, 0x00, 0x00, /* rdSize in words */
2567 0xff, 0x06, /* META_CREATEREGION */
2568 0x00, 0x00, 0x06, 0x00, 0xf6, 0x02, 0x00, 0x00,
2569 0x24, 0x00, 0x01, 0x00, 0x02, 0x00, 0x11, 0x00,
2570 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x02, 0x00,
2571 0x22, 0x00, 0x44, 0x00, 0x11, 0x00, 0x33, 0x00,
2574 /* METARECORD for SelectObject */
2575 0x04, 0x00, 0x00, 0x00,
2576 0x2d, 0x01, /* META_SELECTOBJECT (not META_SELECTCLIPREGION?!) */
2580 0x04, 0x00, 0x00, 0x00,
2581 0xf0, 0x01, /* META_DELETEOBJECT */
2584 /* METARECORD for MoveTo(1,0x30) */
2585 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2586 0x14, 0x02, /* META_MOVETO */
2590 /* METARECORD for LineTo(0x20, 0x30) */
2591 0x05, 0x00, 0x00, 0x00, /* rdSize in words */
2592 0x13, 0x02, /* META_LINETO */
2597 0x03, 0x00, 0x00, 0x00,
2601 static int clip_mf_enum_proc_seen_selectclipregion;
2602 static int clip_mf_enum_proc_seen_selectobject;
2604 static int CALLBACK clip_mf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2605 METARECORD *mr, int n_objs, LPARAM param)
2607 switch (mr->rdFunction) {
2608 case META_SELECTCLIPREGION:
2609 clip_mf_enum_proc_seen_selectclipregion++;
2611 case META_SELECTOBJECT:
2612 clip_mf_enum_proc_seen_selectobject++;
2618 static void test_mf_clipping(void)
2620 /* left top right bottom */
2621 static RECT rc_clip = { 0x11, 0x22, 0x33, 0x44 };
2628 SetLastError(0xdeadbeef);
2629 hdc = CreateMetaFileA(NULL);
2630 ok(hdc != 0, "CreateMetaFileA error %d\n", GetLastError());
2632 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2633 ret = SelectClipRgn(hdc, hrgn);
2634 /* Seems like it should be SIMPLEREGION, but windows returns NULLREGION? */
2635 ok(ret == NULLREGION, "expected NULLREGION, got %d\n", ret);
2637 /* Draw a line that starts off left of the clip region and ends inside it */
2638 MoveToEx(hdc, 0x1, 0x30, NULL);
2639 LineTo(hdc, 0x20, 0x30);
2641 SetLastError(0xdeadbeef);
2642 hmf = CloseMetaFile(hdc);
2643 ok(hmf != 0, "CloseMetaFile error %d\n", GetLastError());
2645 if (compare_mf_bits(hmf, MF_CLIP_BITS, sizeof(MF_CLIP_BITS),
2646 "mf_clipping") != 0)
2648 dump_mf_bits(hmf, "mf_clipping");
2653 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2654 0, 0, 200, 200, 0, 0, 0, NULL);
2655 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2659 ret = EnumMetaFile(hdc, hmf, clip_mf_enum_proc, (LPARAM)&rc_clip);
2660 ok(ret, "EnumMetaFile error %d\n", GetLastError());
2662 /* Oddly, windows doesn't seem to use META_SELECTCLIPREGION */
2663 ok(clip_mf_enum_proc_seen_selectclipregion == 0,
2664 "expected 0 selectclipregion, saw %d\n", clip_mf_enum_proc_seen_selectclipregion);
2665 ok(clip_mf_enum_proc_seen_selectobject == 1,
2666 "expected 1 selectobject, saw %d\n", clip_mf_enum_proc_seen_selectobject);
2668 DeleteMetaFile(hmf);
2669 ReleaseDC(hwnd, hdc);
2670 DestroyWindow(hwnd);
2673 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2675 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2676 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2677 /* When using MM_TEXT Win9x does not update the mapping mode
2678 * until a record is played which actually outputs something */
2679 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2680 LPtoDP(hdc, mapping, 2);
2681 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2682 lpEMFR->iType, lpEMFR->nSize,
2683 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2685 if (lpEMFR->iType == EMR_LINETO)
2688 if (!lpMFP || lpMFP->mm == MM_TEXT)
2692 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2693 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2697 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2699 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2700 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2701 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2702 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2704 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2705 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2706 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2712 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2721 hdcMf = CreateMetaFile(NULL);
2722 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2723 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2724 ok(ret, "LineTo failed with error %d\n", GetLastError());
2725 hmf = CloseMetaFile(hdcMf);
2726 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2728 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2730 dump_mf_bits(hmf, "mf_LineTo");
2731 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2734 size = GetMetaFileBitsEx(hmf, 0, NULL);
2735 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2736 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2737 GetMetaFileBitsEx(hmf, size, pBits);
2738 DeleteMetaFile(hmf);
2739 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2740 HeapFree(GetProcessHeap(), 0, pBits);
2744 static void test_mf_conversions(void)
2746 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2748 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2751 RECT rect = { 0, 0, 100, 100 };
2752 mfp.mm = MM_ANISOTROPIC;
2756 hemf = create_converted_emf(&mfp);
2758 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2759 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2761 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2762 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2765 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2767 DeleteEnhMetaFile(hemf);
2768 DeleteDC(hdcOffscreen);
2771 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2773 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2776 RECT rect = { 0, 0, 100, 100 };
2781 hemf = create_converted_emf(&mfp);
2783 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2784 "emf_LineTo MM_TEXT", TRUE) != 0)
2786 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2787 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2790 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2792 DeleteEnhMetaFile(hemf);
2793 DeleteDC(hdcOffscreen);
2796 trace("Testing MF->EMF conversion (NULL mfp)\n");
2798 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2800 RECT rect = { 0, 0, 100, 100 };
2801 hemf = create_converted_emf(NULL);
2803 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2804 "emf_LineTo NULL", TRUE) != 0)
2806 dump_emf_bits(hemf, "emf_LineTo NULL");
2807 dump_emf_records(hemf, "emf_LineTo NULL");
2810 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2812 DeleteEnhMetaFile(hemf);
2813 DeleteDC(hdcOffscreen);
2817 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2818 LONG mm, LONG xExt, LONG yExt,
2819 RECTL * rclBounds, RECTL * rclFrame)
2822 METAFILEPICT * mfpPtr = NULL;
2824 ENHMETAHEADER header;
2835 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2836 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2837 if (!emf) return FALSE;
2838 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2839 ok(res != 0, "GetEnhMetaHeader failed\n");
2840 DeleteEnhMetaFile(emf);
2841 if (!res) return FALSE;
2843 *rclBounds = header.rclBounds;
2844 *rclFrame = header.rclFrame;
2848 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2849 LONG mm, LONG xExt, LONG yExt,
2850 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2852 RECTL rclBounds, rclFrame;
2854 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2861 msg = "mfp == NULL";
2865 const char * mm_str;
2868 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2869 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2870 default: mm_str = "Unexpected";
2872 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2876 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2877 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2878 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2879 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2880 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2881 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2882 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2883 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2887 static void test_SetWinMetaFileBits(void)
2895 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2896 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2897 RECTL rclBounds, rclFrame;
2901 wmfDC = CreateMetaFile(NULL);
2902 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2905 SetWindowExtEx(wmfDC, 100, 100, NULL);
2906 rect.left = rect.top = 0;
2907 rect.right = rect.bottom = 50;
2908 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2909 wmf = CloseMetaFile(wmfDC);
2910 ok(wmf != NULL, "Metafile creation failed\n");
2913 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2914 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2915 if (buffer_size == 0)
2917 DeleteMetaFile(wmf);
2921 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2922 ok(buffer != NULL, "HeapAlloc failed\n");
2925 DeleteMetaFile(wmf);
2929 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2930 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2931 DeleteMetaFile(wmf);
2932 if (res != buffer_size)
2934 HeapFree(GetProcessHeap(), 0, buffer);
2938 /* Get the reference bounds and frame */
2939 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2940 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2942 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2943 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2944 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2946 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2947 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2948 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2949 if (diffx < 0) diffx = -diffx;
2950 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2952 dc = CreateCompatibleDC(NULL);
2954 /* Allow 1 mm difference (rounding errors) */
2955 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2956 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2957 if (diffx < 0) diffx = -diffx;
2958 if (diffy < 0) diffy = -diffy;
2961 ok(diffx <= 1 && diffy <= 1,
2962 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2963 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2966 /* Allow 1 mm difference (rounding errors) */
2967 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2968 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2969 if (diffx < 0) diffx = -diffx;
2970 if (diffy < 0) diffy = -diffy;
2973 ok(diffx <= 1 && diffy <= 1,
2974 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2975 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2979 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2980 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2982 /* If xExt or yExt is zero or negative, the whole device surface is used */
2983 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2984 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2985 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2986 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2987 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2988 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2989 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2990 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2991 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2992 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2993 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2994 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2996 /* MSDN says that negative xExt and yExt values specify a ratio.
2997 Check that this is wrong and the whole device surface is used */
2998 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2999 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
3001 /* Ordinary conversions */
3003 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3005 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3006 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
3007 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
3008 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
3011 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
3013 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
3014 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
3015 ok(rclBounds.left == 0 && rclBounds.top == 0,
3016 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
3018 /* Wine has a rounding error */
3019 diffx = rclBounds.right - rclBounds.bottom;
3020 if (diffx < 0) diffx = -diffx;
3021 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
3024 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
3026 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
3027 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
3030 HeapFree(GetProcessHeap(), 0, buffer);
3033 static BOOL near_match(int x, int y)
3035 int epsilon = min(abs(x), abs(y));
3037 epsilon = max(epsilon/100, 2);
3039 if(x < y - epsilon || x > y + epsilon) return FALSE;
3043 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
3046 HDC display_dc, emf_dc;
3047 ENHMETAHEADER *enh_header;
3048 UINT size, emf_size, i;
3051 METAHEADER *mh = NULL;
3053 INT horz_res, vert_res, horz_size, vert_size;
3054 INT curve_caps, line_caps, poly_caps;
3056 display_dc = GetDC(NULL);
3057 ok(display_dc != NULL, "display_dc is NULL\n");
3059 horz_res = GetDeviceCaps(display_dc, HORZRES);
3060 vert_res = GetDeviceCaps(display_dc, VERTRES);
3061 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
3062 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
3064 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
3065 ok(emf_dc != NULL, "emf_dc is NULL\n");
3067 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
3068 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
3070 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
3071 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
3073 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
3074 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
3076 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
3077 Rectangle(emf_dc, 0, 0, 1000, 20);
3078 emf = CloseEnhMetaFile(emf_dc);
3079 ok(emf != NULL, "emf is NULL\n");
3081 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
3082 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
3083 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
3084 DeleteEnhMetaFile(emf);
3085 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
3086 have different resolutions */
3087 enh_header->szlDevice.cx *= scale;
3088 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
3089 ok(emf != NULL, "emf is NULL\n");
3090 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
3092 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
3094 broken(size == 0), /* some versions of winxp fail for some reason */
3095 "GetWinMetaFileBits returns 0\n");
3097 mh = HeapAlloc(GetProcessHeap(), 0, size);
3098 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
3100 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
3101 ok(check == 0, "check %04x\n", check);
3103 rec = (METARECORD*)(mh + 1);
3105 while(rec->rdSize && rec->rdFunction)
3107 const DWORD chunk_size = 0x2000;
3108 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
3110 if(rec_num < mfcomment_chunks)
3112 DWORD this_chunk_size = chunk_size;
3114 if(rec_num == mfcomment_chunks - 1)
3115 this_chunk_size = emf_size - rec_num * chunk_size;
3117 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
3118 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
3119 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
3120 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
3121 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
3122 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
3123 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
3124 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
3125 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
3126 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
3127 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
3128 /* parm[8] is the checksum, tested above */
3129 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
3130 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
3131 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
3132 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
3133 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
3134 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
3135 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
3136 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 */
3137 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
3138 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
3141 else if(rec_num == mfcomment_chunks)
3143 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
3144 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
3146 else if(rec_num == mfcomment_chunks + 1)
3149 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
3154 case MM_ANISOTROPIC:
3155 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
3156 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
3159 pt.y = MulDiv(-rc->top, 1, 10) + 1;
3160 pt.x = MulDiv( rc->left, 1, 10);
3163 pt.y = -rc->top + 1;
3164 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
3167 pt.y = MulDiv(-rc->top, 10, 254) + 1;
3168 pt.x = MulDiv( rc->left, 10, 254);
3171 pt.y = MulDiv(-rc->top, 100, 254) + 1;
3172 pt.x = MulDiv( rc->left, 100, 254);
3175 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
3176 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3181 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3182 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3184 if(rec_num == mfcomment_chunks + 2)
3186 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3187 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3188 "got %d\n", (short)rec->rdParm[0]);
3189 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3190 "got %d\n", (short)rec->rdParm[1]);
3194 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3198 HeapFree(GetProcessHeap(), 0, mh);
3199 HeapFree(GetProcessHeap(), 0, enh_header);
3200 DeleteEnhMetaFile(emf);
3202 ReleaseDC(NULL, display_dc);
3205 static void test_GetWinMetaFileBits(void)
3210 { 1000, 2000, 3000, 6000},
3211 {-1000, 2000, 3000, 6000},
3212 { 1000, -2000, 3000, 6000},
3213 { 1005, 2005, 3000, 6000},
3214 {-1005, -2005, 3000, 6000},
3215 {-1005, -2010, 3000, 6000},
3216 {-1005, 2010, 3000, 6000},
3222 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3225 trace("mode %d\n", mode);
3227 for(rc = frames; rc->right - rc->left > 0; rc++)
3229 trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
3230 getwinmetafilebits(mode, 1, rc);
3231 getwinmetafilebits(mode, 2, rc);
3236 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3237 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3238 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3240 static void test_gdiis(void)
3242 RECT rect = {0,0,100,100};
3243 HDC hdc, hemfDC, hmfDC;
3247 /* resolve all the functions */
3248 hgdi32 = GetModuleHandle("gdi32");
3249 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3250 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3251 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3253 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3255 win_skip("Needed GdiIs* functions are not available\n");
3259 /* try with nothing */
3260 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3261 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3262 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3264 /* try with a metafile */
3265 hmfDC = CreateMetaFile(NULL);
3266 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3267 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3268 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3269 DeleteMetaFile(CloseMetaFile(hmfDC));
3271 /* try with an enhanced metafile */
3273 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3274 ok(hemfDC != NULL, "failed to create emf\n");
3276 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3277 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3278 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3280 hemf = CloseEnhMetaFile(hemfDC);
3281 ok(hemf != NULL, "failed to close EMF\n");
3282 DeleteEnhMetaFile(hemf);
3283 ReleaseDC(NULL,hdc);
3286 static void test_SetEnhMetaFileBits(void)
3292 memset(data, 0xAA, sizeof(data));
3293 SetLastError(0xdeadbeef);
3294 hemf = SetEnhMetaFileBits(sizeof(data), data);
3295 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3296 ok(GetLastError() == ERROR_INVALID_DATA ||
3297 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3298 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3300 emh = (ENHMETAHEADER *)data;
3301 memset(emh, 0, sizeof(*emh));
3303 emh->iType = EMR_HEADER;
3304 emh->nSize = sizeof(*emh);
3305 emh->dSignature = ENHMETA_SIGNATURE;
3306 /* emh->nVersion = 0x10000; XP doesn't care about version */
3307 emh->nBytes = sizeof(*emh);
3308 /* emh->nRecords = 1; XP doesn't care about records */
3309 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3311 SetLastError(0xdeadbeef);
3312 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3313 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3314 DeleteEnhMetaFile(hemf);
3316 /* XP refuses to load unaligned EMF */
3318 SetLastError(0xdeadbeef);
3319 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3321 broken(hemf != NULL), /* Win9x, WinMe */
3322 "SetEnhMetaFileBits should fail\n");
3323 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3324 DeleteEnhMetaFile(hemf);
3326 emh->dSignature = 0;
3328 SetLastError(0xdeadbeef);
3329 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3331 broken(hemf != NULL), /* Win9x, WinMe */
3332 "SetEnhMetaFileBits should fail\n");
3333 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3334 DeleteEnhMetaFile(hemf);
3337 static void test_emf_polybezier(void)
3344 SetLastError(0xdeadbeef);
3345 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3346 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3348 pts[0].x = pts[0].y = 10;
3349 pts[1].x = pts[1].y = 20;
3350 pts[2].x = pts[2].y = 15;
3351 pts[3].x = pts[3].y = 25;
3352 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3353 ok( ret, "PolyBezierTo failed\n" );
3354 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3355 ok( ret, "PolyBezier failed\n" );
3357 pts[0].x = pts[0].y = 32769;
3358 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3359 ok( ret, "PolyBezier failed\n" );
3360 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3361 ok( ret, "PolyBezierTo failed\n" );
3363 hemf = CloseEnhMetaFile(hdcMetafile);
3364 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3366 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3367 "emf_Bezier", FALSE) != 0)
3369 dump_emf_bits(hemf, "emf_Bezier");
3370 dump_emf_records(hemf, "emf_Bezier");
3373 DeleteEnhMetaFile(hemf);
3376 START_TEST(metafile)
3378 init_function_pointers();
3380 /* For enhanced metafiles (enhmfdrv) */
3382 test_ExtTextOutScale();
3386 test_emf_ExtTextOut_on_path();
3387 test_emf_clipping();
3388 test_emf_polybezier();
3390 /* For win-format metafiles (mfdrv) */
3394 test_mf_PatternBrush();
3396 test_CopyMetaFile();
3397 test_SetMetaFileBits();
3398 test_mf_ExtTextOut_on_path();
3401 /* For metafile conversions */
3402 test_mf_conversions();
3403 test_SetWinMetaFileBits();
3404 test_GetWinMetaFileBits();
3407 test_SetEnhMetaFileBits();