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
24 #include "wine/test.h"
30 static LOGFONTA orig_lf;
31 static BOOL emr_processed = FALSE;
33 static int CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
34 const ENHMETARECORD *emr, int n_objs, LPARAM param)
39 INT *orig_dx = (INT *)param;
43 trace("hdc %p, emr->iType %ld, emr->nSize %ld, param %p\n",
44 hdc, emr->iType, emr->nSize, (void *)param);
46 PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
56 const EMREXTTEXTOUTA *emr_ExtTextOutA = (const EMREXTTEXTOUTA *)emr;
57 dx = (const INT *)((const char *)emr + emr_ExtTextOutA->emrtext.offDx);
59 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
60 ok( ret == sizeof(device_lf), "GetObjectA error %ld\n", GetLastError());
62 /* compare up to lfOutPrecision, other values are not interesting,
63 * and in fact sometimes arbitrary adapted by Win9x.
65 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
66 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
68 for(i = 0; i < emr_ExtTextOutA->emrtext.nChars; i++)
70 ok(orig_dx[i] == dx[i], "pass %d: dx[%ld] (%d) didn't match %d\n",
71 n_record, i, dx[i], orig_dx[i]);
80 const EMREXTTEXTOUTW *emr_ExtTextOutW = (const EMREXTTEXTOUTW *)emr;
81 dx = (const INT *)((const char *)emr + emr_ExtTextOutW->emrtext.offDx);
83 ret = GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(device_lf), &device_lf);
84 ok( ret == sizeof(device_lf), "GetObjectA error %ld\n", GetLastError());
86 /* compare up to lfOutPrecision, other values are not interesting,
87 * and in fact sometimes arbitrary adapted by Win9x.
89 ok(!memcmp(&orig_lf, &device_lf, FIELD_OFFSET(LOGFONTA, lfOutPrecision)), "fonts don't match\n");
90 ok(!lstrcmpA(orig_lf.lfFaceName, device_lf.lfFaceName), "font names don't match\n");
92 for(i = 0; i < emr_ExtTextOutW->emrtext.nChars; i++)
94 ok(orig_dx[i] == dx[i], "pass %d: dx[%ld] (%d) didn't match %d\n",
95 n_record, i, dx[i], orig_dx[i]);
109 static void test_ExtTextOut(void)
112 HDC hdcDisplay, hdcMetafile;
113 HENHMETAFILE hMetafile;
115 static const char text[] = "Simple text to test ExtTextOut on metafiles";
117 static const RECT rc = { 0, 0, 100, 100 };
120 assert(sizeof(dx)/sizeof(dx[0]) >= lstrlenA(text));
122 /* Win9x doesn't play EMFs on invisible windows */
123 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
124 0, 0, 200, 200, 0, 0, 0, NULL);
125 ok(hwnd != 0, "CreateWindowExA error %ld\n", GetLastError());
127 hdcDisplay = GetDC(hwnd);
128 ok(hdcDisplay != 0, "GetDC error %ld\n", GetLastError());
130 trace("hdcDisplay %p\n", hdcDisplay);
132 SetMapMode(hdcDisplay, MM_TEXT);
134 memset(&orig_lf, 0, sizeof(orig_lf));
136 orig_lf.lfCharSet = ANSI_CHARSET;
137 orig_lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
138 orig_lf.lfWeight = FW_DONTCARE;
139 orig_lf.lfHeight = 7;
140 orig_lf.lfQuality = DEFAULT_QUALITY;
141 lstrcpyA(orig_lf.lfFaceName, "Arial");
142 hFont = CreateFontIndirectA(&orig_lf);
143 ok(hFont != 0, "CreateFontIndirectA error %ld\n", GetLastError());
145 hFont = SelectObject(hdcDisplay, hFont);
147 len = lstrlenA(text);
148 for (i = 0; i < len; i++)
150 ret = GetCharWidthA(hdcDisplay, text[i], text[i], &dx[i]);
151 ok( ret, "GetCharWidthA error %ld\n", GetLastError());
153 hFont = SelectObject(hdcDisplay, hFont);
155 hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
156 ok(hdcMetafile != 0, "CreateEnhMetaFileA error %ld\n", GetLastError());
158 trace("hdcMetafile %p\n", hdcMetafile);
160 ok(GetDeviceCaps(hdcMetafile, TECHNOLOGY) == DT_RASDISPLAY,
161 "GetDeviceCaps(TECHNOLOGY) has to return DT_RASDISPLAY for a display based EMF\n");
163 hFont = SelectObject(hdcMetafile, hFont);
165 /* 1. pass NULL lpDx */
166 ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, lstrlenA(text), NULL);
167 ok( ret, "ExtTextOutA error %ld\n", GetLastError());
169 /* 2. pass custom lpDx */
170 ret = ExtTextOutA(hdcMetafile, 0, 20, 0, &rc, text, lstrlenA(text), dx);
171 ok( ret, "ExtTextOutA error %ld\n", GetLastError());
173 hFont = SelectObject(hdcMetafile, hFont);
174 ret = DeleteObject(hFont);
175 ok( ret, "DeleteObject error %ld\n", GetLastError());
177 hMetafile = CloseEnhMetaFile(hdcMetafile);
178 ok(hMetafile != 0, "CloseEnhMetaFile error %ld\n", GetLastError());
180 ok(!GetObjectType(hdcMetafile), "CloseEnhMetaFile has to destroy metafile hdc\n");
182 ret = PlayEnhMetaFile(hdcDisplay, hMetafile, &rc);
183 ok( ret, "PlayEnhMetaFile error %ld\n", GetLastError());
185 ret = EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, &rc);
186 ok( ret, "EnumEnhMetaFile error %ld\n", GetLastError());
188 ok(emr_processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW record\n");
190 ok(!EnumEnhMetaFile(hdcDisplay, hMetafile, emf_enum_proc, dx, NULL),
191 "A valid hdc has to require a valid rc\n");
193 ret = DeleteEnhMetaFile(hMetafile);
194 ok( ret, "DeleteEnhMetaFile error %ld\n", GetLastError());
195 ret = ReleaseDC(hwnd, hdcDisplay);
196 ok( ret, "ReleaseDC error %ld\n", GetLastError());
199 /* Win-format metafile (mfdrv) tests */
200 /* These tests compare the generated metafiles byte-by-byte */
201 /* with the nominal results. */
203 /* Maximum size of sample metafiles in bytes. */
204 #define MF_BUFSIZE 256
206 /* 8x8 bitmap data for a pattern brush */
207 static const unsigned char SAMPLE_PATTERN_BRUSH[] = {
208 0x01, 0x00, 0x02, 0x00,
209 0x03, 0x00, 0x04, 0x00,
210 0x05, 0x00, 0x06, 0x00,
211 0x07, 0x00, 0x08, 0x00
214 /* Sample metafiles to be compared to the outputs of the
218 static const unsigned char MF_BLANK_BITS[] = {
219 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x0c, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
224 static const unsigned char MF_GRAPHICS_BITS[] = {
225 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x22, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x02,
228 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
229 0x13, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x00,
230 0x00, 0x00, 0x14, 0x02, 0x01, 0x00, 0x01, 0x00,
231 0x07, 0x00, 0x00, 0x00, 0x18, 0x04, 0x02, 0x00,
232 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
233 0x00, 0x00, 0x00, 0x00
236 static const unsigned char MF_PATTERN_BRUSH_BITS[] = {
237 0x01, 0x00, 0x09, 0x00, 0x00, 0x03, 0x3d, 0x00,
238 0x00, 0x00, 0x01, 0x00, 0x2d, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x42, 0x01,
240 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
241 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
242 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0xff, 0xff, 0xff, 0x00, 0x08, 0x00, 0x00, 0x00,
247 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
248 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
249 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
250 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
251 0x2d, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
255 /* For debugging or dumping the raw metafiles produced by
256 * new test functions.
259 static void dump_mf_bits (const HMETAFILE mf, const char *desc)
261 char buf[MF_BUFSIZE];
264 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
265 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
267 printf ("MetaFile %s has bits:\n{\n ", desc);
268 for (i=0; i<mfsize; i++)
270 printf ("0x%.2hhx", buf[i]);
281 /* Compare the metafile produced by a test function with the
282 * expected raw metafile data in "bits".
283 * Return value is 0 for a perfect match,
284 * -1 if lengths aren't equal,
285 * otherwise returns the number of non-matching bytes.
288 static int compare_mf_bits (const HMETAFILE mf, const char *bits, UINT bsize,
291 char buf[MF_BUFSIZE];
295 mfsize = GetMetaFileBitsEx (mf, MF_BUFSIZE, buf);
296 ok (mfsize > 0, "%s: GetMetaFileBitsEx failed.\n", desc);
297 if (mfsize < MF_BUFSIZE)
298 ok (mfsize == bsize, "%s: mfsize=%d, bsize=%d.\n",
299 desc, mfsize, bsize);
301 ok (bsize >= MF_BUFSIZE, "%s: mfsize > bufsize (%d bytes), bsize=%d.\n",
302 desc, mfsize, bsize);
307 for (i=0; i<bsize; i++)
309 if (buf[i] != bits[i])
312 ok (diff == 0, "%s: mfsize=%d, bsize=%d, diff=%d\n",
313 desc, mfsize, bsize, diff);
318 /* Test a blank metafile. May be used as a template for new tests. */
320 static void test_mf_Blank(void)
327 hdcMetafile = CreateMetaFileA(NULL);
328 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
329 trace("hdcMetafile %p\n", hdcMetafile);
331 /* Tests on metafile initialization */
332 caps = GetDeviceCaps (hdcMetafile, TECHNOLOGY);
333 ok (caps == DT_METAFILE,
334 "GetDeviceCaps: TECHNOLOGY=%d != DT_METAFILE.\n", caps);
336 hMetafile = CloseMetaFile(hdcMetafile);
337 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
338 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
340 if (compare_mf_bits (hMetafile, MF_BLANK_BITS, sizeof(MF_BLANK_BITS),
342 dump_mf_bits (hMetafile, "mf_Blank");
344 ret = DeleteMetaFile(hMetafile);
345 ok( ret, "DeleteMetaFile(%p) error %ld\n", hMetafile, GetLastError());
348 /* Simple APIs from mfdrv/graphics.c
351 static void test_mf_Graphics()
358 hdcMetafile = CreateMetaFileA(NULL);
359 ok(hdcMetafile != 0, "CreateMetaFileA(NULL) error %ld\n", GetLastError());
360 trace("hdcMetafile %p\n", hdcMetafile);
362 ret = MoveToEx(hdcMetafile, 1, 1, NULL);
363 ok( ret, "MoveToEx error %ld.\n", GetLastError());
364 ret = LineTo(hdcMetafile, 2, 2);
365 ok( ret, "LineTo error %ld.\n", GetLastError());
366 ret = MoveToEx(hdcMetafile, 1, 1, &oldpoint);
367 ok( ret, "MoveToEx error %ld.\n", GetLastError());
369 /* oldpoint gets garbage under Win XP, so the following test would
370 * work under Wine but fails under Windows:
372 * ok((oldpoint.x == 2) && (oldpoint.y == 2),
373 * "MoveToEx: (x, y) = (%ld, %ld), should be (2, 2).\n",
374 * oldpoint.x, oldpoint.y);
377 ret = Ellipse(hdcMetafile, 0, 0, 2, 2);
378 ok( ret, "Ellipse error %ld.\n", GetLastError());
380 hMetafile = CloseMetaFile(hdcMetafile);
381 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
382 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
384 if (compare_mf_bits (hMetafile, MF_GRAPHICS_BITS, sizeof(MF_GRAPHICS_BITS),
386 dump_mf_bits (hMetafile, "mf_Graphics");
388 ret = DeleteMetaFile(hMetafile);
389 ok( ret, "DeleteMetaFile(%p) error %ld\n",
390 hMetafile, GetLastError());
393 static void test_mf_PatternBrush(void)
401 orig_lb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGBRUSH));
403 orig_lb->lbStyle = BS_PATTERN;
404 orig_lb->lbColor = RGB(0, 0, 0);
405 orig_lb->lbHatch = (INT) CreateBitmap (8, 8, 1, 1, SAMPLE_PATTERN_BRUSH);
406 ok((HBITMAP *)orig_lb->lbHatch != NULL, "CreateBitmap error %ld.\n", GetLastError());
408 hBrush = CreateBrushIndirect (orig_lb);
409 ok(hBrush != 0, "CreateBrushIndirect error %ld\n", GetLastError());
411 hdcMetafile = CreateMetaFileA(NULL);
412 ok(hdcMetafile != 0, "CreateMetaFileA error %ld\n", GetLastError());
413 trace("hdcMetafile %p\n", hdcMetafile);
415 hBrush = SelectObject(hdcMetafile, hBrush);
416 ok(hBrush != 0, "SelectObject error %ld.\n", GetLastError());
418 hMetafile = CloseMetaFile(hdcMetafile);
419 ok(hMetafile != 0, "CloseMetaFile error %ld\n", GetLastError());
420 ok(!GetObjectType(hdcMetafile), "CloseMetaFile has to destroy metafile hdc\n");
422 if (compare_mf_bits (hMetafile, MF_PATTERN_BRUSH_BITS, sizeof(MF_PATTERN_BRUSH_BITS),
423 "mf_Pattern_Brush") != 0)
424 dump_mf_bits (hMetafile, "mf_Pattern_Brush");
426 ret = DeleteMetaFile(hMetafile);
427 ok( ret, "DeleteMetaFile error %ld\n", GetLastError());
428 ret = DeleteObject(hBrush);
429 ok( ret, "DeleteObject(HBRUSH) error %ld\n", GetLastError());
430 ret = DeleteObject((HBITMAP *)orig_lb->lbHatch);
431 ok( ret, "DeleteObject(HBITMAP) error %ld\n",
433 HeapFree (GetProcessHeap(), 0, orig_lb);
438 /* For enhanced metafiles (enhmfdrv) */
441 /* For win-format metafiles (mfdrv) */
444 test_mf_PatternBrush();