gdiplus: Add some tests for pathiterator, fix leaks.
[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     GdipDeleteGraphics(graphics);
281
282     ReleaseDC(0, hdc);
283 }
284
285 static void test_GdipDrawArcI(void)
286 {
287     GpStatus status;
288     GpGraphics *graphics = NULL;
289     GpPen *pen = NULL;
290     HDC hdc = GetDC(0);
291
292     /* make a graphics object and pen object */
293     status = GdipCreateFromHDC(hdc, &graphics);
294     expect(Ok, status);
295     ok(hdc != NULL, "Expected HDC to be initialized\n");
296
297     status = GdipCreateFromHDC(hdc, &graphics);
298     expect(Ok, status);
299     ok(graphics != NULL, "Expected graphics to be initialized\n");
300
301     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
302     expect(Ok, status);
303     ok(pen != NULL, "Expected pen to be initialized\n");
304
305     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
306     status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0);
307     expect(InvalidParameter, status);
308
309     status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0);
310     expect(InvalidParameter, status);
311
312     status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0);
313     expect(InvalidParameter, status);
314
315     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0);
316     expect(InvalidParameter, status);
317
318     status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0);
319     expect(InvalidParameter, status);
320
321     /* successful case */
322     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0);
323     expect(Ok, status);
324
325     GdipDeletePen(pen);
326     GdipDeleteGraphics(graphics);
327
328     ReleaseDC(0, hdc);
329 }
330
331 static void test_GdipDrawBezierI(void)
332 {
333     GpStatus status;
334     GpGraphics *graphics = NULL;
335     GpPen *pen = NULL;
336     HDC hdc = GetDC(0);
337
338     /* make a graphics object and pen object */
339     status = GdipCreateFromHDC(hdc, &graphics);
340     expect(Ok, status);
341     ok(hdc != NULL, "Expected HDC to be initialized\n");
342
343     status = GdipCreateFromHDC(hdc, &graphics);
344     expect(Ok, status);
345     ok(graphics != NULL, "Expected graphics to be initialized\n");
346
347     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
348     expect(Ok, status);
349     ok(pen != NULL, "Expected pen to be initialized\n");
350
351     /* InvalidParameter cases: null graphics, null pen */
352     status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
353     expect(InvalidParameter, status);
354
355     status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
356     expect(InvalidParameter, status);
357
358     status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0);
359     expect(InvalidParameter, status);
360
361     /* successful case */
362     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
363     expect(Ok, status);
364
365     GdipDeletePen(pen);
366     GdipDeleteGraphics(graphics);
367
368     ReleaseDC(0, hdc);
369 }
370
371 static void test_GdipDrawLineI(void)
372 {
373     GpStatus status;
374     GpGraphics *graphics = NULL;
375     GpPen *pen = NULL;
376     HDC hdc = GetDC(0);
377
378     /* make a graphics object and pen object */
379     status = GdipCreateFromHDC(hdc, &graphics);
380     expect(Ok, status);
381     ok(hdc != NULL, "Expected HDC to be initialized\n");
382
383     status = GdipCreateFromHDC(hdc, &graphics);
384     expect(Ok, status);
385     ok(graphics != NULL, "Expected graphics to be initialized\n");
386
387     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
388     expect(Ok, status);
389     ok(pen != NULL, "Expected pen to be initialized\n");
390
391     /* InvalidParameter cases: null graphics, null pen */
392     status = GdipDrawLineI(NULL, NULL, 0, 0, 0, 0);
393     expect(InvalidParameter, status);
394
395     status = GdipDrawLineI(graphics, NULL, 0, 0, 0, 0);
396     expect(InvalidParameter, status);
397
398     status = GdipDrawLineI(NULL, pen, 0, 0, 0, 0);
399     expect(InvalidParameter, status);
400
401     /* successful case */
402     status = GdipDrawLineI(graphics, pen, 0, 0, 0, 0);
403     expect(Ok, status);
404
405     GdipDeletePen(pen);
406     GdipDeleteGraphics(graphics);
407
408     ReleaseDC(0, hdc);
409 }
410
411 static void test_GdipDrawLinesI(void)
412 {
413     GpStatus status;
414     GpGraphics *graphics = NULL;
415     GpPen *pen = NULL;
416     GpPoint *ptf = NULL;
417     HDC hdc = GetDC(0);
418
419     /* make a graphics object and pen object */
420     status = GdipCreateFromHDC(hdc, &graphics);
421     expect(Ok, status);
422     ok(hdc != NULL, "Expected HDC to be initialized\n");
423
424     status = GdipCreateFromHDC(hdc, &graphics);
425     expect(Ok, status);
426     ok(graphics != NULL, "Expected graphics to be initialized\n");
427
428     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
429     expect(Ok, status);
430     ok(pen != NULL, "Expected pen to be initialized\n");
431
432     /* make some arbitrary valid points*/
433     ptf = GdipAlloc(2 * sizeof(GpPointF));
434
435     ptf[0].X = 1;
436     ptf[0].Y = 1;
437
438     ptf[1].X = 2;
439     ptf[1].Y = 2;
440
441     /* InvalidParameter cases: null graphics, null pen, null points, count < 2*/
442     status = GdipDrawLinesI(NULL, NULL, NULL, 0);
443     expect(InvalidParameter, status);
444
445     status = GdipDrawLinesI(graphics, pen, ptf, 0);
446     expect(InvalidParameter, status);
447
448     status = GdipDrawLinesI(graphics, NULL, ptf, 2);
449     expect(InvalidParameter, status);
450
451     status = GdipDrawLinesI(NULL, pen, ptf, 2);
452     expect(InvalidParameter, status);
453
454     /* successful case */
455     status = GdipDrawLinesI(graphics, pen, ptf, 2);
456     expect(Ok, status);
457
458     GdipFree(ptf);
459     GdipDeletePen(pen);
460     GdipDeleteGraphics(graphics);
461
462     ReleaseDC(0, hdc);
463 }
464
465 static void test_Get_Release_DC(void)
466 {
467     GpStatus status;
468     GpGraphics *graphics = NULL;
469     GpPen *pen;
470     GpSolidFill *brush;
471     GpPath *path;
472     HDC hdc = GetDC(0);
473     HDC retdc;
474     REAL r;
475     CompositingQuality quality;
476     CompositingMode compmode;
477     InterpolationMode intmode;
478     GpMatrix *m;
479     GpRegion *region;
480     GpUnit unit;
481     PixelOffsetMode offsetmode;
482     SmoothingMode smoothmode;
483     TextRenderingHint texthint;
484     GpPointF ptf[5];
485     GpPoint  pt[5];
486     GpRectF  rectf[2];
487     GpRect   rect[2];
488     GpRegion *clip;
489     INT i;
490     BOOL res;
491
492     pt[0].X = 10;
493     pt[0].Y = 10;
494     pt[1].X = 20;
495     pt[1].Y = 15;
496     pt[2].X = 40;
497     pt[2].Y = 80;
498     pt[3].X = -20;
499     pt[3].Y = 20;
500     pt[4].X = 50;
501     pt[4].Y = 110;
502
503     for(i = 0; i < 5;i++){
504         ptf[i].X = (REAL)pt[i].X;
505         ptf[i].Y = (REAL)pt[i].Y;
506     }
507
508     rect[0].X = 0;
509     rect[0].Y = 0;
510     rect[0].Width  = 50;
511     rect[0].Height = 70;
512     rect[1].X = 0;
513     rect[1].Y = 0;
514     rect[1].Width  = 10;
515     rect[1].Height = 20;
516
517     for(i = 0; i < 2;i++){
518         rectf[i].X = (REAL)rect[i].X;
519         rectf[i].Y = (REAL)rect[i].Y;
520         rectf[i].Height = (REAL)rect[i].Height;
521         rectf[i].Width  = (REAL)rect[i].Width;
522     }
523
524     GdipCreateMatrix(&m);
525     GdipCreateRegion(&region);
526     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
527     GdipCreatePath(FillModeAlternate, &path);
528     GdipCreateRegion(&clip);
529
530     status = GdipCreateFromHDC(hdc, &graphics);
531     expect(Ok, status);
532     ok(graphics != NULL, "Expected graphics to be initialized\n");
533     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
534     expect(Ok, status);
535
536     /* NULL arguments */
537     status = GdipGetDC(NULL, NULL);
538     expect(InvalidParameter, status);
539     status = GdipGetDC(graphics, NULL);
540     expect(InvalidParameter, status);
541     status = GdipGetDC(NULL, &retdc);
542     expect(InvalidParameter, status);
543
544     status = GdipReleaseDC(NULL, NULL);
545     expect(InvalidParameter, status);
546     status = GdipReleaseDC(graphics, NULL);
547     expect(InvalidParameter, status);
548     status = GdipReleaseDC(NULL, (HDC)0xdeadbeef);
549     expect(InvalidParameter, status);
550
551     /* Release without Get */
552     status = GdipReleaseDC(graphics, hdc);
553     expect(InvalidParameter, status);
554
555     retdc = NULL;
556     status = GdipGetDC(graphics, &retdc);
557     expect(Ok, status);
558     ok(retdc == hdc, "Invalid HDC returned\n");
559     /* call it once more */
560     status = GdipGetDC(graphics, &retdc);
561     expect(ObjectBusy, status);
562
563     /* try all Graphics calls here */
564     status = Ok;
565     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
566     expect(ObjectBusy, status); status = Ok;
567     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0.0, 0.0);
568     expect(ObjectBusy, status); status = Ok;
569     status = GdipDrawBezier(graphics, pen, 0.0, 10.0, 20.0, 15.0, 35.0, -10.0, 10.0, 10.0);
570     expect(ObjectBusy, status); status = Ok;
571     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
572     expect(ObjectBusy, status); status = Ok;
573     status = GdipDrawBeziers(graphics, pen, ptf, 5);
574     expect(ObjectBusy, status); status = Ok;
575     status = GdipDrawBeziersI(graphics, pen, pt, 5);
576     expect(ObjectBusy, status); status = Ok;
577     status = GdipDrawClosedCurve(graphics, pen, ptf, 5);
578     expect(ObjectBusy, status); status = Ok;
579     status = GdipDrawClosedCurveI(graphics, pen, pt, 5);
580     expect(ObjectBusy, status); status = Ok;
581     status = GdipDrawClosedCurve2(graphics, pen, ptf, 5, 1.0);
582     expect(ObjectBusy, status); status = Ok;
583     status = GdipDrawClosedCurve2I(graphics, pen, pt, 5, 1.0);
584     expect(ObjectBusy, status); status = Ok;
585     status = GdipDrawCurve(graphics, pen, ptf, 5);
586     expect(ObjectBusy, status); status = Ok;
587     status = GdipDrawCurveI(graphics, pen, pt, 5);
588     expect(ObjectBusy, status); status = Ok;
589     status = GdipDrawCurve2(graphics, pen, ptf, 5, 1.0);
590     expect(ObjectBusy, status); status = Ok;
591     status = GdipDrawCurve2I(graphics, pen, pt, 5, 1.0);
592     expect(ObjectBusy, status); status = Ok;
593     status = GdipDrawEllipse(graphics, pen, 0.0, 0.0, 100.0, 50.0);
594     expect(ObjectBusy, status); status = Ok;
595     status = GdipDrawEllipseI(graphics, pen, 0, 0, 100, 50);
596     expect(ObjectBusy, status); status = Ok;
597     /* GdipDrawImage/GdipDrawImageI */
598     /* GdipDrawImagePointsRect/GdipDrawImagePointsRectI */
599     /* GdipDrawImageRectRect/GdipDrawImageRectRectI */
600     /* GdipDrawImageRect/GdipDrawImageRectI */
601     status = GdipDrawLine(graphics, pen, 0.0, 0.0, 100.0, 200.0);
602     expect(ObjectBusy, status); status = Ok;
603     status = GdipDrawLineI(graphics, pen, 0, 0, 100, 200);
604     expect(ObjectBusy, status); status = Ok;
605     status = GdipDrawLines(graphics, pen, ptf, 5);
606     expect(ObjectBusy, status); status = Ok;
607     status = GdipDrawLinesI(graphics, pen, pt, 5);
608     expect(ObjectBusy, status); status = Ok;
609     status = GdipDrawPath(graphics, pen, path);
610     expect(ObjectBusy, status); status = Ok;
611     status = GdipDrawPie(graphics, pen, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
612     expect(ObjectBusy, status); status = Ok;
613     status = GdipDrawPieI(graphics, pen, 0, 0, 100, 100, 0.0, 90.0);
614     expect(ObjectBusy, status); status = Ok;
615     status = GdipDrawRectangle(graphics, pen, 0.0, 0.0, 100.0, 300.0);
616     expect(ObjectBusy, status); status = Ok;
617     status = GdipDrawRectangleI(graphics, pen, 0, 0, 100, 300);
618     expect(ObjectBusy, status); status = Ok;
619     status = GdipDrawRectangles(graphics, pen, rectf, 2);
620     expect(ObjectBusy, status); status = Ok;
621     status = GdipDrawRectanglesI(graphics, pen, rect, 2);
622     expect(ObjectBusy, status); status = Ok;
623     /* GdipDrawString */
624     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, ptf, 5, 1.0, FillModeAlternate);
625     expect(ObjectBusy, status); status = Ok;
626     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, pt, 5, 1.0, FillModeAlternate);
627     expect(ObjectBusy, status); status = Ok;
628     status = GdipFillEllipse(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
629     expect(ObjectBusy, status); status = Ok;
630     status = GdipFillEllipseI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
631     expect(ObjectBusy, status); status = Ok;
632     status = GdipFillPath(graphics, (GpBrush*)brush, path);
633     expect(ObjectBusy, status); status = Ok;
634     status = GdipFillPie(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0, 0.0, 15.0);
635     expect(ObjectBusy, status); status = Ok;
636     status = GdipFillPieI(graphics, (GpBrush*)brush, 0, 0, 100, 100, 0.0, 15.0);
637     expect(ObjectBusy, status); status = Ok;
638     status = GdipFillPolygon(graphics, (GpBrush*)brush, ptf, 5, FillModeAlternate);
639     expect(ObjectBusy, status); status = Ok;
640     status = GdipFillPolygonI(graphics, (GpBrush*)brush, pt, 5, FillModeAlternate);
641     expect(ObjectBusy, status); status = Ok;
642     status = GdipFillPolygon2(graphics, (GpBrush*)brush, ptf, 5);
643     expect(ObjectBusy, status); status = Ok;
644     status = GdipFillPolygon2I(graphics, (GpBrush*)brush, pt, 5);
645     expect(ObjectBusy, status); status = Ok;
646     status = GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
647     expect(ObjectBusy, status); status = Ok;
648     status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
649     expect(ObjectBusy, status); status = Ok;
650     status = GdipFillRectangles(graphics, (GpBrush*)brush, rectf, 2);
651     expect(ObjectBusy, status); status = Ok;
652     status = GdipFillRectanglesI(graphics, (GpBrush*)brush, rect, 2);
653     expect(ObjectBusy, status); status = Ok;
654     status = GdipFillRegion(graphics, (GpBrush*)brush, region);
655     expect(ObjectBusy, status); status = Ok;
656     status = GdipFlush(graphics, FlushIntentionFlush);
657     expect(ObjectBusy, status); status = Ok;
658     status = GdipGetCompositingMode(graphics, &compmode);
659     expect(ObjectBusy, status); status = Ok;
660     status = GdipGetCompositingQuality(graphics, &quality);
661     expect(ObjectBusy, status); status = Ok;
662     status = GdipGetInterpolationMode(graphics, &intmode);
663     expect(ObjectBusy, status); status = Ok;
664     status = GdipGetPageScale(graphics, &r);
665     expect(ObjectBusy, status); status = Ok;
666     status = GdipGetPageUnit(graphics, &unit);
667     expect(ObjectBusy, status); status = Ok;
668     status = GdipGetPixelOffsetMode(graphics, &offsetmode);
669     expect(ObjectBusy, status); status = Ok;
670     status = GdipGetSmoothingMode(graphics, &smoothmode);
671     expect(ObjectBusy, status); status = Ok;
672     status = GdipGetTextRenderingHint(graphics, &texthint);
673     expect(ObjectBusy, status); status = Ok;
674     status = GdipGetWorldTransform(graphics, m);
675     expect(ObjectBusy, status); status = Ok;
676     status = GdipGraphicsClear(graphics, 0xdeadbeef);
677     expect(ObjectBusy, status); status = Ok;
678     status = GdipIsVisiblePoint(graphics, 0.0, 0.0, &res);
679     expect(ObjectBusy, status); status = Ok;
680     status = GdipIsVisiblePointI(graphics, 0, 0, &res);
681     expect(ObjectBusy, status); status = Ok;
682     /* GdipMeasureCharacterRanges */
683     /* GdipMeasureString */
684     status = GdipResetClip(graphics);
685     expect(ObjectBusy, status); status = Ok;
686     status = GdipResetWorldTransform(graphics);
687     expect(ObjectBusy, status); status = Ok;
688     /* GdipRestoreGraphics */
689     status = GdipRotateWorldTransform(graphics, 15.0, MatrixOrderPrepend);
690     expect(ObjectBusy, status); status = Ok;
691     /*  GdipSaveGraphics */
692     status = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
693     expect(ObjectBusy, status); status = Ok;
694     status = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
695     expect(ObjectBusy, status); status = Ok;
696     status = GdipSetCompositingQuality(graphics, CompositingQualityDefault);
697     expect(ObjectBusy, status); status = Ok;
698     status = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
699     expect(ObjectBusy, status); status = Ok;
700     status = GdipSetPageScale(graphics, 1.0);
701     expect(ObjectBusy, status); status = Ok;
702     status = GdipSetPageUnit(graphics, UnitWorld);
703     expect(ObjectBusy, status); status = Ok;
704     status = GdipSetPixelOffsetMode(graphics, PixelOffsetModeDefault);
705     expect(ObjectBusy, status); status = Ok;
706     status = GdipSetSmoothingMode(graphics, SmoothingModeDefault);
707     expect(ObjectBusy, status); status = Ok;
708     status = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
709     expect(ObjectBusy, status); status = Ok;
710     status = GdipSetWorldTransform(graphics, m);
711     expect(ObjectBusy, status); status = Ok;
712     status = GdipTranslateWorldTransform(graphics, 0.0, 0.0, MatrixOrderPrepend);
713     expect(ObjectBusy, status); status = Ok;
714     status = GdipSetClipPath(graphics, path, CombineModeReplace);
715     expect(ObjectBusy, status); status = Ok;
716     status = GdipSetClipRect(graphics, 0.0, 0.0, 10.0, 10.0, CombineModeReplace);
717     expect(ObjectBusy, status); status = Ok;
718     status = GdipSetClipRectI(graphics, 0, 0, 10, 10, CombineModeReplace);
719     expect(ObjectBusy, status); status = Ok;
720     status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
721     expect(ObjectBusy, status);
722     status = GdipDrawPolygon(graphics, pen, ptf, 5);
723     expect(ObjectBusy, status); status = Ok;
724     status = GdipDrawPolygonI(graphics, pen, pt, 5);
725     expect(ObjectBusy, status); status = Ok;
726     status = GdipGetDpiX(graphics, &r);
727     expect(ObjectBusy, status); status = Ok;
728     status = GdipGetDpiY(graphics, &r);
729     expect(ObjectBusy, status); status = Ok;
730     status = GdipMultiplyWorldTransform(graphics, m, MatrixOrderPrepend);
731     status = GdipGetClip(graphics, region);
732     expect(ObjectBusy, status); status = Ok;
733     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 5);
734     expect(ObjectBusy, status); status = Ok;
735     /* try to delete before release */
736     status = GdipDeleteGraphics(graphics);
737     expect(ObjectBusy, status);
738
739     status = GdipReleaseDC(graphics, retdc);
740     expect(Ok, status);
741
742     GdipDeletePen(pen);
743     GdipDeleteGraphics(graphics);
744
745     GdipDeletePath(path);
746     GdipDeleteBrush((GpBrush*)brush);
747     GdipDeleteRegion(region);
748     GdipDeleteMatrix(m);
749     GdipDeleteRegion(region);
750
751     ReleaseDC(0, hdc);
752 }
753
754 static void test_transformpoints(void)
755 {
756     GpStatus status;
757     GpGraphics *graphics = NULL;
758     HDC hdc = GetDC(0);
759     GpPointF ptf[5];
760     INT i;
761
762     status = GdipCreateFromHDC(hdc, &graphics);
763     expect(Ok, status);
764
765     for(i = 0; i < 5; i++){
766         ptf[i].X = 200.0 + i * 50.0 * (i % 2);
767         ptf[i].Y = 200.0 + i * 50.0 * !(i % 2);
768     }
769
770     /* NULL arguments */
771     status = GdipTransformPoints(NULL, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
772     expect(InvalidParameter, status);
773     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
774     expect(InvalidParameter, status);
775     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 0);
776     expect(InvalidParameter, status);
777     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, -1);
778     expect(InvalidParameter, status);
779
780     GdipDeleteGraphics(graphics);
781     ReleaseDC(0, hdc);
782 }
783
784 static void test_get_set_clip(void)
785 {
786     GpStatus status;
787     GpGraphics *graphics = NULL;
788     HDC hdc = GetDC(0);
789     GpRegion *clip;
790     GpRectF rect;
791     BOOL res;
792
793     status = GdipCreateFromHDC(hdc, &graphics);
794     expect(Ok, status);
795
796     rect.X = rect.Y = 0.0;
797     rect.Height = rect.Width = 100.0;
798
799     status = GdipCreateRegionRect(&rect, &clip);
800
801     /* NULL arguments */
802     status = GdipGetClip(NULL, NULL);
803     expect(InvalidParameter, status);
804     status = GdipGetClip(graphics, NULL);
805     expect(InvalidParameter, status);
806     status = GdipGetClip(NULL, clip);
807     expect(InvalidParameter, status);
808
809     status = GdipSetClipRegion(NULL, NULL, CombineModeReplace);
810     expect(InvalidParameter, status);
811     status = GdipSetClipRegion(graphics, NULL, CombineModeReplace);
812     expect(InvalidParameter, status);
813
814     status = GdipSetClipPath(NULL, NULL, CombineModeReplace);
815     expect(InvalidParameter, status);
816     status = GdipSetClipPath(graphics, NULL, CombineModeReplace);
817     expect(InvalidParameter, status);
818
819     res = FALSE;
820     status = GdipGetClip(graphics, clip);
821     expect(Ok, status);
822     status = GdipIsInfiniteRegion(clip, graphics, &res);
823     expect(Ok, status);
824     expect(TRUE, res);
825
826     /* remains infinite after reset */
827     res = FALSE;
828     status = GdipResetClip(graphics);
829     expect(Ok, status);
830     status = GdipGetClip(graphics, clip);
831     expect(Ok, status);
832     status = GdipIsInfiniteRegion(clip, graphics, &res);
833     expect(Ok, status);
834     expect(TRUE, res);
835
836     /* set to empty and then reset to infinite */
837     status = GdipSetEmpty(clip);
838     expect(Ok, status);
839     status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
840     expect(Ok, status);
841
842     status = GdipGetClip(graphics, clip);
843     expect(Ok, status);
844     res = FALSE;
845     status = GdipIsEmptyRegion(clip, graphics, &res);
846     expect(Ok, status);
847     expect(TRUE, res);
848     status = GdipResetClip(graphics);
849     expect(Ok, status);
850     status = GdipGetClip(graphics, clip);
851     expect(Ok, status);
852     res = FALSE;
853     status = GdipIsInfiniteRegion(clip, graphics, &res);
854     expect(Ok, status);
855     expect(TRUE, res);
856
857     GdipDeleteRegion(clip);
858
859     GdipDeleteGraphics(graphics);
860     ReleaseDC(0, hdc);
861 }
862
863 static void test_isempty(void)
864 {
865     GpStatus status;
866     GpGraphics *graphics = NULL;
867     HDC hdc = GetDC(0);
868     GpRegion *clip;
869     BOOL res;
870
871     status = GdipCreateFromHDC(hdc, &graphics);
872     expect(Ok, status);
873
874     status = GdipCreateRegion(&clip);
875     expect(Ok, status);
876
877     /* NULL */
878     status = GdipIsClipEmpty(NULL, NULL);
879     expect(InvalidParameter, status);
880     status = GdipIsClipEmpty(graphics, NULL);
881     expect(InvalidParameter, status);
882     status = GdipIsClipEmpty(NULL, &res);
883     expect(InvalidParameter, status);
884
885     /* default is infinite */
886     res = TRUE;
887     status = GdipIsClipEmpty(graphics, &res);
888     expect(Ok, status);
889     expect(FALSE, res);
890
891     GdipDeleteRegion(clip);
892
893     GdipDeleteGraphics(graphics);
894     ReleaseDC(0, hdc);
895 }
896
897 static void test_clear(void)
898 {
899     GpStatus status;
900
901     status = GdipGraphicsClear(NULL, 0xdeadbeef);
902     expect(InvalidParameter, status);
903 }
904
905 START_TEST(graphics)
906 {
907     struct GdiplusStartupInput gdiplusStartupInput;
908     ULONG_PTR gdiplusToken;
909
910     gdiplusStartupInput.GdiplusVersion              = 1;
911     gdiplusStartupInput.DebugEventCallback          = NULL;
912     gdiplusStartupInput.SuppressBackgroundThread    = 0;
913     gdiplusStartupInput.SuppressExternalCodecs      = 0;
914
915     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
916
917     test_constructor_destructor();
918     test_save_restore();
919     test_GdipDrawBezierI();
920     test_GdipDrawArc();
921     test_GdipDrawArcI();
922     test_GdipDrawLineI();
923     test_GdipDrawLinesI();
924     test_Get_Release_DC();
925     test_transformpoints();
926     test_get_set_clip();
927     test_isempty();
928     test_clear();
929
930     GdiplusShutdown(gdiplusToken);
931 }