feat(region): add SRgnGetRectParamsf

This commit is contained in:
Adam Heinermann 2025-04-21 15:20:25 -07:00 committed by fallenoak
parent ff85d9138d
commit a5c55bc803
3 changed files with 153 additions and 14 deletions

View file

@ -106,6 +106,45 @@ void DeleteRect(RECTF* rect) {
rect->top = std::numeric_limits<float>::max(); rect->top = std::numeric_limits<float>::max();
} }
int SortFoundParamsCallback(const void* elem1, const void* elem2) {
const FOUNDPARAM* param1 = static_cast<const FOUNDPARAM*>(elem1);
const FOUNDPARAM* param2 = static_cast<const FOUNDPARAM*>(elem2);
return param1->sequence - param2->sequence;
}
void FindSourceParams(RGN* rgnptr, const RECTF* rect) {
if (CompareRects(rect, &rgnptr->foundparamsrect)) return;
rgnptr->foundparams.SetCount(0);
uint32_t sourceRects = rgnptr->source.Count();
uint32_t params = 0;
for (uint32_t i = 0; i < sourceRects; i++) {
if (!CheckForIntersection(rect, &rgnptr->source[i].rect)) continue;
int32_t sequence = rgnptr->source[i].sequence;
int32_t found = 0;
for (uint32_t j = 0; j < params; j++) {
if (rgnptr->foundparams[j].sequence == sequence) {
found = 1;
break;
}
}
if (!found) {
FOUNDPARAM* newParam = rgnptr->foundparams.New();
newParam->param = rgnptr->source[i].param;
newParam->sequence = sequence;
params++;
}
}
std::qsort(rgnptr->foundparams.Ptr(), rgnptr->foundparams.Count(), sizeof(FOUNDPARAM), SortFoundParamsCallback);
rgnptr->foundparamsrect = *rect;
}
void FragmentCombinedRectangles(TSGrowableArray<RECTF>* combinedArray, uint32_t firstIndex, uint32_t lastIndex, const RECTF* rect) { void FragmentCombinedRectangles(TSGrowableArray<RECTF>* combinedArray, uint32_t firstIndex, uint32_t lastIndex, const RECTF* rect) {
uint32_t index; uint32_t index;
RECTF* checkRect; RECTF* checkRect;
@ -249,8 +288,8 @@ void ProcessBooleanOperation(TSGrowableArray<SOURCE>* sourceArray, int32_t combi
} }
int SortRectCallback(const void* elem1, const void* elem2) { int SortRectCallback(const void* elem1, const void* elem2) {
RECTF* rct1 = (RECTF*)elem1; const RECTF* rct1 = static_cast<const RECTF*>(elem1);
RECTF* rct2 = (RECTF*)elem2; const RECTF* rct2 = static_cast<const RECTF*>(elem2);
double result = rct1->top == rct2->top ? rct1->left - rct2->left : rct1->top - rct2->top; double result = rct1->top == rct2->top ? rct1->left - rct2->left : rct1->top - rct2->top;
@ -272,7 +311,7 @@ void ProduceCombinedRectangles(RGN* rgn) {
CombineRectangles(&rgn->combined); CombineRectangles(&rgn->combined);
std::qsort(rgn->combined.Ptr(), rgn->combined.Count(), sizeof(rgn->combined.Ptr()[0]), SortRectCallback); std::qsort(rgn->combined.Ptr(), rgn->combined.Count(), sizeof(RECTF), SortRectCallback);
for (uint32_t i = rgn->combined.Count(); i > 0; i = rgn->combined.Count()) { for (uint32_t i = rgn->combined.Count(); i > 0; i = rgn->combined.Count()) {
if (!IsNullRect(&rgn->combined[i-1])) break; if (!IsNullRect(&rgn->combined[i-1])) break;
@ -347,17 +386,17 @@ void SRgnDelete(HSRGN handle) {
s_rgntable.Delete(handle); s_rgntable.Delete(handle);
} }
void SRgnDuplicate(HSRGN orighandle, HSRGN *handle, uint32_t reserved) { void SRgnDuplicate(HSRGN origHandle, HSRGN* handle, uint32_t reserved) {
STORM_VALIDATE_BEGIN; STORM_VALIDATE_BEGIN;
STORM_VALIDATE(handle); STORM_VALIDATE(handle);
*handle = nullptr; *handle = nullptr;
STORM_VALIDATE(orighandle); STORM_VALIDATE(origHandle);
STORM_VALIDATE(reserved == 0); STORM_VALIDATE(reserved == 0);
STORM_VALIDATE_END_VOID; STORM_VALIDATE_END_VOID;
HLOCKEDRGN origlockedhandle; HLOCKEDRGN origlockedhandle;
auto rgn = s_rgntable.Lock(orighandle, &origlockedhandle, 0); auto rgn = s_rgntable.Lock(origHandle, &origlockedhandle, 0);
if (rgn) { if (rgn) {
HLOCKEDRGN newlockedhandle; HLOCKEDRGN newlockedhandle;
@ -406,16 +445,57 @@ void SRgnGetBoundingRectf(HSRGN handle, RECTF* rect) {
} }
} }
void SRgnGetRectsf(HSRGN handle, uint32_t* numrects, RECTF* buffer) { void SRgnGetRectParamsf(HSRGN handle, RECTF* rect, uint32_t* numParams, void** buffer) {
STORM_VALIDATE_BEGIN; STORM_VALIDATE_BEGIN;
STORM_VALIDATE(handle); STORM_VALIDATE(handle);
STORM_VALIDATE(numrects); STORM_VALIDATE(rect);
STORM_VALIDATE(numParams);
STORM_VALIDATE_END_VOID;
if (IsNullRect(rect)) {
*numParams = 0;
return;
}
HLOCKEDRGN lockedHandle;
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
if (!rgn) {
*numParams = 0;
return;
}
if (rgn->dirty) {
ProduceCombinedRectangles(rgn);
rgn->dirty = 0;
}
FindSourceParams(rgn, rect);
if (buffer) {
*numParams = std::min(*numParams, rgn->foundparams.Count());
FOUNDPARAM* foundArray = rgn->foundparams.Ptr();
for (uint32_t i = 0; i < *numParams; i++) {
buffer[i] = foundArray[i].param;
}
}
else {
*numParams = rgn->foundparams.Count();
}
s_rgntable.Unlock(lockedHandle);
}
void SRgnGetRectsf(HSRGN handle, uint32_t* numRects, RECTF* buffer) {
STORM_VALIDATE_BEGIN;
STORM_VALIDATE(handle);
STORM_VALIDATE(numRects);
STORM_VALIDATE_END_VOID; STORM_VALIDATE_END_VOID;
HLOCKEDRGN lockedHandle; HLOCKEDRGN lockedHandle;
auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0); auto rgn = s_rgntable.Lock(handle, &lockedHandle, 0);
if (!rgn) { if (!rgn) {
*numrects = 0; *numRects = 0;
return; return;
} }
@ -425,11 +505,11 @@ void SRgnGetRectsf(HSRGN handle, uint32_t* numrects, RECTF* buffer) {
} }
if (buffer) { if (buffer) {
*numrects = std::min(*numrects, rgn->combined.Count()); *numRects = std::min(*numRects, rgn->combined.Count());
memcpy(buffer, rgn->combined.Ptr(), sizeof(rgn->combined.Ptr()[0]) * *numrects); memcpy(buffer, rgn->combined.Ptr(), sizeof(rgn->combined.Ptr()[0]) * *numRects);
} }
else { else {
*numrects = rgn->combined.Count(); *numRects = rgn->combined.Count();
} }
s_rgntable.Unlock(lockedHandle); s_rgntable.Unlock(lockedHandle);

View file

@ -12,10 +12,12 @@ void SRgnCreate(HSRGN* handlePtr, uint32_t reserved = 0);
void SRgnDelete(HSRGN handle); void SRgnDelete(HSRGN handle);
void SRgnDuplicate(HSRGN orighandle, HSRGN *handle, uint32_t reserved = 0); void SRgnDuplicate(HSRGN origHandle, HSRGN* handle, uint32_t reserved = 0);
void SRgnGetBoundingRectf(HSRGN handle, RECTF* rect); void SRgnGetBoundingRectf(HSRGN handle, RECTF* rect);
void SRgnGetRectsf(HSRGN handle, uint32_t* numrects, RECTF* buffer); void SRgnGetRectParamsf(HSRGN handle, RECTF* rect, uint32_t* numParams, void** buffer);
void SRgnGetRectsf(HSRGN handle, uint32_t* numRects, RECTF* buffer);
#endif #endif

View file

@ -143,6 +143,54 @@ TEST_CASE("SRgnDuplicate", "[region]") {
} }
} }
TEST_CASE("SRgnGetRectParamsf", "[region]") {
RgnDataTest region;
SECTION("retrieves empty list if nothing put in") {
uint32_t numParams = 1;
void* buffer[1];
RECTF rect = { 0, 0, 1, 1 };
SRgnGetRectParamsf(region, &rect, &numParams, buffer);
CHECK(numParams == 0);
}
SECTION("retrieves 0 when using an invalid region object") {
HSRGN inval = reinterpret_cast<HSRGN>(1234);
uint32_t numParams = 1;
RECTF rect = { 0, 0, 1, 1 };
SRgnGetRectParamsf(inval, &rect, &numParams, nullptr);
CHECK(numParams == 0);
}
SECTION("retrieves only overlapping params") {
RECTF rect1 = { 0, 0, 1, 1 };
RECTF rect2 = { 2, 2, 4, 4 };
RECTF rect3 = { 2.5, 2.5, 5, 5 };
RECTF queryRect = { 3, 3, 5, 5 };
int param1 = 5;
int param2 = 10;
int param3 = 11;
SRgnCombineRectf(region, &rect1, &param1, SRGN_PARAMONLY);
SRgnCombineRectf(region, &rect2, &param2, SRGN_PARAMONLY);
SRgnCombineRectf(region, &rect3, &param3, SRGN_PARAMONLY);
uint32_t numParams = 0;
SRgnGetRectParamsf(region, &queryRect, &numParams, nullptr);
REQUIRE(numParams == 2);
void* buffer[2];
SRgnGetRectParamsf(region, &queryRect, &numParams, buffer);
CHECK(numParams == 2);
CHECK(buffer[0] == &param2);
CHECK(buffer[1] == &param3);
}
}
TEST_CASE("SRgnGetRectsf", "[region]") { TEST_CASE("SRgnGetRectsf", "[region]") {
RgnDataTest region; RgnDataTest region;
@ -155,6 +203,15 @@ TEST_CASE("SRgnGetRectsf", "[region]") {
CHECK(numrects == 0); CHECK(numrects == 0);
} }
SECTION("retrieves 0 when using an invalid region object") {
HSRGN inval = reinterpret_cast<HSRGN>(1234);
uint32_t numrects = 1;
SRgnGetRectsf(inval, &numrects, nullptr);
CHECK(numrects == 0);
}
SECTION("retrieves all rects that were put in") { SECTION("retrieves all rects that were put in") {
RECTF rct1 = { 5, 5, 10, 10 }; RECTF rct1 = { 5, 5, 10, 10 };
RECTF rct2 = { 0, 0, 1, 1 }; RECTF rct2 = { 0, 0, 1, 1 };