quartz: Fix discontinuities in wave parser.
[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_GdipDrawArc(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 = GdipDrawArc(NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
245     expect(InvalidParameter, status);
246
247     status = GdipDrawArc(graphics, NULL, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
248     expect(InvalidParameter, status);
249
250     status = GdipDrawArc(NULL, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
251     expect(InvalidParameter, status);
252
253     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
254     expect(InvalidParameter, status);
255
256     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
257     expect(InvalidParameter, status);
258
259     /* successful case */
260     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
261     expect(Ok, status);
262
263     GdipDeletePen(pen);
264     ReleaseDC(0, hdc);
265 }
266
267 static void test_GdipDrawArcI(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, non-positive width, non-positive height */
288     status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0);
289     expect(InvalidParameter, status);
290
291     status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0);
292     expect(InvalidParameter, status);
293
294     status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0);
295     expect(InvalidParameter, status);
296
297     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0);
298     expect(InvalidParameter, status);
299
300     status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0);
301     expect(InvalidParameter, status);
302
303     /* successful case */
304     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0);
305     expect(Ok, status);
306
307     GdipDeletePen(pen);
308     ReleaseDC(0, hdc);
309 }
310
311 static void test_GdipDrawBezierI(void)
312 {
313     GpStatus status;
314     GpGraphics *graphics = NULL;
315     GpPen *pen = NULL;
316     HDC hdc = GetDC(0);
317
318     /* make a graphics object and pen object */
319     status = GdipCreateFromHDC(hdc, &graphics);
320     expect(Ok, status);
321     ok(hdc != NULL, "Expected HDC to be initialized\n");
322
323     status = GdipCreateFromHDC(hdc, &graphics);
324     expect(Ok, status);
325     ok(graphics != NULL, "Expected graphics to be initialized\n");
326
327     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
328     expect(Ok, status);
329     ok(pen != NULL, "Expected pen to be initialized\n");
330
331     /* InvalidParameter cases: null graphics, null pen */
332     status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
333     expect(InvalidParameter, status);
334
335     status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
336     expect(InvalidParameter, status);
337
338     status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0);
339     expect(InvalidParameter, status);
340
341     /* successful case */
342     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
343     expect(Ok, status);
344
345     GdipDeletePen(pen);
346     ReleaseDC(0, hdc);
347 }
348
349 static void test_GdipDrawLineI(void)
350 {
351     GpStatus status;
352     GpGraphics *graphics = NULL;
353     GpPen *pen = NULL;
354     HDC hdc = GetDC(0);
355
356     /* make a graphics object and pen object */
357     status = GdipCreateFromHDC(hdc, &graphics);
358     expect(Ok, status);
359     ok(hdc != NULL, "Expected HDC to be initialized\n");
360
361     status = GdipCreateFromHDC(hdc, &graphics);
362     expect(Ok, status);
363     ok(graphics != NULL, "Expected graphics to be initialized\n");
364
365     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
366     expect(Ok, status);
367     ok(pen != NULL, "Expected pen to be initialized\n");
368
369     /* InvalidParameter cases: null graphics, null pen */
370     status = GdipDrawLineI(NULL, NULL, 0, 0, 0, 0);
371     expect(InvalidParameter, status);
372
373     status = GdipDrawLineI(graphics, NULL, 0, 0, 0, 0);
374     expect(InvalidParameter, status);
375
376     status = GdipDrawLineI(NULL, pen, 0, 0, 0, 0);
377     expect(InvalidParameter, status);
378
379     /* successful case */
380     status = GdipDrawLineI(graphics, pen, 0, 0, 0, 0);
381     expect(Ok, status);
382
383     GdipDeletePen(pen);
384     ReleaseDC(0, hdc);
385 }
386
387 static void test_GdipDrawLinesI(void)
388 {
389     GpStatus status;
390     GpGraphics *graphics = NULL;
391     GpPen *pen = NULL;
392     GpPoint *ptf = NULL;
393     HDC hdc = GetDC(0);
394
395     /* make a graphics object and pen object */
396     status = GdipCreateFromHDC(hdc, &graphics);
397     expect(Ok, status);
398     ok(hdc != NULL, "Expected HDC to be initialized\n");
399
400     status = GdipCreateFromHDC(hdc, &graphics);
401     expect(Ok, status);
402     ok(graphics != NULL, "Expected graphics to be initialized\n");
403
404     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
405     expect(Ok, status);
406     ok(pen != NULL, "Expected pen to be initialized\n");
407
408     /* make some arbitrary valid points*/
409     ptf = GdipAlloc(2 * sizeof(GpPointF));
410
411     ptf[0].X = 1;
412     ptf[0].Y = 1;
413
414     ptf[1].X = 2;
415     ptf[1].Y = 2;
416
417     /* InvalidParameter cases: null graphics, null pen, null points, count < 2*/
418     status = GdipDrawLinesI(NULL, NULL, NULL, 0);
419     expect(InvalidParameter, status);
420
421     status = GdipDrawLinesI(graphics, pen, ptf, 0);
422     expect(InvalidParameter, status);
423
424     status = GdipDrawLinesI(graphics, NULL, ptf, 2);
425     expect(InvalidParameter, status);
426
427     status = GdipDrawLinesI(NULL, pen, ptf, 2);
428     expect(InvalidParameter, status);
429
430     /* successful case */
431     status = GdipDrawLinesI(graphics, pen, ptf, 2);
432     expect(Ok, status);
433
434     GdipFree(ptf);
435     GdipDeletePen(pen);
436     ReleaseDC(0, hdc);
437 }
438
439 START_TEST(graphics)
440 {
441     struct GdiplusStartupInput gdiplusStartupInput;
442     ULONG_PTR gdiplusToken;
443
444     gdiplusStartupInput.GdiplusVersion              = 1;
445     gdiplusStartupInput.DebugEventCallback          = NULL;
446     gdiplusStartupInput.SuppressBackgroundThread    = 0;
447     gdiplusStartupInput.SuppressExternalCodecs      = 0;
448
449     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
450
451     test_constructor_destructor();
452     test_save_restore();
453     test_GdipDrawBezierI();
454     test_GdipDrawArc();
455     test_GdipDrawArcI();
456     test_GdipDrawLineI();
457     test_GdipDrawLinesI();
458
459     GdiplusShutdown(gdiplusToken);
460 }