| /* | |
| * Copyright (C) 2007 Google (Evan Stade) | |
| * Copyright (C) 2008 Nikolay Sivov <bunglehead at gmail dot com> | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "wingdi.h" | |
| #include "objbase.h" | |
| #include "gdiplus.h" | |
| #include "gdiplus_private.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); | |
| GpStatus WINGDIPAPI GdipCreatePathIter(GpPathIterator **iterator, GpPath* path) | |
| { | |
| INT size; | |
| TRACE("(%p, %p)\n", iterator, path); | |
| if(!iterator) | |
| return InvalidParameter; | |
| *iterator = GdipAlloc(sizeof(GpPathIterator)); | |
| if(!*iterator) return OutOfMemory; | |
| if(path){ | |
| size = path->pathdata.Count; | |
| (*iterator)->pathdata.Types = GdipAlloc(size); | |
| (*iterator)->pathdata.Points = GdipAlloc(size * sizeof(PointF)); | |
| memcpy((*iterator)->pathdata.Types, path->pathdata.Types, size); | |
| memcpy((*iterator)->pathdata.Points, path->pathdata.Points,size * sizeof(PointF)); | |
| (*iterator)->pathdata.Count = size; | |
| } | |
| else{ | |
| (*iterator)->pathdata.Types = NULL; | |
| (*iterator)->pathdata.Points = NULL; | |
| (*iterator)->pathdata.Count = 0; | |
| } | |
| (*iterator)->subpath_pos = 0; | |
| (*iterator)->marker_pos = 0; | |
| (*iterator)->pathtype_pos = 0; | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipDeletePathIter(GpPathIterator *iter) | |
| { | |
| TRACE("(%p)\n", iter); | |
| if(!iter) | |
| return InvalidParameter; | |
| GdipFree(iter->pathdata.Types); | |
| GdipFree(iter->pathdata.Points); | |
| GdipFree(iter); | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator* iterator, | |
| INT* resultCount, GpPointF* points, BYTE* types, INT startIndex, INT endIndex) | |
| { | |
| TRACE("(%p, %p, %p, %p, %d, %d)\n", iterator, resultCount, points, types, | |
| startIndex, endIndex); | |
| if(!iterator || !types || !points) | |
| return InvalidParameter; | |
| if(endIndex > iterator->pathdata.Count - 1 || startIndex < 0 || | |
| endIndex < startIndex){ | |
| *resultCount = 0; | |
| return Ok; | |
| } | |
| *resultCount = endIndex - startIndex + 1; | |
| memcpy(types, &(iterator->pathdata.Types[startIndex]), *resultCount); | |
| memcpy(points, &(iterator->pathdata.Points[startIndex]), | |
| *resultCount * sizeof(PointF)); | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterHasCurve(GpPathIterator* iterator, BOOL* hasCurve) | |
| { | |
| INT i; | |
| TRACE("(%p, %p)\n", iterator, hasCurve); | |
| if(!iterator) | |
| return InvalidParameter; | |
| *hasCurve = FALSE; | |
| for(i = 0; i < iterator->pathdata.Count; i++) | |
| if((iterator->pathdata.Types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier){ | |
| *hasCurve = TRUE; | |
| break; | |
| } | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterGetSubpathCount(GpPathIterator* iterator, INT* count) | |
| { | |
| INT i; | |
| TRACE("(%p, %p)\n", iterator, count); | |
| if(!iterator || !count) | |
| return InvalidParameter; | |
| *count = 0; | |
| for(i = 0; i < iterator->pathdata.Count; i++){ | |
| if(iterator->pathdata.Types[i] == PathPointTypeStart) | |
| (*count)++; | |
| } | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterNextMarker(GpPathIterator* iterator, INT *resultCount, | |
| INT* startIndex, INT* endIndex) | |
| { | |
| INT i; | |
| TRACE("(%p, %p, %p, %p)\n", iterator, resultCount, startIndex, endIndex); | |
| if(!iterator || !startIndex || !endIndex) | |
| return InvalidParameter; | |
| *resultCount = 0; | |
| /* first call could start with second point as all subsequent, cause | |
| path couldn't contain only one */ | |
| for(i = iterator->marker_pos + 1; i < iterator->pathdata.Count; i++){ | |
| if((iterator->pathdata.Types[i] & PathPointTypePathMarker) || | |
| (i == iterator->pathdata.Count - 1)){ | |
| *startIndex = iterator->marker_pos; | |
| if(iterator->marker_pos > 0) (*startIndex)++; | |
| *endIndex = iterator->marker_pos = i; | |
| *resultCount= *endIndex - *startIndex + 1; | |
| break; | |
| } | |
| } | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterNextMarkerPath(GpPathIterator* iterator, INT* result, | |
| GpPath* path) | |
| { | |
| INT start, end; | |
| TRACE("(%p, %p, %p)\n", iterator, result, path); | |
| if(!iterator || !result) | |
| return InvalidParameter; | |
| GdipPathIterNextMarker(iterator, result, &start, &end); | |
| /* return path */ | |
| if(((*result) > 0) && path){ | |
| GdipResetPath(path); | |
| if(!lengthen_path(path, *result)) | |
| return OutOfMemory; | |
| memcpy(path->pathdata.Points, &(iterator->pathdata.Points[start]), sizeof(GpPointF)*(*result)); | |
| memcpy(path->pathdata.Types, &(iterator->pathdata.Types[start]), sizeof(BYTE)*(*result)); | |
| path->pathdata.Count = *result; | |
| } | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator, | |
| INT *resultCount, INT* startIndex, INT* endIndex, BOOL* isClosed) | |
| { | |
| INT i, count; | |
| TRACE("(%p, %p, %p, %p, %p)\n", iterator, resultCount, startIndex, | |
| endIndex, isClosed); | |
| if(!iterator || !startIndex || !endIndex || !isClosed || !resultCount) | |
| return InvalidParameter; | |
| count = iterator->pathdata.Count; | |
| /* iterator created with NULL path */ | |
| if(count == 0){ | |
| *resultCount = 0; | |
| return Ok; | |
| } | |
| if(iterator->subpath_pos == count){ | |
| *startIndex = *endIndex = *resultCount = 0; | |
| *isClosed = 1; | |
| return Ok; | |
| } | |
| *startIndex = iterator->subpath_pos; | |
| for(i = iterator->subpath_pos + 1; i < count && | |
| !(iterator->pathdata.Types[i] == PathPointTypeStart); i++); | |
| *endIndex = i - 1; | |
| iterator->subpath_pos = i; | |
| *resultCount = *endIndex - *startIndex + 1; | |
| if(iterator->pathdata.Types[*endIndex] & PathPointTypeCloseSubpath) | |
| *isClosed = TRUE; | |
| else | |
| *isClosed = FALSE; | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator *iterator) | |
| { | |
| TRACE("(%p)\n", iterator); | |
| if(!iterator) | |
| return InvalidParameter; | |
| iterator->subpath_pos = 0; | |
| iterator->marker_pos = 0; | |
| iterator->pathtype_pos = 0; | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator* iterator, INT* count) | |
| { | |
| TRACE("(%p, %p)\n", iterator, count); | |
| if(!iterator || !count) | |
| return InvalidParameter; | |
| *count = iterator->pathdata.Count; | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator* iterator, INT* resultCount, | |
| GpPointF *points, BYTE *types, INT count) | |
| { | |
| TRACE("(%p, %p, %p, %p, %d)\n", iterator, resultCount, points, types, count); | |
| if((count < 0) || !resultCount) | |
| return InvalidParameter; | |
| if(count == 0){ | |
| *resultCount = 0; | |
| return Ok; | |
| } | |
| return GdipPathIterCopyData(iterator, resultCount, points, types, 0, count-1); | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator* iterator, BOOL* valid) | |
| { | |
| TRACE("(%p, %p)\n", iterator, valid); | |
| if(!iterator || !valid) | |
| return InvalidParameter; | |
| *valid = TRUE; | |
| return Ok; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterNextPathType(GpPathIterator* iter, INT* result, | |
| BYTE* type, INT* start, INT* end) | |
| { | |
| FIXME("(%p, %p, %p, %p, %p) stub\n", iter, result, type, start, end); | |
| if(!iter || !result || !type || !start || !end) | |
| return InvalidParameter; | |
| return NotImplemented; | |
| } | |
| GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator* iter, INT* result, | |
| GpPath* path, BOOL* closed) | |
| { | |
| INT start, end; | |
| TRACE("(%p, %p, %p, %p)\n", iter, result, path, closed); | |
| if(!iter || !result || !closed) | |
| return InvalidParameter; | |
| GdipPathIterNextSubpath(iter, result, &start, &end, closed); | |
| /* return path */ | |
| if(((*result) > 0) && path){ | |
| GdipResetPath(path); | |
| if(!lengthen_path(path, *result)) | |
| return OutOfMemory; | |
| memcpy(path->pathdata.Points, &(iter->pathdata.Points[start]), sizeof(GpPointF)*(*result)); | |
| memcpy(path->pathdata.Types, &(iter->pathdata.Types[start]), sizeof(BYTE)*(*result)); | |
| path->pathdata.Count = *result; | |
| } | |
| return Ok; | |
| } |