From 63fbdc393c3c8ec5fcbc805ba76bbb11f052152b Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 24 Nov 2008 15:01:47 -0600 Subject: [PATCH] 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 57d63c2..8657d5d 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 fa90d73..aaa1109 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); -- 1.5.6.3