[2/2] gdiplus: implemented GdipPathIterNextSubpathPath with tests

Nikolay Sivov bunglehead at gmail.com
Tue Aug 5 11:56:30 CDT 2008


Changelog:
    - lengthen_path shared by moving to gdiplus.c to use for pathiterator
    - implemented GdipPathIterNextSubpathPath with tests
    - fixed GdipPathIterNextSubPath for result return value on empty path (with test)

---
 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 070a80f..5e449e2 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 625c5a0..5ac1f1a 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 3611239..5a18660 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 51407c7..d465aaf 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 5269b0c..2d27e40 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 d318360..9cbed13 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 d7baf52..c0be696 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*);
-- 
1.4.4.4






More information about the wine-patches mailing list