1 /*
2  * Unit test suite for pathiterator
3  *
4  * Copyright (C) 2008 Nikolay Sivov
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 "objbase.h"
22 #include "gdiplus.h"
23 #include "wine/test.h"
24 
25 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
26 
27 static void test_constructor_destructor(void)
28 {
29     GpPath *path;
30     GpPathIterator *iter;
31     GpStatus stat;
32 
33     GdipCreatePath(FillModeAlternate, &path);
34     GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
35 
36     /* NULL args */
37     stat = GdipCreatePathIter(NULL, NULL);
38     expect(InvalidParameter, stat);
39     iter = NULL;
40     stat = GdipCreatePathIter(&iter, NULL);
41     expect(Ok, stat);
42     ok(iter != NULL, "Expected iterator to be created\n");
43     GdipDeletePathIter(iter);
44     stat = GdipCreatePathIter(NULL, path);
45     expect(InvalidParameter, stat);
46     stat = GdipDeletePathIter(NULL);
47     expect(InvalidParameter, stat);
48 
49     /* valid args */
50     stat = GdipCreatePathIter(&iter, path);
51     expect(Ok, stat);
52 
53     GdipDeletePathIter(iter);
54     GdipDeletePath(path);
55 }
56 
57 static void test_hascurve(void)
58 {
59     GpPath *path;
60     GpPathIterator *iter;
61     GpStatus stat;
62     BOOL hasCurve;
63 
64     GdipCreatePath(FillModeAlternate, &path);
65     GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
66 
67     stat = GdipCreatePathIter(&iter, path);
68     expect(Ok, stat);
69 
70     /* NULL args
71        BOOL out argument is local in wrapper class method,
72        so it always has not-NULL address */
73     stat = GdipPathIterHasCurve(NULL, &hasCurve);
74     expect(InvalidParameter, stat);
75 
76     /* valid args */
77     stat = GdipPathIterHasCurve(iter, &hasCurve);
78     expect(Ok, stat);
79     expect(FALSE, hasCurve);
80 
81     GdipDeletePathIter(iter);
82 
83     stat = GdipAddPathEllipse(path, 0.0, 0.0, 35.0, 70.0);
84     expect(Ok, stat);
85 
86     stat = GdipCreatePathIter(&iter, path);
87     expect(Ok, stat);
88 
89     stat = GdipPathIterHasCurve(iter, &hasCurve);
90     expect(Ok, stat);
91     expect(TRUE, hasCurve);
92 
93     GdipDeletePathIter(iter);
94     GdipDeletePath(path);
95 }
96 
97 static void test_nextmarker(void)
98 {
99     GpPath *path;
100     GpPathIterator *iter;
101     GpStatus stat;
102     INT start, end;
103     INT result;
104 
105     /* NULL args
106        BOOL out argument is local in wrapper class method,
107        so it always has not-NULL address */
108     stat = GdipPathIterNextMarker(NULL, &result, NULL, NULL);
109     expect(InvalidParameter, stat);
110     stat = GdipPathIterNextMarker(NULL, &result, &start, NULL);
111     expect(InvalidParameter, stat);
112     stat = GdipPathIterNextMarker(NULL, &result, NULL, &end);
113     expect(InvalidParameter, stat);
114 
115     GdipCreatePath(FillModeAlternate, &path);
116     GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
117 
118     /* no markers */
119     GdipCreatePathIter(&iter, path);
120     start = end = result = (INT)0xdeadbeef;
121     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
122     expect(Ok, stat);
123     expect(0, start);
124     expect(3, end);
125     expect(4, result);
126     start = end = result = (INT)0xdeadbeef;
127     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
128     expect(Ok, stat);
129     /* start/end remain unchanged */
130     expect((INT)0xdeadbeef, start);
131     expect((INT)0xdeadbeef, end);
132     expect(0, result);
133     GdipDeletePathIter(iter);
134 
135     /* one marker */
136     GdipSetPathMarker(path);
137     GdipCreatePathIter(&iter, path);
138     start = end = result = (INT)0xdeadbeef;
139     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
140     expect(Ok, stat);
141     expect(0, start);
142     expect(3, end);
143     expect(4, result);
144     start = end = result = (INT)0xdeadbeef;
145     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
146     expect(Ok, stat);
147     expect((INT)0xdeadbeef, start);
148     expect((INT)0xdeadbeef, end);
149     expect(0, result);
150     GdipDeletePathIter(iter);
151 
152     /* two markers */
153     GdipAddPathLine(path, 0.0, 0.0, 10.0, 30.0);
154     GdipSetPathMarker(path);
155     GdipCreatePathIter(&iter, path);
156     start = end = result = (INT)0xdeadbeef;
157     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
158     expect(Ok, stat);
159     expect(0, start);
160     expect(3, end);
161     expect(4, result);
162     start = end = result = (INT)0xdeadbeef;
163     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
164     expect(Ok, stat);
165     expect(4, start);
166     expect(5, end);
167     expect(2, result);
168     start = end = result = (INT)0xdeadbeef;
169     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
170     expect(Ok, stat);
171     expect((INT)0xdeadbeef, start);
172     expect((INT)0xdeadbeef, end);
173     expect(0, result);
174     GdipDeletePathIter(iter);
175 
176     GdipDeletePath(path);
177 }
178 
179 static void test_nextmarkerpath(void)
180 {
181     GpPath *path, *retpath;
182     GpPathIterator *iter;
183     GpStatus stat;
184     INT result, count;
185 
186     GdipCreatePath(FillModeAlternate, &path);
187 
188     /* NULL */
189     stat = GdipPathIterNextMarkerPath(NULL, NULL, NULL);
190     expect(InvalidParameter, stat);
191     stat = GdipPathIterNextMarkerPath(NULL, &result, NULL);
192     expect(InvalidParameter, stat);
193     stat = GdipPathIterNextMarkerPath(NULL, &result, path);
194     expect(InvalidParameter, stat);
195 
196     GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
197 
198     /* no markers */
199     GdipCreatePath(FillModeAlternate, &retpath);
200     GdipCreatePathIter(&iter, path);
201     result = -1;
202     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
203     expect(Ok, stat);
204     expect(4, result);
205     count = -1;
206     GdipGetPointCount(retpath, &count);
207     expect(4, count);
208     result = -1;
209     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
210     expect(Ok, stat);
211     expect(0, result);
212     count = -1;
213     GdipGetPointCount(retpath, &count);
214     expect(4, count);
215     GdipDeletePathIter(iter);
216     GdipDeletePath(retpath);
217 
218     /* one marker */
219     GdipSetPathMarker(path);
220     GdipCreatePath(FillModeAlternate, &retpath);
221     GdipCreatePathIter(&iter, path);
222     result = -1;
223     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
224     expect(Ok, stat);
225     expect(4, result);
226     count = -1;
227     GdipGetPointCount(retpath, &count);
228     expect(4, count);
229     result = -1;
230     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
231     expect(Ok, stat);
232     expect(0, result);
233     count = -1;
234     GdipGetPointCount(retpath, &count);
235     expect(4, count);
236     GdipDeletePathIter(iter);
237     GdipDeletePath(retpath);
238 
239     /* two markers */
240     GdipAddPathLine(path, 0.0, 0.0, 10.0, 30.0);
241     GdipSetPathMarker(path);
242     GdipCreatePath(FillModeAlternate, &retpath);
243     GdipCreatePathIter(&iter, path);
244     result = -1;
245     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
246     expect(Ok, stat);
247     expect(4, result);
248     result = -1;
249     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
250     expect(Ok, stat);
251     expect(2, result);
252     result = -1;
253     stat = GdipPathIterNextMarkerPath(iter, &result, retpath);
254     expect(Ok, stat);
255     expect(0, result);
256     GdipDeletePathIter(iter);
257     GdipDeletePath(retpath);
258 
259     GdipDeletePath(path);
260 }
261 
262 static void test_getsubpathcount(void)
263 {
264     GpPath *path;
265     GpPathIterator *iter;
266     GpStatus stat;
267     INT count;
268 
269     /* NULL args */
270     stat = GdipPathIterGetSubpathCount(NULL, NULL);
271     expect(InvalidParameter, stat);
272     stat = GdipPathIterGetSubpathCount(NULL, &count);
273     expect(InvalidParameter, stat);
274 
275     GdipCreatePath(FillModeAlternate, &path);
276 
277     /* empty path */
278     GdipCreatePathIter(&iter, path);
279     stat = GdipPathIterGetSubpathCount(iter, &count);
280     expect(Ok, stat);
281     expect(0, count);
282     GdipDeletePathIter(iter);
283 
284     GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
285 
286     /* open figure */
287     GdipCreatePathIter(&iter, path);
288     stat = GdipPathIterGetSubpathCount(iter, &count);
289     expect(Ok, stat);
290     expect(1, count);
291     GdipDeletePathIter(iter);
292 
293     /* manually start new figure */
294     GdipStartPathFigure(path);
295     GdipAddPathLine(path, 50.0, 50.0, 110.0, 40.0);
296     GdipCreatePathIter(&iter, path);
297     stat = GdipPathIterGetSubpathCount(iter, &count);
298     expect(Ok, stat);
299     expect(2, count);
300     GdipDeletePathIter(iter);
301 
302     GdipDeletePath(path);
303 }
304 
305 static void test_isvalid(void)
306 {
307     GpPath *path;
308     GpPathIterator *iter;
309     GpStatus stat;
310     BOOL isvalid;
311     INT start, end, result;
312 
313     GdipCreatePath(FillModeAlternate, &path);
314 
315     /* NULL args */
316     GdipCreatePathIter(&iter, path);
317     stat = GdipPathIterIsValid(NULL, NULL);
318     expect(InvalidParameter, stat);
319     stat = GdipPathIterIsValid(iter, NULL);
320     expect(InvalidParameter, stat);
321     stat = GdipPathIterIsValid(NULL, &isvalid);
322     expect(InvalidParameter, stat);
323     GdipDeletePathIter(iter);
324 
325     /* on empty path */
326     GdipCreatePathIter(&iter, path);
327     isvalid = FALSE;
328     stat = GdipPathIterIsValid(iter, &isvalid);
329     expect(Ok, stat);
330     expect(TRUE, isvalid);
331     GdipDeletePathIter(iter);
332 
333     /* no markers */
334     stat = GdipAddPathLine(path, 50.0, 50.0, 110.0, 40.0);
335     expect(Ok, stat);
336     stat = GdipCreatePathIter(&iter, path);
337     expect(Ok, stat);
338     stat = GdipPathIterNextMarker(iter, &result, &start, &end);
339     expect(Ok, stat);
340     isvalid = FALSE;
341     stat = GdipPathIterIsValid(iter, &isvalid);
342     expect(Ok, stat);
343     expect(TRUE, isvalid);
344     GdipDeletePathIter(iter);
345 
346     GdipDeletePath(path);
347 }
348 
349 static void test_nextsubpathpath(void)
350 {
351     GpPath *path, *retpath;
352     GpPathIterator *iter;
353     GpStatus stat;
354     BOOL closed;
355     INT count, result;
356 
357     GdipCreatePath(FillModeAlternate, &path);
358 
359     /* NULL args */
360     GdipCreatePath(FillModeAlternate, &retpath);
361     GdipCreatePathIter(&iter, path);
362     stat = GdipPathIterNextSubpathPath(NULL, NULL, NULL, NULL);
363     expect(InvalidParameter, stat);
364     stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, NULL);
365     expect(InvalidParameter, stat);
366     stat = GdipPathIterNextSubpathPath(NULL, &result, NULL, NULL);
367     expect(InvalidParameter, stat);
368     stat = GdipPathIterNextSubpathPath(iter, &result, NULL, &closed);
369     expect(Ok, stat);
370     stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, &closed);
371     expect(InvalidParameter, stat);
372     stat = GdipPathIterNextSubpathPath(iter, NULL, retpath, NULL);
373     expect(InvalidParameter, stat);
374     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, NULL);
375     expect(InvalidParameter, stat);
376     GdipDeletePathIter(iter);
377     GdipDeletePath(retpath);
378 
379     /* empty path */
380     GdipCreatePath(FillModeAlternate, &retpath);
381     GdipCreatePathIter(&iter, path);
382     result = -2;
383     closed = TRUE;
384     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
385     expect(Ok, stat);
386     expect(0, result);
387     expect(TRUE, closed);
388     count = -1;
389     GdipGetPointCount(retpath, &count);
390     expect(0, count);
391     GdipDeletePathIter(iter);
392     GdipDeletePath(retpath);
393 
394     /* open figure */
395     GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
396 
397     GdipCreatePath(FillModeAlternate, &retpath);
398     GdipCreatePathIter(&iter, path);
399     result = -2;
400     closed = TRUE;
401     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
402     expect(Ok, stat);
403     expect(2, result);
404     expect(FALSE, closed);
405     count = -1;
406     GdipGetPointCount(retpath, &count);
407     expect(2, count);
408     /* subsequent call */
409     result = -2;
410     closed = TRUE;
411     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
412     expect(Ok, stat);
413     expect(0, result);
414     expect(TRUE, closed);
415     count = -1;
416     GdipGetPointCount(retpath, &count);
417     expect(2, count);
418     GdipDeletePathIter(iter);
419 
420     /* closed figure, check does it extend retpath or reset it */
421     GdipAddPathLine(retpath, 50.0, 55.0, 200.0, 150.0);
422 
423     GdipClosePathFigure(path);
424     GdipAddPathLine(path, 50.0, 55.0, 200.0, 150.0);
425     GdipClosePathFigure(path);
426 
427     GdipCreatePathIter(&iter, path);
428     result = -2;
429     closed = FALSE;
430     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
431     expect(Ok, stat);
432     expect(2, result);
433     expect(TRUE, closed);
434     count = -1;
435     GdipGetPointCount(retpath, &count);
436     expect(2, count);
437     /* subsequent call */
438     result = -2;
439     closed = FALSE;
440     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
441     expect(Ok, stat);
442     expect(2, result);
443     expect(TRUE, closed);
444     count = -1;
445     GdipGetPointCount(retpath, &count);
446     expect(2, count);
447     result = -2;
448     closed = FALSE;
449     stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed);
450     expect(Ok, stat);
451     expect(0, result);
452     expect(TRUE, closed);
453     count = -1;
454     GdipGetPointCount(retpath, &count);
455     expect(2, count);
456     GdipDeletePathIter(iter);
457 
458     GdipDeletePath(retpath);
459     GdipDeletePath(path);
460 }
461 
462 static void test_nextsubpath(void)
463 {
464     GpPath *path;
465     GpPathIterator *iter;
466     GpStatus stat;
467     INT start, end, result;
468     BOOL closed;
469 
470     /* empty path */
471     GdipCreatePath(FillModeAlternate, &path);
472     GdipCreatePathIter(&iter, path);
473 
474     result = -2;
475     closed = TRUE;
476     stat = GdipPathIterNextSubpath(iter, &result, &start, &end, &closed);
477     expect(Ok, stat);
478     expect(0, result);
479     expect(TRUE, closed);
480 
481     GdipDeletePathIter(iter);
482     GdipDeletePath(path);
483 }
484 
485 static void test_nextpathtype(void)
486 {
487     GpPath *path;
488     GpPathIterator *iter;
489     GpStatus stat;
490     INT start, end, result;
491     BYTE type;
492 
493     GdipCreatePath(FillModeAlternate, &path);
494     GdipCreatePathIter(&iter, path);
495 
496     /* NULL arguments */
497     stat = GdipPathIterNextPathType(NULL, NULL, NULL, NULL, NULL);
498     expect(InvalidParameter, stat);
499     stat = GdipPathIterNextPathType(iter, NULL, NULL, NULL, NULL);
500     expect(InvalidParameter, stat);
501     stat = GdipPathIterNextPathType(iter, &result, NULL, NULL, NULL);
502     expect(InvalidParameter, stat);
503     stat = GdipPathIterNextPathType(iter, NULL, &type, NULL, NULL);
504     expect(InvalidParameter, stat);
505     stat = GdipPathIterNextPathType(iter, NULL, NULL, &start, &end);
506     expect(InvalidParameter, stat);
507     stat = GdipPathIterNextPathType(iter, NULL, &type, &start, &end);
508     expect(InvalidParameter, stat);
509     stat = GdipPathIterNextPathType(iter, &result, &type, NULL, NULL);
510     expect(InvalidParameter, stat);
511 
512     /* empty path */
513     start = end = result = (INT)0xdeadbeef;
514     stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
515     todo_wine expect(Ok, stat);
516     expect((INT)0xdeadbeef, start);
517     expect((INT)0xdeadbeef, end);
518     todo_wine expect(0, result);
519     GdipDeletePathIter(iter);
520 
521     /* single figure */
522     GdipAddPathLine(path, 0.0, 0.0, 10.0, 30.0);
523     GdipCreatePathIter(&iter, path);
524     start = end = result = (INT)0xdeadbeef;
525     type = 255; /* out of range */
526     stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
527     todo_wine expect(Ok, stat);
528     expect((INT)0xdeadbeef, start);
529     expect((INT)0xdeadbeef, end);
530     expect(255, type);
531     todo_wine expect(0, result);
532     GdipDeletePathIter(iter);
533 
534     stat = GdipAddPathEllipse(path, 0.0, 0.0, 35.0, 70.0);
535     expect(Ok, stat);
536     GdipCreatePathIter(&iter, path);
537     start = end = result = (INT)0xdeadbeef;
538     type = 255; /* out of range */
539     stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
540     todo_wine expect(Ok, stat);
541     expect((INT)0xdeadbeef, start);
542     expect((INT)0xdeadbeef, end);
543     expect(255, type);
544     todo_wine expect(0, result);
545     GdipDeletePathIter(iter);
546 
547     /* closed */
548     GdipClosePathFigure(path);
549     GdipCreatePathIter(&iter, path);
550     start = end = result = (INT)0xdeadbeef;
551     type = 255; /* out of range */
552     stat = GdipPathIterNextPathType(iter, &result, &type, &start, &end);
553     todo_wine expect(Ok, stat);
554     expect((INT)0xdeadbeef, start);
555     expect((INT)0xdeadbeef, end);
556     expect(255, type);
557     todo_wine expect(0, result);
558     GdipDeletePathIter(iter);
559 
560     GdipDeletePath(path);
561 }
562 
563 START_TEST(pathiterator)
564 {
565     struct GdiplusStartupInput gdiplusStartupInput;
566     ULONG_PTR gdiplusToken;
567     HMODULE hmsvcrt;
568     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
569 
570     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
571     hmsvcrt = LoadLibraryA("msvcrt");
572     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
573     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
574 
575     gdiplusStartupInput.GdiplusVersion              = 1;
576     gdiplusStartupInput.DebugEventCallback          = NULL;
577     gdiplusStartupInput.SuppressBackgroundThread    = 0;
578     gdiplusStartupInput.SuppressExternalCodecs      = 0;
579 
580     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
581 
582     test_constructor_destructor();
583     test_hascurve();
584     test_nextmarker();
585     test_nextmarkerpath();
586     test_getsubpathcount();
587     test_isvalid();
588     test_nextsubpathpath();
589     test_nextsubpath();
590     test_nextpathtype();
591 
592     GdiplusShutdown(gdiplusToken);
593 }
594