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, ®ion2);
+ 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