gdiplus: Add some tests for pathiterator, fix leaks.
[wine] / dlls / gdiplus / tests / pen.c
1 /*
2  * Unit test suite for pens (and init)
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 <math.h>
22
23 #include "windows.h"
24 #include "gdiplus.h"
25 #include "wine/test.h"
26
27 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
28 #define expectf(expected, got) ok(fabs(got - expected) < 0.1, "Expected %.2f, got %.2f\n", expected, got)
29
30 static void test_startup(void)
31 {
32     GpPen *pen = NULL;
33     Status status;
34     struct GdiplusStartupInput gdiplusStartupInput;
35     ULONG_PTR gdiplusToken;
36
37     gdiplusStartupInput.GdiplusVersion              = 1;
38     gdiplusStartupInput.DebugEventCallback          = NULL;
39     gdiplusStartupInput.SuppressBackgroundThread    = 0;
40     gdiplusStartupInput.SuppressExternalCodecs      = 0;
41
42     status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
43     expect(Ok, status);
44     GdiplusShutdown(gdiplusToken);
45
46     gdiplusStartupInput.GdiplusVersion = 2;
47
48     status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
49     expect(UnsupportedGdiplusVersion, status);
50     GdiplusShutdown(gdiplusToken);
51
52     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
53
54     todo_wine
55         expect(GdiplusNotInitialized, status);
56
57     GdipDeletePen(pen);
58 }
59
60 static void test_constructor_destructor(void)
61 {
62     GpStatus status;
63     GpPen *pen = NULL;
64
65     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, NULL);
66     expect(InvalidParameter, status);
67     ok(pen == NULL, "Expected pen to be NULL\n");
68
69     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
70     expect(Ok, status);
71     ok(pen != NULL, "Expected pen to be initialized\n");
72
73     status = GdipDeletePen(NULL);
74     expect(InvalidParameter, status);
75
76     status = GdipDeletePen(pen);
77     expect(Ok, status);
78 }
79
80 static void test_constructor_destructor2(void)
81 {
82     GpStatus status;
83     GpPen *pen = NULL;
84     GpBrush *brush = NULL;
85     GpPointF points[2];
86
87     status = GdipCreatePen2(NULL, 10.0f, UnitPixel, &pen);
88     expect(InvalidParameter, status);
89     ok(pen == NULL, "Expected pen to be NULL\n");
90
91     points[0].X = 7.0;
92     points[0].Y = 11.0;
93     points[1].X = 13.0;
94     points[1].Y = 17.0;
95
96     status = GdipCreateLineBrush(&points[0], &points[1], (ARGB)0xffff00ff,
97                     (ARGB)0xff0000ff, WrapModeTile, (GpLineGradient **)&brush);
98     expect(Ok, status);
99     ok(brush != NULL, "Expected brush to be initialized\n");
100
101     status = GdipCreatePen2(brush, 10.0f, UnitPixel, &pen);
102     expect(Ok, status);
103     ok(pen != NULL, "Expected pen to be initialized\n");
104
105     status = GdipDeletePen(pen);
106     expect(Ok, status);
107
108     status = GdipDeleteBrush(brush);
109     expect(Ok, status);
110 }
111
112 static void test_brushfill(void)
113 {
114     GpStatus status;
115     GpPen *pen;
116     GpBrush *brush, *brush2;
117     GpBrushType type;
118     ARGB color = 0;
119
120     /* default solid */
121     GdipCreatePen1(0xdeadbeef, 4.5, UnitWorld, &pen);
122     status = GdipGetPenBrushFill(pen, &brush);
123     expect(Ok, status);
124     GdipGetBrushType(brush, &type);
125     expect(BrushTypeSolidColor, type);
126     GdipGetPenColor(pen, &color);
127     expect(0xdeadbeef, color);
128     GdipDeleteBrush(brush);
129
130     /* color controlled by brush */
131     GdipCreateSolidFill(0xabaddeed, (GpSolidFill**)&brush);
132     status = GdipSetPenBrushFill(pen, brush);
133     expect(Ok, status);
134     GdipGetPenColor(pen, &color);
135     expect(0xabaddeed, color);
136     GdipDeleteBrush(brush);
137     color = 0;
138
139     /* get returns a clone, not a reference */
140     GdipGetPenBrushFill(pen, &brush);
141     GdipSetSolidFillColor((GpSolidFill*)brush, 0xbeadfeed);
142     GdipGetPenBrushFill(pen, &brush2);
143     ok(brush != brush2, "Expected to get a clone, not a copy of the reference\n");
144     GdipGetSolidFillColor((GpSolidFill*)brush2, &color);
145     expect(0xabaddeed, color);
146     GdipDeleteBrush(brush);
147     GdipDeleteBrush(brush2);
148
149     /* brush cannot be NULL */
150     status = GdipSetPenBrushFill(pen, NULL);
151     expect(InvalidParameter, status);
152
153     GdipDeletePen(pen);
154 }
155
156 static void test_dasharray(void)
157 {
158     GpPen *pen;
159     GpDashStyle style;
160     GpStatus status;
161     REAL dashes[12];
162
163     GdipCreatePen1(0xdeadbeef, 10.0, UnitWorld, &pen);
164     dashes[0] = 10.0;
165     dashes[1] = 11.0;
166     dashes[2] = 12.0;
167     dashes[3] = 13.0;
168     dashes[4] = 14.0;
169     dashes[5] = -100.0;
170     dashes[6] = -100.0;
171     dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 0.0;
172
173     /* setting the array sets the type to custom */
174     GdipGetPenDashStyle(pen, &style);
175     expect(DashStyleSolid, style);
176     status = GdipSetPenDashArray(pen, dashes, 2);
177     expect(Ok, status);
178     GdipGetPenDashStyle(pen, &style);
179     expect(DashStyleCustom, style);
180
181     /* Getting the array on a non-custom pen returns invalid parameter (unless
182      * you are getting 0 elements).*/
183     GdipSetPenDashStyle(pen, DashStyleSolid);
184     status = GdipGetPenDashArray(pen, &dashes[5], 2);
185     expect(InvalidParameter, status);
186     status = GdipGetPenDashArray(pen, &dashes[5], 0);
187     expect(Ok, status);
188
189     /* What does setting DashStyleCustom do to the array length? */
190     GdipSetPenDashArray(pen, dashes, 2);
191     GdipSetPenDashStyle(pen, DashStyleCustom);
192     status = GdipGetPenDashArray(pen, &dashes[5], 2);
193     expect(Ok, status);
194     expectf(10.0, dashes[5]);
195     expectf(11.0, dashes[6]);
196
197     /* Set the array, then get with different sized buffers. */
198     status = GdipSetPenDashArray(pen, dashes, 5);
199     expect(Ok, status);
200     dashes[5] = -100.0;
201     dashes[6] = -100.0;
202     status = GdipGetPenDashArray(pen, &dashes[5], 1);
203     expect(Ok, status); /* not InsufficientBuffer! */
204     expectf(10.0, dashes[5]);
205     expectf(-100.0, dashes[6]);
206     dashes[5] = -100.0;
207     status = GdipGetPenDashArray(pen, &dashes[5], 6);
208     expect(InvalidParameter, status); /* not Ok! */
209     expectf(-100.0, dashes[5]);
210     expectf(-100.0, dashes[6]);
211
212     /* Some invalid array values. */
213     status = GdipSetPenDashArray(pen, &dashes[7], 5);
214     expect(InvalidParameter, status);
215     dashes[9] = -1.0;
216     status = GdipSetPenDashArray(pen, &dashes[7], 5);
217     expect(InvalidParameter, status);
218
219     /* Try to set with count = 0. */
220     GdipSetPenDashStyle(pen, DashStyleDot);
221     status = GdipSetPenDashArray(pen, dashes, 0);
222     expect(OutOfMemory, status);
223     GdipGetPenDashStyle(pen, &style);
224     expect(DashStyleDot, style);
225
226     GdipDeletePen(pen);
227 }
228
229 static void test_customcap(void)
230 {
231     GpPen *pen;
232     GpStatus status;
233     GpCustomLineCap *custom;
234
235     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
236     expect(Ok, status);
237
238     /* NULL args */
239     status = GdipGetPenCustomStartCap(NULL, NULL);
240     expect(InvalidParameter, status);
241     status = GdipGetPenCustomStartCap(pen, NULL);
242     expect(InvalidParameter, status);
243     status = GdipGetPenCustomStartCap(NULL, &custom);
244     expect(InvalidParameter, status);
245
246     status = GdipGetPenCustomEndCap(NULL, NULL);
247     expect(InvalidParameter, status);
248     status = GdipGetPenCustomEndCap(pen, NULL);
249     expect(InvalidParameter, status);
250     status = GdipGetPenCustomEndCap(NULL, &custom);
251     expect(InvalidParameter, status);
252
253     /* native crashes on pen == NULL, custom != NULL */
254     status = GdipSetPenCustomStartCap(NULL, NULL);
255     expect(InvalidParameter, status);
256     status = GdipSetPenCustomStartCap(pen, NULL);
257     expect(InvalidParameter, status);
258
259     status = GdipSetPenCustomEndCap(NULL, NULL);
260     expect(InvalidParameter, status);
261     status = GdipSetPenCustomEndCap(pen, NULL);
262     expect(InvalidParameter, status);
263
264     /* get without setting previously */
265     custom = (GpCustomLineCap*)0xdeadbeef;
266     status = GdipGetPenCustomEndCap(pen, &custom);
267     expect(Ok, status);
268     ok(custom == NULL,"Expect CustomCap == NULL\n");
269
270     custom = (GpCustomLineCap*)0xdeadbeef;
271     status = GdipGetPenCustomStartCap(pen, &custom);
272     expect(Ok, status);
273     ok(custom == NULL,"Expect CustomCap == NULL\n");
274
275     GdipDeletePen(pen);
276 }
277
278 START_TEST(pen)
279 {
280     struct GdiplusStartupInput gdiplusStartupInput;
281     ULONG_PTR gdiplusToken;
282
283     test_startup();
284
285     gdiplusStartupInput.GdiplusVersion              = 1;
286     gdiplusStartupInput.DebugEventCallback          = NULL;
287     gdiplusStartupInput.SuppressBackgroundThread    = 0;
288     gdiplusStartupInput.SuppressExternalCodecs      = 0;
289
290     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
291
292     test_constructor_destructor();
293     test_constructor_destructor2();
294     test_brushfill();
295     test_dasharray();
296     test_customcap();
297
298     GdiplusShutdown(gdiplusToken);
299 }