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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/test.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 */
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); \
44 trace("GetProcAddress(hGDI, \"%s\") failed\n", #func); \
46 static void init_function_pointers(void)
53 hGDI = GetModuleHandleA("gdi32.dll");
55 GDI_GET_PROC(GetRelAbs);
56 GDI_GET_PROC(SetRelAbs);
59 static int CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
60 const ENHMETARECORD *emr, int n_objs, LPARAM param)
65 INT *orig_dx = (INT *)param;
69 trace("hdc %p, emr->iType %ld, emr->nSize %ld, param %p\n",
70 hdc, emr->iType, emr->nSize, (void *)param);
74 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
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));
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));
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 %ld\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[%ld] (%d) didn't match %d\n",
112 n_record, i, dx[i], orig_dx[i]);
115 emr_processed = TRUE;
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 %ld\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[%ld] (%d) didn't match %d\n",
136 n_record, i, dx[i], orig_dx[i]);
139 emr_processed = TRUE;
150 static void test_ExtTextOut(void)
153 HDC hdcDisplay, hdcMetafile;
154 HENHMETAFILE hMetafile;
156 static const char text[] = "Simple text to test ExtTextOut on metafiles";
158 static const RECT rc = { 0, 0, 100, 100 };
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 %ld\n", GetLastError());
168 hdcDisplay = GetDC(hwnd);
169 ok(hdcDisplay != 0, "GetDC error %ld\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 %ld\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 %ld\n", GetLastError());
194 hFont = SelectObject(hdcDisplay, hFont);
196 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
197 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\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 %ld\n", GetLastError());
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());
214 hFont = SelectObject(hdcMetafile, hFont);
215 ret = DeleteObject(hFont);
216 ok( ret, "DeleteObject error %ld\n", GetLastError());
218 hMetafile = CloseEnhMetaFile(hdcMetafile);
219 ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
221 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
223 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
224 ok( ret, "PlayEnhMetaFile error %ld\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, emf_enum_proc, dx, &rc);
238 ok( ret, "EnumEnhMetaFile error %ld\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 %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));
249 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
251 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, NULL),
252 "A valid hdc has to require a valid rc\n");
254 ok(EnumEnhMetaFile(NULL, hMetafile, 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 %ld\n", GetLastError());
259 ret = ReleaseDC(hwnd, hdcDisplay);
260 ok( ret, "ReleaseDC error %ld\n", GetLastError());
263 /* Win-format metafile (mfdrv) tests */
264 /* These tests compare the generated metafiles byte-by-byte */
265 /* with the nominal results. */
267 /* Maximum size of sample metafiles in bytes. */
268 #define MF_BUFSIZE 256
270 /* 8x8 bitmap data for a pattern brush */
271 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
272 0x01, 0x00, 0x02, 0x00,
273 0x03, 0x00, 0x04, 0x00,
274 0x05, 0x00, 0x06, 0x00,
275 0x07, 0x00, 0x08, 0x00
278 /* Sample metafiles to be compared to the outputs of the
282 static const unsigned char MF_BLANK_BITS[] = {
283 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
288 static const unsigned char MF_GRAPHICS_BITS[] = {
289 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
292 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
293 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
294 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
295 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
296 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
297 0x00, 0x00, 0x00, 0x00
300 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
301 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
302 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
304 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
305 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
306 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
311 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
312 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
313 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
314 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
315 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
319 /* For debugging or dumping the raw metafiles produced by
320 * new test functions.
323 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
325 char buf[MF_BUFSIZE];
328 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
329 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
331 printf ("MetaFile %s has bits:\n{\n ", desc);
332 for (i=0; i<mfsize; i++)
334 printf ("0x%.2hhx", buf[i]);
345 /* Compare the metafile produced by a test function with the
346 * expected raw metafile data in "bits".
347 * Return value is 0 for a perfect match,
348 * -1 if lengths aren't equal,
349 * otherwise returns the number of non-matching bytes.
352 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
355 unsigned char buf[MF_BUFSIZE];
359 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
360 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
361 if (mfsize < MF_BUFSIZE)
362 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
363 desc, mfsize, bsize);
365 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
366 desc, mfsize, bsize);
371 for (i=0; i<bsize; i++)
373 if (buf[i] != bits[i])
376 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
377 desc, mfsize, bsize, diff);
382 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
384 unsigned char buf[MF_BUFSIZE];
385 DWORD mfsize, rd_size, i;
390 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
391 assert(hfile != INVALID_HANDLE_VALUE);
393 mfsize = GetFileSize(hfile, NULL);
394 assert(mfsize <= MF_BUFSIZE);
396 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
397 ok( ret && rd_size == mfsize, "ReadFile: error %ld\n", GetLastError());
401 ok(mfsize == bsize, "%s: mfsize=%ld, bsize=%d.\n", desc, mfsize, bsize);
407 for (i=0; i<bsize; i++)
409 if (buf[i] != bits[i])
412 ok(diff == 0, "%s: mfsize=%ld, bsize=%d, diff=%d\n",
413 desc, mfsize, bsize, diff);
418 /* Test a blank metafile. May be used as a template for new tests. */
420 static void test_mf_Blank(void)
428 hdcMetafile = CreateMetaFileA(NULL);
429 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
430 trace("hdcMetafile %p\n", hdcMetafile);
432 /* Tests on metafile initialization */
433 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
434 ok (caps == DT_METAFILE,
435 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
437 hMetafile = CloseMetaFile(hdcMetafile);
438 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
439 type = GetObjectType(hMetafile);
440 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
441 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
443 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
445 dump_mf_bits (hMetafile, "mf_Blank");
447 ret = DeleteMetaFile(hMetafile);
448 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
451 static void test_CopyMetaFile(void)
454 HMETAFILE hMetafile, hmf_copy;
456 char temp_path[MAX_PATH];
457 char mf_name[MAX_PATH];
460 hdcMetafile = CreateMetaFileA(NULL);
461 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
462 trace("hdcMetafile %p\n", hdcMetafile);
464 hMetafile = CloseMetaFile(hdcMetafile);
465 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
466 type = GetObjectType(hMetafile);
467 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
469 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
471 dump_mf_bits (hMetafile, "mf_Blank");
473 GetTempPathA(MAX_PATH, temp_path);
474 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
476 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
477 ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError());
479 type = GetObjectType(hmf_copy);
480 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
482 ret = DeleteMetaFile(hMetafile);
483 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
485 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
486 dump_mf_bits(hmf_copy, "mf_Blank");
488 ret = DeleteMetaFile(hmf_copy);
489 ok( ret, "DeleteMetaFile(%p) error %ld\n", hmf_copy, GetLastError());
491 DeleteFileA(mf_name);
494 static void test_SetMetaFileBits(void)
502 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
503 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
504 type = GetObjectType(hmf);
505 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
507 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
508 dump_mf_bits(hmf, "mf_Graphics");
510 ret = DeleteMetaFile(hmf);
511 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
513 /* NULL data crashes XP SP1 */
514 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
516 /* Now with not zero size */
517 SetLastError(0xdeadbeef);
518 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
519 ok(!hmf, "SetMetaFileBitsEx should fail\n");
520 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
522 /* Now with not even size */
523 SetLastError(0xdeadbeef);
524 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
525 ok(!hmf, "SetMetaFileBitsEx should fail\n");
526 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError());
528 /* Now with zeroed out or faked some header fields */
529 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
530 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
531 mh = (METAHEADER *)buf;
532 /* corruption of any of the below fields leads to a failure */
535 mh->mtHeaderSize = 0;
536 SetLastError(0xdeadbeef);
537 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
538 ok(!hmf, "SetMetaFileBitsEx should fail\n");
539 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
541 /* Now with corrupted mtSize field */
542 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
543 mh = (METAHEADER *)buf;
544 /* corruption of mtSize doesn't lead to a failure */
546 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
547 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
549 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
550 dump_mf_bits(hmf, "mf_Graphics");
552 ret = DeleteMetaFile(hmf);
553 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
555 /* Now with zeroed out mtSize field */
556 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
557 mh = (METAHEADER *)buf;
558 /* zeroing mtSize doesn't lead to a failure */
560 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
561 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
563 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
564 dump_mf_bits(hmf, "mf_Graphics");
566 ret = DeleteMetaFile(hmf);
567 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
570 /* Simple APIs from mfdrv/graphics.c
573 static void test_mf_Graphics(void)
580 hdcMetafile = CreateMetaFileA(NULL);
581 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
582 trace("hdcMetafile %p\n", hdcMetafile);
584 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
585 ok( ret, "MoveToEx error %ld.\n", GetLastError());
586 ret = LineTo(hdcMetafile, 2, 2);
587 ok( ret, "LineTo error %ld.\n", GetLastError());
588 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
589 ok( ret, "MoveToEx error %ld.\n", GetLastError());
591 /* oldpoint gets garbage under Win XP, so the following test would
592 * work under Wine but fails under Windows:
594 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
595 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
596 * oldpoint.x, oldpoint.y);
599 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
600 ok( ret, "Ellipse error %ld.\n", GetLastError());
602 hMetafile = CloseMetaFile(hdcMetafile);
603 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
604 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
606 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
608 dump_mf_bits (hMetafile, "mf_Graphics");
610 ret = DeleteMetaFile(hMetafile);
611 ok( ret, "DeleteMetaFile(%p) error %ld\n",
612 hMetafile, GetLastError());
615 static void test_mf_PatternBrush(void)
623 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
625 orig_lb->lbStyle = BS_PATTERN;
626 orig_lb->lbColor = RGB(0, 0, 0);
627 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
628 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
630 hBrush = CreateBrushIndirect (orig_lb);
631 ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
633 hdcMetafile = CreateMetaFileA(NULL);
634 ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
635 trace("hdcMetafile %p\n", hdcMetafile);
637 hBrush = SelectObject(hdcMetafile, hBrush);
638 ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
640 hMetafile = CloseMetaFile(hdcMetafile);
641 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
642 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
644 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
645 "mf_Pattern_Brush") != 0)
646 dump_mf_bits (hMetafile, "mf_Pattern_Brush");
648 ret = DeleteMetaFile(hMetafile);
649 ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
650 ret = DeleteObject(hBrush);
651 ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
652 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
653 ok( ret, "DeleteObject(HBITMAP) error %ld\n",
655 HeapFree (GetProcessHeap(), 0, orig_lb);
658 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
660 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
661 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
662 /* When using MM_TEXT Win9x does not update the mapping mode
663 * until a record is played which actually outputs something */
664 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
665 LPtoDP(hdc, mapping, 2);
666 trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
667 if (lpEMFR->iType == EMR_LINETO)
670 if (!lpMFP || lpMFP->mm == MM_TEXT)
674 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
675 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
679 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%ld\n", lpMFP->mm);
681 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
682 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
683 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
684 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
686 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
687 "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
688 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
694 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
702 hdcMf = CreateMetaFile(NULL);
703 ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
704 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
705 ok(ret, "LineTo failed with error %ld\n", GetLastError());
706 hmf = CloseMetaFile(hdcMf);
707 ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());
708 size = GetMetaFileBitsEx(hmf, 0, NULL);
709 ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
710 pBits = HeapAlloc(GetProcessHeap(), 0, size);
711 GetMetaFileBitsEx(hmf, size, pBits);
713 return SetWinMetaFileBits(size, pBits, NULL, mfp);
716 static void test_mf_conversions(void)
718 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
720 HDC hdcOffscreen = CreateCompatibleDC(NULL);
723 RECT rect = { 0, 0, 100, 100 };
724 mfp.mm = MM_ANISOTROPIC;
728 hemf = create_converted_emf(&mfp);
729 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
730 DeleteEnhMetaFile(hemf);
731 DeleteDC(hdcOffscreen);
734 trace("Testing MF->EMF conversion (MM_TEXT)\n");
736 HDC hdcOffscreen = CreateCompatibleDC(NULL);
739 RECT rect = { 0, 0, 100, 100 };
744 hemf = create_converted_emf(&mfp);
745 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
746 DeleteEnhMetaFile(hemf);
747 DeleteDC(hdcOffscreen);
750 trace("Testing MF->EMF conversion (NULL mfp)\n");
752 HDC hdcOffscreen = CreateCompatibleDC(NULL);
754 RECT rect = { 0, 0, 100, 100 };
755 hemf = create_converted_emf(NULL);
756 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
757 DeleteEnhMetaFile(hemf);
758 DeleteDC(hdcOffscreen);
762 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
763 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
764 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
766 static void test_gdiis(void)
768 RECT rect = {0,0,100,100};
769 HDC hdc, hemfDC, hmfDC;
773 /* resolve all the functions */
774 hgdi32 = GetModuleHandle("gdi32");
775 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
776 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
777 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
779 /* they should all exist or none should exist */
780 if(!pGdiIsMetaPrintDC)
783 /* try with nothing */
784 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
785 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
786 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
788 /* try with a metafile */
789 hmfDC = CreateMetaFile(NULL);
790 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
791 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
792 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
793 DeleteObject(CloseMetaFile(hmfDC));
795 /* try with an enhanced metafile */
797 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
798 ok(hemfDC != NULL, "failed to create emf\n");
800 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
801 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
802 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
804 hemf = CloseEnhMetaFile(hemfDC);
805 ok(hemf != NULL, "failed to close EMF\n");
812 init_function_pointers();
814 /* For enhanced metafiles (enhmfdrv) */
817 /* For win-format metafiles (mfdrv) */
820 test_mf_PatternBrush();
822 test_SetMetaFileBits();
824 /* For metafile conversions */
825 test_mf_conversions();