gdiplus: Check custom dash array for bad properties.
[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 <stdarg.h>
22 #include <math.h>
23
24 #include "windef.h"
25 #include "gdiplus.h"
26 #include "wine/test.h"
27
28 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
29 #define expectf(expected, got) ok(fabs(got - expected) < 0.1, "Expected %.2f, got %.2f\n", expected, got)
30
31 static void test_startup(void)
32 {
33     GpPen *pen;
34     Status status;
35     struct GdiplusStartupInput gdiplusStartupInput;
36     ULONG_PTR gdiplusToken;
37
38     gdiplusStartupInput.GdiplusVersion              = 1;
39     gdiplusStartupInput.DebugEventCallback          = NULL;
40     gdiplusStartupInput.SuppressBackgroundThread    = 0;
41     gdiplusStartupInput.SuppressExternalCodecs      = 0;
42
43     status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
44     expect(Ok, status);
45     GdiplusShutdown(gdiplusToken);
46
47     gdiplusStartupInput.GdiplusVersion = 2;
48
49     status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
50     expect(UnsupportedGdiplusVersion, status);
51     GdiplusShutdown(gdiplusToken);
52
53     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
54
55     todo_wine
56         expect(GdiplusNotInitialized, status);
57
58     GdipDeletePen(pen);
59 }
60
61 static void test_constructor_destructor(void)
62 {
63     GpStatus status;
64     GpPen *pen = NULL;
65
66     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
67     expect(Ok, status);
68     ok(pen != NULL, "Expected pen to be initialized\n");
69
70     status = GdipDeletePen(NULL);
71     expect(InvalidParameter, status);
72
73     status = GdipDeletePen(pen);
74     expect(Ok, status);
75 }
76
77 static void test_brushfill(void)
78 {
79     GpStatus status;
80     GpPen *pen;
81     GpBrush *brush, *brush2;
82     GpBrushType type;
83     ARGB color = 0;
84
85     /* default solid */
86     GdipCreatePen1(0xdeadbeef, 4.5, UnitWorld, &pen);
87     status = GdipGetPenBrushFill(pen, &brush);
88     expect(Ok, status);
89     GdipGetBrushType(brush, &type);
90     expect(BrushTypeSolidColor, type);
91     GdipGetPenColor(pen, &color);
92     expect(0xdeadbeef, color);
93     GdipDeleteBrush(brush);
94
95     /* color controlled by brush */
96     GdipCreateSolidFill(0xabaddeed, (GpSolidFill**)&brush);
97     status = GdipSetPenBrushFill(pen, brush);
98     expect(Ok, status);
99     GdipGetPenColor(pen, &color);
100     expect(0xabaddeed, color);
101     GdipDeleteBrush(brush);
102     color = 0;
103
104     /* get returns a clone, not a reference */
105     GdipGetPenBrushFill(pen, &brush);
106     GdipSetSolidFillColor((GpSolidFill*)brush, 0xbeadfeed);
107     GdipGetPenBrushFill(pen, &brush2);
108     ok(brush != brush2, "Expected to get a clone, not a copy of the reference\n");
109     GdipGetSolidFillColor((GpSolidFill*)brush2, &color);
110     expect(0xabaddeed, color);
111     GdipDeleteBrush(brush);
112     GdipDeleteBrush(brush2);
113
114     /* brush cannot be NULL */
115     status = GdipSetPenBrushFill(pen, NULL);
116     expect(InvalidParameter, status);
117
118     GdipDeletePen(pen);
119 }
120
121 static void test_dasharray(void)
122 {
123     GpPen *pen;
124     GpDashStyle style;
125     GpStatus status;
126     REAL dashes[12];
127
128     GdipCreatePen1(0xdeadbeef, 10.0, UnitWorld, &pen);
129     dashes[0] = 10.0;
130     dashes[1] = 11.0;
131     dashes[2] = 12.0;
132     dashes[3] = 13.0;
133     dashes[4] = 14.0;
134     dashes[5] = -100.0;
135     dashes[6] = -100.0;
136     dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 0.0;
137
138     /* setting the array sets the type to custom */
139     GdipGetPenDashStyle(pen, &style);
140     expect(DashStyleSolid, style);
141     status = GdipSetPenDashArray(pen, dashes, 2);
142     expect(Ok, status);
143     GdipGetPenDashStyle(pen, &style);
144     expect(DashStyleCustom, style);
145
146     /* Getting the array on a non-custom pen returns invalid parameter (unless
147      * you are getting 0 elements).*/
148     GdipSetPenDashStyle(pen, DashStyleSolid);
149     status = GdipGetPenDashArray(pen, &dashes[5], 2);
150     expect(InvalidParameter, status);
151     status = GdipGetPenDashArray(pen, &dashes[5], 0);
152     expect(Ok, status);
153
154     /* What does setting DashStyleCustom do to the array length? */
155     GdipSetPenDashArray(pen, dashes, 2);
156     GdipSetPenDashStyle(pen, DashStyleCustom);
157     status = GdipGetPenDashArray(pen, &dashes[5], 2);
158     expect(Ok, status);
159     expectf(10.0, dashes[5]);
160     expectf(11.0, dashes[6]);
161
162     /* Set the array, then get with different sized buffers. */
163     status = GdipSetPenDashArray(pen, dashes, 5);
164     expect(Ok, status);
165     dashes[5] = -100.0;
166     dashes[6] = -100.0;
167     status = GdipGetPenDashArray(pen, &dashes[5], 1);
168     expect(Ok, status); /* not InsufficientBuffer! */
169     expectf(10.0, dashes[5]);
170     expectf(-100.0, dashes[6]);
171     dashes[5] = -100.0;
172     status = GdipGetPenDashArray(pen, &dashes[5], 6);
173     expect(InvalidParameter, status); /* not Ok! */
174     expectf(-100.0, dashes[5]);
175     expectf(-100.0, dashes[6]);
176
177     /* Some invalid array values. */
178     status = GdipSetPenDashArray(pen, &dashes[7], 5);
179     expect(InvalidParameter, status);
180     dashes[9] = -1.0;
181     status = GdipSetPenDashArray(pen, &dashes[7], 5);
182     expect(InvalidParameter, status);
183
184     /* Try to set with count = 0. */
185     GdipSetPenDashStyle(pen, DashStyleDot);
186     status = GdipSetPenDashArray(pen, dashes, 0);
187     expect(OutOfMemory, status);
188     GdipGetPenDashStyle(pen, &style);
189     expect(DashStyleDot, style);
190
191     GdipDeletePen(pen);
192 }
193
194 START_TEST(pen)
195 {
196     struct GdiplusStartupInput gdiplusStartupInput;
197     ULONG_PTR gdiplusToken;
198
199     test_startup();
200
201     gdiplusStartupInput.GdiplusVersion              = 1;
202     gdiplusStartupInput.DebugEventCallback          = NULL;
203     gdiplusStartupInput.SuppressBackgroundThread    = 0;
204     gdiplusStartupInput.SuppressExternalCodecs      = 0;
205
206     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
207
208     test_constructor_destructor();
209     test_brushfill();
210     test_dasharray();
211
212     GdiplusShutdown(gdiplusToken);
213 }