From ef889d94a345b7d637604e5bc9c95b8c5be70d93 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 5 Aug 2008 20:56:30 +0400 Subject: [PATCH] gdiplus: Implemented GdipPathIterNextSubpathPath with tests. --- dlls/gdiplus/gdiplus.c | 33 +++++++ dlls/gdiplus/gdiplus.spec | 2 +- dlls/gdiplus/gdiplus_private.h | 2 + dlls/gdiplus/graphicspath.c | 33 ------- dlls/gdiplus/pathiterator.c | 28 +++++- dlls/gdiplus/tests/pathiterator.c | 140 ++++++++++++++++++++++++++++++ include/gdiplusflat.h | 1 + 7 files changed, 204 insertions(+), 35 deletions(-) diff --git a/dlls/gdiplus/gdiplus.c b/dlls/gdiplus/gdiplus.c index 070a80f993b..5e449e2f348 100644 --- a/dlls/gdiplus/gdiplus.c +++ b/dlls/gdiplus/gdiplus.c @@ -311,3 +311,36 @@ void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, *x = roundr(tension * (xadj - xend) + xend); *y = roundr(tension * (yadj - yend) + yend); } + +/* make sure path has enough space for len more points */ +BOOL lengthen_path(GpPath *path, INT len) +{ + /* initial allocation */ + if(path->datalen == 0){ + path->datalen = len * 2; + + path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF)); + if(!path->pathdata.Points) return FALSE; + + path->pathdata.Types = GdipAlloc(path->datalen); + if(!path->pathdata.Types){ + GdipFree(path->pathdata.Points); + return FALSE; + } + } + /* reallocation, double size of arrays */ + else if(path->datalen - path->pathdata.Count < len){ + while(path->datalen - path->pathdata.Count < len) + path->datalen *= 2; + + path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0, + path->pathdata.Points, path->datalen * sizeof(PointF)); + if(!path->pathdata.Points) return FALSE; + + path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0, + path->pathdata.Types, path->datalen); + if(!path->pathdata.Types) return FALSE; + } + + return TRUE; +} diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 625c5a08bf0..5ac1f1a7be7 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -460,7 +460,7 @@ @ stub GdipPathIterNextMarkerPath @ stub GdipPathIterNextPathType @ stdcall GdipPathIterNextSubpath(ptr ptr ptr ptr ptr) -@ stub GdipPathIterNextSubpathPath +@ stdcall GdipPathIterNextSubpathPath(ptr ptr ptr ptr) @ stdcall GdipPathIterRewind(ptr) @ stub GdipPlayMetafileRecord @ stub GdipPlayTSClientRecord diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 3611239f2b2..5a186602f2e 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -52,6 +52,8 @@ extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1, extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, REAL tension, REAL *x, REAL *y); +extern BOOL lengthen_path(GpPath *path, INT len); + static inline INT roundr(REAL x) { return (INT) floorf(x + 0.5); diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 51407c71d82..d465aaf8bda 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -33,39 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); -/* make sure path has enough space for len more points */ -static BOOL lengthen_path(GpPath *path, INT len) -{ - /* initial allocation */ - if(path->datalen == 0){ - path->datalen = len * 2; - - path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF)); - if(!path->pathdata.Points) return FALSE; - - path->pathdata.Types = GdipAlloc(path->datalen); - if(!path->pathdata.Types){ - GdipFree(path->pathdata.Points); - return FALSE; - } - } - /* reallocation, double size of arrays */ - else if(path->datalen - path->pathdata.Count < len){ - while(path->datalen - path->pathdata.Count < len) - path->datalen *= 2; - - path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0, - path->pathdata.Points, path->datalen * sizeof(PointF)); - if(!path->pathdata.Points) return FALSE; - - path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0, - path->pathdata.Types, path->datalen); - if(!path->pathdata.Types) return FALSE; - } - - return TRUE; -} - GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle) { diff --git a/dlls/gdiplus/pathiterator.c b/dlls/gdiplus/pathiterator.c index 5269b0c480d..afb4f34d2f4 100644 --- a/dlls/gdiplus/pathiterator.c +++ b/dlls/gdiplus/pathiterator.c @@ -164,8 +164,10 @@ GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator, count = iterator->pathdata.Count; /* iterator created with NULL path */ - if(count == 0) + if(count == 0){ + *resultCount = 0; return Ok; + } if(iterator->subpath_pos == count){ *startIndex = *endIndex = *resultCount = 0; @@ -235,3 +237,27 @@ GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator* iterator, BOOL* valid) return Ok; } + +GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator* iter, INT* result, + GpPath* path, BOOL* closed) +{ + INT start, end; + + 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; +} diff --git a/dlls/gdiplus/tests/pathiterator.c b/dlls/gdiplus/tests/pathiterator.c index d3183604786..9cbed1390d0 100644 --- a/dlls/gdiplus/tests/pathiterator.c +++ b/dlls/gdiplus/tests/pathiterator.c @@ -255,6 +255,144 @@ static void test_isvalid(void) GdipDeletePath(path); } +static void test_nextsubpathpath(void) +{ + GpPath *path, *retpath; + GpPathIterator *iter; + GpStatus stat; + BOOL closed; + INT count, result; + + GdipCreatePath(FillModeAlternate, &path); + + /* NULL args */ + GdipCreatePath(FillModeAlternate, &retpath); + GdipCreatePathIter(&iter, path); + stat = GdipPathIterNextSubpathPath(NULL, NULL, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(NULL, &result, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, &result, NULL, &closed); + expect(Ok, stat); + stat = GdipPathIterNextSubpathPath(iter, NULL, NULL, &closed); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, NULL, retpath, NULL); + expect(InvalidParameter, stat); + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, NULL); + expect(InvalidParameter, stat); + GdipDeletePathIter(iter); + GdipDeletePath(retpath); + + /* empty path */ + GdipCreatePath(FillModeAlternate, &retpath); + GdipCreatePathIter(&iter, path); + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(0, count); + GdipDeletePathIter(iter); + GdipDeletePath(retpath); + + /* open figure */ + GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0); + + GdipCreatePath(FillModeAlternate, &retpath); + GdipCreatePathIter(&iter, path); + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(2, result); + expect(FALSE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + /* subsequent call */ + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + GdipDeletePathIter(iter); + + /* closed figure, check does it extend retpath or reset it */ + GdipAddPathLine(retpath, 50.0, 55.0, 200.0, 150.0); + + GdipClosePathFigure(path); + GdipAddPathLine(path, 50.0, 55.0, 200.0, 150.0); + GdipClosePathFigure(path); + + GdipCreatePathIter(&iter, path); + result = -2; + closed = FALSE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(2, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + /* subsequent call */ + result = -2; + closed = FALSE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(2, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + result = -2; + closed = FALSE; + stat = GdipPathIterNextSubpathPath(iter, &result, retpath, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + count = -1; + GdipGetPointCount(retpath, &count); + expect(2, count); + GdipDeletePathIter(iter); + + GdipDeletePath(retpath); + GdipDeletePath(path); +} + +static void test_nextsubpath(void) +{ + GpPath *path; + GpPathIterator *iter; + GpStatus stat; + INT start, end, result; + BOOL closed; + + GdipCreatePath(FillModeAlternate, &path); + + /* empty path */ + GdipCreatePath(FillModeAlternate, &path); + GdipCreatePathIter(&iter, path); + + result = -2; + closed = TRUE; + stat = GdipPathIterNextSubpath(iter, &result, &start, &end, &closed); + expect(Ok, stat); + expect(0, result); + expect(TRUE, closed); + GdipCreatePathIter(&iter, path); + + GdipDeletePath(path); +} + START_TEST(pathiterator) { struct GdiplusStartupInput gdiplusStartupInput; @@ -272,6 +410,8 @@ START_TEST(pathiterator) test_nextmarker(); test_getsubpathcount(); test_isvalid(); + test_nextsubpathpath(); + test_nextsubpath(); GdiplusShutdown(gdiplusToken); } diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index d7baf52eabf..c0be696438c 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -328,6 +328,7 @@ GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator*,INT*,GpPointF*,BYTE*, INT,INT); GpStatus WINGDIPAPI GdipPathIterNextMarker(GpPathIterator*,INT*,INT*,INT*); GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator*,INT*,INT*,INT*,BOOL*); +GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator*,INT*,GpPath*,BOOL*); GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator*); GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator*,INT*); GpStatus WINGDIPAPI GdipPathIterGetSubpathCount(GpPathIterator*,INT*);