Merge HAL changes 34743, 34812, 34839, 34917, 35515, 35771, 35902, 35904,
[reactos.git] / rostests / winetests / gdiplus / 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 static void test_penfilltype(void)
279 {
280 GpPen *pen;
281 GpSolidFill *solid;
282 GpLineGradient *line;
283 GpPointF a, b;
284 GpStatus status;
285 GpPenType type;
286
287 /* NULL */
288 status = GdipGetPenFillType(NULL, NULL);
289 expect(InvalidParameter, status);
290
291 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
292 expect(Ok, status);
293 status = GdipGetPenFillType(pen, NULL);
294 expect(InvalidParameter, status);
295
296 /* created with GdipCreatePen1() */
297 status = GdipGetPenFillType(pen, &type);
298 expect(Ok, status);
299 expect(PenTypeSolidColor, type);
300 GdipDeletePen(pen);
301
302 /* based on SolidBrush */
303 status = GdipCreateSolidFill((ARGB)0xffff00ff, &solid);
304 expect(Ok, status);
305 status = GdipCreatePen2((GpBrush*)solid, 10.0f, UnitPixel, &pen);
306 expect(Ok, status);
307 status = GdipGetPenFillType(pen, &type);
308 expect(Ok, status);
309 expect(PenTypeSolidColor, type);
310 GdipDeletePen(pen);
311 GdipDeleteBrush((GpBrush*)solid);
312
313 /* based on LinearGradientBrush */
314 a.X = a.Y = 0.0;
315 b.X = b.Y = 10.0;
316 status = GdipCreateLineBrush(&a, &b, (ARGB)0xffff00ff, (ARGB)0xffff0000,
317 WrapModeTile, &line);
318 expect(Ok, status);
319 status = GdipCreatePen2((GpBrush*)line, 10.0f, UnitPixel, &pen);
320 expect(Ok, status);
321 status = GdipGetPenFillType(pen, &type);
322 expect(Ok, status);
323 expect(PenTypeLinearGradient, type);
324 GdipDeletePen(pen);
325 GdipDeleteBrush((GpBrush*)line);
326 }
327
328 static void test_compoundarray(void)
329 {
330 GpStatus status;
331 GpPen *pen;
332 static const REAL testvalues[] = {0.2, 0.4, 0.6, 0.8};
333
334 status = GdipSetPenCompoundArray(NULL, testvalues, 4);
335 expect(InvalidParameter, status);
336
337 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
338 expect(Ok, status);
339
340 status = GdipSetPenCompoundArray(pen, NULL, 4);
341 expect(InvalidParameter, status);
342 status = GdipSetPenCompoundArray(pen, testvalues, 3);
343 expect(InvalidParameter, status);
344 status = GdipSetPenCompoundArray(pen, testvalues, 0);
345 expect(InvalidParameter, status);
346 status = GdipSetPenCompoundArray(pen, testvalues, -2);
347 expect(InvalidParameter, status);
348
349 status = GdipSetPenCompoundArray(pen, testvalues, 4);
350 todo_wine expect(Ok, status);
351
352 GdipDeletePen(pen);
353 }
354
355 START_TEST(pen)
356 {
357 struct GdiplusStartupInput gdiplusStartupInput;
358 ULONG_PTR gdiplusToken;
359
360 test_startup();
361
362 gdiplusStartupInput.GdiplusVersion = 1;
363 gdiplusStartupInput.DebugEventCallback = NULL;
364 gdiplusStartupInput.SuppressBackgroundThread = 0;
365 gdiplusStartupInput.SuppressExternalCodecs = 0;
366
367 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
368
369 test_constructor_destructor();
370 test_constructor_destructor2();
371 test_brushfill();
372 test_dasharray();
373 test_customcap();
374 test_penfilltype();
375 test_compoundarray();
376
377 GdiplusShutdown(gdiplusToken);
378 }