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