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