diff --git a/storm/Region.cpp b/storm/Region.cpp index 21e3d04..4350afe 100644 --- a/storm/Region.cpp +++ b/storm/Region.cpp @@ -568,3 +568,25 @@ int32_t SRgnIsRectInRegionf(HSRGN handle, const RECTF* rect) { s_rgntable.Unlock(lockedHandle); return result; } + +void SRgnOffsetf(HSRGN handle, float xoffset, float yoffset) { + STORM_VALIDATE_BEGIN; + STORM_VALIDATE(handle); + STORM_VALIDATE_END_VOID; + + HLOCKEDRGN lockedHandle; + auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0); + if (!rgn) return; + + SOURCE* sourceArray = rgn->source.Ptr(); + uint32_t sourceRects = rgn->source.Count(); + for (uint32_t i = 0; i < sourceRects; i++) { + sourceArray[i].rect.left += xoffset; + sourceArray[i].rect.bottom += yoffset; + sourceArray[i].rect.right += xoffset; + sourceArray[i].rect.top += yoffset; + } + InvalidateRegion(rgn); + + s_rgntable.Unlock(lockedHandle); +} diff --git a/storm/Region.hpp b/storm/Region.hpp index df54302..8d5d3a6 100644 --- a/storm/Region.hpp +++ b/storm/Region.hpp @@ -24,5 +24,6 @@ int32_t SRgnIsPointInRegionf(HSRGN handle, float x, float y); int32_t SRgnIsRectInRegionf(HSRGN handle, const RECTF* rect); +void SRgnOffsetf(HSRGN handle, float xoffset, float yoffset); #endif diff --git a/test/Region.cpp b/test/Region.cpp index b4b5852..495ce18 100644 --- a/test/Region.cpp +++ b/test/Region.cpp @@ -373,3 +373,66 @@ TEST_CASE("SRgnIsRectInRegionf", "[region]") { CHECK_FALSE(SRgnIsRectInRegionf(region, &checkRects[5])); } } + +TEST_CASE("SRgnOffsetf", "[region]") { + RgnDataTest region; + + SECTION("shifts rects by given amount") { + RECTF rects[] = { + { 0.0f, 0.0f, 100.0f, 100.0f }, + { -200.0f, -200.0f, -100.0f, -100.0f } + }; + + SRgnCombineRectf(region, &rects[0], nullptr, SRGN_OR); + SRgnCombineRectf(region, &rects[1], nullptr, SRGN_OR); + + SRgnOffsetf(region, 100.0f, 50.0f); + + uint32_t numRects = 2; + RECTF buffer[2]; + SRgnGetRectsf(region, &numRects, buffer); + + CHECK_THAT(buffer[0], MatchesRect({ -100.0f, -150.0f, 0.0f, -50.0f })); + CHECK_THAT(buffer[1], MatchesRect({ 100.0f, 50.0f, 200.0f, 150.0f })); + } + + SECTION("shifts rects back to their original positions with opposite amounts") { + RECTF rects[] = { + { 0.0f, 0.0f, 100.0f, 100.0f }, + { -200.0f, -200.0f, -100.0f, -100.0f } + }; + + SRgnCombineRectf(region, &rects[0], nullptr, SRGN_OR); + SRgnCombineRectf(region, &rects[1], nullptr, SRGN_OR); + + SRgnOffsetf(region, 100.0f, 50.0f); + SRgnOffsetf(region, 5.0f, 10.0f); + SRgnOffsetf(region, -105.0f, -60.0f); + + uint32_t numRects = 2; + RECTF buffer[2]; + SRgnGetRectsf(region, &numRects, buffer); + + CHECK_THAT(buffer[0], MatchesRect(rects[1])); + CHECK_THAT(buffer[1], MatchesRect(rects[0])); + } + + SECTION("doesn't shift anything with 0") { + RECTF rects[] = { + { 0.0f, 0.0f, 100.0f, 100.0f }, + { -200.0f, -200.0f, -100.0f, -100.0f } + }; + + SRgnCombineRectf(region, &rects[0], nullptr, SRGN_OR); + SRgnCombineRectf(region, &rects[1], nullptr, SRGN_OR); + + SRgnOffsetf(region, 0.0f, 0.0f); + + uint32_t numRects = 2; + RECTF buffer[2]; + SRgnGetRectsf(region, &numRects, buffer); + + CHECK_THAT(buffer[0], MatchesRect(rects[1])); + CHECK_THAT(buffer[1], MatchesRect(rects[0])); + } +}