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     static const struct
625     {
626         LinearGradientMode mode;
627         GpRectF rect;
628         REAL transform[6];
629     }
630     create_from_rect[] =
631     {
632         { LinearGradientModeHorizontal, { 10.0f, 10.0f, -100.0f, -100.0f } },
633         { LinearGradientModeHorizontal, { 10.0f, 10.0f, 100.0f, 100.0f } },
634         { LinearGradientModeHorizontal, { 10.0f, -5.0f, 100.0f, 50.0f } },
635         { LinearGradientModeHorizontal, { -5.0f, 10.0f, 100.0f, 50.0f } },
636         { LinearGradientModeVertical, { 0.0f, 0.0f, 100.0f, 10.0f }, { 0.0f, 0.1f, -10.0f, -0.0f, 100.0f, 0.0f } },
637         { LinearGradientModeVertical, { 10.0f, -12.0f, 100.0f, 105.0f }, { 0.0f, 1.05f, -0.952f, 0.0f, 98.571f, -22.5f } },
638     };
639     static const struct
640     {
641         GpPointF pt1, pt2;
642         GpRectF rect;
643         REAL transform[6];
644     }
645     create_from_pt[] =
646     {
647         { { 1.0f, 1.0f }, { 100.0f, 100.0f }, { 1.0f, 1.0f, 99.0f, 99.0f }, { 1.0f, 1.0f, -1.0f, 1.0f, 50.50f, -50.50f } },
648         { { 0.0f, 0.0f }, { 0.0f, 10.0f }, { -5.0f, 0.0f, 10.0f, 10.0f }, { 0.0f, 1.0f, -1.0f, 0.0f, 5.0f, 5.0f } },
649         { { 0.0f, 0.0f }, { 10.0f, 0.0f }, { 0.0f, -5.0f, 10.0f, 10.0f }, { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f } },
650         /* Slope = -1 */
651         { { 0.0f, 0.0f }, { 20.0f, -20.0f }, { 0.0f, -20.0f, 20.0f, 20.0f }, { 1.0f, -1.0f, 1.0f, 1.0f, 10.0f, 10.0f } },
652         /* Slope = 1/100 */
653         { { 0.0f, 0.0f }, { 100.0f, 1.0f }, { 0.0f, 0.0f, 100.0f, 1.0f }, { 1.0f, 0.01f, -0.02f, 2.0f, 0.01f, -1.0f } },
654         { { 10.0f, 10.0f }, { -90.0f, 10.0f }, { -90.0f, -40.0f, 100.0f, 100.0f }, { -1.0f, 0.0f, 0.0f, -1.0f, -80.0f, 20.0f } },
655     };
656     static const struct
657     {
658         GpRectF rect;
659         REAL angle;
660         BOOL is_scalable;
661         REAL transform[6];
662     }
663     create_with_angle[] =
664     {
665         { { 10.0f, 10.0f, -100.0f, -100.0f }, 0.0f, TRUE },
666         { { 10.0f, 10.0f, -100.0f, -100.0f }, 0.0f, FALSE },
667         { { 10.0f, 10.0f, 100.0f, 100.0f }, 0.0f, FALSE },
668         { { 10.0f, 10.0f, 100.0f, 100.0f }, 0.0f, TRUE },
669         { { 10.0f, -5.0f, 100.0f, 50.0f }, 0.0f, FALSE },
670         { { 10.0f, -5.0f, 100.0f, 50.0f }, 0.0f, TRUE },
671         { { -5.0f, 10.0f, 100.0f, 50.0f }, 0.0f, FALSE },
672         { { -5.0f, 10.0f, 100.0f, 50.0f }, 0.0f, TRUE },
673         { { 0.0f, 0.0f, 100.0f, 10.0f }, -90.0f, TRUE, { 0.0f, -0.1f, 10.0f, 0.0f, 0.0f, 10.0f } },
674         { { 10.0f, -12.0f, 100.0f, 105.0f }, -90.0f, TRUE, { 0.0f, -1.05f, 0.952f, 0.0f, 21.429f, 103.5f } },
675         { { 0.0f, 0.0f, 100.0f, 10.0f }, -90.0f, FALSE, { 0.0f, -0.1f, 10.0f, -0.0f, 0.0f, 10.0f } },
676         { { 10.0f, -12.0f, 100.0f, 105.0f }, -90.0f, FALSE, { 0.0f, -1.05f, 0.952f, 0.0f, 21.429f, 103.5f } },
677     };
678     GpLineGradient *brush;
679     GpMatrix *transform;
680     REAL elements[6];
681     GpStatus status;
682     unsigned int i;
683     ARGB colors[2];
684     GpRectF rectf;
685 
686     status = GdipCreateMatrix(&transform);
687     expect(Ok, status);
688 
689     for (i = 0; i < ARRAY_SIZE(create_from_pt); ++i)
690     {
691         status = GdipCreateLineBrush(&create_from_pt[i].pt1, &create_from_pt[i].pt2, 0x1, 0x2, WrapModeTile, &brush);
692         ok(status == Ok, "Failed to create a brush, %d.\n", status);
693 
694         memset(&rectf, 0, sizeof(rectf));
695         status = GdipGetLineRect(brush, &rectf);
696         ok(status == Ok, "Failed to get brush rect, %d.\n", status);
697         ok(!memcmp(&rectf, &create_from_pt[i].rect, sizeof(rectf)), "Unexpected brush rect.\n");
698 
699         status = GdipGetLineTransform(brush, transform);
700         ok(status == Ok, "Failed to get brush transform, %d.\n", status);
701 
702         status = GdipGetMatrixElements(transform, elements);
703         ok(status == Ok, "Failed to get matrix elements, %d.\n", status);
704 
705 #define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got)
706         expectf2(create_from_pt[i].transform[0], elements[0]);
707         expectf2(create_from_pt[i].transform[1], elements[1]);
708         expectf2(create_from_pt[i].transform[2], elements[2]);
709         expectf2(create_from_pt[i].transform[3], elements[3]);
710         expectf2(create_from_pt[i].transform[4], elements[4]);
711         expectf2(create_from_pt[i].transform[5], elements[5]);
712 #undef expect2f
713 
714         status = GdipGetLineColors(brush, colors);
715         ok(status == Ok, "Failed to get line colors, %d.\n", status);
716         ok(colors[0] == 0x1 && colors[1] == 0x2, "Unexpected brush colors.\n");
717 
718         status = GdipDeleteBrush((GpBrush *)brush);
719         ok(status == Ok, "Failed to delete a brush, %d.\n", status);
720     }
721 
722     /* zero height rect */
723     rectf.X = rectf.Y = 10.0;
724     rectf.Width = 100.0;
725     rectf.Height = 0.0;
726     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeVertical,
727         WrapModeTile, &brush);
728     expect(OutOfMemory, status);
729 
730     /* zero width rect */
731     rectf.X = rectf.Y = 10.0;
732     rectf.Width = 0.0;
733     rectf.Height = 100.0;
734     status = GdipCreateLineBrushFromRect(&rectf, 0, 0, LinearGradientModeHorizontal,
735         WrapModeTile, &brush);
736     expect(OutOfMemory, status);
737 
738     for (i = 0; i < ARRAY_SIZE(create_from_rect); ++i)
739     {
740         ARGB colors[2];
741         BOOL ret;
742 
743         status = GdipCreateLineBrushFromRect(&create_from_rect[i].rect, 0x1, 0x2, create_from_rect[i].mode,
744             WrapModeTile, &brush);
745         ok(status == Ok, "Failed to create a brush, %d.\n", status);
746 
747         memset(&rectf, 0, sizeof(rectf));
748         status = GdipGetLineRect(brush, &rectf);
749         ok(status == Ok, "Failed to get brush rect, %d.\n", status);
750         ok(!memcmp(&rectf, &create_from_rect[i].rect, sizeof(rectf)), "Unexpected brush rect.\n");
751 
752         status = GdipGetLineTransform(brush, transform);
753         ok(status == Ok, "Failed to get brush transform, %d.\n", status);
754 
755         if (create_from_rect[i].mode == LinearGradientModeHorizontal)
756         {
757             status = GdipIsMatrixIdentity(transform, &ret);
758             ok(status == Ok, "Unexpected ret value %d.\n", status);
759         }
760         else
761         {
762             status = GdipGetMatrixElements(transform, elements);
763             ok(status == Ok, "Failed to get matrix elements, %d.\n", status);
764 
765 #define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got)
766             expectf2(create_from_rect[i].transform[0], elements[0]);
767             expectf2(create_from_rect[i].transform[1], elements[1]);
768             expectf2(create_from_rect[i].transform[2], elements[2]);
769             expectf2(create_from_rect[i].transform[3], elements[3]);
770             expectf2(create_from_rect[i].transform[4], elements[4]);
771             expectf2(create_from_rect[i].transform[5], elements[5]);
772 #undef expectf2
773         }
774 
775         status = GdipGetLineColors(brush, colors);
776         ok(status == Ok, "Failed to get line colors, %d.\n", status);
777         ok(colors[0] == 0x1 && colors[1] == 0x2, "Unexpected brush colors.\n");
778 
779         status = GdipDeleteBrush((GpBrush*)brush);
780         ok(status == Ok, "Failed to delete a brush, %d.\n", status);
781     }
782 
783     for (i = 0; i < ARRAY_SIZE(create_with_angle); ++i)
784     {
785         ARGB colors[2];
786         BOOL ret;
787 
788         status = GdipCreateLineBrushFromRectWithAngle(&create_with_angle[i].rect, 0x1, 0x2, create_with_angle[i].angle,
789             create_with_angle[i].is_scalable, WrapModeTile, &brush);
790         ok(status == Ok, "Failed to create a brush, %d.\n", status);
791 
792         memset(&rectf, 0, sizeof(rectf));
793         status = GdipGetLineRect(brush, &rectf);
794         ok(status == Ok, "Failed to get brush rect, %d.\n", status);
795         ok(!memcmp(&rectf, &create_with_angle[i].rect, sizeof(rectf)), "%u: unexpected brush rect {%f,%f,%f,%f}.\n",
796             i, rectf.X, rectf.Y, rectf.Width, rectf.Height);
797 
798         status = GdipGetLineTransform(brush, transform);
799         ok(status == Ok, "Failed to get brush transform, %d.\n", status);
800 
801         if (create_with_angle[i].angle == 0.0f)
802         {
803             status = GdipIsMatrixIdentity(transform, &ret);
804             ok(status == Ok, "Unexpected ret value %d.\n", status);
805         }
806         else
807         {
808             status = GdipGetMatrixElements(transform, elements);
809             ok(status == Ok, "Failed to get matrix elements, %d.\n", status);
810 
811 #define expectf2(expected, got) ok(fabs(expected - got) < 0.001, "%u: expected %.3f, got %.3f.\n", i, expected, got)
812             expectf2(create_with_angle[i].transform[0], elements[0]);
813             expectf2(create_with_angle[i].transform[1], elements[1]);
814             expectf2(create_with_angle[i].transform[2], elements[2]);
815             expectf2(create_with_angle[i].transform[3], elements[3]);
816             expectf2(create_with_angle[i].transform[4], elements[4]);
817             expectf2(create_with_angle[i].transform[5], elements[5]);
818 #undef expectf2
819         }
820 
821         status = GdipGetLineColors(brush, colors);
822         ok(status == Ok, "Failed to get line colors, %d.\n", status);
823         ok(colors[0] == 0x1 && colors[1] == 0x2, "Unexpected brush colors.\n");
824 
825         status = GdipDeleteBrush((GpBrush*)brush);
826         ok(status == Ok, "Failed to delete a brush, %d.\n", status);
827     }
828 
829     GdipDeleteMatrix(transform);
830 }
831 
832 static void test_lineblend(void)
833 {
834     GpLineGradient *brush;
835     GpStatus status;
836     GpPointF pt1, pt2;
837     INT count=10;
838     int i;
839     const REAL factors[5] = {0.0f, 0.1f, 0.5f, 0.9f, 1.0f};
840     const REAL positions[5] = {0.0f, 0.2f, 0.5f, 0.8f, 1.0f};
841     const REAL two_positions[2] = {0.0f, 1.0f};
842     const ARGB colors[5] = {0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffffffff};
843     REAL res_factors[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
844     REAL res_positions[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
845     ARGB res_colors[6] = {0xdeadbeef, 0, 0, 0, 0};
846 
847     pt1.X = pt1.Y = pt2.Y = pt2.X = 1.0;
848     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
849     expect(OutOfMemory, status);
850 
851     pt1.X = pt1.Y = 1.0;
852     pt2.X = pt2.Y = 100.0;
853     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
854     expect(Ok, status);
855 
856     status = GdipGetLineBlendCount(NULL, &count);
857     expect(InvalidParameter, status);
858 
859     status = GdipGetLineBlendCount(brush, NULL);
860     expect(InvalidParameter, status);
861 
862     status = GdipGetLineBlendCount(brush, &count);
863     expect(Ok, status);
864     expect(1, count);
865 
866     status = GdipGetLineBlend(NULL, res_factors, res_positions, 1);
867     expect(InvalidParameter, status);
868 
869     status = GdipGetLineBlend(brush, NULL, res_positions, 1);
870     expect(InvalidParameter, status);
871 
872     status = GdipGetLineBlend(brush, res_factors, NULL, 1);
873     expect(InvalidParameter, status);
874 
875     status = GdipGetLineBlend(brush, res_factors, res_positions, 0);
876     expect(InvalidParameter, status);
877 
878     status = GdipGetLineBlend(brush, res_factors, res_positions, -1);
879     expect(InvalidParameter, status);
880 
881     status = GdipGetLineBlend(brush, res_factors, res_positions, 1);
882     expect(Ok, status);
883 
884     status = GdipGetLineBlend(brush, res_factors, res_positions, 2);
885     expect(Ok, status);
886 
887     status = GdipSetLineBlend(NULL, factors, positions, 5);
888     expect(InvalidParameter, status);
889 
890     status = GdipSetLineBlend(brush, NULL, positions, 5);
891     expect(InvalidParameter, status);
892 
893     status = GdipSetLineBlend(brush, factors, NULL, 5);
894     expect(InvalidParameter, status);
895 
896     status = GdipSetLineBlend(brush, factors, positions, 0);
897     expect(InvalidParameter, status);
898 
899     status = GdipSetLineBlend(brush, factors, positions, -1);
900     expect(InvalidParameter, status);
901 
902     /* leave off the 0.0 position */
903     status = GdipSetLineBlend(brush, &factors[1], &positions[1], 4);
904     expect(InvalidParameter, status);
905 
906     /* leave off the 1.0 position */
907     status = GdipSetLineBlend(brush, factors, positions, 4);
908     expect(InvalidParameter, status);
909 
910     status = GdipSetLineBlend(brush, factors, positions, 5);
911     expect(Ok, status);
912 
913     status = GdipGetLineBlendCount(brush, &count);
914     expect(Ok, status);
915     expect(5, count);
916 
917     status = GdipGetLineBlend(brush, res_factors, res_positions, 4);
918     expect(InsufficientBuffer, status);
919 
920     status = GdipGetLineBlend(brush, res_factors, res_positions, 5);
921     expect(Ok, status);
922 
923     for (i=0; i<5; i++)
924     {
925         expectf(factors[i], res_factors[i]);
926         expectf(positions[i], res_positions[i]);
927     }
928 
929     status = GdipGetLineBlend(brush, res_factors, res_positions, 6);
930     expect(Ok, status);
931 
932     status = GdipSetLineBlend(brush, factors, positions, 1);
933     expect(Ok, status);
934 
935     status = GdipGetLineBlendCount(brush, &count);
936     expect(Ok, status);
937     expect(1, count);
938 
939     status = GdipGetLineBlend(brush, res_factors, res_positions, 1);
940     expect(Ok, status);
941 
942     status = GdipGetLinePresetBlendCount(NULL, &count);
943     expect(InvalidParameter, status);
944 
945     status = GdipGetLinePresetBlendCount(brush, NULL);
946     expect(InvalidParameter, status);
947 
948     status = GdipGetLinePresetBlendCount(brush, &count);
949     expect(Ok, status);
950     expect(0, count);
951 
952     status = GdipGetLinePresetBlend(NULL, res_colors, res_positions, 1);
953     expect(InvalidParameter, status);
954 
955     status = GdipGetLinePresetBlend(brush, NULL, res_positions, 1);
956     expect(InvalidParameter, status);
957 
958     status = GdipGetLinePresetBlend(brush, res_colors, NULL, 1);
959     expect(InvalidParameter, status);
960 
961     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 0);
962     expect(InvalidParameter, status);
963 
964     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, -1);
965     expect(InvalidParameter, status);
966 
967     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 1);
968     expect(InvalidParameter, status);
969 
970     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 2);
971     expect(GenericError, status);
972 
973     status = GdipSetLinePresetBlend(NULL, colors, positions, 5);
974     expect(InvalidParameter, status);
975 
976     status = GdipSetLinePresetBlend(brush, NULL, positions, 5);
977     expect(InvalidParameter, status);
978 
979     status = GdipSetLinePresetBlend(brush, colors, NULL, 5);
980     expect(InvalidParameter, status);
981 
982     status = GdipSetLinePresetBlend(brush, colors, positions, 0);
983     expect(InvalidParameter, status);
984 
985     status = GdipSetLinePresetBlend(brush, colors, positions, -1);
986     expect(InvalidParameter, status);
987 
988     status = GdipSetLinePresetBlend(brush, colors, positions, 1);
989     expect(InvalidParameter, status);
990 
991     /* leave off the 0.0 position */
992     status = GdipSetLinePresetBlend(brush, &colors[1], &positions[1], 4);
993     expect(InvalidParameter, status);
994 
995     /* leave off the 1.0 position */
996     status = GdipSetLinePresetBlend(brush, colors, positions, 4);
997     expect(InvalidParameter, status);
998 
999     status = GdipSetLinePresetBlend(brush, colors, positions, 5);
1000     expect(Ok, status);
1001 
1002     status = GdipGetLinePresetBlendCount(brush, &count);
1003     expect(Ok, status);
1004     expect(5, count);
1005 
1006     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 4);
1007     expect(InsufficientBuffer, status);
1008 
1009     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 5);
1010     expect(Ok, status);
1011 
1012     for (i=0; i<5; i++)
1013     {
1014         expect(colors[i], res_colors[i]);
1015         expectf(positions[i], res_positions[i]);
1016     }
1017 
1018     status = GdipGetLinePresetBlend(brush, res_colors, res_positions, 6);
1019     expect(Ok, status);
1020 
1021     status = GdipSetLinePresetBlend(brush, colors, two_positions, 2);
1022     expect(Ok, status);
1023 
1024     status = GdipDeleteBrush((GpBrush*)brush);
1025     expect(Ok, status);
1026 }
1027 
1028 static void test_linelinearblend(void)
1029 {
1030     GpLineGradient *brush;
1031     GpStatus status;
1032     GpPointF pt1, pt2;
1033     INT count=10;
1034     REAL res_factors[3] = {0.3f};
1035     REAL res_positions[3] = {0.3f};
1036 
1037     status = GdipSetLineLinearBlend(NULL, 0.6, 0.8);
1038     expect(InvalidParameter, status);
1039 
1040     pt1.X = pt1.Y = 1.0;
1041     pt2.X = pt2.Y = 100.0;
1042     status = GdipCreateLineBrush(&pt1, &pt2, 0, 0, WrapModeTile, &brush);
1043     expect(Ok, status);
1044 
1045 
1046     status = GdipSetLineLinearBlend(brush, 0.6, 0.8);
1047     expect(Ok, status);
1048 
1049     status = GdipGetLineBlendCount(brush, &count);
1050     expect(Ok, status);
1051     expect(3, count);
1052 
1053     status = GdipGetLineBlend(brush, res_factors, res_positions, 3);
1054     expect(Ok, status);
1055     expectf(0.0, res_factors[0]);
1056     expectf(0.0, res_positions[0]);
1057     expectf(0.8, res_factors[1]);
1058     expectf(0.6, res_positions[1]);
1059     expectf(0.0, res_factors[2]);
1060     expectf(1.0, res_positions[2]);
1061 
1062 
1063     status = GdipSetLineLinearBlend(brush, 0.0, 0.8);
1064     expect(Ok, status);
1065 
1066     status = GdipGetLineBlendCount(brush, &count);
1067     expect(Ok, status);
1068     expect(2, count);
1069 
1070     status = GdipGetLineBlend(brush, res_factors, res_positions, 3);
1071     expect(Ok, status);
1072     expectf(0.8, res_factors[0]);
1073     expectf(0.0, res_positions[0]);
1074     expectf(0.0, res_factors[1]);
1075     expectf(1.0, res_positions[1]);
1076 
1077 
1078     status = GdipSetLineLinearBlend(brush, 1.0, 0.8);
1079     expect(Ok, status);
1080 
1081     status = GdipGetLineBlendCount(brush, &count);
1082     expect(Ok, status);
1083     expect(2, count);
1084 
1085     status = GdipGetLineBlend(brush, res_factors, res_positions, 3);
1086     expect(Ok, status);
1087     expectf(0.0, res_factors[0]);
1088     expectf(0.0, res_positions[0]);
1089     expectf(0.8, res_factors[1]);
1090     expectf(1.0, res_positions[1]);
1091 
1092     status = GdipDeleteBrush((GpBrush*)brush);
1093     expect(Ok, status);
1094 }
1095 
1096 static void test_gradientsurroundcolorcount(void)
1097 {
1098     GpStatus status;
1099     GpPathGradient *grad;
1100     ARGB color[3];
1101     INT count;
1102 
1103     status = GdipCreatePathGradient(blendcount_ptf, 2, WrapModeClamp, &grad);
1104     expect(Ok, status);
1105 
1106     count = 0;
1107     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1108     expect(Ok, status);
1109     expect(2, count);
1110 
1111     color[0] = color[1] = color[2] = 0xdeadbeef;
1112     count = 3;
1113     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1114     expect(Ok, status);
1115     expect(1, count);
1116     expect(0xffffffff, color[0]);
1117     expect(0xffffffff, color[1]);
1118     expect(0xdeadbeef, color[2]);
1119 
1120     color[0] = color[1] = color[2] = 0xdeadbeef;
1121     count = 2;
1122     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1123     expect(Ok, status);
1124     expect(1, count);
1125     expect(0xffffffff, color[0]);
1126     expect(0xffffffff, color[1]);
1127     expect(0xdeadbeef, color[2]);
1128 
1129     color[0] = color[1] = color[2] = 0xdeadbeef;
1130     count = 1;
1131     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1132     expect(InvalidParameter, status);
1133     expect(1, count);
1134     expect(0xdeadbeef, color[0]);
1135     expect(0xdeadbeef, color[1]);
1136     expect(0xdeadbeef, color[2]);
1137 
1138     color[0] = color[1] = color[2] = 0xdeadbeef;
1139     count = 0;
1140     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1141     expect(InvalidParameter, status);
1142     expect(0, count);
1143     expect(0xdeadbeef, color[0]);
1144     expect(0xdeadbeef, color[1]);
1145     expect(0xdeadbeef, color[2]);
1146 
1147     count = 3;
1148     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1149     expect(InvalidParameter, status);
1150 
1151     count = 2;
1152 
1153     color[0] = 0x00ff0000;
1154     color[1] = 0x0000ff00;
1155 
1156     status = GdipSetPathGradientSurroundColorsWithCount(NULL, color, &count);
1157     expect(InvalidParameter, status);
1158 
1159     status = GdipSetPathGradientSurroundColorsWithCount(grad, NULL, &count);
1160     expect(InvalidParameter, status);
1161 
1162     /* WinXP crashes on this test */
1163     if(0)
1164     {
1165         status = GdipSetPathGradientSurroundColorsWithCount(grad, color, NULL);
1166         expect(InvalidParameter, status);
1167     }
1168 
1169     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1170     expect(Ok, status);
1171     expect(2, count);
1172 
1173     status = GdipGetPathGradientSurroundColorCount(NULL, &count);
1174     expect(InvalidParameter, status);
1175 
1176     status = GdipGetPathGradientSurroundColorCount(grad, NULL);
1177     expect(InvalidParameter, status);
1178 
1179     count = 0;
1180     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1181     expect(Ok, status);
1182     expect(2, count);
1183 
1184     color[0] = color[1] = color[2] = 0xdeadbeef;
1185     count = 2;
1186     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1187     expect(Ok, status);
1188     expect(2, count);
1189     expect(0x00ff0000, color[0]);
1190     expect(0x0000ff00, color[1]);
1191     expect(0xdeadbeef, color[2]);
1192 
1193     count = 1;
1194     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1195     expect(Ok, status);
1196     expect(1, count);
1197 
1198     count = 0;
1199     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1200     expect(Ok, status);
1201     expect(2, count);
1202 
1203     /* If all colors are the same, count is set to 1. */
1204     color[0] = color[1] = 0;
1205     count = 2;
1206     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &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(1, count);
1215     expect(0x00000000, color[0]);
1216     expect(0x00000000, color[1]);
1217     expect(0xdeadbeef, color[2]);
1218 
1219     color[0] = color[1] = 0xff00ff00;
1220     count = 2;
1221     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1222     expect(Ok, status);
1223     expect(2, count);
1224 
1225     color[0] = color[1] = color[2] = 0xdeadbeef;
1226     count = 2;
1227     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1228     expect(Ok, status);
1229     expect(1, count);
1230     expect(0xff00ff00, color[0]);
1231     expect(0xff00ff00, color[1]);
1232     expect(0xdeadbeef, color[2]);
1233 
1234     count = 0;
1235     status = GdipSetPathGradientSurroundColorsWithCount(grad, color, &count);
1236     expect(InvalidParameter, status);
1237     expect(0, count);
1238 
1239     GdipDeleteBrush((GpBrush*)grad);
1240 
1241     status = GdipCreatePathGradient(getbounds_ptf, 3, WrapModeClamp, &grad);
1242     expect(Ok, status);
1243 
1244     color[0] = color[1] = color[2] = 0xdeadbeef;
1245     count = 3;
1246     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1247     expect(Ok, status);
1248     expect(1, count);
1249     expect(0xffffffff, color[0]);
1250     expect(0xffffffff, color[1]);
1251     expect(0xffffffff, color[2]);
1252 
1253     color[0] = color[1] = color[2] = 0xdeadbeef;
1254     count = 2;
1255     status = GdipGetPathGradientSurroundColorsWithCount(grad, color, &count);
1256     expect(InvalidParameter, status);
1257     expect(2, count);
1258     expect(0xdeadbeef, color[0]);
1259     expect(0xdeadbeef, color[1]);
1260     expect(0xdeadbeef, color[2]);
1261 
1262     count = 0;
1263     status = GdipGetPathGradientSurroundColorCount(grad, &count);
1264     expect(Ok, status);
1265     expect(3, count);
1266 
1267     GdipDeleteBrush((GpBrush*)grad);
1268 }
1269 
1270 static void test_pathgradientpath(void)
1271 {
1272     GpStatus status;
1273     GpPath *path=NULL;
1274     GpPathGradient *grad=NULL;
1275 
1276     status = GdipCreatePathGradient(blendcount_ptf, 2, WrapModeClamp, &grad);
1277     expect(Ok, status);
1278 
1279     status = GdipGetPathGradientPath(grad, NULL);
1280     expect(NotImplemented, status);
1281 
1282     status = GdipCreatePath(FillModeWinding, &path);
1283     expect(Ok, status);
1284 
1285     status = GdipGetPathGradientPath(NULL, path);
1286     expect(NotImplemented, status);
1287 
1288     status = GdipGetPathGradientPath(grad, path);
1289     expect(NotImplemented, status);
1290 
1291     status = GdipDeletePath(path);
1292     expect(Ok, status);
1293 
1294     status = GdipDeleteBrush((GpBrush*)grad);
1295     expect(Ok, status);
1296 }
1297 
1298 static void test_pathgradientcenterpoint(void)
1299 {
1300     static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
1301     GpStatus status;
1302     GpPathGradient *grad;
1303     GpPointF point;
1304 
1305     status = GdipCreatePathGradient(path_points+1, 2, WrapModeClamp, &grad);
1306     expect(Ok, status);
1307 
1308     status = GdipGetPathGradientCenterPoint(NULL, &point);
1309     expect(InvalidParameter, status);
1310 
1311     status = GdipGetPathGradientCenterPoint(grad, NULL);
1312     expect(InvalidParameter, status);
1313 
1314     status = GdipGetPathGradientCenterPoint(grad, &point);
1315     expect(Ok, status);
1316     expectf(1.5, point.X);
1317     expectf(2.0, point.Y);
1318 
1319     status = GdipSetPathGradientCenterPoint(NULL, &point);
1320     expect(InvalidParameter, status);
1321 
1322     status = GdipSetPathGradientCenterPoint(grad, NULL);
1323     expect(InvalidParameter, status);
1324 
1325     point.X = 10.0;
1326     point.Y = 15.0;
1327     status = GdipSetPathGradientCenterPoint(grad, &point);
1328     expect(Ok, status);
1329 
1330     point.X = point.Y = -1;
1331     status = GdipGetPathGradientCenterPoint(grad, &point);
1332     expect(Ok, status);
1333     expectf(10.0, point.X);
1334     expectf(15.0, point.Y);
1335 
1336     status = GdipDeleteBrush((GpBrush*)grad);
1337     expect(Ok, status);
1338 
1339     status = GdipCreatePathGradient(path_points, 3, WrapModeClamp, &grad);
1340     expect(Ok, status);
1341 
1342     status = GdipGetPathGradientCenterPoint(grad, &point);
1343     expect(Ok, status);
1344     todo_wine expectf(1.0, point.X);
1345     todo_wine expectf(4.0/3.0, point.Y);
1346 
1347     status = GdipDeleteBrush((GpBrush*)grad);
1348     expect(Ok, status);
1349 }
1350 
1351 static void test_pathgradientpresetblend(void)
1352 {
1353     static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
1354     GpStatus status;
1355     GpPathGradient *grad;
1356     INT count;
1357     int i;
1358     const REAL positions[5] = {0.0f, 0.2f, 0.5f, 0.8f, 1.0f};
1359     const REAL two_positions[2] = {0.0f, 1.0f};
1360     const ARGB colors[5] = {0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffffffff};
1361     REAL res_positions[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
1362     ARGB res_colors[6] = {0xdeadbeef, 0, 0, 0, 0};
1363 
1364     status = GdipCreatePathGradient(path_points+1, 2, WrapModeClamp, &grad);
1365     expect(Ok, status);
1366 
1367     status = GdipGetPathGradientPresetBlendCount(NULL, &count);
1368     expect(InvalidParameter, status);
1369 
1370     status = GdipGetPathGradientPresetBlendCount(grad, NULL);
1371     expect(InvalidParameter, status);
1372 
1373     status = GdipGetPathGradientPresetBlendCount(grad, &count);
1374     expect(Ok, status);
1375     expect(0, count);
1376 
1377     status = GdipGetPathGradientPresetBlend(NULL, res_colors, res_positions, 1);
1378     expect(InvalidParameter, status);
1379 
1380     status = GdipGetPathGradientPresetBlend(grad, NULL, res_positions, 1);
1381     expect(InvalidParameter, status);
1382 
1383     status = GdipGetPathGradientPresetBlend(grad, res_colors, NULL, 1);
1384     expect(InvalidParameter, status);
1385 
1386     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 0);
1387     expect(InvalidParameter, status);
1388 
1389     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, -1);
1390     expect(OutOfMemory, status);
1391 
1392     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 1);
1393     expect(InvalidParameter, status);
1394 
1395     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 2);
1396     expect(GenericError, status);
1397 
1398     status = GdipSetPathGradientPresetBlend(NULL, colors, positions, 5);
1399     expect(InvalidParameter, status);
1400 
1401     status = GdipSetPathGradientPresetBlend(grad, NULL, positions, 5);
1402     expect(InvalidParameter, status);
1403 
1404     if (0)
1405     {
1406         /* crashes on windows xp */
1407         status = GdipSetPathGradientPresetBlend(grad, colors, NULL, 5);
1408         expect(InvalidParameter, status);
1409     }
1410 
1411     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 0);
1412     expect(InvalidParameter, status);
1413 
1414     status = GdipSetPathGradientPresetBlend(grad, colors, positions, -1);
1415     expect(InvalidParameter, status);
1416 
1417     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 1);
1418     expect(InvalidParameter, status);
1419 
1420     /* leave off the 0.0 position */
1421     status = GdipSetPathGradientPresetBlend(grad, &colors[1], &positions[1], 4);
1422     expect(InvalidParameter, status);
1423 
1424     /* leave off the 1.0 position */
1425     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 4);
1426     expect(InvalidParameter, status);
1427 
1428     status = GdipSetPathGradientPresetBlend(grad, colors, positions, 5);
1429     expect(Ok, status);
1430 
1431     status = GdipGetPathGradientPresetBlendCount(grad, &count);
1432     expect(Ok, status);
1433     expect(5, count);
1434 
1435     if (0)
1436     {
1437         /* Native GdipGetPathGradientPresetBlend seems to copy starting from
1438          * the end of each array and do no bounds checking. This is so braindead
1439          * I'm not going to copy it. */
1440 
1441         res_colors[0] = 0xdeadbeef;
1442         res_positions[0] = 0.3;
1443 
1444         status = GdipGetPathGradientPresetBlend(grad, &res_colors[1], &res_positions[1], 4);
1445         expect(Ok, status);
1446 
1447         expect(0xdeadbeef, res_colors[0]);
1448         expectf(0.3, res_positions[0]);
1449 
1450         for (i=1; i<5; i++)
1451         {
1452             expect(colors[i], res_colors[i]);
1453             expectf(positions[i], res_positions[i]);
1454         }
1455 
1456         status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 6);
1457         expect(Ok, status);
1458 
1459         for (i=0; i<5; i++)
1460         {
1461             expect(colors[i], res_colors[i+1]);
1462             expectf(positions[i], res_positions[i+1]);
1463         }
1464     }
1465 
1466     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 5);
1467     expect(Ok, status);
1468 
1469     for (i=0; i<5; i++)
1470     {
1471         expect(colors[i], res_colors[i]);
1472         expectf(positions[i], res_positions[i]);
1473     }
1474 
1475     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 0);
1476     expect(InvalidParameter, status);
1477 
1478     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, -1);
1479     expect(OutOfMemory, status);
1480 
1481     status = GdipGetPathGradientPresetBlend(grad, res_colors, res_positions, 1);
1482     expect(InvalidParameter, status);
1483 
1484     status = GdipSetPathGradientPresetBlend(grad, colors, two_positions, 2);
1485     expect(Ok, status);
1486 
1487     status = GdipDeleteBrush((GpBrush*)grad);
1488     expect(Ok, status);
1489 }
1490 
1491 static void test_pathgradientblend(void)
1492 {
1493     static const GpPointF path_points[] = {{0,0}, {3,0}, {0,4}};
1494     GpPathGradient *brush;
1495     GpStatus status;
1496     INT count, i;
1497     const REAL factors[5] = {0.0f, 0.1f, 0.5f, 0.9f, 1.0f};
1498     const REAL positions[5] = {0.0f, 0.2f, 0.5f, 0.8f, 1.0f};
1499     REAL res_factors[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
1500     REAL res_positions[6] = {0.3f, 0.0f, 0.0f, 0.0f, 0.0f};
1501 
1502     status = GdipCreatePathGradient(path_points, 3, WrapModeClamp, &brush);
1503     expect(Ok, status);
1504 
1505     status = GdipGetPathGradientBlendCount(NULL, &count);
1506     expect(InvalidParameter, status);
1507 
1508     status = GdipGetPathGradientBlendCount(brush, NULL);
1509     expect(InvalidParameter, status);
1510 
1511     status = GdipGetPathGradientBlendCount(brush, &count);
1512     expect(Ok, status);
1513     expect(1, count);
1514 
1515     status = GdipGetPathGradientBlend(NULL, res_factors, res_positions, 1);
1516     expect(InvalidParameter, status);
1517 
1518     status = GdipGetPathGradientBlend(brush, NULL, res_positions, 1);
1519     expect(InvalidParameter, status);
1520 
1521     status = GdipGetPathGradientBlend(brush, res_factors, NULL, 1);
1522     expect(InvalidParameter, status);
1523 
1524     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 0);
1525     expect(InvalidParameter, status);
1526 
1527     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, -1);
1528     expect(InvalidParameter, status);
1529 
1530     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 1);
1531     expect(Ok, status);
1532 
1533     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 2);
1534     expect(Ok, status);
1535 
1536     status = GdipSetPathGradientBlend(NULL, factors, positions, 5);
1537     expect(InvalidParameter, status);
1538 
1539     status = GdipSetPathGradientBlend(brush, NULL, positions, 5);
1540     expect(InvalidParameter, status);
1541 
1542     status = GdipSetPathGradientBlend(brush, factors, NULL, 5);
1543     expect(InvalidParameter, status);
1544 
1545     status = GdipSetPathGradientBlend(brush, factors, positions, 0);
1546     expect(InvalidParameter, status);
1547 
1548     status = GdipSetPathGradientBlend(brush, factors, positions, -1);
1549     expect(InvalidParameter, status);
1550 
1551     /* leave off the 0.0 position */
1552     status = GdipSetPathGradientBlend(brush, &factors[1], &positions[1], 4);
1553     expect(InvalidParameter, status);
1554 
1555     /* leave off the 1.0 position */
1556     status = GdipSetPathGradientBlend(brush, factors, positions, 4);
1557     expect(InvalidParameter, status);
1558 
1559     status = GdipSetPathGradientBlend(brush, factors, positions, 5);
1560     expect(Ok, status);
1561 
1562     status = GdipGetPathGradientBlendCount(brush, &count);
1563     expect(Ok, status);
1564     expect(5, count);
1565 
1566     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 4);
1567     expect(InsufficientBuffer, status);
1568 
1569     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 5);
1570     expect(Ok, status);
1571 
1572     for (i=0; i<5; i++)
1573     {
1574         expectf(factors[i], res_factors[i]);
1575         expectf(positions[i], res_positions[i]);
1576     }
1577 
1578     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 6);
1579     expect(Ok, status);
1580 
1581     status = GdipSetPathGradientBlend(brush, factors, positions, 1);
1582     expect(Ok, status);
1583 
1584     status = GdipGetPathGradientBlendCount(brush, &count);
1585     expect(Ok, status);
1586     expect(1, count);
1587 
1588     status = GdipGetPathGradientBlend(brush, res_factors, res_positions, 1);
1589     expect(Ok, status);
1590 
1591     status = GdipDeleteBrush((GpBrush*)brush);
1592     expect(Ok, status);
1593 }
1594 
1595 static void test_getHatchStyle(void)
1596 {
1597     GpStatus status;
1598     GpHatch *brush;
1599     GpHatchStyle hatchStyle;
1600 
1601     GdipCreateHatchBrush(HatchStyleHorizontal, 11, 12, &brush);
1602 
1603     status = GdipGetHatchStyle(NULL, &hatchStyle);
1604     expect(InvalidParameter, status);
1605 
1606     status = GdipGetHatchStyle(brush, NULL);
1607     expect(InvalidParameter, status);
1608 
1609     status = GdipGetHatchStyle(brush, &hatchStyle);
1610     expect(Ok, status);
1611     expect(HatchStyleHorizontal, hatchStyle);
1612 
1613     GdipDeleteBrush((GpBrush *)brush);
1614 }
1615 
1616 START_TEST(brush)
1617 {
1618     struct GdiplusStartupInput gdiplusStartupInput;
1619     ULONG_PTR gdiplusToken;
1620     HMODULE hmsvcrt;
1621     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
1622     WNDCLASSA class;
1623 
1624     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
1625     hmsvcrt = LoadLibraryA("msvcrt");
1626     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
1627     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
1628 
1629     memset( &class, 0, sizeof(class) );
1630     class.lpszClassName = "gdiplus_test";
1631     class.style = CS_HREDRAW | CS_VREDRAW;
1632     class.lpfnWndProc = DefWindowProcA;
1633     class.hInstance = GetModuleHandleA(0);
1634     class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
1635     class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
1636     class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1637     RegisterClassA( &class );
1638     hwnd = CreateWindowA( "gdiplus_test", "graphics test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1639                           CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, GetModuleHandleA(0), 0 );
1640     ok(hwnd != NULL, "Expected window to be created\n");
1641 
1642     gdiplusStartupInput.GdiplusVersion              = 1;
1643     gdiplusStartupInput.DebugEventCallback          = NULL;
1644     gdiplusStartupInput.SuppressBackgroundThread    = 0;
1645     gdiplusStartupInput.SuppressExternalCodecs      = 0;
1646 
1647     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1648 
1649     test_constructor_destructor();
1650     test_createHatchBrush();
1651     test_createLineBrushFromRectWithAngle();
1652     test_type();
1653     test_gradientblendcount();
1654     test_getblend();
1655     test_getbounds();
1656     test_getgamma();
1657     test_transform();
1658     test_texturewrap();
1659     test_gradientgetrect();
1660     test_lineblend();
1661     test_linelinearblend();
1662     test_gradientsurroundcolorcount();
1663     test_pathgradientpath();
1664     test_pathgradientcenterpoint();
1665     test_pathgradientpresetblend();
1666     test_pathgradientblend();
1667     test_getHatchStyle();
1668 
1669     GdiplusShutdown(gdiplusToken);
1670     DestroyWindow(hwnd);
1671 }
1672