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