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 <stdarg.h> 21 22 #include "windef.h" 23 #include "winbase.h" 24 #include "wingdi.h" 25 26 #include "objbase.h" 27 28 #include "gdiplus.h" 29 #include "gdiplus_private.h" 30 #include "wine/debug.h" 31 32 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); 33 34 GpStatus WINGDIPAPI GdipCreatePathIter(GpPathIterator **iterator, GpPath* path) 35 { 36 INT size; 37 38 TRACE("(%p, %p)\n", iterator, path); 39 40 if(!iterator) 41 return InvalidParameter; 42 43 *iterator = heap_alloc_zero(sizeof(GpPathIterator)); 44 if(!*iterator) return OutOfMemory; 45 46 if(path){ 47 size = path->pathdata.Count; 48 49 (*iterator)->pathdata.Types = heap_alloc_zero(size); 50 (*iterator)->pathdata.Points = heap_alloc_zero(size * sizeof(PointF)); 51 52 memcpy((*iterator)->pathdata.Types, path->pathdata.Types, size); 53 memcpy((*iterator)->pathdata.Points, path->pathdata.Points,size * sizeof(PointF)); 54 (*iterator)->pathdata.Count = size; 55 } 56 else{ 57 (*iterator)->pathdata.Types = NULL; 58 (*iterator)->pathdata.Points = NULL; 59 (*iterator)->pathdata.Count = 0; 60 } 61 62 (*iterator)->subpath_pos = 0; 63 (*iterator)->marker_pos = 0; 64 (*iterator)->pathtype_pos = 0; 65 66 return Ok; 67 } 68 69 GpStatus WINGDIPAPI GdipDeletePathIter(GpPathIterator *iter) 70 { 71 TRACE("(%p)\n", iter); 72 73 if(!iter) 74 return InvalidParameter; 75 76 heap_free(iter->pathdata.Types); 77 heap_free(iter->pathdata.Points); 78 heap_free(iter); 79 80 return Ok; 81 } 82 83 GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator* iterator, 84 INT* resultCount, GpPointF* points, BYTE* types, INT startIndex, INT endIndex) 85 { 86 TRACE("(%p, %p, %p, %p, %d, %d)\n", iterator, resultCount, points, types, 87 startIndex, endIndex); 88 89 if(!iterator || !types || !points) 90 return InvalidParameter; 91 92 if(endIndex > iterator->pathdata.Count - 1 || startIndex < 0 || 93 endIndex < startIndex){ 94 *resultCount = 0; 95 return Ok; 96 } 97 98 *resultCount = endIndex - startIndex + 1; 99 100 memcpy(types, &(iterator->pathdata.Types[startIndex]), *resultCount); 101 memcpy(points, &(iterator->pathdata.Points[startIndex]), 102 *resultCount * sizeof(PointF)); 103 104 return Ok; 105 } 106 107 GpStatus WINGDIPAPI GdipPathIterHasCurve(GpPathIterator* iterator, BOOL* hasCurve) 108 { 109 INT i; 110 111 TRACE("(%p, %p)\n", iterator, hasCurve); 112 113 if(!iterator) 114 return InvalidParameter; 115 116 *hasCurve = FALSE; 117 118 for(i = 0; i < iterator->pathdata.Count; i++) 119 if((iterator->pathdata.Types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){ 120 *hasCurve = TRUE; 121 break; 122 } 123 124 return Ok; 125 } 126 127 GpStatus WINGDIPAPI GdipPathIterGetSubpathCount(GpPathIterator* iterator, INT* count) 128 { 129 INT i; 130 131 TRACE("(%p, %p)\n", iterator, count); 132 133 if(!iterator || !count) 134 return InvalidParameter; 135 136 *count = 0; 137 for(i = 0; i < iterator->pathdata.Count; i++){ 138 if(iterator->pathdata.Types[i] == PathPointTypeStart) 139 (*count)++; 140 } 141 142 return Ok; 143 } 144 145 GpStatus WINGDIPAPI GdipPathIterNextMarker(GpPathIterator* iterator, INT *resultCount, 146 INT* startIndex, INT* endIndex) 147 { 148 INT i; 149 150 TRACE("(%p, %p, %p, %p)\n", iterator, resultCount, startIndex, endIndex); 151 152 if(!iterator || !startIndex || !endIndex) 153 return InvalidParameter; 154 155 *resultCount = 0; 156 157 /* first call could start with second point as all subsequent, cause 158 path couldn't contain only one */ 159 for(i = iterator->marker_pos + 1; i < iterator->pathdata.Count; i++){ 160 if((iterator->pathdata.Types[i] & PathPointTypePathMarker) || 161 (i == iterator->pathdata.Count - 1)){ 162 *startIndex = iterator->marker_pos; 163 if(iterator->marker_pos > 0) (*startIndex)++; 164 *endIndex = iterator->marker_pos = i; 165 *resultCount= *endIndex - *startIndex + 1; 166 break; 167 } 168 } 169 170 return Ok; 171 } 172 173 GpStatus WINGDIPAPI GdipPathIterNextMarkerPath(GpPathIterator* iterator, INT* result, 174 GpPath* path) 175 { 176 INT start, end; 177 178 TRACE("(%p, %p, %p)\n", iterator, result, path); 179 180 if(!iterator || !result) 181 return InvalidParameter; 182 183 GdipPathIterNextMarker(iterator, result, &start, &end); 184 /* return path */ 185 if(((*result) > 0) && path){ 186 GdipResetPath(path); 187 188 if(!lengthen_path(path, *result)) 189 return OutOfMemory; 190 191 memcpy(path->pathdata.Points, &(iterator->pathdata.Points[start]), sizeof(GpPointF)*(*result)); 192 memcpy(path->pathdata.Types, &(iterator->pathdata.Types[start]), sizeof(BYTE)*(*result)); 193 path->pathdata.Count = *result; 194 } 195 196 return Ok; 197 } 198 199 GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator, 200 INT *resultCount, INT* startIndex, INT* endIndex, BOOL* isClosed) 201 { 202 INT i, count; 203 204 TRACE("(%p, %p, %p, %p, %p)\n", iterator, resultCount, startIndex, 205 endIndex, isClosed); 206 207 if(!iterator || !startIndex || !endIndex || !isClosed || !resultCount) 208 return InvalidParameter; 209 210 count = iterator->pathdata.Count; 211 212 /* iterator created with NULL path */ 213 if(count == 0){ 214 *resultCount = 0; 215 return Ok; 216 } 217 218 if(iterator->subpath_pos == count){ 219 *startIndex = *endIndex = *resultCount = 0; 220 *isClosed = TRUE; 221 return Ok; 222 } 223 224 *startIndex = iterator->subpath_pos; 225 226 for(i = iterator->subpath_pos + 1; i < count && 227 !(iterator->pathdata.Types[i] == PathPointTypeStart); i++); 228 229 *endIndex = i - 1; 230 iterator->subpath_pos = i; 231 232 *resultCount = *endIndex - *startIndex + 1; 233 234 if(iterator->pathdata.Types[*endIndex] & PathPointTypeCloseSubpath) 235 *isClosed = TRUE; 236 else 237 *isClosed = FALSE; 238 239 return Ok; 240 } 241 GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator *iterator) 242 { 243 TRACE("(%p)\n", iterator); 244 245 if(!iterator) 246 return InvalidParameter; 247 248 iterator->subpath_pos = 0; 249 iterator->marker_pos = 0; 250 iterator->pathtype_pos = 0; 251 252 return Ok; 253 } 254 255 GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator* iterator, INT* count) 256 { 257 TRACE("(%p, %p)\n", iterator, count); 258 259 if(!iterator || !count) 260 return InvalidParameter; 261 262 *count = iterator->pathdata.Count; 263 264 return Ok; 265 } 266 267 GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator* iterator, INT* resultCount, 268 GpPointF *points, BYTE *types, INT count) 269 { 270 TRACE("(%p, %p, %p, %p, %d)\n", iterator, resultCount, points, types, count); 271 272 if((count < 0) || !resultCount) 273 return InvalidParameter; 274 275 if(count == 0){ 276 *resultCount = 0; 277 return Ok; 278 } 279 280 return GdipPathIterCopyData(iterator, resultCount, points, types, 0, count-1); 281 } 282 283 GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator* iterator, BOOL* valid) 284 { 285 TRACE("(%p, %p)\n", iterator, valid); 286 287 if(!iterator || !valid) 288 return InvalidParameter; 289 290 *valid = TRUE; 291 292 return Ok; 293 } 294 295 GpStatus WINGDIPAPI GdipPathIterNextPathType(GpPathIterator* iter, INT* result, 296 BYTE* type, INT* start, INT* end) 297 { 298 FIXME("(%p, %p, %p, %p, %p) stub\n", iter, result, type, start, end); 299 300 if(!iter || !result || !type || !start || !end) 301 return InvalidParameter; 302 303 return NotImplemented; 304 } 305 306 GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator* iter, INT* result, 307 GpPath* path, BOOL* closed) 308 { 309 INT start, end; 310 311 TRACE("(%p, %p, %p, %p)\n", iter, result, path, closed); 312 313 if(!iter || !result || !closed) 314 return InvalidParameter; 315 316 GdipPathIterNextSubpath(iter, result, &start, &end, closed); 317 /* return path */ 318 if(((*result) > 0) && path){ 319 GdipResetPath(path); 320 321 if(!lengthen_path(path, *result)) 322 return OutOfMemory; 323 324 memcpy(path->pathdata.Points, &(iter->pathdata.Points[start]), sizeof(GpPointF)*(*result)); 325 memcpy(path->pathdata.Types, &(iter->pathdata.Types[start]), sizeof(BYTE)*(*result)); 326 path->pathdata.Count = *result; 327 } 328 329 return Ok; 330 } 331