c7da7bf54fddfe3bc5d04b659b3662beeacab9fe
[reactos.git] / modules / 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 "precomp.h"
22
23 static LOGFONTA orig_lf;
24 static BOOL emr_processed = FALSE;
25
26 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
27 #define LINE_X 55.0f
28 #define LINE_Y 15.0f
29
30 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
31 static INT (WINAPI * pSetRelAbs)(HDC, INT);
32 static COLORREF (WINAPI *pSetDCBrushColor)(HDC,COLORREF);
33 static COLORREF (WINAPI *pSetDCPenColor)(HDC,COLORREF);
34
35 #define GDI_GET_PROC(func) \
36 p ## func = (void *)GetProcAddress(hGDI, #func); \
37 if(!p ## func) \
38 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
39
40 static void init_function_pointers(void)
41 {
42 HMODULE hGDI;
43
44 pGetRelAbs = NULL;
45 pSetRelAbs = NULL;
46
47 hGDI = GetModuleHandleA("gdi32.dll");
48 assert(hGDI);
49 GDI_GET_PROC(GetRelAbs);
50 GDI_GET_PROC(SetRelAbs);
51 GDI_GET_PROC(SetDCBrushColor);
52 GDI_GET_PROC(SetDCPenColor);
53 }
54
55 static DWORD rgn_rect_count(HRGN hrgn)
56 {
57 DWORD size;
58 RGNDATA *data;
59
60 if (!hrgn) return 0;
61 if (!(size = GetRegionData(hrgn, 0, NULL))) return 0;
62 if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return 0;
63 GetRegionData(hrgn, size, data);
64 size = data->rdh.nCount;
65 HeapFree(GetProcessHeap(), 0, data);
66 return size;
67 }
68
69 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
70 const ENHMETARECORD *emr, int n_objs, LPARAM param)
71 {
72 static int n_record;
73 DWORD i;
74 const INT *dx;
75 INT *orig_dx = (INT *)param;
76 LOGFONTA device_lf;
77 INT ret;
78
79 if(!hdc) return 1;
80
81 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
82
83 switch (emr->iType)
84 {
85 case EMR_HEADER:
86 ok(GetTextAlign(hdc) == 0, "text align %08x\n", GetTextAlign(hdc));
87 ok(GetBkColor(hdc) == RGB(0xff, 0xff, 0xff), "bk color %08x\n", GetBkColor(hdc));
88 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08x\n", GetTextColor(hdc));
89 ok(GetROP2(hdc) == R2_COPYPEN, "rop %d\n", GetROP2(hdc));
90 ok(GetArcDirection(hdc) == AD_COUNTERCLOCKWISE, "arc dir %d\n", GetArcDirection(hdc));
91 ok(GetPolyFillMode(hdc) == ALTERNATE, "poly fill %d\n", GetPolyFillMode(hdc));
92 ok(GetStretchBltMode(hdc) == BLACKONWHITE, "stretchblt mode %d\n", GetStretchBltMode(hdc));
93
94 /* GetBkMode, GetRelAbs do not get reset to the default value */
95 ok(GetBkMode(hdc) == OPAQUE, "bk mode %d\n", GetBkMode(hdc));
96 if(pSetRelAbs && pGetRelAbs)
97 ok(pGetRelAbs(hdc, 0) == RELATIVE, "relabs %d\n", pGetRelAbs(hdc, 0));
98
99 n_record = 0;
100 break;
101
102 case EMR_EXTTEXTOUTA:
103 {
104 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
105 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
106
107 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
108 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
109
110 /* compare up to lfOutPrecision, other values are not interesting,
111 * and in fact sometimes arbitrary adapted by Win9x.
112 */
113 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
114 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
115
116 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
117 {
118 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
119 n_record, i, dx[i], orig_dx[i]);
120 }
121 n_record++;
122 emr_processed = TRUE;
123 break;
124 }
125
126 case EMR_EXTTEXTOUTW:
127 {
128 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
129 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
130
131 SetLastError(0xdeadbeef);
132 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
133 ok( ret == sizeof(device_lf) ||
134 broken(ret == (sizeof(device_lf) - LF_FACESIZE + strlen(device_lf.lfFaceName) + 1)), /* NT4 */
135 "GetObjectA error %d\n", GetLastError());
136
137 /* compare up to lfOutPrecision, other values are not interesting,
138 * and in fact sometimes arbitrary adapted by Win9x.
139 */
140 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
141 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
142
143 ok(!emr_ExtTextOutW->rclBounds.left, "emr_ExtTextOutW->rclBounds.left = %d\n",
144 emr_ExtTextOutW->rclBounds.left);
145 ok(emr_ExtTextOutW->rclBounds.right != -1, "emr_ExtTextOutW->rclBounds.right = %d\n",
146 emr_ExtTextOutW->rclBounds.right);
147 ok(emr_ExtTextOutW->rclBounds.bottom != -1, "emr_ExtTextOutW->rclBounds.bottom = %d\n",
148 emr_ExtTextOutW->rclBounds.bottom);
149
150 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
151 {
152 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
153 n_record, i, dx[i], orig_dx[i]);
154 }
155 n_record++;
156 emr_processed = TRUE;
157 break;
158 }
159
160 default:
161 break;
162 }
163
164 return 1;
165 }
166
167 static void test_ExtTextOut(void)
168 {
169 HWND hwnd;
170 HDC hdcDisplay, hdcMetafile;
171 HENHMETAFILE hMetafile;
172 HFONT hFont;
173 static const char text[] = "Simple text to test ExtTextOut on metafiles";
174 INT i, len, dx[256];
175 static const RECT rc = { 0, 0, 100, 100 };
176 BOOL ret;
177
178 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
179
180 /* Win9x doesn't play EMFs on invisible windows */
181 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
182 0, 0, 200, 200, 0, 0, 0, NULL);
183 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
184
185 hdcDisplay = GetDC(hwnd);
186 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
187
188 trace("hdcDisplay %p\n", hdcDisplay);
189
190 SetMapMode(hdcDisplay, MM_TEXT);
191
192 memset(&orig_lf, 0, sizeof(orig_lf));
193
194 orig_lf.lfCharSet = ANSI_CHARSET;
195 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
196 orig_lf.lfWeight = FW_DONTCARE;
197 orig_lf.lfHeight = 7;
198 orig_lf.lfQuality = DEFAULT_QUALITY;
199 lstrcpyA(orig_lf.lfFaceName, "Arial");
200 hFont = CreateFontIndirectA(&orig_lf);
201 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
202
203 hFont = SelectObject(hdcDisplay, hFont);
204
205 len = lstrlenA(text);
206 for (i = 0; i < len; i++)
207 {
208 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
209 ok( ret, "GetCharWidthA error %d\n", GetLastError());
210 }
211 hFont = SelectObject(hdcDisplay, hFont);
212
213 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
214 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
215
216 trace("hdcMetafile %p\n", hdcMetafile);
217
218 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
219 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
220
221 hFont = SelectObject(hdcMetafile, hFont);
222
223 /* 1. pass NULL lpDx */
224 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
225 ok( ret, "ExtTextOutA error %d\n", GetLastError());
226
227 /* 2. pass custom lpDx */
228 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
229 ok( ret, "ExtTextOutA error %d\n", GetLastError());
230
231 /* 3. pass NULL lprc */
232 ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL);
233 ok( ret, "ExtTextOutA error %d\n", GetLastError());
234
235 /* 4. test with unmatched BeginPath/EndPath calls */
236 ret = BeginPath(hdcMetafile);
237 ok( ret, "BeginPath error %d\n", GetLastError());
238 ret = BeginPath(hdcMetafile);
239 ok( ret, "BeginPath error %d\n", GetLastError());
240 ret = EndPath(hdcMetafile);
241 ok( ret, "BeginPath error %d\n", GetLastError());
242 ret = ExtTextOutA(hdcMetafile, 0, 60, 0, NULL, text, lstrlenA(text), NULL);
243 ok( ret, "ExtTextOutA error %d\n", GetLastError());
244
245 hFont = SelectObject(hdcMetafile, hFont);
246 ret = DeleteObject(hFont);
247 ok( ret, "DeleteObject error %d\n", GetLastError());
248
249 hMetafile = CloseEnhMetaFile(hdcMetafile);
250 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
251
252 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
253
254 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
255 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
256
257 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
258 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
259 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
260 SetROP2(hdcDisplay, R2_NOT);
261 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
262 SetPolyFillMode(hdcDisplay, WINDING);
263 SetStretchBltMode(hdcDisplay, HALFTONE);
264
265 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
266 SetBkMode(hdcDisplay, OPAQUE);
267
268 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
269 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
270
271 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
272 "text align %08x\n", GetTextAlign(hdcDisplay));
273 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08x\n", GetBkColor(hdcDisplay));
274 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\n", GetTextColor(hdcDisplay));
275 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
276 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
277 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
278 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
279
280 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
281
282 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
283 "A valid hdc has to require a valid rc\n");
284
285 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
286 "A null hdc does not require a valid rc\n");
287
288 ret = DeleteEnhMetaFile(hMetafile);
289 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
290 ret = ReleaseDC(hwnd, hdcDisplay);
291 ok( ret, "ReleaseDC error %d\n", GetLastError());
292 DestroyWindow(hwnd);
293 }
294
295 struct eto_scale_test_record
296 {
297 INT graphics_mode;
298 INT map_mode;
299 double ex_scale;
300 double ey_scale;
301 BOOL processed;
302 };
303
304 static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
305 const ENHMETARECORD *emr, int n_objs, LPARAM param)
306 {
307 struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
308
309 if (emr->iType == EMR_EXTTEXTOUTW)
310 {
311 const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
312 ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
313 "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
314 ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
315 "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
316 test->processed = TRUE;
317 }
318
319 return 1;
320 }
321
322 static void test_ExtTextOutScale(void)
323 {
324 const RECT rc = { 0, 0, 100, 100 };
325 const WCHAR str[] = {'a',0 };
326 struct eto_scale_test_record test;
327 HDC hdcDisplay, hdcMetafile;
328 HENHMETAFILE hMetafile;
329 HWND hwnd;
330 SIZE wndext, vportext;
331 int horzSize, vertSize, horzRes, vertRes;
332 int ret;
333 int i;
334
335 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
336 0, 0, 200, 200, 0, 0, 0, NULL);
337 ok(hwnd != 0, "CreateWindowExA failed\n");
338
339 hdcDisplay = GetDC(hwnd);
340 ok(hdcDisplay != 0, "GetDC failed\n");
341
342 horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
343 horzRes = GetDeviceCaps(hdcDisplay, HORZRES);
344 vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
345 vertRes = GetDeviceCaps(hdcDisplay, VERTRES);
346 ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
347
348 for (i = 0; i < 16; i++)
349 {
350 test.graphics_mode = i / 8 + 1;
351 test.map_mode = i % 8 + 1;
352
353 ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
354 ok(ret, "SetGraphicsMode failed\n");
355 ret = SetMapMode(hdcDisplay, test.map_mode);
356 ok(ret, "SetMapMode failed\n");
357
358 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
359 {
360 ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
361 ok(ret, "SetWindowExtEx failed\n");
362 ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
363 ok(ret, "SetViewportExtEx failed\n");
364 }
365
366 ret = GetViewportExtEx(hdcDisplay, &vportext);
367 ok(ret, "GetViewportExtEx failed\n");
368 ret = GetWindowExtEx(hdcDisplay, &wndext);
369 ok(ret, "GetWindowExtEx failed\n");
370
371 trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
372 test.graphics_mode, test.map_mode,
373 wndext.cx, wndext.cy, vportext.cx, vportext.cy,
374 horzSize, horzRes, vertSize, vertRes);
375
376 if (test.graphics_mode == GM_COMPATIBLE)
377 {
378 test.ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) /
379 ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
380 test.ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) /
381 ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
382 }
383 else
384 {
385 test.ex_scale = 0.0;
386 test.ey_scale = 0.0;
387 }
388
389 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
390 ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
391
392 ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
393 ok(ret, "SetGraphicsMode failed\n");
394 ret = SetMapMode(hdcMetafile, test.map_mode);
395 ok(ret, "SetMapMode failed\n");
396
397 if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
398 {
399 ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
400 ok(ret, "SetWindowExtEx failed\n");
401 ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
402 ok(ret, "SetViewportExtEx failed\n");
403 }
404
405 ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
406 ok(ret, "ExtTextOutW failed\n");
407
408 hMetafile = CloseEnhMetaFile(hdcMetafile);
409 ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
410
411 test.processed = 0;
412 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
413 ok(ret, "EnumEnhMetaFile failed\n");
414 ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
415
416 ret = DeleteEnhMetaFile(hMetafile);
417 ok(ret, "DeleteEnhMetaFile failed\n");
418 }
419
420 ret = ReleaseDC(hwnd, hdcDisplay);
421 ok(ret, "ReleaseDC failed\n");
422 DestroyWindow(hwnd);
423 }
424
425
426 static void check_dc_state(HDC hdc, int restore_no,
427 int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
428 int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
429 {
430 BOOL ret;
431 XFORM xform;
432 POINT vp_org, win_org;
433 SIZE vp_size, win_size;
434 FLOAT xscale, yscale, edx, edy;
435
436 SetLastError(0xdeadbeef);
437 ret = GetWorldTransform(hdc, &xform);
438 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
439 ok(ret, "GetWorldTransform error %u\n", GetLastError());
440
441 trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
442
443 ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
444 ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
445
446 xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
447 trace("x scale %f\n", xscale);
448 ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
449 restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
450
451 yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
452 trace("y scale %f\n", yscale);
453 ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
454 restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
455
456 edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
457 ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
458 edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
459 ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
460
461 return;
462
463 win9x_here:
464
465 GetWindowOrgEx(hdc, &win_org);
466 GetViewportOrgEx(hdc, &vp_org);
467 GetWindowExtEx(hdc, &win_size);
468 GetViewportExtEx(hdc, &vp_size);
469
470 ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
471 ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
472
473 ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
474 ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
475
476 ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
477 ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
478
479 ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
480 ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
481 }
482
483 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
484 const ENHMETARECORD *emr, int n_objs, LPARAM param)
485 {
486 BOOL ret;
487 XFORM xform;
488 POINT pt;
489 SIZE size;
490 static int save_state;
491 static int restore_no;
492 static int select_no;
493
494 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
495 hdc, emr->iType, emr->nSize, (void *)param);
496
497 SetLastError(0xdeadbeef);
498 ret = GetWorldTransform(hdc, &xform);
499 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
500 {
501 ret = GetWindowOrgEx(hdc, &pt);
502 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
503 trace("window org (%d,%d)\n", pt.x, pt.y);
504 ret = GetViewportOrgEx(hdc, &pt);
505 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
506 trace("vport org (%d,%d)\n", pt.x, pt.y);
507 ret = GetWindowExtEx(hdc, &size);
508 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
509 trace("window ext (%d,%d)\n", size.cx, size.cy);
510 ret = GetViewportExtEx(hdc, &size);
511 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
512 trace("vport ext (%d,%d)\n", size.cx, size.cy);
513 }
514 else
515 {
516 ok(ret, "GetWorldTransform error %u\n", GetLastError());
517 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
518 }
519
520 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
521
522 switch (emr->iType)
523 {
524 case EMR_HEADER:
525 {
526 static RECT exp_bounds = { 0, 0, 150, 150 };
527 RECT bounds;
528 const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
529
530 trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
531 emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
532 emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
533 trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
534 emf->szlDevice.cx, emf->szlDevice.cy);
535
536 SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
537 ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
538
539 save_state = 0;
540 restore_no = 0;
541 select_no = 0;
542 check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
543 break;
544 }
545
546 case EMR_LINETO:
547 {
548 const EMRLINETO *line = (const EMRLINETO *)emr;
549 trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
550 break;
551 }
552 case EMR_SETWINDOWORGEX:
553 {
554 const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
555 trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
556 break;
557 }
558 case EMR_SETWINDOWEXTEX:
559 {
560 const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
561 trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
562 break;
563 }
564 case EMR_SETVIEWPORTORGEX:
565 {
566 const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
567 trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
568 break;
569 }
570 case EMR_SETVIEWPORTEXTEX:
571 {
572 const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
573 trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
574 break;
575 }
576 case EMR_SAVEDC:
577 save_state++;
578 trace("EMR_SAVEDC\n");
579 break;
580
581 case EMR_RESTOREDC:
582 {
583 const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
584 trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
585
586 switch(++restore_no)
587 {
588 case 1:
589 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
590 check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
591 break;
592 case 2:
593 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
594 check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
595 break;
596 case 3:
597 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
598 check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
599 break;
600 }
601 ok(restore_no <= 3, "restore_no %d\n", restore_no);
602 save_state += restoredc->iRelative;
603 break;
604 }
605 case EMR_SELECTOBJECT:
606 {
607 const EMRSELECTOBJECT *selectobj = (const EMRSELECTOBJECT*)emr;
608 trace("EMR_SELECTOBJECT: %x\n",selectobj->ihObject);
609 select_no ++;
610 break;
611 }
612 case EMR_EOF:
613 ok(save_state == 0, "EOF save_state %d\n", save_state);
614 ok(select_no == 3, "Too many/few selects %i\n",select_no);
615 break;
616 }
617
618 SetLastError(0xdeadbeef);
619 ret = GetWorldTransform(hdc, &xform);
620 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
621 {
622 ret = GetWindowOrgEx(hdc, &pt);
623 ok(ret, "GetWindowOrgEx error %u\n", GetLastError());
624 trace("window org (%d,%d)\n", pt.x, pt.y);
625 ret = GetViewportOrgEx(hdc, &pt);
626 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
627 trace("vport org (%d,%d)\n", pt.x, pt.y);
628 ret = GetWindowExtEx(hdc, &size);
629 ok(ret, "GetWindowExtEx error %u\n", GetLastError());
630 trace("window ext (%d,%d)\n", size.cx, size.cy);
631 ret = GetViewportExtEx(hdc, &size);
632 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
633 trace("vport ext (%d,%d)\n", size.cx, size.cy);
634 }
635 else
636 {
637 ok(ret, "GetWorldTransform error %u\n", GetLastError());
638 trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
639 }
640
641 return 1;
642 }
643
644 static void test_SaveDC(void)
645 {
646 HDC hdcMetafile, hdcDisplay;
647 HENHMETAFILE hMetafile;
648 HWND hwnd;
649 int ret;
650 POINT pt;
651 SIZE size;
652 HFONT hFont,hFont2,hFontOld,hFontCheck;
653 static const RECT rc = { 0, 0, 150, 150 };
654
655 /* Win9x doesn't play EMFs on invisible windows */
656 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
657 0, 0, 200, 200, 0, 0, 0, NULL);
658 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
659
660 hdcDisplay = GetDC(hwnd);
661 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
662
663 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
664 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
665
666 SetMapMode(hdcMetafile, MM_ANISOTROPIC);
667
668 /* Need to write something to the emf, otherwise Windows won't play it back */
669 LineTo(hdcMetafile, 150, 150);
670
671 SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
672 SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
673 SetWindowExtEx(hdcMetafile, 110, 110, NULL );
674 SetViewportExtEx(hdcMetafile, 120, 120, NULL );
675
676 /* Force Win9x to update DC state */
677 SetPixelV(hdcMetafile, 50, 50, 0);
678
679 ret = GetViewportOrgEx(hdcMetafile, &pt);
680 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
681 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
682 ret = GetViewportExtEx(hdcMetafile, &size);
683 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
684 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
685 ret = SaveDC(hdcMetafile);
686 ok(ret == 1, "ret = %d\n", ret);
687
688 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
689 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
690 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
691 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
692
693 /* Force Win9x to update DC state */
694 SetPixelV(hdcMetafile, 50, 50, 0);
695
696 ret = GetViewportOrgEx(hdcMetafile, &pt);
697 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
698 ok(pt.x == 10,"Expecting ViewportOrg x of 10, got %i\n",pt.x);
699 ret = GetViewportExtEx(hdcMetafile, &size);
700 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
701 ok(size.cx == 200,"Expecting ViewportExt cx of 200, got %i\n",size.cx);
702 ret = SaveDC(hdcMetafile);
703 ok(ret == 2, "ret = %d\n", ret);
704
705 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
706 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
707 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
708 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
709 SetPolyFillMode( hdcMetafile, ALTERNATE );
710 SetBkColor( hdcMetafile, 0 );
711
712 /* Force Win9x to update DC state */
713 SetPixelV(hdcMetafile, 50, 50, 0);
714
715 ret = GetViewportOrgEx(hdcMetafile, &pt);
716 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
717 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
718 ret = GetViewportExtEx(hdcMetafile, &size);
719 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
720 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
721 ret = SaveDC(hdcMetafile);
722 ok(ret == 3, "ret = %d\n", ret);
723
724 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
725 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
726 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
727 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
728
729 SetPolyFillMode( hdcMetafile, WINDING );
730 SetBkColor( hdcMetafile, 0x123456 );
731 ok( GetPolyFillMode( hdcMetafile ) == WINDING, "PolyFillMode not restored\n" );
732 ok( GetBkColor( hdcMetafile ) == 0x123456, "Background color not restored\n" );
733
734 /* Force Win9x to update DC state */
735 SetPixelV(hdcMetafile, 50, 50, 0);
736
737 ret = GetViewportOrgEx(hdcMetafile, &pt);
738 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
739 ok(pt.x == 30,"Expecting ViewportOrg x of 30, got %i\n",pt.x);
740 ret = GetViewportExtEx(hdcMetafile, &size);
741 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
742 ok(size.cx == 400,"Expecting ViewportExt cx of 400, got %i\n",size.cx);
743 ret = RestoreDC(hdcMetafile, -1);
744 ok(ret, "ret = %d\n", ret);
745
746 ret = GetViewportOrgEx(hdcMetafile, &pt);
747 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
748 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
749 ret = GetViewportExtEx(hdcMetafile, &size);
750 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
751 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
752 ok( GetPolyFillMode( hdcMetafile ) == ALTERNATE, "PolyFillMode not restored\n" );
753 ok( GetBkColor( hdcMetafile ) == 0, "Background color not restored\n" );
754 ret = SaveDC(hdcMetafile);
755 ok(ret == 3, "ret = %d\n", ret);
756
757 ret = GetViewportOrgEx(hdcMetafile, &pt);
758 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
759 ok(pt.x == 20,"Expecting ViewportOrg x of 20, got %i\n",pt.x);
760 ret = GetViewportExtEx(hdcMetafile, &size);
761 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
762 ok(size.cx == 300,"Expecting ViewportExt cx of 300, got %i\n",size.cx);
763 ret = RestoreDC(hdcMetafile, 1);
764 ok(ret, "ret = %d\n", ret);
765 ret = GetViewportOrgEx(hdcMetafile, &pt);
766 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
767 ok(pt.x == 0,"Expecting ViewportOrg x of 0, got %i\n",pt.x);
768 ret = GetViewportExtEx(hdcMetafile, &size);
769 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
770 ok(size.cx == 120,"Expecting ViewportExt cx of 120, got %i\n",size.cx);
771
772 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
773 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
774 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
775 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
776
777 /* Force Win9x to update DC state */
778 SetPixelV(hdcMetafile, 50, 50, 0);
779
780 ret = GetViewportOrgEx(hdcMetafile, &pt);
781 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
782 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
783 ret = GetViewportExtEx(hdcMetafile, &size);
784 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
785 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
786 ret = SaveDC(hdcMetafile);
787 ok(ret == 1, "ret = %d\n", ret);
788
789 ret = GetViewportOrgEx(hdcMetafile, &pt);
790 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
791 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
792 ret = GetViewportExtEx(hdcMetafile, &size);
793 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
794 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
795 ret = SaveDC(hdcMetafile);
796 ok(ret == 2, "ret = %d\n", ret);
797
798 memset(&orig_lf, 0, sizeof(orig_lf));
799 orig_lf.lfCharSet = ANSI_CHARSET;
800 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
801 orig_lf.lfWeight = FW_DONTCARE;
802 orig_lf.lfHeight = 7;
803 orig_lf.lfQuality = DEFAULT_QUALITY;
804 lstrcpyA(orig_lf.lfFaceName, "Arial");
805 hFont = CreateFontIndirectA(&orig_lf);
806 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
807
808 hFontOld = SelectObject(hdcMetafile, hFont);
809
810 hFont2 = CreateFontIndirectA(&orig_lf);
811 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
812 hFontCheck = SelectObject(hdcMetafile, hFont2);
813 ok(hFontCheck == hFont, "Font not selected\n");
814
815 /* Force Win9x to update DC state */
816 SetPixelV(hdcMetafile, 50, 50, 0);
817
818 ret = RestoreDC(hdcMetafile, 1);
819 ok(ret, "ret = %d\n", ret);
820 ret = GetViewportOrgEx(hdcMetafile, &pt);
821 ok(ret, "GetViewportOrgEx error %u\n", GetLastError());
822 ok(pt.x == 40,"Expecting ViewportOrg x of 40, got %i\n",pt.x);
823 ret = GetViewportExtEx(hdcMetafile, &size);
824 ok(ret, "GetViewportExtEx error %u\n", GetLastError());
825 ok(size.cx == 50,"Expecting ViewportExt cx of 50, got %i\n",size.cx);
826
827 hFontCheck = SelectObject(hdcMetafile, hFontOld);
828 ok(hFontOld == hFontCheck && hFontCheck != hFont && hFontCheck != hFont2,
829 "Font not reverted with DC Restore\n");
830
831 ret = RestoreDC(hdcMetafile, -20);
832 ok(!ret, "ret = %d\n", ret);
833 ret = RestoreDC(hdcMetafile, 20);
834 ok(!ret, "ret = %d\n", ret);
835
836 hMetafile = CloseEnhMetaFile(hdcMetafile);
837 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
838
839 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
840 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
841
842 ret = DeleteObject(hFont);
843 ok( ret, "DeleteObject error %d\n", GetLastError());
844 ret = DeleteObject(hFont2);
845 ok( ret, "DeleteObject error %d\n", GetLastError());
846 ret = DeleteEnhMetaFile(hMetafile);
847 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
848 ret = ReleaseDC(hwnd, hdcDisplay);
849 ok( ret, "ReleaseDC error %d\n", GetLastError());
850 DestroyWindow(hwnd);
851 }
852
853 static void test_mf_SaveDC(void)
854 {
855 HDC hdcMetafile;
856 HMETAFILE hMetafile;
857 int ret;
858 POINT pt;
859 SIZE size;
860 HFONT hFont,hFont2,hFontOld,hFontCheck;
861
862 hdcMetafile = CreateMetaFileA(NULL);
863 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
864
865 ret = SetMapMode(hdcMetafile, MM_ANISOTROPIC);
866 ok (ret, "SetMapMode should not fail\n");
867
868 /* Need to write something to the emf, otherwise Windows won't play it back */
869 LineTo(hdcMetafile, 150, 150);
870
871 pt.x = pt.y = 5555;
872 SetWindowOrgEx(hdcMetafile, 0, 0, &pt);
873 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
874 pt.x = pt.y = 5555;
875 SetViewportOrgEx(hdcMetafile, 0, 0, &pt);
876 ok( pt.x == 5555 && pt.y == 5555, "wrong origin %d,%d\n", pt.x, pt.y);
877 size.cx = size.cy = 5555;
878 SetWindowExtEx(hdcMetafile, 110, 110, &size );
879 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
880 size.cx = size.cy = 5555;
881 SetViewportExtEx(hdcMetafile, 120, 120, &size );
882 ok( size.cx == 5555 && size.cy == 5555, "wrong size %d,%d\n", size.cx, size.cy );
883
884 /* Force Win9x to update DC state */
885 SetPixelV(hdcMetafile, 50, 50, 0);
886
887 ret = GetViewportOrgEx(hdcMetafile, &pt);
888 todo_wine ok (!ret, "GetViewportOrgEx should fail\n");
889 ret = GetViewportExtEx(hdcMetafile, &size);
890 todo_wine ok (!ret, "GetViewportExtEx should fail\n");
891 ret = SaveDC(hdcMetafile);
892 ok(ret == 1, "ret = %d\n", ret);
893
894 SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
895 SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
896 SetWindowExtEx(hdcMetafile, 150, 150, NULL );
897 SetViewportExtEx(hdcMetafile, 200, 200, NULL );
898
899 /* Force Win9x to update DC state */
900 SetPixelV(hdcMetafile, 50, 50, 0);
901
902 ret = SaveDC(hdcMetafile);
903 ok(ret == 1, "ret = %d\n", ret);
904
905 SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
906 SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
907 SetWindowExtEx(hdcMetafile, 120, 120, NULL );
908 SetViewportExtEx(hdcMetafile, 300, 300, NULL );
909
910 /* Force Win9x to update DC state */
911 SetPixelV(hdcMetafile, 50, 50, 0);
912 SetPolyFillMode( hdcMetafile, ALTERNATE );
913 SetBkColor( hdcMetafile, 0 );
914
915 ret = SaveDC(hdcMetafile);
916 ok(ret == 1, "ret = %d\n", ret);
917
918 SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
919 SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
920 SetWindowExtEx(hdcMetafile, 200, 200, NULL );
921 SetViewportExtEx(hdcMetafile, 400, 400, NULL );
922
923 SetPolyFillMode( hdcMetafile, WINDING );
924 SetBkColor( hdcMetafile, 0x123456 );
925 todo_wine ok( !GetPolyFillMode( hdcMetafile ), "GetPolyFillMode succeeded\n" );
926 todo_wine ok( GetBkColor( hdcMetafile ) == CLR_INVALID, "GetBkColor succeeded\n" );
927
928 /* Force Win9x to update DC state */
929 SetPixelV(hdcMetafile, 50, 50, 0);
930
931 ret = RestoreDC(hdcMetafile, -1);
932 ok(ret, "ret = %d\n", ret);
933
934 ret = SaveDC(hdcMetafile);
935 ok(ret == 1, "ret = %d\n", ret);
936
937 ret = RestoreDC(hdcMetafile, 1);
938 ok(ret, "ret = %d\n", ret);
939
940 SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
941 SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
942 SetWindowExtEx(hdcMetafile, 500, 500, NULL );
943 SetViewportExtEx(hdcMetafile, 50, 50, NULL );
944
945 /* Force Win9x to update DC state */
946 SetPixelV(hdcMetafile, 50, 50, 0);
947
948 ret = SaveDC(hdcMetafile);
949 ok(ret == 1, "ret = %d\n", ret);
950
951 ret = SaveDC(hdcMetafile);
952 ok(ret == 1, "ret = %d\n", ret);
953
954 memset(&orig_lf, 0, sizeof(orig_lf));
955 orig_lf.lfCharSet = ANSI_CHARSET;
956 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
957 orig_lf.lfWeight = FW_DONTCARE;
958 orig_lf.lfHeight = 7;
959 orig_lf.lfQuality = DEFAULT_QUALITY;
960 lstrcpyA(orig_lf.lfFaceName, "Arial");
961 hFont = CreateFontIndirectA(&orig_lf);
962 ok(hFont != 0, "CreateFontIndirectA error %d\n", GetLastError());
963
964 hFontOld = SelectObject(hdcMetafile, hFont);
965
966 hFont2 = CreateFontIndirectA(&orig_lf);
967 ok(hFont2 != 0, "CreateFontIndirectA error %d\n", GetLastError());
968 hFontCheck = SelectObject(hdcMetafile, hFont2);
969 ok(hFontCheck == hFont, "Font not selected\n");
970
971 /* Force Win9x to update DC state */
972 SetPixelV(hdcMetafile, 50, 50, 0);
973
974 ret = RestoreDC(hdcMetafile, 1);
975 ok(ret, "ret = %d\n", ret);
976
977 hFontCheck = SelectObject(hdcMetafile, hFontOld);
978 ok(hFontOld != hFontCheck && hFontCheck == hFont2, "Font incorrectly reverted with DC Restore\n");
979
980 /* restore level is ignored */
981 ret = RestoreDC(hdcMetafile, -20);
982 ok(ret, "ret = %d\n", ret);
983 ret = RestoreDC(hdcMetafile, 20);
984 ok(ret, "ret = %d\n", ret);
985 ret = RestoreDC(hdcMetafile, 0);
986 ok(ret, "ret = %d\n", ret);
987
988 hMetafile = CloseMetaFile(hdcMetafile);
989 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
990
991 ret = DeleteMetaFile(hMetafile);
992 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
993 ret = DeleteObject(hFont);
994 ok( ret, "DeleteObject error %d\n", GetLastError());
995 ret = DeleteObject(hFont2);
996 ok( ret, "DeleteObject error %d\n", GetLastError());
997 }
998
999
1000 /* Win-format metafile (mfdrv) tests */
1001 /* These tests compare the generated metafiles byte-by-byte */
1002 /* with the nominal results. */
1003
1004 /* Maximum size of sample metafiles in bytes. */
1005 #define MF_BUFSIZE 1024
1006
1007 /* 8x8 bitmap data for a pattern brush */
1008 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
1009 0x01, 0x00, 0x02, 0x00,
1010 0x03, 0x00, 0x04, 0x00,
1011 0x05, 0x00, 0x06, 0x00,
1012 0x07, 0x00, 0x08, 0x00
1013 };
1014
1015 /* Sample metafiles to be compared to the outputs of the
1016 * test functions.
1017 */
1018
1019 static const unsigned char MF_BLANK_BITS[] = {
1020 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
1021 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1023 };
1024
1025 static const unsigned char MF_GRAPHICS_BITS[] = {
1026 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
1027 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1028 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
1029 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
1030 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
1031 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
1032 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
1033 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
1034 0x00, 0x00, 0x00, 0x00
1035 };
1036
1037 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
1038 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
1039 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
1040 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
1041 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1042 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1043 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1044 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1045 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
1048 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1049 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1050 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1051 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1052 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1053 0x00, 0x00
1054 };
1055
1056 static const unsigned char MF_DCBRUSH_BITS[] =
1057 {
1058 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x2a, 0x00,
1059 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00,
1060 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xfc, 0x02,
1061 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
1062 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00,
1063 0x08, 0x00, 0x00, 0x00, 0xfa, 0x02, 0x00, 0x00,
1064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1065 0x04, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x01, 0x00,
1066 0x07, 0x00, 0x00, 0x00, 0x1b, 0x04, 0x14, 0x00,
1067 0x14, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x03, 0x00,
1068 0x00, 0x00, 0x00, 0x00
1069 };
1070
1071 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
1072 {
1073 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
1074 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1075 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
1076 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
1077 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
1078 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
1079 0x00, 0x00
1080 };
1081
1082 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
1083 {
1084 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1086 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
1089 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1090 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1091 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1094 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1097 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
1098 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
1099 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1101 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
1102 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
1103 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
1104 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
1105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1106 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1107 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
1108 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
1109 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1110 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1111 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1112 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1113 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1114 0x14, 0x00, 0x00, 0x00
1115 };
1116
1117 static const unsigned char MF_LINETO_BITS[] = {
1118 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1119 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1120 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1121 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1122 0x00, 0x00
1123 };
1124
1125 static const unsigned char EMF_LINETO_BITS[] = {
1126 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1128 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1130 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1131 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1132 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1133 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1135 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1136 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1138 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1139 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1140 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1141 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1142 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
1143 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1144 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1146 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1147 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1148 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1149 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1150 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1151 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1152 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1153 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1154 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1155 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1156 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1157 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1158 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1159 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1160 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1161 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1163 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1164 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1165 };
1166
1167 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
1168 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1170 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1173 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1174 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
1175 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1178 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1180 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1181 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
1182 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
1183 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
1184 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
1185 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
1186 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
1189 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
1190 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
1191 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
1192 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1193 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1194 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1195 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1196 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1197 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1198 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1199 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
1200 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
1201 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1202 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
1203 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1205 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
1207 };
1208
1209 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
1210 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1212 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
1215 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1216 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1217 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1219 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1220 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
1223 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
1224 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1225 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1226 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
1227 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1228 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
1229 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1230 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
1231 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1232 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
1233 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
1234 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1236 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1237 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1238 0x14, 0x00, 0x00, 0x00
1239 };
1240
1241 static const unsigned char EMF_BITBLT[] =
1242 {
1243 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1245 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1247 0x4f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
1248 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1249 0x64, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1250 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1252 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
1253 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
1254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1255 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
1256 0x30, 0xda, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00,
1257 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1259 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1261 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1263 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1267 0x64, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1268 0x8c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1269 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1270 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1271 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1280 0x4c, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1285 0x62, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
1287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1288 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
1293 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1295 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1296 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1297 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0xcc, 0x00,
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1299 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, 0x00, 0x00,
1300 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x23, 0x3c,
1301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
1303 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1304 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1305 0x90, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1306 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1307 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1318 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1319 0x14, 0x00, 0x00, 0x00
1320 };
1321
1322 static const unsigned char EMF_DCBRUSH_BITS[] =
1323 {
1324 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1325 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1326 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1327 0x39, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00,
1328 0x52, 0x02, 0x00, 0x00, 0x52, 0x02, 0x00, 0x00,
1329 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1330 0x44, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
1331 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
1334 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
1335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1336 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
1337 0x80, 0xa9, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
1338 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x80,
1339 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1340 0x13, 0x00, 0x00, 0x80, 0x27, 0x00, 0x00, 0x00,
1341 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1342 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1344 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1345 0x26, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
1346 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1348 0x33, 0x44, 0x55, 0x00, 0x25, 0x00, 0x00, 0x00,
1349 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1350 0x2b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
1351 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1352 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
1353 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1354 0x01, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
1355 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1356 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00,
1357 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
1358 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1359 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
1360 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
1361 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1362 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1363 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1364 0x14, 0x00, 0x00, 0x00
1365 };
1366
1367 static const unsigned char EMF_BEZIER_BITS[] =
1368 {
1369 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1373 0x1a, 0x2a, 0x0d, 0x00, 0x1a, 0x2f, 0x0d, 0x00,
1374 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1375 0x44, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1376 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1378 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1379 0x51, 0x01, 0x00, 0x00, 0x0e, 0x01, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x00, 0x00, 0x00, 0x00, 0x68, 0x24, 0x05, 0x00,
1382 0xb0, 0x1e, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
1383 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1384 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1385 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1386 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1387 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x00, 0x00, 0x00,
1388 0x2c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1389 0x0a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1390 0x19, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1391 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00,
1392 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00,
1393 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
1394 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1395 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1396 0x04, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1397 0x01, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1398 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1399 0x0f, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
1400 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1401 0x34, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1402 0x0f, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1403 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1404 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
1405 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1406 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
1407 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1408 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1409 0x14, 0x00, 0x00, 0x00
1410 };
1411
1412 static const unsigned char EMF_POLYPOLYLINE_BITS[] =
1413 {
1414 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1415 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1416 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1417 0x61, 0x01, 0x00, 0x00, 0xc2, 0x02, 0x00, 0x00,
1418 0x7a, 0xd4, 0x13, 0x00, 0xe8, 0x44, 0x00, 0x00,
1419 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1420 0x84, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1421 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423 0xa1, 0x05, 0x00, 0x00, 0x47, 0x03, 0x00, 0x00,
1424 0xfc, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1426 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc1, 0x07, 0x00,
1427 0x2c, 0x84, 0x04, 0x00, 0x5a, 0x00, 0x00, 0x00,
1428 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1429 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1430 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
1432 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
1434 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
1435 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1436 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00,
1437 0x5a, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
1438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1439 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1440 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1441 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1442 0x0a, 0x00, 0x14, 0x00, 0x64, 0x00, 0xc8, 0x00,
1443 0x07, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1445 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1446 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1447 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1448 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1449 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1450 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1451 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
1452 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1453 0x00, 0x90, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1454 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1455 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1456 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1457 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00,
1458 0x00, 0x90, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
1459 0x90, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00,
1460 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1461 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1462 0x14, 0x00, 0x00, 0x00
1463 };
1464
1465 static const unsigned char EMF_GRADIENTFILL_BITS[] =
1466 {
1467 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
1468 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1469 0x2b, 0x01, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00,
1470 0x23, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00,
1471 0x31, 0x29, 0x00, 0x00, 0xa3, 0x2a, 0x00, 0x00,
1472 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
1473 0x0c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1474 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1476 0x40, 0x05, 0x00, 0x00, 0x46, 0x03, 0x00, 0x00,
1477 0xda, 0x01, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
1478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1479 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0x07, 0x00,
1480 0xcb, 0x82, 0x04, 0x00, 0x76, 0x00, 0x00, 0x00,
1481 0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1482 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00,
1483 0x35, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1484 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1485 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
1486 0x00, 0xff, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80,
1487 0xc8, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00,
1488 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
1489 0xb4, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
1490 0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xf0, 0xde,
1491 0x2c, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
1492 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1493 0x90, 0x01, 0x00, 0x00, 0x9a, 0x01, 0x00, 0x00,
1494 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00,
1495 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1496 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1497 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1498 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
1499 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1500 0x14, 0x00, 0x00, 0x00
1501 };
1502
1503 /* For debugging or dumping the raw metafiles produced by
1504 * new test functions.
1505 */
1506 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
1507 INT nobj, LPARAM param)
1508 {
1509 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
1510 hdc, mr->rdFunction, mr->rdSize, (void *)param);
1511 return TRUE;
1512 }
1513
1514 /* For debugging or dumping the raw metafiles produced by
1515 * new test functions.
1516 */
1517
1518 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
1519 {
1520 BYTE buf[MF_BUFSIZE];
1521 UINT mfsize, i;
1522
1523 if (!winetest_debug) return;
1524
1525 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1526 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1527
1528 printf ("MetaFile %s has bits:\n{\n ", desc);
1529 for (i=0; i<mfsize; i++)
1530 {
1531 printf ("0x%02x", buf[i]);
1532 if (i == mfsize-1)
1533 printf ("\n");
1534 else if (i % 8 == 7)
1535 printf (",\n ");
1536 else
1537 printf (", ");
1538 }
1539 printf ("};\n");
1540 }
1541
1542 /* Compare the metafile produced by a test function with the
1543 * expected raw metafile data in "bits".
1544 * Return value is 0 for a perfect match,
1545 * -1 if lengths aren't equal,
1546 * otherwise returns the number of non-matching bytes.
1547 */
1548
1549 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
1550 const char *desc)
1551 {
1552 unsigned char buf[MF_BUFSIZE];
1553 UINT mfsize, i;
1554 int diff;
1555
1556 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
1557 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
1558 if (mfsize < MF_BUFSIZE)
1559 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
1560 desc, mfsize, bsize);
1561 else
1562 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
1563 desc, mfsize, bsize);
1564 if (mfsize != bsize)
1565 return -1;
1566
1567 diff = 0;
1568 for (i=0; i<bsize; i++)
1569 {
1570 if (buf[i] != bits[i])
1571 diff++;
1572 }
1573 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1574 desc, mfsize, bsize, diff);
1575
1576 return diff;
1577 }
1578
1579 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
1580 {
1581 unsigned char buf[MF_BUFSIZE];
1582 DWORD mfsize, rd_size, i;
1583 int diff;
1584 HANDLE hfile;
1585 BOOL ret;
1586
1587 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
1588 assert(hfile != INVALID_HANDLE_VALUE);
1589
1590 mfsize = GetFileSize(hfile, NULL);
1591 assert(mfsize <= MF_BUFSIZE);
1592
1593 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
1594 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
1595
1596 CloseHandle(hfile);
1597
1598 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
1599
1600 if (mfsize != bsize)
1601 return -1;
1602
1603 diff = 0;
1604 for (i=0; i<bsize; i++)
1605 {
1606 if (buf[i] != bits[i])
1607 diff++;
1608 }
1609 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
1610 desc, mfsize, bsize, diff);
1611
1612 return diff;
1613 }
1614
1615 /* For debugging or dumping the raw EMFs produced by
1616 * new test functions.
1617 */
1618 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
1619 {
1620 BYTE buf[MF_BUFSIZE];
1621 UINT mfsize, i;
1622
1623 if (!winetest_debug) return;
1624
1625 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1626 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
1627
1628 printf("EMF %s has bits:\n{\n ", desc);
1629 for (i = 0; i < mfsize; i++)
1630 {
1631 printf ("0x%02x", buf[i]);
1632 if (i == mfsize-1)
1633 printf ("\n");
1634 else if (i % 8 == 7)
1635 printf (",\n ");
1636 else
1637 printf (", ");
1638 }
1639 printf ("};\n");
1640 }
1641
1642 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
1643 {
1644 BYTE *emf;
1645 BYTE buf[MF_BUFSIZE];
1646 UINT mfsize, offset;
1647
1648 if (!winetest_debug) return;
1649
1650 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1651 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1652
1653 printf("EMF %s has records:\n", desc);
1654
1655 emf = buf;
1656 offset = 0;
1657 while(offset < mfsize)
1658 {
1659 EMR *emr = (EMR *)(emf + offset);
1660 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
1661 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
1662 offset += emr->nSize;
1663 }
1664 }
1665
1666 static void dump_emf_record(const ENHMETARECORD *emr, const char *desc)
1667 {
1668 const BYTE *buf;
1669 DWORD i;
1670
1671 if (!winetest_debug) return;
1672
1673 printf ("%s: EMF record %u has bits:\n{\n", desc, emr->iType);
1674 buf = (const BYTE *)emr;
1675 for (i = 0; i < emr->nSize; i++)
1676 {
1677 printf ("0x%02x", buf[i]);
1678 if (i == emr->nSize - 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_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
1689 {
1690 trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left, eto->rclBounds.top,
1691 eto->rclBounds.right, eto->rclBounds.bottom);
1692 trace("iGraphicsMode %u\n", eto->iGraphicsMode);
1693 trace("exScale: %f\n", eto->exScale);
1694 trace("eyScale: %f\n", eto->eyScale);
1695 trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x, eto->emrtext.ptlReference.y);
1696 trace("emrtext.nChars %u\n", eto->emrtext.nChars);
1697 trace("emrtext.offString %#x\n", eto->emrtext.offString);
1698 trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
1699 trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left, eto->emrtext.rcl.top,
1700 eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
1701 trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
1702 }
1703
1704 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
1705 const char *desc, BOOL ignore_scaling)
1706 {
1707 int diff;
1708
1709 ok(emr1->iType == emr2->iType, "%s: emr->iType %u != %u\n",
1710 desc, emr1->iType, emr2->iType);
1711
1712 ok(emr1->nSize == emr2->nSize, "%s: emr->nSize %u != %u\n",
1713 desc, emr1->nSize, emr2->nSize);
1714
1715 /* iType and nSize mismatches are fatal */
1716 if (emr1->iType != emr2->iType || emr1->nSize != emr2->nSize) return FALSE;
1717
1718 /* contents of EMR_GDICOMMENT are not interesting */
1719 if (emr1->iType == EMR_GDICOMMENT) return TRUE;
1720
1721 /* different Windows versions setup DC scaling differently when
1722 * converting an old style metafile to an EMF.
1723 */
1724 if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
1725 emr1->iType == EMR_SETVIEWPORTEXTEX))
1726 return TRUE;
1727
1728 if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
1729 {
1730 EMREXTTEXTOUTW *eto1, *eto2;
1731
1732 eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
1733 memcpy(eto1, emr1, emr1->nSize);
1734 eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1735 memcpy(eto2, emr2, emr2->nSize);
1736
1737 /* different Windows versions setup DC scaling differently */
1738 eto1->exScale = eto1->eyScale = 0.0;
1739 eto2->exScale = eto2->eyScale = 0.0;
1740
1741 diff = memcmp(eto1, eto2, emr1->nSize);
1742 if (diff)
1743 {
1744 dump_EMREXTTEXTOUT(eto1);
1745 dump_EMREXTTEXTOUT(eto2);
1746 }
1747 HeapFree(GetProcessHeap(), 0, eto1);
1748 HeapFree(GetProcessHeap(), 0, eto2);
1749 }
1750 else if (emr1->iType == EMR_EXTSELECTCLIPRGN && !lstrcmpA(desc, "emf_clipping"))
1751 {
1752 /* We have to take care of NT4 differences here */
1753 diff = memcmp(emr1, emr2, emr1->nSize);
1754 if (diff)
1755 {
1756 ENHMETARECORD *emr_nt4;
1757
1758 emr_nt4 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
1759 memcpy(emr_nt4, emr2, emr2->nSize);
1760 /* Correct the nRgnSize field */
1761 emr_nt4->dParm[5] = sizeof(RECT);
1762
1763 diff = memcmp(emr1, emr_nt4, emr1->nSize);
1764 if (!diff)
1765 win_skip("Catered for NT4 differences\n");
1766
1767 HeapFree(GetProcessHeap(), 0, emr_nt4);
1768 }
1769 }
1770 else if (emr1->iType == EMR_POLYBEZIERTO16 || emr1->iType == EMR_POLYBEZIER16)
1771 {
1772 EMRPOLYBEZIER16 *eto1, *eto2;
1773
1774 eto1 = (EMRPOLYBEZIER16*)emr1;
1775 eto2 = (EMRPOLYBEZIER16*)emr2;
1776
1777 diff = eto1->cpts != eto2->cpts;
1778 if(!diff)
1779 diff = memcmp(eto1->apts, eto2->apts, eto1->cpts * sizeof(POINTS));
1780 }
1781 else if (emr1->iType == EMR_POLYBEZIERTO || emr1->iType == EMR_POLYBEZIER)
1782 {
1783 EMRPOLYBEZIER *eto1, *eto2;
1784
1785 eto1 = (EMRPOLYBEZIER*)emr1;
1786 eto2 = (EMRPOLYBEZIER*)emr2;
1787
1788 diff = eto1->cptl != eto2->cptl;
1789 if(!diff)
1790 diff = memcmp(eto1->aptl, eto2->aptl, eto1->cptl * sizeof(POINTL));
1791 }
1792 else
1793 diff = memcmp(emr1, emr2, emr1->nSize);
1794
1795 ok(diff == 0, "%s: contents of record %u don't match\n", desc, emr1->iType);
1796
1797 if (diff)
1798 {
1799 dump_emf_record(emr1, "expected bits");
1800 dump_emf_record(emr2, "actual bits");
1801 }
1802
1803 return diff == 0; /* report all non-fatal record mismatches */
1804 }
1805
1806 /* Compare the EMF produced by a test function with the
1807 * expected raw EMF data in "bits".
1808 * Return value is 0 for a perfect match,
1809 * -1 if lengths aren't equal,
1810 * otherwise returns the number of non-matching bytes.
1811 */
1812 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
1813 UINT bsize, const char *desc,
1814 BOOL ignore_scaling)
1815 {
1816 unsigned char buf[MF_BUFSIZE];
1817 UINT mfsize, offset1, offset2, diff_nt4, diff_9x;
1818 const ENHMETAHEADER *emh1, *emh2;
1819
1820 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
1821 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
1822
1823 /* ENHMETAHEADER size could differ, depending on platform */
1824 diff_nt4 = sizeof(SIZEL);
1825 diff_9x = sizeof(SIZEL) + 3 * sizeof(DWORD);
1826
1827 if (mfsize < MF_BUFSIZE)
1828 {
1829 ok(mfsize == bsize ||
1830 broken(mfsize == bsize - diff_nt4) || /* NT4 */
1831 broken(mfsize == bsize - diff_9x), /* Win9x/WinME */
1832 "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
1833 }
1834 else
1835 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
1836 desc, mfsize, bsize);
1837
1838 /* basic things must match */
1839 emh1 = (const ENHMETAHEADER *)bits;
1840 emh2 = (const ENHMETAHEADER *)buf;
1841 ok(emh1->iType == EMR_HEADER, "expected EMR_HEADER, got %u\n", emh1->iType);
1842 ok(emh1->nSize == sizeof(ENHMETAHEADER), "expected sizeof(ENHMETAHEADER), got %u\n", emh1->nSize);
1843 ok(emh2->nBytes == mfsize, "expected emh->nBytes %u, got %u\n", mfsize, emh2->nBytes);
1844 ok(emh1->dSignature == ENHMETA_SIGNATURE, "expected ENHMETA_SIGNATURE, got %u\n", emh1->dSignature);
1845
1846 ok(emh1->iType == emh2->iType, "expected EMR_HEADER, got %u\n", emh2->iType);
1847 ok(emh1->nSize == emh2->nSize ||
1848 broken(emh1->nSize - diff_nt4 == emh2->nSize) ||
1849 broken(emh1->nSize - diff_9x == emh2->nSize),
1850 "expected nSize %u, got %u\n", emh1->nSize, emh2->nSize);
1851 ok(emh1->rclBounds.left == emh2->rclBounds.left, "%s: expected rclBounds.left = %d, got %d\n",
1852 desc, emh1->rclBounds.left, emh2->rclBounds.left);
1853 ok(emh1->rclBounds.top == emh2->rclBounds.top, "%s: expected rclBounds.top = %d, got %d\n",
1854 desc, emh1->rclBounds.top, emh2->rclBounds.top);
1855 ok(emh1->rclBounds.right == emh2->rclBounds.right, "%s: expected rclBounds.right = %d, got %d\n",
1856 desc, emh1->rclBounds.right, emh2->rclBounds.right);
1857 ok(emh1->rclBounds.bottom == emh2->rclBounds.bottom, "%s: expected rclBounds.bottom = %d, got %d\n",
1858 desc, emh1->rclBounds.bottom, emh2->rclBounds.bottom);
1859 ok(emh1->dSignature == emh2->dSignature, "expected dSignature %u, got %u\n", emh1->dSignature, emh2->dSignature);
1860 ok(emh1->nBytes == emh2->nBytes ||
1861 broken(emh1->nBytes - diff_nt4 == emh2->nBytes) ||
1862 broken(emh1->nBytes - diff_9x == emh2->nBytes),
1863 "expected nBytes %u, got %u\n", emh1->nBytes, emh2->nBytes);
1864 ok(emh1->nRecords == emh2->nRecords, "expected nRecords %u, got %u\n", emh1->nRecords, emh2->nRecords);
1865
1866 offset1 = emh1->nSize;
1867 offset2 = emh2->nSize; /* Needed for Win9x/WinME/NT4 */
1868 while (offset1 < emh1->nBytes)
1869 {
1870 const ENHMETARECORD *emr1 = (const ENHMETARECORD *)(bits + offset1);
1871 const ENHMETARECORD *emr2 = (const ENHMETARECORD *)(buf + offset2);
1872
1873 trace("%s: EMF record %u, size %u/record %u, size %u\n",
1874 desc, emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
1875
1876 if (!match_emf_record(emr1, emr2, desc, ignore_scaling)) return -1;
1877
1878 /* We have already bailed out if iType or nSize don't match */
1879 offset1 += emr1->nSize;
1880 offset2 += emr2->nSize;
1881 }
1882 return 0;
1883 }
1884
1885
1886 /* tests blitting to an EMF */
1887 static void test_emf_BitBlt(void)
1888 {
1889 HDC hdcDisplay, hdcMetafile, hdcBitmap;
1890 HBITMAP hBitmap, hOldBitmap;
1891 HENHMETAFILE hMetafile;
1892 #define BMP_DIM 4
1893 BITMAPINFOHEADER bmih =
1894 {
1895 sizeof(BITMAPINFOHEADER),
1896 BMP_DIM,/* biWidth */
1897 BMP_DIM,/* biHeight */
1898 1, /* biPlanes */
1899 24, /* biBitCount */
1900 BI_RGB, /* biCompression */
1901 0, /* biXPelsPerMeter */
1902 0, /* biYPelsPerMeter */
1903 0, /* biClrUsed */
1904 0, /* biClrImportant */
1905 };
1906 void *bits;
1907 XFORM xform;
1908 BOOL ret;
1909
1910 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
1911 ok( hdcDisplay != 0, "CreateDCA error %d\n", GetLastError() );
1912
1913 hdcBitmap = CreateCompatibleDC(hdcDisplay);
1914 ok( hdcBitmap != 0, "CreateCompatibleDC failed\n" );
1915 ok(SetGraphicsMode(hdcBitmap, GM_ADVANCED), "SetGraphicsMode failed\n");
1916 bmih.biXPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSX), 100, 3937);
1917 bmih.biYPelsPerMeter = MulDiv(GetDeviceCaps(hdcDisplay, LOGPIXELSY), 100, 3937);
1918 hBitmap = CreateDIBSection(hdcDisplay, (const BITMAPINFO *)&bmih,
1919 DIB_RGB_COLORS, &bits, NULL, 0);
1920 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
1921
1922 hdcMetafile = CreateEnhMetaFileA(hdcBitmap, NULL, NULL, NULL);
1923 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1924
1925 /* First fill the bitmap DC with something recognizable, like BLACKNESS */
1926 ret = BitBlt(hdcBitmap, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, BLACKNESS);
1927 ok( ret, "BitBlt(BLACKNESS) failed\n" );
1928
1929 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, SRCCOPY);
1930 ok( ret, "BitBlt(SRCCOPY) failed\n" );
1931 ret = BitBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, 0, 0, 0, WHITENESS);
1932 ok( ret, "BitBlt(WHITENESS) failed\n" );
1933
1934 ok(SetMapMode(hdcBitmap, MM_ANISOTROPIC), "SetMapMode failed\n");
1935 ok(SetWindowOrgEx(hdcBitmap, 0, 0, NULL), "SetWindowOrgEx failed\n");
1936 ok(SetWindowExtEx(hdcBitmap, 400, 400, NULL), "SetWindowExtEx failed\n");
1937 ok(SetViewportOrgEx(hdcBitmap, 0, 0, NULL), "SetViewportOrgEx failed\n");
1938 ok(SetViewportExtEx(hdcBitmap, BMP_DIM, BMP_DIM, NULL), "SetViewportExtEx failed\n");
1939 memset(&xform, 0, sizeof(xform));
1940 xform.eM11 = 0.5;
1941 xform.eM22 = 1.0;
1942 ok(SetWorldTransform(hdcBitmap, &xform), "SetWorldTransform failed\n");
1943
1944 ret = StretchBlt(hdcMetafile, 0, 0, BMP_DIM, BMP_DIM, hdcBitmap, 0, 0, 400, 400, SRCCOPY);
1945 ok( ret, "StretchBlt(SRCCOPY) failed\n" );
1946
1947 hMetafile = CloseEnhMetaFile(hdcMetafile);
1948 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
1949
1950 if(compare_emf_bits(hMetafile, EMF_BITBLT, sizeof(EMF_BITBLT),
1951 "emf_BitBlt", FALSE) != 0)
1952 {
1953 dump_emf_bits(hMetafile, "emf_BitBlt");
1954 dump_emf_records(hMetafile, "emf_BitBlt");
1955 }
1956
1957 SelectObject(hdcBitmap, hOldBitmap);
1958 DeleteObject(hBitmap);
1959 DeleteDC(hdcBitmap);
1960 DeleteDC(hdcDisplay);
1961 #undef BMP_DIM
1962 }
1963
1964 static void test_emf_DCBrush(void)
1965 {
1966 HDC hdcMetafile;
1967 HENHMETAFILE hMetafile;
1968 HBRUSH hBrush;
1969 HPEN hPen;
1970 BOOL ret;
1971 COLORREF color;
1972
1973 if (!pSetDCBrushColor || !pSetDCPenColor)
1974 {
1975 win_skip( "SetDCBrush/PenColor not supported\n" );
1976 return;
1977 }
1978
1979 hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
1980 ok( hdcMetafile != 0, "CreateEnhMetaFileA failed\n" );
1981
1982 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
1983 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1984
1985 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
1986 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
1987
1988 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
1989 ok( color == 0xffffff, "SetDCBrushColor returned %x\n", color );
1990
1991 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
1992 ok( color == 0, "SetDCPenColor returned %x\n", color );
1993
1994 Rectangle( hdcMetafile, 10, 10, 20, 20 );
1995
1996 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
1997 ok( color == 0x555555, "SetDCBrushColor returned %x\n", color );
1998
1999 hMetafile = CloseEnhMetaFile(hdcMetafile);
2000 ok( hMetafile != 0, "CloseEnhMetaFile failed\n" );
2001
2002 if (compare_emf_bits (hMetafile, EMF_DCBRUSH_BITS, sizeof(EMF_DCBRUSH_BITS),
2003 "emf_DC_Brush", FALSE ) != 0)
2004 {
2005 dump_emf_bits(hMetafile, "emf_DC_Brush");
2006 dump_emf_records(hMetafile, "emf_DC_Brush");
2007 }
2008 ret = DeleteEnhMetaFile(hMetafile);
2009 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2010 ret = DeleteObject(hBrush);
2011 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2012 ret = DeleteObject(hPen);
2013 ok( ret, "DeleteObject(HPEN) error %d\n", GetLastError());
2014 }
2015
2016 /* Test a blank metafile. May be used as a template for new tests. */
2017
2018 static void test_mf_Blank(void)
2019 {
2020 HDC hdcMetafile;
2021 HMETAFILE hMetafile;
2022 INT caps;
2023 BOOL ret;
2024 INT type;
2025
2026 hdcMetafile = CreateMetaFileA(NULL);
2027 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2028 trace("hdcMetafile %p\n", hdcMetafile);
2029
2030 /* Tests on metafile initialization */
2031 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
2032 ok (caps == DT_METAFILE,
2033 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
2034
2035 hMetafile = CloseMetaFile(hdcMetafile);
2036 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2037 type = GetObjectType(hMetafile);
2038 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2039 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2040
2041 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2042 "mf_blank") != 0)
2043 {
2044 dump_mf_bits(hMetafile, "mf_Blank");
2045 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2046 }
2047
2048 ret = DeleteMetaFile(hMetafile);
2049 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2050 }
2051
2052 static void test_CopyMetaFile(void)
2053 {
2054 HDC hdcMetafile;
2055 HMETAFILE hMetafile, hmf_copy;
2056 BOOL ret;
2057 char temp_path[MAX_PATH];
2058 char mf_name[MAX_PATH];
2059 INT type;
2060
2061 hdcMetafile = CreateMetaFileA(NULL);
2062 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2063 trace("hdcMetafile %p\n", hdcMetafile);
2064
2065 hMetafile = CloseMetaFile(hdcMetafile);
2066 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2067 type = GetObjectType(hMetafile);
2068 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
2069
2070 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
2071 "mf_blank") != 0)
2072 {
2073 dump_mf_bits(hMetafile, "mf_Blank");
2074 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2075 }
2076
2077 GetTempPathA(MAX_PATH, temp_path);
2078 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
2079
2080 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
2081 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
2082
2083 type = GetObjectType(hmf_copy);
2084 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
2085
2086 ret = DeleteMetaFile(hMetafile);
2087 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2088
2089 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
2090 {
2091 dump_mf_bits(hmf_copy, "mf_Blank");
2092 EnumMetaFile(0, hmf_copy, mf_enum_proc, 0);
2093 }
2094
2095 ret = DeleteMetaFile(hmf_copy);
2096 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
2097
2098 DeleteFileA(mf_name);
2099 }
2100
2101 static void test_SetMetaFileBits(void)
2102 {
2103 HMETAFILE hmf;
2104 INT type;
2105 BOOL ret;
2106 BYTE buf[256];
2107 METAHEADER *mh;
2108
2109 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
2110 trace("hmf %p\n", hmf);
2111 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2112 type = GetObjectType(hmf);
2113 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
2114
2115 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2116 {
2117 dump_mf_bits(hmf, "mf_Graphics");
2118 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2119 }
2120
2121 ret = DeleteMetaFile(hmf);
2122 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2123
2124 /* NULL data crashes XP SP1 */
2125 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
2126
2127 /* Now with zero size */
2128 SetLastError(0xdeadbeef);
2129 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
2130 trace("hmf %p\n", hmf);
2131 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2132 ok(GetLastError() == ERROR_INVALID_DATA ||
2133 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2134 "wrong error %d\n", GetLastError());
2135
2136 /* Now with odd size */
2137 SetLastError(0xdeadbeef);
2138 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
2139 trace("hmf %p\n", hmf);
2140 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2141 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %d\n", GetLastError());
2142
2143 /* Now with zeroed out header fields */
2144 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
2145 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2146 mh = (METAHEADER *)buf;
2147 /* corruption of any of the below fields leads to a failure */
2148 mh->mtType = 0;
2149 mh->mtVersion = 0;
2150 mh->mtHeaderSize = 0;
2151 SetLastError(0xdeadbeef);
2152 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2153 trace("hmf %p\n", hmf);
2154 ok(!hmf, "SetMetaFileBitsEx should fail\n");
2155 ok(GetLastError() == ERROR_INVALID_DATA ||
2156 broken(GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
2157 "wrong error %d\n", GetLastError());
2158
2159 /* Now with corrupted mtSize field */
2160 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2161 mh = (METAHEADER *)buf;
2162 /* corruption of mtSize doesn't lead to a failure */
2163 mh->mtSize *= 2;
2164 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2165 trace("hmf %p\n", hmf);
2166 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2167
2168 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2169 {
2170 dump_mf_bits(hmf, "mf_Graphics");
2171 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2172 }
2173
2174 ret = DeleteMetaFile(hmf);
2175 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2176
2177 #ifndef _WIN64 /* Generates access violation on XP x64 and Win2003 x64 */
2178 /* Now with zeroed out mtSize field */
2179 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
2180 mh = (METAHEADER *)buf;
2181 /* zeroing mtSize doesn't lead to a failure */
2182 mh->mtSize = 0;
2183 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
2184 trace("hmf %p\n", hmf);
2185 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
2186
2187 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
2188 {
2189 dump_mf_bits(hmf, "mf_Graphics");
2190 EnumMetaFile(0, hmf, mf_enum_proc, 0);
2191 }
2192
2193 ret = DeleteMetaFile(hmf);
2194 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
2195 #endif
2196 }
2197
2198 /* Simple APIs from mfdrv/graphics.c
2199 */
2200
2201 static void test_mf_Graphics(void)
2202 {
2203 HDC hdcMetafile;
2204 HMETAFILE hMetafile;
2205 POINT oldpoint;
2206 BOOL ret;
2207
2208 hdcMetafile = CreateMetaFileA(NULL);
2209 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2210 trace("hdcMetafile %p\n", hdcMetafile);
2211
2212 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
2213 ok( ret, "MoveToEx error %d.\n", GetLastError());
2214 ret = LineTo(hdcMetafile, 2, 2);
2215 ok( ret, "LineTo error %d.\n", GetLastError());
2216 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
2217 ok( ret, "MoveToEx error %d.\n", GetLastError());
2218
2219 /* oldpoint gets garbage under Win XP, so the following test would
2220 * work under Wine but fails under Windows:
2221 *
2222 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
2223 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
2224 * oldpoint.x, oldpoint.y);
2225 */
2226
2227 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
2228 ok( ret, "Ellipse error %d.\n", GetLastError());
2229
2230 hMetafile = CloseMetaFile(hdcMetafile);
2231 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2232 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2233
2234 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
2235 "mf_Graphics") != 0)
2236 {
2237 dump_mf_bits(hMetafile, "mf_Graphics");
2238 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2239 }
2240
2241 ret = DeleteMetaFile(hMetafile);
2242 ok( ret, "DeleteMetaFile(%p) error %d\n",
2243 hMetafile, GetLastError());
2244 }
2245
2246 static void test_mf_PatternBrush(void)
2247 {
2248 HDC hdcMetafile;
2249 HMETAFILE hMetafile;
2250 LOGBRUSH *orig_lb;
2251 HBRUSH hBrush;
2252 BOOL ret;
2253
2254 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
2255
2256 orig_lb->lbStyle = BS_PATTERN;
2257 orig_lb->lbColor = RGB(0, 0, 0);
2258 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
2259 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %d.\n", GetLastError());
2260
2261 hBrush = CreateBrushIndirect (orig_lb);
2262 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
2263
2264 hdcMetafile = CreateMetaFileA(NULL);
2265 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
2266 trace("hdcMetafile %p\n", hdcMetafile);
2267
2268 hBrush = SelectObject(hdcMetafile, hBrush);
2269 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2270
2271 hMetafile = CloseMetaFile(hdcMetafile);
2272 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2273 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
2274
2275 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
2276 "mf_Pattern_Brush") != 0)
2277 {
2278 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
2279 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2280 }
2281
2282 ret = DeleteMetaFile(hMetafile);
2283 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
2284 ret = DeleteObject(hBrush);
2285 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
2286 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
2287 ok( ret, "DeleteObject(HBITMAP) error %d\n",
2288 GetLastError());
2289 HeapFree (GetProcessHeap(), 0, orig_lb);
2290 }
2291
2292 static void test_mf_DCBrush(void)
2293 {
2294 HDC hdcMetafile;
2295 HMETAFILE hMetafile;
2296 HBRUSH hBrush;
2297 HPEN hPen;
2298 BOOL ret;
2299 COLORREF color;
2300
2301 if (!pSetDCBrushColor || !pSetDCPenColor)
2302 {
2303 win_skip( "SetDCBrush/PenColor not supported\n" );
2304 return;
2305 }
2306
2307 hdcMetafile = CreateMetaFileA(NULL);
2308 ok( hdcMetafile != 0, "CreateMetaFileA failed\n" );
2309
2310 hBrush = SelectObject(hdcMetafile, GetStockObject(DC_BRUSH));
2311 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
2312
2313 hPen = SelectObject(hdcMetafile, GetStockObject(DC_PEN));
2314 ok(hPen != 0, "SelectObject error %d.\n", GetLastError());
2315
2316 color = pSetDCBrushColor( hdcMetafile, RGB(0x55,0x55,0x55) );
2317 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2318
2319 color = pSetDCPenColor( hdcMetafile, RGB(0x33,0x44,0x55) );
2320 ok( color == CLR_INVALID, "SetDCPenColor returned %x\n", color );
2321
2322 Rectangle( hdcMetafile, 10, 10, 20, 20 );
2323
2324 color = pSetDCBrushColor( hdcMetafile, RGB(0x12,0x34,0x56) );
2325 ok( color == CLR_INVALID, "SetDCBrushColor returned %x\n", color );
2326
2327 hMetafile = CloseMetaFile(hdcMetafile);
2328 ok( hMetafile != 0, "CloseMetaFile failed\n" );
2329
2330 if (compare_mf_bits(hMetafile, MF_DCBRUSH_BITS, sizeof(MF_DCBRUSH_BITS), "mf_DCBrush") != 0)
2331 {
2332 dump_mf_bits(hMetafile, "mf_DCBrush");
2333 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2334 }
2335 ret = DeleteMetaFile(hMetafile);
2336 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2337 }
2338
2339 static void test_mf_ExtTextOut_on_path(void)
2340 {
2341 HDC hdcMetafile;
2342 HMETAFILE hMetafile;
2343 BOOL ret;
2344 static const INT dx[4] = { 3, 5, 8, 12 };
2345
2346 hdcMetafile = CreateMetaFileA(NULL);
2347 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
2348 trace("hdcMetafile %p\n", hdcMetafile);
2349
2350 ret = BeginPath(hdcMetafile);
2351 ok(!ret, "BeginPath on metafile DC should fail\n");
2352
2353 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2354 ok(ret, "ExtTextOut error %d\n", GetLastError());
2355
2356 ret = EndPath(hdcMetafile);
2357 ok(!ret, "EndPath on metafile DC should fail\n");
2358
2359 hMetafile = CloseMetaFile(hdcMetafile);
2360 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
2361
2362 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
2363 "mf_TextOut_on_path") != 0)
2364 {
2365 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
2366 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
2367 }
2368
2369 ret = DeleteMetaFile(hMetafile);
2370 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
2371 }
2372
2373 static void test_emf_ExtTextOut_on_path(void)
2374 {
2375 HWND hwnd;
2376 HDC hdcDisplay, hdcMetafile;
2377 HENHMETAFILE hMetafile;
2378 BOOL ret;
2379 static const INT dx[4] = { 3, 5, 8, 12 };
2380
2381 /* Win9x doesn't play EMFs on invisible windows */
2382 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
2383 0, 0, 200, 200, 0, 0, 0, NULL);
2384 ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
2385
2386 hdcDisplay = GetDC(hwnd);
2387 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
2388
2389 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
2390 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
2391
2392 ret = BeginPath(hdcMetafile);
2393 ok(ret, "BeginPath error %d\n", GetLastError());
2394
2395 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
2396 todo_wine ok(ret, "ExtTextOut error %d\n", GetLastError());
2397
2398 ret = EndPath(hdcMetafile);
2399 ok(ret, "EndPath error %d\n", GetLastError());
2400
2401 hMetafile = CloseEnhMetaFile(hdcMetafile);
2402 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
2403
2404 /* this doesn't succeed yet: EMF has correct size, all EMF records
2405 * are there, but their contents don't match for different reasons.
2406 */
2407 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
2408 "emf_TextOut_on_path", FALSE) != 0)
2409 {
2410 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
2411 dump_emf_records(hMetafile, "emf_TextOut_on_path");
2412 }
2413
2414 ret = DeleteEnhMetaFile(hMetafile);
2415 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
2416 ret = ReleaseDC(hwnd, hdcDisplay);
2417 ok(ret, "ReleaseDC error %d\n", GetLastError());
2418 DestroyWindow(hwnd);
2419 }
2420
2421 static const unsigned char EMF_CLIPPING[] =
2422 {
2423 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
2424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2425 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2427 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
2428 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
2429 0x04, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
2430 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2432 0x80, 0x07, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00,
2433 0xfc, 0x01, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00,
2434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2435 0x00, 0x00, 0x00, 0x00, 0x60, 0xc0, 0x07, 0x00,
2436 0x30, 0xda, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00,
2437 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2438 0x01, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00,
2439 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
2440 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
2441 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2442 0x10, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2443 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2444 0x00, 0x04, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2445 0x64, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
2446 0x00, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
2447 0x08, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
2448 0x18, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
2449 0x64, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00,
2450 0xff, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
2451 0x08, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
2452 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2453 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
2454 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2455 0x14, 0x00, 0x00, 0x00
2456 };
2457
2458 static void translate( POINT *pt, UINT count, const XFORM *xform )
2459 {
2460 while (count--)
2461 {
2462 FLOAT x = (FLOAT)pt->x;
2463 FLOAT y = (FLOAT)pt->y;
2464 pt->x = (LONG)floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
2465 pt->y = (LONG)floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
2466 pt++;
2467 }
2468 }
2469
2470 /* Compare rectangles allowing rounding errors */
2471 static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
2472 {
2473 return abs(rc1->left - rc2->left) <= 1 &&
2474 abs(rc1->top - rc2->top) <= 1 &&
2475 abs(rc1->right - rc2->right) <= 1 &&
2476 abs(rc1->bottom - rc2->bottom) <= 1;
2477 }
2478
2479 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
2480 const ENHMETARECORD *emr, int n_objs, LPARAM param)
2481 {
2482 if (emr->iType == EMR_EXTSELECTCLIPRGN)
2483 {
2484 const EMREXTSELECTCLIPRGN *clip = (const EMREXTSELECTCLIPRGN *)emr;
2485 union _rgn
2486 {
2487 RGNDATA data;
2488 char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
2489 };
2490 const union _rgn *rgn1;
2491 union _rgn rgn2;
2492 RECT rect, rc_transformed;
2493 const RECT *rc = (const RECT *)param;
2494 HRGN hrgn;
2495 XFORM xform;
2496 INT ret;
2497 BOOL is_win9x;
2498
2499 trace("EMR_EXTSELECTCLIPRGN: cbRgnData %#x, iMode %u\n",
2500 clip->cbRgnData, clip->iMode);
2501
2502 ok(clip->iMode == RGN_COPY, "expected RGN_COPY, got %u\n", clip->iMode);
2503 ok(clip->cbRgnData >= sizeof(RGNDATAHEADER) + sizeof(RECT),
2504 "too small data block: %u bytes\n", clip->cbRgnData);
2505 if (clip->cbRgnData < sizeof(RGNDATAHEADER) + sizeof(RECT))
2506 return 0;
2507
2508 rgn1 = (const union _rgn *)clip->RgnData;
2509
2510 trace("size %u, type %u, count %u, rgn size %u, bound %s\n",
2511 rgn1->data.rdh.dwSize, rgn1->data.rdh.iType,
2512 rgn1->data.rdh.nCount, rgn1->data.rdh.nRgnSize,
2513 wine_dbgstr_rect(&rgn1->data.rdh.rcBound));
2514
2515 ok(EqualRect(&rgn1->data.rdh.rcBound, rc), "rects don't match\n");
2516
2517 rect = *(const RECT *)rgn1->data.Buffer;
2518 trace("rect %s\n", wine_dbgstr_rect(&rect));
2519 ok(EqualRect(&rect, rc), "rects don't match\n");
2520
2521 ok(rgn1->data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u\n", rgn1->data.rdh.dwSize);
2522 ok(rgn1->data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn1->data.rdh.iType);
2523 ok(rgn1->data.rdh.nCount == 1, "expected 1, got %u\n", rgn1->data.rdh.nCount);
2524 ok(rgn1->data.rdh.nRgnSize == sizeof(RECT) ||
2525 broken(rgn1->data.rdh.nRgnSize == 168), /* NT4 */
2526 "expected sizeof(RECT), got %u\n", rgn1->data.rdh.nRgnSize);
2527
2528 hrgn = CreateRectRgn(0, 0, 0, 0);
2529
2530 memset(&xform, 0, sizeof(xform));
2531 SetLastError(0xdeadbeef);
2532 ret = GetWorldTransform(hdc, &xform);
2533 is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
2534 if (!is_win9x)
2535 ok(ret, "GetWorldTransform error %u\n", GetLastError());
2536
2537 trace("xform.eM11 %f, xform.eM22 %f\n", xform.eM11, xform.eM22);
2538
2539 ret = GetClipRgn(hdc, hrgn);
2540 ok(ret == 0, "GetClipRgn returned %d, expected 0\n", ret);
2541
2542 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
2543
2544 ret = GetClipRgn(hdc, hrgn);
2545 ok(ret == 1, "GetClipRgn returned %d, expected 1\n", ret);
2546
2547 /* Win9x returns empty clipping region */
2548 if (is_win9x) return 1;
2549
2550 ret = GetRegionData(hrgn, 0, NULL);
2551 ok(ret == sizeof(rgn2.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
2552
2553 ret = GetRegionData(hrgn, sizeof(rgn2), &rgn2.data);
2554