gdiplus: GdipStringFormatGetGenericTypographic implemented.
[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 = GdipCreateFromHWNDICM(NULL, &graphics);
51     expect(Ok, stat);
52     stat = GdipDeleteGraphics(graphics);
53     expect(Ok, stat);
54
55     stat = GdipDeleteGraphics(NULL);
56     expect(InvalidParameter, stat);
57     ReleaseDC(0, hdc);
58 }
59
60 typedef struct node{
61     GraphicsState data;
62     struct node * next;
63 } node;
64
65 /* Linked list prepend function. */
66 static void log_state(GraphicsState data, node ** log)
67 {
68     node * new_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(node));
69
70     new_entry->data = data;
71     new_entry->next = *log;
72     *log = new_entry;
73 }
74
75 /* Checks if there are duplicates in the list, and frees it. */
76 static void check_no_duplicates(node * log)
77 {
78     INT dups = 0;
79     node * temp = NULL;
80     node * temp2 = NULL;
81     node * orig = log;
82
83     if(!log)
84         goto end;
85
86     do{
87         temp = log;
88         while((temp = temp->next)){
89             if(log->data == temp->data){
90                 dups++;
91                 break;
92             }
93             if(dups > 0)
94                 break;
95         }
96     }while((log = log->next));
97
98     temp = orig;
99     do{
100         temp2 = temp->next;
101         HeapFree(GetProcessHeap(), 0, temp);
102         temp = temp2;
103     }while(temp);
104
105 end:
106     expect(0, dups);
107 }
108
109 static void test_save_restore(void)
110 {
111     GpStatus stat;
112     GraphicsState state_a, state_b, state_c;
113     InterpolationMode mode;
114     GpGraphics *graphics1, *graphics2;
115     node * state_log = NULL;
116     HDC hdc = GetDC(0);
117     state_a = state_b = state_c = 0xdeadbeef;
118
119     /* Invalid saving. */
120     GdipCreateFromHDC(hdc, &graphics1);
121     stat = GdipSaveGraphics(graphics1, NULL);
122     expect(InvalidParameter, stat);
123     stat = GdipSaveGraphics(NULL, &state_a);
124     expect(InvalidParameter, stat);
125     GdipDeleteGraphics(graphics1);
126
127     log_state(state_a, &state_log);
128
129     /* Basic save/restore. */
130     GdipCreateFromHDC(hdc, &graphics1);
131     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
132     stat = GdipSaveGraphics(graphics1, &state_a);
133     todo_wine
134         expect(Ok, stat);
135     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
136     stat = GdipRestoreGraphics(graphics1, state_a);
137     todo_wine
138         expect(Ok, stat);
139     GdipGetInterpolationMode(graphics1, &mode);
140     todo_wine
141         expect(InterpolationModeBilinear, mode);
142     GdipDeleteGraphics(graphics1);
143
144     log_state(state_a, &state_log);
145
146     /* Restoring garbage doesn't affect saves. */
147     GdipCreateFromHDC(hdc, &graphics1);
148     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
149     GdipSaveGraphics(graphics1, &state_a);
150     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
151     GdipSaveGraphics(graphics1, &state_b);
152     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
153     stat = GdipRestoreGraphics(graphics1, 0xdeadbeef);
154     todo_wine
155         expect(Ok, stat);
156     GdipRestoreGraphics(graphics1, state_b);
157     GdipGetInterpolationMode(graphics1, &mode);
158     todo_wine
159         expect(InterpolationModeBicubic, mode);
160     GdipRestoreGraphics(graphics1, state_a);
161     GdipGetInterpolationMode(graphics1, &mode);
162     todo_wine
163         expect(InterpolationModeBilinear, mode);
164     GdipDeleteGraphics(graphics1);
165
166     log_state(state_a, &state_log);
167     log_state(state_b, &state_log);
168
169     /* Restoring older state invalidates newer saves (but not older saves). */
170     GdipCreateFromHDC(hdc, &graphics1);
171     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
172     GdipSaveGraphics(graphics1, &state_a);
173     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
174     GdipSaveGraphics(graphics1, &state_b);
175     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
176     GdipSaveGraphics(graphics1, &state_c);
177     GdipSetInterpolationMode(graphics1, InterpolationModeHighQualityBilinear);
178     GdipRestoreGraphics(graphics1, state_b);
179     GdipGetInterpolationMode(graphics1, &mode);
180     todo_wine
181         expect(InterpolationModeBicubic, mode);
182     GdipRestoreGraphics(graphics1, state_c);
183     GdipGetInterpolationMode(graphics1, &mode);
184     todo_wine
185         expect(InterpolationModeBicubic, mode);
186     GdipRestoreGraphics(graphics1, state_a);
187     GdipGetInterpolationMode(graphics1, &mode);
188     todo_wine
189         expect(InterpolationModeBilinear, mode);
190     GdipDeleteGraphics(graphics1);
191
192     log_state(state_a, &state_log);
193     log_state(state_b, &state_log);
194     log_state(state_c, &state_log);
195
196     /* Restoring older save from one graphics object does not invalidate
197      * newer save from other graphics object. */
198     GdipCreateFromHDC(hdc, &graphics1);
199     GdipCreateFromHDC(hdc, &graphics2);
200     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
201     GdipSaveGraphics(graphics1, &state_a);
202     GdipSetInterpolationMode(graphics2, InterpolationModeBicubic);
203     GdipSaveGraphics(graphics2, &state_b);
204     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
205     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
206     GdipRestoreGraphics(graphics1, state_a);
207     GdipGetInterpolationMode(graphics1, &mode);
208     todo_wine
209         expect(InterpolationModeBilinear, mode);
210     GdipRestoreGraphics(graphics2, state_b);
211     GdipGetInterpolationMode(graphics2, &mode);
212     todo_wine
213         expect(InterpolationModeBicubic, mode);
214     GdipDeleteGraphics(graphics1);
215     GdipDeleteGraphics(graphics2);
216
217     /* You can't restore a state to a graphics object that didn't save it. */
218     GdipCreateFromHDC(hdc, &graphics1);
219     GdipCreateFromHDC(hdc, &graphics2);
220     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
221     GdipSaveGraphics(graphics1, &state_a);
222     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
223     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
224     GdipRestoreGraphics(graphics2, state_a);
225     GdipGetInterpolationMode(graphics2, &mode);
226     expect(InterpolationModeNearestNeighbor, mode);
227     GdipDeleteGraphics(graphics1);
228     GdipDeleteGraphics(graphics2);
229
230     log_state(state_a, &state_log);
231
232     /* The same state value should never be returned twice. */
233     todo_wine
234         check_no_duplicates(state_log);
235
236     ReleaseDC(0, hdc);
237 }
238
239 static void test_GdipDrawArc(void)
240 {
241     GpStatus status;
242     GpGraphics *graphics = NULL;
243     GpPen *pen = NULL;
244     HDC hdc = GetDC(0);
245
246     /* make a graphics object and pen object */
247     status = GdipCreateFromHDC(hdc, &graphics);
248     expect(Ok, status);
249     ok(hdc != NULL, "Expected HDC to be initialized\n");
250
251     status = GdipCreateFromHDC(hdc, &graphics);
252     expect(Ok, status);
253     ok(graphics != NULL, "Expected graphics to be initialized\n");
254
255     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
256     expect(Ok, status);
257     ok(pen != NULL, "Expected pen to be initialized\n");
258
259     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
260     status = GdipDrawArc(NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
261     expect(InvalidParameter, status);
262
263     status = GdipDrawArc(graphics, NULL, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
264     expect(InvalidParameter, status);
265
266     status = GdipDrawArc(NULL, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
267     expect(InvalidParameter, status);
268
269     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
270     expect(InvalidParameter, status);
271
272     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
273     expect(InvalidParameter, status);
274
275     /* successful case */
276     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
277     expect(Ok, status);
278
279     GdipDeletePen(pen);
280     ReleaseDC(0, hdc);
281 }
282
283 static void test_GdipDrawArcI(void)
284 {
285     GpStatus status;
286     GpGraphics *graphics = NULL;
287     GpPen *pen = NULL;
288     HDC hdc = GetDC(0);
289
290     /* make a graphics object and pen object */
291     status = GdipCreateFromHDC(hdc, &graphics);
292     expect(Ok, status);
293     ok(hdc != NULL, "Expected HDC to be initialized\n");
294
295     status = GdipCreateFromHDC(hdc, &graphics);
296     expect(Ok, status);
297     ok(graphics != NULL, "Expected graphics to be initialized\n");
298
299     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
300     expect(Ok, status);
301     ok(pen != NULL, "Expected pen to be initialized\n");
302
303     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
304     status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0);
305     expect(InvalidParameter, status);
306
307     status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0);
308     expect(InvalidParameter, status);
309
310     status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0);
311     expect(InvalidParameter, status);
312
313     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0);
314     expect(InvalidParameter, status);
315
316     status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0);
317     expect(InvalidParameter, status);
318
319     /* successful case */
320     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0);
321     expect(Ok, status);
322
323     GdipDeletePen(pen);
324     ReleaseDC(0, hdc);
325 }
326
327 static void test_GdipDrawBezierI(void)
328 {
329     GpStatus status;
330     GpGraphics *graphics = NULL;
331     GpPen *pen = NULL;
332     HDC hdc = GetDC(0);
333
334     /* make a graphics object and pen object */
335     status = GdipCreateFromHDC(hdc, &graphics);
336     expect(Ok, status);
337     ok(hdc != NULL, "Expected HDC to be initialized\n");
338
339     status = GdipCreateFromHDC(hdc, &graphics);
340     expect(Ok, status);
341     ok(graphics != NULL, "Expected graphics to be initialized\n");
342
343     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
344     expect(Ok, status);
345     ok(pen != NULL, "Expected pen to be initialized\n");
346
347     /* InvalidParameter cases: null graphics, null pen */
348     status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
349     expect(InvalidParameter, status);
350
351     status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
352     expect(InvalidParameter, status);
353
354     status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0);
355     expect(InvalidParameter, status);
356
357     /* successful case */
358     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
359     expect(Ok, status);
360
361     GdipDeletePen(pen);
362     ReleaseDC(0, hdc);
363 }
364
365 static void test_GdipDrawLineI(void)
366 {
367     GpStatus status;
368     GpGraphics *graphics = NULL;
369     GpPen *pen = NULL;
370     HDC hdc = GetDC(0);
371
372     /* make a graphics object and pen object */
373     status = GdipCreateFromHDC(hdc, &graphics);
374     expect(Ok, status);
375     ok(hdc != NULL, "Expected HDC to be initialized\n");
376
377     status = GdipCreateFromHDC(hdc, &graphics);
378     expect(Ok, status);
379     ok(graphics != NULL, "Expected graphics to be initialized\n");
380
381     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
382     expect(Ok, status);
383     ok(pen != NULL, "Expected pen to be initialized\n");
384
385     /* InvalidParameter cases: null graphics, null pen */
386     status = GdipDrawLineI(NULL, NULL, 0, 0, 0, 0);
387     expect(InvalidParameter, status);
388
389     status = GdipDrawLineI(graphics, NULL, 0, 0, 0, 0);
390     expect(InvalidParameter, status);
391
392     status = GdipDrawLineI(NULL, pen, 0, 0, 0, 0);
393     expect(InvalidParameter, status);
394
395     /* successful case */
396     status = GdipDrawLineI(graphics, pen, 0, 0, 0, 0);
397     expect(Ok, status);
398
399     GdipDeletePen(pen);
400     ReleaseDC(0, hdc);
401 }
402
403 static void test_GdipDrawLinesI(void)
404 {
405     GpStatus status;
406     GpGraphics *graphics = NULL;
407     GpPen *pen = NULL;
408     GpPoint *ptf = NULL;
409     HDC hdc = GetDC(0);
410
411     /* make a graphics object and pen object */
412     status = GdipCreateFromHDC(hdc, &graphics);
413     expect(Ok, status);
414     ok(hdc != NULL, "Expected HDC to be initialized\n");
415
416     status = GdipCreateFromHDC(hdc, &graphics);
417     expect(Ok, status);
418     ok(graphics != NULL, "Expected graphics to be initialized\n");
419
420     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
421     expect(Ok, status);
422     ok(pen != NULL, "Expected pen to be initialized\n");
423
424     /* make some arbitrary valid points*/
425     ptf = GdipAlloc(2 * sizeof(GpPointF));
426
427     ptf[0].X = 1;
428     ptf[0].Y = 1;
429
430     ptf[1].X = 2;
431     ptf[1].Y = 2;
432
433     /* InvalidParameter cases: null graphics, null pen, null points, count < 2*/
434     status = GdipDrawLinesI(NULL, NULL, NULL, 0);
435     expect(InvalidParameter, status);
436
437     status = GdipDrawLinesI(graphics, pen, ptf, 0);
438     expect(InvalidParameter, status);
439
440     status = GdipDrawLinesI(graphics, NULL, ptf, 2);
441     expect(InvalidParameter, status);
442
443     status = GdipDrawLinesI(NULL, pen, ptf, 2);
444     expect(InvalidParameter, status);
445
446     /* successful case */
447     status = GdipDrawLinesI(graphics, pen, ptf, 2);
448     expect(Ok, status);
449
450     GdipFree(ptf);
451     GdipDeletePen(pen);
452     ReleaseDC(0, hdc);
453 }
454
455 START_TEST(graphics)
456 {
457     struct GdiplusStartupInput gdiplusStartupInput;
458     ULONG_PTR gdiplusToken;
459
460     gdiplusStartupInput.GdiplusVersion              = 1;
461     gdiplusStartupInput.DebugEventCallback          = NULL;
462     gdiplusStartupInput.SuppressBackgroundThread    = 0;
463     gdiplusStartupInput.SuppressExternalCodecs      = 0;
464
465     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
466
467     test_constructor_destructor();
468     test_save_restore();
469     test_GdipDrawBezierI();
470     test_GdipDrawArc();
471     test_GdipDrawArcI();
472     test_GdipDrawLineI();
473     test_GdipDrawLinesI();
474
475     GdiplusShutdown(gdiplusToken);
476 }