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