Vincent Povirk : gdiplus: Implement GdipTransformRegion.

Alexandre Julliard julliard at winehq.org
Fri Oct 1 11:38:44 CDT 2010


Module: wine
Branch: master
Commit: 40d8876fc4ce90a07043b4b0b78d8b98c7a972f3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=40d8876fc4ce90a07043b4b0b78d8b98c7a972f3

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Thu Sep 30 14:39:27 2010 -0500

gdiplus: Implement GdipTransformRegion.

---

 dlls/gdiplus/region.c       |   59 ++++++++++++++++++++++-
 dlls/gdiplus/tests/region.c |  108 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+), 2 deletions(-)

diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index decaaf9..9b8ed18 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -1248,11 +1248,66 @@ GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *region)
     return stat;
 }
 
+/* Transforms GpRegion elements with given matrix */
+static GpStatus transform_region_element(region_element* element, GpMatrix *matrix)
+{
+    GpStatus stat;
+
+    switch(element->type)
+    {
+        case RegionDataEmptyRect:
+        case RegionDataInfiniteRect:
+            return Ok;
+        case RegionDataRect:
+        {
+            /* We can't transform a rectangle, so convert it to a path. */
+            GpRegion *new_region;
+            GpPath *path;
+
+            stat = GdipCreatePath(FillModeAlternate, &path);
+            if (stat == Ok)
+            {
+                stat = GdipAddPathRectangle(path,
+                    element->elementdata.rect.X, element->elementdata.rect.Y,
+                    element->elementdata.rect.Width, element->elementdata.rect.Height);
+
+                if (stat == Ok)
+                    stat = GdipCreateRegionPath(path, &new_region);
+
+                GdipDeletePath(path);
+            }
+
+            if (stat == Ok)
+            {
+                /* Steal the element from the created region. */
+                memcpy(element, &new_region->node, sizeof(region_element));
+                HeapFree(GetProcessHeap(), 0, new_region);
+            }
+            else
+                return stat;
+        }
+        /* Fall-through to do the actual conversion. */
+        case RegionDataPath:
+            stat = GdipTransformMatrixPoints(matrix,
+                element->elementdata.pathdata.path->pathdata.Points,
+                element->elementdata.pathdata.path->pathdata.Count);
+            return stat;
+        default:
+            stat = transform_region_element(element->elementdata.combine.left, matrix);
+            if (stat == Ok)
+                stat = transform_region_element(element->elementdata.combine.right, matrix);
+            return stat;
+    }
+}
+
 GpStatus WINGDIPAPI GdipTransformRegion(GpRegion *region, GpMatrix *matrix)
 {
-    FIXME("(%p, %p): stub\n", region, matrix);
+    TRACE("(%p, %p)\n", region, matrix);
 
-    return NotImplemented;
+    if (!region || !matrix)
+        return InvalidParameter;
+
+    return transform_region_element(&region->node, matrix);
 }
 
 /* Translates GpRegion elements with specified offsets */
diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c
index efd2115..96ac40e 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -1123,6 +1123,113 @@ static void test_translate(void)
     ReleaseDC(0, hdc);
 }
 
+static void test_transform(void)
+{
+    GpRegion *region, *region2;
+    GpMatrix *matrix;
+    GpGraphics *graphics;
+    GpPath *path;
+    GpRectF rectf;
+    GpStatus status;
+    HDC hdc = GetDC(0);
+    BOOL res;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+
+    status = GdipCreatePath(FillModeAlternate, &path);
+    expect(Ok, status);
+
+    status = GdipCreateRegion(&region);
+    expect(Ok, status);
+    status = GdipCreateRegion(&region2);
+    expect(Ok, status);
+
+    status = GdipCreateMatrix(&matrix);
+    expect(Ok, status);
+    status = GdipScaleMatrix(matrix, 2.0, 3.0, MatrixOrderAppend);
+    expect(Ok, status);
+
+    /* NULL */
+    status = GdipTransformRegion(NULL, matrix);
+    expect(InvalidParameter, status);
+
+    status = GdipTransformRegion(region, NULL);
+    expect(InvalidParameter, status);
+
+    /* infinite */
+    status = GdipTransformRegion(region, matrix);
+    expect(Ok, status);
+
+    res = FALSE;
+    status = GdipIsEqualRegion(region, region2, graphics, &res);
+    expect(Ok, status);
+    ok(res, "Expected to be equal.\n");
+
+    /* empty */
+    status = GdipSetEmpty(region);
+    expect(Ok, status);
+    status = GdipTransformRegion(region, matrix);
+    expect(Ok, status);
+
+    status = GdipSetEmpty(region2);
+    expect(Ok, status);
+
+    res = FALSE;
+    status = GdipIsEqualRegion(region, region2, graphics, &res);
+    expect(Ok, status);
+    ok(res, "Expected to be equal.\n");
+
+    /* rect */
+    rectf.X = 10.0;
+    rectf.Y = 0.0;
+    rectf.Width = rectf.Height = 100.0;
+    status = GdipCombineRegionRect(region, &rectf, CombineModeReplace);
+    expect(Ok, status);
+    rectf.X = 20.0;
+    rectf.Y = 0.0;
+    rectf.Width = 200.0;
+    rectf.Height = 300.0;
+    status = GdipCombineRegionRect(region2, &rectf, CombineModeReplace);
+    expect(Ok, status);
+    status = GdipTransformRegion(region, matrix);
+    expect(Ok, status);
+    res = FALSE;
+    status = GdipIsEqualRegion(region, region2, graphics, &res);
+    expect(Ok, status);
+    ok(res, "Expected to be equal.\n");
+
+    /* path */
+    status = GdipAddPathEllipse(path, 0.0, 10.0, 100.0, 150.0);
+    expect(Ok, status);
+    status = GdipCombineRegionPath(region, path, CombineModeReplace);
+    expect(Ok, status);
+    status = GdipResetPath(path);
+    expect(Ok, status);
+    status = GdipAddPathEllipse(path, 0.0, 30.0, 200.0, 450.0);
+    expect(Ok, status);
+    status = GdipCombineRegionPath(region2, path, CombineModeReplace);
+    expect(Ok, status);
+    status = GdipTransformRegion(region, matrix);
+    expect(Ok, status);
+    res = FALSE;
+    status = GdipIsEqualRegion(region, region2, graphics, &res);
+    expect(Ok, status);
+    ok(res, "Expected to be equal.\n");
+
+    status = GdipDeleteRegion(region);
+    expect(Ok, status);
+    status = GdipDeleteRegion(region2);
+    expect(Ok, status);
+    status = GdipDeleteGraphics(graphics);
+    expect(Ok, status);
+    status = GdipDeletePath(path);
+    expect(Ok, status);
+    status = GdipDeleteMatrix(matrix);
+    expect(Ok, status);
+    ReleaseDC(0, hdc);
+}
+
 static void test_getbounds(void)
 {
     GpRegion *region;
@@ -1634,6 +1741,7 @@ START_TEST(region)
     test_gethrgn();
     test_isequal();
     test_translate();
+    test_transform();
     test_getbounds();
     test_isvisiblepoint();
     test_isvisiblerect();




More information about the wine-cvs mailing list