- Move NCI generated files to arch-specific directories
[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 %ld, emr->nSize %ld, 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 %08lx\n", GetBkColor(hdc));
81 ok(GetTextColor(hdc) == RGB(0x0, 0x0, 0x0), "text color %08lx\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 %ld\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[%ld] (%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 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
125 ok( ret == sizeof(device_lf), "GetObjectA error %ld\n", GetLastError());
126
127 /* compare up to lfOutPrecision, other values are not interesting,
128 * and in fact sometimes arbitrary adapted by Win9x.
129 */
130 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
131 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
132
133 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
134 {
135 ok(orig_dx[i] == dx[i], "pass %d: dx[%ld] (%d) didn't match %d\n",
136 n_record, i, dx[i], orig_dx[i]);
137 }
138 n_record++;
139 emr_processed = TRUE;
140 break;
141 }
142
143 default:
144 break;
145 }
146
147 return 1;
148 }
149
150 static void test_ExtTextOut(void)
151 {
152 HWND hwnd;
153 HDC hdcDisplay, hdcMetafile;
154 HENHMETAFILE hMetafile;
155 HFONT hFont;
156 static const char text[] = "Simple text to test ExtTextOut on metafiles";
157 INT i, len, dx[256];
158 static const RECT rc = { 0, 0, 100, 100 };
159 BOOL ret;
160
161 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
162
163 /* Win9x doesn't play EMFs on invisible windows */
164 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
165 0, 0, 200, 200, 0, 0, 0, NULL);
166 ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
167
168 hdcDisplay = GetDC(hwnd);
169 ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
170
171 trace("hdcDisplay %p\n", hdcDisplay);
172
173 SetMapMode(hdcDisplay, MM_TEXT);
174
175 memset(&orig_lf, 0, sizeof(orig_lf));
176
177 orig_lf.lfCharSet = ANSI_CHARSET;
178 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
179 orig_lf.lfWeight = FW_DONTCARE;
180 orig_lf.lfHeight = 7;
181 orig_lf.lfQuality = DEFAULT_QUALITY;
182 lstrcpyA(orig_lf.lfFaceName, "Arial");
183 hFont = CreateFontIndirectA(&orig_lf);
184 ok(hFont != 0, "CreateFontIndirectA error %ld\n", GetLastError());
185
186 hFont = SelectObject(hdcDisplay, hFont);
187
188 len = lstrlenA(text);
189 for (i = 0; i < len; i++)
190 {
191 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
192 ok( ret, "GetCharWidthA error %ld\n", GetLastError());
193 }
194 hFont = SelectObject(hdcDisplay, hFont);
195
196 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
198
199 trace("hdcMetafile %p\n", hdcMetafile);
200
201 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
202 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
203
204 hFont = SelectObject(hdcMetafile, hFont);
205
206 /* 1. pass NULL lpDx */
207 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
208 ok( ret, "ExtTextOutA error %ld\n", GetLastError());
209
210 /* 2. pass custom lpDx */
211 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
212 ok( ret, "ExtTextOutA error %ld\n", GetLastError());
213
214 hFont = SelectObject(hdcMetafile, hFont);
215 ret = DeleteObject(hFont);
216 ok( ret, "DeleteObject error %ld\n", GetLastError());
217
218 hMetafile = CloseEnhMetaFile(hdcMetafile);
219 ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
220
221 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
222
223 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224 ok( ret, "PlayEnhMetaFile error %ld\n", GetLastError());
225
226 SetTextAlign(hdcDisplay, TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING );
227 SetBkColor(hdcDisplay, RGB(0xff, 0, 0));
228 SetTextColor(hdcDisplay, RGB(0, 0xff, 0));
229 SetROP2(hdcDisplay, R2_NOT);
230 SetArcDirection(hdcDisplay, AD_CLOCKWISE);
231 SetPolyFillMode(hdcDisplay, WINDING);
232 SetStretchBltMode(hdcDisplay, HALFTONE);
233
234 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
235 SetBkMode(hdcDisplay, OPAQUE);
236
237 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
238 ok( ret, "EnumEnhMetaFile error %ld\n", GetLastError());
239
240 ok( GetTextAlign(hdcDisplay) == (TA_UPDATECP | TA_CENTER | TA_BASELINE | TA_RTLREADING),
241 "text align %08x\n", GetTextAlign(hdcDisplay));
242 ok( GetBkColor(hdcDisplay) == RGB(0xff, 0, 0), "bk color %08lx\n", GetBkColor(hdcDisplay));
243 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08lx\n", GetTextColor(hdcDisplay));
244 ok( GetROP2(hdcDisplay) == R2_NOT, "rop2 %d\n", GetROP2(hdcDisplay));
245 ok( GetArcDirection(hdcDisplay) == AD_CLOCKWISE, "arc dir %d\n", GetArcDirection(hdcDisplay));
246 ok( GetPolyFillMode(hdcDisplay) == WINDING, "poly fill %d\n", GetPolyFillMode(hdcDisplay));
247 ok( GetStretchBltMode(hdcDisplay) == HALFTONE, "stretchblt mode %d\n", GetStretchBltMode(hdcDisplay));
248
249 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
250
251 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
252 "A valid hdc has to require a valid rc\n");
253
254 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
255 "A null hdc does not require a valid rc\n");
256
257 ret = DeleteEnhMetaFile(hMetafile);
258 ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
259 ret = ReleaseDC(hwnd, hdcDisplay);
260 ok( ret, "ReleaseDC error %ld\n", GetLastError());
261 DestroyWindow(hwnd);
262 }
263
264 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
265 const ENHMETARECORD *emr, int n_objs, LPARAM param)
266 {
267 static int save_state;
268 static int restore_no;
269
270 switch (emr->iType)
271 {
272 case EMR_HEADER:
273 save_state = 0;
274 restore_no = 0;
275 break;
276
277 case EMR_SAVEDC:
278 save_state++;
279 break;
280
281 case EMR_RESTOREDC:
282 {
283 EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr;
284 switch(++restore_no)
285 {
286 case 1:
287 ok(restoredc->iRelative == -1, "first restore %ld\n", restoredc->iRelative);
288 break;
289
290 case 2:
291 ok(restoredc->iRelative == -3, "second restore %ld\n", restoredc->iRelative);
292 break;
293 case 3:
294 ok(restoredc->iRelative == -2, "third restore %ld\n", restoredc->iRelative);
295 break;
296 }
297 ok(restore_no <= 3, "restore_no %d\n", restore_no);
298 save_state += restoredc->iRelative;
299 break;
300 }
301 case EMR_EOF:
302 ok(save_state == 0, "EOF save_state %d\n", save_state);
303 break;
304 }
305
306
307 return 1;
308 }
309
310 void test_SaveDC(void)
311 {
312 HDC hdcMetafile, hdcDisplay;
313 HENHMETAFILE hMetafile;
314 HWND hwnd;
315 int ret;
316 static const RECT rc = { 0, 0, 100, 100 };
317
318 /* Win9x doesn't play EMFs on invisible windows */
319 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
320 0, 0, 200, 200, 0, 0, 0, NULL);
321 ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
322
323 hdcDisplay = GetDC(hwnd);
324 ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
325
326 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
327 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
328
329 /* Need to write something to the emf, otherwise Windows won't play it back */
330 LineTo(hdcMetafile, 100, 100);
331
332 ret = SaveDC(hdcMetafile);
333 ok(ret == 1, "ret = %d\n", ret);
334
335 ret = SaveDC(hdcMetafile);
336 ok(ret == 2, "ret = %d\n", ret);
337
338 ret = SaveDC(hdcMetafile);
339 ok(ret == 3, "ret = %d\n", ret);
340
341 ret = RestoreDC(hdcMetafile, -1);
342 ok(ret, "ret = %d\n", ret);
343
344 ret = SaveDC(hdcMetafile);
345 ok(ret == 3, "ret = %d\n", ret);
346
347 ret = RestoreDC(hdcMetafile, 1);
348 ok(ret, "ret = %d\n", ret);
349
350 ret = SaveDC(hdcMetafile);
351 ok(ret == 1, "ret = %d\n", ret);
352
353 ret = SaveDC(hdcMetafile);
354 ok(ret == 2, "ret = %d\n", ret);
355
356 hMetafile = CloseEnhMetaFile(hdcMetafile);
357 ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
358
359 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
360 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
361
362 ret = DeleteEnhMetaFile(hMetafile);
363 ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
364 ret = ReleaseDC(hwnd, hdcDisplay);
365 ok( ret, "ReleaseDC error %ld\n", GetLastError());
366 DestroyWindow(hwnd);
367 }
368
369 /* Win-format metafile (mfdrv) tests */
370 /* These tests compare the generated metafiles byte-by-byte */
371 /* with the nominal results. */
372
373 /* Maximum size of sample metafiles in bytes. */
374 #define MF_BUFSIZE 512
375
376 /* 8x8 bitmap data for a pattern brush */
377 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
378 0x01, 0x00, 0x02, 0x00,
379 0x03, 0x00, 0x04, 0x00,
380 0x05, 0x00, 0x06, 0x00,
381 0x07, 0x00, 0x08, 0x00
382 };
383
384 /* Sample metafiles to be compared to the outputs of the
385 * test functions.
386 */
387
388 static const unsigned char MF_BLANK_BITS[] = {
389 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
392 };
393
394 static const unsigned char MF_GRAPHICS_BITS[] = {
395 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
398 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
399 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
400 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
401 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
402 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
403 0x00, 0x00, 0x00, 0x00
404 };
405
406 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
407 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
408 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
410 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
411 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
412 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
417 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
418 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
419 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
420 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
421 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
422 0x00, 0x00
423 };
424
425 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
426 {
427 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x19, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x0a,
430 0x16, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00,
431 0x54, 0x65, 0x73, 0x74, 0x03, 0x00, 0x05, 0x00,
432 0x08, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x00, 0x00,
433 0x00, 0x00
434 };
435
436 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
437 {
438 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0xe7, 0xff, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xff,
443 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
444 0xf4, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
445 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
448 0x40, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00,
451 0x80, 0xa9, 0x03, 0x00, 0x3b, 0x00, 0x00, 0x00,
452 0x08, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
453 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
455 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0xc8, 0x41, 0x00, 0x80, 0xbb, 0x41,
457 0x0b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
458 0x04, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
461 0xff, 0xff, 0xff, 0xff, 0x54, 0x00, 0x00, 0x00,
462 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
463 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
464 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
465 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
466 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
467 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
468 0x14, 0x00, 0x00, 0x00
469 };
470
471 static const unsigned char MF_LINETO_BITS[] = {
472 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
475 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
476 0x00, 0x00
477 };
478
479 static const unsigned char EMF_LINETO_BITS[] = {
480 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
481 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
485 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
486 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
487 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
490 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
493 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
494 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
495 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
496 0x00, 0x03, 0x00, 0x00, 0x60, 0xe5, 0xf4, 0x73,
497 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
498 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
501 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
503 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
504 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
505 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
506 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
507 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
508 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
509 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
510 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
511 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
512 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
513 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
514 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
515 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
516 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
517 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
519 };
520
521 static const unsigned char EMF_LINETO_MM_ANISOTROPIC_BITS[] = {
522 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
527 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
528 0x38, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
529 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
532 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
534 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
535 0xe0, 0x93, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
536 0x48, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
537 0x47, 0x44, 0x49, 0x43, 0x01, 0x00, 0x00, 0x80,
538 0x00, 0x03, 0x00, 0x00, 0xa4, 0xfe, 0xf4, 0x73,
539 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
540 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x11, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x02,
543 0x0f, 0x00, 0x37, 0x00, 0x03, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
545 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
546 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
547 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
548 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
549 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
550 0x36, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
551 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
552 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
553 0x07, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x00,
554 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
555 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
556 0x0f, 0x00, 0x00, 0x80, 0x4b, 0x00, 0x00, 0x00,
557 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x05, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
559 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
560 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00
561 };
562
563 static const unsigned char EMF_LINETO_MM_TEXT_BITS[] = {
564 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x37, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568 0x61, 0x06, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
569 0x20, 0x45, 0x4d, 0x46, 0x00, 0x00, 0x01, 0x00,
570 0xe4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
571 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
574 0x7c, 0x01, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x05, 0x00,
577 0xe0, 0x93, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
578 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
579 0x00, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
580 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
581 0x00, 0x04, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
582 0x10, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
583 0x0f, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
584 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80,
585 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
586 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00,
587 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80,
588 0x4b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
589 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
590 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
592 0x14, 0x00, 0x00, 0x00
593 };
594
595 /* For debugging or dumping the raw metafiles produced by
596 * new test functions.
597 */
598 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
599 INT nobj, LPARAM param)
600 {
601 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %lu, param %p\n",
602 hdc, mr->rdFunction, mr->rdSize, (void *)param);
603 return TRUE;
604 }
605
606 /* For debugging or dumping the raw metafiles produced by
607 * new test functions.
608 */
609
610 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
611 {
612 BYTE buf[MF_BUFSIZE];
613 UINT mfsize, i;
614
615 if (!winetest_debug) return;
616
617 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
618 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
619
620 printf ("MetaFile %s has bits:\n{\n ", desc);
621 for (i=0; i<mfsize; i++)
622 {
623 printf ("0x%02x", buf[i]);
624 if (i == mfsize-1)
625 printf ("\n");
626 else if (i % 8 == 7)
627 printf (",\n ");
628 else
629 printf (", ");
630 }
631 printf ("};\n");
632 }
633
634 /* Compare the metafile produced by a test function with the
635 * expected raw metafile data in "bits".
636 * Return value is 0 for a perfect match,
637 * -1 if lengths aren't equal,
638 * otherwise returns the number of non-matching bytes.
639 */
640
641 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
642 const char *desc)
643 {
644 unsigned char buf[MF_BUFSIZE];
645 UINT mfsize, i;
646 int diff;
647
648 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
649 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
650 if (mfsize < MF_BUFSIZE)
651 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
652 desc, mfsize, bsize);
653 else
654 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
655 desc, mfsize, bsize);
656 if (mfsize != bsize)
657 return -1;
658
659 diff = 0;
660 for (i=0; i<bsize; i++)
661 {
662 if (buf[i] != bits[i])
663 diff++;
664 }
665 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
666 desc, mfsize, bsize, diff);
667
668 return diff;
669 }
670
671 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
672 {
673 unsigned char buf[MF_BUFSIZE];
674 DWORD mfsize, rd_size, i;
675 int diff;
676 HANDLE hfile;
677 BOOL ret;
678
679 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
680 assert(hfile != INVALID_HANDLE_VALUE);
681
682 mfsize = GetFileSize(hfile, NULL);
683 assert(mfsize <= MF_BUFSIZE);
684
685 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
686 ok( ret && rd_size == mfsize, "ReadFile: error %ld\n", GetLastError());
687
688 CloseHandle(hfile);
689
690 ok(mfsize == bsize, "%s: mfsize=%ld, bsize=%d.\n", desc, mfsize, bsize);
691
692 if (mfsize != bsize)
693 return -1;
694
695 diff = 0;
696 for (i=0; i<bsize; i++)
697 {
698 if (buf[i] != bits[i])
699 diff++;
700 }
701 ok(diff == 0, "%s: mfsize=%ld, bsize=%d, diff=%d\n",
702 desc, mfsize, bsize, diff);
703
704 return diff;
705 }
706
707 /* For debugging or dumping the raw EMFs produced by
708 * new test functions.
709 */
710 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
711 {
712 BYTE buf[MF_BUFSIZE];
713 UINT mfsize, i;
714
715 if (!winetest_debug) return;
716
717 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
718 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
719
720 printf("EMF %s has bits:\n{\n ", desc);
721 for (i = 0; i < mfsize; i++)
722 {
723 printf ("0x%02x", buf[i]);
724 if (i == mfsize-1)
725 printf ("\n");
726 else if (i % 8 == 7)
727 printf (",\n ");
728 else
729 printf (", ");
730 }
731 printf ("};\n");
732 }
733
734 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
735 {
736 BYTE *emf;
737 BYTE buf[MF_BUFSIZE];
738 UINT mfsize, offset;
739
740 if (!winetest_debug) return;
741
742 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
743 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %ld\n", desc, GetLastError());
744
745 printf("EMF %s has records:\n", desc);
746
747 emf = buf;
748 offset = 0;
749 while(offset < mfsize)
750 {
751 EMR *emr = (EMR *)(emf + offset);
752 printf("emr->iType %ld, emr->nSize %lu\n", emr->iType, emr->nSize);
753 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
754 offset += emr->nSize;
755 }
756 }
757
758 /* Compare the EMF produced by a test function with the
759 * expected raw EMF data in "bits".
760 * Return value is 0 for a perfect match,
761 * -1 if lengths aren't equal,
762 * otherwise returns the number of non-matching bytes.
763 */
764 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
765 UINT bsize, const char *desc, BOOL todo)
766 {
767 unsigned char buf[MF_BUFSIZE];
768 UINT mfsize, i;
769 int diff;
770
771 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
772 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %ld\n", desc, GetLastError());
773
774 if (mfsize < MF_BUFSIZE)
775 {
776 if (mfsize != bsize && todo)
777 {
778 todo_wine
779 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
780 }
781 else
782 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
783 }
784 else
785 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
786 desc, mfsize, bsize);
787
788 if (mfsize != bsize)
789 return -1;
790
791 diff = 0;
792 for (i = 0; i < bsize; i++)
793 {
794 if (buf[i] != bits[i])
795 diff++;
796 }
797 if (diff != 0 && todo)
798 {
799 todo_wine
800 {
801 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
802 desc, mfsize, bsize, diff);
803 }
804 return diff;
805 }
806 else
807 {
808 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
809 desc, mfsize, bsize, diff);
810
811 return diff;
812 }
813 }
814
815 /* Test a blank metafile. May be used as a template for new tests. */
816
817 static void test_mf_Blank(void)
818 {
819 HDC hdcMetafile;
820 HMETAFILE hMetafile;
821 INT caps;
822 BOOL ret;
823 INT type;
824
825 hdcMetafile = CreateMetaFileA(NULL);
826 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
827 trace("hdcMetafile %p\n", hdcMetafile);
828
829 /* Tests on metafile initialization */
830 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
831 ok (caps == DT_METAFILE,
832 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
833
834 hMetafile = CloseMetaFile(hdcMetafile);
835 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
836 type = GetObjectType(hMetafile);
837 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
838 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
839
840 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
841 "mf_blank") != 0)
842 {
843 dump_mf_bits(hMetafile, "mf_Blank");
844 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
845 }
846
847 ret = DeleteMetaFile(hMetafile);
848 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
849 }
850
851 static void test_CopyMetaFile(void)
852 {
853 HDC hdcMetafile;
854 HMETAFILE hMetafile, hmf_copy;
855 BOOL ret;
856 char temp_path[MAX_PATH];
857 char mf_name[MAX_PATH];
858 INT type;
859
860 hdcMetafile = CreateMetaFileA(NULL);
861 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
862 trace("hdcMetafile %p\n", hdcMetafile);
863
864 hMetafile = CloseMetaFile(hdcMetafile);
865 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
866 type = GetObjectType(hMetafile);
867 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
868
869 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
870 "mf_blank") != 0)
871 {
872 dump_mf_bits(hMetafile, "mf_Blank");
873 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
874 }
875
876 GetTempPathA(MAX_PATH, temp_path);
877 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
878
879 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
880 ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError());
881
882 type = GetObjectType(hmf_copy);
883 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
884
885 ret = DeleteMetaFile(hMetafile);
886 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
887
888 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
889 {
890 dump_mf_bits(hMetafile, "mf_Blank");
891 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
892 }
893
894 ret = DeleteMetaFile(hmf_copy);
895 ok( ret, "DeleteMetaFile(%p) error %ld\n", hmf_copy, GetLastError());
896
897 DeleteFileA(mf_name);
898 }
899
900 static void test_SetMetaFileBits(void)
901 {
902 HMETAFILE hmf;
903 INT type;
904 BOOL ret;
905 BYTE buf[256];
906 METAHEADER *mh;
907
908 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
909 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
910 type = GetObjectType(hmf);
911 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
912
913 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
914 {
915 dump_mf_bits(hmf, "mf_Graphics");
916 EnumMetaFile(0, hmf, mf_enum_proc, 0);
917 }
918
919 ret = DeleteMetaFile(hmf);
920 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
921
922 /* NULL data crashes XP SP1 */
923 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
924
925 /* Now with not zero size */
926 SetLastError(0xdeadbeef);
927 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
928 ok(!hmf, "SetMetaFileBitsEx should fail\n");
929 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
930
931 /* Now with not even size */
932 SetLastError(0xdeadbeef);
933 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
934 ok(!hmf, "SetMetaFileBitsEx should fail\n");
935 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError());
936
937 /* Now with zeroed out or faked some header fields */
938 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
939 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
940 mh = (METAHEADER *)buf;
941 /* corruption of any of the below fields leads to a failure */
942 mh->mtType = 0;
943 mh->mtVersion = 0;
944 mh->mtHeaderSize = 0;
945 SetLastError(0xdeadbeef);
946 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
947 ok(!hmf, "SetMetaFileBitsEx should fail\n");
948 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
949
950 /* Now with corrupted mtSize field */
951 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
952 mh = (METAHEADER *)buf;
953 /* corruption of mtSize doesn't lead to a failure */
954 mh->mtSize *= 2;
955 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
956 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
957
958 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
959 {
960 dump_mf_bits(hmf, "mf_Graphics");
961 EnumMetaFile(0, hmf, mf_enum_proc, 0);
962 }
963
964 ret = DeleteMetaFile(hmf);
965 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
966
967 /* Now with zeroed out mtSize field */
968 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
969 mh = (METAHEADER *)buf;
970 /* zeroing mtSize doesn't lead to a failure */
971 mh->mtSize = 0;
972 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
973 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
974
975 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
976 {
977 dump_mf_bits(hmf, "mf_Graphics");
978 EnumMetaFile(0, hmf, mf_enum_proc, 0);
979 }
980
981 ret = DeleteMetaFile(hmf);
982 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
983 }
984
985 /* Simple APIs from mfdrv/graphics.c
986 */
987
988 static void test_mf_Graphics(void)
989 {
990 HDC hdcMetafile;
991 HMETAFILE hMetafile;
992 POINT oldpoint;
993 BOOL ret;
994
995 hdcMetafile = CreateMetaFileA(NULL);
996 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
997 trace("hdcMetafile %p\n", hdcMetafile);
998
999 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1000 ok( ret, "MoveToEx error %ld.\n", GetLastError());
1001 ret = LineTo(hdcMetafile, 2, 2);
1002 ok( ret, "LineTo error %ld.\n", GetLastError());
1003 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1004 ok( ret, "MoveToEx error %ld.\n", GetLastError());
1005
1006 /* oldpoint gets garbage under Win XP, so the following test would
1007 * work under Wine but fails under Windows:
1008 *
1009 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1010 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1011 * oldpoint.x, oldpoint.y);
1012 */
1013
1014 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1015 ok( ret, "Ellipse error %ld.\n", GetLastError());
1016
1017 hMetafile = CloseMetaFile(hdcMetafile);
1018 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
1019 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1020
1021 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1022 "mf_Graphics") != 0)
1023 {
1024 dump_mf_bits(hMetafile, "mf_Graphics");
1025 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1026 }
1027
1028 ret = DeleteMetaFile(hMetafile);
1029 ok( ret, "DeleteMetaFile(%p) error %ld\n",
1030 hMetafile, GetLastError());
1031 }
1032
1033 static void test_mf_PatternBrush(void)
1034 {
1035 HDC hdcMetafile;
1036 HMETAFILE hMetafile;
1037 LOGBRUSH *orig_lb;
1038 HBRUSH hBrush;
1039 BOOL ret;
1040
1041 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
1042
1043 orig_lb->lbStyle = BS_PATTERN;
1044 orig_lb->lbColor = RGB(0, 0, 0);
1045 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
1046 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
1047
1048 hBrush = CreateBrushIndirect (orig_lb);
1049 ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
1050
1051 hdcMetafile = CreateMetaFileA(NULL);
1052 ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
1053 trace("hdcMetafile %p\n", hdcMetafile);
1054
1055 hBrush = SelectObject(hdcMetafile, hBrush);
1056 ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
1057
1058 hMetafile = CloseMetaFile(hdcMetafile);
1059 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
1060 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1061
1062 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1063 "mf_Pattern_Brush") != 0)
1064 {
1065 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1066 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1067 }
1068
1069 ret = DeleteMetaFile(hMetafile);
1070 ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
1071 ret = DeleteObject(hBrush);
1072 ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
1073 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1074 ok( ret, "DeleteObject(HBITMAP) error %ld\n",
1075 GetLastError());
1076 HeapFree (GetProcessHeap(), 0, orig_lb);
1077 }
1078
1079 static void test_mf_ExtTextOut_on_path(void)
1080 {
1081 HDC hdcMetafile;
1082 HMETAFILE hMetafile;
1083 BOOL ret;
1084 static const INT dx[4] = { 3, 5, 8, 12 };
1085
1086 hdcMetafile = CreateMetaFileA(NULL);
1087 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
1088 trace("hdcMetafile %p\n", hdcMetafile);
1089
1090 ret = BeginPath(hdcMetafile);
1091 ok(!ret, "BeginPath on metafile DC should fail\n");
1092
1093 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1094 ok(ret, "ExtTextOut error %ld\n", GetLastError());
1095
1096 ret = EndPath(hdcMetafile);
1097 ok(!ret, "EndPath on metafile DC should fail\n");
1098
1099 hMetafile = CloseMetaFile(hdcMetafile);
1100 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
1101
1102 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1103 "mf_TextOut_on_path") != 0)
1104 {
1105 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1106 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1107 }
1108
1109 ret = DeleteMetaFile(hMetafile);
1110 ok(ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
1111 }
1112
1113 static void test_emf_ExtTextOut_on_path(void)
1114 {
1115 HWND hwnd;
1116 HDC hdcDisplay, hdcMetafile;
1117 HENHMETAFILE hMetafile;
1118 BOOL ret;
1119 static const INT dx[4] = { 3, 5, 8, 12 };
1120
1121 /* Win9x doesn't play EMFs on invisible windows */
1122 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
1123 0, 0, 200, 200, 0, 0, 0, NULL);
1124 ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
1125
1126 hdcDisplay = GetDC(hwnd);
1127 ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
1128
1129 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1130 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
1131
1132 ret = BeginPath(hdcMetafile);
1133 ok(ret, "BeginPath error %ld\n", GetLastError());
1134
1135 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1136 ok(ret, "ExtTextOut error %ld\n", GetLastError());
1137
1138 ret = EndPath(hdcMetafile);
1139 ok(ret, "EndPath error %ld\n", GetLastError());
1140
1141 hMetafile = CloseEnhMetaFile(hdcMetafile);
1142 ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
1143
1144 /* this doesn't succeed yet: EMF has correct size, all EMF records
1145 * are there, but their contents don't match for different reasons.
1146 */
1147 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1148 "emf_TextOut_on_path", TRUE) != 0)
1149 {
1150 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1151 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1152 }
1153
1154 ret = DeleteEnhMetaFile(hMetafile);
1155 ok(ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
1156 ret = ReleaseDC(hwnd, hdcDisplay);
1157 ok(ret, "ReleaseDC error %ld\n", GetLastError());
1158 DestroyWindow(hwnd);
1159 }
1160
1161 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
1162 {
1163 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
1164 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
1165 /* When using MM_TEXT Win9x does not update the mapping mode
1166 * until a record is played which actually outputs something */
1167 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
1168 LPtoDP(hdc, mapping, 2);
1169 trace("Meta record: iType %ld, nSize %ld, (%ld,%ld)-(%ld,%ld)\n",
1170 lpEMFR->iType, lpEMFR->nSize,
1171 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1172
1173 if (lpEMFR->iType == EMR_LINETO)
1174 {
1175 INT x0, y0, x1, y1;
1176 if (!lpMFP || lpMFP->mm == MM_TEXT)
1177 {
1178 x0 = 0;
1179 y0 = 0;
1180 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
1181 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
1182 }
1183 else
1184 {
1185 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%ld\n", lpMFP->mm);
1186
1187 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1188 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1189 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
1190 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
1191 }
1192 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1193 "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
1194 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1195 x0, y0, x1, y1);
1196 }
1197 return TRUE;
1198 }
1199
1200 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1201 {
1202 HDC hdcMf;
1203 HMETAFILE hmf;
1204 BOOL ret;
1205 UINT size;
1206 LPBYTE pBits;
1207
1208 hdcMf = CreateMetaFile(NULL);
1209 ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
1210 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1211 ok(ret, "LineTo failed with error %ld\n", GetLastError());
1212 hmf = CloseMetaFile(hdcMf);
1213 ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());
1214
1215 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1216 {
1217 dump_mf_bits(hmf, "mf_LineTo");
1218 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1219 }
1220
1221 size = GetMetaFileBitsEx(hmf, 0, NULL);
1222 ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
1223 pBits = HeapAlloc(GetProcessHeap(), 0, size);
1224 GetMetaFileBitsEx(hmf, size, pBits);
1225 DeleteMetaFile(hmf);
1226 return SetWinMetaFileBits(size, pBits, NULL, mfp);
1227 }
1228
1229 static void test_mf_conversions(void)
1230 {
1231 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
1232 {
1233 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1234 HENHMETAFILE hemf;
1235 METAFILEPICT mfp;
1236 RECT rect = { 0, 0, 100, 100 };
1237 mfp.mm = MM_ANISOTROPIC;
1238 mfp.xExt = 100;
1239 mfp.yExt = 100;
1240 mfp.hMF = NULL;
1241 hemf = create_converted_emf(&mfp);
1242
1243 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1244 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1245 {
1246 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1247 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1248 }
1249
1250 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1251
1252 DeleteEnhMetaFile(hemf);
1253 DeleteDC(hdcOffscreen);
1254 }
1255
1256 trace("Testing MF->EMF conversion (MM_TEXT)\n");
1257 {
1258 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1259 HENHMETAFILE hemf;
1260 METAFILEPICT mfp;
1261 RECT rect = { 0, 0, 100, 100 };
1262 mfp.mm = MM_TEXT;
1263 mfp.xExt = 0;
1264 mfp.yExt = 0;
1265 mfp.hMF = NULL;
1266 hemf = create_converted_emf(&mfp);
1267
1268 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1269 "emf_LineTo MM_TEXT", TRUE) != 0)
1270 {
1271 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1272 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1273 }
1274
1275 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1276
1277 DeleteEnhMetaFile(hemf);
1278 DeleteDC(hdcOffscreen);
1279 }
1280
1281 trace("Testing MF->EMF conversion (NULL mfp)\n");
1282 {
1283 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1284 HENHMETAFILE hemf;
1285 RECT rect = { 0, 0, 100, 100 };
1286 hemf = create_converted_emf(NULL);
1287
1288 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1289 "emf_LineTo NULL", TRUE) != 0)
1290 {
1291 dump_emf_bits(hemf, "emf_LineTo NULL");
1292 dump_emf_records(hemf, "emf_LineTo NULL");
1293 }
1294
1295 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1296
1297 DeleteEnhMetaFile(hemf);
1298 DeleteDC(hdcOffscreen);
1299 }
1300 }
1301
1302 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1303 LONG mm, LONG xExt, LONG yExt,
1304 RECTL * rclBounds, RECTL * rclFrame)
1305 {
1306 METAFILEPICT mfp;
1307 METAFILEPICT * mfpPtr = NULL;
1308 HENHMETAFILE emf;
1309 ENHMETAHEADER header;
1310 UINT res;
1311
1312 if (!mfpIsNull)
1313 {
1314 mfp.mm = mm;
1315 mfp.xExt = xExt;
1316 mfp.yExt = yExt;
1317 mfpPtr = &mfp;
1318 }
1319
1320 emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
1321 ok(emf != NULL, "SetWinMetaFileBits failed\n");
1322 if (!emf) return FALSE;
1323 res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
1324 ok(res != 0, "GetEnhMetaHeader failed\n");
1325 DeleteEnhMetaFile(emf);
1326 if (!res) return FALSE;
1327
1328 *rclBounds = header.rclBounds;
1329 *rclFrame = header.rclFrame;
1330 return TRUE;
1331 }
1332
1333 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1334 LONG mm, LONG xExt, LONG yExt,
1335 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1336 {
1337 RECTL rclBounds, rclFrame;
1338
1339 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1340 {
1341 const char * msg;
1342 char buf[64];
1343
1344 if (mfpIsNull)
1345 {
1346 msg = "mfp == NULL";
1347 }
1348 else
1349 {
1350 const char * mm_str;
1351 switch (mm)
1352 {
1353 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1354 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
1355 default: mm_str = "Unexpected";
1356 }
1357 sprintf(buf, "mm=%s, xExt=%ld, yExt=%ld", mm_str, xExt, yExt);
1358 msg = buf;
1359 }
1360
1361 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %ld, got %ld (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1362 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %ld, got %ld (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1363 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %ld, got %ld (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1364 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %ld, got %ld (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1365 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %ld, got %ld (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1366 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %ld, got %ld (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1367 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %ld, got %ld (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1368 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %ld, got %ld (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1369 }
1370 }
1371
1372 static void test_SetWinMetaFileBits(void)
1373 {
1374 HMETAFILE wmf;
1375 HDC wmfDC;
1376 BYTE * buffer;
1377 UINT buffer_size;
1378 RECT rect;
1379 UINT res;
1380 RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
1381 RECTL rclBoundsIsotropic, rclFrameIsotropic;
1382 RECTL rclBounds, rclFrame;
1383 HDC dc;
1384 LONG diffx, diffy;
1385
1386 wmfDC = CreateMetaFile(NULL);
1387 ok(wmfDC != NULL, "CreateMetaFile failed\n");
1388 if (!wmfDC) return;
1389
1390 SetWindowExtEx(wmfDC, 100, 100, NULL);
1391 rect.left = rect.top = 0;
1392 rect.right = rect.bottom = 50;
1393 FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
1394 wmf = CloseMetaFile(wmfDC);
1395 ok(wmf != NULL, "Metafile creation failed\n");
1396 if (!wmf) return;
1397
1398 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1399 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1400 if (buffer_size == 0)
1401 {
1402 DeleteMetaFile(wmf);
1403 return;
1404 }
1405
1406 buffer = (BYTE *)HeapAlloc(GetProcessHeap(), 0, buffer_size);
1407 ok(buffer != NULL, "HeapAlloc failed\n");
1408 if (!buffer)
1409 {
1410 DeleteMetaFile(wmf);
1411 return;
1412 }
1413
1414 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1415 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1416 DeleteMetaFile(wmf);
1417 if (res != buffer_size)
1418 {
1419 HeapFree(GetProcessHeap(), 0, buffer);
1420 return;
1421 }
1422
1423 /* Get the reference bounds and frame */
1424 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1425 getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1426
1427 ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
1428 rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
1429 "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");
1430
1431 ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
1432 ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
1433 diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
1434 if (diffx < 0) diffx = -diffx;
1435 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");
1436
1437 dc = CreateCompatibleDC(NULL);
1438 todo_wine
1439 {
1440 ok(rclBoundsAnisotropic.right == GetDeviceCaps(dc, HORZRES) / 2 - 1 &&
1441 rclBoundsAnisotropic.bottom == GetDeviceCaps(dc, VERTRES) / 2 - 1,
1442 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%ldx%ld)\n",
1443 GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
1444 }
1445
1446 /* Allow 1 mm difference (rounding errors) */
1447 diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
1448 diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
1449 if (diffx < 0) diffx = -diffx;
1450 if (diffy < 0) diffy = -diffy;
1451 todo_wine
1452 {
1453 ok(diffx <= 1 && diffy <= 1,
1454 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%ldx%ld)\n",
1455 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1456 }
1457 DeleteDC(dc);
1458
1459 /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
1460 checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1461
1462 /* If xExt or yExt is zero or negative, the whole device surface is used */
1463 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1464 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1465 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1466 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1467 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1468 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
1469 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1470 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1471 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1472 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1473 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1474 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
1475
1476 /* MSDN says that negative xExt and yExt values specify a ratio.
1477 Check that this is wrong and the whole device surface is used */
1478 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
1479 checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);
1480
1481 /* Ordinary conversions */
1482
1483 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1484 {
1485 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1486 "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
1487 ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
1488 "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
1489 }
1490
1491 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
1492 {
1493 ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
1494 "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
1495 ok(rclBounds.left == 0 && rclBounds.top == 0,
1496 "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");
1497
1498 /* Wine has a rounding error */
1499 diffx = rclBounds.right - rclBounds.bottom;
1500 if (diffx < 0) diffx = -diffx;
1501 ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
1502 }
1503
1504 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
1505 {
1506 ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
1507 "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
1508 }
1509
1510 HeapFree(GetProcessHeap(), 0, buffer);
1511 }
1512
1513 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
1514 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
1515 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
1516
1517 static void test_gdiis(void)
1518 {
1519 RECT rect = {0,0,100,100};
1520 HDC hdc, hemfDC, hmfDC;
1521 HENHMETAFILE hemf;
1522 HMODULE hgdi32;
1523
1524 /* resolve all the functions */
1525 hgdi32 = GetModuleHandle("gdi32");
1526 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
1527 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
1528 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
1529
1530 /* they should all exist or none should exist */
1531 if(!pGdiIsMetaPrintDC)
1532 return;
1533
1534 /* try with nothing */
1535 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
1536 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
1537 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
1538
1539 /* try with a metafile */
1540 hmfDC = CreateMetaFile(NULL);
1541 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
1542 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
1543 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
1544 DeleteObject(CloseMetaFile(hmfDC));
1545
1546 /* try with an enhanced metafile */
1547 hdc = GetDC(NULL);
1548 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
1549 ok(hemfDC != NULL, "failed to create emf\n");
1550
1551 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
1552 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
1553 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
1554
1555 hemf = CloseEnhMetaFile(hemfDC);
1556 ok(hemf != NULL, "failed to close EMF\n");
1557 DeleteObject(hemf);
1558 ReleaseDC(NULL,hdc);
1559 }
1560
1561 START_TEST(metafile)
1562 {
1563 init_function_pointers();
1564
1565 /* For enhanced metafiles (enhmfdrv) */
1566 test_ExtTextOut();
1567 test_SaveDC();
1568
1569 /* For win-format metafiles (mfdrv) */
1570 test_mf_Blank();
1571 test_mf_Graphics();
1572 test_mf_PatternBrush();
1573 test_CopyMetaFile();
1574 test_SetMetaFileBits();
1575 test_mf_ExtTextOut_on_path();
1576 test_emf_ExtTextOut_on_path();
1577
1578 /* For metafile conversions */
1579 test_mf_conversions();
1580 test_SetWinMetaFileBits();
1581
1582 test_gdiis();
1583 }