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 eto_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, eto_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, 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 %ld\n", GetLastError());
259 ret = ReleaseDC(hwnd, hdcDisplay);
260 ok( ret, "ReleaseDC error %ld\n", GetLastError());
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;
283 EMRRESTOREDC *restoredc = (EMRRESTOREDC *)emr;
287 ok(restoredc->iRelative == -1, "first restore %ld\n", restoredc->iRelative);
291 ok(restoredc->iRelative == -3, "second restore %ld\n", restoredc->iRelative);
294 ok(restoredc->iRelative == -2, "third restore %ld\n", restoredc->iRelative);
297 ok(restore_no <= 3, "restore_no %d\n", restore_no);
298 save_state += restoredc->iRelative;
302 ok(save_state == 0, "EOF save_state %d\n", save_state);
310 void test_SaveDC(void)
312 HDC hdcMetafile, hdcDisplay;
313 HENHMETAFILE hMetafile;
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 %ld\n", GetLastError());
323 hdcDisplay = GetDC(hwnd);
324 ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
326 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
327 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\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 %ld\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 %ld\n", GetLastError());
364 ret = ReleaseDC(hwnd, hdcDisplay);
365 ok( ret, "ReleaseDC error %ld\n", GetLastError());
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 256
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
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,
425 /* For debugging or dumping the raw metafiles produced by
426 * new test functions.
429 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
431 char buf[MF_BUFSIZE];
434 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
435 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
437 printf ("MetaFile %s has bits:\n{\n ", desc);
438 for (i=0; i<mfsize; i++)
440 printf ("0x%.2hhx", buf[i]);
451 /* Compare the metafile produced by a test function with the
452 * expected raw metafile data in "bits".
453 * Return value is 0 for a perfect match,
454 * -1 if lengths aren't equal,
455 * otherwise returns the number of non-matching bytes.
458 static int compare_mf_bits (const HMETAFILE mf, const unsigned char *bits, UINT bsize,
461 unsigned char buf[MF_BUFSIZE];
465 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
466 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
467 if (mfsize < MF_BUFSIZE)
468 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
469 desc, mfsize, bsize);
471 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
472 desc, mfsize, bsize);
477 for (i=0; i<bsize; i++)
479 if (buf[i] != bits[i])
482 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
483 desc, mfsize, bsize, diff);
488 static int compare_mf_disk_bits(LPCSTR name, const BYTE *bits, UINT bsize, const char *desc)
490 unsigned char buf[MF_BUFSIZE];
491 DWORD mfsize, rd_size, i;
496 hfile = CreateFileA(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
497 assert(hfile != INVALID_HANDLE_VALUE);
499 mfsize = GetFileSize(hfile, NULL);
500 assert(mfsize <= MF_BUFSIZE);
502 ret = ReadFile(hfile, buf, sizeof(buf), &rd_size, NULL);
503 ok( ret && rd_size == mfsize, "ReadFile: error %ld\n", GetLastError());
507 ok(mfsize == bsize, "%s: mfsize=%ld, bsize=%d.\n", desc, mfsize, bsize);
513 for (i=0; i<bsize; i++)
515 if (buf[i] != bits[i])
518 ok(diff == 0, "%s: mfsize=%ld, bsize=%d, diff=%d\n",
519 desc, mfsize, bsize, diff);
524 /* Test a blank metafile. May be used as a template for new tests. */
526 static void test_mf_Blank(void)
534 hdcMetafile = CreateMetaFileA(NULL);
535 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
536 trace("hdcMetafile %p\n", hdcMetafile);
538 /* Tests on metafile initialization */
539 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
540 ok (caps == DT_METAFILE,
541 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
543 hMetafile = CloseMetaFile(hdcMetafile);
544 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
545 type = GetObjectType(hMetafile);
546 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
547 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
549 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
551 dump_mf_bits (hMetafile, "mf_Blank");
553 ret = DeleteMetaFile(hMetafile);
554 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
557 static void test_CopyMetaFile(void)
560 HMETAFILE hMetafile, hmf_copy;
562 char temp_path[MAX_PATH];
563 char mf_name[MAX_PATH];
566 hdcMetafile = CreateMetaFileA(NULL);
567 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
568 trace("hdcMetafile %p\n", hdcMetafile);
570 hMetafile = CloseMetaFile(hdcMetafile);
571 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
572 type = GetObjectType(hMetafile);
573 ok(type == OBJ_METAFILE, "CloseMetaFile created object with type %d\n", type);
575 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
577 dump_mf_bits (hMetafile, "mf_Blank");
579 GetTempPathA(MAX_PATH, temp_path);
580 GetTempFileNameA(temp_path, "wmf", 0, mf_name);
582 hmf_copy = CopyMetaFileA(hMetafile, mf_name);
583 ok(hmf_copy != 0, "CopyMetaFile error %ld\n", GetLastError());
585 type = GetObjectType(hmf_copy);
586 ok(type == OBJ_METAFILE, "CopyMetaFile created object with type %d\n", type);
588 ret = DeleteMetaFile(hMetafile);
589 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
591 if (compare_mf_disk_bits(mf_name, MF_BLANK_BITS, sizeof(MF_BLANK_BITS), "mf_blank") != 0)
592 dump_mf_bits(hmf_copy, "mf_Blank");
594 ret = DeleteMetaFile(hmf_copy);
595 ok( ret, "DeleteMetaFile(%p) error %ld\n", hmf_copy, GetLastError());
597 DeleteFileA(mf_name);
600 static void test_SetMetaFileBits(void)
608 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), MF_GRAPHICS_BITS);
609 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
610 type = GetObjectType(hmf);
611 ok(type == OBJ_METAFILE, "SetMetaFileBitsEx created object with type %d\n", type);
613 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
614 dump_mf_bits(hmf, "mf_Graphics");
616 ret = DeleteMetaFile(hmf);
617 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
619 /* NULL data crashes XP SP1 */
620 /*hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), NULL);*/
622 /* Now with not zero size */
623 SetLastError(0xdeadbeef);
624 hmf = SetMetaFileBitsEx(0, MF_GRAPHICS_BITS);
625 ok(!hmf, "SetMetaFileBitsEx should fail\n");
626 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
628 /* Now with not even size */
629 SetLastError(0xdeadbeef);
630 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS) - 1, MF_GRAPHICS_BITS);
631 ok(!hmf, "SetMetaFileBitsEx should fail\n");
632 ok(GetLastError() == 0xdeadbeef /* XP SP1 */, "wrong error %ld\n", GetLastError());
634 /* Now with zeroed out or faked some header fields */
635 assert(sizeof(buf) >= sizeof(MF_GRAPHICS_BITS));
636 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
637 mh = (METAHEADER *)buf;
638 /* corruption of any of the below fields leads to a failure */
641 mh->mtHeaderSize = 0;
642 SetLastError(0xdeadbeef);
643 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
644 ok(!hmf, "SetMetaFileBitsEx should fail\n");
645 ok(GetLastError() == ERROR_INVALID_DATA, "wrong error %ld\n", GetLastError());
647 /* Now with corrupted mtSize field */
648 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
649 mh = (METAHEADER *)buf;
650 /* corruption of mtSize doesn't lead to a failure */
652 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
653 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
655 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
656 dump_mf_bits(hmf, "mf_Graphics");
658 ret = DeleteMetaFile(hmf);
659 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
661 /* Now with zeroed out mtSize field */
662 memcpy(buf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS));
663 mh = (METAHEADER *)buf;
664 /* zeroing mtSize doesn't lead to a failure */
666 hmf = SetMetaFileBitsEx(sizeof(MF_GRAPHICS_BITS), buf);
667 ok(hmf != 0, "SetMetaFileBitsEx error %ld\n", GetLastError());
669 if (compare_mf_bits(hmf, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS), "mf_Graphics") != 0)
670 dump_mf_bits(hmf, "mf_Graphics");
672 ret = DeleteMetaFile(hmf);
673 ok(ret, "DeleteMetaFile(%p) error %ld\n", hmf, GetLastError());
676 /* Simple APIs from mfdrv/graphics.c
679 static void test_mf_Graphics(void)
686 hdcMetafile = CreateMetaFileA(NULL);
687 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
688 trace("hdcMetafile %p\n", hdcMetafile);
690 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
691 ok( ret, "MoveToEx error %ld.\n", GetLastError());
692 ret = LineTo(hdcMetafile, 2, 2);
693 ok( ret, "LineTo error %ld.\n", GetLastError());
694 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
695 ok( ret, "MoveToEx error %ld.\n", GetLastError());
697 /* oldpoint gets garbage under Win XP, so the following test would
698 * work under Wine but fails under Windows:
700 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
701 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
702 * oldpoint.x, oldpoint.y);
705 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
706 ok( ret, "Ellipse error %ld.\n", GetLastError());
708 hMetafile = CloseMetaFile(hdcMetafile);
709 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
710 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
712 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
714 dump_mf_bits (hMetafile, "mf_Graphics");
716 ret = DeleteMetaFile(hMetafile);
717 ok( ret, "DeleteMetaFile(%p) error %ld\n",
718 hMetafile, GetLastError());
721 static void test_mf_PatternBrush(void)
729 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
731 orig_lb->lbStyle = BS_PATTERN;
732 orig_lb->lbColor = RGB(0, 0, 0);
733 orig_lb->lbHatch = (ULONG_PTR)CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
734 ok((HBITMAP)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
736 hBrush = CreateBrushIndirect (orig_lb);
737 ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
739 hdcMetafile = CreateMetaFileA(NULL);
740 ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
741 trace("hdcMetafile %p\n", hdcMetafile);
743 hBrush = SelectObject(hdcMetafile, hBrush);
744 ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
746 hMetafile = CloseMetaFile(hdcMetafile);
747 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
748 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
750 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
751 "mf_Pattern_Brush") != 0)
752 dump_mf_bits (hMetafile, "mf_Pattern_Brush");
754 ret = DeleteMetaFile(hMetafile);
755 ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
756 ret = DeleteObject(hBrush);
757 ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
758 ret = DeleteObject((HBITMAP)orig_lb->lbHatch);
759 ok( ret, "DeleteObject(HBITMAP) error %ld\n",
761 HeapFree (GetProcessHeap(), 0, orig_lb);
764 static INT CALLBACK EmfEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData)
766 LPMETAFILEPICT lpMFP = (LPMETAFILEPICT)lpData;
767 POINT mapping[2] = { { 0, 0 }, { 10, 10 } };
768 /* When using MM_TEXT Win9x does not update the mapping mode
769 * until a record is played which actually outputs something */
770 PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj);
771 LPtoDP(hdc, mapping, 2);
772 trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y);
773 if (lpEMFR->iType == EMR_LINETO)
776 if (!lpMFP || lpMFP->mm == MM_TEXT)
780 x1 = (INT)floor(10 * 100.0 / LINE_X + 0.5);
781 y1 = (INT)floor(10 * 100.0 / LINE_Y + 0.5);
785 ok(lpMFP->mm == MM_ANISOTROPIC, "mm=%ld\n", lpMFP->mm);
787 x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
788 y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
789 x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
790 y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
792 ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
793 "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
794 mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
800 static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
808 hdcMf = CreateMetaFile(NULL);
809 ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
810 ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
811 ok(ret, "LineTo failed with error %ld\n", GetLastError());
812 hmf = CloseMetaFile(hdcMf);
813 ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());
814 size = GetMetaFileBitsEx(hmf, 0, NULL);
815 ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
816 pBits = HeapAlloc(GetProcessHeap(), 0, size);
817 GetMetaFileBitsEx(hmf, size, pBits);
819 return SetWinMetaFileBits(size, pBits, NULL, mfp);
822 static void test_mf_conversions(void)
824 trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
826 HDC hdcOffscreen = CreateCompatibleDC(NULL);
829 RECT rect = { 0, 0, 100, 100 };
830 mfp.mm = MM_ANISOTROPIC;
834 hemf = create_converted_emf(&mfp);
835 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
836 DeleteEnhMetaFile(hemf);
837 DeleteDC(hdcOffscreen);
840 trace("Testing MF->EMF conversion (MM_TEXT)\n");
842 HDC hdcOffscreen = CreateCompatibleDC(NULL);
845 RECT rect = { 0, 0, 100, 100 };
850 hemf = create_converted_emf(&mfp);
851 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);
852 DeleteEnhMetaFile(hemf);
853 DeleteDC(hdcOffscreen);
856 trace("Testing MF->EMF conversion (NULL mfp)\n");
858 HDC hdcOffscreen = CreateCompatibleDC(NULL);
860 RECT rect = { 0, 0, 100, 100 };
861 hemf = create_converted_emf(NULL);
862 EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);
863 DeleteEnhMetaFile(hemf);
864 DeleteDC(hdcOffscreen);
868 static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
869 static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
870 static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);
872 static void test_gdiis(void)
874 RECT rect = {0,0,100,100};
875 HDC hdc, hemfDC, hmfDC;
879 /* resolve all the functions */
880 hgdi32 = GetModuleHandle("gdi32");
881 pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
882 pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
883 pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");
885 /* they should all exist or none should exist */
886 if(!pGdiIsMetaPrintDC)
889 /* try with nothing */
890 ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
891 ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
892 ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");
894 /* try with a metafile */
895 hmfDC = CreateMetaFile(NULL);
896 ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
897 ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
898 ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
899 DeleteObject(CloseMetaFile(hmfDC));
901 /* try with an enhanced metafile */
903 hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
904 ok(hemfDC != NULL, "failed to create emf\n");
906 ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
907 ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
908 ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");
910 hemf = CloseEnhMetaFile(hemfDC);
911 ok(hemf != NULL, "failed to close EMF\n");
918 init_function_pointers();
920 /* For enhanced metafiles (enhmfdrv) */
924 /* For win-format metafiles (mfdrv) */
927 test_mf_PatternBrush();
929 test_SetMetaFileBits();
931 /* For metafile conversions */
932 test_mf_conversions();