xref: /reactos/dll/win32/gdiplus/pathiterator.c (revision 5f279f2d)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright (C) 2007 Google (Evan Stade)
3c2c66affSColin Finck  * Copyright (C) 2008 Nikolay Sivov <bunglehead at gmail dot com>
4c2c66affSColin Finck  *
5c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck  * License as published by the Free Software Foundation; either
8c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck  *
10c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13c2c66affSColin Finck  * Lesser General Public License for more details.
14c2c66affSColin Finck  *
15c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck  */
19c2c66affSColin Finck 
20*5f279f2dSAmine Khaldi #include <stdarg.h>
21*5f279f2dSAmine Khaldi 
22*5f279f2dSAmine Khaldi #include "windef.h"
23*5f279f2dSAmine Khaldi #include "winbase.h"
24*5f279f2dSAmine Khaldi #include "wingdi.h"
25*5f279f2dSAmine Khaldi 
26*5f279f2dSAmine Khaldi #include "objbase.h"
27*5f279f2dSAmine Khaldi 
28*5f279f2dSAmine Khaldi #include "gdiplus.h"
29c2c66affSColin Finck #include "gdiplus_private.h"
30*5f279f2dSAmine Khaldi #include "wine/debug.h"
31*5f279f2dSAmine Khaldi 
32*5f279f2dSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
33c2c66affSColin Finck 
GdipCreatePathIter(GpPathIterator ** iterator,GpPath * path)34c2c66affSColin Finck GpStatus WINGDIPAPI GdipCreatePathIter(GpPathIterator **iterator, GpPath* path)
35c2c66affSColin Finck {
36c2c66affSColin Finck     INT size;
37c2c66affSColin Finck 
38c2c66affSColin Finck     TRACE("(%p, %p)\n", iterator, path);
39c2c66affSColin Finck 
40c2c66affSColin Finck     if(!iterator)
41c2c66affSColin Finck         return InvalidParameter;
42c2c66affSColin Finck 
43c2c66affSColin Finck     *iterator = heap_alloc_zero(sizeof(GpPathIterator));
44c2c66affSColin Finck     if(!*iterator)  return OutOfMemory;
45c2c66affSColin Finck 
46c2c66affSColin Finck     if(path){
47c2c66affSColin Finck         size = path->pathdata.Count;
48c2c66affSColin Finck 
49c2c66affSColin Finck         (*iterator)->pathdata.Types  = heap_alloc_zero(size);
50c2c66affSColin Finck         (*iterator)->pathdata.Points = heap_alloc_zero(size * sizeof(PointF));
51c2c66affSColin Finck 
52c2c66affSColin Finck         memcpy((*iterator)->pathdata.Types, path->pathdata.Types, size);
53c2c66affSColin Finck         memcpy((*iterator)->pathdata.Points, path->pathdata.Points,size * sizeof(PointF));
54c2c66affSColin Finck         (*iterator)->pathdata.Count = size;
55c2c66affSColin Finck     }
56c2c66affSColin Finck     else{
57c2c66affSColin Finck         (*iterator)->pathdata.Types  = NULL;
58c2c66affSColin Finck         (*iterator)->pathdata.Points = NULL;
59c2c66affSColin Finck         (*iterator)->pathdata.Count  = 0;
60c2c66affSColin Finck     }
61c2c66affSColin Finck 
62c2c66affSColin Finck     (*iterator)->subpath_pos  = 0;
63c2c66affSColin Finck     (*iterator)->marker_pos   = 0;
64c2c66affSColin Finck     (*iterator)->pathtype_pos = 0;
65c2c66affSColin Finck 
66c2c66affSColin Finck     return Ok;
67c2c66affSColin Finck }
68c2c66affSColin Finck 
GdipDeletePathIter(GpPathIterator * iter)69c2c66affSColin Finck GpStatus WINGDIPAPI GdipDeletePathIter(GpPathIterator *iter)
70c2c66affSColin Finck {
71c2c66affSColin Finck     TRACE("(%p)\n", iter);
72c2c66affSColin Finck 
73c2c66affSColin Finck     if(!iter)
74c2c66affSColin Finck         return InvalidParameter;
75c2c66affSColin Finck 
76c2c66affSColin Finck     heap_free(iter->pathdata.Types);
77c2c66affSColin Finck     heap_free(iter->pathdata.Points);
78c2c66affSColin Finck     heap_free(iter);
79c2c66affSColin Finck 
80c2c66affSColin Finck     return Ok;
81c2c66affSColin Finck }
82c2c66affSColin Finck 
GdipPathIterCopyData(GpPathIterator * iterator,INT * resultCount,GpPointF * points,BYTE * types,INT startIndex,INT endIndex)83c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator* iterator,
84c2c66affSColin Finck     INT* resultCount, GpPointF* points, BYTE* types, INT startIndex, INT endIndex)
85c2c66affSColin Finck {
86c2c66affSColin Finck     TRACE("(%p, %p, %p, %p, %d, %d)\n", iterator, resultCount, points, types,
87c2c66affSColin Finck            startIndex, endIndex);
88c2c66affSColin Finck 
89c2c66affSColin Finck     if(!iterator || !types || !points)
90c2c66affSColin Finck         return InvalidParameter;
91c2c66affSColin Finck 
92c2c66affSColin Finck     if(endIndex > iterator->pathdata.Count - 1 || startIndex < 0 ||
93c2c66affSColin Finck         endIndex < startIndex){
94c2c66affSColin Finck         *resultCount = 0;
95c2c66affSColin Finck         return Ok;
96c2c66affSColin Finck     }
97c2c66affSColin Finck 
98c2c66affSColin Finck     *resultCount = endIndex - startIndex + 1;
99c2c66affSColin Finck 
100c2c66affSColin Finck     memcpy(types, &(iterator->pathdata.Types[startIndex]), *resultCount);
101c2c66affSColin Finck     memcpy(points, &(iterator->pathdata.Points[startIndex]),
102c2c66affSColin Finck         *resultCount * sizeof(PointF));
103c2c66affSColin Finck 
104c2c66affSColin Finck     return Ok;
105c2c66affSColin Finck }
106c2c66affSColin Finck 
GdipPathIterHasCurve(GpPathIterator * iterator,BOOL * hasCurve)107c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterHasCurve(GpPathIterator* iterator, BOOL* hasCurve)
108c2c66affSColin Finck {
109c2c66affSColin Finck     INT i;
110c2c66affSColin Finck 
111c2c66affSColin Finck     TRACE("(%p, %p)\n", iterator, hasCurve);
112c2c66affSColin Finck 
113c2c66affSColin Finck     if(!iterator)
114c2c66affSColin Finck         return InvalidParameter;
115c2c66affSColin Finck 
116c2c66affSColin Finck     *hasCurve = FALSE;
117c2c66affSColin Finck 
118c2c66affSColin Finck     for(i = 0; i < iterator->pathdata.Count; i++)
119c2c66affSColin Finck         if((iterator->pathdata.Types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){
120c2c66affSColin Finck             *hasCurve = TRUE;
121c2c66affSColin Finck             break;
122c2c66affSColin Finck         }
123c2c66affSColin Finck 
124c2c66affSColin Finck     return Ok;
125c2c66affSColin Finck }
126c2c66affSColin Finck 
GdipPathIterGetSubpathCount(GpPathIterator * iterator,INT * count)127c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterGetSubpathCount(GpPathIterator* iterator, INT* count)
128c2c66affSColin Finck {
129c2c66affSColin Finck     INT i;
130c2c66affSColin Finck 
131c2c66affSColin Finck     TRACE("(%p, %p)\n", iterator, count);
132c2c66affSColin Finck 
133c2c66affSColin Finck     if(!iterator || !count)
134c2c66affSColin Finck         return InvalidParameter;
135c2c66affSColin Finck 
136c2c66affSColin Finck     *count = 0;
137c2c66affSColin Finck     for(i = 0; i < iterator->pathdata.Count; i++){
138c2c66affSColin Finck         if(iterator->pathdata.Types[i] == PathPointTypeStart)
139c2c66affSColin Finck             (*count)++;
140c2c66affSColin Finck     }
141c2c66affSColin Finck 
142c2c66affSColin Finck     return Ok;
143c2c66affSColin Finck }
144c2c66affSColin Finck 
GdipPathIterNextMarker(GpPathIterator * iterator,INT * resultCount,INT * startIndex,INT * endIndex)145c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterNextMarker(GpPathIterator* iterator, INT *resultCount,
146c2c66affSColin Finck     INT* startIndex, INT* endIndex)
147c2c66affSColin Finck {
148c2c66affSColin Finck     INT i;
149c2c66affSColin Finck 
150c2c66affSColin Finck     TRACE("(%p, %p, %p, %p)\n", iterator, resultCount, startIndex, endIndex);
151c2c66affSColin Finck 
152c2c66affSColin Finck     if(!iterator || !startIndex || !endIndex)
153c2c66affSColin Finck         return InvalidParameter;
154c2c66affSColin Finck 
155c2c66affSColin Finck     *resultCount = 0;
156c2c66affSColin Finck 
157c2c66affSColin Finck     /* first call could start with second point as all subsequent, cause
158c2c66affSColin Finck        path couldn't contain only one */
159c2c66affSColin Finck     for(i = iterator->marker_pos + 1; i < iterator->pathdata.Count; i++){
160c2c66affSColin Finck         if((iterator->pathdata.Types[i] & PathPointTypePathMarker) ||
161c2c66affSColin Finck            (i == iterator->pathdata.Count - 1)){
162c2c66affSColin Finck             *startIndex = iterator->marker_pos;
163c2c66affSColin Finck             if(iterator->marker_pos > 0) (*startIndex)++;
164c2c66affSColin Finck             *endIndex   = iterator->marker_pos = i;
165c2c66affSColin Finck             *resultCount= *endIndex - *startIndex + 1;
166c2c66affSColin Finck             break;
167c2c66affSColin Finck         }
168c2c66affSColin Finck     }
169c2c66affSColin Finck 
170c2c66affSColin Finck     return Ok;
171c2c66affSColin Finck }
172c2c66affSColin Finck 
GdipPathIterNextMarkerPath(GpPathIterator * iterator,INT * result,GpPath * path)173c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterNextMarkerPath(GpPathIterator* iterator, INT* result,
174c2c66affSColin Finck     GpPath* path)
175c2c66affSColin Finck {
176c2c66affSColin Finck     INT start, end;
177c2c66affSColin Finck 
178c2c66affSColin Finck     TRACE("(%p, %p, %p)\n", iterator, result, path);
179c2c66affSColin Finck 
180c2c66affSColin Finck     if(!iterator || !result)
181c2c66affSColin Finck         return InvalidParameter;
182c2c66affSColin Finck 
183c2c66affSColin Finck     GdipPathIterNextMarker(iterator, result, &start, &end);
184c2c66affSColin Finck     /* return path */
185c2c66affSColin Finck     if(((*result) > 0) && path){
186c2c66affSColin Finck         GdipResetPath(path);
187c2c66affSColin Finck 
188c2c66affSColin Finck         if(!lengthen_path(path, *result))
189c2c66affSColin Finck             return OutOfMemory;
190c2c66affSColin Finck 
191c2c66affSColin Finck         memcpy(path->pathdata.Points, &(iterator->pathdata.Points[start]), sizeof(GpPointF)*(*result));
192c2c66affSColin Finck         memcpy(path->pathdata.Types,  &(iterator->pathdata.Types[start]),  sizeof(BYTE)*(*result));
193c2c66affSColin Finck         path->pathdata.Count = *result;
194c2c66affSColin Finck     }
195c2c66affSColin Finck 
196c2c66affSColin Finck     return Ok;
197c2c66affSColin Finck }
198c2c66affSColin Finck 
GdipPathIterNextSubpath(GpPathIterator * iterator,INT * resultCount,INT * startIndex,INT * endIndex,BOOL * isClosed)199c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator,
200c2c66affSColin Finck     INT *resultCount, INT* startIndex, INT* endIndex, BOOL* isClosed)
201c2c66affSColin Finck {
202c2c66affSColin Finck     INT i, count;
203c2c66affSColin Finck 
204c2c66affSColin Finck     TRACE("(%p, %p, %p, %p, %p)\n", iterator, resultCount, startIndex,
205c2c66affSColin Finck            endIndex, isClosed);
206c2c66affSColin Finck 
207c2c66affSColin Finck     if(!iterator || !startIndex || !endIndex || !isClosed || !resultCount)
208c2c66affSColin Finck         return InvalidParameter;
209c2c66affSColin Finck 
210c2c66affSColin Finck     count = iterator->pathdata.Count;
211c2c66affSColin Finck 
212c2c66affSColin Finck     /* iterator created with NULL path */
213c2c66affSColin Finck     if(count == 0){
214c2c66affSColin Finck         *resultCount = 0;
215c2c66affSColin Finck         return Ok;
216c2c66affSColin Finck     }
217c2c66affSColin Finck 
218c2c66affSColin Finck     if(iterator->subpath_pos == count){
219c2c66affSColin Finck         *startIndex = *endIndex = *resultCount = 0;
220c2c66affSColin Finck         *isClosed = TRUE;
221c2c66affSColin Finck         return Ok;
222c2c66affSColin Finck     }
223c2c66affSColin Finck 
224c2c66affSColin Finck     *startIndex = iterator->subpath_pos;
225c2c66affSColin Finck 
226c2c66affSColin Finck     for(i = iterator->subpath_pos + 1; i < count &&
227c2c66affSColin Finck         !(iterator->pathdata.Types[i] == PathPointTypeStart); i++);
228c2c66affSColin Finck 
229c2c66affSColin Finck     *endIndex = i - 1;
230c2c66affSColin Finck     iterator->subpath_pos = i;
231c2c66affSColin Finck 
232c2c66affSColin Finck     *resultCount = *endIndex - *startIndex + 1;
233c2c66affSColin Finck 
234c2c66affSColin Finck     if(iterator->pathdata.Types[*endIndex] & PathPointTypeCloseSubpath)
235c2c66affSColin Finck         *isClosed = TRUE;
236c2c66affSColin Finck     else
237c2c66affSColin Finck         *isClosed = FALSE;
238c2c66affSColin Finck 
239c2c66affSColin Finck     return Ok;
240c2c66affSColin Finck }
GdipPathIterRewind(GpPathIterator * iterator)241c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator *iterator)
242c2c66affSColin Finck {
243c2c66affSColin Finck     TRACE("(%p)\n", iterator);
244c2c66affSColin Finck 
245c2c66affSColin Finck     if(!iterator)
246c2c66affSColin Finck         return InvalidParameter;
247c2c66affSColin Finck 
248c2c66affSColin Finck     iterator->subpath_pos = 0;
249c2c66affSColin Finck     iterator->marker_pos = 0;
250c2c66affSColin Finck     iterator->pathtype_pos = 0;
251c2c66affSColin Finck 
252c2c66affSColin Finck     return Ok;
253c2c66affSColin Finck }
254c2c66affSColin Finck 
GdipPathIterGetCount(GpPathIterator * iterator,INT * count)255c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator* iterator, INT* count)
256c2c66affSColin Finck {
257c2c66affSColin Finck     TRACE("(%p, %p)\n", iterator, count);
258c2c66affSColin Finck 
259c2c66affSColin Finck     if(!iterator || !count)
260c2c66affSColin Finck         return InvalidParameter;
261c2c66affSColin Finck 
262c2c66affSColin Finck     *count = iterator->pathdata.Count;
263c2c66affSColin Finck 
264c2c66affSColin Finck     return Ok;
265c2c66affSColin Finck }
266c2c66affSColin Finck 
GdipPathIterEnumerate(GpPathIterator * iterator,INT * resultCount,GpPointF * points,BYTE * types,INT count)267c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator* iterator, INT* resultCount,
268c2c66affSColin Finck     GpPointF *points, BYTE *types, INT count)
269c2c66affSColin Finck {
270c2c66affSColin Finck     TRACE("(%p, %p, %p, %p, %d)\n", iterator, resultCount, points, types, count);
271c2c66affSColin Finck 
272c2c66affSColin Finck     if((count < 0) || !resultCount)
273c2c66affSColin Finck         return InvalidParameter;
274c2c66affSColin Finck 
275c2c66affSColin Finck     if(count == 0){
276c2c66affSColin Finck         *resultCount = 0;
277c2c66affSColin Finck         return Ok;
278c2c66affSColin Finck     }
279c2c66affSColin Finck 
280c2c66affSColin Finck     return GdipPathIterCopyData(iterator, resultCount, points, types, 0, count-1);
281c2c66affSColin Finck }
282c2c66affSColin Finck 
GdipPathIterIsValid(GpPathIterator * iterator,BOOL * valid)283c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator* iterator, BOOL* valid)
284c2c66affSColin Finck {
285c2c66affSColin Finck     TRACE("(%p, %p)\n", iterator, valid);
286c2c66affSColin Finck 
287c2c66affSColin Finck     if(!iterator || !valid)
288c2c66affSColin Finck         return InvalidParameter;
289c2c66affSColin Finck 
290c2c66affSColin Finck     *valid = TRUE;
291c2c66affSColin Finck 
292c2c66affSColin Finck     return Ok;
293c2c66affSColin Finck }
294c2c66affSColin Finck 
GdipPathIterNextPathType(GpPathIterator * iter,INT * result,BYTE * type,INT * start,INT * end)295c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterNextPathType(GpPathIterator* iter, INT* result,
296c2c66affSColin Finck     BYTE* type, INT* start, INT* end)
297c2c66affSColin Finck {
298c2c66affSColin Finck     FIXME("(%p, %p, %p, %p, %p) stub\n", iter, result, type, start, end);
299c2c66affSColin Finck 
300c2c66affSColin Finck     if(!iter || !result || !type || !start || !end)
301c2c66affSColin Finck         return InvalidParameter;
302c2c66affSColin Finck 
303c2c66affSColin Finck     return NotImplemented;
304c2c66affSColin Finck }
305c2c66affSColin Finck 
GdipPathIterNextSubpathPath(GpPathIterator * iter,INT * result,GpPath * path,BOOL * closed)306c2c66affSColin Finck GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator* iter, INT* result,
307c2c66affSColin Finck     GpPath* path, BOOL* closed)
308c2c66affSColin Finck {
309c2c66affSColin Finck     INT start, end;
310c2c66affSColin Finck 
311c2c66affSColin Finck     TRACE("(%p, %p, %p, %p)\n", iter, result, path, closed);
312c2c66affSColin Finck 
313c2c66affSColin Finck     if(!iter || !result || !closed)
314c2c66affSColin Finck         return InvalidParameter;
315c2c66affSColin Finck 
316c2c66affSColin Finck     GdipPathIterNextSubpath(iter, result, &start, &end, closed);
317c2c66affSColin Finck     /* return path */
318c2c66affSColin Finck     if(((*result) > 0) && path){
319c2c66affSColin Finck         GdipResetPath(path);
320c2c66affSColin Finck 
321c2c66affSColin Finck         if(!lengthen_path(path, *result))
322c2c66affSColin Finck             return OutOfMemory;
323c2c66affSColin Finck 
324c2c66affSColin Finck         memcpy(path->pathdata.Points, &(iter->pathdata.Points[start]), sizeof(GpPointF)*(*result));
325c2c66affSColin Finck         memcpy(path->pathdata.Types,  &(iter->pathdata.Types[start]),  sizeof(BYTE)*(*result));
326c2c66affSColin Finck         path->pathdata.Count = *result;
327c2c66affSColin Finck     }
328c2c66affSColin Finck 
329c2c66affSColin Finck     return Ok;
330c2c66affSColin Finck }
331