d3dcompiler: Add argument check in D3DReflect().
[wine] / dlls / gdiplus / tests / metafile.c
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 "windows.h"
22 #include <stdio.h>
23 #include "gdiplus.h"
24 #include "wine/test.h"
25
26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
27
28 typedef struct emfplus_record
29 {
30     ULONG todo;
31     ULONG record_type;
32     int is_emfplus;
33 } emfplus_record;
34
35 typedef struct emfplus_check_state
36 {
37     const char *desc;
38     int count;
39     const struct emfplus_record *expected;
40 } emfplus_check_state;
41
42 static void check_record(int count, const char *desc, const struct emfplus_record *expected, const struct emfplus_record *actual)
43 {
44     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);
47
48     ok(expected->is_emfplus == actual->is_emfplus,
49         "%s.%i: Expected is_emfplus %i, got %i\n", desc, count,
50         expected->record_type, actual->record_type);
51 }
52
53 typedef struct EmfPlusRecordHeader
54 {
55     WORD Type;
56     WORD Flags;
57     DWORD Size;
58     DWORD DataSize;
59 } EmfPlusRecordHeader;
60
61 static int CALLBACK enum_emf_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
62     int nObj, LPARAM lpData)
63 {
64     emfplus_check_state *state = (emfplus_check_state*)lpData;
65     emfplus_record actual;
66
67     if (lpEMFR->iType == EMR_GDICOMMENT)
68     {
69         const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR;
70
71         if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0)
72         {
73             int offset = 4;
74
75             while (offset + sizeof(EmfPlusRecordHeader) <= comment->cbData)
76             {
77                 const EmfPlusRecordHeader *record = (const EmfPlusRecordHeader*)&comment->Data[offset];
78
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);
81
82                 ok(offset + record->DataSize <= comment->cbData,
83                     "%s: EMF+ record truncated\n", state->desc);
84
85                 if (offset + record->DataSize > comment->cbData)
86                     return 0;
87
88                 if (state->expected[state->count].record_type)
89                 {
90                     actual.todo = 0;
91                     actual.record_type = record->Type;
92                     actual.is_emfplus = 1;
93
94                     check_record(state->count, state->desc, &state->expected[state->count], &actual);
95
96                     state->count++;
97                 }
98                 else
99                 {
100                     ok(0, "%s: Unexpected EMF+ 0x%x record\n", state->desc, record->Type);
101                 }
102
103                 offset += record->Size;
104             }
105
106             ok(offset == comment->cbData, "%s: truncated EMF+ record data?\n", state->desc);
107
108             return 1;
109         }
110     }
111
112     if (state->expected[state->count].record_type)
113     {
114         actual.todo = 0;
115         actual.record_type = lpEMFR->iType;
116         actual.is_emfplus = 0;
117
118         check_record(state->count, state->desc, &state->expected[state->count], &actual);
119
120         state->count++;
121     }
122     else
123     {
124         ok(0, "%s: Unexpected EMF 0x%x record\n", state->desc, lpEMFR->iType);
125     }
126
127     return 1;
128 }
129
130 static void check_emfplus(HENHMETAFILE hemf, const emfplus_record *expected, const char *desc)
131 {
132     emfplus_check_state state;
133
134     state.desc = desc;
135     state.count = 0;
136     state.expected = expected;
137
138     EnumEnhMetaFile(0, hemf, enum_emf_proc, &state, NULL);
139
140     ok(expected[state.count].record_type == 0, "%s: Got %i records, expecting more\n", desc, state.count);
141 }
142
143 static const emfplus_record empty_records[] = {
144     {0, EMR_HEADER, 0},
145     {0, EmfPlusRecordTypeHeader, 1},
146     {0, EmfPlusRecordTypeEndOfFile, 1},
147     {0, EMR_EOF, 0},
148     {0}
149 };
150
151 static void test_empty(void)
152 {
153     GpStatus stat;
154     GpMetafile *metafile;
155     GpGraphics *graphics;
156     HDC hdc;
157     HENHMETAFILE hemf, dummy;
158     BOOL ret;
159     static const GpRectF frame = {0.0, 0.0, 100.0, 100.0};
160     static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
161
162     hdc = CreateCompatibleDC(0);
163
164     stat = GdipRecordMetafile(hdc, EmfTypeEmfPlusOnly, &frame, MetafileFrameUnitPixel, description, &metafile);
165     todo_wine expect(Ok, stat);
166
167     DeleteDC(hdc);
168
169     if (stat != Ok)
170         return;
171
172     stat = GdipGetHemfFromMetafile(metafile, &hemf);
173     expect(InvalidParameter, stat);
174
175     stat = GdipGetImageGraphicsContext((GpImage*)metafile, &graphics);
176     expect(Ok, stat);
177
178     stat = GdipGetHemfFromMetafile(metafile, &hemf);
179     expect(InvalidParameter, stat);
180
181     stat = GdipDeleteGraphics(graphics);
182     expect(Ok, stat);
183
184     stat = GdipGetHemfFromMetafile(metafile, &hemf);
185     expect(Ok, stat);
186
187     stat = GdipGetHemfFromMetafile(metafile, &dummy);
188     expect(InvalidParameter, stat);
189
190     stat = GdipDisposeImage((GpImage*)metafile);
191     expect(Ok, stat);
192
193     check_emfplus(hemf, empty_records, "empty");
194
195     ret = DeleteEnhMetaFile(hemf);
196     ok(ret != 0, "Failed to delete enhmetafile %p\n", hemf);
197 }
198
199 START_TEST(metafile)
200 {
201     struct GdiplusStartupInput gdiplusStartupInput;
202     ULONG_PTR gdiplusToken;
203
204     gdiplusStartupInput.GdiplusVersion              = 1;
205     gdiplusStartupInput.DebugEventCallback          = NULL;
206     gdiplusStartupInput.SuppressBackgroundThread    = 0;
207     gdiplusStartupInput.SuppressExternalCodecs      = 0;
208
209     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
210
211     test_empty();
212
213     GdiplusShutdown(gdiplusToken);
214 }