gdi/tests: Win64 printf format warning fixes.
[wine/wine-kai.git] / dlls / gdi / tests / metafile.c
blobd7e655e8e5ed80d16b85696cf8a12deda78e823d
1 /*
2 * Unit tests for metafile functions
4 * Copyright (c) 2002 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
31 static LOGFONTA orig_lf;
32 static BOOL emr_processed = FALSE;
34 /* Arbitrarily chosen values for the second co-ordinate of a metafile line */
35 #define LINE_X 55.0f
36 #define LINE_Y 15.0f
38 static INT (WINAPI * pGetRelAbs)(HDC, DWORD);
39 static INT (WINAPI * pSetRelAbs)(HDC, INT);
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); \
46 static void init_function_pointers(void)
48 HMODULE hGDI;
50 pGetRelAbs = NULL;
51 pSetRelAbs = NULL;
53 hGDI = GetModuleHandleA("gdi32.dll");
54 assert(hGDI);
55 GDI_GET_PROC(GetRelAbs);
56 GDI_GET_PROC(SetRelAbs);
59 static int CALLBACK eto_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60 const ENHMETARECORD *emr, int n_objs, LPARAM param)
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;
69 trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
70 hdc, emr->iType, emr->nSize, (void *)param);
72 if(!hdc) return 1;
74 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
76 switch (emr->iType)
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));
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));
92 n_record = 0;
93 break;
95 case EMR_EXTTEXTOUTA:
97 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
98 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
100 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
101 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
103 /* compare up to lfOutPrecision, other values are not interesting,
104 * and in fact sometimes arbitrary adapted by Win9x.
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");
109 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
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]);
114 n_record++;
115 emr_processed = TRUE;
116 break;
119 case EMR_EXTTEXTOUTW:
121 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
122 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
124 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
125 ok( ret == sizeof(device_lf), "GetObjectA error %d\n", GetLastError());
127 /* compare up to lfOutPrecision, other values are not interesting,
128 * and in fact sometimes arbitrary adapted by Win9x.
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");
133 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
135 ok(orig_dx[i] == dx[i], "pass %d: dx[%d] (%d) didn't match %d\n",
136 n_record, i, dx[i], orig_dx[i]);
138 n_record++;
139 emr_processed = TRUE;
140 break;
143 default:
144 break;
147 return 1;
150 static void test_ExtTextOut(void)
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;
161 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
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 %d\n", GetLastError());
168 hdcDisplay = GetDC(hwnd);
169 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
171 trace("hdcDisplay %p\n", hdcDisplay);
173 SetMapMode(hdcDisplay, MM_TEXT);
175 memset(&orig_lf, 0, sizeof(orig_lf));
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 %d\n", GetLastError());
186 hFont = SelectObject(hdcDisplay, hFont);
188 len = lstrlenA(text);
189 for (i = 0; i < len; i++)
191 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
192 ok( ret, "GetCharWidthA error %d\n", GetLastError());
194 hFont = SelectObject(hdcDisplay, hFont);
196 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
199 trace("hdcMetafile %p\n", hdcMetafile);
201 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
202 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
204 hFont = SelectObject(hdcMetafile, hFont);
206 /* 1. pass NULL lpDx */
207 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
208 ok( ret, "ExtTextOutA error %d\n", GetLastError());
210 /* 2. pass custom lpDx */
211 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
212 ok( ret, "ExtTextOutA error %d\n", GetLastError());
214 hFont = SelectObject(hdcMetafile, hFont);
215 ret = DeleteObject(hFont);
216 ok( ret, "DeleteObject error %d\n", GetLastError());
218 hMetafile = CloseEnhMetaFile(hdcMetafile);
219 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
221 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
223 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224 ok( ret, "PlayEnhMetaFile error %d\n", GetLastError());
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);
234 if(pSetRelAbs) pSetRelAbs(hdcDisplay, RELATIVE);
235 SetBkMode(hdcDisplay, OPAQUE);
237 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, &rc);
238 ok( ret, "EnumEnhMetaFile error %d\n", GetLastError());
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 %08x\n", GetBkColor(hdcDisplay));
243 ok( GetTextColor(hdcDisplay) == RGB(0, 0xff, 0), "text color %08x\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));
249 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
251 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, eto_emf_enum_proc, dx, NULL),
252 "A valid hdc has to require a valid rc\n");
254 ok(EnumEnhMetaFile(NULL, hMetafile, eto_emf_enum_proc, dx, NULL),
255 "A null hdc does not require a valid rc\n");
257 ret = DeleteEnhMetaFile(hMetafile);
258 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
259 ret = ReleaseDC(hwnd, hdcDisplay);
260 ok( ret, "ReleaseDC error %d\n", GetLastError());
261 DestroyWindow(hwnd);
264 static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
265 const ENHMETARECORD *emr, int n_objs, LPARAM param)
267 static int save_state;
268 static int restore_no;
270 switch (emr->iType)
272 case EMR_HEADER:
273 save_state = 0;
274 restore_no = 0;
275 break;
277 case EMR_SAVEDC:
278 save_state++;
279 break;
281 case EMR_RESTOREDC:
283 EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr;
284 switch(++restore_no)
286 case 1:
287 ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
288 break;
290 case 2:
291 ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
292 break;
293 case 3:
294 ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
295 break;
297 ok(restore_no <= 3, "restore_no %d\n", restore_no);
298 save_state += restoredc->iRelative;
299 break;
301 case EMR_EOF:
302 ok(save_state == 0, "EOF save_state %d\n", save_state);
303 break;
307 return 1;
310 void test_SaveDC(void)
312 HDC hdcMetafile, hdcDisplay;
313 HENHMETAFILE hMetafile;
314 HWND hwnd;
315 int ret;
316 static const RECT rc = { 0, 0, 100, 100 };
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 %d\n", GetLastError());
323 hdcDisplay = GetDC(hwnd);
324 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
326 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
327 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
329 /* Need to write something to the emf, otherwise Windows won't play it back */
330 LineTo(hdcMetafile, 100, 100);
332 ret = SaveDC(hdcMetafile);
333 ok(ret == 1, "ret = %d\n", ret);
335 ret = SaveDC(hdcMetafile);
336 ok(ret == 2, "ret = %d\n", ret);
338 ret = SaveDC(hdcMetafile);
339 ok(ret == 3, "ret = %d\n", ret);
341 ret = RestoreDC(hdcMetafile, -1);
342 ok(ret, "ret = %d\n", ret);
344 ret = SaveDC(hdcMetafile);
345 ok(ret == 3, "ret = %d\n", ret);
347 ret = RestoreDC(hdcMetafile, 1);
348 ok(ret, "ret = %d\n", ret);
350 ret = SaveDC(hdcMetafile);
351 ok(ret == 1, "ret = %d\n", ret);
353 ret = SaveDC(hdcMetafile);
354 ok(ret == 2, "ret = %d\n", ret);
356 hMetafile = CloseEnhMetaFile(hdcMetafile);
357 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
359 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, savedc_emf_enum_proc, 0, &rc);
360 ok( ret == 1, "EnumEnhMetaFile rets %d\n", ret);
362 ret = DeleteEnhMetaFile(hMetafile);
363 ok( ret, "DeleteEnhMetaFile error %d\n", GetLastError());
364 ret = ReleaseDC(hwnd, hdcDisplay);
365 ok( ret, "ReleaseDC error %d\n", GetLastError());
366 DestroyWindow(hwnd);
369 /* Win-format metafile (mfdrv) tests */
370 /* These tests compare the generated metafiles byte-by-byte */
371 /* with the nominal results. */
373 /* Maximum size of sample metafiles in bytes. */
374 #define MF_BUFSIZE 512
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
384 /* Sample metafiles to be compared to the outputs of the
385 * test functions.
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,
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
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
425 static const unsigned char MF_TEXTOUT_ON_PATH_BITS[] =
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
436 static const unsigned char EMF_TEXTOUT_ON_PATH_BITS[] =
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
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
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
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
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
595 /* For debugging or dumping the raw metafiles produced by
596 * new test functions.
598 static INT CALLBACK mf_enum_proc(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
599 INT nobj, LPARAM param)
601 trace("hdc %p, mr->rdFunction %04x, mr->rdSize %u, param %p\n",
602 hdc, mr->rdFunction, mr->rdSize, (void *)param);
603 return TRUE;
606 /* For debugging or dumping the raw metafiles produced by
607 * new test functions.
610 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
612 BYTE buf[MF_BUFSIZE];
613 UINT mfsize, i;
615 if (!winetest_debug) return;
617 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
618 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
620 printf ("MetaFile %s has bits:\n{\n ", desc);
621 for (i=0; i<mfsize; i++)
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 (", ");
631 printf ("};\n");
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.
641 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
642 const char *desc)
644 unsigned char buf[MF_BUFSIZE];
645 UINT mfsize, i;
646 int diff;
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;
659 diff = 0;
660 for (i=0; i<bsize; i++)
662 if (buf[i] != bits[i])
663 diff++;
665 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
666 desc, mfsize, bsize, diff);
668 return diff;
671 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
673 unsigned char buf[MF_BUFSIZE];
674 DWORD mfsize, rd_size, i;
675 int diff;
676 HANDLE hfile;
677 BOOL ret;
679 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
680 assert(hfile != INVALID_HANDLE_VALUE);
682 mfsize = GetFileSize(hfile, NULL);
683 assert(mfsize <= MF_BUFSIZE);
685 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
686 ok( ret && rd_size == mfsize, "ReadFile: error %d\n", GetLastError());
688 CloseHandle(hfile);
690 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n", desc, mfsize, bsize);
692 if (mfsize != bsize)
693 return -1;
695 diff = 0;
696 for (i=0; i<bsize; i++)
698 if (buf[i] != bits[i])
699 diff++;
701 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
702 desc, mfsize, bsize, diff);
704 return diff;
707 /* For debugging or dumping the raw EMFs produced by
708 * new test functions.
710 static void dump_emf_bits(const HENHMETAFILE mf, const char *desc)
712 BYTE buf[MF_BUFSIZE];
713 UINT mfsize, i;
715 if (!winetest_debug) return;
717 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
718 ok (mfsize > 0, "%s: GetEnhMetaFileBits failed\n", desc);
720 printf("EMF %s has bits:\n{\n ", desc);
721 for (i = 0; i < mfsize; i++)
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 (", ");
731 printf ("};\n");
734 static void dump_emf_records(const HENHMETAFILE mf, const char *desc)
736 BYTE *emf;
737 BYTE buf[MF_BUFSIZE];
738 UINT mfsize, offset;
740 if (!winetest_debug) return;
742 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
743 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
745 printf("EMF %s has records:\n", desc);
747 emf = buf;
748 offset = 0;
749 while(offset < mfsize)
751 EMR *emr = (EMR *)(emf + offset);
752 printf("emr->iType %d, emr->nSize %u\n", emr->iType, emr->nSize);
753 /*trace("emr->iType 0x%04lx, emr->nSize 0x%04lx\n", emr->iType, emr->nSize);*/
754 offset += emr->nSize;
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.
764 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
765 UINT bsize, const char *desc, BOOL todo)
767 unsigned char buf[MF_BUFSIZE];
768 UINT mfsize, i;
769 int diff;
771 mfsize = GetEnhMetaFileBits(mf, MF_BUFSIZE, buf);
772 ok (mfsize > 0, "%s: GetEnhMetaFileBits error %d\n", desc, GetLastError());
774 if (mfsize < MF_BUFSIZE)
776 if (mfsize != bsize && todo)
778 todo_wine
779 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
781 else
782 ok(mfsize == bsize, "%s: mfsize=%d, bsize=%d\n", desc, mfsize, bsize);
784 else
785 ok(bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d\n",
786 desc, mfsize, bsize);
788 if (mfsize != bsize)
789 return -1;
791 diff = 0;
792 for (i = 0; i < bsize; i++)
794 if (buf[i] != bits[i])
795 diff++;
797 if (diff != 0 && todo)
799 todo_wine
801 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
802 desc, mfsize, bsize, diff);
804 return diff;
806 else
808 ok(diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
809 desc, mfsize, bsize, diff);
811 return diff;
815 /* Test a blank metafile. May be used as a template for new tests. */
817 static void test_mf_Blank(void)
819 HDC hdcMetafile;
820 HMETAFILE hMetafile;
821 INT caps;
822 BOOL ret;
823 INT type;
825 hdcMetafile = CreateMetaFileA(NULL);
826 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
827 trace("hdcMetafile %p\n", hdcMetafile);
829 /* Tests on metafile initialization */
830 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
831 ok (caps == DT_METAFILE,
832 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
834 hMetafile = CloseMetaFile(hdcMetafile);
835 ok(hMetafile != 0, "CloseMetaFile error %d\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");
840 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
841 "mf_blank") != 0)
843 dump_mf_bits(hMetafile, "mf_Blank");
844 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
847 ret = DeleteMetaFile(hMetafile);
848 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
851 static void test_CopyMetaFile(void)
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;
860 hdcMetafile = CreateMetaFileA(NULL);
861 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
862 trace("hdcMetafile %p\n", hdcMetafile);
864 hMetafile = CloseMetaFile(hdcMetafile);
865 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
866 type = GetObjectType(hMetafile);
867 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
869 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
870 "mf_blank") != 0)
872 dump_mf_bits(hMetafile, "mf_Blank");
873 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
876 GetTempPathA(MAX_PATH, temp_path);
877 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
879 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
880 ok(hmf_copy != 0, "CopyMetaFile error %d\n", GetLastError());
882 type = GetObjectType(hmf_copy);
883 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
885 ret = DeleteMetaFile(hMetafile);
886 ok( ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
888 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
890 dump_mf_bits(hMetafile, "mf_Blank");
891 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
894 ret = DeleteMetaFile(hmf_copy);
895 ok( ret, "DeleteMetaFile(%p) error %d\n", hmf_copy, GetLastError());
897 DeleteFileA(mf_name);
900 static void test_SetMetaFileBits(void)
902 HMETAFILE hmf;
903 INT type;
904 BOOL ret;
905 BYTE buf[256];
906 METAHEADER *mh;
908 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
909 ok(hmf != 0, "SetMetaFileBitsEx error %d\n", GetLastError());
910 type = GetObjectType(hmf);
911 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
913 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
915 dump_mf_bits(hmf, "mf_Graphics");
916 EnumMetaFile(0, hmf, mf_enum_proc, 0);
919 ret = DeleteMetaFile(hmf);
920 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
922 /* NULL data crashes XP SP1 */
923 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
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 %d\n", GetLastError());
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 %d\n", GetLastError());
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 %d\n", GetLastError());
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 %d\n", GetLastError());
958 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
960 dump_mf_bits(hmf, "mf_Graphics");
961 EnumMetaFile(0, hmf, mf_enum_proc, 0);
964 ret = DeleteMetaFile(hmf);
965 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
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 %d\n", GetLastError());
975 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
977 dump_mf_bits(hmf, "mf_Graphics");
978 EnumMetaFile(0, hmf, mf_enum_proc, 0);
981 ret = DeleteMetaFile(hmf);
982 ok(ret, "DeleteMetaFile(%p) error %d\n", hmf, GetLastError());
985 /* Simple APIs from mfdrv/graphics.c
988 static void test_mf_Graphics(void)
990 HDC hdcMetafile;
991 HMETAFILE hMetafile;
992 POINT oldpoint;
993 BOOL ret;
995 hdcMetafile = CreateMetaFileA(NULL);
996 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
997 trace("hdcMetafile %p\n", hdcMetafile);
999 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
1000 ok( ret, "MoveToEx error %d.\n", GetLastError());
1001 ret = LineTo(hdcMetafile, 2, 2);
1002 ok( ret, "LineTo error %d.\n", GetLastError());
1003 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
1004 ok( ret, "MoveToEx error %d.\n", GetLastError());
1006 /* oldpoint gets garbage under Win XP, so the following test would
1007 * work under Wine but fails under Windows:
1009 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
1010 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
1011 * oldpoint.x, oldpoint.y);
1014 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
1015 ok( ret, "Ellipse error %d.\n", GetLastError());
1017 hMetafile = CloseMetaFile(hdcMetafile);
1018 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1019 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1021 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
1022 "mf_Graphics") != 0)
1024 dump_mf_bits(hMetafile, "mf_Graphics");
1025 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1028 ret = DeleteMetaFile(hMetafile);
1029 ok( ret, "DeleteMetaFile(%p) error %d\n",
1030 hMetafile, GetLastError());
1033 static void test_mf_PatternBrush(void)
1035 HDC hdcMetafile;
1036 HMETAFILE hMetafile;
1037 LOGBRUSH *orig_lb;
1038 HBRUSH hBrush;
1039 BOOL ret;
1041 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
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 %d.\n", GetLastError());
1048 hBrush = CreateBrushIndirect (orig_lb);
1049 ok(hBrush != 0, "CreateBrushIndirect error %d\n", GetLastError());
1051 hdcMetafile = CreateMetaFileA(NULL);
1052 ok(hdcMetafile != 0, "CreateMetaFileA error %d\n", GetLastError());
1053 trace("hdcMetafile %p\n", hdcMetafile);
1055 hBrush = SelectObject(hdcMetafile, hBrush);
1056 ok(hBrush != 0, "SelectObject error %d.\n", GetLastError());
1058 hMetafile = CloseMetaFile(hdcMetafile);
1059 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1060 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
1062 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
1063 "mf_Pattern_Brush") != 0)
1065 dump_mf_bits(hMetafile, "mf_Pattern_Brush");
1066 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1069 ret = DeleteMetaFile(hMetafile);
1070 ok( ret, "DeleteMetaFile error %d\n", GetLastError());
1071 ret = DeleteObject(hBrush);
1072 ok( ret, "DeleteObject(HBRUSH) error %d\n", GetLastError());
1073 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
1074 ok( ret, "DeleteObject(HBITMAP) error %d\n",
1075 GetLastError());
1076 HeapFree (GetProcessHeap(), 0, orig_lb);
1079 static void test_mf_ExtTextOut_on_path(void)
1081 HDC hdcMetafile;
1082 HMETAFILE hMetafile;
1083 BOOL ret;
1084 static const INT dx[4] = { 3, 5, 8, 12 };
1086 hdcMetafile = CreateMetaFileA(NULL);
1087 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %d\n", GetLastError());
1088 trace("hdcMetafile %p\n", hdcMetafile);
1090 ret = BeginPath(hdcMetafile);
1091 ok(!ret, "BeginPath on metafile DC should fail\n");
1093 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1094 ok(ret, "ExtTextOut error %d\n", GetLastError());
1096 ret = EndPath(hdcMetafile);
1097 ok(!ret, "EndPath on metafile DC should fail\n");
1099 hMetafile = CloseMetaFile(hdcMetafile);
1100 ok(hMetafile != 0, "CloseMetaFile error %d\n", GetLastError());
1102 if (compare_mf_bits(hMetafile, MF_TEXTOUT_ON_PATH_BITS, sizeof(MF_TEXTOUT_ON_PATH_BITS),
1103 "mf_TextOut_on_path") != 0)
1105 dump_mf_bits(hMetafile, "mf_TextOut_on_path");
1106 EnumMetaFile(0, hMetafile, mf_enum_proc, 0);
1109 ret = DeleteMetaFile(hMetafile);
1110 ok(ret, "DeleteMetaFile(%p) error %d\n", hMetafile, GetLastError());
1113 static void test_emf_ExtTextOut_on_path(void)
1115 HWND hwnd;
1116 HDC hdcDisplay, hdcMetafile;
1117 HENHMETAFILE hMetafile;
1118 BOOL ret;
1119 static const INT dx[4] = { 3, 5, 8, 12 };
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 %d\n", GetLastError());
1126 hdcDisplay = GetDC(hwnd);
1127 ok(hdcDisplay != 0, "GetDC error %d\n", GetLastError());
1129 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
1130 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
1132 ret = BeginPath(hdcMetafile);
1133 ok(ret, "BeginPath error %d\n", GetLastError());
1135 ret = ExtTextOutA(hdcMetafile, 11, 22, 0, NULL, "Test", 4, dx);
1136 ok(ret, "ExtTextOut error %d\n", GetLastError());
1138 ret = EndPath(hdcMetafile);
1139 ok(ret, "EndPath error %d\n", GetLastError());
1141 hMetafile = CloseEnhMetaFile(hdcMetafile);
1142 ok(hMetafile != 0, "CloseEnhMetaFile error %d\n", GetLastError());
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.
1147 if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
1148 "emf_TextOut_on_path", TRUE) != 0)
1150 dump_emf_bits(hMetafile, "emf_TextOut_on_path");
1151 dump_emf_records(hMetafile, "emf_TextOut_on_path");
1154 ret = DeleteEnhMetaFile(hMetafile);
1155 ok(ret, "DeleteEnhMetaFile error %d\n", GetLastError());
1156 ret = ReleaseDC(hwnd, hdcDisplay);
1157 ok(ret, "ReleaseDC error %d\n", GetLastError());
1158 DestroyWindow(hwnd);
1161 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
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 %d, nSize %d, (%d,%d)-(%d,%d)\n",
1170 lpEMFR->iType, lpEMFR->nSize,
1171 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
1173 if (lpEMFR->iType == EMR_LINETO)
1175 INT x0, y0, x1, y1;
1176 if (!lpMFP || lpMFP->mm == MM_TEXT)
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);
1183 else
1185 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%d\n", lpMFP->mm);
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));
1192 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
1193 "(%d,%d)->(%d,%d), expected (%d,%d)->(%d,%d)\n",
1194 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
1195 x0, y0, x1, y1);
1197 return TRUE;
1200 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
1202 HDC hdcMf;
1203 HMETAFILE hmf;
1204 BOOL ret;
1205 UINT size;
1206 LPBYTE pBits;
1208 hdcMf = CreateMetaFile(NULL);
1209 ok(hdcMf != NULL, "CreateMetaFile failed with error %d\n", GetLastError());
1210 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
1211 ok(ret, "LineTo failed with error %d\n", GetLastError());
1212 hmf = CloseMetaFile(hdcMf);
1213 ok(hmf != NULL, "CloseMetaFile failed with error %d\n", GetLastError());
1215 if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
1217 dump_mf_bits(hmf, "mf_LineTo");
1218 EnumMetaFile(0, hmf, mf_enum_proc, 0);
1221 size = GetMetaFileBitsEx(hmf, 0, NULL);
1222 ok(size, "GetMetaFileBitsEx failed with error %d\n", GetLastError());
1223 pBits = HeapAlloc(GetProcessHeap(), 0, size);
1224 GetMetaFileBitsEx(hmf, size, pBits);
1225 DeleteMetaFile(hmf);
1226 return SetWinMetaFileBits(size, pBits, NULL, mfp);
1229 static void test_mf_conversions(void)
1231 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
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);
1243 if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
1244 "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
1246 dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
1247 dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
1250 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1252 DeleteEnhMetaFile(hemf);
1253 DeleteDC(hdcOffscreen);
1256 trace("Testing MF->EMF conversion (MM_TEXT)\n");
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);
1268 if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
1269 "emf_LineTo MM_TEXT", TRUE) != 0)
1271 dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
1272 dump_emf_records(hemf, "emf_LineTo MM_TEXT");
1275 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
1277 DeleteEnhMetaFile(hemf);
1278 DeleteDC(hdcOffscreen);
1281 trace("Testing MF->EMF conversion (NULL mfp)\n");
1283 HDC hdcOffscreen = CreateCompatibleDC(NULL);
1284 HENHMETAFILE hemf;
1285 RECT rect = { 0, 0, 100, 100 };
1286 hemf = create_converted_emf(NULL);
1288 if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
1289 "emf_LineTo NULL", TRUE) != 0)
1291 dump_emf_bits(hemf, "emf_LineTo NULL");
1292 dump_emf_records(hemf, "emf_LineTo NULL");
1295 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
1297 DeleteEnhMetaFile(hemf);
1298 DeleteDC(hdcOffscreen);
1302 static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1303 LONG mm, LONG xExt, LONG yExt,
1304 RECTL * rclBounds, RECTL * rclFrame)
1306 METAFILEPICT mfp;
1307 METAFILEPICT * mfpPtr = NULL;
1308 HENHMETAFILE emf;
1309 ENHMETAHEADER header;
1310 UINT res;
1312 if (!mfpIsNull)
1314 mfp.mm = mm;
1315 mfp.xExt = xExt;
1316 mfp.yExt = yExt;
1317 mfpPtr = &mfp;
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;
1328 *rclBounds = header.rclBounds;
1329 *rclFrame = header.rclFrame;
1330 return TRUE;
1333 static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
1334 LONG mm, LONG xExt, LONG yExt,
1335 RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
1337 RECTL rclBounds, rclFrame;
1339 if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
1341 const char * msg;
1342 char buf[64];
1344 if (mfpIsNull)
1346 msg = "mfp == NULL";
1348 else
1350 const char * mm_str;
1351 switch (mm)
1353 case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
1354 case MM_ISOTROPIC: mm_str = "MM_ISOTROPIC"; break;
1355 default: mm_str = "Unexpected";
1357 sprintf(buf, "mm=%s, xExt=%d, yExt=%d", mm_str, xExt, yExt);
1358 msg = buf;
1361 ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %d, got %d (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
1362 ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %d, got %d (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
1363 ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %d, got %d (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
1364 ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %d, got %d (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
1365 ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %d, got %d (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
1366 ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %d, got %d (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
1367 ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %d, got %d (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
1368 ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %d, got %d (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
1372 static void test_SetWinMetaFileBits(void)
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;
1386 wmfDC = CreateMetaFile(NULL);
1387 ok(wmfDC != NULL, "CreateMetaFile failed\n");
1388 if (!wmfDC) return;
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;
1398 buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
1399 ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
1400 if (buffer_size == 0)
1402 DeleteMetaFile(wmf);
1403 return;
1406 buffer = (BYTE *)HeapAlloc(GetProcessHeap(), 0, buffer_size);
1407 ok(buffer != NULL, "HeapAlloc failed\n");
1408 if (!buffer)
1410 DeleteMetaFile(wmf);
1411 return;
1414 res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
1415 ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
1416 DeleteMetaFile(wmf);
1417 if (res != buffer_size)
1419 HeapFree(GetProcessHeap(), 0, buffer);
1420 return;
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);
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");
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");
1437 dc = CreateCompatibleDC(NULL);
1438 todo_wine
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 (%dx%d)\n",
1443 GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
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
1453 ok(diffx <= 1 && diffy <= 1,
1454 "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%dx%d)\n",
1455 GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
1457 DeleteDC(dc);
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);
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);
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);
1481 /* Ordinary conversions */
1483 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
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");
1491 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
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");
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");
1504 if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
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");
1510 HeapFree(GetProcessHeap(), 0, buffer);
1513 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
1514 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
1515 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
1517 static void test_gdiis(void)
1519 RECT rect = {0,0,100,100};
1520 HDC hdc, hemfDC, hmfDC;
1521 HENHMETAFILE hemf;
1522 HMODULE hgdi32;
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");
1530 /* they should all exist or none should exist */
1531 if(!pGdiIsMetaPrintDC)
1532 return;
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");
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));
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");
1551 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
1552 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
1553 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
1555 hemf = CloseEnhMetaFile(hemfDC);
1556 ok(hemf != NULL, "failed to close EMF\n");
1557 DeleteObject(hemf);
1558 ReleaseDC(NULL,hdc);
1561 START_TEST(metafile)
1563 init_function_pointers();
1565 /* For enhanced metafiles (enhmfdrv) */
1566 test_ExtTextOut();
1567 test_SaveDC();
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();
1578 /* For metafile conversions */
1579 test_mf_conversions();
1580 test_SetWinMetaFileBits();
1582 test_gdiis();