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