Vincent Povirk : gdiplus: Implement GdipRegionGetHRgn for paths.

Alexandre Julliard julliard at winehq.org
Tue Nov 25 07:21:49 CST 2008


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Nov 24 15:01:47 2008 -0600

gdiplus: Implement GdipRegionGetHRgn for paths.

---

 dlls/gdiplus/gdiplus_private.h |    2 +
 dlls/gdiplus/graphics.c        |   11 +++++++++
 dlls/gdiplus/region.c          |   45 ++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/tests/region.c    |   29 ++++++++++++++++++++++++-
 4 files changed, 86 insertions(+), 1 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index e9cbfa5..a279268 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -54,6 +54,8 @@ extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
 
 extern BOOL lengthen_path(GpPath *path, INT len);
 
+extern GpStatus trace_path(GpGraphics *graphics, GpPath *path);
+
 typedef struct region_element region_element;
 extern inline void delete_element(region_element *element);
 
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index da2ea6f..b9cb1c2 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -715,6 +715,17 @@ end:
     return status;
 }
 
+GpStatus trace_path(GpGraphics *graphics, GpPath *path)
+{
+    GpStatus result;
+
+    BeginPath(graphics->hdc);
+    result = draw_poly(graphics, NULL, path->pathdata.Points,
+                       path->pathdata.Types, path->pathdata.Count, FALSE);
+    EndPath(graphics->hdc);
+    return result;
+}
+
 GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
 {
     TRACE("(%p, %p)\n", hdc, graphics);
diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index 8cae004..5580319 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -768,6 +768,49 @@ GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
     return Ok;
 }
 
+static GpStatus get_path_hrgn(GpPath *path, GpGraphics *graphics, HRGN *hrgn)
+{
+    HDC new_hdc=NULL;
+    GpStatus stat;
+    INT save_state;
+
+    if (!graphics)
+    {
+        new_hdc = GetDC(0);
+        if (!new_hdc)
+            return OutOfMemory;
+
+        stat = GdipCreateFromHDC(new_hdc, &graphics);
+        if (stat != Ok)
+        {
+            ReleaseDC(0, new_hdc);
+            return stat;
+        }
+    }
+
+    save_state = SaveDC(graphics->hdc);
+    EndPath(graphics->hdc);
+
+    SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
+                                                                    : WINDING));
+
+    stat = trace_path(graphics, path);
+    if (stat == Ok)
+    {
+        *hrgn = PathToRegion(graphics->hdc);
+        stat = *hrgn ? Ok : OutOfMemory;
+    }
+
+    RestoreDC(graphics->hdc, save_state);
+    if (new_hdc)
+    {
+        ReleaseDC(0, new_hdc);
+        GdipDeleteGraphics(graphics);
+    }
+
+    return stat;
+}
+
 static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *graphics, HRGN *hrgn)
 {
     switch (element->type)
@@ -778,6 +821,8 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
         case RegionDataEmptyRect:
             *hrgn = CreateRectRgn(0, 0, 0, 0);
             return *hrgn ? Ok : OutOfMemory;
+        case RegionDataPath:
+            return get_path_hrgn(element->elementdata.pathdata.path, graphics, hrgn);
         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 9cdd929..45ef0b1 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -797,11 +797,14 @@ todo_wine{
 static void test_gethrgn(void)
 {
     GpStatus status;
-    GpRegion *region;
+    GpRegion *region, *region2;
+    GpPath *path;
     GpGraphics *graphics;
     HRGN hrgn;
     HDC hdc=GetDC(0);
     static const RECT empty_rect = {0,0,0,0};
+    static const RECT test_rect = {10, 11, 20, 21};
+    static const RECT scaled_rect = {20, 22, 40, 42};
 
     status = GdipCreateFromHDC(hdc, &graphics);
     ok(status == Ok, "status %08x\n", status);
@@ -831,8 +834,32 @@ static void test_gethrgn(void)
     verify_region(hrgn, &empty_rect);
     DeleteObject(hrgn);
 
+    status = GdipCreatePath(FillModeAlternate, &path);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipAddPathRectangle(path, 10.0, 11.0, 10.0, 10.0);
+    ok(status == Ok, "status %08x\n", status);
+
+    status = GdipCreateRegionPath(path, &region2);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region2, NULL, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &test_rect);
+    DeleteObject(hrgn);
+
+    /* resulting HRGN is in device coordinates */
+    status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
+    ok(status == Ok, "status %08x\n", status);
+    status = GdipGetRegionHRgn(region2, graphics, &hrgn);
+    ok(status == Ok, "status %08x\n", status);
+    verify_region(hrgn, &scaled_rect);
+    DeleteObject(hrgn);
+
+    status = GdipDeletePath(path);
+    ok(status == Ok, "status %08x\n", status);
     status = GdipDeleteRegion(region);
     ok(status == Ok, "status %08x\n", status);
+    status = GdipDeleteRegion(region2);
+    ok(status == Ok, "status %08x\n", status);
     status = GdipDeleteGraphics(graphics);
     ok(status == Ok, "status %08x\n", status);
     ReleaseDC(0, hdc);




More information about the wine-cvs mailing list