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 int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
64 const ENHMETARECORD *emr, int n_objs, LPARAM param)
69 INT *orig_dx = (INT *)param;
73 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
74 hdc, emr->iType, emr->nSize, (void *)param);
78 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
83 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
84 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
85 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
86 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
87 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
88 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
89 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
91 /* GetBkMode, GetRelAbs do not get reset to the default value */
92 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
93 if(pSetRelAbs && pGetRelAbs)
94 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
101 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
102 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
104 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
105 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
107 /* compare up to lfOutPrecision, other values are not interesting,
108 * and in fact sometimes arbitrary adapted by Win9x.
110 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
111 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
113 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
115 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
116 n_record, i, dx[i], orig_dx[i]);
119 emr_processed = TRUE;
123 case EMR_EXTTEXTOUTW:
125 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
126 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
128 SetLastError(0xdeadbeef);
129 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
130 ok( ret == sizeof(device_lf) ||
131 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
132 "GetObjectA error %d\n", GetLastError());
134 /* compare up to lfOutPrecision, other values are not interesting,
135 * and in fact sometimes arbitrary adapted by Win9x.
137 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
138 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
140 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
142 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
143 n_record, i, dx[i], orig_dx[i]);
146 emr_processed = TRUE;
157 static void test_ExtTextOut(void)
160 HDC hdcDisplay, hdcMetafile;
161 HENHMETAFILE hMetafile;
163 static const char text[] = "Simple text to test ExtTextOut on metafiles";
165 static const RECT rc = { 0, 0, 100, 100 };
168 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
170 /* Win9x doesn't play EMFs on invisible windows */
171 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
172 0, 0, 200, 200, 0, 0, 0, NULL);
173 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
175 hdcDisplay = GetDC(hwnd);
176 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
178 trace("hdcDisplay %p\n", hdcDisplay);
180 SetMapMode(hdcDisplay, MM_TEXT);
182 memset(&orig_lf, 0, sizeof(orig_lf));
184 orig_lf.lfCharSet = ANSI_CHARSET;
185 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
186 orig_lf.lfWeight = FW_DONTCARE;
187 orig_lf.lfHeight = 7;
188 orig_lf.lfQuality = DEFAULT_QUALITY;
189 lstrcpyA(orig_lf.lfFaceName, "Arial");
190 hFont = CreateFontIndirectA(&orig_lf);
191 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
193 hFont = SelectObject(hdcDisplay, hFont);
195 len = lstrlenA(text);
196 for (i = 0; i < len; i++)
198 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
199 ok( ret, "GetCharWidthA error %d\n", GetLastError());
201 hFont = SelectObject(hdcDisplay, hFont);
203 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
204 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
206 trace("hdcMetafile %p\n", hdcMetafile);
208 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
209 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
211 hFont = SelectObject(hdcMetafile, hFont);
213 /* 1. pass NULL lpDx */
214 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
215 ok( ret, "ExtTextOutA error %d\n", GetLastError());
217 /* 2. pass custom lpDx */
218 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
219 ok( ret, "ExtTextOutA error %d\n", GetLastError());
221 hFont = SelectObject(hdcMetafile, hFont);
222 ret = DeleteObject(hFont);
223 ok( ret, "DeleteObject error %d\n", GetLastError());
225 hMetafile = CloseEnhMetaFile(hdcMetafile);
226 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
228 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
230 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
231 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
233 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
234 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
235 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
236 SetROP2(hdcDisplay, R2_NOT);
237 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
238 SetPolyFillMode(hdcDisplay, WINDING);
239 SetStretchBltMode(hdcDisplay, HALFTONE);
241 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
242 SetBkMode(hdcDisplay, OPAQUE);
244 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
245 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
247 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
248 "text align %08x\n", GetTextAlign(hdcDisplay));
249 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
250 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
251 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
252 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
253 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
254 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
256 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
258 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
259 "A valid hdc has to require a valid rc\n");
261 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
262 "A null hdc does not require a valid rc\n");
264 ret = DeleteEnhMetaFile(hMetafile);
265 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
266 ret = ReleaseDC(hwnd, hdcDisplay);
267 ok( ret, "ReleaseDC error %d\n", GetLastError());
271 struct eto_scale_test_record
280 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
281 const ENHMETARECORD *emr, int n_objs, LPARAM param)
283 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
285 if (emr->iType == EMR_EXTTEXTOUTW)
287 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
288 trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
289 test->graphics_mode, test->map_mode,
290 pExtTextOutW->exScale, pExtTextOutW->eyScale,
291 test->ex_scale, test->ey_scale);
292 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
293 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
294 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
295 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
296 test->processed = TRUE;
302 static void test_ExtTextOutScale(void)
304 const RECT rc = { 0, 0, 100, 100 };
305 const WCHAR str[] = {'a',0 };
306 struct eto_scale_test_record test;
307 HDC hdcDisplay, hdcMetafile;
308 HENHMETAFILE hMetafile;
310 SIZE wndext, vportext;
311 int horzSize, vertSize, horzRes, vertRes;
315 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
316 0, 0, 200, 200, 0, 0, 0, NULL);
317 ok(hwnd != 0, "CreateWindowExA failed\n");
319 hdcDisplay = GetDC(hwnd);
320 ok(hdcDisplay != 0, "GetDC failed\n");
322 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
323 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
324 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
325 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
326 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
328 for (i = 0; i < 16; i++)
330 test.graphics_mode = i / 8 + 1;
331 test.map_mode = i % 8 + 1;
333 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
334 ok(ret, "SetGraphicsMode failed\n");
335 ret = SetMapMode(hdcDisplay, test.map_mode);
336 ok(ret, "SetMapMode failed\n");
338 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
340 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
341 ok(ret, "SetWindowExtEx failed\n");
342 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
343 ok(ret, "SetViewportExtEx failed\n");
346 ret = GetViewportExtEx(hdcDisplay, &vportext);
347 ok(ret, "GetViewportExtEx failed\n");
348 ret = GetWindowExtEx(hdcDisplay, &wndext);
349 ok(ret, "GetWindowExtEx failed\n");
351 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
352 test.graphics_mode, test.map_mode,
353 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
354 horzSize, horzRes, vertSize, vertRes);
356 if (test.graphics_mode == GM_COMPATIBLE)
358 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
359 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
360 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
361 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
369 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
370 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
372 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
373 ok(ret, "SetGraphicsMode failed\n");
374 ret = SetMapMode(hdcMetafile, test.map_mode);
375 ok(ret, "SetMapMode failed\n");
377 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
379 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
380 ok(ret, "SetWindowExtEx failed\n");
381 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
382 ok(ret, "SetViewportExtEx failed\n");
385 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
386 ok(ret, "ExtTextOutW failed\n");
388 hMetafile = CloseEnhMetaFile(hdcMetafile);
389 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
392 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
393 ok(ret, "EnumEnhMetaFile failed\n");
394 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
396 ret = DeleteEnhMetaFile(hMetafile);
397 ok(ret, "DeleteEnhMetaFile failed\n");
400 ret = ReleaseDC(hwnd, hdcDisplay);
401 ok(ret, "ReleaseDC failed\n");
406 static void check_dc_state(HDC hdc, int restore_no,
407 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
408 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
412 POINT vp_org, win_org;
413 SIZE vp_size, win_size;
414 FLOAT xscale, yscale, edx, edy;
416 SetLastError(0xdeadbeef);
417 ret = GetWorldTransform(hdc, &xform);
418 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
419 ok(ret, "GetWorldTransform error %u\n", GetLastError());
421 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
423 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
424 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
426 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
427 trace("x scale %f\n", xscale);
428 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
429 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
431 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
432 trace("y scale %f\n", yscale);
433 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
434 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
436 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
437 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
438 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
439 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
445 GetWindowOrgEx(hdc, &win_org);
446 GetViewportOrgEx(hdc, &vp_org);
447 GetWindowExtEx(hdc, &win_size);
448 GetViewportExtEx(hdc, &vp_size);
450 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
451 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
453 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
454 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
456 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
457 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
459 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
460 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
463 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
464 const ENHMETARECORD *emr, int n_objs, LPARAM param)
470 static int save_state;
471 static int restore_no;
472 static int select_no;
474 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
475 hdc, emr->iType, emr->nSize, (void *)param);
478 SetLastError(0xdeadbeef);
479 ret = GetWorldTransform(hdc, &xform);
480 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
482 ret = GetWindowOrgEx(hdc, &pt);
483 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
484 trace("window org (%d,%d)\n", pt.x, pt.y);
485 ret = GetViewportOrgEx(hdc, &pt);
486 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
487 trace("vport org (%d,%d)\n", pt.x, pt.y);
488 ret = GetWindowExtEx(hdc, &size);
489 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
490 trace("window ext (%d,%d)\n", size.cx, size.cy);
491 ret = GetViewportExtEx(hdc, &size);
492 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
493 trace("vport ext (%d,%d)\n", size.cx, size.cy);
497 ok(ret, "GetWorldTransform error %u\n", GetLastError());
498 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
501 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
507 static RECT exp_bounds = { 0, 0, 150, 150 };
509 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
511 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
512 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
513 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
514 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
515 emf->szlDevice.cx, emf->szlDevice.cy);
517 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
518 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
523 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
529 const EMRLINETO *line = (const EMRLINETO *)emr;
530 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
533 case EMR_SETWINDOWORGEX:
535 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
536 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
539 case EMR_SETWINDOWEXTEX:
541 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
542 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
545 case EMR_SETVIEWPORTORGEX:
547 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
548 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
551 case EMR_SETVIEWPORTEXTEX:
553 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
554 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
559 trace("EMR_SAVEDC\n");
564 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
565 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
570 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
571 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
574 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
575 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
578 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
579 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
582 ok(restore_no <= 3, "restore_no %d\n", restore_no);
583 save_state += restoredc->iRelative;
586 case EMR_SELECTOBJECT:
588 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
589 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
594 ok(save_state == 0, "EOF save_state %d\n", save_state);
595 ok(select_no == 3, "Too many/few selects %i\n",select_no);
600 SetLastError(0xdeadbeef);
601 ret = GetWorldTransform(hdc, &xform);
602 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
604 ret = GetWindowOrgEx(hdc, &pt);
605 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
606 trace("window org (%d,%d)\n", pt.x, pt.y);
607 ret = GetViewportOrgEx(hdc, &pt);
608 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
609 trace("vport org (%d,%d)\n", pt.x, pt.y);
610 ret = GetWindowExtEx(hdc, &size);
611 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
612 trace("window ext (%d,%d)\n", size.cx, size.cy);
613 ret = GetViewportExtEx(hdc, &size);
614 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
615 trace("vport ext (%d,%d)\n", size.cx, size.cy);
619 ok(ret, "GetWorldTransform error %u\n", GetLastError());
620 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
626 static void test_SaveDC(void)
628 HDC hdcMetafile, hdcDisplay;
629 HENHMETAFILE hMetafile;
634 HFONT hFont,hFont2,hFontOld,hFontCheck;
635 static const RECT rc = { 0, 0, 150, 150 };
637 /* Win9x doesn't play EMFs on invisible windows */
638 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
639 0, 0, 200, 200, 0, 0, 0, NULL);
640 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
642 hdcDisplay = GetDC(hwnd);
643 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
645 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
646 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
648 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
650 /* Need to write something to the emf, otherwise Windows won't play it back */
651 LineTo(hdcMetafile, 150, 150);
653 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
654 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
655 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
656 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
658 /* Force Win9x to update DC state */
659 SetPixelV(hdcMetafile, 50, 50, 0);
661 ret = GetViewportOrgEx(hdcMetafile, &pt);
662 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
663 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
664 ret = GetViewportExtEx(hdcMetafile, &size);
665 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
666 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
667 ret = SaveDC(hdcMetafile);
668 ok(ret == 1, "ret = %d\n", ret);
670 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
671 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
672 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
673 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
675 /* Force Win9x to update DC state */
676 SetPixelV(hdcMetafile, 50, 50, 0);
678 ret = GetViewportOrgEx(hdcMetafile, &pt);
679 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
680 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
681 ret = GetViewportExtEx(hdcMetafile, &size);
682 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
683 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
684 ret = SaveDC(hdcMetafile);
685 ok(ret == 2, "ret = %d\n", ret);
687 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
688 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
689 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
690 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
691 SetPolyFillMode( hdcMetafile, ALTERNATE );
692 SetBkColor( hdcMetafile, 0 );
694 /* Force Win9x to update DC state */
695 SetPixelV(hdcMetafile, 50, 50, 0);
697 ret = GetViewportOrgEx(hdcMetafile, &pt);
698 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
699 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
700 ret = GetViewportExtEx(hdcMetafile, &size);
701 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
702 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
703 ret = SaveDC(hdcMetafile);
704 ok(ret == 3, "ret = %d\n", ret);
706 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
707 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
708 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
709 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
711 SetPolyFillMode( hdcMetafile, WINDING );
712 SetBkColor( hdcMetafile, 0x123456 );
713 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
714 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
716 /* Force Win9x to update DC state */
717 SetPixelV(hdcMetafile, 50, 50, 0);
719 ret = GetViewportOrgEx(hdcMetafile, &pt);
720 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
721 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
722 ret = GetViewportExtEx(hdcMetafile, &size);
723 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
724 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
725 ret = RestoreDC(hdcMetafile, -1);
726 ok(ret, "ret = %d\n", ret);
728 ret = GetViewportOrgEx(hdcMetafile, &pt);
729 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
730 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
731 ret = GetViewportExtEx(hdcMetafile, &size);
732 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
733 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
734 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
735 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
736 ret = SaveDC(hdcMetafile);
737 ok(ret == 3, "ret = %d\n", ret);
739 ret = GetViewportOrgEx(hdcMetafile, &pt);
740 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
741 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
742 ret = GetViewportExtEx(hdcMetafile, &size);
743 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
744 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
745 ret = RestoreDC(hdcMetafile, 1);
746 ok(ret, "ret = %d\n", ret);
747 ret = GetViewportOrgEx(hdcMetafile, &pt);
748 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
749 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
750 ret = GetViewportExtEx(hdcMetafile, &size);
751 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
752 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
754 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
755 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
756 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
757 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
759 /* Force Win9x to update DC state */
760 SetPixelV(hdcMetafile, 50, 50, 0);
762 ret = GetViewportOrgEx(hdcMetafile, &pt);
763 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
764 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
765 ret = GetViewportExtEx(hdcMetafile, &size);
766 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
767 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
768 ret = SaveDC(hdcMetafile);
769 ok(ret == 1, "ret = %d\n", ret);
771 ret = GetViewportOrgEx(hdcMetafile, &pt);
772 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
773 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
774 ret = GetViewportExtEx(hdcMetafile, &size);
775 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
776 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
777 ret = SaveDC(hdcMetafile);
778 ok(ret == 2, "ret = %d\n", ret);
780 memset(&orig_lf, 0, sizeof(orig_lf));
781 orig_lf.lfCharSet = ANSI_CHARSET;
782 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
783 orig_lf.lfWeight = FW_DONTCARE;
784 orig_lf.lfHeight = 7;
785 orig_lf.lfQuality = DEFAULT_QUALITY;
786 lstrcpyA(orig_lf.lfFaceName, "Arial");
787 hFont = CreateFontIndirectA(&orig_lf);
788 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
790 hFontOld = SelectObject(hdcMetafile, hFont);
792 hFont2 = CreateFontIndirectA(&orig_lf);
793 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
794 hFontCheck = SelectObject(hdcMetafile, hFont2);
795 ok(hFontCheck == hFont, "Font not selected\n");
797 /* Force Win9x to update DC state */
798 SetPixelV(hdcMetafile, 50, 50, 0);
800 ret = RestoreDC(hdcMetafile, 1);
801 ok(ret, "ret = %d\n", ret);
802 ret = GetViewportOrgEx(hdcMetafile, &pt);
803 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
804 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
805 ret = GetViewportExtEx(hdcMetafile, &size);
806 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
807 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
809 hFontCheck = SelectObject(hdcMetafile, hFontOld);
810 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
811 "Font not reverted with DC Restore\n");
813 ret = RestoreDC(hdcMetafile, -20);
814 ok(!ret, "ret = %d\n", ret);
815 ret = RestoreDC(hdcMetafile, 20);
816 ok(!ret, "ret = %d\n", ret);
818 hMetafile = CloseEnhMetaFile(hdcMetafile);
819 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
821 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
822 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
824 ret = DeleteObject(hFont);
825 ok( ret, "DeleteObject error %d\n", GetLastError());
826 ret = DeleteObject(hFont2);
827 ok( ret, "DeleteObject error %d\n", GetLastError());
828 ret = DeleteEnhMetaFile(hMetafile);
829 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
830 ret = ReleaseDC(hwnd, hdcDisplay);
831 ok( ret, "ReleaseDC error %d\n", GetLastError());
835 static void test_mf_SaveDC(void)
842 HFONT hFont,hFont2,hFontOld,hFontCheck;
844 hdcMetafile = CreateMetaFileA(NULL);
845 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
847 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
848 ok (ret, "SetMapMode should not fail\n");
850 /* Need to write something to the emf, otherwise Windows won't play it back */
851 LineTo(hdcMetafile, 150, 150);
854 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
855 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
857 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
858 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
859 size.cx = size.cy = 5555;
860 SetWindowExtEx(hdcMetafile, 110, 110, &size );
861 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
862 size.cx = size.cy = 5555;
863 SetViewportExtEx(hdcMetafile, 120, 120, &size );
864 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
866 /* Force Win9x to update DC state */
867 SetPixelV(hdcMetafile, 50, 50, 0);
869 ret = GetViewportOrgEx(hdcMetafile, &pt);
870 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
871 ret = GetViewportExtEx(hdcMetafile, &size);
872 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
873 ret = SaveDC(hdcMetafile);
874 ok(ret == 1, "ret = %d\n", ret);
876 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
877 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
878 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
879 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
881 /* Force Win9x to update DC state */
882 SetPixelV(hdcMetafile, 50, 50, 0);
884 ret = SaveDC(hdcMetafile);
885 ok(ret == 1, "ret = %d\n", ret);
887 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
888 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
889 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
890 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
892 /* Force Win9x to update DC state */
893 SetPixelV(hdcMetafile, 50, 50, 0);
894 SetPolyFillMode( hdcMetafile, ALTERNATE );
895 SetBkColor( hdcMetafile, 0 );
897 ret = SaveDC(hdcMetafile);
898 ok(ret == 1, "ret = %d\n", ret);
900 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
901 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
902 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
903 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
905 SetPolyFillMode( hdcMetafile, WINDING );
906 SetBkColor( hdcMetafile, 0x123456 );
907 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
908 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
910 /* Force Win9x to update DC state */
911 SetPixelV(hdcMetafile, 50, 50, 0);
913 ret = RestoreDC(hdcMetafile, -1);
914 ok(ret, "ret = %d\n", ret);
916 ret = SaveDC(hdcMetafile);
917 ok(ret == 1, "ret = %d\n", ret);
919 ret = RestoreDC(hdcMetafile, 1);
920 ok(ret, "ret = %d\n", ret);
922 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
923 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
924 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
925 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
927 /* Force Win9x to update DC state */
928 SetPixelV(hdcMetafile, 50, 50, 0);
930 ret = SaveDC(hdcMetafile);
931 ok(ret == 1, "ret = %d\n", ret);
933 ret = SaveDC(hdcMetafile);
934 ok(ret == 1, "ret = %d\n", ret);
936 memset(&orig_lf, 0, sizeof(orig_lf));
937 orig_lf.lfCharSet = ANSI_CHARSET;
938 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
939 orig_lf.lfWeight = FW_DONTCARE;
940 orig_lf.lfHeight = 7;
941 orig_lf.lfQuality = DEFAULT_QUALITY;
942 lstrcpyA(orig_lf.lfFaceName, "Arial");
943 hFont = CreateFontIndirectA(&orig_lf);
944 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
946 hFontOld = SelectObject(hdcMetafile, hFont);
948 hFont2 = CreateFontIndirectA(&orig_lf);
949 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
950 hFontCheck = SelectObject(hdcMetafile, hFont2);
951 ok(hFontCheck == hFont, "Font not selected\n");
953 /* Force Win9x to update DC state */
954 SetPixelV(hdcMetafile, 50, 50, 0);
956 ret = RestoreDC(hdcMetafile, 1);
957 ok(ret, "ret = %d\n", ret);
959 hFontCheck = SelectObject(hdcMetafile, hFontOld);
960 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
962 /* restore level is ignored */
963 ret = RestoreDC(hdcMetafile, -20);
964 ok(ret, "ret = %d\n", ret);
965 ret = RestoreDC(hdcMetafile, 20);
966 ok(ret, "ret = %d\n", ret);
967 ret = RestoreDC(hdcMetafile, 0);
968 ok(ret, "ret = %d\n", ret);
970 hMetafile = CloseMetaFile(hdcMetafile);
971 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
973 ret = DeleteMetaFile(hMetafile);
974 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
975 ret = DeleteObject(hFont);
976 ok( ret, "DeleteObject error %d\n", GetLastError());
977 ret = DeleteObject(hFont2);
978 ok( ret, "DeleteObject error %d\n", GetLastError());
982 /* Win-format metafile (mfdrv) tests */
983 /* These tests compare the generated metafiles byte-by-byte */
984 /* with the nominal results. */
986 /* Maximum size of sample metafiles in bytes. */
987 #define MF_BUFSIZE 512
989 /* 8x8 bitmap data for a pattern brush */
990 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
991 0x01, 0x00, 0x02, 0x00,
992 0x03, 0x00, 0x04, 0x00,
993 0x05, 0x00, 0x06, 0x00,
994 0x07, 0x00, 0x08, 0x00
997 /* Sample metafiles to be compared to the outputs of the
1001 static const unsigned char MF_BLANK_BITS[] = {
1002 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1003 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1004 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1007 static const unsigned char MF_GRAPHICS_BITS[] = {
1008 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1009 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1010 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1011 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1012 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1013 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1014 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1015 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1016 0x00, 0x00, 0x00, 0x00
1019 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1020 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1021 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1023 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1024 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1025 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1026 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1029 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1030 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1031 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1032 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1033 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1034 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1038 static const unsigned char MF_DCBRUSH_BITS[] =
1040 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1041 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1043 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1044 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1045 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1048 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1049 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1050 0x00, 0x00, 0x00, 0x00
1053 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1055 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1056 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1057 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1058 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1059 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1060 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1064 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1066 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1071 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1072 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1073 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1076 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1078 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1079 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1080 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1081 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1082 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1083 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1084 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1085 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1086 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1089 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1090 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1091 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1092 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1093 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1094 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1095 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1096 0x14, 0x00, 0x00, 0x00
1099 static const unsigned char MF_LINETO_BITS[] = {
1100 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1101 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1102 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1103 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1107 static const unsigned char EMF_LINETO_BITS[] = {
1108 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1113 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1114 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1115 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1117 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1118 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1121 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1122 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1123 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1124 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1125 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1126 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1128 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1129 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1130 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1131 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1132 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1133 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1134 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1135 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1136 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1137 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1138 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1139 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1140 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1141 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1142 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1143 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1144 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1145 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1146 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1149 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1150 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1152 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1154 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1155 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1156 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1157 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1160 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1163 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1164 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1165 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1166 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1167 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1168 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1169 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1170 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1171 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1173 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1174 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1175 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1176 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1177 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1178 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1179 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1180 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1181 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1182 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1183 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1184 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1185 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1187 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1191 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1192 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1194 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1196 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1197 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1198 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1199 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1202 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1205 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1206 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1207 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1208 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1209 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1210 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1211 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1212 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1213 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1214 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1215 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1216 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1218 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1220 0x14, 0x00, 0x00, 0x00
1223 static const unsigned char EMF_BITBLT[] =
1225 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1227 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1229 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
1230 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1231 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1232 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234 0x23, 0x04, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00,
1235 0x75, 0x01, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0x05, 0x00,
1238 0x28, 0x11, 0x03, 0x00, 0x4c, 0x00, 0x00, 0x00,
1239 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1241 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1243 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1249 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1250 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1251 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1252 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1253 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1262 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1264 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1267 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270 0x00, 0x00, 0x80, 0x3f, 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, 0x0e, 0x00, 0x00, 0x00,
1275 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1279 static const unsigned char EMF_DCBRUSH_BITS[] =
1281 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1282 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1283 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1284 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1285 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1286 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1287 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1288 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1291 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1294 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1295 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1296 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1297 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1298 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1299 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1301 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1302 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1303 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1305 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1306 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1307 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1308 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1309 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1310 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1311 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1312 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1315 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1316 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1317 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1318 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1319 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1320 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1321 0x14, 0x00, 0x00, 0x00
1324 static const unsigned char EMF_BEZIER_BITS[] =
1326 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1328 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1330 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1331 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1332 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1333 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1336 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1338 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1339 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1340 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1342 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1343 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1344 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1345 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1346 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1347 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1348 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1349 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1350 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1351 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1352 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1353 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1354 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1355 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1356 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1357 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1358 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1359 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1360 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1361 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1362 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1363 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1364 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1365 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1366 0x14, 0x00, 0x00, 0x00
1369 /* For debugging or dumping the raw metafiles produced by
1370 * new test functions.
1372 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1373 INT nobj, LPARAM param)
1375 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1376 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1380 /* For debugging or dumping the raw metafiles produced by
1381 * new test functions.
1384 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1386 BYTE buf[MF_BUFSIZE];
1389 if (!winetest_debug) return;
1391 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1392 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1394 printf ("MetaFile %s has bits:\n{\n ", desc);
1395 for (i=0; i<mfsize; i++)
1397 printf ("0x%02x", buf[i]);
1400 else if (i % 8 == 7)
1408 /* Compare the metafile produced by a test function with the
1409 * expected raw metafile data in "bits".
1410 * Return value is 0 for a perfect match,
1411 * -1 if lengths aren't equal,
1412 * otherwise returns the number of non-matching bytes.
1415 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1418 unsigned char buf[MF_BUFSIZE];
1422 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1423 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1424 if (mfsize < MF_BUFSIZE)
1425 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1426 desc, mfsize, bsize);
1428 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1429 desc, mfsize, bsize);
1430 if (mfsize != bsize)
1434 for (i=0; i<bsize; i++)
1436 if (buf[i] != bits[i])
1439 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1440 desc, mfsize, bsize, diff);
1445 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1447 unsigned char buf[MF_BUFSIZE];
1448 DWORD mfsize, rd_size, i;
1453 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1454 assert(hfile != INVALID_HANDLE_VALUE);
1456 mfsize = GetFileSize(hfile, NULL);
1457 assert(mfsize <= MF_BUFSIZE);
1459 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1460 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1464 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1466 if (mfsize != bsize)
1470 for (i=0; i<bsize; i++)
1472 if (buf[i] != bits[i])
1475 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1476 desc, mfsize, bsize, diff);
1481 /* For debugging or dumping the raw EMFs produced by
1482 * new test functions.
1484 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1486 BYTE buf[MF_BUFSIZE];
1489 if (!winetest_debug) return;
1491 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1492 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1494 printf("EMF %s has bits:\n{\n ", desc);
1495 for (i = 0; i < mfsize; i++)
1497 printf ("0x%02x", buf[i]);
1500 else if (i % 8 == 7)
1508 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1511 BYTE buf[MF_BUFSIZE];
1512 UINT mfsize, offset;
1514 if (!winetest_debug) return;
1516 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1517 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1519 printf("EMF %s has records:\n", desc);
1523 while(offset < mfsize)
1525 EMR *emr = (EMR *)(emf + offset);
1526 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1527 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1528 offset += emr->nSize;
1532 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1537 if (!winetest_debug) return;
1539 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1540 buf = (const BYTE *)emr;
1541 for (i = 0; i < emr->nSize; i++)
1543 printf ("0x%02x", buf[i]);
1544 if (i == emr->nSize - 1)
1546 else if (i % 8 == 7)
1554 static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1556 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1557 eto->rclBounds.right, eto->rclBounds.bottom);
1558 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1559 trace("exScale: %f\n", eto->exScale);
1560 trace("eyScale: %f\n", eto->eyScale);
1561 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1562 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1563 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1564 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1565 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1566 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1567 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1570 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1571 const char *desc, BOOL ignore_scaling)
1575 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1576 desc, emr1->iType, emr2->iType);
1578 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1579 desc, emr1->nSize, emr2->nSize);
1581 /* iType and nSize mismatches are fatal */
1582 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1584 /* contents of EMR_GDICOMMENT are not interesting */
1585 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1587 /* different Windows versions setup DC scaling differently when
1588 * converting an old style metafile to an EMF.
1590 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1591 emr1->iType == EMR_SETVIEWPORTEXTEX))
1594 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1596 EMREXTTEXTOUTW *eto1, *eto2;
1598 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1599 memcpy(eto1, emr1, emr1->nSize);
1600 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1601 memcpy(eto2, emr2, emr2->nSize);
1603 /* different Windows versions setup DC scaling differently */
1604 eto1->exScale = eto1->eyScale = 0.0;
1605 eto2->exScale = eto2->eyScale = 0.0;
1607 diff = memcmp(eto1, eto2, emr1->nSize);
1610 dump_EMREXTTEXTOUT(eto1);
1611 dump_EMREXTTEXTOUT(eto2);
1613 HeapFree(GetProcessHeap(), 0, eto1);
1614 HeapFree(GetProcessHeap(), 0, eto2);
1616 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1618 /* We have to take care of NT4 differences here */
1619 diff = memcmp(emr1, emr2, emr1->nSize);
1622 ENHMETARECORD *emr_nt4;
1624 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1625 memcpy(emr_nt4, emr2, emr2->nSize);
1626 /* Correct the nRgnSize field */
1627 emr_nt4->dParm[5] = sizeof(RECT);
1629 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1631 win_skip("Catered for NT4 differences\n");
1633 HeapFree(GetProcessHeap(), 0, emr_nt4);
1636 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1638 EMRPOLYBEZIER16 *eto1, *eto2;
1640 eto1 = (EMRPOLYBEZIER16*)emr1;
1641 eto2 = (EMRPOLYBEZIER16*)emr2;
1643 diff = eto1->cpts != eto1->cpts;
1645 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1647 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1649 EMRPOLYBEZIER *eto1, *eto2;
1651 eto1 = (EMRPOLYBEZIER*)emr1;
1652 eto2 = (EMRPOLYBEZIER*)emr2;
1654 diff = eto1->cptl != eto1->cptl;
1656 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1659 diff = memcmp(emr1, emr2, emr1->nSize);
1661 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1665 dump_emf_record(emr1, "expected bits");
1666 dump_emf_record(emr2, "actual bits");
1669 return diff == 0; /* report all non-fatal record mismatches */
1672 /* Compare the EMF produced by a test function with the
1673 * expected raw EMF data in "bits".
1674 * Return value is 0 for a perfect match,
1675 * -1 if lengths aren't equal,
1676 * otherwise returns the number of non-matching bytes.
1678 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1679 UINT bsize, const char *desc,
1680 BOOL ignore_scaling)
1682 unsigned char buf[MF_BUFSIZE];
1683 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1684 const ENHMETAHEADER *emh1, *emh2;
1686 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1687 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1689 /* ENHMETAHEADER size could differ, depending on platform */
1690 diff_nt4 = sizeof(SIZEL);
1691 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1693 if (mfsize < MF_BUFSIZE)
1695 ok(mfsize == bsize ||
1696 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1697 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1698 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1701 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1702 desc, mfsize, bsize);
1704 /* basic things must match */
1705 emh1 = (const ENHMETAHEADER *)bits;
1706 emh2 = (const ENHMETAHEADER *)buf;
1707 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1708 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1709 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1710 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1712 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1713 ok(emh1->nSize == emh2->nSize ||
1714 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1715 broken(emh1->nSize - diff_9x == emh2->nSize),
1716 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1717 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1718 ok(emh1->nBytes == emh2->nBytes ||
1719 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1720 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1721 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1722 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1724 offset1 = emh1->nSize;
1725 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1726 while (offset1 < emh1->nBytes)
1728 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1729 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1731 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1732 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1734 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1736 /* We have already bailed out if iType or nSize don't match */
1737 offset1 += emr1->nSize;
1738 offset2 += emr2->nSize;
1744 /* tests blitting to an EMF */
1745 static void test_emf_BitBlt(void)
1747 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1748 HBITMAP hBitmap, hOldBitmap;
1749 HENHMETAFILE hMetafile;
1751 BITMAPINFOHEADER bmih =
1753 sizeof(BITMAPINFOHEADER),
1754 BMP_DIM,/* biWidth */
1755 BMP_DIM,/* biHeight */
1757 24, /* biBitCount */
1758 BI_RGB, /* biCompression */
1759 0, /* biXPelsPerMeter */
1760 0, /* biYPelsPerMeter */
1762 0, /* biClrImportant */
1767 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1768 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1770 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1771 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1772 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1773 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1774 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1775 DIB_RGB_COLORS, &bits, NULL, 0);
1776 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1778 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1779 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1781 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1782 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1783 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1785 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1786 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1787 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1788 ok( ret, "BitBlt(WHITENESS) failed\n" );
1790 hMetafile = CloseEnhMetaFile(hdcMetafile);
1791 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1793 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1794 "emf_BitBlt", FALSE) != 0)
1796 dump_emf_bits(hMetafile, "emf_BitBlt");
1797 dump_emf_records(hMetafile, "emf_BitBlt");
1800 SelectObject(hdcBitmap, hOldBitmap);
1801 DeleteObject(hBitmap);
1802 DeleteDC(hdcBitmap);
1803 DeleteDC(hdcDisplay);
1807 static void test_emf_DCBrush(void)
1810 HENHMETAFILE hMetafile;
1816 if (!pSetDCBrushColor || !pSetDCPenColor)
1818 win_skip( "SetDCBrush/PenColor not supported\n" );
1822 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1823 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1825 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1826 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1828 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1829 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1831 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1832 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1834 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1835 ok( color == 0, "SetDCPenColor returned %x\n", color );
1837 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1839 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1840 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1842 hMetafile = CloseEnhMetaFile(hdcMetafile);
1843 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1845 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
1846 "emf_DC_Brush", FALSE ) != 0)
1848 dump_emf_bits(hMetafile, "emf_DC_Brush");
1849 dump_emf_records(hMetafile, "emf_DC_Brush");
1851 ret = DeleteEnhMetaFile(hMetafile);
1852 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1853 ret = DeleteObject(hBrush);
1854 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1855 ret = DeleteObject(hPen);
1856 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
1859 /* Test a blank metafile. May be used as a template for new tests. */
1861 static void test_mf_Blank(void)
1864 HMETAFILE hMetafile;
1869 hdcMetafile = CreateMetaFileA(NULL);
1870 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1871 trace("hdcMetafile %p\n", hdcMetafile);
1873 /* Tests on metafile initialization */
1874 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
1875 ok (caps == DT_METAFILE,
1876 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
1878 hMetafile = CloseMetaFile(hdcMetafile);
1879 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1880 type = GetObjectType(hMetafile);
1881 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1882 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1884 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1887 dump_mf_bits(hMetafile, "mf_Blank");
1888 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1891 ret = DeleteMetaFile(hMetafile);
1892 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1895 static void test_CopyMetaFile(void)
1898 HMETAFILE hMetafile, hmf_copy;
1900 char temp_path[MAX_PATH];
1901 char mf_name[MAX_PATH];
1904 hdcMetafile = CreateMetaFileA(NULL);
1905 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1906 trace("hdcMetafile %p\n", hdcMetafile);
1908 hMetafile = CloseMetaFile(hdcMetafile);
1909 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1910 type = GetObjectType(hMetafile);
1911 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
1913 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
1916 dump_mf_bits(hMetafile, "mf_Blank");
1917 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1920 GetTempPathA(MAX_PATH, temp_path);
1921 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
1923 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
1924 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
1926 type = GetObjectType(hmf_copy);
1927 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
1929 ret = DeleteMetaFile(hMetafile);
1930 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1932 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
1934 dump_mf_bits(hmf_copy, "mf_Blank");
1935 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
1938 ret = DeleteMetaFile(hmf_copy);
1939 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
1941 DeleteFileA(mf_name);
1944 static void test_SetMetaFileBits(void)
1952 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
1953 trace("hmf %p\n", hmf);
1954 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
1955 type = GetObjectType(hmf);
1956 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
1958 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
1960 dump_mf_bits(hmf, "mf_Graphics");
1961 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1964 ret = DeleteMetaFile(hmf);
1965 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
1967 /* NULL data crashes XP SP1 */
1968 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
1970 /* Now with zero size */
1971 SetLastError(0xdeadbeef);
1972 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
1973 trace("hmf %p\n", hmf);
1974 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1975 ok(GetLastError() == ERROR_INVALID_DATA ||
1976 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
1977 "wrong error %d\n", GetLastError());
1979 /* Now with odd size */
1980 SetLastError(0xdeadbeef);
1981 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
1982 trace("hmf %p\n", hmf);
1983 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1984 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
1986 /* Now with zeroed out header fields */
1987 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
1988 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
1989 mh = (METAHEADER *)buf;
1990 /* corruption of any of the below fields leads to a failure */
1993 mh->mtHeaderSize = 0;
1994 SetLastError(0xdeadbeef);
1995 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
1996 trace("hmf %p\n", hmf);
1997 ok(!hmf, "SetMetaFileBitsEx should fail\n");
1998 ok(GetLastError() == ERROR_INVALID_DATA ||
1999 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2000 "wrong error %d\n", GetLastError());
2002 /* Now with corrupted mtSize field */
2003 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2004 mh = (METAHEADER *)buf;
2005 /* corruption of mtSize doesn't lead to a failure */
2007 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2008 trace("hmf %p\n", hmf);
2009 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2011 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2013 dump_mf_bits(hmf, "mf_Graphics");
2014 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2017 ret = DeleteMetaFile(hmf);
2018 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2020 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2021 /* Now with zeroed out mtSize field */
2022 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2023 mh = (METAHEADER *)buf;
2024 /* zeroing mtSize doesn't lead to a failure */
2026 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2027 trace("hmf %p\n", hmf);
2028 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2030 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2032 dump_mf_bits(hmf, "mf_Graphics");
2033 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2036 ret = DeleteMetaFile(hmf);
2037 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2041 /* Simple APIs from mfdrv/graphics.c
2044 static void test_mf_Graphics(void)
2047 HMETAFILE hMetafile;
2051 hdcMetafile = CreateMetaFileA(NULL);
2052 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2053 trace("hdcMetafile %p\n", hdcMetafile);
2055 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2056 ok( ret, "MoveToEx error %d.\n", GetLastError());
2057 ret = LineTo(hdcMetafile, 2, 2);
2058 ok( ret, "LineTo error %d.\n", GetLastError());
2059 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2060 ok( ret, "MoveToEx error %d.\n", GetLastError());
2062 /* oldpoint gets garbage under Win XP, so the following test would
2063 * work under Wine but fails under Windows:
2065 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2066 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2067 * oldpoint.x, oldpoint.y);
2070 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2071 ok( ret, "Ellipse error %d.\n", GetLastError());
2073 hMetafile = CloseMetaFile(hdcMetafile);
2074 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2075 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2077 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2078 "mf_Graphics") != 0)
2080 dump_mf_bits(hMetafile, "mf_Graphics");
2081 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2084 ret = DeleteMetaFile(hMetafile);
2085 ok( ret, "DeleteMetaFile(%p) error %d\n",
2086 hMetafile, GetLastError());
2089 static void test_mf_PatternBrush(void)
2092 HMETAFILE hMetafile;
2097 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2099 orig_lb->lbStyle = BS_PATTERN;
2100 orig_lb->lbColor = RGB(0, 0, 0);
2101 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2102 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2104 hBrush = CreateBrushIndirect (orig_lb);
2105 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2107 hdcMetafile = CreateMetaFileA(NULL);
2108 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2109 trace("hdcMetafile %p\n", hdcMetafile);
2111 hBrush = SelectObject(hdcMetafile, hBrush);
2112 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2114 hMetafile = CloseMetaFile(hdcMetafile);
2115 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2116 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2118 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2119 "mf_Pattern_Brush") != 0)
2121 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2122 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2125 ret = DeleteMetaFile(hMetafile);
2126 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2127 ret = DeleteObject(hBrush);
2128 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2129 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2130 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2132 HeapFree (GetProcessHeap(), 0, orig_lb);
2135 static void test_mf_DCBrush(void)
2138 HMETAFILE hMetafile;
2144 if (!pSetDCBrushColor || !pSetDCPenColor)
2146 win_skip( "SetDCBrush/PenColor not supported\n" );
2150 hdcMetafile = CreateMetaFileA(NULL);
2151 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2153 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2154 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2156 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2157 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2159 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2160 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2162 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2163 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2165 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2167 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2168 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2170 hMetafile = CloseMetaFile(hdcMetafile);
2171 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2173 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2175 dump_mf_bits(hMetafile, "mf_DCBrush");
2176 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2178 ret = DeleteMetaFile(hMetafile);
2179 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2182 static void test_mf_ExtTextOut_on_path(void)
2185 HMETAFILE hMetafile;
2187 static const INT dx[4] = { 3, 5, 8, 12 };
2189 hdcMetafile = CreateMetaFileA(NULL);
2190 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2191 trace("hdcMetafile %p\n", hdcMetafile);
2193 ret = BeginPath(hdcMetafile);
2194 ok(!ret, "BeginPath on metafile DC should fail\n");
2196 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2197 ok(ret, "ExtTextOut error %d\n", GetLastError());
2199 ret = EndPath(hdcMetafile);
2200 ok(!ret, "EndPath on metafile DC should fail\n");
2202 hMetafile = CloseMetaFile(hdcMetafile);
2203 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2205 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2206 "mf_TextOut_on_path") != 0)
2208 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2209 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2212 ret = DeleteMetaFile(hMetafile);
2213 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2216 static void test_emf_ExtTextOut_on_path(void)
2219 HDC hdcDisplay, hdcMetafile;
2220 HENHMETAFILE hMetafile;
2222 static const INT dx[4] = { 3, 5, 8, 12 };
2224 /* Win9x doesn't play EMFs on invisible windows */
2225 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2226 0, 0, 200, 200, 0, 0, 0, NULL);
2227 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2229 hdcDisplay = GetDC(hwnd);
2230 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2232 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2233 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2235 ret = BeginPath(hdcMetafile);
2236 ok(ret, "BeginPath error %d\n", GetLastError());
2238 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2239 ok(ret, "ExtTextOut error %d\n", GetLastError());
2241 ret = EndPath(hdcMetafile);
2242 ok(ret, "EndPath error %d\n", GetLastError());
2244 hMetafile = CloseEnhMetaFile(hdcMetafile);
2245 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2247 /* this doesn't succeed yet: EMF has correct size, all EMF records
2248 * are there, but their contents don't match for different reasons.
2250 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2251 "emf_TextOut_on_path", FALSE) != 0)
2253 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2254 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2257 ret = DeleteEnhMetaFile(hMetafile);
2258 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2259 ret = ReleaseDC(hwnd, hdcDisplay);
2260 ok(ret, "ReleaseDC error %d\n", GetLastError());
2261 DestroyWindow(hwnd);
2264 static const unsigned char EMF_CLIPPING[] =
2266 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2268 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2270 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
2271 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2272 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
2273 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2275 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2276 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
2277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2278 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
2279 0xe0, 0x93, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2280 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2281 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2282 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2283 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2284 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2285 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2286 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2287 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2288 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2289 0x00, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
2290 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2291 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
2294 static void translate( POINT *pt, UINT count, const XFORM *xform )
2298 FLOAT x = (FLOAT)pt->x;
2299 FLOAT y = (FLOAT)pt->y;
2300 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2301 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2306 /* Compare rectangles allowing rounding errors */
2307 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2309 return abs(rc1->left - rc2->left) <= 1 &&
2310 abs(rc1->top - rc2->top) <= 1 &&
2311 abs(rc1->right - rc2->right) <= 1 &&
2312 abs(rc1->bottom - rc2->bottom) <= 1;
2315 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2316 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2318 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2320 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2324 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2326 const union _rgn *rgn1;
2328 RECT rect, rc_transformed;
2329 const RECT *rc = (const RECT *)param;
2335 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2336 clip->cbRgnData, clip->iMode);
2338 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2339 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2340 "too small data block: %u bytes\n", clip->cbRgnData);
2341 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2344 rgn1 = (const union _rgn *)clip->RgnData;
2346 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2347 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2348 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2349 rgn1->data.rdh.rcBound.left, rgn1->data.rdh.rcBound.top,
2350 rgn1->data.rdh.rcBound.right, rgn1->data.rdh.rcBound.bottom);
2352 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2354 rect = *(const RECT *)rgn1->data.Buffer;
2355 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2356 ok(EqualRect(&rect, rc), "rects don't match\n");
2358 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2359 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2360 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2361 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2362 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2363 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2365 hrgn = CreateRectRgn(0, 0, 0, 0);
2367 memset(&xform, 0, sizeof(xform));
2368 SetLastError(0xdeadbeef);
2369 ret = GetWorldTransform(hdc, &xform);
2370 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2372 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2374 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2376 ret = GetClipRgn(hdc, hrgn);
2377 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2379 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2381 ret = GetClipRgn(hdc, hrgn);
2382 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2384 /* Win9x returns empty clipping region */
2385 if (is_win9x) return 1;
2387 ret = GetRegionData(hrgn, 0, NULL);
2388 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2390 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2391 ok(ret == sizeof(rgn2), "expected sizeof(rgn2), got %u\n", ret);
2393 trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
2394 rgn2.data.rdh.dwSize, rgn2.data.rdh.iType,
2395 rgn2.data.rdh.nCount, rgn2.data.rdh.nRgnSize,
2396 rgn2.data.rdh.rcBound.left, rgn2.data.rdh.rcBound.top,
2397 rgn2.data.rdh.rcBound.right, rgn2.data.rdh.rcBound.bottom);
2399 rect = rgn2.data.rdh.rcBound;
2400 rc_transformed = *rc;
2401 translate((POINT *)&rc_transformed, 2, &xform);
2402 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2403 rc_transformed.right, rc_transformed.bottom);
2404 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2406 rect = *(const RECT *)rgn2.data.Buffer;
2407 trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
2408 rc_transformed = *rc;
2409 translate((POINT *)&rc_transformed, 2, &xform);
2410 trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
2411 rc_transformed.right, rc_transformed.bottom);
2412 ok(is_equal_rect(&rect, &rc_transformed), "rects don't match\n");
2414 ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn2.data.rdh.dwSize);
2415 ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn2.data.rdh.iType);
2416 ok(rgn2.data.rdh.nCount == 1, "expected 1, got %u\n", rgn2.data.rdh.nCount);
2417 ok(rgn2.data.rdh.nRgnSize == sizeof(RECT) ||
2418 broken(rgn2.data.rdh.nRgnSize == 168), /* NT4 */
2419 "expected sizeof(RECT), got %u\n", rgn2.data.rdh.nRgnSize);
2426 static void test_emf_clipping(void)
2428 static const RECT rc = { 0, 0, 100, 100 };
2429 RECT rc_clip = { 100, 100, 1024, 1024 };
2435 RECT rc_res, rc_sclip;
2437 SetLastError(0xdeadbeef);
2438 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2439 ok(hdc != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2441 /* Need to write something to the emf, otherwise Windows won't play it back */
2444 hrgn = CreateRectRgn(rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
2445 ret = SelectClipRgn(hdc, hrgn);
2446 ok(ret == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", ret);
2448 SetLastError(0xdeadbeef);
2449 hemf = CloseEnhMetaFile(hdc);
2450 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2452 if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
2453 "emf_clipping", FALSE) != 0)
2455 dump_emf_bits(hemf, "emf_clipping");
2456 dump_emf_records(hemf, "emf_clipping");
2461 /* Win9x doesn't play EMFs on invisible windows */
2462 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2463 0, 0, 200, 200, 0, 0, 0, NULL);
2464 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2468 ret = EnumEnhMetaFile(hdc, hemf, clip_emf_enum_proc, &rc_clip, &rc);
2469 ok(ret, "EnumEnhMetaFile error %d\n", GetLastError());
2471 DeleteEnhMetaFile(hemf);
2472 ReleaseDC(hwnd, hdc);
2473 DestroyWindow(hwnd);
2475 hdc = CreateEnhMetaFileA(0, NULL, NULL, NULL);
2477 SetRect(&rc_sclip, 100, 100, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2478 hrgn = CreateRectRgn(rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom);
2479 SelectClipRgn(hdc, hrgn);
2480 ret = GetClipBox(hdc, &rc_res);
2482 ok(ret == SIMPLEREGION, "got %d\n", ret);
2483 if(ret == SIMPLEREGION)
2484 ok(EqualRect(&rc_res, &rc_sclip),
2485 "expected rc_res (%d, %d) - (%d, %d), got (%d, %d) - (%d, %d)\n",
2486 rc_sclip.left, rc_sclip.top, rc_sclip.right, rc_sclip.bottom,
2487 rc_res.left, rc_res.top, rc_res.right, rc_res.bottom);
2489 hemf = CloseEnhMetaFile(hdc);
2490 DeleteEnhMetaFile(hemf);
2495 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
2497 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
2498 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
2499 /* When using MM_TEXT Win9x does not update the mapping mode
2500 * until a record is played which actually outputs something */
2501 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
2502 LPtoDP(hdc, mapping, 2);
2503 trace("EMF record: iType %d, nSize %d, (%d,%d)-(%d,%d)\n",
2504 lpEMFR->iType, lpEMFR->nSize,
2505 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
2507 if (lpEMFR->iType == EMR_LINETO)
2510 if (!lpMFP || lpMFP->mm == MM_TEXT)
2514 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
2515 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
2519 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
2521 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2522 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2523 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
2524 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
2526 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
2527 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
2528 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
2534 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
2543 hdcMf = CreateMetaFile(NULL);
2544 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
2545 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
2546 ok(ret, "LineTo failed with error %d\n", GetLastError());
2547 hmf = CloseMetaFile(hdcMf);
2548 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
2550 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
2552 dump_mf_bits(hmf, "mf_LineTo");
2553 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2556 size = GetMetaFileBitsEx(hmf, 0, NULL);
2557 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
2558 pBits = HeapAlloc(GetProcessHeap(), 0, size);
2559 GetMetaFileBitsEx(hmf, size, pBits);
2560 DeleteMetaFile(hmf);
2561 hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
2562 HeapFree(GetProcessHeap(), 0, pBits);
2566 static void test_mf_conversions(void)
2568 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
2570 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2573 RECT rect = { 0, 0, 100, 100 };
2574 mfp.mm = MM_ANISOTROPIC;
2578 hemf = create_converted_emf(&mfp);
2580 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
2581 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
2583 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
2584 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
2587 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2589 DeleteEnhMetaFile(hemf);
2590 DeleteDC(hdcOffscreen);
2593 trace("Testing MF->EMF conversion (MM_TEXT)\n");
2595 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2598 RECT rect = { 0, 0, 100, 100 };
2603 hemf = create_converted_emf(&mfp);
2605 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
2606 "emf_LineTo MM_TEXT", TRUE) != 0)
2608 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
2609 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
2612 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
2614 DeleteEnhMetaFile(hemf);
2615 DeleteDC(hdcOffscreen);
2618 trace("Testing MF->EMF conversion (NULL mfp)\n");
2620 HDC hdcOffscreen = CreateCompatibleDC(NULL);
2622 RECT rect = { 0, 0, 100, 100 };
2623 hemf = create_converted_emf(NULL);
2625 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
2626 "emf_LineTo NULL", TRUE) != 0)
2628 dump_emf_bits(hemf, "emf_LineTo NULL");
2629 dump_emf_records(hemf, "emf_LineTo NULL");
2632 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
2634 DeleteEnhMetaFile(hemf);
2635 DeleteDC(hdcOffscreen);
2639 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2640 LONG mm, LONG xExt, LONG yExt,
2641 RECTL * rclBounds, RECTL * rclFrame)
2644 METAFILEPICT * mfpPtr = NULL;
2646 ENHMETAHEADER header;
2657 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
2658 ok(emf != NULL, "SetWinMetaFileBits failed\n");
2659 if (!emf) return FALSE;
2660 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
2661 ok(res != 0, "GetEnhMetaHeader failed\n");
2662 DeleteEnhMetaFile(emf);
2663 if (!res) return FALSE;
2665 *rclBounds = header.rclBounds;
2666 *rclFrame = header.rclFrame;
2670 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
2671 LONG mm, LONG xExt, LONG yExt,
2672 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
2674 RECTL rclBounds, rclFrame;
2676 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
2683 msg = "mfp == NULL";
2687 const char * mm_str;
2690 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
2691 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
2692 default: mm_str = "Unexpected";
2694 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
2698 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
2699 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
2700 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
2701 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
2702 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
2703 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
2704 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
2705 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
2709 static void test_SetWinMetaFileBits(void)
2717 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
2718 RECTL rclBoundsIsotropic, rclFrameIsotropic;
2719 RECTL rclBounds, rclFrame;
2723 wmfDC = CreateMetaFile(NULL);
2724 ok(wmfDC != NULL, "CreateMetaFile failed\n");
2727 SetWindowExtEx(wmfDC, 100, 100, NULL);
2728 rect.left = rect.top = 0;
2729 rect.right = rect.bottom = 50;
2730 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
2731 wmf = CloseMetaFile(wmfDC);
2732 ok(wmf != NULL, "Metafile creation failed\n");
2735 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
2736 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
2737 if (buffer_size == 0)
2739 DeleteMetaFile(wmf);
2743 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size);
2744 ok(buffer != NULL, "HeapAlloc failed\n");
2747 DeleteMetaFile(wmf);
2751 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
2752 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
2753 DeleteMetaFile(wmf);
2754 if (res != buffer_size)
2756 HeapFree(GetProcessHeap(), 0, buffer);
2760 /* Get the reference bounds and frame */
2761 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2762 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2764 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
2765 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
2766 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
2768 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
2769 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
2770 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
2771 if (diffx < 0) diffx = -diffx;
2772 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
2774 dc = CreateCompatibleDC(NULL);
2776 /* Allow 1 mm difference (rounding errors) */
2777 diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
2778 diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
2779 if (diffx < 0) diffx = -diffx;
2780 if (diffy < 0) diffy = -diffy;
2783 ok(diffx <= 1 && diffy <= 1,
2784 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2785 GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
2788 /* Allow 1 mm difference (rounding errors) */
2789 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
2790 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
2791 if (diffx < 0) diffx = -diffx;
2792 if (diffy < 0) diffy = -diffy;
2795 ok(diffx <= 1 && diffy <= 1,
2796 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
2797 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
2801 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
2802 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2804 /* If xExt or yExt is zero or negative, the whole device surface is used */
2805 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2806 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2807 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2808 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2809 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2810 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
2811 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2812 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2813 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2814 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2815 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2816 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
2818 /* MSDN says that negative xExt and yExt values specify a ratio.
2819 Check that this is wrong and the whole device surface is used */
2820 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
2821 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
2823 /* Ordinary conversions */
2825 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2827 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2828 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
2829 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
2830 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
2833 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
2835 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
2836 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
2837 ok(rclBounds.left == 0 && rclBounds.top == 0,
2838 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
2840 /* Wine has a rounding error */
2841 diffx = rclBounds.right - rclBounds.bottom;
2842 if (diffx < 0) diffx = -diffx;
2843 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
2846 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
2848 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
2849 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
2852 HeapFree(GetProcessHeap(), 0, buffer);
2855 static BOOL near_match(int x, int y)
2857 int epsilon = min(abs(x), abs(y));
2859 epsilon = max(epsilon/100, 2);
2861 if(x < y - epsilon || x > y + epsilon) return FALSE;
2865 static void getwinmetafilebits(UINT mode, int scale, RECT *rc)
2868 HDC display_dc, emf_dc;
2869 ENHMETAHEADER *enh_header;
2870 UINT size, emf_size, i;
2873 METAHEADER *mh = NULL;
2875 INT horz_res, vert_res, horz_size, vert_size;
2876 INT curve_caps, line_caps, poly_caps;
2878 display_dc = GetDC(NULL);
2879 ok(display_dc != NULL, "display_dc is NULL\n");
2881 horz_res = GetDeviceCaps(display_dc, HORZRES);
2882 vert_res = GetDeviceCaps(display_dc, VERTRES);
2883 horz_size = GetDeviceCaps(display_dc, HORZSIZE);
2884 vert_size = GetDeviceCaps(display_dc, VERTSIZE);
2886 emf_dc = CreateEnhMetaFileA(display_dc, NULL, rc, NULL);
2887 ok(emf_dc != NULL, "emf_dc is NULL\n");
2889 curve_caps = GetDeviceCaps(emf_dc, CURVECAPS);
2890 ok(curve_caps == 511, "expect 511 got %d\n", curve_caps);
2892 line_caps = GetDeviceCaps(emf_dc, LINECAPS);
2893 ok(line_caps == 254, "expect 254 got %d\n", line_caps);
2895 poly_caps = GetDeviceCaps(emf_dc, POLYGONALCAPS);
2896 ok(poly_caps == 255, "expect 511 got %d\n", poly_caps);
2898 for(i = 0; i < 3000; i++) /* This is enough to take emf_size > 0xffff */
2899 Rectangle(emf_dc, 0, 0, 1000, 20);
2900 emf = CloseEnhMetaFile(emf_dc);
2901 ok(emf != NULL, "emf is NULL\n");
2903 emf_size = GetEnhMetaFileBits(emf, 0, NULL);
2904 enh_header = HeapAlloc(GetProcessHeap(), 0, emf_size);
2905 emf_size = GetEnhMetaFileBits(emf, emf_size, (BYTE*)enh_header);
2906 DeleteEnhMetaFile(emf);
2907 /* multiply szlDevice.cx by scale, when scale != 1 the recording and playback dcs
2908 have different resolutions */
2909 enh_header->szlDevice.cx *= scale;
2910 emf = SetEnhMetaFileBits(emf_size, (BYTE*)enh_header);
2911 ok(emf != NULL, "emf is NULL\n");
2912 ok(EqualRect((RECT*)&enh_header->rclFrame, rc), "Frame rectangles differ\n");
2914 size = GetWinMetaFileBits(emf, 0, NULL, mode, display_dc);
2916 broken(size == 0), /* some versions of winxp fail for some reason */
2917 "GetWinMetaFileBits returns 0\n");
2919 mh = HeapAlloc(GetProcessHeap(), 0, size);
2920 GetWinMetaFileBits(emf, size, (BYTE*)mh, mode, display_dc);
2922 for(i = 0; i < size / 2; i++) check += ((WORD*)mh)[i];
2923 ok(check == 0, "check %04x\n", check);
2925 rec = (METARECORD*)(mh + 1);
2927 while(rec->rdSize && rec->rdFunction)
2929 const DWORD chunk_size = 0x2000;
2930 DWORD mfcomment_chunks = (emf_size + chunk_size - 1) / chunk_size;
2932 if(rec_num < mfcomment_chunks)
2934 DWORD this_chunk_size = chunk_size;
2936 if(rec_num == mfcomment_chunks - 1)
2937 this_chunk_size = emf_size - rec_num * chunk_size;
2939 ok(rec->rdSize == (this_chunk_size + 44) / 2, "%04x: got %04x expected %04x\n", rec_num, rec->rdSize, (this_chunk_size + 44) / 2);
2940 ok(rec->rdFunction == META_ESCAPE, "%04x: got %04x\n", rec_num, rec->rdFunction);
2941 if(rec->rdSize < (this_chunk_size + 44) / 2) break;
2942 ok(rec->rdParm[0] == MFCOMMENT, "got %04x\n", rec->rdParm[0]);
2943 ok(rec->rdParm[1] == this_chunk_size + 34, "got %04x %x\n", rec->rdParm[1], emf_size + 34);
2944 ok(rec->rdParm[2] == 0x4d57, "got %04x\n", rec->rdParm[2]); /* WMFC */
2945 ok(rec->rdParm[3] == 0x4346, "got %04x\n", rec->rdParm[3]); /* " */
2946 ok(rec->rdParm[4] == 1, "got %04x\n", rec->rdParm[4]);
2947 ok(rec->rdParm[5] == 0, "got %04x\n", rec->rdParm[5]);
2948 ok(rec->rdParm[6] == 0, "got %04x\n", rec->rdParm[6]);
2949 ok(rec->rdParm[7] == 1, "got %04x\n", rec->rdParm[7]);
2950 /* parm[8] is the checksum, tested above */
2951 if(rec_num > 0) ok(rec->rdParm[8] == 0, "got %04x\n", rec->rdParm[8]);
2952 ok(rec->rdParm[9] == 0, "got %04x\n", rec->rdParm[9]);
2953 ok(rec->rdParm[10] == 0, "got %04x\n", rec->rdParm[10]);
2954 ok(rec->rdParm[11] == mfcomment_chunks, "got %04x\n", rec->rdParm[11]); /* num chunks */
2955 ok(rec->rdParm[12] == 0, "got %04x\n", rec->rdParm[12]);
2956 ok(rec->rdParm[13] == this_chunk_size, "got %04x expected %04x\n", rec->rdParm[13], this_chunk_size);
2957 ok(rec->rdParm[14] == 0, "got %04x\n", rec->rdParm[14]);
2958 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 */
2959 ok(*(DWORD*)(rec->rdParm + 17) == emf_size, "got %08x emf_size %08x\n", *(DWORD*)(rec->rdParm + 17), emf_size);
2960 ok(!memcmp(rec->rdParm + 19, (char*)enh_header + rec_num * chunk_size, this_chunk_size), "bits mismatch\n");
2963 else if(rec_num == mfcomment_chunks)
2965 ok(rec->rdFunction == META_SETMAPMODE, "got %04x\n", rec->rdFunction);
2966 ok(rec->rdParm[0] == mode, "got %04x\n", rec->rdParm[0]);
2968 else if(rec_num == mfcomment_chunks + 1)
2971 ok(rec->rdFunction == META_SETWINDOWORG, "got %04x\n", rec->rdFunction);
2976 case MM_ANISOTROPIC:
2977 pt.y = MulDiv(rc->top, vert_res, vert_size * 100) + 1;
2978 pt.x = MulDiv(rc->left, horz_res, horz_size * 100);
2981 pt.y = MulDiv(-rc->top, 1, 10) + 1;
2982 pt.x = MulDiv( rc->left, 1, 10);
2985 pt.y = -rc->top + 1;
2986 pt.x = (rc->left >= 0) ? rc->left : rc->left + 1; /* strange but true */
2989 pt.y = MulDiv(-rc->top, 10, 254) + 1;
2990 pt.x = MulDiv( rc->left, 10, 254);
2993 pt.y = MulDiv(-rc->top, 100, 254) + 1;
2994 pt.x = MulDiv( rc->left, 100, 254);
2997 pt.y = MulDiv(-rc->top, 72 * 20, 2540) + 1;
2998 pt.x = MulDiv( rc->left, 72 * 20, 2540);
3003 ok(near_match((short)rec->rdParm[0], pt.y), "got %d expect %d\n", (short)rec->rdParm[0], pt.y);
3004 ok(near_match((short)rec->rdParm[1], pt.x), "got %d expect %d\n", (short)rec->rdParm[1], pt.x);
3006 if(rec_num == mfcomment_chunks + 2)
3008 ok(rec->rdFunction == META_SETWINDOWEXT, "got %04x\n", rec->rdFunction);
3009 ok(near_match((short)rec->rdParm[0], MulDiv(rc->bottom - rc->top, vert_res, vert_size * 100)),
3010 "got %d\n", (short)rec->rdParm[0]);
3011 ok(near_match((short)rec->rdParm[1], MulDiv(rc->right - rc->left, horz_res, horz_size * 100)),
3012 "got %d\n", (short)rec->rdParm[1]);
3016 rec = (METARECORD*)((WORD*)rec + rec->rdSize);
3020 HeapFree(GetProcessHeap(), 0, mh);
3021 HeapFree(GetProcessHeap(), 0, enh_header);
3022 DeleteEnhMetaFile(emf);
3024 ReleaseDC(NULL, display_dc);
3027 static void test_GetWinMetaFileBits(void)
3032 { 1000, 2000, 3000, 6000},
3033 {-1000, 2000, 3000, 6000},
3034 { 1000, -2000, 3000, 6000},
3035 { 1005, 2005, 3000, 6000},
3036 {-1005, -2005, 3000, 6000},
3037 {-1005, -2010, 3000, 6000},
3038 {-1005, 2010, 3000, 6000},
3044 for(mode = MM_MIN; mode <= MM_MAX; mode++)
3047 trace("mode %d\n", mode);
3049 for(rc = frames; rc->right - rc->left > 0; rc++)
3051 trace("frame %d,%d - %d,%d\n", rc->left, rc->top, rc->right, rc->bottom);
3052 getwinmetafilebits(mode, 1, rc);
3053 getwinmetafilebits(mode, 2, rc);
3058 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
3059 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
3060 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
3062 static void test_gdiis(void)
3064 RECT rect = {0,0,100,100};
3065 HDC hdc, hemfDC, hmfDC;
3069 /* resolve all the functions */
3070 hgdi32 = GetModuleHandle("gdi32");
3071 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
3072 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
3073 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
3075 if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
3077 win_skip("Needed GdiIs* functions are not available\n");
3081 /* try with nothing */
3082 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
3083 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
3084 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
3086 /* try with a metafile */
3087 hmfDC = CreateMetaFile(NULL);
3088 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
3089 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
3090 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
3091 DeleteMetaFile(CloseMetaFile(hmfDC));
3093 /* try with an enhanced metafile */
3095 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
3096 ok(hemfDC != NULL, "failed to create emf\n");
3098 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
3099 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
3100 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
3102 hemf = CloseEnhMetaFile(hemfDC);
3103 ok(hemf != NULL, "failed to close EMF\n");
3104 DeleteEnhMetaFile(hemf);
3105 ReleaseDC(NULL,hdc);
3108 static void test_SetEnhMetaFileBits(void)
3114 memset(data, 0xAA, sizeof(data));
3115 SetLastError(0xdeadbeef);
3116 hemf = SetEnhMetaFileBits(sizeof(data), data);
3117 ok(!hemf, "SetEnhMetaFileBits should fail\n");
3118 ok(GetLastError() == ERROR_INVALID_DATA ||
3119 GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
3120 "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3122 emh = (ENHMETAHEADER *)data;
3123 memset(emh, 0, sizeof(*emh));
3125 emh->iType = EMR_HEADER;
3126 emh->nSize = sizeof(*emh);
3127 emh->dSignature = ENHMETA_SIGNATURE;
3128 /* emh->nVersion = 0x10000; XP doesn't care about version */
3129 emh->nBytes = sizeof(*emh);
3130 /* emh->nRecords = 1; XP doesn't care about records */
3131 emh->nHandles = 1; /* XP refuses to load a EMF if nHandles == 0 */
3133 SetLastError(0xdeadbeef);
3134 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3135 ok(hemf != 0, "SetEnhMetaFileBits error %u\n", GetLastError());
3136 DeleteEnhMetaFile(hemf);
3138 /* XP refuses to load unaligned EMF */
3140 SetLastError(0xdeadbeef);
3141 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3143 broken(hemf != NULL), /* Win9x, WinMe */
3144 "SetEnhMetaFileBits should fail\n");
3145 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3146 DeleteEnhMetaFile(hemf);
3148 emh->dSignature = 0;
3150 SetLastError(0xdeadbeef);
3151 hemf = SetEnhMetaFileBits(emh->nBytes, data);
3153 broken(hemf != NULL), /* Win9x, WinMe */
3154 "SetEnhMetaFileBits should fail\n");
3155 ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n", GetLastError());
3156 DeleteEnhMetaFile(hemf);
3159 static void test_emf_polybezier(void)
3166 SetLastError(0xdeadbeef);
3167 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
3168 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
3170 pts[0].x = pts[0].y = 10;
3171 pts[1].x = pts[1].y = 20;
3172 pts[2].x = pts[2].y = 15;
3173 pts[3].x = pts[3].y = 25;
3174 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO16 */
3175 ok( ret, "PolyBezierTo failed\n" );
3176 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER16 */
3177 ok( ret, "PolyBezier failed\n" );
3179 pts[0].x = pts[0].y = 32769;
3180 ret = PolyBezier(hdcMetafile, pts, 4); /* EMR_POLYBEZIER */
3181 ok( ret, "PolyBezier failed\n" );
3182 ret = PolyBezierTo(hdcMetafile, pts, 3); /* EMR_POLYBEZIERTO */
3183 ok( ret, "PolyBezierTo failed\n" );
3185 hemf = CloseEnhMetaFile(hdcMetafile);
3186 ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
3188 if(compare_emf_bits(hemf, EMF_BEZIER_BITS, sizeof(EMF_BEZIER_BITS),
3189 "emf_Bezier", FALSE) != 0)
3191 dump_emf_bits(hemf, "emf_Bezier");
3192 dump_emf_records(hemf, "emf_Bezier");
3195 DeleteEnhMetaFile(hemf);
3198 START_TEST(metafile)
3200 init_function_pointers();
3202 /* For enhanced metafiles (enhmfdrv) */
3204 test_ExtTextOutScale();
3209 /* For win-format metafiles (mfdrv) */
3213 test_mf_PatternBrush();
3215 test_CopyMetaFile();
3216 test_SetMetaFileBits();
3217 test_mf_ExtTextOut_on_path();
3218 test_emf_ExtTextOut_on_path();
3219 test_emf_clipping();
3220 test_emf_polybezier();
3222 /* For metafile conversions */
3223 test_mf_conversions();
3224 test_SetWinMetaFileBits();
3225 test_GetWinMetaFileBits();
3228 test_SetEnhMetaFileBits();