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 "objbase.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 
test_startup(void)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 
test_constructor_destructor(void)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 
test_constructor_destructor2(void)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 
test_brushfill(void)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 
test_dasharray(void)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 
test_customcap(void)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 
test_penfilltype(void)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 
test_compoundarray(void)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     INT count;
348 
349     status = GdipSetPenCompoundArray(NULL, testvalues, 4);
350     expect(InvalidParameter, status);
351 
352     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
353     expect(Ok, status);
354 
355     status = GdipGetPenCompoundCount(NULL, NULL);
356     expect(InvalidParameter, status);
357 
358     status = GdipGetPenCompoundCount(pen, NULL);
359     expect(InvalidParameter, status);
360 
361     count = 10;
362     status = GdipGetPenCompoundCount(pen, &count);
363 todo_wine {
364     expect(Ok, status);
365     ok(count == 0, "Unexpected compound count %d\n", count);
366 }
367     status = GdipSetPenCompoundArray(pen, NULL, 0);
368     expect(InvalidParameter, status);
369     status = GdipSetPenCompoundArray(pen, NULL, 4);
370     expect(InvalidParameter, status);
371     status = GdipSetPenCompoundArray(pen, testvalues, 3);
372     expect(InvalidParameter, status);
373     status = GdipSetPenCompoundArray(pen, testvalues, 0);
374     expect(InvalidParameter, status);
375     status = GdipSetPenCompoundArray(pen, testvalues, -2);
376     expect(InvalidParameter, status);
377 
378     status = GdipSetPenCompoundArray(pen, testvalues, 4);
379     todo_wine expect(Ok, status);
380     status = GdipSetPenCompoundArray(pen, NULL, 0);
381     expect(InvalidParameter, status);
382 
383     count = 0;
384     status = GdipGetPenCompoundCount(pen, &count);
385 todo_wine {
386     expect(Ok, status);
387     ok(count == 4, "Unexpected compound count %d\n", count);
388 }
389     GdipDeletePen(pen);
390 }
391 
get_pen_transform(GpPen * pen,REAL * values)392 static void get_pen_transform(GpPen *pen, REAL *values)
393 {
394     GpMatrix *matrix;
395     GpStatus status;
396 
397     status = GdipCreateMatrix(&matrix);
398     expect(Ok, status);
399 
400     status = GdipGetPenTransform(pen, matrix);
401     expect(Ok, status);
402     status = GdipGetMatrixElements(matrix, values);
403     expect(Ok, status);
404 
405     GdipDeleteMatrix(matrix);
406 }
407 
test_transform(void)408 static void test_transform(void)
409 {
410     GpStatus status;
411     GpPen *pen;
412     GpMatrix *matrix, *matrix2;
413     REAL values[6];
414 
415     status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen);
416     expect(Ok, status);
417 
418     status = GdipCreateMatrix(&matrix);
419     expect(Ok, status);
420 
421     status = GdipGetPenTransform(pen, matrix);
422     expect(Ok, status);
423 
424     status = GdipGetMatrixElements(matrix, values);
425     expect(Ok, status);
426 
427     expectf(1.0, values[0]);
428     expectf(0.0, values[1]);
429     expectf(0.0, values[2]);
430     expectf(1.0, values[3]);
431     expectf(0.0, values[4]);
432     expectf(0.0, values[5]);
433 
434     GdipCreateMatrix2(3.0, -2.0, 5.0, 2.0, 6.0, 3.0, &matrix2);
435     status = GdipSetPenTransform(pen, matrix2);
436     expect(Ok, status);
437     GdipDeleteMatrix(matrix2);
438 
439     status = GdipGetPenTransform(pen, matrix);
440     expect(Ok, status);
441     status = GdipGetMatrixElements(matrix, values);
442     expect(Ok, status);
443     expectf(3.0,  values[0]);
444     expectf(-2.0,  values[1]);
445     expectf(5.0,  values[2]);
446     expectf(2.0, values[3]);
447     expectf(6.0, values[4]);
448     expectf(3.0,  values[5]);
449 
450     /* Translate */
451     status = GdipTranslatePenTransform(NULL, 1.0, -2.0, MatrixOrderAppend);
452     expect(InvalidParameter, status);
453 
454     status = GdipTranslatePenTransform(pen, 1.0, -2.0, MatrixOrderAppend);
455     expect(Ok, status);
456 
457     status = GdipGetPenTransform(pen, matrix);
458     expect(Ok, status);
459     status = GdipGetMatrixElements(matrix, values);
460     expect(Ok, status);
461     expectf(3.0,  values[0]);
462     expectf(-2.0,  values[1]);
463     expectf(5.0,  values[2]);
464     expectf(2.0, values[3]);
465     expectf(7.0, values[4]);
466     expectf(1.0,  values[5]);
467 
468     status = GdipTranslatePenTransform(pen, -3.0, 5.0, MatrixOrderPrepend);
469     expect(Ok, status);
470 
471     status = GdipGetPenTransform(pen, matrix);
472     expect(Ok, status);
473     status = GdipGetMatrixElements(matrix, values);
474     expect(Ok, status);
475     expectf(3.0,  values[0]);
476     expectf(-2.0,  values[1]);
477     expectf(5.0,  values[2]);
478     expectf(2.0, values[3]);
479     expectf(23.0, values[4]);
480     expectf(17.0,  values[5]);
481 
482     status = GdipResetPenTransform(pen);
483     expect(Ok, status);
484 
485     status = GdipGetPenTransform(pen, matrix);
486     expect(Ok, status);
487     status = GdipGetMatrixElements(matrix, values);
488     expect(Ok, status);
489 
490     expectf(1.0, values[0]);
491     expectf(0.0, values[1]);
492     expectf(0.0, values[2]);
493     expectf(1.0, values[3]);
494     expectf(0.0, values[4]);
495     expectf(0.0, values[5]);
496 
497     /* Scale */
498     status = GdipScalePenTransform(NULL, 1.0, 1.0, MatrixOrderPrepend);
499     expect(InvalidParameter, status);
500 
501     status = GdipScalePenTransform(pen, 1.0, 1.0, MatrixOrderPrepend);
502     expect(Ok, status);
503 
504     get_pen_transform(pen, values);
505     expectf(1.0, values[0]);
506     expectf(0.0, values[1]);
507     expectf(0.0, values[2]);
508     expectf(1.0, values[3]);
509     expectf(0.0, values[4]);
510     expectf(0.0, values[5]);
511 
512     status = GdipScalePenTransform(pen, 2.0, -10.0, MatrixOrderPrepend);
513     expect(Ok, status);
514 
515     get_pen_transform(pen, values);
516     expectf(2.0, values[0]);
517     expectf(0.0, values[1]);
518     expectf(0.0, values[2]);
519     expectf(-10.0, values[3]);
520     expectf(0.0, values[4]);
521     expectf(0.0, values[5]);
522 
523     status = GdipScalePenTransform(pen, 2.0, -10.0, MatrixOrderAppend);
524     expect(Ok, status);
525 
526     get_pen_transform(pen, values);
527     expectf(4.0, values[0]);
528     expectf(0.0, values[1]);
529     expectf(0.0, values[2]);
530     expectf(100.0, values[3]);
531     expectf(0.0, values[4]);
532     expectf(0.0, values[5]);
533 
534     status = GdipTranslatePenTransform(pen, 1.0, -2.0, MatrixOrderAppend);
535     expect(Ok, status);
536 
537     get_pen_transform(pen, values);
538     expectf(4.0, values[0]);
539     expectf(0.0, values[1]);
540     expectf(0.0, values[2]);
541     expectf(100.0, values[3]);
542     expectf(1.0, values[4]);
543     expectf(-2.0, values[5]);
544 
545     status = GdipScalePenTransform(pen, 2.0, -10.0, MatrixOrderPrepend);
546     expect(Ok, status);
547 
548     get_pen_transform(pen, values);
549     expectf(8.0, values[0]);
550     expectf(0.0, values[1]);
551     expectf(0.0, values[2]);
552     expectf(-1000.0, values[3]);
553     expectf(1.0, values[4]);
554     expectf(-2.0, values[5]);
555 
556     /* Multiply */
557     status = GdipResetPenTransform(pen);
558     expect(Ok, status);
559 
560     status = GdipSetMatrixElements(matrix, 2.0, 1.0, 1.0, 4.0, 1.0, 2.0);
561     expect(Ok, status);
562 
563     status = GdipMultiplyPenTransform(NULL, matrix, MatrixOrderPrepend);
564     expect(InvalidParameter, status);
565 
566     status = GdipMultiplyPenTransform(pen, matrix, MatrixOrderPrepend);
567     expect(Ok, status);
568 
569     get_pen_transform(pen, values);
570     expectf(2.0, values[0]);
571     expectf(1.0, values[1]);
572     expectf(1.0, values[2]);
573     expectf(4.0, values[3]);
574     expectf(1.0, values[4]);
575     expectf(2.0, values[5]);
576 
577     status = GdipScalePenTransform(pen, 2.0, -10.0, MatrixOrderAppend);
578     expect(Ok, status);
579 
580     status = GdipMultiplyPenTransform(pen, matrix, MatrixOrderAppend);
581     expect(Ok, status);
582 
583     get_pen_transform(pen, values);
584     expectf(-2.0, values[0]);
585     expectf(-36.0, values[1]);
586     expectf(-36.0, values[2]);
587     expectf(-158.0, values[3]);
588     expectf(-15.0, values[4]);
589     expectf(-76.0, values[5]);
590 
591     /* Rotate */
592     status = GdipResetPenTransform(pen);
593     expect(Ok, status);
594 
595     status = GdipSetMatrixElements(matrix, 2.0, 1.0, 1.0, 4.0, 1.0, 2.0);
596     expect(Ok, status);
597 
598     status = GdipSetPenTransform(pen, matrix);
599     expect(Ok, status);
600 
601     status = GdipRotatePenTransform(NULL, 10.0, MatrixOrderPrepend);
602     expect(InvalidParameter, status);
603 
604     status = GdipRotatePenTransform(pen, 45.0, MatrixOrderPrepend);
605     expect(Ok, status);
606 
607     get_pen_transform(pen, values);
608     expectf(2.12, values[0]);
609     expectf(3.54, values[1]);
610     expectf(-0.71, values[2]);
611     expectf(2.12, values[3]);
612     expectf(1.0, values[4]);
613     expectf(2.0, values[5]);
614 
615     status = GdipScalePenTransform(pen, 2.0, -10.0, MatrixOrderAppend);
616     expect(Ok, status);
617 
618     status = GdipRotatePenTransform(pen, 180.0, MatrixOrderAppend);
619     expect(Ok, status);
620 
621     get_pen_transform(pen, values);
622     expectf(-4.24, values[0]);
623     expectf(35.36, values[1]);
624     expectf(1.41, values[2]);
625     expectf(21.21, values[3]);
626     expectf(-2.0, values[4]);
627     expectf(20.0, values[5]);
628 
629     GdipDeletePen(pen);
630 
631     GdipDeleteMatrix(matrix);
632 }
633 
START_TEST(pen)634 START_TEST(pen)
635 {
636     struct GdiplusStartupInput gdiplusStartupInput;
637     ULONG_PTR gdiplusToken;
638     HMODULE hmsvcrt;
639     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
640 
641     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
642     hmsvcrt = LoadLibraryA("msvcrt");
643     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
644     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
645 
646     test_startup();
647 
648     gdiplusStartupInput.GdiplusVersion              = 1;
649     gdiplusStartupInput.DebugEventCallback          = NULL;
650     gdiplusStartupInput.SuppressBackgroundThread    = 0;
651     gdiplusStartupInput.SuppressExternalCodecs      = 0;
652 
653     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
654 
655     test_constructor_destructor();
656     test_constructor_destructor2();
657     test_brushfill();
658     test_dasharray();
659     test_customcap();
660     test_penfilltype();
661     test_compoundarray();
662     test_transform();
663 
664     GdiplusShutdown(gdiplusToken);
665 }
666