1 /*
2 * Unit test suite for metafiles
3 *
4 * Copyright (C) 2011 Vincent Povirk for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <math.h>
22
23 #include "objbase.h"
24 #include "gdiplus.h"
25 #include "wine/test.h"
26
27 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
28 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
29 #define expectf(expected, got) expectf_((expected), (got), 0.001)
30
31 static BOOL save_metafiles;
32 static BOOL load_metafiles;
33
34 typedef struct emfplus_record
35 {
36 DWORD record_type;
37 DWORD flags; /* Used for EMF+ records only. */
38 BOOL todo;
39 BOOL playback_todo;
40 void (*playback_fn)(GpMetafile* metafile, EmfPlusRecordType record_type,
41 unsigned int flags, unsigned int dataSize, const unsigned char *pStr);
42 DWORD broken_flags;
43 } emfplus_record;
44
45 typedef struct emfplus_check_state
46 {
47 const char *desc;
48 int count;
49 const struct emfplus_record *expected;
50 GpMetafile *metafile;
51 } emfplus_check_state;
52
check_record(int count,const char * desc,const struct emfplus_record * expected,const struct emfplus_record * actual)53 static void check_record(int count, const char *desc, const struct emfplus_record *expected, const struct emfplus_record *actual)
54 {
55 if (actual->record_type > GDIP_EMFPLUS_RECORD_BASE)
56 {
57 todo_wine_if (expected->todo)
58 ok(expected->record_type == actual->record_type && (expected->flags == actual->flags ||
59 broken(expected->broken_flags == actual->flags)),
60 "%s.%i: Expected record type 0x%x, got 0x%x. Expected flags %#x, got %#x.\n", desc, count,
61 expected->record_type, actual->record_type, expected->flags, actual->flags);
62 }
63 else
64 {
65 todo_wine_if (expected->todo)
66 ok(expected->record_type == actual->record_type,
67 "%s.%i: Expected record type 0x%x, got 0x%x.\n", desc, count,
68 expected->record_type, actual->record_type);
69 }
70 }
71
72 typedef struct EmfPlusRecordHeader
73 {
74 WORD Type;
75 WORD Flags;
76 DWORD Size;
77 DWORD DataSize;
78 } EmfPlusRecordHeader;
79
80 typedef enum
81 {
82 ObjectTypeInvalid,
83 ObjectTypeBrush,
84 ObjectTypePen,
85 ObjectTypePath,
86 ObjectTypeRegion,
87 ObjectTypeImage,
88 ObjectTypeFont,
89 ObjectTypeStringFormat,
90 ObjectTypeImageAttributes,
91 ObjectTypeCustomLineCap,
92 } ObjectType;
93
94 typedef enum
95 {
96 ImageDataTypeUnknown,
97 ImageDataTypeBitmap,
98 ImageDataTypeMetafile,
99 } ImageDataType;
100
101 typedef struct
102 {
103 EmfPlusRecordHeader Header;
104 /* EmfPlusImage */
105 DWORD Version;
106 ImageDataType Type;
107 /* EmfPlusMetafile */
108 DWORD MetafileType;
109 DWORD MetafileDataSize;
110 BYTE MetafileData[1];
111 } MetafileImageObject;
112
enum_emf_proc(HDC hDC,HANDLETABLE * lpHTable,const ENHMETARECORD * lpEMFR,int nObj,LPARAM lpData)113 static int CALLBACK enum_emf_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
114 int nObj, LPARAM lpData)
115 {
116 emfplus_check_state *state = (emfplus_check_state*)lpData;
117 emfplus_record actual;
118
119 if (lpEMFR->iType == EMR_GDICOMMENT)
120 {
121 const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR;
122
123 if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0)
124 {
125 int offset = 4;
126
127 while (offset + sizeof(EmfPlusRecordHeader) <= comment->cbData)
128 {
129 const EmfPlusRecordHeader *record = (const EmfPlusRecordHeader*)&comment->Data[offset];
130
131 ok(record->Size == record->DataSize + sizeof(EmfPlusRecordHeader),
132 "%s: EMF+ record datasize %u and size %u mismatch\n", state->desc, record->DataSize, record->Size);
133
134 ok(offset + record->DataSize <= comment->cbData,
135 "%s: EMF+ record truncated\n", state->desc);
136
137 if (offset + record->DataSize > comment->cbData)
138 return 0;
139
140 if (state->expected[state->count].record_type)
141 {
142 actual.todo = FALSE;
143 actual.record_type = record->Type;
144 actual.flags = record->Flags;
145
146 check_record(state->count, state->desc, &state->expected[state->count], &actual);
147 state->count++;
148
149 if (state->expected[state->count-1].todo && state->expected[state->count-1].record_type != actual.record_type)
150 continue;
151 }
152 else
153 {
154 ok(0, "%s: Unexpected EMF+ 0x%x record\n", state->desc, record->Type);
155 }
156
157 if ((record->Flags >> 8) == ObjectTypeImage && record->Type == EmfPlusRecordTypeObject)
158 {
159 const MetafileImageObject *image = (const MetafileImageObject*)record;
160
161 if (image->Type == ImageDataTypeMetafile)
162 {
163 HENHMETAFILE hemf = SetEnhMetaFileBits(image->MetafileDataSize, image->MetafileData);
164 ok(hemf != NULL, "%s: SetEnhMetaFileBits failed\n", state->desc);
165
166 EnumEnhMetaFile(0, hemf, enum_emf_proc, state, NULL);
167 DeleteEnhMetaFile(hemf);
168 }
169 }
170
171 offset += record->Size;
172 }
173
174 ok(offset == comment->cbData, "%s: truncated EMF+ record data?\n", state->desc);
175
176 return 1;
177 }
178 }
179
180 if (state->expected[state->count].record_type)
181 {
182 actual.todo = FALSE;
183 actual.record_type = lpEMFR->iType;
184 actual.flags = 0;
185
186 check_record(state->count, state->desc, &state->expected[state->count], &actual);
187
188 state->count++;
189 }
190 else
191 {
192 ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, lpEMFR->iType);
193 }
194
195 return 1;
196 }
197
check_emfplus(HENHMETAFILE hemf,const emfplus_record * expected,const char * desc)198 static void check_emfplus(HENHMETAFILE hemf, const emfplus_record *expected, const char *desc)
199 {
200 emfplus_check_state state;
201
202 state.desc = desc;
203 state.count = 0;
204 state.expected = expected;
205
206 EnumEnhMetaFile(0, hemf, enum_emf_proc, &state, NULL);
207
208 todo_wine_if (expected[state.count].todo)
209 ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
210 }
211
enum_metafile_proc(EmfPlusRecordType record_type,unsigned int flags,unsigned int dataSize,const unsigned char * pStr,void * userdata)212 static BOOL CALLBACK enum_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
213 unsigned int dataSize, const unsigned char *pStr, void *userdata)
214 {
215 emfplus_check_state *state = (emfplus_check_state*)userdata;
216 emfplus_record actual;
217
218 actual.todo = FALSE;
219 actual.record_type = record_type;
220 actual.flags = flags;
221
222 if (dataSize == 0)
223 ok(pStr == NULL, "non-NULL pStr\n");
224
225 if (state->expected[state->count].record_type)
226 {
227 check_record(state->count, state->desc, &state->expected[state->count], &actual);
228
229 state->count++;
230 }
231 else
232 {
233 ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, record_type);
234 }
235
236 return TRUE;
237 }
238
check_metafile(GpMetafile * metafile,const emfplus_record * expected,const char * desc,const GpPointF * dst_points,const GpRectF * src_rect,Unit src_unit)239 static void check_metafile(GpMetafile *metafile, const emfplus_record *expected, const char *desc,
240 const GpPointF *dst_points, const GpRectF *src_rect, Unit src_unit)
241 {
242 GpStatus stat;
243 HDC hdc;
244 GpGraphics *graphics;
245 emfplus_check_state state;
246
247 state.desc = desc;
248 state.count = 0;
249 state.expected = expected;
250 state.metafile = metafile;
251
252 hdc = CreateCompatibleDC(0);
253
254 stat = GdipCreateFromHDC(hdc, &graphics);
255 expect(Ok, stat);
256
257 stat = GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, dst_points,
258 3, src_rect, src_unit, enum_metafile_proc, &state, NULL);
259 expect(Ok, stat);
260
261 todo_wine_if (expected[state.count].todo)
262 ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
263
264 GdipDeleteGraphics(graphics);
265
266 DeleteDC(hdc);
267 }
268
play_metafile_proc(EmfPlusRecordType record_type,unsigned int flags,unsigned int dataSize,const unsigned char * pStr,void * userdata)269 static BOOL CALLBACK play_metafile_proc(EmfPlusRecordType record_type, unsigned int flags,
270 unsigned int dataSize, const unsigned char *pStr, void *userdata)
271 {
272 emfplus_check_state *state = (emfplus_check_state*)userdata;
273 GpStatus stat;
274
275 if (state->expected[state->count].record_type)
276 {
277 BOOL match = (state->expected[state->count].record_type == record_type);
278
279 if (match && state->expected[state->count].playback_fn)
280 state->expected[state->count].playback_fn(state->metafile, record_type, flags, dataSize, pStr);
281 else
282 {
283 stat = GdipPlayMetafileRecord(state->metafile, record_type, flags, dataSize, pStr);
284 todo_wine_if (state->expected[state->count].playback_todo)
285 ok(stat == Ok, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state->desc, state->count, stat);
286 }
287
288 todo_wine_if (state->expected[state->count].todo)
289 ok(state->expected[state->count].record_type == record_type,
290 "%s.%i: expected record type 0x%x, got 0x%x\n", state->desc, state->count,
291 state->expected[state->count].record_type, record_type);
292 state->count++;
293 }
294 else
295 {
296 todo_wine_if (state->expected[state->count].playback_todo)
297 ok(0, "%s: unexpected record 0x%x\n", state->desc, record_type);
298
299 return FALSE;
300 }
301
302 return TRUE;
303 }
304
play_metafile(GpMetafile * metafile,GpGraphics * graphics,const emfplus_record * expected,const char * desc,const GpPointF * dst_points,const GpRectF * src_rect,Unit src_unit)305 static void play_metafile(GpMetafile *metafile, GpGraphics *graphics, const emfplus_record *expected,
306 const char *desc, const GpPointF *dst_points, const GpRectF *src_rect, Unit src_unit)
307 {
308 GpStatus stat;
309 emfplus_check_state state;
310
311 state.desc = desc;
312 state.count = 0;
313 state.expected = expected;
314 state.metafile = metafile;
315
316 stat = GdipEnumerateMetafileSrcRectDestPoints(graphics, metafile, dst_points,
317 3, src_rect, src_unit, play_metafile_proc, &state, NULL);
318 expect(Ok, stat);
319 }
320
321 /* When 'save' or 'load' is specified on the command line, save or
322 * load the specified filename. */
sync_metafile(GpMetafile ** metafile,const char * filename)323 static void sync_metafile(GpMetafile **metafile, const char *filename)
324 {
325 GpStatus stat;
326 if (save_metafiles)
327 {
328 GpMetafile *clone;
329 HENHMETAFILE hemf;
330
331 stat = GdipCloneImage((GpImage*)*metafile, (GpImage**)&clone);
332 expect(Ok, stat);
333
334 stat = GdipGetHemfFromMetafile(clone, &hemf);
335 expect(Ok, stat);
336
337 DeleteEnhMetaFile(CopyEnhMetaFileA(hemf, filename));
338
339 DeleteEnhMetaFile(hemf);
340
341 stat = GdipDisposeImage((GpImage*)clone);
342 expect(Ok, stat);
343 }
344 else if (load_metafiles)
345 {
346 HENHMETAFILE hemf;
347
348 stat = GdipDisposeImage((GpImage*)*metafile);
349 expect(Ok, stat);
350 *metafile = NULL;
351
352 hemf = GetEnhMetaFileA(filename);
353 ok(hemf != NULL, "%s could not be opened\n", filename);
354
355 stat = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
356 expect(Ok, stat);
357 }
358 }
359
360 static const emfplus_record empty_records[] = {
361 { EMR_HEADER },
362 { EmfPlusRecordTypeHeader },
363 { EmfPlusRecordTypeEndOfFile },
364 { EMR_EOF },
365 { 0 }
366 };
367
test_empty(void)368 static void test_empty(void)
369 {
370 GpStatus stat;
371 GpMetafile *metafile;
372 GpGraphics *graphics;
373 HDC hdc;
374 GpRectF bounds;
375 GpUnit unit;
376 REAL xres, yres;
377 HENHMETAFILE hemf, dummy;
378 MetafileHeader header;
379 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
380 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
381 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
382
383 hdc = CreateCompatibleDC(0);
384
385 stat = GdipRecordMetafile(NULL, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
386 expect(InvalidParameter, stat);
387
388 stat = GdipRecordMetafile(hdc, MetafileTypeInvalid, &frame, MetafileFrameUnitPixel, description, &metafile);
389 expect(InvalidParameter, stat);
390
391 stat = GdipRecordMetafile(hdc, MetafileTypeWmf, &frame, MetafileFrameUnitPixel, description, &metafile);
392 expect(InvalidParameter, stat);
393
394 stat = GdipRecordMetafile(hdc, MetafileTypeWmfPlaceable, &frame, MetafileFrameUnitPixel, description, &metafile);
395 expect(InvalidParameter, stat);
396
397 stat = GdipRecordMetafile(hdc, MetafileTypeEmfPlusDual+1, &frame, MetafileFrameUnitPixel, description, &metafile);
398 expect(InvalidParameter, stat);
399
400 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, NULL);
401 expect(InvalidParameter, stat);
402
403 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
404 expect(Ok, stat);
405
406 DeleteDC(hdc);
407
408 if (stat != Ok)
409 return;
410
411 stat = GdipGetHemfFromMetafile(metafile, &hemf);
412 expect(InvalidParameter, stat);
413
414 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
415 expect(Ok, stat);
416
417 stat = GdipGetHemfFromMetafile(metafile, &hemf);
418 expect(InvalidParameter, stat);
419
420 stat = GdipDeleteGraphics(graphics);
421 expect(Ok, stat);
422
423 check_metafile(metafile, empty_records, "empty metafile", dst_points, &frame, UnitPixel);
424
425 sync_metafile(&metafile, "empty.emf");
426
427 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
428 expect(Ok, stat);
429 expectf(0.0, bounds.X);
430 expectf(0.0, bounds.Y);
431 expectf_(100.0, bounds.Width, 0.05);
432 expectf_(100.0, bounds.Height, 0.05);
433 expect(UnitPixel, unit);
434
435 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
436 expect(Ok, stat);
437
438 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
439 expect(Ok, stat);
440
441 memset(&header, 0xaa, sizeof(header));
442 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
443 expect(Ok, stat);
444 expect(MetafileTypeEmfPlusOnly, header.Type);
445 expect(U(header).EmfHeader.nBytes, header.Size);
446 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
447 expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
448 expectf(xres, header.DpiX);
449 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
450 expectf(yres, header.DpiY);
451 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
452 expect(0, header.X);
453 expect(0, header.Y);
454 expect(100, header.Width);
455 expect(100, header.Height);
456 expect(28, header.EmfPlusHeaderSize);
457 expect(96, header.LogicalDpiX);
458 expect(96, header.LogicalDpiX);
459 expect(EMR_HEADER, U(header).EmfHeader.iType);
460 expect(0, U(header).EmfHeader.rclBounds.left);
461 expect(0, U(header).EmfHeader.rclBounds.top);
462 expect(-1, U(header).EmfHeader.rclBounds.right);
463 expect(-1, U(header).EmfHeader.rclBounds.bottom);
464 expect(0, U(header).EmfHeader.rclFrame.left);
465 expect(0, U(header).EmfHeader.rclFrame.top);
466 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
467 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
468
469 stat = GdipGetHemfFromMetafile(metafile, &hemf);
470 expect(Ok, stat);
471
472 stat = GdipGetHemfFromMetafile(metafile, &dummy);
473 expect(InvalidParameter, stat);
474
475 stat = GdipDisposeImage((GpImage*)metafile);
476 expect(Ok, stat);
477
478 check_emfplus(hemf, empty_records, "empty emf");
479
480 memset(&header, 0xaa, sizeof(header));
481 stat = GdipGetMetafileHeaderFromEmf(hemf, &header);
482 expect(Ok, stat);
483 expect(MetafileTypeEmfPlusOnly, header.Type);
484 expect(U(header).EmfHeader.nBytes, header.Size);
485 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
486 expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
487 expectf(xres, header.DpiX);
488 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
489 expectf(yres, header.DpiY);
490 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
491 expect(0, header.X);
492 expect(0, header.Y);
493 expect(100, header.Width);
494 expect(100, header.Height);
495 expect(28, header.EmfPlusHeaderSize);
496 expect(96, header.LogicalDpiX);
497 expect(96, header.LogicalDpiX);
498 expect(EMR_HEADER, U(header).EmfHeader.iType);
499 expect(0, U(header).EmfHeader.rclBounds.left);
500 expect(0, U(header).EmfHeader.rclBounds.top);
501 expect(-1, U(header).EmfHeader.rclBounds.right);
502 expect(-1, U(header).EmfHeader.rclBounds.bottom);
503 expect(0, U(header).EmfHeader.rclFrame.left);
504 expect(0, U(header).EmfHeader.rclFrame.top);
505 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
506 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
507
508 stat = GdipCreateMetafileFromEmf(hemf, TRUE, &metafile);
509 expect(Ok, stat);
510
511 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
512 expect(Ok, stat);
513 expectf(0.0, bounds.X);
514 expectf(0.0, bounds.Y);
515 expectf_(100.0, bounds.Width, 0.05);
516 expectf_(100.0, bounds.Height, 0.05);
517 expect(UnitPixel, unit);
518
519 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
520 expect(Ok, stat);
521 expectf(header.DpiX, xres);
522
523 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
524 expect(Ok, stat);
525 expectf(header.DpiY, yres);
526
527 memset(&header, 0xaa, sizeof(header));
528 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
529 expect(Ok, stat);
530 expect(MetafileTypeEmfPlusOnly, header.Type);
531 expect(U(header).EmfHeader.nBytes, header.Size);
532 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
533 expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
534 expectf(xres, header.DpiX);
535 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
536 expectf(yres, header.DpiY);
537 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
538 expect(0, header.X);
539 expect(0, header.Y);
540 expect(100, header.Width);
541 expect(100, header.Height);
542 expect(28, header.EmfPlusHeaderSize);
543 expect(96, header.LogicalDpiX);
544 expect(96, header.LogicalDpiX);
545 expect(EMR_HEADER, U(header).EmfHeader.iType);
546 expect(0, U(header).EmfHeader.rclBounds.left);
547 expect(0, U(header).EmfHeader.rclBounds.top);
548 expect(-1, U(header).EmfHeader.rclBounds.right);
549 expect(-1, U(header).EmfHeader.rclBounds.bottom);
550 expect(0, U(header).EmfHeader.rclFrame.left);
551 expect(0, U(header).EmfHeader.rclFrame.top);
552 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
553 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
554
555 stat = GdipDisposeImage((GpImage*)metafile);
556 expect(Ok, stat);
557 }
558
559 static const emfplus_record getdc_records[] = {
560 { EMR_HEADER },
561 { EmfPlusRecordTypeHeader },
562 { EmfPlusRecordTypeGetDC },
563 { EMR_CREATEBRUSHINDIRECT },
564 { EMR_SELECTOBJECT },
565 { EMR_RECTANGLE },
566 { EMR_SELECTOBJECT },
567 { EMR_DELETEOBJECT },
568 { EmfPlusRecordTypeEndOfFile },
569 { EMR_EOF },
570 { 0 }
571 };
572
test_getdc(void)573 static void test_getdc(void)
574 {
575 GpStatus stat;
576 GpMetafile *metafile;
577 GpGraphics *graphics;
578 HDC hdc, metafile_dc;
579 HENHMETAFILE hemf;
580 BOOL ret;
581 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
582 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
583 static const GpPointF dst_points_half[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
584 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
585 HBRUSH hbrush, holdbrush;
586 GpBitmap *bitmap;
587 ARGB color;
588
589 hdc = CreateCompatibleDC(0);
590
591 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
592 expect(Ok, stat);
593
594 DeleteDC(hdc);
595
596 if (stat != Ok)
597 return;
598
599 stat = GdipGetHemfFromMetafile(metafile, &hemf);
600 expect(InvalidParameter, stat);
601
602 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
603 expect(Ok, stat);
604
605 stat = GdipGetDC(graphics, &metafile_dc);
606 expect(Ok, stat);
607
608 if (stat != Ok)
609 {
610 GdipDeleteGraphics(graphics);
611 GdipDisposeImage((GpImage*)metafile);
612 return;
613 }
614
615 hbrush = CreateSolidBrush(0xff0000);
616
617 holdbrush = SelectObject(metafile_dc, hbrush);
618
619 Rectangle(metafile_dc, 25, 25, 75, 75);
620
621 SelectObject(metafile_dc, holdbrush);
622
623 DeleteObject(hbrush);
624
625 stat = GdipReleaseDC(graphics, metafile_dc);
626 expect(Ok, stat);
627
628 stat = GdipDeleteGraphics(graphics);
629 expect(Ok, stat);
630
631 check_metafile(metafile, getdc_records, "getdc metafile", dst_points, &frame, UnitPixel);
632
633 sync_metafile(&metafile, "getdc.emf");
634
635 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
636 expect(Ok, stat);
637
638 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
639 expect(Ok, stat);
640
641 play_metafile(metafile, graphics, getdc_records, "getdc playback", dst_points, &frame, UnitPixel);
642
643 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
644 expect(Ok, stat);
645 expect(0, color);
646
647 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
648 expect(Ok, stat);
649 expect(0xff0000ff, color);
650
651 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
652 expect(Ok, stat);
653
654 play_metafile(metafile, graphics, getdc_records, "getdc playback", dst_points_half, &frame, UnitPixel);
655
656 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
657 expect(Ok, stat);
658 expect(0xff0000ff, color);
659
660 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
661 expect(Ok, stat);
662 expect(0, color);
663
664 stat = GdipBitmapSetPixel(bitmap, 15, 15, 0);
665 expect(Ok, stat);
666
667 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
668 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
669 expect(Ok, stat);
670
671 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
672 expect(Ok, stat);
673 expect(0, color);
674
675 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
676 expect(Ok, stat);
677 expect(0xff0000ff, color);
678
679 stat = GdipDeleteGraphics(graphics);
680 expect(Ok, stat);
681
682 stat = GdipDisposeImage((GpImage*)bitmap);
683 expect(Ok, stat);
684
685 stat = GdipGetHemfFromMetafile(metafile, &hemf);
686 expect(Ok, stat);
687
688 stat = GdipDisposeImage((GpImage*)metafile);
689 expect(Ok, stat);
690
691 check_emfplus(hemf, getdc_records, "getdc emf");
692
693 ret = DeleteEnhMetaFile(hemf);
694 ok(ret != 0, "Failed to delete enhmetafile %p\n", hemf);
695 }
696
697 static const emfplus_record emfonly_records[] = {
698 { EMR_HEADER },
699 { EMR_CREATEBRUSHINDIRECT },
700 { EMR_SELECTOBJECT },
701 { EMR_RECTANGLE },
702 { EMR_SELECTOBJECT },
703 { EMR_DELETEOBJECT },
704 { EMR_EOF },
705 { 0 }
706 };
707
708 static const emfplus_record emfonly_draw_records[] = {
709 { EMR_HEADER },
710 { EMR_SAVEDC, 0, 1 },
711 { EMR_SETICMMODE, 0, 1 },
712 { EMR_SETMITERLIMIT, 0, 1 },
713 { EMR_MODIFYWORLDTRANSFORM, 0, 1 },
714 { EMR_EXTCREATEPEN, 0, 1 },
715 { EMR_SELECTOBJECT, 0, 1 },
716 { EMR_SELECTOBJECT, 0, 1 },
717 { EMR_POLYLINE16, 0, 1 },
718 { EMR_SELECTOBJECT, 0, 1 },
719 { EMR_SELECTOBJECT, 0, 1 },
720 { EMR_MODIFYWORLDTRANSFORM, 0, 1 },
721 { EMR_DELETEOBJECT, 0, 1 },
722 { EMR_SETMITERLIMIT, 0, 1 },
723 { EMR_RESTOREDC, 0, 1 },
724 { EMR_EOF },
725 { 0, 0, 1 }
726 };
727
test_emfonly(void)728 static void test_emfonly(void)
729 {
730 GpStatus stat;
731 GpMetafile *metafile;
732 GpImage *clone;
733 GpGraphics *graphics;
734 HDC hdc, metafile_dc;
735 GpRectF bounds;
736 GpUnit unit;
737 REAL xres, yres;
738 HENHMETAFILE hemf;
739 MetafileHeader header;
740 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
741 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
742 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
743 HBRUSH hbrush, holdbrush;
744 GpBitmap *bitmap;
745 ARGB color;
746 GpPen *pen;
747
748 hdc = CreateCompatibleDC(0);
749
750 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
751 expect(Ok, stat);
752
753 DeleteDC(hdc);
754
755 if (stat != Ok)
756 return;
757
758 stat = GdipGetHemfFromMetafile(metafile, &hemf);
759 expect(InvalidParameter, stat);
760
761 memset(&header, 0xaa, sizeof(header));
762 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
763 expect(Ok, stat);
764 expect(MetafileTypeEmf, header.Type);
765 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
766 /* The rest is zeroed or seemingly random/uninitialized garbage. */
767
768 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
769 expect(Ok, stat);
770
771 stat = GdipGetDC(graphics, &metafile_dc);
772 expect(Ok, stat);
773
774 if (stat != Ok)
775 {
776 GdipDeleteGraphics(graphics);
777 GdipDisposeImage((GpImage*)metafile);
778 return;
779 }
780
781 hbrush = CreateSolidBrush(0xff0000);
782
783 holdbrush = SelectObject(metafile_dc, hbrush);
784
785 Rectangle(metafile_dc, 25, 25, 75, 75);
786
787 SelectObject(metafile_dc, holdbrush);
788
789 DeleteObject(hbrush);
790
791 stat = GdipReleaseDC(graphics, metafile_dc);
792 expect(Ok, stat);
793
794 stat = GdipDeleteGraphics(graphics);
795 expect(Ok, stat);
796
797 check_metafile(metafile, emfonly_records, "emfonly metafile", dst_points, &frame, UnitPixel);
798
799 sync_metafile(&metafile, "emfonly.emf");
800
801 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
802 expect(Ok, stat);
803 expectf(0.0, bounds.X);
804 expectf(0.0, bounds.Y);
805 expectf_(100.0, bounds.Width, 0.05);
806 expectf_(100.0, bounds.Height, 0.05);
807 expect(UnitPixel, unit);
808
809 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
810 expect(Ok, stat);
811
812 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
813 expect(Ok, stat);
814
815 memset(&header, 0xaa, sizeof(header));
816 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
817 expect(Ok, stat);
818 expect(MetafileTypeEmf, header.Type);
819 expect(U(header).EmfHeader.nBytes, header.Size);
820 /* For some reason a recoreded EMF Metafile has an EMF+ version. */
821 todo_wine ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
822 expect(0, header.EmfPlusFlags);
823 expectf(xres, header.DpiX);
824 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
825 expectf(yres, header.DpiY);
826 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
827 expect(0, header.X);
828 expect(0, header.Y);
829 expect(100, header.Width);
830 expect(100, header.Height);
831 expect(0, header.EmfPlusHeaderSize);
832 expect(0, header.LogicalDpiX);
833 expect(0, header.LogicalDpiX);
834 expect(EMR_HEADER, U(header).EmfHeader.iType);
835 expect(25, U(header).EmfHeader.rclBounds.left);
836 expect(25, U(header).EmfHeader.rclBounds.top);
837 expect(74, U(header).EmfHeader.rclBounds.right);
838 expect(74, U(header).EmfHeader.rclBounds.bottom);
839 expect(0, U(header).EmfHeader.rclFrame.left);
840 expect(0, U(header).EmfHeader.rclFrame.top);
841 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
842 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
843
844 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
845 expect(Ok, stat);
846
847 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
848 expect(Ok, stat);
849
850 play_metafile(metafile, graphics, emfonly_records, "emfonly playback", dst_points, &frame, UnitPixel);
851
852 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
853 expect(Ok, stat);
854 expect(0, color);
855
856 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
857 expect(Ok, stat);
858 expect(0xff0000ff, color);
859
860 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
861 expect(Ok, stat);
862
863 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
864 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
865 expect(Ok, stat);
866
867 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
868 expect(Ok, stat);
869 expect(0, color);
870
871 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
872 expect(Ok, stat);
873 expect(0xff0000ff, color);
874
875 stat = GdipCloneImage((GpImage*)metafile, &clone);
876 expect(Ok, stat);
877
878 if (stat == Ok)
879 {
880 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
881 expect(Ok, stat);
882
883 stat = GdipDrawImagePointsRect(graphics, clone, dst_points, 3,
884 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
885 expect(Ok, stat);
886
887 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
888 expect(Ok, stat);
889 expect(0, color);
890
891 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
892 expect(Ok, stat);
893 expect(0xff0000ff, color);
894
895 GdipDisposeImage(clone);
896 }
897
898 stat = GdipDeleteGraphics(graphics);
899 expect(Ok, stat);
900
901 stat = GdipDisposeImage((GpImage*)bitmap);
902 expect(Ok, stat);
903
904 stat = GdipGetHemfFromMetafile(metafile, &hemf);
905 expect(Ok, stat);
906
907 stat = GdipDisposeImage((GpImage*)metafile);
908 expect(Ok, stat);
909
910 check_emfplus(hemf, emfonly_records, "emfonly emf");
911
912 memset(&header, 0xaa, sizeof(header));
913 stat = GdipGetMetafileHeaderFromEmf(hemf, &header);
914 expect(Ok, stat);
915 expect(MetafileTypeEmf, header.Type);
916 expect(U(header).EmfHeader.nBytes, header.Size);
917 expect(0x10000, header.Version);
918 expect(0, header.EmfPlusFlags);
919 expectf(xres, header.DpiX);
920 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
921 expectf(yres, header.DpiY);
922 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
923 expect(0, header.X);
924 expect(0, header.Y);
925 expect(100, header.Width);
926 expect(100, header.Height);
927 expect(0, header.EmfPlusHeaderSize);
928 expect(0, header.LogicalDpiX);
929 expect(0, header.LogicalDpiX);
930 expect(EMR_HEADER, U(header).EmfHeader.iType);
931 expect(25, U(header).EmfHeader.rclBounds.left);
932 expect(25, U(header).EmfHeader.rclBounds.top);
933 expect(74, U(header).EmfHeader.rclBounds.right);
934 expect(74, U(header).EmfHeader.rclBounds.bottom);
935 expect(0, U(header).EmfHeader.rclFrame.left);
936 expect(0, U(header).EmfHeader.rclFrame.top);
937 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
938 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
939
940 stat = GdipCreateMetafileFromEmf(hemf, TRUE, &metafile);
941 expect(Ok, stat);
942
943 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
944 expect(Ok, stat);
945 expectf(0.0, bounds.X);
946 expectf(0.0, bounds.Y);
947 expectf_(100.0, bounds.Width, 0.05);
948 expectf_(100.0, bounds.Height, 0.05);
949 expect(UnitPixel, unit);
950
951 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &xres);
952 expect(Ok, stat);
953 expectf(header.DpiX, xres);
954
955 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &yres);
956 expect(Ok, stat);
957 expectf(header.DpiY, yres);
958
959 memset(&header, 0xaa, sizeof(header));
960 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
961 expect(Ok, stat);
962 expect(MetafileTypeEmf, header.Type);
963 expect(U(header).EmfHeader.nBytes, header.Size);
964 expect(0x10000, header.Version);
965 expect(0, header.EmfPlusFlags);
966 expectf(xres, header.DpiX);
967 expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
968 expectf(yres, header.DpiY);
969 expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
970 expect(0, header.X);
971 expect(0, header.Y);
972 expect(100, header.Width);
973 expect(100, header.Height);
974 expect(0, header.EmfPlusHeaderSize);
975 expect(0, header.LogicalDpiX);
976 expect(0, header.LogicalDpiX);
977 expect(EMR_HEADER, U(header).EmfHeader.iType);
978 expect(25, U(header).EmfHeader.rclBounds.left);
979 expect(25, U(header).EmfHeader.rclBounds.top);
980 expect(74, U(header).EmfHeader.rclBounds.right);
981 expect(74, U(header).EmfHeader.rclBounds.bottom);
982 expect(0, U(header).EmfHeader.rclFrame.left);
983 expect(0, U(header).EmfHeader.rclFrame.top);
984 expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
985 expectf_(100.0, U(header).EmfHeader.rclFrame.bottom * yres / 2540.0, 2.0);
986
987 stat = GdipDisposeImage((GpImage*)metafile);
988 expect(Ok, stat);
989
990 /* test drawing to metafile with gdi+ functions */
991 hdc = CreateCompatibleDC(0);
992
993 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
994 expect(Ok, stat);
995
996 DeleteDC(hdc);
997
998 if (stat != Ok)
999 return;
1000
1001 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1002 expect(Ok, stat);
1003
1004 stat = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
1005 expect(Ok, stat);
1006 stat = GdipDrawLineI(graphics, pen, 0, 0, 10, 10);
1007 todo_wine expect(Ok, stat);
1008 GdipDeletePen(pen);
1009
1010 stat = GdipDeleteGraphics(graphics);
1011 expect(Ok, stat);
1012
1013 check_metafile(metafile, emfonly_draw_records, "emfonly draw metafile", dst_points, &frame, UnitPixel);
1014 sync_metafile(&metafile, "emfonly_draw.emf");
1015
1016 stat = GdipDisposeImage((GpImage*)metafile);
1017 expect(Ok, stat);
1018 }
1019
1020 static const emfplus_record fillrect_records[] = {
1021 { EMR_HEADER },
1022 { EmfPlusRecordTypeHeader },
1023 { EmfPlusRecordTypeFillRects, 0xc000 },
1024 { EmfPlusRecordTypeEndOfFile },
1025 { EMR_EOF },
1026 { 0 }
1027 };
1028
test_fillrect(void)1029 static void test_fillrect(void)
1030 {
1031 GpStatus stat;
1032 GpMetafile *metafile;
1033 GpGraphics *graphics;
1034 HDC hdc;
1035 HENHMETAFILE hemf;
1036 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1037 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1038 static const GpPointF dst_points_half[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
1039 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1040 GpBitmap *bitmap;
1041 ARGB color;
1042 GpBrush *brush;
1043
1044 hdc = CreateCompatibleDC(0);
1045
1046 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1047 expect(Ok, stat);
1048
1049 DeleteDC(hdc);
1050
1051 if (stat != Ok)
1052 return;
1053
1054 stat = GdipGetHemfFromMetafile(metafile, &hemf);
1055 expect(InvalidParameter, stat);
1056
1057 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1058 expect(Ok, stat);
1059
1060 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1061 expect(Ok, stat);
1062
1063 stat = GdipFillRectangleI(graphics, brush, 25, 25, 75, 75);
1064 expect(Ok, stat);
1065
1066 stat = GdipDeleteBrush(brush);
1067 expect(Ok, stat);
1068
1069 stat = GdipDeleteGraphics(graphics);
1070 expect(Ok, stat);
1071
1072 check_metafile(metafile, fillrect_records, "fillrect metafile", dst_points, &frame, UnitPixel);
1073
1074 sync_metafile(&metafile, "fillrect.emf");
1075
1076 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
1077 expect(Ok, stat);
1078
1079 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1080 expect(Ok, stat);
1081
1082 play_metafile(metafile, graphics, fillrect_records, "fillrect playback", dst_points, &frame, UnitPixel);
1083
1084 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1085 expect(Ok, stat);
1086 expect(0, color);
1087
1088 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1089 expect(Ok, stat);
1090 expect(0xff0000ff, color);
1091
1092 stat = GdipBitmapSetPixel(bitmap, 50, 50, 0);
1093 expect(Ok, stat);
1094
1095 play_metafile(metafile, graphics, fillrect_records, "fillrect playback", dst_points_half, &frame, UnitPixel);
1096
1097 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1098 expect(Ok, stat);
1099 expect(0xff0000ff, color);
1100
1101 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1102 expect(Ok, stat);
1103 expect(0, color);
1104
1105 stat = GdipBitmapSetPixel(bitmap, 15, 15, 0);
1106 expect(Ok, stat);
1107
1108 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
1109 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
1110 expect(Ok, stat);
1111
1112 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1113 expect(Ok, stat);
1114 expect(0, color);
1115
1116 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1117 expect(Ok, stat);
1118 expect(0xff0000ff, color);
1119
1120 stat = GdipDeleteGraphics(graphics);
1121 expect(Ok, stat);
1122
1123 stat = GdipDisposeImage((GpImage*)bitmap);
1124 expect(Ok, stat);
1125
1126 stat = GdipDisposeImage((GpImage*)metafile);
1127 expect(Ok, stat);
1128 }
1129
1130 static const emfplus_record clear_emf_records[] = {
1131 { EMR_HEADER },
1132 { EmfPlusRecordTypeHeader },
1133 { EmfPlusRecordTypeClear },
1134 { EMR_SAVEDC, 0, 1 },
1135 { EMR_SETICMMODE, 0, 1 },
1136 { EMR_BITBLT, 0, 1 },
1137 { EMR_RESTOREDC, 0, 1 },
1138 { EmfPlusRecordTypeEndOfFile },
1139 { EMR_EOF },
1140 { 0 }
1141 };
1142
test_clear(void)1143 static void test_clear(void)
1144 {
1145 GpStatus stat;
1146 GpMetafile *metafile;
1147 GpGraphics *graphics;
1148 HDC hdc;
1149 HENHMETAFILE hemf;
1150 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1151 static const GpPointF dst_points[3] = {{10.0,10.0},{20.0,10.0},{10.0,20.0}};
1152 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1153 GpBitmap *bitmap;
1154 ARGB color;
1155
1156 hdc = CreateCompatibleDC(0);
1157
1158 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1159 expect(Ok, stat);
1160
1161 DeleteDC(hdc);
1162
1163 if (stat != Ok)
1164 return;
1165
1166 stat = GdipGetHemfFromMetafile(metafile, &hemf);
1167 expect(InvalidParameter, stat);
1168
1169 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1170 expect(Ok, stat);
1171
1172 stat = GdipGraphicsClear(graphics, 0xffffff00);
1173 expect(Ok, stat);
1174
1175 stat = GdipDeleteGraphics(graphics);
1176 expect(Ok, stat);
1177
1178 sync_metafile(&metafile, "clear.emf");
1179
1180 stat = GdipCreateBitmapFromScan0(30, 30, 0, PixelFormat32bppRGB, NULL, &bitmap);
1181 expect(Ok, stat);
1182
1183 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1184 expect(Ok, stat);
1185
1186 stat = GdipDrawImagePointsRect(graphics, (GpImage*)metafile, dst_points, 3,
1187 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
1188 expect(Ok, stat);
1189
1190 stat = GdipBitmapGetPixel(bitmap, 5, 5, &color);
1191 expect(Ok, stat);
1192 expect(0xff000000, color);
1193
1194 stat = GdipBitmapGetPixel(bitmap, 15, 15, &color);
1195 expect(Ok, stat);
1196 expect(0xffffff00, color);
1197
1198 stat = GdipBitmapGetPixel(bitmap, 25, 25, &color);
1199 expect(Ok, stat);
1200 expect(0xff000000, color);
1201
1202 stat = GdipDeleteGraphics(graphics);
1203 expect(Ok, stat);
1204
1205 stat = GdipDisposeImage((GpImage*)bitmap);
1206 expect(Ok, stat);
1207
1208 stat = GdipGetHemfFromMetafile(metafile, &hemf);
1209 expect(Ok, stat);
1210
1211 stat = GdipDisposeImage((GpImage*)metafile);
1212 expect(Ok, stat);
1213
1214 check_emfplus(hemf, clear_emf_records, "clear emf");
1215
1216 DeleteEnhMetaFile(hemf);
1217 }
1218
test_nullframerect(void)1219 static void test_nullframerect(void) {
1220 GpStatus stat;
1221 GpMetafile *metafile;
1222 GpGraphics *graphics;
1223 HDC hdc, metafile_dc;
1224 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1225 GpBrush *brush;
1226 HBRUSH hbrush, holdbrush;
1227 GpRectF bounds;
1228 GpUnit unit;
1229
1230 hdc = CreateCompatibleDC(0);
1231
1232 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, NULL, MetafileFrameUnitPixel, description, &metafile);
1233 expect(Ok, stat);
1234
1235 DeleteDC(hdc);
1236
1237 if (stat != Ok)
1238 return;
1239
1240 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1241 expect(Ok, stat);
1242 expect(UnitPixel, unit);
1243 expectf(0.0, bounds.X);
1244 expectf(0.0, bounds.Y);
1245 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1246 "expected 1.0, got %f\n", bounds.Width);
1247 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1248 "expected 1.0, got %f\n", bounds.Height);
1249
1250 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1251 expect(Ok, stat);
1252
1253 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1254 expect(Ok, stat);
1255
1256 stat = GdipFillRectangleI(graphics, brush, 25, 25, 75, 75);
1257 expect(Ok, stat);
1258
1259 stat = GdipDeleteBrush(brush);
1260 expect(Ok, stat);
1261
1262 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1263 expect(Ok, stat);
1264 expect(UnitPixel, unit);
1265 expectf(0.0, bounds.X);
1266 expectf(0.0, bounds.Y);
1267 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1268 "expected 1.0, got %f\n", bounds.Width);
1269 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1270 "expected 1.0, got %f\n", bounds.Height);
1271
1272 stat = GdipDeleteGraphics(graphics);
1273 expect(Ok, stat);
1274
1275 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1276 expect(Ok, stat);
1277 expect(UnitPixel, unit);
1278 expectf_(25.0, bounds.X, 0.05);
1279 expectf_(25.0, bounds.Y, 0.05);
1280 expectf_(75.0, bounds.Width, 0.05);
1281 expectf_(75.0, bounds.Height, 0.05);
1282
1283 stat = GdipDisposeImage((GpImage*)metafile);
1284 expect(Ok, stat);
1285
1286 hdc = CreateCompatibleDC(0);
1287
1288 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, NULL, MetafileFrameUnitMillimeter, description, &metafile);
1289 expect(Ok, stat);
1290
1291 DeleteDC(hdc);
1292
1293 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1294 expect(Ok, stat);
1295
1296 stat = GdipGetDC(graphics, &metafile_dc);
1297 expect(Ok, stat);
1298
1299 if (stat != Ok)
1300 {
1301 GdipDeleteGraphics(graphics);
1302 GdipDisposeImage((GpImage*)metafile);
1303 return;
1304 }
1305
1306 hbrush = CreateSolidBrush(0xff0000);
1307
1308 holdbrush = SelectObject(metafile_dc, hbrush);
1309
1310 Rectangle(metafile_dc, 25, 25, 75, 75);
1311
1312 SelectObject(metafile_dc, holdbrush);
1313
1314 DeleteObject(hbrush);
1315
1316 stat = GdipReleaseDC(graphics, metafile_dc);
1317 expect(Ok, stat);
1318
1319 stat = GdipDeleteGraphics(graphics);
1320 expect(Ok, stat);
1321
1322 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1323 expect(Ok, stat);
1324 expect(UnitPixel, unit);
1325 expectf_(25.0, bounds.X, 0.05);
1326 expectf_(25.0, bounds.Y, 0.05);
1327 todo_wine expectf_(50.0, bounds.Width, 0.05);
1328 todo_wine expectf_(50.0, bounds.Height, 0.05);
1329
1330 stat = GdipDisposeImage((GpImage*)metafile);
1331 expect(Ok, stat);
1332 }
1333
1334 static const emfplus_record pagetransform_records[] = {
1335 { EMR_HEADER },
1336 { EmfPlusRecordTypeHeader },
1337 { EmfPlusRecordTypeFillRects, 0xc000 },
1338 { EmfPlusRecordTypeSetPageTransform, UnitPixel },
1339 { EmfPlusRecordTypeFillRects, 0xc000 },
1340 { EmfPlusRecordTypeSetPageTransform, UnitPixel },
1341 { EmfPlusRecordTypeFillRects, 0xc000 },
1342 { EmfPlusRecordTypeSetPageTransform, UnitInch },
1343 { EmfPlusRecordTypeFillRects, 0x8000 },
1344 { EmfPlusRecordTypeSetPageTransform, UnitDisplay },
1345 { EmfPlusRecordTypeFillRects, 0xc000 },
1346 { EmfPlusRecordTypeEndOfFile },
1347 { EMR_EOF },
1348 { 0 }
1349 };
1350
test_pagetransform(void)1351 static void test_pagetransform(void)
1352 {
1353 GpStatus stat;
1354 GpMetafile *metafile;
1355 GpGraphics *graphics;
1356 HDC hdc;
1357 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
1358 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1359 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1360 GpBitmap *bitmap;
1361 ARGB color;
1362 GpBrush *brush;
1363 GpUnit unit;
1364 REAL scale, dpix, dpiy;
1365 UINT width, height;
1366
1367 hdc = CreateCompatibleDC(0);
1368
1369 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitInch, description, &metafile);
1370 expect(Ok, stat);
1371
1372 DeleteDC(hdc);
1373
1374 if (stat != Ok)
1375 return;
1376
1377 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &dpix);
1378 todo_wine expect(InvalidParameter, stat);
1379
1380 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &dpiy);
1381 todo_wine expect(InvalidParameter, stat);
1382
1383 stat = GdipGetImageWidth((GpImage*)metafile, &width);
1384 todo_wine expect(InvalidParameter, stat);
1385
1386 stat = GdipGetImageHeight((GpImage*)metafile, &height);
1387 todo_wine expect(InvalidParameter, stat);
1388
1389 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1390 expect(Ok, stat);
1391
1392 /* initial scale */
1393 stat = GdipGetPageUnit(graphics, &unit);
1394 expect(Ok, stat);
1395 expect(UnitDisplay, unit);
1396
1397 stat = GdipGetPageScale(graphics, &scale);
1398 expect(Ok, stat);
1399 expectf(1.0, scale);
1400
1401 stat = GdipGetDpiX(graphics, &dpix);
1402 expect(Ok, stat);
1403 expectf(96.0, dpix);
1404
1405 stat = GdipGetDpiY(graphics, &dpiy);
1406 expect(Ok, stat);
1407 expectf(96.0, dpiy);
1408
1409 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1410 expect(Ok, stat);
1411
1412 stat = GdipFillRectangleI(graphics, brush, 1, 2, 1, 1);
1413 expect(Ok, stat);
1414
1415 stat = GdipDeleteBrush(brush);
1416 expect(Ok, stat);
1417
1418 /* page unit = pixels */
1419 stat = GdipSetPageUnit(graphics, UnitPixel);
1420 expect(Ok, stat);
1421
1422 stat = GdipGetPageUnit(graphics, &unit);
1423 expect(Ok, stat);
1424 expect(UnitPixel, unit);
1425
1426 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
1427 expect(Ok, stat);
1428
1429 stat = GdipFillRectangleI(graphics, brush, 0, 1, 1, 1);
1430 expect(Ok, stat);
1431
1432 stat = GdipDeleteBrush(brush);
1433 expect(Ok, stat);
1434
1435 /* page scale = 3, unit = pixels */
1436 stat = GdipSetPageScale(graphics, 3.0);
1437 expect(Ok, stat);
1438
1439 stat = GdipGetPageScale(graphics, &scale);
1440 expect(Ok, stat);
1441 expectf(3.0, scale);
1442
1443 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
1444 expect(Ok, stat);
1445
1446 stat = GdipFillRectangleI(graphics, brush, 0, 1, 2, 2);
1447 expect(Ok, stat);
1448
1449 stat = GdipDeleteBrush(brush);
1450 expect(Ok, stat);
1451
1452 /* page scale = 3, unit = inches */
1453 stat = GdipSetPageUnit(graphics, UnitInch);
1454 expect(Ok, stat);
1455
1456 stat = GdipGetPageUnit(graphics, &unit);
1457 expect(Ok, stat);
1458 expect(UnitInch, unit);
1459
1460 stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
1461 expect(Ok, stat);
1462
1463 stat = GdipFillRectangle(graphics, brush, 1.0/96.0, 0, 1, 1);
1464 expect(Ok, stat);
1465
1466 stat = GdipDeleteBrush(brush);
1467 expect(Ok, stat);
1468
1469 /* page scale = 3, unit = display */
1470 stat = GdipSetPageUnit(graphics, UnitDisplay);
1471 expect(Ok, stat);
1472
1473 stat = GdipGetPageUnit(graphics, &unit);
1474 expect(Ok, stat);
1475 expect(UnitDisplay, unit);
1476
1477 stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
1478 expect(Ok, stat);
1479
1480 stat = GdipFillRectangle(graphics, brush, 3, 3, 2, 2);
1481 expect(Ok, stat);
1482
1483 stat = GdipDeleteBrush(brush);
1484 expect(Ok, stat);
1485
1486 stat = GdipDeleteGraphics(graphics);
1487 expect(Ok, stat);
1488
1489 check_metafile(metafile, pagetransform_records, "pagetransform metafile", dst_points, &frame, UnitPixel);
1490
1491 sync_metafile(&metafile, "pagetransform.emf");
1492
1493 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
1494 expect(Ok, stat);
1495
1496 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1497 expect(Ok, stat);
1498
1499 play_metafile(metafile, graphics, pagetransform_records, "pagetransform playback", dst_points, &frame, UnitPixel);
1500
1501 stat = GdipBitmapGetPixel(bitmap, 50, 50, &color);
1502 expect(Ok, stat);
1503 expect(0, color);
1504
1505 stat = GdipBitmapGetPixel(bitmap, 30, 50, &color);
1506 expect(Ok, stat);
1507 expect(0xff0000ff, color);
1508
1509 stat = GdipBitmapGetPixel(bitmap, 10, 30, &color);
1510 expect(Ok, stat);
1511 expect(0xff00ff00, color);
1512
1513 stat = GdipBitmapGetPixel(bitmap, 20, 80, &color);
1514 expect(Ok, stat);
1515 expect(0xff00ffff, color);
1516
1517 stat = GdipBitmapGetPixel(bitmap, 80, 20, &color);
1518 expect(Ok, stat);
1519 expect(0xffff0000, color);
1520
1521 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
1522 expect(Ok, stat);
1523 expect(0xffff00ff, color);
1524
1525 stat = GdipDeleteGraphics(graphics);
1526 expect(Ok, stat);
1527
1528 stat = GdipDisposeImage((GpImage*)bitmap);
1529 expect(Ok, stat);
1530
1531 stat = GdipDisposeImage((GpImage*)metafile);
1532 expect(Ok, stat);
1533 }
1534
1535 static const emfplus_record worldtransform_records[] = {
1536 { EMR_HEADER },
1537 { EmfPlusRecordTypeHeader },
1538 { EmfPlusRecordTypeFillRects, 0xc000 },
1539 { EmfPlusRecordTypeScaleWorldTransform },
1540 { EmfPlusRecordTypeFillRects, 0x8000 },
1541 { EmfPlusRecordTypeResetWorldTransform },
1542 { EmfPlusRecordTypeFillRects, 0xc000 },
1543 { EmfPlusRecordTypeMultiplyWorldTransform },
1544 { EmfPlusRecordTypeFillRects, 0x8000 },
1545 { EmfPlusRecordTypeRotateWorldTransform, 0x2000 },
1546 { EmfPlusRecordTypeFillRects, 0x8000 },
1547 { EmfPlusRecordTypeSetWorldTransform },
1548 { EmfPlusRecordTypeFillRects, 0xc000 },
1549 { EmfPlusRecordTypeTranslateWorldTransform, 0x2000 },
1550 { EmfPlusRecordTypeFillRects, 0xc000 },
1551 { EmfPlusRecordTypeEndOfFile },
1552 { EMR_EOF },
1553 { 0 }
1554 };
1555
test_worldtransform(void)1556 static void test_worldtransform(void)
1557 {
1558 GpStatus stat;
1559 GpMetafile *metafile;
1560 GpGraphics *graphics;
1561 HDC hdc;
1562 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
1563 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1564 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1565 GpBitmap *bitmap;
1566 ARGB color;
1567 GpBrush *brush;
1568 GpMatrix *transform;
1569 BOOL identity;
1570 REAL elements[6];
1571
1572 hdc = CreateCompatibleDC(0);
1573
1574 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
1575 expect(Ok, stat);
1576
1577 DeleteDC(hdc);
1578
1579 if (stat != Ok)
1580 return;
1581
1582 stat = GdipCreateMatrix(&transform);
1583 expect(Ok, stat);
1584
1585 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1586 expect(Ok, stat);
1587
1588 /* initial transform */
1589 stat = GdipGetWorldTransform(graphics, transform);
1590 expect(Ok, stat);
1591
1592 stat = GdipIsMatrixIdentity(transform, &identity);
1593 expect(Ok, stat);
1594 expect(TRUE, identity);
1595
1596 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
1597 expect(Ok, stat);
1598
1599 stat = GdipFillRectangleI(graphics, brush, 0, 0, 1, 1);
1600 expect(Ok, stat);
1601
1602 stat = GdipDeleteBrush(brush);
1603 expect(Ok, stat);
1604
1605 /* scale transform */
1606 stat = GdipScaleWorldTransform(graphics, 2.0, 4.0, MatrixOrderPrepend);
1607 expect(Ok, stat);
1608
1609 stat = GdipGetWorldTransform(graphics, transform);
1610 expect(Ok, stat);
1611
1612 stat = GdipGetMatrixElements(transform, elements);
1613 expect(Ok, stat);
1614 expectf(2.0, elements[0]);
1615 expectf(0.0, elements[1]);
1616 expectf(0.0, elements[2]);
1617 expectf(4.0, elements[3]);
1618 expectf(0.0, elements[4]);
1619 expectf(0.0, elements[5]);
1620
1621 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
1622 expect(Ok, stat);
1623
1624 stat = GdipFillRectangle(graphics, brush, 0.5, 0.5, 0.5, 0.25);
1625 expect(Ok, stat);
1626
1627 stat = GdipDeleteBrush(brush);
1628 expect(Ok, stat);
1629
1630 /* reset transform */
1631 stat = GdipResetWorldTransform(graphics);
1632 expect(Ok, stat);
1633
1634 stat = GdipGetWorldTransform(graphics, transform);
1635 expect(Ok, stat);
1636
1637 stat = GdipIsMatrixIdentity(transform, &identity);
1638 expect(Ok, stat);
1639 expect(TRUE, identity);
1640
1641 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
1642 expect(Ok, stat);
1643
1644 stat = GdipFillRectangle(graphics, brush, 1.0, 0.0, 1.0, 1.0);
1645 expect(Ok, stat);
1646
1647 stat = GdipDeleteBrush(brush);
1648 expect(Ok, stat);
1649
1650 /* multiply transform */
1651 stat = GdipSetMatrixElements(transform, 2.0, 0.0, 0.0, 1.0, 0.0, 0.0);
1652 expect(Ok, stat);
1653
1654 stat = GdipMultiplyWorldTransform(graphics, transform, MatrixOrderPrepend);
1655 expect(Ok, stat);
1656
1657 stat = GdipGetWorldTransform(graphics, transform);
1658 expect(Ok, stat);
1659
1660 stat = GdipGetMatrixElements(transform, elements);
1661 expect(Ok, stat);
1662 expectf(2.0, elements[0]);
1663 expectf(0.0, elements[1]);
1664 expectf(0.0, elements[2]);
1665 expectf(1.0, elements[3]);
1666 expectf(0.0, elements[4]);
1667 expectf(0.0, elements[5]);
1668
1669 stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
1670 expect(Ok, stat);
1671
1672 stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 0.5, 1.0);
1673 expect(Ok, stat);
1674
1675 stat = GdipDeleteBrush(brush);
1676 expect(Ok, stat);
1677
1678 /* rotate transform */
1679 stat = GdipRotateWorldTransform(graphics, 90.0, MatrixOrderAppend);
1680 expect(Ok, stat);
1681
1682 stat = GdipGetWorldTransform(graphics, transform);
1683 expect(Ok, stat);
1684
1685 stat = GdipGetMatrixElements(transform, elements);
1686 expect(Ok, stat);
1687 expectf(0.0, elements[0]);
1688 expectf(2.0, elements[1]);
1689 expectf(-1.0, elements[2]);
1690 expectf(0.0, elements[3]);
1691 expectf(0.0, elements[4]);
1692 expectf(0.0, elements[5]);
1693
1694 stat = GdipCreateSolidFill((ARGB)0xffff00ff, (GpSolidFill**)&brush);
1695 expect(Ok, stat);
1696
1697 stat = GdipFillRectangle(graphics, brush, 1.0, -1.0, 0.5, 1.0);
1698 expect(Ok, stat);
1699
1700 stat = GdipDeleteBrush(brush);
1701 expect(Ok, stat);
1702
1703 /* set transform */
1704 stat = GdipSetMatrixElements(transform, 1.0, 0.0, 0.0, 3.0, 0.0, 0.0);
1705 expect(Ok, stat);
1706
1707 stat = GdipSetWorldTransform(graphics, transform);
1708 expect(Ok, stat);
1709
1710 stat = GdipGetWorldTransform(graphics, transform);
1711 expect(Ok, stat);
1712
1713 stat = GdipGetMatrixElements(transform, elements);
1714 expect(Ok, stat);
1715 expectf(1.0, elements[0]);
1716 expectf(0.0, elements[1]);
1717 expectf(0.0, elements[2]);
1718 expectf(3.0, elements[3]);
1719 expectf(0.0, elements[4]);
1720 expectf(0.0, elements[5]);
1721
1722 stat = GdipCreateSolidFill((ARGB)0xffffff00, (GpSolidFill**)&brush);
1723 expect(Ok, stat);
1724
1725 stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 1.0, 1.0);
1726 expect(Ok, stat);
1727
1728 stat = GdipDeleteBrush(brush);
1729 expect(Ok, stat);
1730
1731 /* translate transform */
1732 stat = GdipTranslateWorldTransform(graphics, -1.0, 0.0, MatrixOrderAppend);
1733 expect(Ok, stat);
1734
1735 stat = GdipGetWorldTransform(graphics, transform);
1736 expect(Ok, stat);
1737
1738 stat = GdipGetMatrixElements(transform, elements);
1739 expect(Ok, stat);
1740 expectf(1.0, elements[0]);
1741 expectf(0.0, elements[1]);
1742 expectf(0.0, elements[2]);
1743 expectf(3.0, elements[3]);
1744 expectf(-1.0, elements[4]);
1745 expectf(0.0, elements[5]);
1746
1747 stat = GdipCreateSolidFill((ARGB)0xffffffff, (GpSolidFill**)&brush);
1748 expect(Ok, stat);
1749
1750 stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 1.0, 1.0);
1751 expect(Ok, stat);
1752
1753 stat = GdipDeleteBrush(brush);
1754 expect(Ok, stat);
1755
1756 stat = GdipDeleteMatrix(transform);
1757 expect(Ok, stat);
1758
1759 stat = GdipDeleteGraphics(graphics);
1760 expect(Ok, stat);
1761
1762 check_metafile(metafile, worldtransform_records, "worldtransform metafile", dst_points, &frame, UnitPixel);
1763
1764 sync_metafile(&metafile, "worldtransform.emf");
1765
1766 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
1767 expect(Ok, stat);
1768
1769 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1770 expect(Ok, stat);
1771
1772 play_metafile(metafile, graphics, worldtransform_records, "worldtransform playback", dst_points, &frame, UnitPixel);
1773
1774 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
1775 expect(Ok, stat);
1776 expect(0, color);
1777
1778 stat = GdipBitmapGetPixel(bitmap, 10, 10, &color);
1779 expect(Ok, stat);
1780 expect(0xff0000ff, color);
1781
1782 stat = GdipBitmapGetPixel(bitmap, 30, 50, &color);
1783 expect(Ok, stat);
1784 expect(0xff00ff00, color);
1785
1786 stat = GdipBitmapGetPixel(bitmap, 30, 10, &color);
1787 expect(Ok, stat);
1788 expect(0xff00ffff, color);
1789
1790 stat = GdipBitmapGetPixel(bitmap, 50, 30, &color);
1791 expect(Ok, stat);
1792 expect(0xffff0000, color);
1793
1794 stat = GdipBitmapGetPixel(bitmap, 10, 50, &color);
1795 expect(Ok, stat);
1796 expect(0xffff00ff, color);
1797
1798 stat = GdipBitmapGetPixel(bitmap, 30, 90, &color);
1799 expect(Ok, stat);
1800 expect(0xffffff00, color);
1801
1802 stat = GdipBitmapGetPixel(bitmap, 10, 90, &color);
1803 expect(Ok, stat);
1804 expect(0xffffffff, color);
1805
1806 stat = GdipDeleteGraphics(graphics);
1807 expect(Ok, stat);
1808
1809 stat = GdipDisposeImage((GpImage*)bitmap);
1810 expect(Ok, stat);
1811
1812 stat = GdipDisposeImage((GpImage*)metafile);
1813 expect(Ok, stat);
1814 }
1815
test_converttoemfplus(void)1816 static void test_converttoemfplus(void)
1817 {
1818 GpStatus (WINAPI *pGdipConvertToEmfPlus)( const GpGraphics *graphics, GpMetafile *metafile, BOOL *succ,
1819 EmfType emfType, const WCHAR *description, GpMetafile **outmetafile);
1820 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1821 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1822 GpStatus stat;
1823 GpMetafile *metafile, *metafile2 = NULL, *emhmeta;
1824 GpGraphics *graphics;
1825 HDC hdc;
1826 BOOL succ;
1827 HMODULE mod = GetModuleHandleA("gdiplus.dll");
1828
1829 pGdipConvertToEmfPlus = (void*)GetProcAddress( mod, "GdipConvertToEmfPlus");
1830 if(!pGdipConvertToEmfPlus)
1831 {
1832 /* GdipConvertToEmfPlus was introduced in Windows Vista. */
1833 win_skip("GDIPlus version 1.1 not available\n");
1834 return;
1835 }
1836
1837 hdc = CreateCompatibleDC(0);
1838
1839 stat = GdipRecordMetafile(hdc, MetafileTypeEmf, &frame, MetafileFrameUnitPixel, description, &metafile);
1840 expect(Ok, stat);
1841
1842 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &emhmeta);
1843 expect(Ok, stat);
1844
1845 DeleteDC(hdc);
1846
1847 if (stat != Ok)
1848 return;
1849
1850 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1851 expect(Ok, stat);
1852
1853 /* Invalid Parameters */
1854 stat = pGdipConvertToEmfPlus(NULL, metafile, &succ, EmfTypeEmfPlusOnly, description, &metafile2);
1855 expect(InvalidParameter, stat);
1856
1857 stat = pGdipConvertToEmfPlus(graphics, NULL, &succ, EmfTypeEmfPlusOnly, description, &metafile2);
1858 expect(InvalidParameter, stat);
1859
1860 stat = pGdipConvertToEmfPlus(graphics, metafile, &succ, EmfTypeEmfPlusOnly, description, NULL);
1861 expect(InvalidParameter, stat);
1862
1863 stat = pGdipConvertToEmfPlus(graphics, metafile, NULL, MetafileTypeInvalid, NULL, &metafile2);
1864 expect(InvalidParameter, stat);
1865
1866 stat = pGdipConvertToEmfPlus(graphics, metafile, NULL, MetafileTypeEmfPlusDual+1, NULL, &metafile2);
1867 expect(InvalidParameter, stat);
1868
1869 /* If we are already an Enhanced Metafile then the conversion fails. */
1870 stat = pGdipConvertToEmfPlus(graphics, emhmeta, NULL, EmfTypeEmfPlusOnly, NULL, &metafile2);
1871 todo_wine expect(InvalidParameter, stat);
1872
1873 stat = pGdipConvertToEmfPlus(graphics, metafile, NULL, EmfTypeEmfPlusOnly, NULL, &metafile2);
1874 todo_wine expect(Ok, stat);
1875 if(metafile2)
1876 GdipDisposeImage((GpImage*)metafile2);
1877
1878 succ = FALSE;
1879 stat = pGdipConvertToEmfPlus(graphics, metafile, &succ, EmfTypeEmfPlusOnly, NULL, &metafile2);
1880 todo_wine expect(Ok, stat);
1881 if(metafile2)
1882 GdipDisposeImage((GpImage*)metafile2);
1883
1884 stat = GdipDeleteGraphics(graphics);
1885 expect(Ok, stat);
1886
1887 stat = GdipDisposeImage((GpImage*)metafile);
1888 expect(Ok, stat);
1889
1890 stat = GdipDisposeImage((GpImage*)emhmeta);
1891 expect(Ok, stat);
1892 }
1893
test_frameunit(void)1894 static void test_frameunit(void)
1895 {
1896 GpStatus stat;
1897 GpMetafile *metafile;
1898 GpGraphics *graphics;
1899 HDC hdc;
1900 static const GpRectF frame = {0.0, 0.0, 5.0, 5.0};
1901 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1902 GpUnit unit;
1903 REAL dpix, dpiy;
1904 GpRectF bounds;
1905
1906 hdc = CreateCompatibleDC(0);
1907
1908 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitInch, description, &metafile);
1909 expect(Ok, stat);
1910
1911 DeleteDC(hdc);
1912
1913 if (stat != Ok)
1914 return;
1915
1916 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1917 expect(Ok, stat);
1918 expect(UnitPixel, unit);
1919 expectf(0.0, bounds.X);
1920 expectf(0.0, bounds.Y);
1921 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1922 "expected 1.0, got %f\n", bounds.Width);
1923 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1924 "expected 1.0, got %f\n", bounds.Height);
1925
1926 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
1927 expect(Ok, stat);
1928
1929 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1930 expect(Ok, stat);
1931 expect(UnitPixel, unit);
1932 expectf(0.0, bounds.X);
1933 expectf(0.0, bounds.Y);
1934 ok(bounds.Width == 1.0 || broken(bounds.Width == 0.0) /* xp sp1 */,
1935 "expected 1.0, got %f\n", bounds.Width);
1936 ok(bounds.Height == 1.0 || broken(bounds.Height == 0.0) /* xp sp1 */,
1937 "expected 1.0, got %f\n", bounds.Height);
1938
1939 stat = GdipDeleteGraphics(graphics);
1940 expect(Ok, stat);
1941
1942 stat = GdipGetImageHorizontalResolution((GpImage*)metafile, &dpix);
1943 expect(Ok, stat);
1944
1945 stat = GdipGetImageVerticalResolution((GpImage*)metafile, &dpiy);
1946 expect(Ok, stat);
1947
1948 stat = GdipGetImageBounds((GpImage*)metafile, &bounds, &unit);
1949 expect(Ok, stat);
1950 expect(UnitPixel, unit);
1951 expectf(0.0, bounds.X);
1952 expectf(0.0, bounds.Y);
1953 expectf_(5.0 * dpix, bounds.Width, 1.0);
1954 expectf_(5.0 * dpiy, bounds.Height, 1.0);
1955
1956 stat = GdipDisposeImage((GpImage*)metafile);
1957 expect(Ok, stat);
1958 }
1959
1960 static const emfplus_record container_records[] = {
1961 { EMR_HEADER },
1962 { EmfPlusRecordTypeHeader },
1963 { EmfPlusRecordTypeBeginContainerNoParams },
1964 { EmfPlusRecordTypeScaleWorldTransform },
1965 { EmfPlusRecordTypeFillRects, 0xc000 },
1966 { EmfPlusRecordTypeEndContainer },
1967 { EmfPlusRecordTypeScaleWorldTransform },
1968 { EmfPlusRecordTypeFillRects, 0xc000 },
1969 { EmfPlusRecordTypeSave },
1970 { EmfPlusRecordTypeRestore },
1971 { EmfPlusRecordTypeScaleWorldTransform },
1972 { EmfPlusRecordTypeBeginContainerNoParams },
1973 { EmfPlusRecordTypeScaleWorldTransform },
1974 { EmfPlusRecordTypeBeginContainerNoParams },
1975 { EmfPlusRecordTypeEndContainer },
1976 { EmfPlusRecordTypeFillRects, 0xc000 },
1977 { EmfPlusRecordTypeBeginContainer, UnitInch },
1978 { EmfPlusRecordTypeFillRects, 0xc000 },
1979 { EmfPlusRecordTypeEndContainer },
1980 { EmfPlusRecordTypeBeginContainerNoParams },
1981 { EmfPlusRecordTypeEndOfFile },
1982 { EMR_EOF },
1983 { 0 }
1984 };
1985
test_containers(void)1986 static void test_containers(void)
1987 {
1988 GpStatus stat;
1989 GpMetafile *metafile;
1990 GpGraphics *graphics;
1991 GpBitmap *bitmap;
1992 GpBrush *brush;
1993 ARGB color;
1994 HDC hdc;
1995 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
1996 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
1997 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
1998 GraphicsContainer state1, state2;
1999 GpRectF srcrect, dstrect;
2000 REAL dpix, dpiy;
2001
2002 hdc = CreateCompatibleDC(0);
2003
2004 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2005 expect(Ok, stat);
2006
2007 DeleteDC(hdc);
2008
2009 if (stat != Ok)
2010 return;
2011
2012 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2013 expect(Ok, stat);
2014
2015 /* Normal usage */
2016 stat = GdipBeginContainer2(graphics, &state1);
2017 expect(Ok, stat);
2018
2019 stat = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
2020 expect(Ok, stat);
2021
2022 stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
2023 expect(Ok, stat);
2024
2025 stat = GdipFillRectangle(graphics, brush, 5.0, 5.0, 5.0, 5.0);
2026 expect(Ok, stat);
2027
2028 stat = GdipDeleteBrush(brush);
2029 expect(Ok, stat);
2030
2031 stat = GdipEndContainer(graphics, state1);
2032 expect(Ok, stat);
2033
2034 stat = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
2035 expect(Ok, stat);
2036
2037 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
2038 expect(Ok, stat);
2039
2040 stat = GdipFillRectangle(graphics, brush, 5.0, 5.0, 5.0, 5.0);
2041 expect(Ok, stat);
2042
2043 stat = GdipDeleteBrush(brush);
2044 expect(Ok, stat);
2045
2046 stat = GdipSaveGraphics(graphics, &state1);
2047 expect(Ok, stat);
2048
2049 stat = GdipRestoreGraphics(graphics, state1);
2050 expect(Ok, stat);
2051
2052 /* Popping two states at once */
2053 stat = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
2054 expect(Ok, stat);
2055
2056 stat = GdipBeginContainer2(graphics, &state1);
2057 expect(Ok, stat);
2058
2059 stat = GdipScaleWorldTransform(graphics, 4.0, 4.0, MatrixOrderPrepend);
2060 expect(Ok, stat);
2061
2062 stat = GdipBeginContainer2(graphics, &state2);
2063 expect(Ok, stat);
2064
2065 stat = GdipEndContainer(graphics, state1);
2066 expect(Ok, stat);
2067
2068 stat = GdipCreateSolidFill((ARGB)0xff00ff00, (GpSolidFill**)&brush);
2069 expect(Ok, stat);
2070
2071 stat = GdipFillRectangle(graphics, brush, 20.0, 20.0, 5.0, 5.0);
2072 expect(Ok, stat);
2073
2074 stat = GdipDeleteBrush(brush);
2075 expect(Ok, stat);
2076
2077 /* With transform applied */
2078 stat = GdipGetDpiX(graphics, &dpix);
2079 expect(Ok, stat);
2080
2081 stat = GdipGetDpiY(graphics, &dpiy);
2082 expect(Ok, stat);
2083
2084 srcrect.X = 0.0;
2085 srcrect.Y = 0.0;
2086 srcrect.Width = 1.0;
2087 srcrect.Height = 1.0;
2088
2089 dstrect.X = 25.0;
2090 dstrect.Y = 0.0;
2091 dstrect.Width = 5.0;
2092 dstrect.Height = 5.0;
2093
2094 stat = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state1);
2095 expect(Ok, stat);
2096
2097 stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
2098 expect(Ok, stat);
2099
2100 stat = GdipFillRectangle(graphics, brush, 0.0, 0.0, dpix, dpiy);
2101 expect(Ok, stat);
2102
2103 stat = GdipDeleteBrush(brush);
2104 expect(Ok, stat);
2105
2106 stat = GdipEndContainer(graphics, state1);
2107 expect(Ok, stat);
2108
2109 /* Restoring an invalid state seems to break the graphics object? */
2110 if (0) {
2111 stat = GdipEndContainer(graphics, state1);
2112 expect(Ok, stat);
2113 }
2114
2115 /* Ending metafile with a state open */
2116 stat = GdipBeginContainer2(graphics, &state1);
2117 expect(Ok, stat);
2118
2119 stat = GdipDeleteGraphics(graphics);
2120 expect(Ok, stat);
2121
2122 check_metafile(metafile, container_records, "container metafile", dst_points, &frame, UnitPixel);
2123
2124 sync_metafile(&metafile, "container.emf");
2125
2126 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
2127 expect(Ok, stat);
2128
2129 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2130 expect(Ok, stat);
2131
2132 play_metafile(metafile, graphics, container_records, "container playback", dst_points, &frame, UnitPixel);
2133
2134 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
2135 expect(Ok, stat);
2136 expect(0, color);
2137
2138 stat = GdipBitmapGetPixel(bitmap, 12, 12, &color);
2139 expect(Ok, stat);
2140 expect(0xff000000, color);
2141
2142 stat = GdipBitmapGetPixel(bitmap, 8, 8, &color);
2143 expect(Ok, stat);
2144 expect(0xff0000ff, color);
2145
2146 stat = GdipBitmapGetPixel(bitmap, 42, 42, &color);
2147 expect(Ok, stat);
2148 expect(0xff00ff00, color);
2149
2150 stat = GdipBitmapGetPixel(bitmap, 55, 5, &color);
2151 expect(Ok, stat);
2152 expect(0xff00ffff, color);
2153
2154 stat = GdipDeleteGraphics(graphics);
2155 expect(Ok, stat);
2156
2157 stat = GdipDisposeImage((GpImage*)bitmap);
2158 expect(Ok, stat);
2159
2160 stat = GdipDisposeImage((GpImage*)metafile);
2161 expect(Ok, stat);
2162 }
2163
2164 static const emfplus_record clipping_records[] = {
2165 { EMR_HEADER },
2166 { EmfPlusRecordTypeHeader },
2167 { EmfPlusRecordTypeSave },
2168 { EmfPlusRecordTypeSetClipRect },
2169 { EmfPlusRecordTypeFillRects, 0xc000 },
2170 { EmfPlusRecordTypeRestore },
2171 { EmfPlusRecordTypeSetClipRect, 0x300 },
2172 { EmfPlusRecordTypeFillRects, 0xc000 },
2173 { EmfPlusRecordTypeObject, ObjectTypeRegion << 8 },
2174 { EmfPlusRecordTypeSetClipRegion, 0x100 },
2175 { EmfPlusRecordTypeEndOfFile },
2176 { EMR_EOF },
2177 { 0 }
2178 };
2179
test_clipping(void)2180 static void test_clipping(void)
2181 {
2182 GpStatus stat;
2183 GpMetafile *metafile;
2184 GpGraphics *graphics;
2185 GpBitmap *bitmap;
2186 GpRegion *region;
2187 GpBrush *brush;
2188 GpRectF rect;
2189 ARGB color;
2190 HDC hdc;
2191 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2192 static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
2193 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2194 GraphicsState state;
2195
2196 hdc = CreateCompatibleDC(0);
2197
2198 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2199 expect(Ok, stat);
2200
2201 DeleteDC(hdc);
2202
2203 if (stat != Ok)
2204 return;
2205
2206 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2207 expect(Ok, stat);
2208
2209 stat = GdipSaveGraphics(graphics, &state);
2210 expect(Ok, stat);
2211
2212 stat = GdipGetVisibleClipBounds(graphics, &rect);
2213 expect(Ok, stat);
2214 ok(rect.X == -0x400000, "rect.X = %f\n", rect.X);
2215 ok(rect.Y == -0x400000, "rect.Y = %f\n", rect.Y);
2216 ok(rect.Width == 0x800000, "rect.Width = %f\n", rect.Width);
2217 ok(rect.Height == 0x800000, "rect.Height = %f\n", rect.Height);
2218
2219 stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeReplace);
2220 expect(Ok, stat);
2221
2222 stat = GdipGetVisibleClipBounds(graphics, &rect);
2223 expect(Ok, stat);
2224 ok(rect.X == 30, "rect.X = %f\n", rect.X);
2225 ok(rect.Y == 30, "rect.Y = %f\n", rect.Y);
2226 ok(rect.Width == 10, "rect.Width = %f\n", rect.Width);
2227 ok(rect.Height == 10, "rect.Height = %f\n", rect.Height);
2228
2229 stat = GdipCreateSolidFill((ARGB)0xff000000, (GpSolidFill**)&brush);
2230 expect(Ok, stat);
2231
2232 stat = GdipFillRectangle(graphics, brush, 0, 0, 100, 100);
2233 expect(Ok, stat);
2234
2235 stat = GdipDeleteBrush(brush);
2236 expect(Ok, stat);
2237
2238 stat = GdipRestoreGraphics(graphics, state);
2239 expect(Ok, stat);
2240
2241 stat = GdipSetClipRect(graphics, 30, 30, 10, 10, CombineModeXor);
2242 expect(Ok, stat);
2243
2244 stat = GdipCreateSolidFill((ARGB)0xff0000ff, (GpSolidFill**)&brush);
2245 expect(Ok, stat);
2246
2247 stat = GdipFillRectangle(graphics, brush, 30, 30, 20, 10);
2248 expect(Ok, stat);
2249
2250 stat = GdipDeleteBrush(brush);
2251 expect(Ok, stat);
2252
2253 stat = GdipCreateRegionRect(&rect, ®ion);
2254 expect(Ok, stat);
2255
2256 stat = GdipSetClipRegion(graphics, region, CombineModeIntersect);
2257 expect(Ok, stat);
2258
2259 stat = GdipDeleteRegion(region);
2260 expect(Ok, stat);
2261
2262 stat = GdipDeleteGraphics(graphics);
2263 expect(Ok, stat);
2264
2265 check_metafile(metafile, clipping_records, "clipping metafile", dst_points, &frame, UnitPixel);
2266
2267 sync_metafile(&metafile, "clipping.emf");
2268
2269 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
2270 expect(Ok, stat);
2271
2272 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2273 expect(Ok, stat);
2274
2275 play_metafile(metafile, graphics, clipping_records, "clipping playback", dst_points, &frame, UnitPixel);
2276
2277 stat = GdipBitmapGetPixel(bitmap, 80, 80, &color);
2278 expect(Ok, stat);
2279 expect(0, color);
2280
2281 stat = GdipBitmapGetPixel(bitmap, 35, 35, &color);
2282 expect(Ok, stat);
2283 expect(0xff000000, color);
2284
2285 stat = GdipBitmapGetPixel(bitmap, 45, 35, &color);
2286 expect(Ok, stat);
2287 expect(0xff0000ff, color);
2288
2289 stat = GdipDeleteGraphics(graphics);
2290 expect(Ok, stat);
2291
2292 stat = GdipDisposeImage((GpImage*)bitmap);
2293 expect(Ok, stat);
2294
2295 stat = GdipDisposeImage((GpImage*)metafile);
2296 expect(Ok, stat);
2297 }
2298
test_gditransform_cb(GpMetafile * metafile,EmfPlusRecordType record_type,unsigned int flags,unsigned int dataSize,const unsigned char * pStr)2299 static void test_gditransform_cb(GpMetafile* metafile, EmfPlusRecordType record_type,
2300 unsigned int flags, unsigned int dataSize, const unsigned char *pStr)
2301 {
2302 static const XFORM xform = {0.5, 0, 0, 0.5, 0, 0};
2303 static const RECTL rectangle = {0,0,100,100};
2304 GpStatus stat;
2305
2306 stat = GdipPlayMetafileRecord(metafile, EMR_SETWORLDTRANSFORM, 0, sizeof(xform), (void*)&xform);
2307 expect(Ok, stat);
2308
2309 stat = GdipPlayMetafileRecord(metafile, EMR_RECTANGLE, 0, sizeof(rectangle), (void*)&rectangle);
2310 expect(Ok, stat);
2311 }
2312
2313 static const emfplus_record gditransform_records[] = {
2314 { EMR_HEADER },
2315 { EMR_CREATEBRUSHINDIRECT },
2316 { EMR_SELECTOBJECT },
2317 { EMR_GDICOMMENT, 0, 0, 0, test_gditransform_cb },
2318 { EMR_SELECTOBJECT },
2319 { EMR_DELETEOBJECT },
2320 { EMR_EOF },
2321 { 0 }
2322 };
2323
test_gditransform(void)2324 static void test_gditransform(void)
2325 {
2326 GpStatus stat;
2327 GpMetafile *metafile;
2328 GpGraphics *graphics;
2329 HDC hdc, metafile_dc;
2330 HENHMETAFILE hemf;
2331 MetafileHeader header;
2332 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2333 static const GpPointF dst_points[3] = {{0.0,0.0},{40.0,0.0},{0.0,40.0}};
2334 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2335 HBRUSH hbrush, holdbrush;
2336 GpBitmap *bitmap;
2337 ARGB color;
2338
2339 hdc = CreateCompatibleDC(0);
2340
2341 stat = GdipRecordMetafile(hdc, EmfTypeEmfOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2342 expect(Ok, stat);
2343
2344 DeleteDC(hdc);
2345
2346 if (stat != Ok)
2347 return;
2348
2349 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2350 expect(InvalidParameter, stat);
2351
2352 memset(&header, 0xaa, sizeof(header));
2353 stat = GdipGetMetafileHeaderFromMetafile(metafile, &header);
2354 expect(Ok, stat);
2355 expect(MetafileTypeEmf, header.Type);
2356 ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
2357
2358 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2359 expect(Ok, stat);
2360
2361 stat = GdipGetDC(graphics, &metafile_dc);
2362 expect(Ok, stat);
2363
2364 if (stat != Ok)
2365 {
2366 GdipDeleteGraphics(graphics);
2367 GdipDisposeImage((GpImage*)metafile);
2368 return;
2369 }
2370
2371 hbrush = CreateSolidBrush(0xff);
2372
2373 holdbrush = SelectObject(metafile_dc, hbrush);
2374
2375 GdiComment(metafile_dc, 8, (const BYTE*)"winetest");
2376
2377 SelectObject(metafile_dc, holdbrush);
2378
2379 DeleteObject(hbrush);
2380
2381 stat = GdipReleaseDC(graphics, metafile_dc);
2382 expect(Ok, stat);
2383
2384 stat = GdipDeleteGraphics(graphics);
2385 expect(Ok, stat);
2386
2387 check_metafile(metafile, gditransform_records, "gditransform metafile", dst_points, &frame, UnitPixel);
2388
2389 sync_metafile(&metafile, "gditransform.emf");
2390
2391 stat = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap);
2392 expect(Ok, stat);
2393
2394 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
2395 expect(Ok, stat);
2396
2397 play_metafile(metafile, graphics, gditransform_records, "gditransform playback", dst_points, &frame, UnitPixel);
2398
2399 stat = GdipBitmapGetPixel(bitmap, 10, 10, &color);
2400 expect(Ok, stat);
2401 expect(0xffff0000, color);
2402
2403 stat = GdipBitmapGetPixel(bitmap, 30, 30, &color);
2404 expect(Ok, stat);
2405 expect(0x00000000, color);
2406
2407 stat = GdipDeleteGraphics(graphics);
2408 expect(Ok, stat);
2409
2410 stat = GdipDisposeImage((GpImage*)bitmap);
2411 expect(Ok, stat);
2412
2413 stat = GdipDisposeImage((GpImage*)metafile);
2414 expect(Ok, stat);
2415 }
2416
2417 static const emfplus_record draw_image_bitmap_records[] = {
2418 { EMR_HEADER },
2419 { EmfPlusRecordTypeHeader },
2420 { EmfPlusRecordTypeObject, ObjectTypeImage << 8 },
2421 { EmfPlusRecordTypeObject, (ObjectTypeImageAttributes << 8) | 1 },
2422 { EmfPlusRecordTypeDrawImagePoints, 0, 0, 0, NULL, 0x4000 },
2423 { EMR_SAVEDC, 0, 1 },
2424 { EMR_SETICMMODE, 0, 1 },
2425 { EMR_BITBLT, 0, 1 },
2426 { EMR_RESTOREDC, 0, 1 },
2427 { EmfPlusRecordTypeEndOfFile },
2428 { EMR_EOF },
2429 { 0 }
2430 };
2431
2432 static const emfplus_record draw_image_metafile_records[] = {
2433 { EMR_HEADER },
2434 { EmfPlusRecordTypeHeader },
2435 { EmfPlusRecordTypeObject, ObjectTypeImage << 8 },
2436 /* metafile object */
2437 { EMR_HEADER },
2438 { EmfPlusRecordTypeHeader },
2439 { EmfPlusRecordTypeObject, ObjectTypeImage << 8 },
2440 { EmfPlusRecordTypeObject, (ObjectTypeImageAttributes << 8) | 1 },
2441 { EmfPlusRecordTypeDrawImagePoints },
2442 { EMR_SAVEDC, 0, 1 },
2443 { EMR_SETICMMODE, 0, 1 },
2444 { EMR_BITBLT, 0, 1 },
2445 { EMR_RESTOREDC, 0, 1 },
2446 { EmfPlusRecordTypeEndOfFile },
2447 { EMR_EOF },
2448 /* end of metafile object */
2449 { EmfPlusRecordTypeDrawImagePoints },
2450 { EMR_SAVEDC, 0, 1 },
2451 { EMR_SETICMMODE, 0, 1 },
2452 { EMR_BITBLT, 0, 1 },
2453 { EMR_RESTOREDC, 0, 1 },
2454 { EmfPlusRecordTypeEndOfFile },
2455 { EMR_EOF },
2456 { 0 }
2457 };
2458
test_drawimage(void)2459 static void test_drawimage(void)
2460 {
2461 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2462 static const GpPointF dst_points[3] = {{10.0,10.0},{85.0,15.0},{10.0,80.0}};
2463 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2464 const ColorMatrix double_red = {{
2465 {2.0,0.0,0.0,0.0,0.0},
2466 {0.0,1.0,0.0,0.0,0.0},
2467 {0.0,0.0,1.0,0.0,0.0},
2468 {0.0,0.0,0.0,1.0,0.0},
2469 {0.0,0.0,0.0,0.0,1.0}}};
2470
2471 GpImageAttributes *imageattr;
2472 GpMetafile *metafile;
2473 GpGraphics *graphics;
2474 HENHMETAFILE hemf;
2475 GpStatus stat;
2476 BITMAPINFO info;
2477 BYTE buff[400];
2478 GpImage *image;
2479 HDC hdc;
2480
2481 hdc = CreateCompatibleDC(0);
2482 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2483 expect(Ok, stat);
2484
2485 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2486 expect(Ok, stat);
2487
2488 memset(&info, 0, sizeof(info));
2489 info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2490 info.bmiHeader.biWidth = 10;
2491 info.bmiHeader.biHeight = 10;
2492 info.bmiHeader.biPlanes = 1;
2493 info.bmiHeader.biBitCount = 32;
2494 info.bmiHeader.biCompression = BI_RGB;
2495 memset(buff, 0x80, sizeof(buff));
2496 stat = GdipCreateBitmapFromGdiDib(&info, buff, (GpBitmap**)&image);
2497 expect(Ok, stat);
2498
2499 stat = GdipCreateImageAttributes(&imageattr);
2500 expect(Ok, stat);
2501
2502 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2503 TRUE, &double_red, NULL, ColorMatrixFlagsDefault);
2504 expect(Ok, stat);
2505
2506 stat = GdipDrawImagePointsRect(graphics, image, dst_points, 3,
2507 0.0, 0.0, 10.0, 10.0, UnitPixel, imageattr, NULL, NULL);
2508 GdipDisposeImageAttributes(imageattr);
2509 expect(Ok, stat);
2510
2511 GdipDisposeImage(image);
2512
2513 stat = GdipDeleteGraphics(graphics);
2514 expect(Ok, stat);
2515 sync_metafile(&metafile, "draw_image_bitmap.emf");
2516
2517 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2518 expect(Ok, stat);
2519
2520 check_emfplus(hemf, draw_image_bitmap_records, "draw image bitmap");
2521
2522 /* test drawing metafile */
2523 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2524 expect(Ok, stat);
2525
2526 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2527 expect(Ok, stat);
2528
2529 stat = GdipCreateMetafileFromEmf(hemf, TRUE, (GpMetafile**)&image);
2530 expect(Ok, stat);
2531
2532 stat = GdipDrawImagePointsRect(graphics, image, dst_points, 3,
2533 0.0, 0.0, 100.0, 100.0, UnitPixel, NULL, NULL, NULL);
2534 expect(Ok, stat);
2535
2536 GdipDisposeImage(image);
2537
2538 stat = GdipDeleteGraphics(graphics);
2539 expect(Ok, stat);
2540 sync_metafile(&metafile, "draw_image_metafile.emf");
2541
2542 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2543 expect(Ok, stat);
2544
2545 if (GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipConvertToEmfPlus"))
2546 {
2547 check_emfplus(hemf, draw_image_metafile_records, "draw image metafile");
2548 }
2549 else
2550 {
2551 win_skip("draw image metafile records tests skipped\n");
2552 }
2553 DeleteEnhMetaFile(hemf);
2554
2555 DeleteDC(hdc);
2556 stat = GdipDisposeImage((GpImage*)metafile);
2557 expect(Ok, stat);
2558 }
2559
2560 static const emfplus_record properties_records[] = {
2561 { EMR_HEADER },
2562 { EmfPlusRecordTypeHeader },
2563 { EmfPlusRecordTypeSetTextRenderingHint, TextRenderingHintAntiAlias },
2564 { EmfPlusRecordTypeSetPixelOffsetMode, PixelOffsetModeHighQuality },
2565 { EmfPlusRecordTypeSetAntiAliasMode, (SmoothingModeAntiAlias << 1) | 1, 0, 0, NULL, 0x1 },
2566 { EmfPlusRecordTypeSetCompositingMode, CompositingModeSourceCopy },
2567 { EmfPlusRecordTypeSetCompositingQuality, CompositingQualityHighQuality },
2568 { EmfPlusRecordTypeSetInterpolationMode, InterpolationModeHighQualityBicubic },
2569 { EmfPlusRecordTypeEndOfFile },
2570 { EMR_EOF },
2571 { 0 }
2572 };
2573
test_properties(void)2574 static void test_properties(void)
2575 {
2576 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2577 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2578
2579 GpMetafile *metafile;
2580 GpGraphics *graphics;
2581 HENHMETAFILE hemf;
2582 GpStatus stat;
2583 HDC hdc;
2584
2585 hdc = CreateCompatibleDC(0);
2586 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2587 expect(Ok, stat);
2588 DeleteDC(hdc);
2589
2590 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2591 expect(Ok, stat);
2592
2593 stat = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
2594 expect(Ok, stat);
2595 stat = GdipSetTextRenderingHint(graphics, TextRenderingHintAntiAlias);
2596 expect(Ok, stat);
2597
2598 stat = GdipSetPixelOffsetMode(graphics, PixelOffsetModeHighQuality);
2599 expect(Ok, stat);
2600 stat = GdipSetPixelOffsetMode(graphics, PixelOffsetModeHighQuality);
2601 expect(Ok, stat);
2602
2603 stat = GdipSetSmoothingMode(graphics, SmoothingModeAntiAlias);
2604 expect(Ok, stat);
2605 stat = GdipSetSmoothingMode(graphics, SmoothingModeAntiAlias);
2606 expect(Ok, stat);
2607
2608 stat = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
2609 expect(Ok, stat);
2610 stat = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
2611 expect(Ok, stat);
2612
2613 stat = GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
2614 expect(Ok, stat);
2615 stat = GdipSetCompositingQuality(graphics, CompositingQualityHighQuality);
2616 expect(Ok, stat);
2617
2618 stat = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
2619 expect(Ok, stat);
2620 stat = GdipSetInterpolationMode(graphics, InterpolationModeHighQuality);
2621 expect(Ok, stat);
2622
2623 stat = GdipDeleteGraphics(graphics);
2624 expect(Ok, stat);
2625 sync_metafile(&metafile, "properties.emf");
2626
2627 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2628 expect(Ok, stat);
2629
2630 check_emfplus(hemf, properties_records, "properties");
2631 DeleteEnhMetaFile(hemf);
2632
2633 stat = GdipDisposeImage((GpImage*)metafile);
2634 expect(Ok, stat);
2635 }
2636
2637 static const emfplus_record draw_path_records[] = {
2638 { EMR_HEADER },
2639 { EmfPlusRecordTypeHeader },
2640 { EmfPlusRecordTypeObject, ObjectTypePen << 8 },
2641 { EmfPlusRecordTypeObject, (ObjectTypePath << 8) | 1 },
2642 { EmfPlusRecordTypeDrawPath, 1 },
2643 { EMR_SAVEDC, 0, 1 },
2644 { EMR_SETICMMODE, 0, 1 },
2645 { EMR_BITBLT, 0, 1 },
2646 { EMR_RESTOREDC, 0, 1 },
2647 { EmfPlusRecordTypeEndOfFile },
2648 { EMR_EOF },
2649 { 0 }
2650 };
2651
test_drawpath(void)2652 static void test_drawpath(void)
2653 {
2654 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2655 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2656
2657 GpMetafile *metafile;
2658 GpGraphics *graphics;
2659 HENHMETAFILE hemf;
2660 GpStatus stat;
2661 GpPath *path;
2662 GpPen *pen;
2663 HDC hdc;
2664
2665 hdc = CreateCompatibleDC(0);
2666 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2667 expect(Ok, stat);
2668 DeleteDC(hdc);
2669
2670 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2671 expect(Ok, stat);
2672
2673 stat = GdipCreatePath(FillModeAlternate, &path);
2674 expect(Ok, stat);
2675 stat = GdipAddPathLine(path, 5, 5, 30, 30);
2676 expect(Ok, stat);
2677
2678 stat = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
2679 expect(Ok, stat);
2680
2681 stat = GdipDrawPath(graphics, pen, path);
2682 expect(Ok, stat);
2683
2684 stat = GdipDeletePen(pen);
2685 expect(Ok, stat);
2686 stat = GdipDeletePath(path);
2687 expect(Ok, stat);
2688
2689 stat = GdipDeleteGraphics(graphics);
2690 expect(Ok, stat);
2691 sync_metafile(&metafile, "draw_path.emf");
2692
2693 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2694 expect(Ok, stat);
2695
2696 check_emfplus(hemf, draw_path_records, "draw path");
2697 DeleteEnhMetaFile(hemf);
2698
2699 stat = GdipDisposeImage((GpImage*)metafile);
2700 expect(Ok, stat);
2701 }
2702
2703 static const emfplus_record fill_path_records[] = {
2704 { EMR_HEADER },
2705 { EmfPlusRecordTypeHeader },
2706 { EmfPlusRecordTypeObject, ObjectTypePath << 8 },
2707 { EmfPlusRecordTypeFillPath, 0x8000 },
2708 { EMR_SAVEDC, 0, 1 },
2709 { EMR_SETICMMODE, 0, 1 },
2710 { EMR_BITBLT, 0, 1 },
2711 { EMR_RESTOREDC, 0, 1 },
2712 { EmfPlusRecordTypeEndOfFile },
2713 { EMR_EOF },
2714 { 0 }
2715 };
2716
test_fillpath(void)2717 static void test_fillpath(void)
2718 {
2719 static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
2720 static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
2721 static const WCHAR winetestemfW[] = {'w','i','n','e','t','e','s','t','.','e','m','f',0};
2722
2723 GpMetafile *metafile;
2724 GpGraphics *graphics;
2725 GpSolidFill *brush;
2726 HENHMETAFILE hemf;
2727 GpStatus stat;
2728 GpPath *path;
2729 HDC hdc;
2730
2731 hdc = CreateCompatibleDC(0);
2732 stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
2733 expect(Ok, stat);
2734 DeleteDC(hdc);
2735
2736 stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
2737 expect(Ok, stat);
2738
2739 stat = GdipCreatePath(FillModeAlternate, &path);
2740 expect(Ok, stat);
2741 stat = GdipAddPathLine(path, 5, 5, 30, 30);
2742 expect(Ok, stat);
2743 stat = GdipAddPathLine(path, 30, 30, 5, 30);
2744 expect(Ok, stat);
2745
2746 stat = GdipCreateSolidFill(0xffaabbcc, &brush);
2747 expect(Ok, stat);
2748
2749 stat = GdipFillPath(graphics, (GpBrush*)brush, path);
2750 expect(Ok, stat);
2751
2752 stat = GdipDeleteBrush((GpBrush*)brush);
2753 expect(Ok, stat);
2754 stat = GdipDeletePath(path);
2755 expect(Ok, stat);
2756
2757 stat = GdipDeleteGraphics(graphics);
2758 expect(Ok, stat);
2759 sync_metafile(&metafile, "fill_path.emf");
2760
2761 stat = GdipGetHemfFromMetafile(metafile, &hemf);
2762 expect(Ok, stat);
2763
2764 check_emfplus(hemf, fill_path_records, "fill path");
2765
2766 /* write to disk */
2767 DeleteEnhMetaFile(CopyEnhMetaFileW(hemf, winetestemfW));
2768
2769 DeleteEnhMetaFile(hemf);
2770
2771 stat = GdipDisposeImage((GpImage*)metafile);
2772 expect(Ok, stat);
2773
2774 /* should succeed when given path to an EMF */
2775 stat = GdipCreateMetafileFromWmfFile(winetestemfW, NULL, &metafile);
2776 expect(Ok, stat);
2777
2778 stat = GdipDisposeImage((GpImage*)metafile);
2779 expect(Ok, stat);
2780
2781 DeleteFileW(winetestemfW);
2782
2783 stat = GdipCreateMetafileFromWmfFile(winetestemfW, NULL, &metafile);
2784 expect(GenericError, stat);
2785 }
2786
START_TEST(metafile)2787 START_TEST(metafile)
2788 {
2789 struct GdiplusStartupInput gdiplusStartupInput;
2790 ULONG_PTR gdiplusToken;
2791 int myARGC;
2792 char **myARGV;
2793 HMODULE hmsvcrt;
2794 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
2795
2796 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
2797 hmsvcrt = LoadLibraryA("msvcrt");
2798 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
2799 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
2800
2801 gdiplusStartupInput.GdiplusVersion = 1;
2802 gdiplusStartupInput.DebugEventCallback = NULL;
2803 gdiplusStartupInput.SuppressBackgroundThread = 0;
2804 gdiplusStartupInput.SuppressExternalCodecs = 0;
2805
2806 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
2807
2808 myARGC = winetest_get_mainargs( &myARGV );
2809
2810 if (myARGC >= 3)
2811 {
2812 if (!strcmp(myARGV[2], "save"))
2813 save_metafiles = TRUE;
2814 else if (!strcmp(myARGV[2], "load"))
2815 load_metafiles = TRUE;
2816 }
2817
2818 test_empty();
2819 test_getdc();
2820 test_emfonly();
2821 test_fillrect();
2822 test_clear();
2823 test_nullframerect();
2824 test_pagetransform();
2825 test_worldtransform();
2826 test_converttoemfplus();
2827 test_frameunit();
2828 test_containers();
2829 test_clipping();
2830 test_gditransform();
2831 test_drawimage();
2832 test_properties();
2833 test_drawpath();
2834 test_fillpath();
2835
2836 GdiplusShutdown(gdiplusToken);
2837 }
2838