2 * Unit test suite for metafiles
4 * Copyright (C) 2011 Vincent Povirk for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
27 #include <wine/test.h>
32 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
33 #define expectf_(expected, got, precision) ok(fabs((expected) - (got)) <= (precision), "Expected %f, got %f\n", (expected), (got))
34 #define expectf(expected, got) expectf_((expected), (got), 0.001)
36 static BOOL save_metafiles
;
38 typedef struct emfplus_record
45 typedef struct emfplus_check_state
49 const struct emfplus_record
*expected
;
51 } emfplus_check_state
;
53 static void check_record(int count
, const char *desc
, const struct emfplus_record
*expected
, const struct emfplus_record
*actual
)
56 todo_wine
ok(expected
->record_type
== actual
->record_type
,
57 "%s.%i: Expected record type 0x%x, got 0x%x\n", desc
, count
,
58 expected
->record_type
, actual
->record_type
);
60 ok(expected
->record_type
== actual
->record_type
,
61 "%s.%i: Expected record type 0x%x, got 0x%x\n", desc
, count
,
62 expected
->record_type
, actual
->record_type
);
65 typedef struct EmfPlusRecordHeader
71 } EmfPlusRecordHeader
;
73 static int CALLBACK
enum_emf_proc(HDC hDC
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
,
74 int nObj
, LPARAM lpData
)
76 emfplus_check_state
*state
= (emfplus_check_state
*)lpData
;
77 emfplus_record actual
;
79 if (lpEMFR
->iType
== EMR_GDICOMMENT
)
81 const EMRGDICOMMENT
*comment
= (const EMRGDICOMMENT
*)lpEMFR
;
83 if (comment
->cbData
>= 4 && memcmp(comment
->Data
, "EMF+", 4) == 0)
87 while (offset
+ sizeof(EmfPlusRecordHeader
) <= comment
->cbData
)
89 const EmfPlusRecordHeader
*record
= (const EmfPlusRecordHeader
*)&comment
->Data
[offset
];
91 ok(record
->Size
== record
->DataSize
+ sizeof(EmfPlusRecordHeader
),
92 "%s: EMF+ record datasize %u and size %u mismatch\n", state
->desc
, record
->DataSize
, record
->Size
);
94 ok(offset
+ record
->DataSize
<= comment
->cbData
,
95 "%s: EMF+ record truncated\n", state
->desc
);
97 if (offset
+ record
->DataSize
> comment
->cbData
)
100 if (state
->expected
[state
->count
].record_type
)
103 actual
.record_type
= record
->Type
;
105 check_record(state
->count
, state
->desc
, &state
->expected
[state
->count
], &actual
);
111 ok(0, "%s: Unexpected EMF+ 0x%x record\n", state
->desc
, record
->Type
);
114 offset
+= record
->Size
;
117 ok(offset
== comment
->cbData
, "%s: truncated EMF+ record data?\n", state
->desc
);
123 if (state
->expected
[state
->count
].record_type
)
126 actual
.record_type
= lpEMFR
->iType
;
128 check_record(state
->count
, state
->desc
, &state
->expected
[state
->count
], &actual
);
134 ok(0, "%s: Unexpected EMF 0x%x record\n", state
->desc
, lpEMFR
->iType
);
140 static void check_emfplus(HENHMETAFILE hemf
, const emfplus_record
*expected
, const char *desc
)
142 emfplus_check_state state
;
146 state
.expected
= expected
;
148 EnumEnhMetaFile(0, hemf
, enum_emf_proc
, &state
, NULL
);
150 if (expected
[state
.count
].todo
)
151 todo_wine
ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
153 ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
156 static BOOL CALLBACK
enum_metafile_proc(EmfPlusRecordType record_type
, unsigned int flags
,
157 unsigned int dataSize
, const unsigned char *pStr
, void *userdata
)
159 emfplus_check_state
*state
= (emfplus_check_state
*)userdata
;
160 emfplus_record actual
;
163 actual
.record_type
= record_type
;
166 ok(pStr
== NULL
, "non-NULL pStr\n");
168 if (state
->expected
[state
->count
].record_type
)
170 check_record(state
->count
, state
->desc
, &state
->expected
[state
->count
], &actual
);
176 ok(0, "%s: Unexpected EMF 0x%x record\n", state
->desc
, record_type
);
182 static void check_metafile(GpMetafile
*metafile
, const emfplus_record
*expected
, const char *desc
,
183 const GpPointF
*dst_points
, const GpRectF
*src_rect
, Unit src_unit
)
187 GpGraphics
*graphics
;
188 emfplus_check_state state
;
192 state
.expected
= expected
;
193 state
.metafile
= metafile
;
195 hdc
= CreateCompatibleDC(0);
197 stat
= GdipCreateFromHDC(hdc
, &graphics
);
200 stat
= GdipEnumerateMetafileSrcRectDestPoints(graphics
, metafile
, dst_points
,
201 3, src_rect
, src_unit
, enum_metafile_proc
, &state
, NULL
);
204 if (expected
[state
.count
].todo
)
205 todo_wine
ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
207 ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
209 GdipDeleteGraphics(graphics
);
214 static BOOL CALLBACK
play_metafile_proc(EmfPlusRecordType record_type
, unsigned int flags
,
215 unsigned int dataSize
, const unsigned char *pStr
, void *userdata
)
217 emfplus_check_state
*state
= (emfplus_check_state
*)userdata
;
220 stat
= GdipPlayMetafileRecord(state
->metafile
, record_type
, flags
, dataSize
, pStr
);
222 if (state
->expected
[state
->count
].record_type
)
224 if (state
->expected
[state
->count
].playback_todo
)
225 todo_wine
ok(stat
== Ok
, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state
->desc
, state
->count
, stat
);
227 ok(stat
== Ok
, "%s.%i: GdipPlayMetafileRecord failed with stat %i\n", state
->desc
, state
->count
, stat
);
232 if (state
->expected
[state
->count
].playback_todo
)
233 todo_wine
ok(0, "%s: too many records\n", state
->desc
);
235 ok(0, "%s: too many records\n", state
->desc
);
243 static void play_metafile(GpMetafile
*metafile
, GpGraphics
*graphics
, const emfplus_record
*expected
,
244 const char *desc
, const GpPointF
*dst_points
, const GpRectF
*src_rect
, Unit src_unit
)
247 emfplus_check_state state
;
251 state
.expected
= expected
;
252 state
.metafile
= metafile
;
254 stat
= GdipEnumerateMetafileSrcRectDestPoints(graphics
, metafile
, dst_points
,
255 3, src_rect
, src_unit
, play_metafile_proc
, &state
, NULL
);
259 static void save_metafile(GpMetafile
*metafile
, const char *filename
)
267 stat
= GdipCloneImage((GpImage
*)metafile
, (GpImage
**)&clone
);
270 stat
= GdipGetHemfFromMetafile(clone
, &hemf
);
273 DeleteEnhMetaFile(CopyEnhMetaFileA(hemf
, filename
));
275 DeleteEnhMetaFile(hemf
);
277 stat
= GdipDisposeImage((GpImage
*)clone
);
282 static const emfplus_record empty_records
[] = {
284 {0, EmfPlusRecordTypeHeader
},
285 {0, EmfPlusRecordTypeEndOfFile
},
290 static void test_empty(void)
293 GpMetafile
*metafile
;
294 GpGraphics
*graphics
;
299 HENHMETAFILE hemf
, dummy
;
300 MetafileHeader header
;
301 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
302 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
303 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
305 hdc
= CreateCompatibleDC(0);
307 stat
= GdipRecordMetafile(NULL
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
308 expect(InvalidParameter
, stat
);
310 stat
= GdipRecordMetafile(hdc
, MetafileTypeInvalid
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
311 expect(InvalidParameter
, stat
);
313 stat
= GdipRecordMetafile(hdc
, MetafileTypeWmf
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
314 expect(InvalidParameter
, stat
);
316 stat
= GdipRecordMetafile(hdc
, MetafileTypeWmfPlaceable
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
317 expect(InvalidParameter
, stat
);
319 stat
= GdipRecordMetafile(hdc
, MetafileTypeEmfPlusDual
+1, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
320 expect(InvalidParameter
, stat
);
322 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, NULL
);
323 expect(InvalidParameter
, stat
);
325 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
333 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
334 expect(InvalidParameter
, stat
);
336 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
339 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
340 expect(InvalidParameter
, stat
);
342 stat
= GdipDeleteGraphics(graphics
);
345 check_metafile(metafile
, empty_records
, "empty metafile", dst_points
, &frame
, UnitPixel
);
347 save_metafile(metafile
, "empty.emf");
349 stat
= GdipGetImageBounds((GpImage
*)metafile
, &bounds
, &unit
);
351 expectf(0.0, bounds
.X
);
352 expectf(0.0, bounds
.Y
);
353 expectf_(100.0, bounds
.Width
, 0.05);
354 expectf_(100.0, bounds
.Height
, 0.05);
355 expect(UnitPixel
, unit
);
357 stat
= GdipGetImageHorizontalResolution((GpImage
*)metafile
, &xres
);
360 stat
= GdipGetImageVerticalResolution((GpImage
*)metafile
, &yres
);
363 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
366 stat
= GdipGetHemfFromMetafile(metafile
, &dummy
);
367 expect(InvalidParameter
, stat
);
369 stat
= GdipDisposeImage((GpImage
*)metafile
);
372 check_emfplus(hemf
, empty_records
, "empty emf");
374 memset(&header
, 0xaa, sizeof(header
));
375 stat
= GdipGetMetafileHeaderFromEmf(hemf
, &header
);
377 expect(MetafileTypeEmfPlusOnly
, header
.Type
);
378 expect(U(header
).EmfHeader
.nBytes
, header
.Size
);
379 ok(header
.Version
== 0xdbc01001 || header
.Version
== 0xdbc01002, "Unexpected version %x\n", header
.Version
);
380 expect(1, header
.EmfPlusFlags
); /* reference device was display, not printer */
381 expectf(xres
, header
.DpiX
);
382 expectf(xres
, U(header
).EmfHeader
.szlDevice
.cx
/ (REAL
)U(header
).EmfHeader
.szlMillimeters
.cx
* 25.4);
383 expectf(yres
, header
.DpiY
);
384 expectf(yres
, U(header
).EmfHeader
.szlDevice
.cy
/ (REAL
)U(header
).EmfHeader
.szlMillimeters
.cy
* 25.4);
387 expect(100, header
.Width
);
388 expect(100, header
.Height
);
389 expect(28, header
.EmfPlusHeaderSize
);
390 expect(96, header
.LogicalDpiX
);
391 expect(96, header
.LogicalDpiX
);
392 expect(EMR_HEADER
, U(header
).EmfHeader
.iType
);
393 expect(0, U(header
).EmfHeader
.rclBounds
.left
);
394 expect(0, U(header
).EmfHeader
.rclBounds
.top
);
395 expect(-1, U(header
).EmfHeader
.rclBounds
.right
);
396 expect(-1, U(header
).EmfHeader
.rclBounds
.bottom
);
397 expect(0, U(header
).EmfHeader
.rclFrame
.left
);
398 expect(0, U(header
).EmfHeader
.rclFrame
.top
);
399 expectf_(100.0, U(header
).EmfHeader
.rclFrame
.right
* xres
/ 2540.0, 2.0);
400 expectf_(100.0, U(header
).EmfHeader
.rclFrame
.bottom
* yres
/ 2540.0, 2.0);
402 stat
= GdipCreateMetafileFromEmf(hemf
, TRUE
, &metafile
);
405 stat
= GdipGetImageBounds((GpImage
*)metafile
, &bounds
, &unit
);
407 expectf(0.0, bounds
.X
);
408 expectf(0.0, bounds
.Y
);
409 expectf_(100.0, bounds
.Width
, 0.05);
410 expectf_(100.0, bounds
.Height
, 0.05);
411 expect(UnitPixel
, unit
);
413 stat
= GdipGetImageHorizontalResolution((GpImage
*)metafile
, &xres
);
415 expectf(header
.DpiX
, xres
);
417 stat
= GdipGetImageVerticalResolution((GpImage
*)metafile
, &yres
);
419 expectf(header
.DpiY
, yres
);
421 stat
= GdipDisposeImage((GpImage
*)metafile
);
425 static const emfplus_record getdc_records
[] = {
427 {0, EmfPlusRecordTypeHeader
},
428 {0, EmfPlusRecordTypeGetDC
},
429 {0, EMR_CREATEBRUSHINDIRECT
},
430 {0, EMR_SELECTOBJECT
},
432 {0, EMR_SELECTOBJECT
},
433 {0, EMR_DELETEOBJECT
},
434 {0, EmfPlusRecordTypeEndOfFile
},
439 static void test_getdc(void)
442 GpMetafile
*metafile
;
443 GpGraphics
*graphics
;
444 HDC hdc
, metafile_dc
;
447 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
448 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
449 static const GpPointF dst_points_half
[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
450 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
451 HBRUSH hbrush
, holdbrush
;
455 hdc
= CreateCompatibleDC(0);
457 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
465 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
466 expect(InvalidParameter
, stat
);
468 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
471 stat
= GdipGetDC(graphics
, &metafile_dc
);
476 GdipDeleteGraphics(graphics
);
477 GdipDisposeImage((GpImage
*)metafile
);
481 hbrush
= CreateSolidBrush(0xff0000);
483 holdbrush
= SelectObject(metafile_dc
, hbrush
);
485 Rectangle(metafile_dc
, 25, 25, 75, 75);
487 SelectObject(metafile_dc
, holdbrush
);
489 DeleteObject(hbrush
);
491 stat
= GdipReleaseDC(graphics
, metafile_dc
);
494 stat
= GdipDeleteGraphics(graphics
);
497 check_metafile(metafile
, getdc_records
, "getdc metafile", dst_points
, &frame
, UnitPixel
);
499 save_metafile(metafile
, "getdc.emf");
501 stat
= GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB
, NULL
, &bitmap
);
504 stat
= GdipGetImageGraphicsContext((GpImage
*)bitmap
, &graphics
);
507 play_metafile(metafile
, graphics
, getdc_records
, "getdc playback", dst_points
, &frame
, UnitPixel
);
509 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
513 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
515 expect(0xff0000ff, color
);
517 stat
= GdipBitmapSetPixel(bitmap
, 50, 50, 0);
520 play_metafile(metafile
, graphics
, getdc_records
, "getdc playback", dst_points_half
, &frame
, UnitPixel
);
522 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
524 expect(0xff0000ff, color
);
526 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
530 stat
= GdipBitmapSetPixel(bitmap
, 15, 15, 0);
533 stat
= GdipDrawImagePointsRect(graphics
, (GpImage
*)metafile
, dst_points
, 3,
534 0.0, 0.0, 100.0, 100.0, UnitPixel
, NULL
, NULL
, NULL
);
537 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
541 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
543 expect(0xff0000ff, color
);
545 stat
= GdipDeleteGraphics(graphics
);
548 stat
= GdipDisposeImage((GpImage
*)bitmap
);
551 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
554 stat
= GdipDisposeImage((GpImage
*)metafile
);
557 check_emfplus(hemf
, getdc_records
, "getdc emf");
559 ret
= DeleteEnhMetaFile(hemf
);
560 ok(ret
!= 0, "Failed to delete enhmetafile %p\n", hemf
);
563 static const emfplus_record emfonly_records
[] = {
565 {0, EMR_CREATEBRUSHINDIRECT
},
566 {0, EMR_SELECTOBJECT
},
568 {0, EMR_SELECTOBJECT
},
569 {0, EMR_DELETEOBJECT
},
574 static void test_emfonly(void)
577 GpMetafile
*metafile
;
579 GpGraphics
*graphics
;
580 HDC hdc
, metafile_dc
;
585 MetafileHeader header
;
586 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
587 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
588 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
589 HBRUSH hbrush
, holdbrush
;
593 hdc
= CreateCompatibleDC(0);
595 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
603 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
604 expect(InvalidParameter
, stat
);
606 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
609 stat
= GdipGetDC(graphics
, &metafile_dc
);
614 GdipDeleteGraphics(graphics
);
615 GdipDisposeImage((GpImage
*)metafile
);
619 hbrush
= CreateSolidBrush(0xff0000);
621 holdbrush
= SelectObject(metafile_dc
, hbrush
);
623 Rectangle(metafile_dc
, 25, 25, 75, 75);
625 SelectObject(metafile_dc
, holdbrush
);
627 DeleteObject(hbrush
);
629 stat
= GdipReleaseDC(graphics
, metafile_dc
);
632 stat
= GdipDeleteGraphics(graphics
);
635 check_metafile(metafile
, emfonly_records
, "emfonly metafile", dst_points
, &frame
, UnitPixel
);
637 save_metafile(metafile
, "emfonly.emf");
639 stat
= GdipGetImageBounds((GpImage
*)metafile
, &bounds
, &unit
);
641 expectf(0.0, bounds
.X
);
642 expectf(0.0, bounds
.Y
);
643 expectf_(100.0, bounds
.Width
, 0.05);
644 expectf_(100.0, bounds
.Height
, 0.05);
645 expect(UnitPixel
, unit
);
647 stat
= GdipGetImageHorizontalResolution((GpImage
*)metafile
, &xres
);
650 stat
= GdipGetImageVerticalResolution((GpImage
*)metafile
, &yres
);
653 stat
= GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB
, NULL
, &bitmap
);
656 stat
= GdipGetImageGraphicsContext((GpImage
*)bitmap
, &graphics
);
659 play_metafile(metafile
, graphics
, emfonly_records
, "emfonly playback", dst_points
, &frame
, UnitPixel
);
661 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
665 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
667 expect(0xff0000ff, color
);
669 stat
= GdipBitmapSetPixel(bitmap
, 50, 50, 0);
672 stat
= GdipDrawImagePointsRect(graphics
, (GpImage
*)metafile
, dst_points
, 3,
673 0.0, 0.0, 100.0, 100.0, UnitPixel
, NULL
, NULL
, NULL
);
676 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
680 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
682 expect(0xff0000ff, color
);
684 stat
= GdipCloneImage((GpImage
*)metafile
, &clone
);
689 stat
= GdipBitmapSetPixel(bitmap
, 50, 50, 0);
692 stat
= GdipDrawImagePointsRect(graphics
, clone
, dst_points
, 3,
693 0.0, 0.0, 100.0, 100.0, UnitPixel
, NULL
, NULL
, NULL
);
696 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
700 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
702 expect(0xff0000ff, color
);
704 GdipDisposeImage(clone
);
707 stat
= GdipDeleteGraphics(graphics
);
710 stat
= GdipDisposeImage((GpImage
*)bitmap
);
713 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
716 stat
= GdipDisposeImage((GpImage
*)metafile
);
719 check_emfplus(hemf
, emfonly_records
, "emfonly emf");
721 memset(&header
, 0xaa, sizeof(header
));
722 stat
= GdipGetMetafileHeaderFromEmf(hemf
, &header
);
724 expect(MetafileTypeEmf
, header
.Type
);
725 expect(U(header
).EmfHeader
.nBytes
, header
.Size
);
726 expect(0x10000, header
.Version
);
727 expect(0, header
.EmfPlusFlags
);
728 expectf(xres
, header
.DpiX
);
729 expectf(xres
, U(header
).EmfHeader
.szlDevice
.cx
/ (REAL
)U(header
).EmfHeader
.szlMillimeters
.cx
* 25.4);
730 expectf(yres
, header
.DpiY
);
731 expectf(yres
, U(header
).EmfHeader
.szlDevice
.cy
/ (REAL
)U(header
).EmfHeader
.szlMillimeters
.cy
* 25.4);
734 expect(100, header
.Width
);
735 expect(100, header
.Height
);
736 expect(0, header
.EmfPlusHeaderSize
);
737 expect(0, header
.LogicalDpiX
);
738 expect(0, header
.LogicalDpiX
);
739 expect(EMR_HEADER
, U(header
).EmfHeader
.iType
);
740 expect(25, U(header
).EmfHeader
.rclBounds
.left
);
741 expect(25, U(header
).EmfHeader
.rclBounds
.top
);
742 expect(74, U(header
).EmfHeader
.rclBounds
.right
);
743 expect(74, U(header
).EmfHeader
.rclBounds
.bottom
);
744 expect(0, U(header
).EmfHeader
.rclFrame
.left
);
745 expect(0, U(header
).EmfHeader
.rclFrame
.top
);
746 expectf_(100.0, U(header
).EmfHeader
.rclFrame
.right
* xres
/ 2540.0, 2.0);
747 expectf_(100.0, U(header
).EmfHeader
.rclFrame
.bottom
* yres
/ 2540.0, 2.0);
749 stat
= GdipCreateMetafileFromEmf(hemf
, TRUE
, &metafile
);
752 stat
= GdipGetImageBounds((GpImage
*)metafile
, &bounds
, &unit
);
754 expectf(0.0, bounds
.X
);
755 expectf(0.0, bounds
.Y
);
756 expectf_(100.0, bounds
.Width
, 0.05);
757 expectf_(100.0, bounds
.Height
, 0.05);
758 expect(UnitPixel
, unit
);
760 stat
= GdipGetImageHorizontalResolution((GpImage
*)metafile
, &xres
);
762 expectf(header
.DpiX
, xres
);
764 stat
= GdipGetImageVerticalResolution((GpImage
*)metafile
, &yres
);
766 expectf(header
.DpiY
, yres
);
768 stat
= GdipDisposeImage((GpImage
*)metafile
);
772 static const emfplus_record fillrect_records
[] = {
774 {0, EmfPlusRecordTypeHeader
},
775 {0, EmfPlusRecordTypeFillRects
},
776 {0, EmfPlusRecordTypeEndOfFile
},
781 static void test_fillrect(void)
784 GpMetafile
*metafile
;
785 GpGraphics
*graphics
;
788 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
789 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
790 static const GpPointF dst_points_half
[3] = {{0.0,0.0},{50.0,0.0},{0.0,50.0}};
791 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
796 hdc
= CreateCompatibleDC(0);
798 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
806 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
807 expect(InvalidParameter
, stat
);
809 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
812 stat
= GdipCreateSolidFill((ARGB
)0xff0000ff, (GpSolidFill
**)&brush
);
815 stat
= GdipFillRectangleI(graphics
, brush
, 25, 25, 75, 75);
818 stat
= GdipDeleteBrush(brush
);
821 stat
= GdipDeleteGraphics(graphics
);
824 check_metafile(metafile
, fillrect_records
, "fillrect metafile", dst_points
, &frame
, UnitPixel
);
826 save_metafile(metafile
, "fillrect.emf");
828 stat
= GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB
, NULL
, &bitmap
);
831 stat
= GdipGetImageGraphicsContext((GpImage
*)bitmap
, &graphics
);
834 play_metafile(metafile
, graphics
, fillrect_records
, "fillrect playback", dst_points
, &frame
, UnitPixel
);
836 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
840 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
842 expect(0xff0000ff, color
);
844 stat
= GdipBitmapSetPixel(bitmap
, 50, 50, 0);
847 play_metafile(metafile
, graphics
, fillrect_records
, "fillrect playback", dst_points_half
, &frame
, UnitPixel
);
849 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
851 expect(0xff0000ff, color
);
853 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
857 stat
= GdipBitmapSetPixel(bitmap
, 15, 15, 0);
860 stat
= GdipDrawImagePointsRect(graphics
, (GpImage
*)metafile
, dst_points
, 3,
861 0.0, 0.0, 100.0, 100.0, UnitPixel
, NULL
, NULL
, NULL
);
864 stat
= GdipBitmapGetPixel(bitmap
, 15, 15, &color
);
868 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
870 expect(0xff0000ff, color
);
872 stat
= GdipDeleteGraphics(graphics
);
875 stat
= GdipDisposeImage((GpImage
*)bitmap
);
878 stat
= GdipDisposeImage((GpImage
*)metafile
);
882 static const emfplus_record pagetransform_records
[] = {
884 {0, EmfPlusRecordTypeHeader
},
885 {0, EmfPlusRecordTypeFillRects
},
886 {0, EmfPlusRecordTypeSetPageTransform
},
887 {0, EmfPlusRecordTypeFillRects
},
888 {0, EmfPlusRecordTypeSetPageTransform
},
889 {0, EmfPlusRecordTypeFillRects
},
890 {0, EmfPlusRecordTypeSetPageTransform
},
891 {0, EmfPlusRecordTypeFillRects
},
892 {0, EmfPlusRecordTypeSetPageTransform
},
893 {0, EmfPlusRecordTypeFillRects
},
894 {0, EmfPlusRecordTypeEndOfFile
},
899 static void test_pagetransform(void)
902 GpMetafile
*metafile
;
903 GpGraphics
*graphics
;
905 static const GpRectF frame
= {0.0, 0.0, 5.0, 5.0};
906 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
907 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
912 REAL scale
, dpix
, dpiy
;
915 hdc
= CreateCompatibleDC(0);
917 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitInch
, description
, &metafile
);
925 stat
= GdipGetImageHorizontalResolution((GpImage
*)metafile
, &dpix
);
926 todo_wine
expect(InvalidParameter
, stat
);
928 stat
= GdipGetImageVerticalResolution((GpImage
*)metafile
, &dpiy
);
929 todo_wine
expect(InvalidParameter
, stat
);
931 stat
= GdipGetImageWidth((GpImage
*)metafile
, &width
);
932 todo_wine
expect(InvalidParameter
, stat
);
934 stat
= GdipGetImageHeight((GpImage
*)metafile
, &height
);
935 todo_wine
expect(InvalidParameter
, stat
);
937 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
941 stat
= GdipGetPageUnit(graphics
, &unit
);
943 expect(UnitDisplay
, unit
);
945 stat
= GdipGetPageScale(graphics
, &scale
);
949 stat
= GdipGetDpiX(graphics
, &dpix
);
953 stat
= GdipGetDpiY(graphics
, &dpiy
);
957 stat
= GdipCreateSolidFill((ARGB
)0xff0000ff, (GpSolidFill
**)&brush
);
960 stat
= GdipFillRectangleI(graphics
, brush
, 1, 2, 1, 1);
963 stat
= GdipDeleteBrush(brush
);
966 /* page unit = pixels */
967 stat
= GdipSetPageUnit(graphics
, UnitPixel
);
970 stat
= GdipGetPageUnit(graphics
, &unit
);
972 expect(UnitPixel
, unit
);
974 stat
= GdipCreateSolidFill((ARGB
)0xff00ff00, (GpSolidFill
**)&brush
);
977 stat
= GdipFillRectangleI(graphics
, brush
, 0, 1, 1, 1);
980 stat
= GdipDeleteBrush(brush
);
983 /* page scale = 3, unit = pixels */
984 stat
= GdipSetPageScale(graphics
, 3.0);
987 stat
= GdipGetPageScale(graphics
, &scale
);
991 stat
= GdipCreateSolidFill((ARGB
)0xff00ffff, (GpSolidFill
**)&brush
);
994 stat
= GdipFillRectangleI(graphics
, brush
, 0, 1, 2, 2);
997 stat
= GdipDeleteBrush(brush
);
1000 /* page scale = 3, unit = inches */
1001 stat
= GdipSetPageUnit(graphics
, UnitInch
);
1004 stat
= GdipGetPageUnit(graphics
, &unit
);
1006 expect(UnitInch
, unit
);
1008 stat
= GdipCreateSolidFill((ARGB
)0xffff0000, (GpSolidFill
**)&brush
);
1011 stat
= GdipFillRectangle(graphics
, brush
, 1.0/96.0, 0, 1, 1);
1014 stat
= GdipDeleteBrush(brush
);
1017 /* page scale = 3, unit = display */
1018 stat
= GdipSetPageUnit(graphics
, UnitDisplay
);
1021 stat
= GdipGetPageUnit(graphics
, &unit
);
1023 expect(UnitDisplay
, unit
);
1025 stat
= GdipCreateSolidFill((ARGB
)0xffff00ff, (GpSolidFill
**)&brush
);
1028 stat
= GdipFillRectangle(graphics
, brush
, 3, 3, 2, 2);
1031 stat
= GdipDeleteBrush(brush
);
1034 stat
= GdipDeleteGraphics(graphics
);
1037 check_metafile(metafile
, pagetransform_records
, "pagetransform metafile", dst_points
, &frame
, UnitPixel
);
1039 save_metafile(metafile
, "pagetransform.emf");
1041 stat
= GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB
, NULL
, &bitmap
);
1044 stat
= GdipGetImageGraphicsContext((GpImage
*)bitmap
, &graphics
);
1047 play_metafile(metafile
, graphics
, pagetransform_records
, "pagetransform playback", dst_points
, &frame
, UnitPixel
);
1049 stat
= GdipBitmapGetPixel(bitmap
, 50, 50, &color
);
1053 stat
= GdipBitmapGetPixel(bitmap
, 30, 50, &color
);
1055 expect(0xff0000ff, color
);
1057 stat
= GdipBitmapGetPixel(bitmap
, 10, 30, &color
);
1059 expect(0xff00ff00, color
);
1061 stat
= GdipBitmapGetPixel(bitmap
, 20, 80, &color
);
1063 expect(0xff00ffff, color
);
1065 stat
= GdipBitmapGetPixel(bitmap
, 80, 20, &color
);
1067 expect(0xffff0000, color
);
1069 stat
= GdipBitmapGetPixel(bitmap
, 80, 80, &color
);
1071 expect(0xffff00ff, color
);
1073 stat
= GdipDeleteGraphics(graphics
);
1076 stat
= GdipDisposeImage((GpImage
*)bitmap
);
1079 stat
= GdipDisposeImage((GpImage
*)metafile
);
1083 static void test_converttoemfplus(void)
1085 GpStatus (WINAPI
*pGdipConvertToEmfPlus
)( const GpGraphics
*graphics
, GpMetafile
*metafile
, BOOL
*succ
,
1086 EmfType emfType
, const WCHAR
*description
, GpMetafile
**outmetafile
);
1087 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
1088 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
1090 GpMetafile
*metafile
, *metafile2
= NULL
, *emhmeta
;
1091 GpGraphics
*graphics
;
1094 HMODULE mod
= GetModuleHandleA("gdiplus.dll");
1096 pGdipConvertToEmfPlus
= (void*)GetProcAddress( mod
, "GdipConvertToEmfPlus");
1097 if(!pGdipConvertToEmfPlus
)
1099 /* GdipConvertToEmfPlus was introduced in Windows Vista. */
1100 win_skip("GDIPlus version 1.1 not available\n");
1104 hdc
= CreateCompatibleDC(0);
1106 stat
= GdipRecordMetafile(hdc
, MetafileTypeEmf
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
1109 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &emhmeta
);
1117 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
1120 /* Invalid Parameters */
1121 stat
= pGdipConvertToEmfPlus(NULL
, metafile
, &succ
, EmfTypeEmfPlusOnly
, description
, &metafile2
);
1122 expect(InvalidParameter
, stat
);
1124 stat
= pGdipConvertToEmfPlus(graphics
, NULL
, &succ
, EmfTypeEmfPlusOnly
, description
, &metafile2
);
1125 expect(InvalidParameter
, stat
);
1127 stat
= pGdipConvertToEmfPlus(graphics
, metafile
, &succ
, EmfTypeEmfPlusOnly
, description
, NULL
);
1128 expect(InvalidParameter
, stat
);
1130 stat
= pGdipConvertToEmfPlus(graphics
, metafile
, NULL
, MetafileTypeInvalid
, NULL
, &metafile2
);
1131 expect(InvalidParameter
, stat
);
1133 stat
= pGdipConvertToEmfPlus(graphics
, metafile
, NULL
, MetafileTypeEmfPlusDual
+1, NULL
, &metafile2
);
1134 expect(InvalidParameter
, stat
);
1136 /* If we are already an Enhanced Metafile then the conversion fails. */
1137 stat
= pGdipConvertToEmfPlus(graphics
, emhmeta
, NULL
, EmfTypeEmfPlusOnly
, NULL
, &metafile2
);
1138 todo_wine
expect(InvalidParameter
, stat
);
1140 stat
= pGdipConvertToEmfPlus(graphics
, metafile
, NULL
, EmfTypeEmfPlusOnly
, NULL
, &metafile2
);
1141 todo_wine
expect(Ok
, stat
);
1143 GdipDisposeImage((GpImage
*)metafile2
);
1146 stat
= pGdipConvertToEmfPlus(graphics
, metafile
, &succ
, EmfTypeEmfPlusOnly
, NULL
, &metafile2
);
1147 todo_wine
expect(Ok
, stat
);
1149 GdipDisposeImage((GpImage
*)metafile2
);
1151 stat
= GdipDeleteGraphics(graphics
);
1154 stat
= GdipDisposeImage((GpImage
*)metafile
);
1157 stat
= GdipDisposeImage((GpImage
*)emhmeta
);
1161 START_TEST(metafile
)
1163 struct GdiplusStartupInput gdiplusStartupInput
;
1164 ULONG_PTR gdiplusToken
;
1168 gdiplusStartupInput
.GdiplusVersion
= 1;
1169 gdiplusStartupInput
.DebugEventCallback
= NULL
;
1170 gdiplusStartupInput
.SuppressBackgroundThread
= 0;
1171 gdiplusStartupInput
.SuppressExternalCodecs
= 0;
1173 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, NULL
);
1175 myARGC
= winetest_get_mainargs( &myARGV
);
1177 if (myARGC
>= 3 && !strcmp(myARGV
[2], "save"))
1178 save_metafiles
= TRUE
;
1184 test_pagetransform();
1185 test_converttoemfplus();
1187 GdiplusShutdown(gdiplusToken
);