diplus: Implemented GdipDrawArcI based on GdipDrawArc.
[wine] / dlls / gdiplus / tests / graphics.c
1 /*
2  * Unit test suite for graphics objects
3  *
4  * Copyright (C) 2007 Google (Evan Stade)
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 "gdiplus.h"
23 #include "wingdi.h"
24 #include "wine/test.h"
25
26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
27 #define TABLE_LEN (23)
28
29 static void test_constructor_destructor(void)
30 {
31     GpStatus stat;
32     GpGraphics *graphics = NULL;
33     HDC hdc = GetDC(0);
34
35     stat = GdipCreateFromHDC(NULL, &graphics);
36     expect(OutOfMemory, stat);
37     stat = GdipDeleteGraphics(graphics);
38     expect(InvalidParameter, stat);
39
40     stat = GdipCreateFromHDC(hdc, &graphics);
41     expect(Ok, stat);
42     stat = GdipDeleteGraphics(graphics);
43     expect(Ok, stat);
44
45     stat = GdipCreateFromHWND(NULL, &graphics);
46     expect(Ok, stat);
47     stat = GdipDeleteGraphics(graphics);
48     expect(Ok, stat);
49
50     stat = GdipDeleteGraphics(NULL);
51     expect(InvalidParameter, stat);
52     ReleaseDC(0, hdc);
53 }
54
55 typedef struct node{
56     GraphicsState data;
57     struct node * next;
58 } node;
59
60 /* Linked list prepend function. */
61 static void log_state(GraphicsState data, node ** log)
62 {
63     node * new_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(node));
64
65     new_entry->data = data;
66     new_entry->next = *log;
67     *log = new_entry;
68 }
69
70 /* Checks if there are duplicates in the list, and frees it. */
71 static void check_no_duplicates(node * log)
72 {
73     INT dups = 0;
74     node * temp = NULL;
75
76     if(!log)
77         goto end;
78
79     do{
80         HeapFree(GetProcessHeap(), 0, temp);
81         temp = log;
82         while((temp = temp->next))
83             if(log->data == temp->data)
84                 dups++;
85
86     }while((log = log->next));
87
88     HeapFree(GetProcessHeap(), 0, temp);
89
90 end:
91     expect(0, dups);
92 }
93
94 static void test_save_restore(void)
95 {
96     GpStatus stat;
97     GraphicsState state_a, state_b, state_c;
98     InterpolationMode mode;
99     GpGraphics *graphics1, *graphics2;
100     node * state_log = NULL;
101     HDC hdc = GetDC(0);
102
103     /* Invalid saving. */
104     GdipCreateFromHDC(hdc, &graphics1);
105     stat = GdipSaveGraphics(graphics1, NULL);
106     expect(InvalidParameter, stat);
107     stat = GdipSaveGraphics(NULL, &state_a);
108     expect(InvalidParameter, stat);
109     GdipDeleteGraphics(graphics1);
110
111     log_state(state_a, &state_log);
112
113     /* Basic save/restore. */
114     GdipCreateFromHDC(hdc, &graphics1);
115     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
116     stat = GdipSaveGraphics(graphics1, &state_a);
117     todo_wine
118         expect(Ok, stat);
119     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
120     stat = GdipRestoreGraphics(graphics1, state_a);
121     todo_wine
122         expect(Ok, stat);
123     GdipGetInterpolationMode(graphics1, &mode);
124     todo_wine
125         expect(InterpolationModeBilinear, mode);
126     GdipDeleteGraphics(graphics1);
127
128     log_state(state_a, &state_log);
129
130     /* Restoring garbage doesn't affect saves. */
131     GdipCreateFromHDC(hdc, &graphics1);
132     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
133     GdipSaveGraphics(graphics1, &state_a);
134     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
135     GdipSaveGraphics(graphics1, &state_b);
136     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
137     stat = GdipRestoreGraphics(graphics1, 0xdeadbeef);
138     todo_wine
139         expect(Ok, stat);
140     GdipRestoreGraphics(graphics1, state_b);
141     GdipGetInterpolationMode(graphics1, &mode);
142     todo_wine
143         expect(InterpolationModeBicubic, mode);
144     GdipRestoreGraphics(graphics1, state_a);
145     GdipGetInterpolationMode(graphics1, &mode);
146     todo_wine
147         expect(InterpolationModeBilinear, mode);
148     GdipDeleteGraphics(graphics1);
149
150     log_state(state_a, &state_log);
151     log_state(state_b, &state_log);
152
153     /* Restoring older state invalidates newer saves (but not older saves). */
154     GdipCreateFromHDC(hdc, &graphics1);
155     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
156     GdipSaveGraphics(graphics1, &state_a);
157     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
158     GdipSaveGraphics(graphics1, &state_b);
159     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
160     GdipSaveGraphics(graphics1, &state_c);
161     GdipSetInterpolationMode(graphics1, InterpolationModeHighQualityBilinear);
162     GdipRestoreGraphics(graphics1, state_b);
163     GdipGetInterpolationMode(graphics1, &mode);
164     todo_wine
165         expect(InterpolationModeBicubic, mode);
166     GdipRestoreGraphics(graphics1, state_c);
167     GdipGetInterpolationMode(graphics1, &mode);
168     todo_wine
169         expect(InterpolationModeBicubic, mode);
170     GdipRestoreGraphics(graphics1, state_a);
171     GdipGetInterpolationMode(graphics1, &mode);
172     todo_wine
173         expect(InterpolationModeBilinear, mode);
174     GdipDeleteGraphics(graphics1);
175
176     log_state(state_a, &state_log);
177     log_state(state_b, &state_log);
178     log_state(state_c, &state_log);
179
180     /* Restoring older save from one graphics object does not invalidate
181      * newer save from other graphics object. */
182     GdipCreateFromHDC(hdc, &graphics1);
183     GdipCreateFromHDC(hdc, &graphics2);
184     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
185     GdipSaveGraphics(graphics1, &state_a);
186     GdipSetInterpolationMode(graphics2, InterpolationModeBicubic);
187     GdipSaveGraphics(graphics2, &state_b);
188     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
189     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
190     GdipRestoreGraphics(graphics1, state_a);
191     GdipGetInterpolationMode(graphics1, &mode);
192     todo_wine
193         expect(InterpolationModeBilinear, mode);
194     GdipRestoreGraphics(graphics2, state_b);
195     GdipGetInterpolationMode(graphics2, &mode);
196     todo_wine
197         expect(InterpolationModeBicubic, mode);
198     GdipDeleteGraphics(graphics1);
199     GdipDeleteGraphics(graphics2);
200
201     /* You can't restore a state to a graphics object that didn't save it. */
202     GdipCreateFromHDC(hdc, &graphics1);
203     GdipCreateFromHDC(hdc, &graphics2);
204     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
205     GdipSaveGraphics(graphics1, &state_a);
206     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
207     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
208     GdipRestoreGraphics(graphics2, state_a);
209     GdipGetInterpolationMode(graphics2, &mode);
210     expect(InterpolationModeNearestNeighbor, mode);
211     GdipDeleteGraphics(graphics1);
212     GdipDeleteGraphics(graphics2);
213
214     log_state(state_a, &state_log);
215
216     /* The same state value should never be returned twice. */
217     todo_wine
218         check_no_duplicates(state_log);
219
220     ReleaseDC(0, hdc);
221 }
222
223 static void test_GdipDrawArcI(void)
224 {
225     GpStatus status;
226     GpGraphics *graphics = NULL;
227     GpPen *pen = NULL;
228     HDC hdc = GetDC(0);
229
230     /* make a graphics object and pen object */
231     status = GdipCreateFromHDC(hdc, &graphics);
232     expect(Ok, status);
233     ok(hdc != NULL, "Expected HDC to be initialized\n");
234
235     status = GdipCreateFromHDC(hdc, &graphics);
236     expect(Ok, status);
237     ok(graphics != NULL, "Expected graphics to be initialized\n");
238
239     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
240     expect(Ok, status);
241     ok(pen != NULL, "Expected pen to be initialized\n");
242
243     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
244     status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0);
245     expect(InvalidParameter, status);
246
247     status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0);
248     expect(InvalidParameter, status);
249
250     status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0);
251     expect(InvalidParameter, status);
252
253     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0);
254     expect(InvalidParameter, status);
255
256     status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0);
257     expect(InvalidParameter, status);
258
259     /* successful case */
260     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0);
261     expect(Ok, status);
262
263     GdipDeletePen(pen);
264     ReleaseDC(0, hdc);
265 }
266
267 static void test_GdipDrawBezierI(void)
268 {
269     GpStatus status;
270     GpGraphics *graphics = NULL;
271     GpPen *pen = NULL;
272     HDC hdc = GetDC(0);
273
274     /* make a graphics object and pen object */
275     status = GdipCreateFromHDC(hdc, &graphics);
276     expect(Ok, status);
277     ok(hdc != NULL, "Expected HDC to be initialized\n");
278
279     status = GdipCreateFromHDC(hdc, &graphics);
280     expect(Ok, status);
281     ok(graphics != NULL, "Expected graphics to be initialized\n");
282
283     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
284     expect(Ok, status);
285     ok(pen != NULL, "Expected pen to be initialized\n");
286
287     /* InvalidParameter cases: null graphics, null pen */
288     status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
289     expect(InvalidParameter, status);
290
291     status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
292     expect(InvalidParameter, status);
293
294     status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0);
295     expect(InvalidParameter, status);
296
297     /* successful case */
298     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
299     expect(Ok, status);
300
301     GdipDeletePen(pen);
302     ReleaseDC(0, hdc);
303 }
304
305 START_TEST(graphics)
306 {
307     struct GdiplusStartupInput gdiplusStartupInput;
308     ULONG_PTR gdiplusToken;
309
310     gdiplusStartupInput.GdiplusVersion              = 1;
311     gdiplusStartupInput.DebugEventCallback          = NULL;
312     gdiplusStartupInput.SuppressBackgroundThread    = 0;
313     gdiplusStartupInput.SuppressExternalCodecs      = 0;
314
315     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
316
317     test_constructor_destructor();
318     test_save_restore();
319     test_GdipDrawBezierI();
320     test_GdipDrawArcI();
321
322     GdiplusShutdown(gdiplusToken);
323 }