a8ee9da1b432627890f48faf1abe5f661c78d92c
[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 #define WIN32_NO_STATUS
24 #define _INC_WINDOWS
25 #define COM_NO_WINDOWS_H
26
27 //#include "windows.h"
28 #include <wine/test.h>
29 #include <wingdi.h>
30 #include <objbase.h>
31 #include <gdiplus.h>
32
33 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
34 #define expectf(expected, got) ok(fabs(got - expected) < 0.1, "Expected %.2f, got %.2f\n", expected, got)
35
36 static void test_startup(void)
37 {
38 GpPen *pen = NULL;
39 Status status;
40 struct GdiplusStartupInput gdiplusStartupInput;
41 ULONG_PTR gdiplusToken;
42 int gpversion;
43
44 gdiplusStartupInput.DebugEventCallback = NULL;
45 gdiplusStartupInput.SuppressBackgroundThread = 0;
46 gdiplusStartupInput.SuppressExternalCodecs = 0;
47
48 for (gpversion=1; gpversion<256; gpversion++)
49 {
50 gdiplusStartupInput.GdiplusVersion = gpversion;
51 status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
52 ok(status == Ok || status == UnsupportedGdiplusVersion,
53 "GdiplusStartup returned %x\n", status);
54 GdiplusShutdown(gdiplusToken);
55 if (status != Ok)
56 {
57 gpversion--;
58 break;
59 }
60 }
61
62 ok(gpversion > 0 && gpversion <= 2, "unexpected gdiplus version %i\n", gpversion);
63 trace("gdiplus version is %i\n", gpversion);
64
65 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
66
67 todo_wine
68 expect(GdiplusNotInitialized, status);
69
70 GdipDeletePen(pen);
71 }
72
73 static void test_constructor_destructor(void)
74 {
75 GpStatus status;
76 GpPen *pen = NULL;
77
78 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, NULL);
79 expect(InvalidParameter, status);
80 ok(pen == NULL, "Expected pen to be NULL\n");
81
82 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
83 expect(Ok, status);
84 ok(pen != NULL, "Expected pen to be initialized\n");
85
86 status = GdipDeletePen(NULL);
87 expect(InvalidParameter, status);
88
89 status = GdipDeletePen(pen);
90 expect(Ok, status);
91 }
92
93 static void test_constructor_destructor2(void)
94 {
95 GpStatus status;
96 GpPen *pen = NULL;
97 GpBrush *brush = NULL;
98 GpPointF points[2];
99
100 status = GdipCreatePen2(NULL, 10.0f, UnitPixel, &pen);
101 expect(InvalidParameter, status);
102 ok(pen == NULL, "Expected pen to be NULL\n");
103
104 points[0].X = 7.0;
105 points[0].Y = 11.0;
106 points[1].X = 13.0;
107 points[1].Y = 17.0;
108
109 status = GdipCreateLineBrush(&points[0], &points[1], (ARGB)0xffff00ff,
110 (ARGB)0xff0000ff, WrapModeTile, (GpLineGradient **)&brush);
111 expect(Ok, status);
112 ok(brush != NULL, "Expected brush to be initialized\n");
113
114 status = GdipCreatePen2(brush, 10.0f, UnitPixel, &pen);
115 expect(Ok, status);
116 ok(pen != NULL, "Expected pen to be initialized\n");
117
118 status = GdipDeletePen(pen);
119 expect(Ok, status);
120
121 status = GdipDeleteBrush(brush);
122 expect(Ok, status);
123 }
124
125 static void test_brushfill(void)
126 {
127 GpStatus status;
128 GpPen *pen;
129 GpBrush *brush, *brush2;
130 GpBrushType type;
131 ARGB color = 0;
132
133 /* default solid */
134 GdipCreatePen1(0xdeadbeef, 4.5, UnitWorld, &pen);
135 status = GdipGetPenBrushFill(pen, &brush);
136 expect(Ok, status);
137 GdipGetBrushType(brush, &type);
138 expect(BrushTypeSolidColor, type);
139 GdipGetPenColor(pen, &color);
140 expect(0xdeadbeef, color);
141 GdipDeleteBrush(brush);
142
143 /* color controlled by brush */
144 GdipCreateSolidFill(0xabaddeed, (GpSolidFill**)&brush);
145 status = GdipSetPenBrushFill(pen, brush);
146 expect(Ok, status);
147 GdipGetPenColor(pen, &color);
148 expect(0xabaddeed, color);
149 GdipDeleteBrush(brush);
150 color = 0;
151
152 /* get returns a clone, not a reference */
153 GdipGetPenBrushFill(pen, &brush);
154 GdipSetSolidFillColor((GpSolidFill*)brush, 0xbeadfeed);
155 GdipGetPenBrushFill(pen, &brush2);
156 ok(brush != brush2, "Expected to get a clone, not a copy of the reference\n");
157 GdipGetSolidFillColor((GpSolidFill*)brush2, &color);
158 expect(0xabaddeed, color);
159 GdipDeleteBrush(brush);
160 GdipDeleteBrush(brush2);
161
162 /* brush cannot be NULL */
163 status = GdipSetPenBrushFill(pen, NULL);
164 expect(InvalidParameter, status);
165
166 GdipDeletePen(pen);
167 }
168
169 static void test_dasharray(void)
170 {
171 GpPen *pen;
172 GpDashStyle style;
173 GpStatus status;
174 REAL dashes[12];
175
176 GdipCreatePen1(0xdeadbeef, 10.0, UnitWorld, &pen);
177 dashes[0] = 10.0;
178 dashes[1] = 11.0;
179 dashes[2] = 12.0;
180 dashes[3] = 13.0;
181 dashes[4] = 14.0;
182 dashes[5] = -100.0;
183 dashes[6] = -100.0;
184 dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 0.0;
185
186 /* setting the array sets the type to custom */
187 GdipGetPenDashStyle(pen, &style);
188 expect(DashStyleSolid, style);
189 status = GdipSetPenDashArray(pen, dashes, 2);
190 expect(Ok, status);
191 GdipGetPenDashStyle(pen, &style);
192 expect(DashStyleCustom, style);
193
194 /* Getting the array on a non-custom pen returns invalid parameter (unless
195 * you are getting 0 elements).*/
196 GdipSetPenDashStyle(pen, DashStyleSolid);
197 status = GdipGetPenDashArray(pen, &dashes[5], 2);
198 expect(InvalidParameter, status);
199 status = GdipGetPenDashArray(pen, &dashes[5], 0);
200 expect(Ok, status);
201
202 /* What does setting DashStyleCustom do to the array length? */
203 GdipSetPenDashArray(pen, dashes, 2);
204 GdipSetPenDashStyle(pen, DashStyleCustom);
205 status = GdipGetPenDashArray(pen, &dashes[5], 2);
206 expect(Ok, status);
207 expectf(10.0, dashes[5]);
208 expectf(11.0, dashes[6]);
209
210 /* Set the array, then get with different sized buffers. */
211 status = GdipSetPenDashArray(pen, dashes, 5);
212 expect(Ok, status);
213 dashes[5] = -100.0;
214 dashes[6] = -100.0;
215 status = GdipGetPenDashArray(pen, &dashes[5], 1);
216 expect(Ok, status); /* not InsufficientBuffer! */
217 expectf(10.0, dashes[5]);
218 expectf(-100.0, dashes[6]);
219 dashes[5] = -100.0;
220 status = GdipGetPenDashArray(pen, &dashes[5], 6);
221 expect(InvalidParameter, status); /* not Ok! */
222 expectf(-100.0, dashes[5]);
223 expectf(-100.0, dashes[6]);
224
225 /* Some invalid array values. */
226 status = GdipSetPenDashArray(pen, &dashes[7], 5);
227 expect(InvalidParameter, status);
228 dashes[9] = -1.0;
229 status = GdipSetPenDashArray(pen, &dashes[7], 5);
230 expect(InvalidParameter, status);
231
232 /* Try to set with count = 0. */
233 GdipSetPenDashStyle(pen, DashStyleDot);
234 if (0) /* corrupts stack on 64-bit Vista */
235 {
236 status = GdipSetPenDashArray(pen, dashes, 0);
237 ok(status == OutOfMemory || status == InvalidParameter,
238 "Expected OutOfMemory or InvalidParameter, got %.8x\n", status);
239 }
240 status = GdipSetPenDashArray(pen, dashes, -1);
241 ok(status == OutOfMemory || status == InvalidParameter,
242 "Expected OutOfMemory or InvalidParameter, got %.8x\n", status);
243 GdipGetPenDashStyle(pen, &style);
244 expect(DashStyleDot, style);
245
246 GdipDeletePen(pen);
247 }
248
249 static void test_customcap(void)
250 {
251 GpPen *pen;
252 GpStatus status;
253 GpCustomLineCap *custom;
254
255 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
256 expect(Ok, status);
257
258 /* NULL args */
259 status = GdipGetPenCustomStartCap(NULL, NULL);
260 expect(InvalidParameter, status);
261 status = GdipGetPenCustomStartCap(pen, NULL);
262 expect(InvalidParameter, status);
263 status = GdipGetPenCustomStartCap(NULL, &custom);
264 expect(InvalidParameter, status);
265
266 status = GdipGetPenCustomEndCap(NULL, NULL);
267 expect(InvalidParameter, status);
268 status = GdipGetPenCustomEndCap(pen, NULL);
269 expect(InvalidParameter, status);
270 status = GdipGetPenCustomEndCap(NULL, &custom);
271 expect(InvalidParameter, status);
272
273 /* native crashes on pen == NULL, custom != NULL */
274 status = GdipSetPenCustomStartCap(NULL, NULL);
275 expect(InvalidParameter, status);
276 status = GdipSetPenCustomStartCap(pen, NULL);
277 expect(InvalidParameter, status);
278
279 status = GdipSetPenCustomEndCap(NULL, NULL);
280 expect(InvalidParameter, status);
281 status = GdipSetPenCustomEndCap(pen, NULL);
282 expect(InvalidParameter, status);
283
284 /* get without setting previously */
285 custom = (GpCustomLineCap*)0xdeadbeef;
286 status = GdipGetPenCustomEndCap(pen, &custom);
287 expect(Ok, status);
288 ok(custom == NULL,"Expect CustomCap == NULL\n");
289
290 custom = (GpCustomLineCap*)0xdeadbeef;
291 status = GdipGetPenCustomStartCap(pen, &custom);
292 expect(Ok, status);
293 ok(custom == NULL,"Expect CustomCap == NULL\n");
294
295 GdipDeletePen(pen);
296 }
297
298 static void test_penfilltype(void)
299 {
300 GpPen *pen;
301 GpSolidFill *solid;
302 GpLineGradient *line;
303 GpPointF a, b;
304 GpStatus status;
305 GpPenType type;
306
307 /* NULL */
308 status = GdipGetPenFillType(NULL, NULL);
309 expect(InvalidParameter, status);
310
311 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
312 expect(Ok, status);
313 status = GdipGetPenFillType(pen, NULL);
314 expect(InvalidParameter, status);
315
316 /* created with GdipCreatePen1() */
317 status = GdipGetPenFillType(pen, &type);
318 expect(Ok, status);
319 expect(PenTypeSolidColor, type);
320 GdipDeletePen(pen);
321
322 /* based on SolidBrush */
323 status = GdipCreateSolidFill((ARGB)0xffff00ff, &solid);
324 expect(Ok, status);
325 status = GdipCreatePen2((GpBrush*)solid, 10.0f, UnitPixel, &pen);
326 expect(Ok, status);
327 status = GdipGetPenFillType(pen, &type);
328 expect(Ok, status);
329 expect(PenTypeSolidColor, type);
330 GdipDeletePen(pen);
331 GdipDeleteBrush((GpBrush*)solid);
332
333 /* based on LinearGradientBrush */
334 a.X = a.Y = 0.0;
335 b.X = b.Y = 10.0;
336 status = GdipCreateLineBrush(&a, &b, (ARGB)0xffff00ff, (ARGB)0xffff0000,
337 WrapModeTile, &line);
338 expect(Ok, status);
339 status = GdipCreatePen2((GpBrush*)line, 10.0f, UnitPixel, &pen);
340 expect(Ok, status);
341 status = GdipGetPenFillType(pen, &type);
342 expect(Ok, status);
343 expect(PenTypeLinearGradient, type);
344 GdipDeletePen(pen);
345 GdipDeleteBrush((GpBrush*)line);
346 }
347
348 static void test_compoundarray(void)
349 {
350 GpStatus status;
351 GpPen *pen;
352 static const REAL testvalues[] = {0.2, 0.4, 0.6, 0.8};
353 INT count;
354
355 status = GdipSetPenCompoundArray(NULL, testvalues, 4);
356 expect(InvalidParameter, status);
357
358 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
359 expect(Ok, status);
360
361 status = GdipGetPenCompoundCount(NULL, NULL);
362 expect(InvalidParameter, status);
363
364 status = GdipGetPenCompoundCount(pen, NULL);
365 expect(InvalidParameter, status);
366
367 count = 10;
368 status = GdipGetPenCompoundCount(pen, &count);
369 todo_wine {
370 expect(Ok, status);
371 ok(count == 0, "Unexpected compound count %d\n", count);
372 }
373 status = GdipSetPenCompoundArray(pen, NULL, 0);
374 expect(InvalidParameter, status);
375 status = GdipSetPenCompoundArray(pen, NULL, 4);
376 expect(InvalidParameter, status);
377 status = GdipSetPenCompoundArray(pen, testvalues, 3);
378 expect(InvalidParameter, status);
379 status = GdipSetPenCompoundArray(pen, testvalues, 0);
380 expect(InvalidParameter, status);
381 status = GdipSetPenCompoundArray(pen, testvalues, -2);
382 expect(InvalidParameter, status);
383
384 status = GdipSetPenCompoundArray(pen, testvalues, 4);
385 todo_wine expect(Ok, status);
386 status = GdipSetPenCompoundArray(pen, NULL, 0);
387 expect(InvalidParameter, status);
388
389 count = 0;
390 status = GdipGetPenCompoundCount(pen, &count);
391 todo_wine {
392 expect(Ok, status);
393 ok(count == 4, "Unexpected compound count %d\n", count);
394 }
395 GdipDeletePen(pen);
396 }
397
398 static void test_transform(void)
399 {
400 GpStatus status;
401 GpPen *pen;
402 GpMatrix *matrix, *matrix2;
403 REAL values[6];
404
405 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
406 expect(Ok, status);
407
408 status = GdipCreateMatrix(&matrix);
409 expect(Ok, status);
410
411 status = GdipGetPenTransform(pen, matrix);
412 expect(Ok, status);
413
414 status = GdipGetMatrixElements(matrix, values);
415 expect(Ok, status);
416
417 expectf(1.0, values[0]);
418 expectf(0.0, values[1]);
419 expectf(0.0, values[2]);
420 expectf(1.0, values[3]);
421 expectf(0.0, values[4]);
422 expectf(0.0, values[5]);
423
424 GdipCreateMatrix2(3.0, -2.0, 5.0, 2.0, 6.0, 3.0, &matrix2);
425 status = GdipSetPenTransform(pen, matrix2);
426 expect(Ok, status);
427 GdipDeleteMatrix(matrix2);
428
429 status = GdipGetPenTransform(pen, matrix);
430 expect(Ok, status);
431 status = GdipGetMatrixElements(matrix, values);
432 expect(Ok, status);
433 expectf(3.0, values[0]);
434 expectf(-2.0, values[1]);
435 expectf(5.0, values[2]);
436 expectf(2.0, values[3]);
437 expectf(6.0, values[4]);
438 expectf(3.0, values[5]);
439
440 status = GdipResetPenTransform(pen);
441 expect(Ok, status);
442
443 status = GdipGetPenTransform(pen, matrix);
444 expect(Ok, status);
445 status = GdipGetMatrixElements(matrix, values);
446 expect(Ok, status);
447
448 expectf(1.0, values[0]);
449 expectf(0.0, values[1]);
450 expectf(0.0, values[2]);
451 expectf(1.0, values[3]);
452 expectf(0.0, values[4]);
453 expectf(0.0, values[5]);
454
455 GdipDeletePen(pen);
456
457 GdipDeleteMatrix(matrix);
458 }
459
460 START_TEST(pen)
461 {
462 struct GdiplusStartupInput gdiplusStartupInput;
463 ULONG_PTR gdiplusToken;
464
465 test_startup();
466
467 gdiplusStartupInput.GdiplusVersion = 1;
468 gdiplusStartupInput.DebugEventCallback = NULL;
469 gdiplusStartupInput.SuppressBackgroundThread = 0;
470 gdiplusStartupInput.SuppressExternalCodecs = 0;
471
472 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
473
474 test_constructor_destructor();
475 test_constructor_destructor2();
476 test_brushfill();
477 test_dasharray();
478 test_customcap();
479 test_penfilltype();
480 test_compoundarray();
481 test_transform();
482
483 GdiplusShutdown(gdiplusToken);
484 }