user32/tests: Fix the listbox delete test on NT4.
[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 #include <math.h>
26
27 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
28 #define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
29 #define TABLE_LEN (23)
30
31 static void test_constructor_destructor(void)
32 {
33     GpStatus stat;
34     GpGraphics *graphics = NULL;
35     HDC hdc = GetDC(0);
36
37     stat = GdipCreateFromHDC(NULL, &graphics);
38     expect(OutOfMemory, stat);
39     stat = GdipDeleteGraphics(graphics);
40     expect(InvalidParameter, stat);
41
42     stat = GdipCreateFromHDC(hdc, &graphics);
43     expect(Ok, stat);
44     stat = GdipDeleteGraphics(graphics);
45     expect(Ok, stat);
46
47     stat = GdipCreateFromHWND(NULL, &graphics);
48     expect(Ok, stat);
49     stat = GdipDeleteGraphics(graphics);
50     expect(Ok, stat);
51
52     stat = GdipCreateFromHWNDICM(NULL, &graphics);
53     expect(Ok, stat);
54     stat = GdipDeleteGraphics(graphics);
55     expect(Ok, stat);
56
57     stat = GdipDeleteGraphics(NULL);
58     expect(InvalidParameter, stat);
59     ReleaseDC(0, hdc);
60 }
61
62 typedef struct node{
63     GraphicsState data;
64     struct node * next;
65 } node;
66
67 /* Linked list prepend function. */
68 static void log_state(GraphicsState data, node ** log)
69 {
70     node * new_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(node));
71
72     new_entry->data = data;
73     new_entry->next = *log;
74     *log = new_entry;
75 }
76
77 /* Checks if there are duplicates in the list, and frees it. */
78 static void check_no_duplicates(node * log)
79 {
80     INT dups = 0;
81     node * temp = NULL;
82     node * temp2 = NULL;
83     node * orig = log;
84
85     if(!log)
86         goto end;
87
88     do{
89         temp = log;
90         while((temp = temp->next)){
91             if(log->data == temp->data){
92                 dups++;
93                 break;
94             }
95             if(dups > 0)
96                 break;
97         }
98     }while((log = log->next));
99
100     temp = orig;
101     do{
102         temp2 = temp->next;
103         HeapFree(GetProcessHeap(), 0, temp);
104         temp = temp2;
105     }while(temp);
106
107 end:
108     expect(0, dups);
109 }
110
111 static void test_save_restore(void)
112 {
113     GpStatus stat;
114     GraphicsState state_a, state_b, state_c;
115     InterpolationMode mode;
116     GpGraphics *graphics1, *graphics2;
117     node * state_log = NULL;
118     HDC hdc = GetDC(0);
119     state_a = state_b = state_c = 0xdeadbeef;
120
121     /* Invalid saving. */
122     GdipCreateFromHDC(hdc, &graphics1);
123     stat = GdipSaveGraphics(graphics1, NULL);
124     expect(InvalidParameter, stat);
125     stat = GdipSaveGraphics(NULL, &state_a);
126     expect(InvalidParameter, stat);
127     GdipDeleteGraphics(graphics1);
128
129     log_state(state_a, &state_log);
130
131     /* Basic save/restore. */
132     GdipCreateFromHDC(hdc, &graphics1);
133     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
134     stat = GdipSaveGraphics(graphics1, &state_a);
135     expect(Ok, stat);
136     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
137     stat = GdipRestoreGraphics(graphics1, state_a);
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     expect(Ok, stat);
155     GdipRestoreGraphics(graphics1, state_b);
156     GdipGetInterpolationMode(graphics1, &mode);
157     todo_wine
158         expect(InterpolationModeBicubic, mode);
159     GdipRestoreGraphics(graphics1, state_a);
160     GdipGetInterpolationMode(graphics1, &mode);
161     todo_wine
162         expect(InterpolationModeBilinear, mode);
163     GdipDeleteGraphics(graphics1);
164
165     log_state(state_a, &state_log);
166     log_state(state_b, &state_log);
167
168     /* Restoring older state invalidates newer saves (but not older saves). */
169     GdipCreateFromHDC(hdc, &graphics1);
170     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
171     GdipSaveGraphics(graphics1, &state_a);
172     GdipSetInterpolationMode(graphics1, InterpolationModeBicubic);
173     GdipSaveGraphics(graphics1, &state_b);
174     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
175     GdipSaveGraphics(graphics1, &state_c);
176     GdipSetInterpolationMode(graphics1, InterpolationModeHighQualityBilinear);
177     GdipRestoreGraphics(graphics1, state_b);
178     GdipGetInterpolationMode(graphics1, &mode);
179     todo_wine
180         expect(InterpolationModeBicubic, mode);
181     GdipRestoreGraphics(graphics1, state_c);
182     GdipGetInterpolationMode(graphics1, &mode);
183     todo_wine
184         expect(InterpolationModeBicubic, mode);
185     GdipRestoreGraphics(graphics1, state_a);
186     GdipGetInterpolationMode(graphics1, &mode);
187     todo_wine
188         expect(InterpolationModeBilinear, mode);
189     GdipDeleteGraphics(graphics1);
190
191     log_state(state_a, &state_log);
192     log_state(state_b, &state_log);
193     log_state(state_c, &state_log);
194
195     /* Restoring older save from one graphics object does not invalidate
196      * newer save from other graphics object. */
197     GdipCreateFromHDC(hdc, &graphics1);
198     GdipCreateFromHDC(hdc, &graphics2);
199     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
200     GdipSaveGraphics(graphics1, &state_a);
201     GdipSetInterpolationMode(graphics2, InterpolationModeBicubic);
202     GdipSaveGraphics(graphics2, &state_b);
203     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
204     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
205     GdipRestoreGraphics(graphics1, state_a);
206     GdipGetInterpolationMode(graphics1, &mode);
207     todo_wine
208         expect(InterpolationModeBilinear, mode);
209     GdipRestoreGraphics(graphics2, state_b);
210     GdipGetInterpolationMode(graphics2, &mode);
211     todo_wine
212         expect(InterpolationModeBicubic, mode);
213     GdipDeleteGraphics(graphics1);
214     GdipDeleteGraphics(graphics2);
215
216     /* You can't restore a state to a graphics object that didn't save it. */
217     GdipCreateFromHDC(hdc, &graphics1);
218     GdipCreateFromHDC(hdc, &graphics2);
219     GdipSetInterpolationMode(graphics1, InterpolationModeBilinear);
220     GdipSaveGraphics(graphics1, &state_a);
221     GdipSetInterpolationMode(graphics1, InterpolationModeNearestNeighbor);
222     GdipSetInterpolationMode(graphics2, InterpolationModeNearestNeighbor);
223     GdipRestoreGraphics(graphics2, state_a);
224     GdipGetInterpolationMode(graphics2, &mode);
225     expect(InterpolationModeNearestNeighbor, mode);
226     GdipDeleteGraphics(graphics1);
227     GdipDeleteGraphics(graphics2);
228
229     log_state(state_a, &state_log);
230
231     /* The same state value should never be returned twice. */
232     todo_wine
233         check_no_duplicates(state_log);
234
235     ReleaseDC(0, hdc);
236 }
237
238 static void test_GdipDrawArc(void)
239 {
240     GpStatus status;
241     GpGraphics *graphics = NULL;
242     GpPen *pen = NULL;
243     HDC hdc = GetDC(0);
244
245     /* make a graphics object and pen object */
246     status = GdipCreateFromHDC(hdc, &graphics);
247     expect(Ok, status);
248     ok(hdc != NULL, "Expected HDC to be initialized\n");
249
250     status = GdipCreateFromHDC(hdc, &graphics);
251     expect(Ok, status);
252     ok(graphics != NULL, "Expected graphics to be initialized\n");
253
254     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
255     expect(Ok, status);
256     ok(pen != NULL, "Expected pen to be initialized\n");
257
258     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
259     status = GdipDrawArc(NULL, NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
260     expect(InvalidParameter, status);
261
262     status = GdipDrawArc(graphics, NULL, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
263     expect(InvalidParameter, status);
264
265     status = GdipDrawArc(NULL, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
266     expect(InvalidParameter, status);
267
268     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);
269     expect(InvalidParameter, status);
270
271     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0);
272     expect(InvalidParameter, status);
273
274     /* successful case */
275     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
276     expect(Ok, status);
277
278     GdipDeletePen(pen);
279     GdipDeleteGraphics(graphics);
280
281     ReleaseDC(0, hdc);
282 }
283
284 static void test_GdipDrawArcI(void)
285 {
286     GpStatus status;
287     GpGraphics *graphics = NULL;
288     GpPen *pen = NULL;
289     HDC hdc = GetDC(0);
290
291     /* make a graphics object and pen object */
292     status = GdipCreateFromHDC(hdc, &graphics);
293     expect(Ok, status);
294     ok(hdc != NULL, "Expected HDC to be initialized\n");
295
296     status = GdipCreateFromHDC(hdc, &graphics);
297     expect(Ok, status);
298     ok(graphics != NULL, "Expected graphics to be initialized\n");
299
300     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
301     expect(Ok, status);
302     ok(pen != NULL, "Expected pen to be initialized\n");
303
304     /* InvalidParameter cases: null graphics, null pen, non-positive width, non-positive height */
305     status = GdipDrawArcI(NULL, NULL, 0, 0, 0, 0, 0, 0);
306     expect(InvalidParameter, status);
307
308     status = GdipDrawArcI(graphics, NULL, 0, 0, 1, 1, 0, 0);
309     expect(InvalidParameter, status);
310
311     status = GdipDrawArcI(NULL, pen, 0, 0, 1, 1, 0, 0);
312     expect(InvalidParameter, status);
313
314     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 0, 0, 0);
315     expect(InvalidParameter, status);
316
317     status = GdipDrawArcI(graphics, pen, 0, 0, 0, 1, 0, 0);
318     expect(InvalidParameter, status);
319
320     /* successful case */
321     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0, 0);
322     expect(Ok, status);
323
324     GdipDeletePen(pen);
325     GdipDeleteGraphics(graphics);
326
327     ReleaseDC(0, hdc);
328 }
329
330 static void test_GdipDrawBezierI(void)
331 {
332     GpStatus status;
333     GpGraphics *graphics = NULL;
334     GpPen *pen = NULL;
335     HDC hdc = GetDC(0);
336
337     /* make a graphics object and pen object */
338     status = GdipCreateFromHDC(hdc, &graphics);
339     expect(Ok, status);
340     ok(hdc != NULL, "Expected HDC to be initialized\n");
341
342     status = GdipCreateFromHDC(hdc, &graphics);
343     expect(Ok, status);
344     ok(graphics != NULL, "Expected graphics to be initialized\n");
345
346     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
347     expect(Ok, status);
348     ok(pen != NULL, "Expected pen to be initialized\n");
349
350     /* InvalidParameter cases: null graphics, null pen */
351     status = GdipDrawBezierI(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
352     expect(InvalidParameter, status);
353
354     status = GdipDrawBezierI(graphics, NULL, 0, 0, 0, 0, 0, 0, 0, 0);
355     expect(InvalidParameter, status);
356
357     status = GdipDrawBezierI(NULL, pen, 0, 0, 0, 0, 0, 0, 0, 0);
358     expect(InvalidParameter, status);
359
360     /* successful case */
361     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
362     expect(Ok, status);
363
364     GdipDeletePen(pen);
365     GdipDeleteGraphics(graphics);
366
367     ReleaseDC(0, hdc);
368 }
369
370 static void test_GdipDrawLineI(void)
371 {
372     GpStatus status;
373     GpGraphics *graphics = NULL;
374     GpPen *pen = NULL;
375     HDC hdc = GetDC(0);
376
377     /* make a graphics object and pen object */
378     status = GdipCreateFromHDC(hdc, &graphics);
379     expect(Ok, status);
380     ok(hdc != NULL, "Expected HDC to be initialized\n");
381
382     status = GdipCreateFromHDC(hdc, &graphics);
383     expect(Ok, status);
384     ok(graphics != NULL, "Expected graphics to be initialized\n");
385
386     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
387     expect(Ok, status);
388     ok(pen != NULL, "Expected pen to be initialized\n");
389
390     /* InvalidParameter cases: null graphics, null pen */
391     status = GdipDrawLineI(NULL, NULL, 0, 0, 0, 0);
392     expect(InvalidParameter, status);
393
394     status = GdipDrawLineI(graphics, NULL, 0, 0, 0, 0);
395     expect(InvalidParameter, status);
396
397     status = GdipDrawLineI(NULL, pen, 0, 0, 0, 0);
398     expect(InvalidParameter, status);
399
400     /* successful case */
401     status = GdipDrawLineI(graphics, pen, 0, 0, 0, 0);
402     expect(Ok, status);
403
404     GdipDeletePen(pen);
405     GdipDeleteGraphics(graphics);
406
407     ReleaseDC(0, hdc);
408 }
409
410 static void test_GdipDrawLinesI(void)
411 {
412     GpStatus status;
413     GpGraphics *graphics = NULL;
414     GpPen *pen = NULL;
415     GpPoint *ptf = NULL;
416     HDC hdc = GetDC(0);
417
418     /* make a graphics object and pen object */
419     status = GdipCreateFromHDC(hdc, &graphics);
420     expect(Ok, status);
421     ok(hdc != NULL, "Expected HDC to be initialized\n");
422
423     status = GdipCreateFromHDC(hdc, &graphics);
424     expect(Ok, status);
425     ok(graphics != NULL, "Expected graphics to be initialized\n");
426
427     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
428     expect(Ok, status);
429     ok(pen != NULL, "Expected pen to be initialized\n");
430
431     /* make some arbitrary valid points*/
432     ptf = GdipAlloc(2 * sizeof(GpPointF));
433
434     ptf[0].X = 1;
435     ptf[0].Y = 1;
436
437     ptf[1].X = 2;
438     ptf[1].Y = 2;
439
440     /* InvalidParameter cases: null graphics, null pen, null points, count < 2*/
441     status = GdipDrawLinesI(NULL, NULL, NULL, 0);
442     expect(InvalidParameter, status);
443
444     status = GdipDrawLinesI(graphics, pen, ptf, 0);
445     expect(InvalidParameter, status);
446
447     status = GdipDrawLinesI(graphics, NULL, ptf, 2);
448     expect(InvalidParameter, status);
449
450     status = GdipDrawLinesI(NULL, pen, ptf, 2);
451     expect(InvalidParameter, status);
452
453     /* successful case */
454     status = GdipDrawLinesI(graphics, pen, ptf, 2);
455     expect(Ok, status);
456
457     GdipFree(ptf);
458     GdipDeletePen(pen);
459     GdipDeleteGraphics(graphics);
460
461     ReleaseDC(0, hdc);
462 }
463
464 static void test_Get_Release_DC(void)
465 {
466     GpStatus status;
467     GpGraphics *graphics = NULL;
468     GpPen *pen;
469     GpSolidFill *brush;
470     GpPath *path;
471     HDC hdc = GetDC(0);
472     HDC retdc;
473     REAL r;
474     CompositingQuality quality;
475     CompositingMode compmode;
476     InterpolationMode intmode;
477     GpMatrix *m;
478     GpRegion *region;
479     GpUnit unit;
480     PixelOffsetMode offsetmode;
481     SmoothingMode smoothmode;
482     TextRenderingHint texthint;
483     GpPointF ptf[5];
484     GpPoint  pt[5];
485     GpRectF  rectf[2];
486     GpRect   rect[2];
487     GpRegion *clip;
488     INT i;
489     BOOL res;
490     ARGB color = 0x00000000;
491     HRGN hrgn = CreateRectRgn(0, 0, 10, 10);
492
493     pt[0].X = 10;
494     pt[0].Y = 10;
495     pt[1].X = 20;
496     pt[1].Y = 15;
497     pt[2].X = 40;
498     pt[2].Y = 80;
499     pt[3].X = -20;
500     pt[3].Y = 20;
501     pt[4].X = 50;
502     pt[4].Y = 110;
503
504     for(i = 0; i < 5;i++){
505         ptf[i].X = (REAL)pt[i].X;
506         ptf[i].Y = (REAL)pt[i].Y;
507     }
508
509     rect[0].X = 0;
510     rect[0].Y = 0;
511     rect[0].Width  = 50;
512     rect[0].Height = 70;
513     rect[1].X = 0;
514     rect[1].Y = 0;
515     rect[1].Width  = 10;
516     rect[1].Height = 20;
517
518     for(i = 0; i < 2;i++){
519         rectf[i].X = (REAL)rect[i].X;
520         rectf[i].Y = (REAL)rect[i].Y;
521         rectf[i].Height = (REAL)rect[i].Height;
522         rectf[i].Width  = (REAL)rect[i].Width;
523     }
524
525     GdipCreateMatrix(&m);
526     GdipCreateRegion(&region);
527     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
528     GdipCreatePath(FillModeAlternate, &path);
529     GdipCreateRegion(&clip);
530
531     status = GdipCreateFromHDC(hdc, &graphics);
532     expect(Ok, status);
533     ok(graphics != NULL, "Expected graphics to be initialized\n");
534     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
535     expect(Ok, status);
536
537     /* NULL arguments */
538     status = GdipGetDC(NULL, NULL);
539     expect(InvalidParameter, status);
540     status = GdipGetDC(graphics, NULL);
541     expect(InvalidParameter, status);
542     status = GdipGetDC(NULL, &retdc);
543     expect(InvalidParameter, status);
544
545     status = GdipReleaseDC(NULL, NULL);
546     expect(InvalidParameter, status);
547     status = GdipReleaseDC(graphics, NULL);
548     expect(InvalidParameter, status);
549     status = GdipReleaseDC(NULL, (HDC)0xdeadbeef);
550     expect(InvalidParameter, status);
551
552     /* Release without Get */
553     status = GdipReleaseDC(graphics, hdc);
554     expect(InvalidParameter, status);
555
556     retdc = NULL;
557     status = GdipGetDC(graphics, &retdc);
558     expect(Ok, status);
559     ok(retdc == hdc, "Invalid HDC returned\n");
560     /* call it once more */
561     status = GdipGetDC(graphics, &retdc);
562     expect(ObjectBusy, status);
563
564     /* try all Graphics calls here */
565     status = Ok;
566     status = GdipDrawArc(graphics, pen, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0);
567     expect(ObjectBusy, status); status = Ok;
568     status = GdipDrawArcI(graphics, pen, 0, 0, 1, 1, 0.0, 0.0);
569     expect(ObjectBusy, status); status = Ok;
570     status = GdipDrawBezier(graphics, pen, 0.0, 10.0, 20.0, 15.0, 35.0, -10.0, 10.0, 10.0);
571     expect(ObjectBusy, status); status = Ok;
572     status = GdipDrawBezierI(graphics, pen, 0, 0, 0, 0, 0, 0, 0, 0);
573     expect(ObjectBusy, status); status = Ok;
574     status = GdipDrawBeziers(graphics, pen, ptf, 5);
575     expect(ObjectBusy, status); status = Ok;
576     status = GdipDrawBeziersI(graphics, pen, pt, 5);
577     expect(ObjectBusy, status); status = Ok;
578     status = GdipDrawClosedCurve(graphics, pen, ptf, 5);
579     expect(ObjectBusy, status); status = Ok;
580     status = GdipDrawClosedCurveI(graphics, pen, pt, 5);
581     expect(ObjectBusy, status); status = Ok;
582     status = GdipDrawClosedCurve2(graphics, pen, ptf, 5, 1.0);
583     expect(ObjectBusy, status); status = Ok;
584     status = GdipDrawClosedCurve2I(graphics, pen, pt, 5, 1.0);
585     expect(ObjectBusy, status); status = Ok;
586     status = GdipDrawCurve(graphics, pen, ptf, 5);
587     expect(ObjectBusy, status); status = Ok;
588     status = GdipDrawCurveI(graphics, pen, pt, 5);
589     expect(ObjectBusy, status); status = Ok;
590     status = GdipDrawCurve2(graphics, pen, ptf, 5, 1.0);
591     expect(ObjectBusy, status); status = Ok;
592     status = GdipDrawCurve2I(graphics, pen, pt, 5, 1.0);
593     expect(ObjectBusy, status); status = Ok;
594     status = GdipDrawEllipse(graphics, pen, 0.0, 0.0, 100.0, 50.0);
595     expect(ObjectBusy, status); status = Ok;
596     status = GdipDrawEllipseI(graphics, pen, 0, 0, 100, 50);
597     expect(ObjectBusy, status); status = Ok;
598     /* GdipDrawImage/GdipDrawImageI */
599     /* GdipDrawImagePointsRect/GdipDrawImagePointsRectI */
600     /* GdipDrawImageRectRect/GdipDrawImageRectRectI */
601     /* GdipDrawImageRect/GdipDrawImageRectI */
602     status = GdipDrawLine(graphics, pen, 0.0, 0.0, 100.0, 200.0);
603     expect(ObjectBusy, status); status = Ok;
604     status = GdipDrawLineI(graphics, pen, 0, 0, 100, 200);
605     expect(ObjectBusy, status); status = Ok;
606     status = GdipDrawLines(graphics, pen, ptf, 5);
607     expect(ObjectBusy, status); status = Ok;
608     status = GdipDrawLinesI(graphics, pen, pt, 5);
609     expect(ObjectBusy, status); status = Ok;
610     status = GdipDrawPath(graphics, pen, path);
611     expect(ObjectBusy, status); status = Ok;
612     status = GdipDrawPie(graphics, pen, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
613     expect(ObjectBusy, status); status = Ok;
614     status = GdipDrawPieI(graphics, pen, 0, 0, 100, 100, 0.0, 90.0);
615     expect(ObjectBusy, status); status = Ok;
616     status = GdipDrawRectangle(graphics, pen, 0.0, 0.0, 100.0, 300.0);
617     expect(ObjectBusy, status); status = Ok;
618     status = GdipDrawRectangleI(graphics, pen, 0, 0, 100, 300);
619     expect(ObjectBusy, status); status = Ok;
620     status = GdipDrawRectangles(graphics, pen, rectf, 2);
621     expect(ObjectBusy, status); status = Ok;
622     status = GdipDrawRectanglesI(graphics, pen, rect, 2);
623     expect(ObjectBusy, status); status = Ok;
624     /* GdipDrawString */
625     status = GdipFillClosedCurve2(graphics, (GpBrush*)brush, ptf, 5, 1.0, FillModeAlternate);
626     expect(ObjectBusy, status); status = Ok;
627     status = GdipFillClosedCurve2I(graphics, (GpBrush*)brush, pt, 5, 1.0, FillModeAlternate);
628     expect(ObjectBusy, status); status = Ok;
629     status = GdipFillEllipse(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
630     expect(ObjectBusy, status); status = Ok;
631     status = GdipFillEllipseI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
632     expect(ObjectBusy, status); status = Ok;
633     status = GdipFillPath(graphics, (GpBrush*)brush, path);
634     expect(ObjectBusy, status); status = Ok;
635     status = GdipFillPie(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0, 0.0, 15.0);
636     expect(ObjectBusy, status); status = Ok;
637     status = GdipFillPieI(graphics, (GpBrush*)brush, 0, 0, 100, 100, 0.0, 15.0);
638     expect(ObjectBusy, status); status = Ok;
639     status = GdipFillPolygon(graphics, (GpBrush*)brush, ptf, 5, FillModeAlternate);
640     expect(ObjectBusy, status); status = Ok;
641     status = GdipFillPolygonI(graphics, (GpBrush*)brush, pt, 5, FillModeAlternate);
642     expect(ObjectBusy, status); status = Ok;
643     status = GdipFillPolygon2(graphics, (GpBrush*)brush, ptf, 5);
644     expect(ObjectBusy, status); status = Ok;
645     status = GdipFillPolygon2I(graphics, (GpBrush*)brush, pt, 5);
646     expect(ObjectBusy, status); status = Ok;
647     status = GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, 100.0, 100.0);
648     expect(ObjectBusy, status); status = Ok;
649     status = GdipFillRectangleI(graphics, (GpBrush*)brush, 0, 0, 100, 100);
650     expect(ObjectBusy, status); status = Ok;
651     status = GdipFillRectangles(graphics, (GpBrush*)brush, rectf, 2);
652     expect(ObjectBusy, status); status = Ok;
653     status = GdipFillRectanglesI(graphics, (GpBrush*)brush, rect, 2);
654     expect(ObjectBusy, status); status = Ok;
655     status = GdipFillRegion(graphics, (GpBrush*)brush, region);
656     expect(ObjectBusy, status); status = Ok;
657     status = GdipFlush(graphics, FlushIntentionFlush);
658     expect(ObjectBusy, status); status = Ok;
659     status = GdipGetClipBounds(graphics, rectf);
660     expect(ObjectBusy, status); status = Ok;
661     status = GdipGetClipBoundsI(graphics, rect);
662     expect(ObjectBusy, status); status = Ok;
663     status = GdipGetCompositingMode(graphics, &compmode);
664     expect(ObjectBusy, status); status = Ok;
665     status = GdipGetCompositingQuality(graphics, &quality);
666     expect(ObjectBusy, status); status = Ok;
667     status = GdipGetInterpolationMode(graphics, &intmode);
668     expect(ObjectBusy, status); status = Ok;
669     status = GdipGetNearestColor(graphics, &color);
670     expect(ObjectBusy, status); status = Ok;
671     status = GdipGetPageScale(graphics, &r);
672     expect(ObjectBusy, status); status = Ok;
673     status = GdipGetPageUnit(graphics, &unit);
674     expect(ObjectBusy, status); status = Ok;
675     status = GdipGetPixelOffsetMode(graphics, &offsetmode);
676     expect(ObjectBusy, status); status = Ok;
677     status = GdipGetSmoothingMode(graphics, &smoothmode);
678     expect(ObjectBusy, status); status = Ok;
679     status = GdipGetTextRenderingHint(graphics, &texthint);
680     expect(ObjectBusy, status); status = Ok;
681     status = GdipGetWorldTransform(graphics, m);
682     expect(ObjectBusy, status); status = Ok;
683     status = GdipGraphicsClear(graphics, 0xdeadbeef);
684     expect(ObjectBusy, status); status = Ok;
685     status = GdipIsVisiblePoint(graphics, 0.0, 0.0, &res);
686     expect(ObjectBusy, status); status = Ok;
687     status = GdipIsVisiblePointI(graphics, 0, 0, &res);
688     expect(ObjectBusy, status); status = Ok;
689     /* GdipMeasureCharacterRanges */
690     /* GdipMeasureString */
691     status = GdipResetClip(graphics);
692     expect(ObjectBusy, status); status = Ok;
693     status = GdipResetWorldTransform(graphics);
694     expect(ObjectBusy, status); status = Ok;
695     /* GdipRestoreGraphics */
696     status = GdipRotateWorldTransform(graphics, 15.0, MatrixOrderPrepend);
697     expect(ObjectBusy, status); status = Ok;
698     /*  GdipSaveGraphics */
699     status = GdipScaleWorldTransform(graphics, 1.0, 1.0, MatrixOrderPrepend);
700     expect(ObjectBusy, status); status = Ok;
701     status = GdipSetCompositingMode(graphics, CompositingModeSourceOver);
702     expect(ObjectBusy, status); status = Ok;
703     status = GdipSetCompositingQuality(graphics, CompositingQualityDefault);
704     expect(ObjectBusy, status); status = Ok;
705     status = GdipSetInterpolationMode(graphics, InterpolationModeDefault);
706     expect(ObjectBusy, status); status = Ok;
707     status = GdipSetPageScale(graphics, 1.0);
708     expect(ObjectBusy, status); status = Ok;
709     status = GdipSetPageUnit(graphics, UnitWorld);
710     expect(ObjectBusy, status); status = Ok;
711     status = GdipSetPixelOffsetMode(graphics, PixelOffsetModeDefault);
712     expect(ObjectBusy, status); status = Ok;
713     status = GdipSetSmoothingMode(graphics, SmoothingModeDefault);
714     expect(ObjectBusy, status); status = Ok;
715     status = GdipSetTextRenderingHint(graphics, TextRenderingHintSystemDefault);
716     expect(ObjectBusy, status); status = Ok;
717     status = GdipSetWorldTransform(graphics, m);
718     expect(ObjectBusy, status); status = Ok;
719     status = GdipTranslateWorldTransform(graphics, 0.0, 0.0, MatrixOrderPrepend);
720     expect(ObjectBusy, status); status = Ok;
721     status = GdipSetClipHrgn(graphics, hrgn, CombineModeReplace);
722     expect(ObjectBusy, status); status = Ok;
723     status = GdipSetClipPath(graphics, path, CombineModeReplace);
724     expect(ObjectBusy, status); status = Ok;
725     status = GdipSetClipRect(graphics, 0.0, 0.0, 10.0, 10.0, CombineModeReplace);
726     expect(ObjectBusy, status); status = Ok;
727     status = GdipSetClipRectI(graphics, 0, 0, 10, 10, CombineModeReplace);
728     expect(ObjectBusy, status); status = Ok;
729     status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
730     expect(ObjectBusy, status); status = Ok;
731     status = GdipTranslateClip(graphics, 0.0, 0.0);
732     expect(ObjectBusy, status); status = Ok;
733     status = GdipTranslateClipI(graphics, 0, 0);
734     expect(ObjectBusy, status); status = Ok;
735     status = GdipDrawPolygon(graphics, pen, ptf, 5);
736     expect(ObjectBusy, status); status = Ok;
737     status = GdipDrawPolygonI(graphics, pen, pt, 5);
738     expect(ObjectBusy, status); status = Ok;
739     status = GdipGetDpiX(graphics, &r);
740     expect(ObjectBusy, status); status = Ok;
741     status = GdipGetDpiY(graphics, &r);
742     expect(ObjectBusy, status); status = Ok;
743     status = GdipMultiplyWorldTransform(graphics, m, MatrixOrderPrepend);
744     status = GdipGetClip(graphics, region);
745     expect(ObjectBusy, status); status = Ok;
746     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 5);
747     expect(ObjectBusy, status); status = Ok;
748     /* try to delete before release */
749     status = GdipDeleteGraphics(graphics);
750     expect(ObjectBusy, status);
751
752     status = GdipReleaseDC(graphics, retdc);
753     expect(Ok, status);
754
755     GdipDeletePen(pen);
756     GdipDeleteGraphics(graphics);
757
758     GdipDeletePath(path);
759     GdipDeleteBrush((GpBrush*)brush);
760     GdipDeleteRegion(region);
761     GdipDeleteMatrix(m);
762     DeleteObject(hrgn);
763
764     ReleaseDC(0, hdc);
765 }
766
767 static void test_transformpoints(void)
768 {
769     GpStatus status;
770     GpGraphics *graphics = NULL;
771     HDC hdc = GetDC(0);
772     GpPointF ptf[2];
773     GpPoint pt[2];
774
775     status = GdipCreateFromHDC(hdc, &graphics);
776     expect(Ok, status);
777
778     /* NULL arguments */
779     status = GdipTransformPoints(NULL, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
780     expect(InvalidParameter, status);
781     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0);
782     expect(InvalidParameter, status);
783     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 0);
784     expect(InvalidParameter, status);
785     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, -1);
786     expect(InvalidParameter, status);
787
788     ptf[0].X = 1.0;
789     ptf[0].Y = 0.0;
790     ptf[1].X = 0.0;
791     ptf[1].Y = 1.0;
792     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2);
793     expect(Ok, status);
794     expectf(1.0, ptf[0].X);
795     expectf(0.0, ptf[0].Y);
796     expectf(0.0, ptf[1].X);
797     expectf(1.0, ptf[1].Y);
798
799     status = GdipTranslateWorldTransform(graphics, 5.0, 5.0, MatrixOrderAppend);
800     expect(Ok, status);
801     status = GdipSetPageUnit(graphics, UnitPixel);
802     expect(Ok, status);
803     status = GdipSetPageScale(graphics, 3.0);
804     expect(Ok, status);
805
806     ptf[0].X = 1.0;
807     ptf[0].Y = 0.0;
808     ptf[1].X = 0.0;
809     ptf[1].Y = 1.0;
810     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2);
811     expect(Ok, status);
812     expectf(18.0, ptf[0].X);
813     expectf(15.0, ptf[0].Y);
814     expectf(15.0, ptf[1].X);
815     expectf(18.0, ptf[1].Y);
816
817     ptf[0].X = 1.0;
818     ptf[0].Y = 0.0;
819     ptf[1].X = 0.0;
820     ptf[1].Y = 1.0;
821     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 2);
822     expect(Ok, status);
823     expectf(6.0, ptf[0].X);
824     expectf(5.0, ptf[0].Y);
825     expectf(5.0, ptf[1].X);
826     expectf(6.0, ptf[1].Y);
827
828     ptf[0].X = 1.0;
829     ptf[0].Y = 0.0;
830     ptf[1].X = 0.0;
831     ptf[1].Y = 1.0;
832     status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpacePage, ptf, 2);
833     expect(Ok, status);
834     expectf(3.0, ptf[0].X);
835     expectf(0.0, ptf[0].Y);
836     expectf(0.0, ptf[1].X);
837     expectf(3.0, ptf[1].Y);
838
839     ptf[0].X = 18.0;
840     ptf[0].Y = 15.0;
841     ptf[1].X = 15.0;
842     ptf[1].Y = 18.0;
843     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2);
844     expect(Ok, status);
845     expectf(1.0, ptf[0].X);
846     expectf(0.0, ptf[0].Y);
847     expectf(0.0, ptf[1].X);
848     expectf(1.0, ptf[1].Y);
849
850     ptf[0].X = 6.0;
851     ptf[0].Y = 5.0;
852     ptf[1].X = 5.0;
853     ptf[1].Y = 6.0;
854     status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpacePage, ptf, 2);
855     expect(Ok, status);
856     expectf(1.0, ptf[0].X);
857     expectf(0.0, ptf[0].Y);
858     expectf(0.0, ptf[1].X);
859     expectf(1.0, ptf[1].Y);
860
861     ptf[0].X = 3.0;
862     ptf[0].Y = 0.0;
863     ptf[1].X = 0.0;
864     ptf[1].Y = 3.0;
865     status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceDevice, ptf, 2);
866     expect(Ok, status);
867     expectf(1.0, ptf[0].X);
868     expectf(0.0, ptf[0].Y);
869     expectf(0.0, ptf[1].X);
870     expectf(1.0, ptf[1].Y);
871
872     pt[0].X = 1;
873     pt[0].Y = 0;
874     pt[1].X = 0;
875     pt[1].Y = 1;
876     status = GdipTransformPointsI(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, pt, 2);
877     expect(Ok, status);
878     expect(18, pt[0].X);
879     expect(15, pt[0].Y);
880     expect(15, pt[1].X);
881     expect(18, pt[1].Y);
882
883     GdipDeleteGraphics(graphics);
884     ReleaseDC(0, hdc);
885 }
886
887 static void test_get_set_clip(void)
888 {
889     GpStatus status;
890     GpGraphics *graphics = NULL;
891     HDC hdc = GetDC(0);
892     GpRegion *clip;
893     GpRectF rect;
894     BOOL res;
895
896     status = GdipCreateFromHDC(hdc, &graphics);
897     expect(Ok, status);
898
899     rect.X = rect.Y = 0.0;
900     rect.Height = rect.Width = 100.0;
901
902     status = GdipCreateRegionRect(&rect, &clip);
903
904     /* NULL arguments */
905     status = GdipGetClip(NULL, NULL);
906     expect(InvalidParameter, status);
907     status = GdipGetClip(graphics, NULL);
908     expect(InvalidParameter, status);
909     status = GdipGetClip(NULL, clip);
910     expect(InvalidParameter, status);
911
912     status = GdipSetClipRegion(NULL, NULL, CombineModeReplace);
913     expect(InvalidParameter, status);
914     status = GdipSetClipRegion(graphics, NULL, CombineModeReplace);
915     expect(InvalidParameter, status);
916
917     status = GdipSetClipPath(NULL, NULL, CombineModeReplace);
918     expect(InvalidParameter, status);
919     status = GdipSetClipPath(graphics, NULL, CombineModeReplace);
920     expect(InvalidParameter, status);
921
922     res = FALSE;
923     status = GdipGetClip(graphics, clip);
924     expect(Ok, status);
925     status = GdipIsInfiniteRegion(clip, graphics, &res);
926     expect(Ok, status);
927     expect(TRUE, res);
928
929     /* remains infinite after reset */
930     res = FALSE;
931     status = GdipResetClip(graphics);
932     expect(Ok, status);
933     status = GdipGetClip(graphics, clip);
934     expect(Ok, status);
935     status = GdipIsInfiniteRegion(clip, graphics, &res);
936     expect(Ok, status);
937     expect(TRUE, res);
938
939     /* set to empty and then reset to infinite */
940     status = GdipSetEmpty(clip);
941     expect(Ok, status);
942     status = GdipSetClipRegion(graphics, clip, CombineModeReplace);
943     expect(Ok, status);
944
945     status = GdipGetClip(graphics, clip);
946     expect(Ok, status);
947     res = FALSE;
948     status = GdipIsEmptyRegion(clip, graphics, &res);
949     expect(Ok, status);
950     expect(TRUE, res);
951     status = GdipResetClip(graphics);
952     expect(Ok, status);
953     status = GdipGetClip(graphics, clip);
954     expect(Ok, status);
955     res = FALSE;
956     status = GdipIsInfiniteRegion(clip, graphics, &res);
957     expect(Ok, status);
958     expect(TRUE, res);
959
960     GdipDeleteRegion(clip);
961
962     GdipDeleteGraphics(graphics);
963     ReleaseDC(0, hdc);
964 }
965
966 static void test_isempty(void)
967 {
968     GpStatus status;
969     GpGraphics *graphics = NULL;
970     HDC hdc = GetDC(0);
971     GpRegion *clip;
972     BOOL res;
973
974     status = GdipCreateFromHDC(hdc, &graphics);
975     expect(Ok, status);
976
977     status = GdipCreateRegion(&clip);
978     expect(Ok, status);
979
980     /* NULL */
981     status = GdipIsClipEmpty(NULL, NULL);
982     expect(InvalidParameter, status);
983     status = GdipIsClipEmpty(graphics, NULL);
984     expect(InvalidParameter, status);
985     status = GdipIsClipEmpty(NULL, &res);
986     expect(InvalidParameter, status);
987
988     /* default is infinite */
989     res = TRUE;
990     status = GdipIsClipEmpty(graphics, &res);
991     expect(Ok, status);
992     expect(FALSE, res);
993
994     GdipDeleteRegion(clip);
995
996     GdipDeleteGraphics(graphics);
997     ReleaseDC(0, hdc);
998 }
999
1000 static void test_clear(void)
1001 {
1002     GpStatus status;
1003
1004     status = GdipGraphicsClear(NULL, 0xdeadbeef);
1005     expect(InvalidParameter, status);
1006 }
1007
1008 static void test_textcontrast(void)
1009 {
1010     GpStatus status;
1011     HDC hdc = GetDC(0);
1012     GpGraphics *graphics;
1013     UINT contrast;
1014
1015     status = GdipGetTextContrast(NULL, NULL);
1016     expect(InvalidParameter, status);
1017
1018     status = GdipCreateFromHDC(hdc, &graphics);
1019     expect(Ok, status);
1020
1021     status = GdipGetTextContrast(graphics, NULL);
1022     expect(InvalidParameter, status);
1023     status = GdipGetTextContrast(graphics, &contrast);
1024     expect(4, contrast);
1025
1026     GdipDeleteGraphics(graphics);
1027     ReleaseDC(0, hdc);
1028 }
1029
1030 static void test_GdipDrawString(void)
1031 {
1032     GpStatus status;
1033     GpGraphics *graphics = NULL;
1034     GpFont *fnt = NULL;
1035     RectF  rect;
1036     GpStringFormat *format;
1037     GpBrush *brush;
1038     LOGFONTA logfont;
1039     HDC hdc = GetDC(0);
1040     static const WCHAR string[] = {'T','e','s','t',0};
1041
1042     memset(&logfont,0,sizeof(logfont));
1043     strcpy(logfont.lfFaceName,"Arial");
1044     logfont.lfHeight = 12;
1045     logfont.lfCharSet = DEFAULT_CHARSET;
1046
1047     status = GdipCreateFromHDC(hdc, &graphics);
1048     expect(Ok, status);
1049
1050     status = GdipCreateFontFromLogfontA(hdc, &logfont, &fnt);
1051     if (status == FileNotFound)
1052     {
1053         skip("Arial not installed.\n");
1054         return;
1055     }
1056     expect(Ok, status);
1057
1058     status = GdipCreateSolidFill((ARGB)0xdeadbeef, (GpSolidFill**)&brush);
1059     expect(Ok, status);
1060
1061     status = GdipCreateStringFormat(0,0,&format);
1062     expect(Ok, status);
1063
1064     rect.X = 0;
1065     rect.Y = 0;
1066     rect.Width = 0;
1067     rect.Height = 12;
1068
1069     status = GdipDrawString(graphics, string, 4, fnt, &rect, format, brush);
1070     expect(Ok, status);
1071
1072     GdipDeleteGraphics(graphics);
1073     GdipDeleteBrush(brush);
1074     GdipDeleteFont(fnt);
1075     GdipDeleteStringFormat(format);
1076
1077     ReleaseDC(0, hdc);
1078 }
1079
1080
1081 START_TEST(graphics)
1082 {
1083     struct GdiplusStartupInput gdiplusStartupInput;
1084     ULONG_PTR gdiplusToken;
1085
1086     gdiplusStartupInput.GdiplusVersion              = 1;
1087     gdiplusStartupInput.DebugEventCallback          = NULL;
1088     gdiplusStartupInput.SuppressBackgroundThread    = 0;
1089     gdiplusStartupInput.SuppressExternalCodecs      = 0;
1090
1091     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1092
1093     test_constructor_destructor();
1094     test_save_restore();
1095     test_GdipDrawBezierI();
1096     test_GdipDrawArc();
1097     test_GdipDrawArcI();
1098     test_GdipDrawLineI();
1099     test_GdipDrawLinesI();
1100     test_GdipDrawString();
1101     test_Get_Release_DC();
1102     test_transformpoints();
1103     test_get_set_clip();
1104     test_isempty();
1105     test_clear();
1106     test_textcontrast();
1107
1108     GdiplusShutdown(gdiplusToken);
1109 }