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
24 #include "wine/test.h"
26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
28 typedef struct emfplus_record
34 typedef struct emfplus_check_state
38 const struct emfplus_record
*expected
;
39 } emfplus_check_state
;
41 static void check_record(int count
, const char *desc
, const struct emfplus_record
*expected
, const struct emfplus_record
*actual
)
44 todo_wine
ok(expected
->record_type
== actual
->record_type
,
45 "%s.%i: Expected record type 0x%x, got 0x%x\n", desc
, count
,
46 expected
->record_type
, actual
->record_type
);
48 ok(expected
->record_type
== actual
->record_type
,
49 "%s.%i: Expected record type 0x%x, got 0x%x\n", desc
, count
,
50 expected
->record_type
, actual
->record_type
);
53 typedef struct EmfPlusRecordHeader
59 } EmfPlusRecordHeader
;
61 static int CALLBACK
enum_emf_proc(HDC hDC
, HANDLETABLE
*lpHTable
, const ENHMETARECORD
*lpEMFR
,
62 int nObj
, LPARAM lpData
)
64 emfplus_check_state
*state
= (emfplus_check_state
*)lpData
;
65 emfplus_record actual
;
67 if (lpEMFR
->iType
== EMR_GDICOMMENT
)
69 const EMRGDICOMMENT
*comment
= (const EMRGDICOMMENT
*)lpEMFR
;
71 if (comment
->cbData
>= 4 && memcmp(comment
->Data
, "EMF+", 4) == 0)
75 while (offset
+ sizeof(EmfPlusRecordHeader
) <= comment
->cbData
)
77 const EmfPlusRecordHeader
*record
= (const EmfPlusRecordHeader
*)&comment
->Data
[offset
];
79 ok(record
->Size
== record
->DataSize
+ sizeof(EmfPlusRecordHeader
),
80 "%s: EMF+ record datasize %u and size %u mismatch\n", state
->desc
, record
->DataSize
, record
->Size
);
82 ok(offset
+ record
->DataSize
<= comment
->cbData
,
83 "%s: EMF+ record truncated\n", state
->desc
);
85 if (offset
+ record
->DataSize
> comment
->cbData
)
88 if (state
->expected
[state
->count
].record_type
)
91 actual
.record_type
= record
->Type
;
93 check_record(state
->count
, state
->desc
, &state
->expected
[state
->count
], &actual
);
99 ok(0, "%s: Unexpected EMF+ 0x%x record\n", state
->desc
, record
->Type
);
102 offset
+= record
->Size
;
105 ok(offset
== comment
->cbData
, "%s: truncated EMF+ record data?\n", state
->desc
);
111 if (state
->expected
[state
->count
].record_type
)
114 actual
.record_type
= lpEMFR
->iType
;
116 check_record(state
->count
, state
->desc
, &state
->expected
[state
->count
], &actual
);
122 ok(0, "%s: Unexpected EMF 0x%x record\n", state
->desc
, lpEMFR
->iType
);
128 static void check_emfplus(HENHMETAFILE hemf
, const emfplus_record
*expected
, const char *desc
)
130 emfplus_check_state state
;
134 state
.expected
= expected
;
136 EnumEnhMetaFile(0, hemf
, enum_emf_proc
, &state
, NULL
);
138 if (expected
[state
.count
].todo
)
139 todo_wine
ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
141 ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
144 static BOOL CALLBACK
enum_metafile_proc(EmfPlusRecordType record_type
, unsigned int flags
,
145 unsigned int dataSize
, const unsigned char *pStr
, void *userdata
)
147 emfplus_check_state
*state
= (emfplus_check_state
*)userdata
;
148 emfplus_record actual
;
151 actual
.record_type
= record_type
;
154 ok(pStr
== NULL
, "non-NULL pStr\n");
156 if (state
->expected
[state
->count
].record_type
)
158 check_record(state
->count
, state
->desc
, &state
->expected
[state
->count
], &actual
);
164 ok(0, "%s: Unexpected EMF 0x%x record\n", state
->desc
, record_type
);
170 static void check_metafile(GpMetafile
*metafile
, const emfplus_record
*expected
, const char *desc
,
171 const GpPointF
*dst_points
, const GpRectF
*src_rect
, Unit src_unit
)
175 GpGraphics
*graphics
;
176 emfplus_check_state state
;
180 state
.expected
= expected
;
182 hdc
= CreateCompatibleDC(0);
184 stat
= GdipCreateFromHDC(hdc
, &graphics
);
187 stat
= GdipEnumerateMetafileSrcRectDestPoints(graphics
, metafile
, dst_points
,
188 3, src_rect
, src_unit
, enum_metafile_proc
, &state
, NULL
);
191 if (expected
[state
.count
].todo
)
192 todo_wine
ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
194 ok(expected
[state
.count
].record_type
== 0, "%s: Got %i records, expecting more\n", desc
, state
.count
);
196 GdipDeleteGraphics(graphics
);
201 static const emfplus_record empty_records
[] = {
203 {0, EmfPlusRecordTypeHeader
},
204 {0, EmfPlusRecordTypeEndOfFile
},
209 static void test_empty(void)
212 GpMetafile
*metafile
;
213 GpGraphics
*graphics
;
215 HENHMETAFILE hemf
, dummy
;
217 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
218 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
219 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
221 hdc
= CreateCompatibleDC(0);
223 stat
= GdipRecordMetafile(NULL
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
224 expect(InvalidParameter
, stat
);
226 stat
= GdipRecordMetafile(hdc
, MetafileTypeInvalid
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
227 expect(InvalidParameter
, stat
);
229 stat
= GdipRecordMetafile(hdc
, MetafileTypeWmf
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
230 expect(InvalidParameter
, stat
);
232 stat
= GdipRecordMetafile(hdc
, MetafileTypeWmfPlaceable
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
233 expect(InvalidParameter
, stat
);
235 stat
= GdipRecordMetafile(hdc
, MetafileTypeEmfPlusDual
+1, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
236 expect(InvalidParameter
, stat
);
238 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, NULL
);
239 expect(InvalidParameter
, stat
);
241 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
249 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
250 expect(InvalidParameter
, stat
);
252 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
255 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
256 expect(InvalidParameter
, stat
);
258 stat
= GdipDeleteGraphics(graphics
);
261 check_metafile(metafile
, empty_records
, "empty metafile", dst_points
, &frame
, UnitPixel
);
263 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
266 stat
= GdipGetHemfFromMetafile(metafile
, &dummy
);
267 expect(InvalidParameter
, stat
);
269 stat
= GdipDisposeImage((GpImage
*)metafile
);
272 check_emfplus(hemf
, empty_records
, "empty emf");
274 ret
= DeleteEnhMetaFile(hemf
);
275 ok(ret
!= 0, "Failed to delete enhmetafile %p\n", hemf
);
278 static const emfplus_record getdc_records
[] = {
280 {0, EmfPlusRecordTypeHeader
},
281 {1, EmfPlusRecordTypeGetDC
},
282 {1, EMR_CREATEBRUSHINDIRECT
},
283 {1, EMR_SELECTOBJECT
},
285 {0, EMR_SELECTOBJECT
},
286 {0, EMR_DELETEOBJECT
},
287 {0, EmfPlusRecordTypeEndOfFile
},
292 static void test_getdc(void)
295 GpMetafile
*metafile
;
296 GpGraphics
*graphics
;
297 HDC hdc
, metafile_dc
;
300 static const GpRectF frame
= {0.0, 0.0, 100.0, 100.0};
301 static const GpPointF dst_points
[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
302 static const WCHAR description
[] = {'w','i','n','e','t','e','s','t',0};
303 HBRUSH hbrush
, holdbrush
;
305 hdc
= CreateCompatibleDC(0);
307 stat
= GdipRecordMetafile(hdc
, EmfTypeEmfPlusOnly
, &frame
, MetafileFrameUnitPixel
, description
, &metafile
);
315 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
316 expect(InvalidParameter
, stat
);
318 stat
= GdipGetImageGraphicsContext((GpImage
*)metafile
, &graphics
);
321 stat
= GdipGetDC(graphics
, &metafile_dc
);
326 GdipDeleteGraphics(graphics
);
327 GdipDisposeImage((GpImage
*)metafile
);
331 hbrush
= CreateSolidBrush(0xff0000);
333 holdbrush
= SelectObject(metafile_dc
, hbrush
);
335 Rectangle(metafile_dc
, 25, 25, 75, 75);
337 SelectObject(metafile_dc
, holdbrush
);
339 DeleteObject(hbrush
);
341 stat
= GdipReleaseDC(graphics
, metafile_dc
);
344 stat
= GdipDeleteGraphics(graphics
);
347 check_metafile(metafile
, getdc_records
, "getdc metafile", dst_points
, &frame
, UnitPixel
);
349 stat
= GdipGetHemfFromMetafile(metafile
, &hemf
);
352 stat
= GdipDisposeImage((GpImage
*)metafile
);
355 check_emfplus(hemf
, getdc_records
, "getdc emf");
357 ret
= DeleteEnhMetaFile(hemf
);
358 ok(ret
!= 0, "Failed to delete enhmetafile %p\n", hemf
);
363 struct GdiplusStartupInput gdiplusStartupInput
;
364 ULONG_PTR gdiplusToken
;
366 gdiplusStartupInput
.GdiplusVersion
= 1;
367 gdiplusStartupInput
.DebugEventCallback
= NULL
;
368 gdiplusStartupInput
.SuppressBackgroundThread
= 0;
369 gdiplusStartupInput
.SuppressExternalCodecs
= 0;
371 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, NULL
);
376 GdiplusShutdown(gdiplusToken
);