From f14bb23717d8511c846ca2fd6c16519eb5efb92f Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 24 Nov 2008 17:20:00 -0600 Subject: [PATCH] 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); -- 1.5.6.3