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