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