Vincent Povirk : gdiplus: Implement GdipGetRegionHRgn for combined regions.

Alexandre Julliard julliard at winehq.org
Thu Dec 4 09:02:26 CST 2008


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Nov 24 17:20:00 2008 -0600

gdiplus: Implement GdipGetRegionHRgn for combined regions.

---

 dlls/gdiplus/region.c       |   92 +++++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/tests/region.c |   49 +++++++++++++++++++++++
 2 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index 509c7ce..d28292c 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -841,6 +841,98 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
 
             return stat;
         }
+        case CombineModeIntersect:
+        case CombineModeUnion:
+        case CombineModeXor:
+        case CombineModeExclude:
+        case CombineModeComplement:
+        {
+            HRGN left, right;
+            GpStatus stat;
+            int ret;
+
+            stat = get_region_hrgn(element->elementdata.combine.left, graphics, &left);
+            if (stat != Ok)
+            {
+                *hrgn = NULL;
+                return stat;
+            }
+
+            if (left == NULL)
+            {
+                /* existing region is infinite */
+                switch (element->type)
+                {
+                    case CombineModeIntersect:
+                        return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn);
+                    case CombineModeXor: case CombineModeExclude:
+                        FIXME("cannot exclude from an infinite region\n");
+                        /* fall-through */
+                    case CombineModeUnion: case CombineModeComplement:
+                        *hrgn = NULL;
+                        return Ok;
+                }
+            }
+
+            stat = get_region_hrgn(element->elementdata.combine.right, graphics, &right);
+            if (stat != Ok)
+            {
+                DeleteObject(left);
+                *hrgn = NULL;
+                return stat;
+            }
+
+            if (right == NULL)
+            {
+                /* new region is infinite */
+                switch (element->type)
+                {
+                    case CombineModeIntersect:
+                        *hrgn = left;
+                        return Ok;
+                    case CombineModeXor: case CombineModeComplement:
+                        FIXME("cannot exclude from an infinite region\n");
+                        /* fall-through */
+                    case CombineModeUnion: case CombineModeExclude:
+                        DeleteObject(left);
+                        *hrgn = NULL;
+                        return Ok;
+                }
+            }
+
+            switch (element->type)
+            {
+                case CombineModeIntersect:
+                    ret = CombineRgn(left, left, right, RGN_AND);
+                    break;
+                case CombineModeUnion:
+                    ret = CombineRgn(left, left, right, RGN_OR);
+                    break;
+                case CombineModeXor:
+                    ret = CombineRgn(left, left, right, RGN_XOR);
+                    break;
+                case CombineModeExclude:
+                    ret = CombineRgn(left, left, right, RGN_DIFF);
+                    break;
+                case CombineModeComplement:
+                    ret = CombineRgn(left, right, left, RGN_DIFF);
+                    break;
+                default:
+                    ret = ERROR;
+            }
+
+            DeleteObject(right);
+
+            if (ret == ERROR)
+            {
+                DeleteObject(left);
+                *hrgn = NULL;
+                return GenericError;
+            }
+
+            *hrgn = left;
+            return Ok;
+        }
         default:
             FIXME("GdipGetRegionHRgn unimplemented for region type=%x\n", element->type);
             *hrgn = NULL;
diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c
index 34024be..15363f2 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -806,6 +806,10 @@ static void test_gethrgn(void)
     static const RECT test_rect = {10, 11, 20, 21};
     static const GpRectF test_rectF = {10.0, 11.0, 10.0, 10.0};
     static const RECT scaled_rect = {20, 22, 40, 42};
+    static const RECT test_rect2 = {10, 21, 20, 31};
+    static const GpRectF test_rect2F = {10.0, 21.0, 10.0, 10.0};
+    static const RECT test_rect3 = {10, 11, 20, 31};
+    static const GpRectF test_rect3F = {10.0, 11.0, 10.0, 20.0};
 
     status = GdipCreateFromHDC(hdc, &graphics);
     ok(status == Ok, "status %08x\n", status);
@@ -867,6 +871,51 @@ static void test_gethrgn(void)
     verify_region(hrgn, &scaled_rect);
     DeleteObject(hrgn);
 
+    status = GdipSetInfinite(region);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeIntersect);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rect2F, CombineModeUnion);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect3);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rect3F, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rect2F, CombineModeXor);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rect3F, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeExclude);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect2);
+    DeleteObject(hrgn);
+
+    status = GdipCombineRegionRect(region, &test_rectF, CombineModeReplace);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipCombineRegionRect(region, &test_rect3F, CombineModeComplement);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect2);
+    DeleteObject(hrgn);
+
     status = GdipDeletePath(path);
     ok(status == Ok, "status %08x\n", status);
     status = GdipDeleteRegion(region);




More information about the wine-cvs mailing list