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