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