1 /*
2  * Unit test suite for brushes
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(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
29 
30 static HWND hwnd;
31 
32 static void test_constructor_destructor(void)
33 {
34     GpStatus status;
35     GpSolidFill *brush = NULL;
36 
37     status = GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
38     expect(Ok, status);
39     ok(brush != NULL, "Expected brush to be initialized\n");
40 
41     status = GdipDeleteBrush(NULL);
42     expect(InvalidParameter, status);
43 
44     status = GdipDeleteBrush((GpBrush*) brush);
45     expect(Ok, status);
46 }
47 
48 static void test_createHatchBrush(void)
49 {
50     GpStatus status;
51     GpHatch *brush;
52 
53     status = GdipCreateHatchBrush(HatchStyleMin, 1, 2, &brush);
54     expect(Ok, status);
55     ok(brush != NULL, "Expected the brush to be initialized.\n");
56 
57     GdipDeleteBrush((GpBrush *)brush);
58 
59     status = GdipCreateHatchBrush(HatchStyleMax, 1, 2, &brush);
60     expect(Ok, status);
61     ok(brush != NULL, "Expected the brush to be initialized.\n");
62 
63     GdipDeleteBrush((GpBrush *)brush);
64 
65     status = GdipCreateHatchBrush(HatchStyle05Percent, 1, 2, NULL);
66     expect(InvalidParameter, status);
67 
68     status = GdipCreateHatchBrush((HatchStyle)(HatchStyleMin - 1), 1, 2, &brush);
69     expect(InvalidParameter, status);
70 
71     status = GdipCreateHatchBrush((HatchStyle)(HatchStyleMax + 1), 1, 2, &brush);
72     expect(InvalidParameter, status);
73 }
74 
75 static void test_createLineBrushFromRectWithAngle(void)
76 {
77     GpStatus status;
78     GpLineGradient *brush;
79     GpRectF rect1 = { 1, 3, 1, 2 };
80     GpRectF rect2 = { 1, 3, -1, -2 };
81     GpRectF rect3 = { 1, 3, 0, 1 };
82     GpRectF rect4 = { 1, 3, 1, 0 };
83 
84     status = GdipCreateLineBrushFromRectWithAngle(&rect1, 10, 11, 0, TRUE, WrapModeTile, &brush);
85     expect(Ok, status);
86     GdipDeleteBrush((GpBrush *) brush);
87 
88     status = GdipCreateLineBrushFromRectWithAngle(&rect2, 10, 11, 135, TRUE, (WrapMode)(WrapModeTile - 1), &brush);
89     expect(Ok, status);
90     GdipDeleteBrush((GpBrush *) brush);
91 
92     status = GdipCreateLineBrushFromRectWithAngle(&rect2, 10, 11, -225, FALSE, (WrapMode)(WrapModeTile - 1), &brush);
93     expect(Ok, status);
94     GdipDeleteBrush((GpBrush *) brush);
95 
96     status = GdipCreateLineBrushFromRectWithAngle(&rect1, 10, 11, 405, TRUE, (WrapMode)(WrapModeClamp + 1), &brush);
97     expect(Ok, status);
98     GdipDeleteBrush((GpBrush *) brush);
99 
100     status = GdipCreateLineBrushFromRectWithAngle(&rect1, 10, 11, 45, FALSE, (WrapMode)(WrapModeClamp + 1), &brush);
101     expect(Ok, status);
102     GdipDeleteBrush((GpBrush *) brush);
103 
104     status = GdipCreateLineBrushFromRectWithAngle(&rect1, 10, 11, 90, TRUE, WrapModeTileFlipX, &brush);
105     expect(Ok, status);
106 
107     status = GdipCreateLineBrushFromRectWithAngle(NULL, 10, 11, 90, TRUE, WrapModeTile, &brush);
108     expect(InvalidParameter, status);
109 
110     status = GdipCreateLineBrushFromRectWithAngle(&rect3, 10, 11, 90, TRUE, WrapModeTileFlipXY, &brush);
111     expect(OutOfMemory, status);
112 
113     status = GdipCreateLineBrushFromRectWithAngle(&rect4, 10, 11, 90, TRUE, WrapModeTileFlipXY, &brush);
114     expect(OutOfMemory, status);
115 
116     status = GdipCreateLineBrushFromRectWithAngle(&rect3, 10, 11, 90, TRUE, WrapModeTileFlipXY, NULL);
117     expect(InvalidParameter, status);
118 
119     status = GdipCreateLineBrushFromRectWithAngle(&rect4, 10, 11, 90, TRUE, WrapModeTileFlipXY, NULL);
120     expect(InvalidParameter, status);
121 
122     status = GdipCreateLineBrushFromRectWithAngle(&rect3, 10, 11, 90, TRUE, WrapModeClamp, &brush);
123     expect(InvalidParameter, status);
124 
125     status = GdipCreateLineBrushFromRectWithAngle(&rect4, 10, 11, 90, TRUE, WrapModeClamp, &brush);
126     expect(InvalidParameter, status);
127 
128     status = GdipCreateLineBrushFromRectWithAngle(&rect1, 10, 11, 90, TRUE, WrapModeClamp, &brush);
129     expect(InvalidParameter, status);
130 
131     status = GdipCreateLineBrushFromRectWithAngle(&rect1, 10, 11, 90, TRUE, WrapModeTile, NULL);
132     expect(InvalidParameter, status);
133 
134     GdipDeleteBrush((GpBrush *) brush);
135 }
136 
137 static void test_type(void)
138 {
139     GpStatus status;
140     GpBrushType bt;
141     GpSolidFill *brush = NULL;
142 
143     GdipCreateSolidFill((ARGB)0xdeadbeef, &brush);
144 
145     status = GdipGetBrushType((GpBrush*)brush, &bt);
146     expect(Ok, status);
147     expect(BrushTypeSolidColor, bt);
148 
149     GdipDeleteBrush((GpBrush*) brush);
150 }
151 static GpPointF blendcount_ptf[] = {{0.0, 0.0},
152                                     {50.0, 50.0}};
153 static void test_gradientblendcount(void)
154 {
155     GpStatus status;
156     GpPathGradient *brush;
157     INT count;
158 
159     status = GdipCreatePathGradient(blendcount_ptf, 2, WrapModeClamp, &brush);
160     expect(Ok, status);
161 
162     status = GdipGetPathGradientBlendCount(NULL, NULL);
163     expect(InvalidParameter, status);
164     status = GdipGetPathGradientBlendCount(NULL, &count);
165     expect(InvalidParameter, status);
166     status = GdipGetPathGradientBlendCount(brush, NULL);
167     expect(InvalidParameter, status);
168 
169     status = GdipGetPathGradientBlendCount(brush, &count);
170     expect(Ok, status);
171     expect(1, count);
172 
173     GdipDeleteBrush((GpBrush*) brush);
174 }
175 
176 static GpPointF getblend_ptf[] = {{0.0, 0.0},
177                                   {50.0, 50.0}};
178 static void test_getblend(void)
179 {
180     GpStatus status;
181     GpPathGradient *brush;
182     REAL blends[4];
183     REAL pos[4];
184 
185     status = GdipCreatePathGradient(getblend_ptf, 2, WrapModeClamp, &brush);
186     expect(Ok, status);
187 
188     /* check some invalid parameters combinations */
189     status = GdipGetPathGradientBlend(NULL, NULL,  NULL, -1);
190     expect(InvalidParameter, status);
191     status = GdipGetPathGradientBlend(brush,NULL,  NULL, -1);
192     expect(InvalidParameter, status);
193     status = GdipGetPathGradientBlend(NULL, blends,NULL, -1);
194     expect(InvalidParameter, status);
195     status = GdipGetPathGradientBlend(NULL, NULL,  pos,  -1);
196     expect(InvalidParameter, status);
197     status = GdipGetPathGradientBlend(NULL, NULL,  NULL,  1);
198     expect(InvalidParameter, status);
199 
200     blends[0] = (REAL)0xdeadbeef;
201     pos[0]    = (REAL)0xdeadbeef;
202     status = GdipGetPathGradientBlend(brush, blends, pos, 1);
203     expect(Ok, status);
204     expectf(1.0, blends[0]);
205     expectf((REAL)0xdeadbeef, pos[0]);
206 
207     GdipDeleteBrush((GpBrush*) brush);
208 }
209 
210 static GpPointF getbounds_ptf[] = {{0.0, 20.0},
211                                    {50.0, 50.0},
212                                    {21.0, 25.0},
213                                    {25.0, 46.0}};
214 static void test_getbounds(void)
215 {
216     GpStatus status;
217     GpPathGradient *brush;
218     GpRectF bounds;
219 
220     status = GdipCreatePathGradient(getbounds_ptf, 4, WrapModeClamp, &brush);
221     expect(Ok, status);
222 
223     status = GdipGetPathGradientRect(NULL, NULL);
224     expect(InvalidParameter, status);
225     status = GdipGetPathGradientRect(brush, NULL);
226     expect(InvalidParameter, status);
227     status = GdipGetPathGradientRect(NULL, &bounds);
228     expect(InvalidParameter, status);
229 
230     status = GdipGetPathGradientRect(brush, &bounds);
231     expect(Ok, status);
232     expectf(0.0, bounds.X);
233     expectf(20.0, bounds.Y);
234     expectf(50.0, bounds.Width);
235     expectf(30.0, bounds.Height);
236 
237     GdipDeleteBrush((GpBrush*) brush);
238 }
239 
240 static void test_getgamma(void)
241 {
242     GpStatus status;
243     GpLineGradient *line;
244     GpPointF start, end;
245     BOOL gamma;
246 
247     start.X = start.Y = 0.0;
248     end.X = end.Y = 100.0;
249 
250     status = GdipCreateLineBrush(&start, &end, (ARGB)0xdeadbeef, 0xdeadbeef, WrapModeTile, &line);
251     expect(Ok, status);
252 
253     /* NULL arguments */
254     status = GdipGetLineGammaCorrection(NULL, NULL);
255     expect(InvalidParameter, status);
256     status = GdipGetLineGammaCorrection(line, NULL);
257     expect(InvalidParameter, status);
258     status = GdipGetLineGammaCorrection(NULL, &gamma);
259     expect(InvalidParameter, status);
260 
261     GdipDeleteBrush((GpBrush*)line);
262 }
263 
264 static void test_transform(void)
265 {
266     GpStatus status;
267     GpTexture *texture;
268     GpLineGradient *line;
269     GpGraphics *graphics = NULL;
270     GpBitmap *bitmap;
271     HDC hdc = GetDC(0);
272     GpMatrix *m, *m1;
273     BOOL res;
274     GpPointF start, end;
275     GpRectF rectf;
276     REAL elements[6];
277 
278     /* GpTexture */
279     status = GdipCreateMatrix2(2.0, 0.0, 0.0, 0.0, 0.0, 0.0, &m);
280     expect(Ok, status);
281 
282     status = GdipCreateFromHDC(hdc, &graphics);
283     expect(Ok, status);
284     status = GdipCreateBitmapFromGraphics(1, 1, graphics, &bitmap);
285     expect(Ok, status);
286 
287     status = GdipCreateTexture((GpImage*)bitmap, WrapModeTile, &texture);
288     expect(Ok, status);
289 
290     /* NULL */
291     status = GdipGetTextureTransform(NULL, NULL);
292     expect(InvalidParameter, status);
293     status = GdipGetTextureTransform(texture, NULL);
294     expect(InvalidParameter, status);
295 
296     /* get default value - identity matrix */
297     status = GdipGetTextureTransform(texture, m);
298     expect(Ok, status);
299     status = GdipIsMatrixIdentity(m, &res);
300     expect(Ok, status);
301     expect(TRUE, res);
302     /* set and get then */
303     status = GdipCreateMatrix2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0, &m1);
304     expect(Ok, status);
305     status = GdipSetTextureTransform(texture, m1);
306     expect(Ok, status);
307     status = GdipGetTextureTransform(texture, m);
308     expect(Ok, status);
309     status = GdipIsMatrixEqual(m, m1, &res);
310     expect(Ok, status);
311     expect(TRUE, res);
312     /* reset */
313     status = GdipResetTextureTransform(texture);
314     expect(Ok, status);
315     status = GdipGetTextureTransform(texture, m);
316     expect(Ok, status);
317     status = GdipIsMatrixIdentity(m, &res);
318     expect(Ok, status);
319     expect(TRUE, res);
320 
321     status = GdipDeleteBrush((GpBrush*)texture);
322     expect(Ok, status);
323 
324     status = GdipDeleteMatrix(m1);
325     expect(Ok, status);
326     status = GdipDeleteMatrix(m);
327     expect(Ok, status);
328     status = GdipDisposeImage((GpImage*)bitmap);
329     expect(Ok, status);
330     status = GdipDeleteGraphics(graphics);
331     expect(Ok, status);
332 
333 
334 
335     status = GdipCreateFromHWND(hwnd, &graphics);
336     expect(Ok, status);
337 
338     /* GpLineGradient */
339     /* create with vertical gradient line */
340     start.X = start.Y = end.X = 0.0;
341     end.Y = 100.0;
342 
343     status = GdipCreateLineBrush(&start, &end, (ARGB)0xffff0000, 0xff00ff00, WrapModeTile, &line);
344     expect(Ok, status);
345 
346     status = GdipCreateMatrix2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, &m);
347     expect(Ok, status);
348 
349     /* NULL arguments */
350     status = GdipResetLineTransform(NULL);
351     expect(InvalidParameter, status);
352     status = GdipSetLineTransform(NULL, m);
353     expect(InvalidParameter, status);
354     status = GdipSetLineTransform(line, NULL);
355     expect(InvalidParameter, status);
356     status = GdipGetLineTransform(NULL, m);
357     expect(InvalidParameter, status);
358     status = GdipGetLineTransform(line, NULL);
359     expect(InvalidParameter, status);
360     status = GdipScaleLineTransform(NULL, 1, 1, MatrixOrderPrepend);
361     expect(InvalidParameter, status);
362     status = GdipMultiplyLineTransform(NULL, m, MatrixOrderPrepend);
363     expect(InvalidParameter, status);
364     status = GdipTranslateLineTransform(NULL, 0, 0, MatrixOrderPrepend);
365     expect(InvalidParameter, status);
366 
367     /* initial transform */
368     status = GdipGetLineTransform(line, m);
369     expect(Ok, status);
370 
371     status = GdipGetMatrixElements(m, elements);
372     expect(Ok, status);
373     expectf(0.0, elements[0]);
374     expectf(1.0, elements[1]);
375     expectf(-1.0, elements[2]);
376     expectf(0.0, elements[3]);
377     expectf(50.0, elements[4]);
378     expectf(50.0, elements[5]);
379 
380     status = GdipGetLineRect(line, &rectf);
381     expect(Ok, status);
382     expectf(-50.0, rectf.X);
383     expectf(0.0, rectf.Y);
384     expectf(100.0, rectf.Width);
385     expectf(100.0, rectf.Height);
386 
387     status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 0, 200, 200);
388     expect(Ok, status);
389 
390     /* manually set transform */
391     GdipSetMatrixElements(m, 2.0, 0.0, 0.0, 4.0, 0.0, 0.0);
392 
393     status = GdipSetLineTransform(line, m);
394     expect(Ok, status);
395 
396     status = GdipGetLineTransform(line, m);
397     expect(Ok, status);
398 
399     status = GdipGetMatrixElements(m, elements);
400     expect(Ok, status);
401     expectf(2.0, elements[0]);
402     expectf(0.0, elements[1]);
403     expectf(0.0, elements[2]);
404     expectf(4.0, elements[3]);
405     expectf(0.0, elements[4]);
406     expectf(0.0, elements[5]);
407 
408     status = GdipGetLineRect(line, &rectf);
409     expect(Ok, status);
410     expectf(-50.0, rectf.X);
411     expectf(0.0, rectf.Y);
412     expectf(100.0, rectf.Width);
413     expectf(100.0, rectf.Height);
414 
415     status = GdipFillRectangle(graphics, (GpBrush*)line, 200, 0, 200, 200);
416     expect(Ok, status);
417 
418     /* scale transform */
419     status = GdipScaleLineTransform(line, 4.0, 0.5, MatrixOrderAppend);
420     expect(Ok, status);
421 
422     status = GdipGetLineTransform(line, m);
423     expect(Ok, status);
424 
425     status = GdipGetMatrixElements(m, elements);
426     expect(Ok, status);
427     expectf(8.0, elements[0]);
428     expectf(0.0, elements[1]);
429     expectf(0.0, elements[2]);
430     expectf(2.0, elements[3]);
431     expectf(0.0, elements[4]);
432     expectf(0.0, elements[5]);
433 
434     status = GdipGetLineRect(line, &rectf);
435     expect(Ok, status);
436     expectf(-50.0, rectf.X);
437     expectf(0.0, rectf.Y);
438     expectf(100.0, rectf.Width);
439     expectf(100.0, rectf.Height);
440 
441     status = GdipFillRectangle(graphics, (GpBrush*)line, 400, 0, 200, 200);
442     expect(Ok, status);
443 
444     /* translate transform */
445     status = GdipTranslateLineTransform(line, 10.0, -20.0, MatrixOrderAppend);
446     expect(Ok, status);
447 
448     status = GdipGetLineTransform(line, m);
449     expect(Ok, status);
450 
451     status = GdipGetMatrixElements(m, elements);
452     expect(Ok, status);
453     expectf(8.0, elements[0]);
454     expectf(0.0, elements[1]);
455     expectf(0.0, elements[2]);
456     expectf(2.0, elements[3]);
457     expectf(10.0, elements[4]);
458     expectf(-20.0, elements[5]);
459 
460     status = GdipGetLineRect(line, &rectf);
461     expect(Ok, status);
462     expectf(-50.0, rectf.X);
463     expectf(0.0, rectf.Y);
464     expectf(100.0, rectf.Width);
465     expectf(100.0, rectf.Height);
466 
467     status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 200, 200, 200);
468     expect(Ok, status);
469 
470     /* multiply transform */
471     GdipSetMatrixElements(m, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
472     GdipRotateMatrix(m, 45.0, MatrixOrderAppend);
473     GdipScaleMatrix(m, 0.25, 0.5, MatrixOrderAppend);
474 
475     status = GdipMultiplyLineTransform(line, m, MatrixOrderAppend);
476     expect(Ok, status);
477 
478     /* NULL transform does nothing */
479     status = GdipMultiplyLineTransform(line, NULL, MatrixOrderAppend);
480     expect(Ok, status);
481 
482     status = GdipGetLineTransform(line, m);
483     expect(Ok, status);
484 
485     status = GdipGetMatrixElements(m, elements);
486     expect(Ok, status);
487     expectf(1.414214, elements[0]);
488     expectf(2.828427, elements[1]);
489     expectf(-0.353553, elements[2]);
490     expectf(0.707107, elements[3]);
491     expectf(5.303300, elements[4]);
492     expectf(-3.535534, elements[5]);
493 
494     status = GdipGetLineRect(line, &rectf);
495     expect(Ok, status);
496     expectf(-50.0, rectf.X);
497     expectf(0.0, rectf.Y);
498     expectf(100.0, rectf.Width);
499     expectf(100.0, rectf.Height);
500 
501     status = GdipFillRectangle(graphics, (GpBrush*)line, 200, 200, 200, 200);
502     expect(Ok, status);
503 
504     /* reset transform sets to identity */
505     status = GdipResetLineTransform(line);
506     expect(Ok, status);
507 
508     status = GdipGetLineTransform(line, m);
509     expect(Ok, status);
510 
511     status = GdipGetMatrixElements(m, elements);
512     expect(Ok, status);
513     expectf(1.0, elements[0]);
514     expectf(0.0, elements[1]);
515     expectf(0.0, elements[2]);
516     expectf(1.0, elements[3]);
517     expectf(0.0, elements[4]);
518     expectf(0.0, elements[5]);
519 
520     status = GdipGetLineRect(line, &rectf);
521     expect(Ok, status);
522     expectf(-50.0, rectf.X);
523     expectf(0.0, rectf.Y);
524     expectf(100.0, rectf.Width);
525     expectf(100.0, rectf.Height);
526 
527     status = GdipFillRectangle(graphics, (GpBrush*)line, 400, 200, 200, 200);
528     expect(Ok, status);
529 
530     GdipDeleteBrush((GpBrush*)line);
531 
532     /* passing negative Width/Height to LinearGradientModeHorizontal */
533     rectf.X = rectf.Y = 10.0;
534     rectf.Width = rectf.Height = -100.0;
535     status = GdipCreateLineBrushFromRect(&rectf, (ARGB)0xffff0000, 0xff00ff00,
536             LinearGradientModeHorizontal, WrapModeTile, &line);
537     expect(Ok, status);
538     memset(&rectf, 0, sizeof(GpRectF));
539     status = GdipGetLineRect(line, &rectf);
540     expect(Ok, status);
541     expectf(10.0, rectf.X);
542     expectf(10.0, rectf.Y);
543     expectf(-100.0, rectf.Width);
544     expectf(-100.0, rectf.Height);
545     status = GdipGetLineTransform(line, m);
546     expect(Ok, status);
547     status = GdipGetMatrixElements(m, elements);
548     expect(Ok,status);
549     expectf(1.0, elements[0]);
550     expectf(0.0, elements[1]);
551     expectf(0.0, elements[2]);
552     expectf(1.0, elements[3]);
553     expectf(0.0, elements[4]);
554     expectf(0.0, elements[5]);
555     status = GdipFillRectangle(graphics, (GpBrush*)line, 0, 400, 200, 200);
556     expect(Ok, status);
557     status = GdipDeleteBrush((GpBrush*)line);
558     expect(Ok,status);
559 
560     if(0){
561         /* enable to visually compare with Windows */
562         MSG msg;
563         while(GetMessageW(&msg, hwnd, 0, 0) > 0){
564             TranslateMessage(&msg);
565             DispatchMessageW(&msg);
566         }
567     }
568 
569     GdipDeleteMatrix(m);
570     GdipDeleteGraphics(graphics);
571     ReleaseDC(0, hdc);
572 }
573 
574 static void test_texturewrap(void)
575 {
576     GpStatus status;
577     GpTexture *texture;
578     GpGraphics *graphics = NULL;
579     GpBitmap *bitmap;
580     HDC hdc = GetDC(0);
581     GpWrapMode wrap;
582 
583     status = GdipCreateFromHDC(hdc, &graphics);
584     expect(Ok, status);
585     status = GdipCreateBitmapFromGraphics(1, 1, graphics, &bitmap);
586     expect(Ok, status);
587 
588     status = GdipCreateTexture((GpImage*)bitmap, WrapModeTile, &texture);
589     expect(Ok, status);
590 
591     /* NULL */
592     status = GdipGetTextureWrapMode(NULL, NULL);
593     expect(InvalidParameter, status);
594     status = GdipGetTextureWrapMode(texture, NULL);
595     expect(InvalidParameter, status);
596     status = GdipGetTextureWrapMode(NULL, &wrap);
597     expect(InvalidParameter, status);
598 
599     /* get */
600     wrap = WrapModeClamp;
601     status = GdipGetTextureWrapMode(texture, &wrap);
602     expect(Ok, status);
603     expect(WrapModeTile, wrap);
604     /* set, then get */
605     wrap = WrapModeClamp;
606     status = GdipSetTextureWrapMode(texture, wrap);
607     expect(Ok, status);
608     wrap = WrapModeTile;
609     status = GdipGetTextureWrapMode(texture, &wrap);
610     expect(Ok, status);
611     expect(WrapModeClamp, wrap);
612 
613     status = GdipDeleteBrush((GpBrush*)texture);
614     expect(Ok, status);
615     status = GdipDisposeImage((GpImage*)bitmap);
616     expect(Ok, status);
617     status = GdipDeleteGraphics(graphics);
618     expect(Ok, status);
619     ReleaseDC(0, hdc);
620 }
621 
622 static void test_gradientgetrect(void)
623 {
624     GpLineGradient *brush;
625     GpMatrix *transform;
626     REAL elements[6];
627     GpRectF rectf;
628     GpStatus status;
629     GpPointF pt1, pt2;
630 
631     status = GdipCreateMatrix(&transform);
632     expect(Ok, status);
633 
634     pt1.X = pt1.Y = 1.0;
635     pt2.X = pt2.Y = 100.0;
636     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
637     expect(Ok, status);
638     memset(&rectf, 0, sizeof(GpRectF));
639     status = GdipGetLineRect(brush, &rectf);
640     expect(Ok, status);
641     expectf(1.0, rectf.X);
642     expectf(1.0, rectf.Y);
643     expectf(99.0, rectf.Width);
644     expectf(99.0, rectf.Height);
645     status = GdipGetLineTransform(brush, transform);
646     expect(Ok, status);
647     status = GdipGetMatrixElements(transform, elements);
648     expect(Ok, status);
649     expectf(1.0, elements[0]);
650     expectf(1.0, elements[1]);
651     expectf(-1.0, elements[2]);
652     expectf(1.0, elements[3]);
653     expectf(50.50, elements[4]);
654     expectf(-50.50, elements[5]);
655     status = GdipDeleteBrush((GpBrush*)brush);
656     expect(Ok, status);
657 
658     /* vertical gradient */
659     pt1.X = pt1.Y = pt2.X = 0.0;
660     pt2.Y = 10.0;
661     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
662     expect(Ok, status);
663     memset(&rectf, 0, sizeof(GpRectF));
664     status = GdipGetLineRect(brush, &rectf);
665     expect(Ok, status);
666     expectf(-5.0, rectf.X);
667     expectf(0.0, rectf.Y);
668     expectf(10.0, rectf.Width);
669     expectf(10.0, rectf.Height);
670     status = GdipGetLineTransform(brush, transform);
671     expect(Ok, status);
672     status = GdipGetMatrixElements(transform, elements);
673     expect(Ok, status);
674     expectf(0.0, elements[0]);
675     expectf(1.0, elements[1]);
676     expectf(-1.0, elements[2]);
677     expectf(0.0, elements[3]);
678     expectf(5.0, elements[4]);
679     expectf(5.0, elements[5]);
680     status = GdipDeleteBrush((GpBrush*)brush);
681     expect(Ok, status);
682 
683     /* horizontal gradient */
684     pt1.X = pt1.Y = pt2.Y = 0.0;
685     pt2.X = 10.0;
686     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
687     expect(Ok, status);
688     memset(&rectf, 0, sizeof(GpRectF));
689     status = GdipGetLineRect(brush, &rectf);
690     expect(Ok, status);
691     expectf(0.0, rectf.X);
692     expectf(-5.0, rectf.Y);
693     expectf(10.0, rectf.Width);
694     expectf(10.0, rectf.Height);
695     status = GdipGetLineTransform(brush, transform);
696     expect(Ok, status);
697     status = GdipGetMatrixElements(transform, elements);
698     expect(Ok, status);
699     expectf(1.0, elements[0]);
700     expectf(0.0, elements[1]);
701     expectf(0.0, elements[2]);
702     expectf(1.0, elements[3]);
703     expectf(0.0, elements[4]);
704     expectf(0.0, elements[5]);
705     status = GdipDeleteBrush((GpBrush*)brush);
706     expect(Ok, status);
707 
708     /* slope = -1 */
709     pt1.X = pt1.Y = 0.0;
710     pt2.X = 20.0;
711     pt2.Y = -20.0;
712     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
713     expect(Ok, status);
714     memset(&rectf, 0, sizeof(GpRectF));
715     status = GdipGetLineRect(brush, &rectf);
716     expect(Ok, status);
717     expectf(0.0, rectf.X);
718     expectf(-20.0, rectf.Y);
719     expectf(20.0, rectf.Width);
720     expectf(20.0, rectf.Height);
721     status = GdipGetLineTransform(brush, transform);
722     expect(Ok, status);
723     status = GdipGetMatrixElements(transform, elements);
724     expect(Ok, status);
725     expectf(1.0, elements[0]);
726     expectf(-1.0, elements[1]);
727     expectf(1.0, elements[2]);
728     expectf(1.0, elements[3]);
729     expectf(10.0, elements[4]);
730     expectf(10.0, elements[5]);
731     status = GdipDeleteBrush((GpBrush*)brush);
732     expect(Ok, status);
733 
734     /* slope = 1/100 */
735     pt1.X = pt1.Y = 0.0;
736     pt2.X = 100.0;
737     pt2.Y = 1.0;
738     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
739     expect(Ok, status);
740     memset(&rectf, 0, sizeof(GpRectF));
741     status = GdipGetLineRect(brush, &rectf);
742     expect(Ok, status);
743     expectf(0.0, rectf.X);
744     expectf(0.0, rectf.Y);
745     expectf(100.0, rectf.Width);
746     expectf(1.0, rectf.Height);
747     status = GdipGetLineTransform(brush, transform);
748     expect(Ok, status);
749     status = GdipGetMatrixElements(transform, elements);
750     expect(Ok,status);
751     expectf(1.0, elements[0]);
752     expectf(0.01, elements[1]);
753     expectf(-0.02, elements[2]);
754     /* expectf(2.0, elements[3]); */
755     expectf(0.01, elements[4]);
756     /* expectf(-1.0, elements[5]); */
757     status = GdipDeleteBrush((GpBrush*)brush);
758     expect(Ok,status);
759 
760     /* zero height rect */
761     rectf.X = rectf.Y = 10.0;
762     rectf.Width = 100.0;
763     rectf.Height = 0.0;
764     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeVertical,
765         WrapModeTile, &brush);
766     expect(OutOfMemory, status);
767 
768     /* zero width rect */
769     rectf.X = rectf.Y = 10.0;
770     rectf.Width = 0.0;
771     rectf.Height = 100.0;
772     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal,
773         WrapModeTile, &brush);
774     expect(OutOfMemory, status);
775 
776     /* from rect with LinearGradientModeHorizontal */
777     rectf.X = rectf.Y = 10.0;
778     rectf.Width = rectf.Height = 100.0;
779     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal,
780         WrapModeTile, &brush);
781     expect(Ok, status);
782     memset(&rectf, 0, sizeof(GpRectF));
783     status = GdipGetLineRect(brush, &rectf);
784     expect(Ok, status);
785     expectf(10.0, rectf.X);
786     expectf(10.0, rectf.Y);
787     expectf(100.0, rectf.Width);
788     expectf(100.0, rectf.Height);
789     status = GdipGetLineTransform(brush, transform);
790     expect(Ok, status);
791     status = GdipGetMatrixElements(transform, elements);
792     expect(Ok,status);
793     expectf(1.0, elements[0]);
794     expectf(0.0, elements[1]);
795     expectf(0.0, elements[2]);
796     expectf(1.0, elements[3]);
797     expectf(0.0, elements[4]);
798     expectf(0.0, elements[5]);
799     status = GdipDeleteBrush((GpBrush*)brush);
800     expect(Ok,status);
801 
802     /* passing negative Width/Height to LinearGradientModeHorizontal */
803     rectf.X = rectf.Y = 10.0;
804     rectf.Width = rectf.Height = -100.0;
805     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal,
806         WrapModeTile, &brush);
807     expect(Ok, status);
808     memset(&rectf, 0, sizeof(GpRectF));
809     status = GdipGetLineRect(brush, &rectf);
810     expect(Ok, status);
811     expectf(10.0, rectf.X);
812     expectf(10.0, rectf.Y);
813     expectf(-100.0, rectf.Width);
814     expectf(-100.0, rectf.Height);
815     status = GdipGetLineTransform(brush, transform);
816     expect(Ok, status);
817     status = GdipGetMatrixElements(transform, elements);
818     expect(Ok,status);
819     expectf(1.0, elements[0]);
820     expectf(0.0, elements[1]);
821     expectf(0.0, elements[2]);
822     expectf(1.0, elements[3]);
823     expectf(0.0, elements[4]);
824     expectf(0.0, elements[5]);
825     status = GdipDeleteBrush((GpBrush*)brush);
826     expect(Ok,status);
827 
828     /* reverse gradient line as immediately previous */
829     pt1.X = 10.0;
830     pt1.Y = 10.0;
831     pt2.X = -90.0;
832     pt2.Y = 10.0;
833     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
834     expect(Ok, status);
835     memset(&rectf, 0, sizeof(GpRectF));
836     status = GdipGetLineRect(brush, &rectf);
837     expect(Ok, status);
838     expectf(-90.0, rectf.X);
839     expectf(-40.0, rectf.Y);
840     expectf(100.0, rectf.Width);
841     expectf(100.0, rectf.Height);
842     status = GdipGetLineTransform(brush, transform);
843     expect(Ok, status);
844     status = GdipGetMatrixElements(transform, elements);
845     expect(Ok, status);
846     expectf(-1.0, elements[0]);
847     expectf(0.0, elements[1]);
848     expectf(0.0, elements[2]);
849     expectf(-1.0, elements[3]);
850     expectf(-80.0, elements[4]);
851     expectf(20.0, elements[5]);
852     status = GdipDeleteBrush((GpBrush*)brush);
853     expect(Ok, status);
854 
855     GdipDeleteMatrix(transform);
856 }
857 
858 static void test_lineblend(void)
859 {
860     GpLineGradient *brush;
861     GpStatus status;
862     GpPointF pt1, pt2;
863     INT count=10;
864     int i;
865     const REAL factors[5] = {0.0f, 0.1f, 0.5f, 0.9f, 1.0f};
866     const REAL positions[5] = {0.0f, 0.2f, 0.5f, 0.8f, 1.0f};
867     const REAL two_positions[2] = {0.0f, 1.0f};
868     const ARGB colors[5] = {0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffffffff};
869     REAL res_factors[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
870     REAL res_positions[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
871     ARGB res_colors[6] = {0xdeadbeef, 0, 0, 0, 0};
872 
873     pt1.X = pt1.Y = pt2.Y = pt2.X = 1.0;
874     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
875     expect(OutOfMemory, status);
876 
877     pt1.X = pt1.Y = 1.0;
878     pt2.X = pt2.Y = 100.0;
879     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
880     expect(Ok, status);
881 
882     status = GdipGetLineBlendCount(NULL, &count);
883     expect(InvalidParameter, status);
884 
885     status = GdipGetLineBlendCount(brush, NULL);
886     expect(InvalidParameter, status);
887 
888     status = GdipGetLineBlendCount(brush, &count);
889     expect(Ok, status);
890     expect(1, count);
891 
892     status = GdipGetLineBlend(NULL, res_factors, res_positions, 1);
893     expect(InvalidParameter, status);
894 
895     status = GdipGetLineBlend(brush, NULL, res_positions, 1);
896     expect(InvalidParameter, status);
897 
898     status = GdipGetLineBlend(brush, res_factors, NULL, 1);
899     expect(InvalidParameter, status);
900 
901     status = GdipGetLineBlend(brush, res_factors, res_positions, 0);
902     expect(InvalidParameter, status);
903 
904     status = GdipGetLineBlend(brush, res_factors, res_positions, -1);
905     expect(InvalidParameter, status);
906 
907     status = GdipGetLineBlend(brush, res_factors, res_positions, 1);
908     expect(Ok, status);
909 
910     status = GdipGetLineBlend(brush, res_factors, res_positions, 2);
911     expect(Ok, status);
912 
913     status = GdipSetLineBlend(NULL, factors, positions, 5);
914     expect(InvalidParameter, status);
915 
916     status = GdipSetLineBlend(brush, NULL, positions, 5);
917     expect(InvalidParameter, status);
918 
919     status = GdipSetLineBlend(brush, factors, NULL, 5);
920     expect(InvalidParameter, status);
921 
922     status = GdipSetLineBlend(brush, factors, positions, 0);
923     expect(InvalidParameter, status);
924 
925     status = GdipSetLineBlend(brush, factors, positions, -1);
926     expect(InvalidParameter, status);
927 
928     /* leave off the 0.0 position */
929     status = GdipSetLineBlend(brush, &factors[1], &positions[1], 4);
930     expect(InvalidParameter, status);
931 
932     /* leave off the 1.0 position */
933     status = GdipSetLineBlend(brush, factors, positions, 4);
934     expect(InvalidParameter, status);
935 
936     status = GdipSetLineBlend(brush, factors, positions, 5);
937     expect(Ok, status);
938 
939     status = GdipGetLineBlendCount(brush, &count);
940     expect(Ok, status);
941     expect(5, count);
942 
943     status = GdipGetLineBlend(brush, res_factors, res_positions, 4);
944     expect(InsufficientBuffer, status);
945 
946     status = GdipGetLineBlend(brush, res_factors, res_positions, 5);
947     expect(Ok, status);
948 
949     for (i=0; i<5; i++)
950     {
951         expectf(factors[i], res_factors[i]);
952         expectf(positions[i], res_positions[i]);
953     }
954 
955     status = GdipGetLineBlend(brush, res_factors, res_positions, 6);
956     expect(Ok, status);
957 
958     status = GdipSetLineBlend(brush, factors, positions, 1);
959     expect(Ok, status);
960 
961     status = GdipGetLineBlendCount(brush, &count);
962     expect(Ok, status);
963     expect(1, count);
964 
965     status = GdipGetLineBlend(brush, res_factors, res_positions, 1);
966     expect(Ok, status);
967 
968     status = GdipGetLinePresetBlendCount(NULL, &count);
969     expect(InvalidParameter, status);
970 
971     status = GdipGetLinePresetBlendCount(brush, NULL);
972     expect(InvalidParameter, status);
973 
974     status = GdipGetLinePresetBlendCount(brush, &count);
975     expect(Ok, status);
976     expect(0, count);
977 
978     status = GdipGetLinePresetBlend(NULL, res_colors, res_positions, 1);
979     expect(InvalidParameter, status);
980 
981     status = GdipGetLinePresetBlend(brush, NULL, res_positions, 1);
982     expect(InvalidParameter, status);
983 
984     status = GdipGetLinePresetBlend(brush, res_colors, NULL, 1);
985     expect(InvalidParameter, status);
986 
987     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 0);
988     expect(InvalidParameter, status);
989 
990     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, -1);
991     expect(InvalidParameter, status);
992 
993     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 1);
994     expect(InvalidParameter, status);
995 
996     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 2);
997     expect(GenericError, status);
998 
999     status = GdipSetLinePresetBlend(NULL, colors, positions, 5);
1000     expect(InvalidParameter, status);
1001 
1002     status = GdipSetLinePresetBlend(brush, NULL, positions, 5);
1003     expect(InvalidParameter, status);
1004 
1005     status = GdipSetLinePresetBlend(brush, colors, NULL, 5);
1006     expect(InvalidParameter, status);
1007 
1008     status = GdipSetLinePresetBlend(brush, colors, positions, 0);
1009     expect(InvalidParameter, status);
1010 
1011     status = GdipSetLinePresetBlend(brush, colors, positions, -1);
1012     expect(InvalidParameter, status);
1013 
1014     status = GdipSetLinePresetBlend(brush, colors, positions, 1);
1015     expect(InvalidParameter, status);
1016 
1017     /* leave off the 0.0 position */
1018     status = GdipSetLinePresetBlend(brush, &colors[1], &positions[1], 4);
1019     expect(InvalidParameter, status);
1020 
1021     /* leave off the 1.0 position */
1022     status = GdipSetLinePresetBlend(brush, colors, positions, 4);
1023     expect(InvalidParameter, status);
1024 
1025     status = GdipSetLinePresetBlend(brush, colors, positions, 5);
1026     expect(Ok, status);
1027 
1028     status = GdipGetLinePresetBlendCount(brush, &count);
1029     expect(Ok, status);
1030     expect(5, count);
1031 
1032     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 4);
1033     expect(InsufficientBuffer, status);
1034 
1035     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 5);
1036     expect(Ok, status);
1037 
1038     for (i=0; i<5; i++)
1039     {
1040         expect(colors[i], res_colors[i]);
1041         expectf(positions[i], res_positions[i]);
1042     }
1043 
1044     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 6);
1045     expect(Ok, status);
1046 
1047     status = GdipSetLinePresetBlend(brush, colors, two_positions, 2);
1048     expect(Ok, status);
1049 
1050     status = GdipDeleteBrush((GpBrush*)brush);
1051     expect(Ok, status);
1052 }
1053 
1054 static void test_linelinearblend(void)
1055 {
1056     GpLineGradient *brush;
1057     GpStatus status;
1058     GpPointF pt1, pt2;
1059     INT count=10;
1060     REAL res_factors[3] = {0.3f};
1061     REAL res_positions[3] = {0.3f};
1062 
1063     status = GdipSetLineLinearBlend(NULL, 0.6, 0.8);
1064     expect(InvalidParameter, status);
1065 
1066     pt1.X = pt1.Y = 1.0;
1067     pt2.X = pt2.Y = 100.0;
1068     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
1069     expect(Ok, status);
1070 
1071 
1072     status = GdipSetLineLinearBlend(brush, 0.6, 0.8);
1073     expect(Ok, status);
1074 
1075     status = GdipGetLineBlendCount(brush, &count);
1076     expect(Ok, status);
1077     expect(3, count);
1078 
1079     status = GdipGetLineBlend(brush, res_factors, res_positions, 3);
1080     expect(Ok, status);
1081     expectf(0.0, res_factors[0]);
1082     expectf(0.0, res_positions[0]);
1083     expectf(0.8, res_factors[1]);
1084     expectf(0.6, res_positions[1]);
1085     expectf(0.0, res_factors[2]);
1086     expectf(1.0, res_positions[2]);
1087 
1088 
1089     status = GdipSetLineLinearBlend(brush, 0.0, 0.8);
1090     expect(Ok, status);
1091 
1092     status = GdipGetLineBlendCount(brush, &count);
1093     expect(Ok, status);
1094     expect(2, count);
1095 
1096     status = GdipGetLineBlend(brush, res_factors, res_positions, 3);
1097     expect(Ok, status);
1098     expectf(0.8, res_factors[0]);
1099     expectf(0.0, res_positions[0]);
1100     expectf(0.0, res_factors[1]);
1101     expectf(1.0, res_positions[1]);
1102 
1103 
1104     status = GdipSetLineLinearBlend(brush, 1.0, 0.8);
1105     expect(Ok, status);
1106 
1107     status = GdipGetLineBlendCount(brush, &count);
1108     expect(Ok, status);
1109     expect(2, count);
1110 
1111     status = GdipGetLineBlend(brush, res_factors, res_positions, 3);
1112     expect(Ok, status);
1113     expectf(0.0, res_factors[0]);
1114     expectf(0.0, res_positions[0]);
1115     expectf(0.8, res_factors[1]);
1116     expectf(1.0, res_positions[1]);
1117 
1118     status = GdipDeleteBrush((GpBrush*)brush);
1119     expect(Ok, status);
1120 }
1121 
1122 static void test_gradientsurroundcolorcount(void)
1123 {
1124     GpStatus status;
1125     GpPathGradient *grad;
1126     ARGB color[3];
1127     INT count;
1128 
1129     status = GdipCreatePathGradient(blendcount_ptf, 2, WrapModeClamp, &grad);
1130     expect(Ok, status);
1131 
1132     count = 0;
1133     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1134     expect(Ok, status);
1135     expect(2, count);
1136 
1137     color[0] = color[1] = color[2] = 0xdeadbeef;
1138     count = 3;
1139     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1140     expect(Ok, status);
1141     expect(1, count);
1142     expect(0xffffffff, color[0]);
1143     expect(0xffffffff, color[1]);
1144     expect(0xdeadbeef, color[2]);
1145 
1146     color[0] = color[1] = color[2] = 0xdeadbeef;
1147     count = 2;
1148     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1149     expect(Ok, status);
1150     expect(1, count);
1151     expect(0xffffffff, color[0]);
1152     expect(0xffffffff, color[1]);
1153     expect(0xdeadbeef, color[2]);
1154 
1155     color[0] = color[1] = color[2] = 0xdeadbeef;
1156     count = 1;
1157     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1158     expect(InvalidParameter, status);
1159     expect(1, count);
1160     expect(0xdeadbeef, color[0]);
1161     expect(0xdeadbeef, color[1]);
1162     expect(0xdeadbeef, color[2]);
1163 
1164     color[0] = color[1] = color[2] = 0xdeadbeef;
1165     count = 0;
1166     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1167     expect(InvalidParameter, status);
1168     expect(0, count);
1169     expect(0xdeadbeef, color[0]);
1170     expect(0xdeadbeef, color[1]);
1171     expect(0xdeadbeef, color[2]);
1172 
1173     count = 3;
1174     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1175     expect(InvalidParameter, status);
1176 
1177     count = 2;
1178 
1179     color[0] = 0x00ff0000;
1180     color[1] = 0x0000ff00;
1181 
1182     status = GdipSetPathGradientSurroundColorsWithCount(NULL, color, &count);
1183     expect(InvalidParameter, status);
1184 
1185     status = GdipSetPathGradientSurroundColorsWithCount(grad, NULL, &count);
1186     expect(InvalidParameter, status);
1187 
1188     /* WinXP crashes on this test */
1189     if(0)
1190     {
1191         status = GdipSetPathGradientSurroundColorsWithCount(grad, color, NULL);
1192         expect(InvalidParameter, status);
1193     }
1194 
1195     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1196     expect(Ok, status);
1197     expect(2, count);
1198 
1199     status = GdipGetPathGradientSurroundColorCount(NULL, &count);
1200     expect(InvalidParameter, status);
1201 
1202     status = GdipGetPathGradientSurroundColorCount(grad, NULL);
1203     expect(InvalidParameter, status);
1204 
1205     count = 0;
1206     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1207     expect(Ok, status);
1208     expect(2, count);
1209 
1210     color[0] = color[1] = color[2] = 0xdeadbeef;
1211     count = 2;
1212     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1213     expect(Ok, status);
1214     expect(2, count);
1215     expect(0x00ff0000, color[0]);
1216     expect(0x0000ff00, color[1]);
1217     expect(0xdeadbeef, color[2]);
1218 
1219     count = 1;
1220     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1221     expect(Ok, status);
1222     expect(1, count);
1223 
1224     count = 0;
1225     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1226     expect(Ok, status);
1227     expect(2, count);
1228 
1229     /* If all colors are the same, count is set to 1. */
1230     color[0] = color[1] = 0;
1231     count = 2;
1232     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1233     expect(Ok, status);
1234     expect(2, count);
1235 
1236     color[0] = color[1] = color[2] = 0xdeadbeef;
1237     count = 2;
1238     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1239     expect(Ok, status);
1240     expect(1, count);
1241     expect(0x00000000, color[0]);
1242     expect(0x00000000, color[1]);
1243     expect(0xdeadbeef, color[2]);
1244 
1245     color[0] = color[1] = 0xff00ff00;
1246     count = 2;
1247     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1248     expect(Ok, status);
1249     expect(2, count);
1250 
1251     color[0] = color[1] = color[2] = 0xdeadbeef;
1252     count = 2;
1253     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1254     expect(Ok, status);
1255     expect(1, count);
1256     expect(0xff00ff00, color[0]);
1257     expect(0xff00ff00, color[1]);
1258     expect(0xdeadbeef, color[2]);
1259 
1260     count = 0;
1261     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1262     expect(InvalidParameter, status);
1263     expect(0, count);
1264 
1265     GdipDeleteBrush((GpBrush*)grad);
1266 
1267     status = GdipCreatePathGradient(getbounds_ptf, 3, WrapModeClamp, &grad);
1268     expect(Ok, status);
1269 
1270     color[0] = color[1] = color[2] = 0xdeadbeef;
1271     count = 3;
1272     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1273     expect(Ok, status);
1274     expect(1, count);
1275     expect(0xffffffff, color[0]);
1276     expect(0xffffffff, color[1]);
1277     expect(0xffffffff, color[2]);
1278 
1279     color[0] = color[1] = color[2] = 0xdeadbeef;
1280     count = 2;
1281     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1282     expect(InvalidParameter, status);
1283     expect(2, count);
1284     expect(0xdeadbeef, color[0]);
1285     expect(0xdeadbeef, color[1]);
1286     expect(0xdeadbeef, color[2]);
1287 
1288     count = 0;
1289     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1290     expect(Ok, status);
1291     expect(3, count);
1292 
1293     GdipDeleteBrush((GpBrush*)grad);
1294 }
1295 
1296 static void test_pathgradientpath(void)
1297 {
1298     GpStatus status;
1299     GpPath *path=NULL;
1300     GpPathGradient *grad=NULL;
1301 
1302     status = GdipCreatePathGradient(blendcount_ptf, 2, WrapModeClamp, &grad);
1303     expect(Ok, status);
1304 
1305     status = GdipGetPathGradientPath(grad, NULL);
1306     expect(NotImplemented, status);
1307 
1308     status = GdipCreatePath(FillModeWinding, &path);
1309     expect(Ok, status);
1310 
1311     status = GdipGetPathGradientPath(NULL, path);
1312     expect(NotImplemented, status);
1313 
1314     status = GdipGetPathGradientPath(grad, path);
1315     expect(NotImplemented, status);
1316 
1317     status = GdipDeletePath(path);
1318     expect(Ok, status);
1319 
1320     status = GdipDeleteBrush((GpBrush*)grad);
1321     expect(Ok, status);
1322 }
1323 
1324 static void test_pathgradientcenterpoint(void)
1325 {
1326     static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
1327     GpStatus status;
1328     GpPathGradient *grad;
1329     GpPointF point;
1330 
1331     status = GdipCreatePathGradient(path_points+1, 2, WrapModeClamp, &grad);
1332     expect(Ok, status);
1333 
1334     status = GdipGetPathGradientCenterPoint(NULL, &point);
1335     expect(InvalidParameter, status);
1336 
1337     status = GdipGetPathGradientCenterPoint(grad, NULL);
1338     expect(InvalidParameter, status);
1339 
1340     status = GdipGetPathGradientCenterPoint(grad, &point);
1341     expect(Ok, status);
1342     expectf(1.5, point.X);
1343     expectf(2.0, point.Y);
1344 
1345     status = GdipSetPathGradientCenterPoint(NULL, &point);
1346     expect(InvalidParameter, status);
1347 
1348     status = GdipSetPathGradientCenterPoint(grad, NULL);
1349     expect(InvalidParameter, status);
1350 
1351     point.X = 10.0;
1352     point.Y = 15.0;
1353     status = GdipSetPathGradientCenterPoint(grad, &point);
1354     expect(Ok, status);
1355 
1356     point.X = point.Y = -1;
1357     status = GdipGetPathGradientCenterPoint(grad, &point);
1358     expect(Ok, status);
1359     expectf(10.0, point.X);
1360     expectf(15.0, point.Y);
1361 
1362     status = GdipDeleteBrush((GpBrush*)grad);
1363     expect(Ok, status);
1364 
1365     status = GdipCreatePathGradient(path_points, 3, WrapModeClamp, &grad);
1366     expect(Ok, status);
1367 
1368     status = GdipGetPathGradientCenterPoint(grad, &point);
1369     expect(Ok, status);
1370     todo_wine expectf(1.0, point.X);
1371     todo_wine expectf(4.0/3.0, point.Y);
1372 
1373     status = GdipDeleteBrush((GpBrush*)grad);
1374     expect(Ok, status);
1375 }
1376 
1377 static void test_pathgradientpresetblend(void)
1378 {
1379     static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
1380     GpStatus status;
1381     GpPathGradient *grad;
1382     INT count;
1383     int i;
1384     const REAL positions[5] = {0.0f, 0.2f, 0.5f, 0.8f, 1.0f};
1385     const REAL two_positions[2] = {0.0f, 1.0f};
1386     const ARGB colors[5] = {0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffffffff};
1387     REAL res_positions[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
1388     ARGB res_colors[6] = {0xdeadbeef, 0, 0, 0, 0};
1389 
1390     status = GdipCreatePathGradient(path_points+1, 2, WrapModeClamp, &grad);
1391     expect(Ok, status);
1392 
1393     status = GdipGetPathGradientPresetBlendCount(NULL, &count);
1394     expect(InvalidParameter, status);
1395 
1396     status = GdipGetPathGradientPresetBlendCount(grad, NULL);
1397     expect(InvalidParameter, status);
1398 
1399     status = GdipGetPathGradientPresetBlendCount(grad, &count);
1400     expect(Ok, status);
1401     expect(0, count);
1402 
1403     status = GdipGetPathGradientPresetBlend(NULL, res_colors, res_positions, 1);
1404     expect(InvalidParameter, status);
1405 
1406     status = GdipGetPathGradientPresetBlend(grad, NULL, res_positions, 1);
1407     expect(InvalidParameter, status);
1408 
1409     status = GdipGetPathGradientPresetBlend(grad, res_colors, NULL, 1);
1410     expect(InvalidParameter, status);
1411 
1412     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 0);
1413     expect(InvalidParameter, status);
1414 
1415     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, -1);
1416     expect(OutOfMemory, status);
1417 
1418     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 1);
1419     expect(InvalidParameter, status);
1420 
1421     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 2);
1422     expect(GenericError, status);
1423 
1424     status = GdipSetPathGradientPresetBlend(NULL, colors, positions, 5);
1425     expect(InvalidParameter, status);
1426 
1427     status = GdipSetPathGradientPresetBlend(grad, NULL, positions, 5);
1428     expect(InvalidParameter, status);
1429 
1430     if (0)
1431     {
1432         /* crashes on windows xp */
1433         status = GdipSetPathGradientPresetBlend(grad, colors, NULL, 5);
1434         expect(InvalidParameter, status);
1435     }
1436 
1437     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 0);
1438     expect(InvalidParameter, status);
1439 
1440     status = GdipSetPathGradientPresetBlend(grad, colors, positions, -1);
1441     expect(InvalidParameter, status);
1442 
1443     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 1);
1444     expect(InvalidParameter, status);
1445 
1446     /* leave off the 0.0 position */
1447     status = GdipSetPathGradientPresetBlend(grad, &colors[1], &positions[1], 4);
1448     expect(InvalidParameter, status);
1449 
1450     /* leave off the 1.0 position */
1451     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 4);
1452     expect(InvalidParameter, status);
1453 
1454     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 5);
1455     expect(Ok, status);
1456 
1457     status = GdipGetPathGradientPresetBlendCount(grad, &count);
1458     expect(Ok, status);
1459     expect(5, count);
1460 
1461     if (0)
1462     {
1463         /* Native GdipGetPathGradientPresetBlend seems to copy starting from
1464          * the end of each array and do no bounds checking. This is so braindead
1465          * I'm not going to copy it. */
1466 
1467         res_colors[0] = 0xdeadbeef;
1468         res_positions[0] = 0.3;
1469 
1470         status = GdipGetPathGradientPresetBlend(grad, &res_colors[1], &res_positions[1], 4);
1471         expect(Ok, status);
1472 
1473         expect(0xdeadbeef, res_colors[0]);
1474         expectf(0.3, res_positions[0]);
1475 
1476         for (i=1; i<5; i++)
1477         {
1478             expect(colors[i], res_colors[i]);
1479             expectf(positions[i], res_positions[i]);
1480         }
1481 
1482         status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 6);
1483         expect(Ok, status);
1484 
1485         for (i=0; i<5; i++)
1486         {
1487             expect(colors[i], res_colors[i+1]);
1488             expectf(positions[i], res_positions[i+1]);
1489         }
1490     }
1491 
1492     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 5);
1493     expect(Ok, status);
1494 
1495     for (i=0; i<5; i++)
1496     {
1497         expect(colors[i], res_colors[i]);
1498         expectf(positions[i], res_positions[i]);
1499     }
1500 
1501     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 0);
1502     expect(InvalidParameter, status);
1503 
1504     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, -1);
1505     expect(OutOfMemory, status);
1506 
1507     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 1);
1508     expect(InvalidParameter, status);
1509 
1510     status = GdipSetPathGradientPresetBlend(grad, colors, two_positions, 2);
1511     expect(Ok, status);
1512 
1513     status = GdipDeleteBrush((GpBrush*)grad);
1514     expect(Ok, status);
1515 }
1516 
1517 static void test_pathgradientblend(void)
1518 {
1519     static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
1520     GpPathGradient *brush;
1521     GpStatus status;
1522     INT count, i;
1523     const REAL factors[5] = {0.0f, 0.1f, 0.5f, 0.9f, 1.0f};
1524     const REAL positions[5] = {0.0f, 0.2f, 0.5f, 0.8f, 1.0f};
1525     REAL res_factors[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
1526     REAL res_positions[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
1527 
1528     status = GdipCreatePathGradient(path_points, 3, WrapModeClamp, &brush);
1529     expect(Ok, status);
1530 
1531     status = GdipGetPathGradientBlendCount(NULL, &count);
1532     expect(InvalidParameter, status);
1533 
1534     status = GdipGetPathGradientBlendCount(brush, NULL);
1535     expect(InvalidParameter, status);
1536 
1537     status = GdipGetPathGradientBlendCount(brush, &count);
1538     expect(Ok, status);
1539     expect(1, count);
1540 
1541     status = GdipGetPathGradientBlend(NULL, res_factors, res_positions, 1);
1542     expect(InvalidParameter, status);
1543 
1544     status = GdipGetPathGradientBlend(brush, NULL, res_positions, 1);
1545     expect(InvalidParameter, status);
1546 
1547     status = GdipGetPathGradientBlend(brush, res_factors, NULL, 1);
1548     expect(InvalidParameter, status);
1549 
1550     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 0);
1551     expect(InvalidParameter, status);
1552 
1553     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, -1);
1554     expect(InvalidParameter, status);
1555 
1556     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 1);
1557     expect(Ok, status);
1558 
1559     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 2);
1560     expect(Ok, status);
1561 
1562     status = GdipSetPathGradientBlend(NULL, factors, positions, 5);
1563     expect(InvalidParameter, status);
1564 
1565     status = GdipSetPathGradientBlend(brush, NULL, positions, 5);
1566     expect(InvalidParameter, status);
1567 
1568     status = GdipSetPathGradientBlend(brush, factors, NULL, 5);
1569     expect(InvalidParameter, status);
1570 
1571     status = GdipSetPathGradientBlend(brush, factors, positions, 0);
1572     expect(InvalidParameter, status);
1573 
1574     status = GdipSetPathGradientBlend(brush, factors, positions, -1);
1575     expect(InvalidParameter, status);
1576 
1577     /* leave off the 0.0 position */
1578     status = GdipSetPathGradientBlend(brush, &factors[1], &positions[1], 4);
1579     expect(InvalidParameter, status);
1580 
1581     /* leave off the 1.0 position */
1582     status = GdipSetPathGradientBlend(brush, factors, positions, 4);
1583     expect(InvalidParameter, status);
1584 
1585     status = GdipSetPathGradientBlend(brush, factors, positions, 5);
1586     expect(Ok, status);
1587 
1588     status = GdipGetPathGradientBlendCount(brush, &count);
1589     expect(Ok, status);
1590     expect(5, count);
1591 
1592     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 4);
1593     expect(InsufficientBuffer, status);
1594 
1595     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 5);
1596     expect(Ok, status);
1597 
1598     for (i=0; i<5; i++)
1599     {
1600         expectf(factors[i], res_factors[i]);
1601         expectf(positions[i], res_positions[i]);
1602     }
1603 
1604     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 6);
1605     expect(Ok, status);
1606 
1607     status = GdipSetPathGradientBlend(brush, factors, positions, 1);
1608     expect(Ok, status);
1609 
1610     status = GdipGetPathGradientBlendCount(brush, &count);
1611     expect(Ok, status);
1612     expect(1, count);
1613 
1614     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 1);
1615     expect(Ok, status);
1616 
1617     status = GdipDeleteBrush((GpBrush*)brush);
1618     expect(Ok, status);
1619 }
1620 
1621 static void test_getHatchStyle(void)
1622 {
1623     GpStatus status;
1624     GpHatch *brush;
1625     GpHatchStyle hatchStyle;
1626 
1627     GdipCreateHatchBrush(HatchStyleHorizontal, 11, 12, &brush);
1628 
1629     status = GdipGetHatchStyle(NULL, &hatchStyle);
1630     expect(InvalidParameter, status);
1631 
1632     status = GdipGetHatchStyle(brush, NULL);
1633     expect(InvalidParameter, status);
1634 
1635     status = GdipGetHatchStyle(brush, &hatchStyle);
1636     expect(Ok, status);
1637     expect(HatchStyleHorizontal, hatchStyle);
1638 
1639     GdipDeleteBrush((GpBrush *)brush);
1640 }
1641 
1642 START_TEST(brush)
1643 {
1644     struct GdiplusStartupInput gdiplusStartupInput;
1645     ULONG_PTR gdiplusToken;
1646     HMODULE hmsvcrt;
1647     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
1648     WNDCLASSA class;
1649 
1650     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
1651     hmsvcrt = LoadLibraryA("msvcrt");
1652     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
1653     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
1654 
1655     memset( &class, 0, sizeof(class) );
1656     class.lpszClassName = "gdiplus_test";
1657     class.style = CS_HREDRAW | CS_VREDRAW;
1658     class.lpfnWndProc = DefWindowProcA;
1659     class.hInstance = GetModuleHandleA(0);
1660     class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
1661     class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
1662     class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1663     RegisterClassA( &class );
1664     hwnd = CreateWindowA( "gdiplus_test", "graphics test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1665                           CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, GetModuleHandleA(0), 0 );
1666     ok(hwnd != NULL, "Expected window to be created\n");
1667 
1668     gdiplusStartupInput.GdiplusVersion              = 1;
1669     gdiplusStartupInput.DebugEventCallback          = NULL;
1670     gdiplusStartupInput.SuppressBackgroundThread    = 0;
1671     gdiplusStartupInput.SuppressExternalCodecs      = 0;
1672 
1673     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1674 
1675     test_constructor_destructor();
1676     test_createHatchBrush();
1677     test_createLineBrushFromRectWithAngle();
1678     test_type();
1679     test_gradientblendcount();
1680     test_getblend();
1681     test_getbounds();
1682     test_getgamma();
1683     test_transform();
1684     test_texturewrap();
1685     test_gradientgetrect();
1686     test_lineblend();
1687     test_linelinearblend();
1688     test_gradientsurroundcolorcount();
1689     test_pathgradientpath();
1690     test_pathgradientcenterpoint();
1691     test_pathgradientpresetblend();
1692     test_pathgradientblend();
1693     test_getHatchStyle();
1694 
1695     GdiplusShutdown(gdiplusToken);
1696     DestroyWindow(hwnd);
1697 }
1698