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