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