mirror of
https://github.com/thunderbrewhq/squall.git
synced 2026-02-04 00:49:08 +00:00
feat(region): write several tests and finish SRgn functionality
This commit is contained in:
parent
e7d8124b43
commit
8d86943c94
3 changed files with 401 additions and 41 deletions
117
storm/Region.cpp
117
storm/Region.cpp
|
|
@ -11,6 +11,7 @@ static TSExportTableSyncReuse<RGN, HSRGN, HLOCKEDRGN, CCritSect> s_rgntable;
|
|||
|
||||
void DeleteCombinedRect(TSGrowableArray<RECTF>* combinedArray, uint32_t index);
|
||||
void DeleteRect(RECTF* rect);
|
||||
void DeleteSourceRect(TSGrowableArray<SOURCE>* sourceArray, uint32_t index);
|
||||
int32_t IsNullRect(const RECTF* rect);
|
||||
|
||||
|
||||
|
|
@ -184,32 +185,104 @@ void FragmentCombinedRectangles(TSGrowableArray<RECTF>* combinedArray, uint32_t
|
|||
}
|
||||
|
||||
void FragmentSourceRectangles(TSGrowableArray<SOURCE>* sourceArray, uint32_t firstIndex, uint32_t lastIndex, int32_t previousOverlap, const RECTF* rect, void* param, int32_t sequence) {
|
||||
if (firstIndex >= lastIndex) {
|
||||
AddSourceRect(sourceArray, rect, param, sequence, SF_ADDING | (previousOverlap ? SF_OVERLAPS : SF_NONE));
|
||||
return;
|
||||
}
|
||||
|
||||
auto overlapsExisting = previousOverlap;
|
||||
|
||||
for (uint32_t i = firstIndex; i < lastIndex; i++) {
|
||||
auto source = &(*sourceArray)[i];
|
||||
for (uint32_t index = firstIndex; index < lastIndex; index++) {
|
||||
RECTF* checkRect = &(*sourceArray)[index].rect;
|
||||
|
||||
if (CheckForIntersection(rect, &source->rect)) {
|
||||
if (!CompareRects(rect, &source->rect)) {
|
||||
break;
|
||||
}
|
||||
|
||||
source->flags |= SF_OVERLAPS;
|
||||
if (CheckForIntersection(rect, checkRect)) {
|
||||
if (CompareRects(rect, checkRect)) {
|
||||
(*sourceArray)[index].flags |= SF_OVERLAPS;
|
||||
overlapsExisting = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i + 1 == lastIndex) {
|
||||
AddSourceRect(sourceArray, rect, param, sequence, SF_ADDING | (previousOverlap ? SF_OVERLAPS : SF_NONE));
|
||||
const RECTF* overlapRect[2] = { rect, checkRect };
|
||||
|
||||
uint32_t minLeft = rect->left > checkRect->left ? 1 : 0;
|
||||
uint32_t maxLeft = checkRect->left > rect->left ? 1 : 0;
|
||||
uint32_t minBottom = rect->bottom > checkRect->bottom ? 1 : 0;
|
||||
uint32_t maxBottom = checkRect->bottom > rect->bottom ? 1 : 0;
|
||||
uint32_t minRight = rect->right > checkRect->right ? 1 : 0;
|
||||
uint32_t maxRight = checkRect->right > rect->right ? 1 : 0;
|
||||
uint32_t minTop = rect->top > checkRect->top ? 1 : 0;
|
||||
uint32_t maxTop = checkRect->top > rect->top ? 1 : 0;
|
||||
|
||||
RECTF newRect[5];
|
||||
|
||||
newRect[0] = {
|
||||
overlapRect[minBottom]->left,
|
||||
overlapRect[minBottom]->bottom,
|
||||
overlapRect[minBottom]->right,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
};
|
||||
|
||||
newRect[1] = {
|
||||
overlapRect[maxTop]->left,
|
||||
overlapRect[minTop]->top,
|
||||
overlapRect[maxTop]->right,
|
||||
overlapRect[maxTop]->top,
|
||||
};
|
||||
|
||||
newRect[2] = {
|
||||
overlapRect[minLeft]->left,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
overlapRect[maxLeft]->left,
|
||||
overlapRect[minTop]->top,
|
||||
};
|
||||
|
||||
newRect[3] = {
|
||||
overlapRect[minRight]->right,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
overlapRect[maxRight]->right,
|
||||
overlapRect[minTop]->top,
|
||||
};
|
||||
|
||||
newRect[4] = {
|
||||
overlapRect[maxLeft]->left,
|
||||
overlapRect[maxBottom]->bottom,
|
||||
overlapRect[minRight]->right,
|
||||
overlapRect[minTop]->top,
|
||||
};
|
||||
|
||||
int32_t overlaps[5][2];
|
||||
for (uint32_t j = 0; j < 5; j++) {
|
||||
if (IsNullRect(&newRect[j])) {
|
||||
overlaps[j][1] = 0;
|
||||
overlaps[j][0] = 0;
|
||||
}
|
||||
else {
|
||||
for (uint32_t k = 0; k < 2; k++) {
|
||||
overlaps[j][k] = CheckForIntersection(&newRect[j], overlapRect[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < 5; j++) {
|
||||
if (overlaps[j][0]) {
|
||||
FragmentSourceRectangles(
|
||||
sourceArray,
|
||||
index + 1,
|
||||
lastIndex,
|
||||
overlapsExisting || overlaps[j][1],
|
||||
&newRect[j],
|
||||
param,
|
||||
sequence);
|
||||
}
|
||||
|
||||
if (overlaps[j][1]) {
|
||||
uint32_t newFlags = (*sourceArray)[index].flags & ~SF_TEMPMASK;
|
||||
newFlags |= overlaps[j][0] ? SF_OVERLAPS : SF_NONE;
|
||||
|
||||
AddSourceRect(sourceArray, &newRect[j], (*sourceArray)[index].param, (*sourceArray)[index].sequence, newFlags);
|
||||
}
|
||||
}
|
||||
DeleteSourceRect(sourceArray, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
AddSourceRect(sourceArray, rect, param, sequence, SF_ADDING | (overlapsExisting ? SF_OVERLAPS : SF_NONE));
|
||||
}
|
||||
|
||||
int32_t IsNullRect(const RECTF* rect) {
|
||||
|
|
@ -242,20 +315,20 @@ void DeleteSourceRect(TSGrowableArray<SOURCE>* sourceArray, uint32_t index) {
|
|||
}
|
||||
|
||||
void OptimizeSource(TSGrowableArray<SOURCE>* sourceArray) {
|
||||
for (uint32_t i = 0; i < sourceArray->Count(); i++) {
|
||||
auto source = &(*sourceArray)[i];
|
||||
for (uint32_t index = 0; index < sourceArray->Count(); ) {
|
||||
auto source = &(*sourceArray)[index];
|
||||
|
||||
if (IsNullRect(&source->rect)) {
|
||||
// Set current (null) element to last element
|
||||
auto last = &(*sourceArray)[sourceArray->Count() - 1];
|
||||
(*sourceArray)[i] = *last;
|
||||
|
||||
// Decrement index by 1 to force null check on copied last element on next tick
|
||||
i--;
|
||||
(*sourceArray)[index] = *last;
|
||||
|
||||
// Shrink by 1 (to account for the removal of the null element)
|
||||
sourceArray->SetCount(sourceArray->Count() - 1);
|
||||
}
|
||||
else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <cstdint>
|
||||
|
||||
// region flgs
|
||||
#define SF_NONE 0x00
|
||||
#define SF_NONE 0x00000000
|
||||
#define SF_ADDING 0x00000001
|
||||
#define SF_OVERLAPS 0x00000002
|
||||
#define SF_TEMPMASK 0x00000003
|
||||
|
|
|
|||
323
test/Region.cpp
323
test/Region.cpp
|
|
@ -1,10 +1,13 @@
|
|||
#include "RegionTest.hpp"
|
||||
|
||||
// Note: diagrams are y inverted when building for WoW,
|
||||
// still conveys understanding.
|
||||
|
||||
TEST_CASE("SRgnClear", "[region]") {
|
||||
RgnDataTest region;
|
||||
|
||||
SECTION("operates on an empty object") {
|
||||
uint32_t numrects = 0;
|
||||
uint32_t numrects = 1;
|
||||
|
||||
SRgnClear(region);
|
||||
|
||||
|
|
@ -12,6 +15,11 @@ TEST_CASE("SRgnClear", "[region]") {
|
|||
CHECK(numrects == 0);
|
||||
}
|
||||
|
||||
SECTION("runs on an invalid pointer") {
|
||||
HSRGN inval = reinterpret_cast<HSRGN>(1234);
|
||||
CHECK_NOTHROW(SRgnClear(inval));
|
||||
}
|
||||
|
||||
SECTION("clears rects out of a region object") {
|
||||
uint32_t numrects = 0;
|
||||
|
||||
|
|
@ -26,6 +34,23 @@ TEST_CASE("SRgnClear", "[region]") {
|
|||
SRgnGetRectsf(region, &numrects, nullptr);
|
||||
CHECK(numrects == 0);
|
||||
}
|
||||
|
||||
SECTION("clears params out of a region object") {
|
||||
uint32_t numParams = 1;
|
||||
void* params[1];
|
||||
|
||||
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &baseRect, &baseRect, SRGN_PARAMONLY);
|
||||
|
||||
SRgnGetRectParamsf(region, &baseRect, &numParams, params);
|
||||
CHECK(numParams == 1);
|
||||
|
||||
SRgnClear(region);
|
||||
|
||||
SRgnGetRectParamsf(region, &baseRect, &numParams, params);
|
||||
CHECK(numParams == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SRgnCreate", "[region]") {
|
||||
|
|
@ -41,9 +66,10 @@ TEST_CASE("SRgnCreate", "[region]") {
|
|||
|
||||
TEST_CASE("SRgnCombineRectf", "[region]") {
|
||||
RgnDataTest region;
|
||||
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
RECTF testRect = { 0.5f, 0.6f, 1.8f, 1.4f };
|
||||
|
||||
SECTION("combines the region with a single given rect 1") {
|
||||
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
RECTF boundingRect = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
|
@ -53,7 +79,6 @@ TEST_CASE("SRgnCombineRectf", "[region]") {
|
|||
}
|
||||
|
||||
SECTION("combines the region with multiple given rects 1") {
|
||||
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
RECTF newRect = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
|
@ -66,7 +91,6 @@ TEST_CASE("SRgnCombineRectf", "[region]") {
|
|||
}
|
||||
|
||||
SECTION("combines the region with multiple given rects 2") {
|
||||
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
RECTF newRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
|
|
@ -79,7 +103,6 @@ TEST_CASE("SRgnCombineRectf", "[region]") {
|
|||
}
|
||||
|
||||
SECTION("combines the region with multiple given rects 3") {
|
||||
RECTF baseRect = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
RECTF newRect = { 0.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
|
@ -90,6 +113,202 @@ TEST_CASE("SRgnCombineRectf", "[region]") {
|
|||
|
||||
CHECK_THAT(boundingRect, MatchesRect({ 0.0f, 0.0f, 1.0f, 1.0f }));
|
||||
}
|
||||
|
||||
SECTION("OR operation combines rects") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &testRect, nullptr, SRGN_OR);
|
||||
|
||||
uint32_t numRects = 4;
|
||||
RECTF buffer[4];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
// ┌─────────┐
|
||||
// │ 0 │
|
||||
// │┈┈┈┈┌────┼──────┐
|
||||
// │ 1 │
|
||||
// └────┼────┘┈┈┈┈┈┈│
|
||||
// │ 2 │
|
||||
// └───────────┘
|
||||
CHECK(numRects == 3);
|
||||
CHECK_THAT(buffer[0], MatchesRect({ 0.0f, 0.0f, 1.0f, 0.6f }));
|
||||
CHECK_THAT(buffer[1], MatchesRect({ 0.0f, 0.6f, 1.8f, 1.0f }));
|
||||
CHECK_THAT(buffer[2], MatchesRect({ 0.5f, 1.0f, 1.8f, 1.4f }));
|
||||
}
|
||||
|
||||
SECTION("AND operation intersects rects") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &testRect, nullptr, SRGN_AND);
|
||||
|
||||
uint32_t numRects = 2;
|
||||
RECTF buffer[2];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
// ┌─────────┐
|
||||
// │╳╳╳╳╳╳╳╳╳│
|
||||
// │╳╳╳╳┌────┼──────┐
|
||||
// │╳╳╳╳│ 0 │╳╳╳╳╳╳│
|
||||
// └────┼────┘╳╳╳╳╳╳│
|
||||
// │╳╳╳╳╳╳╳╳╳╳╳│
|
||||
// └───────────┘
|
||||
CHECK(numRects == 1);
|
||||
CHECK_THAT(buffer[0], MatchesRect({ 0.5f, 0.6f, 1.0f, 1.0f }));
|
||||
}
|
||||
|
||||
SECTION("XOR operation takes exclusive differences of rects") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &testRect, nullptr, SRGN_XOR);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
// ┌─────────┐
|
||||
// │ 0 │
|
||||
// │┈┈┈┈┌────┼──────┐
|
||||
// │ 1 │╳╳╳╳│ 2 │
|
||||
// └────┼────┘┈┈┈┈┈┈│
|
||||
// │ 3 │
|
||||
// └───────────┘
|
||||
CHECK(numRects == 4);
|
||||
CHECK_THAT(buffer[0], MatchesRect({ 0.0f, 0.0f, 1.0f, 0.6f }));
|
||||
CHECK_THAT(buffer[1], MatchesRect({ 0.0f, 0.6f, 0.5f, 1.0f }));
|
||||
CHECK_THAT(buffer[2], MatchesRect({ 1.0f, 0.6f, 1.8f, 1.0f }));
|
||||
CHECK_THAT(buffer[3], MatchesRect({ 0.5f, 1.0f, 1.8f, 1.4f }));
|
||||
}
|
||||
|
||||
SECTION("DIFF operation removes parts of rects") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &testRect, nullptr, SRGN_DIFF);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
// ┌─────────┐
|
||||
// │ 0 │
|
||||
// │┈┈┈┈┌────┼──────┐
|
||||
// │ 1 │╳╳╳╳│╳╳╳╳╳╳│
|
||||
// └────┼────┘╳╳╳╳╳╳│
|
||||
// │╳╳╳╳╳╳╳╳╳╳╳│
|
||||
// └───────────┘
|
||||
CHECK(numRects == 2);
|
||||
CHECK_THAT(buffer[0], MatchesRect({ 0.0f, 0.0f, 1.0f, 0.6f }));
|
||||
CHECK_THAT(buffer[1], MatchesRect({ 0.0f, 0.6f, 0.5f, 1.0f }));
|
||||
}
|
||||
|
||||
SECTION("COPY operation splits intersecting rects") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &testRect, nullptr, SRGN_COPY);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
// ┌─────────┐
|
||||
// │ 0 │
|
||||
// │┈┈┈┈┌────┼──────┐
|
||||
// │ 1 │╳╳╳╳╳╳│
|
||||
// └────┼────┘╳╳╳╳╳╳│
|
||||
// │╳╳╳╳╳╳╳╳╳╳╳│
|
||||
// └───────────┘
|
||||
CHECK(numRects == 2);
|
||||
CHECK_THAT(buffer[0], MatchesRect({ 0.0f, 0.0f, 1.0f, 0.6f }));
|
||||
CHECK_THAT(buffer[1], MatchesRect({ 0.0f, 0.6f, 1.0f, 1.0f }));
|
||||
}
|
||||
|
||||
SECTION("COPY operation splits intersecting rects 2") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
RECTF testRect2 = { 0.4f, 0.4f, 0.6f, 0.6f };
|
||||
SRgnCombineRectf(region, &testRect2, nullptr, SRGN_COPY);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
// ┌─────────┐
|
||||
// │ 0 │
|
||||
// │┈┈┈┌┈┐┈┈┈│
|
||||
// │┈┈┈└┈┘┈1┈│
|
||||
// │ 2 │
|
||||
// └─────────┘
|
||||
CHECK(numRects == 3);
|
||||
CHECK_THAT(buffer[0], MatchesRect({ 0.0f, 0.0f, 1.0f, 0.4f }));
|
||||
CHECK_THAT(buffer[1], MatchesRect({ 0.0f, 0.4f, 1.0f, 0.6f }));
|
||||
CHECK_THAT(buffer[2], MatchesRect({ 0.0f, 0.6f, 1.0f, 1.0f }));
|
||||
}
|
||||
|
||||
SECTION("operation doesn't work when operating rect width or height is <= 0") {
|
||||
int32_t combineMode = GENERATE(SRGN_OR, SRGN_XOR, SRGN_DIFF, SRGN_COPY, SRGN_PARAMONLY);
|
||||
RECTF testRects = GENERATE(
|
||||
RECTF{ 0.5f, 0.0f, 0.5f, 1.0f },
|
||||
RECTF{ 0.0f, 0.5f, 1.0f, 0.5f },
|
||||
RECTF{ 1.0f, 0.0f, 0.5f, 1.0f },
|
||||
RECTF{ 0.0f, 1.0f, 1.0f, 0.5f }
|
||||
);
|
||||
|
||||
INFO("CombineMode = " << combineMode);
|
||||
INFO("testRects = " << testRects);
|
||||
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
|
||||
SRgnCombineRectf(region, &testRects, &testRects, combineMode);
|
||||
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
CHECK(numRects == 1);
|
||||
CHECK_THAT(buffer[0], MatchesRect(baseRect));
|
||||
|
||||
uint32_t numParams = 1;
|
||||
SRgnGetRectParamsf(region, &testRects, &numParams, nullptr);
|
||||
CHECK(numParams == 0);
|
||||
|
||||
SRgnGetRectParamsf(region, &baseRect, &numParams, nullptr);
|
||||
CHECK(numParams == 1);
|
||||
}
|
||||
|
||||
SECTION("AND kills all rects when rect width or height is <= 0") {
|
||||
int32_t combineMode = SRGN_AND;
|
||||
RECTF testRects = GENERATE(
|
||||
RECTF{ 0.5f, 0.0f, 0.5f, 1.0f },
|
||||
RECTF{ 0.0f, 0.5f, 1.0f, 0.5f },
|
||||
RECTF{ 1.0f, 0.0f, 0.5f, 1.0f },
|
||||
RECTF{ 0.0f, 1.0f, 1.0f, 0.5f }
|
||||
);
|
||||
|
||||
INFO("CombineMode = " << combineMode);
|
||||
INFO("testRects = " << testRects);
|
||||
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
|
||||
SRgnCombineRectf(region, &testRects, &testRects, combineMode);
|
||||
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
CHECK(numRects == 0);
|
||||
|
||||
uint32_t numParams = 1;
|
||||
SRgnGetRectParamsf(region, &testRects, &numParams, nullptr);
|
||||
CHECK(numParams == 0);
|
||||
|
||||
SRgnGetRectParamsf(region, &baseRect, &numParams, nullptr);
|
||||
CHECK(numParams == 0);
|
||||
}
|
||||
|
||||
SECTION("PARAM operation doesn't influence rects") {
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
SRgnCombineRectf(region, &testRect, nullptr, SRGN_PARAMONLY);
|
||||
|
||||
uint32_t numRects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
CHECK(numRects == 1);
|
||||
CHECK_THAT(buffer[0], MatchesRect(baseRect));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SRgnDelete", "[region]") {
|
||||
|
|
@ -114,9 +333,9 @@ TEST_CASE("SRgnDelete", "[region]") {
|
|||
|
||||
TEST_CASE("SRgnDuplicate", "[region]") {
|
||||
RgnDataTest region;
|
||||
RECTF baseRect = { -1.0f, 1.0f, 1.0f, 2.0f };
|
||||
|
||||
SECTION("creates an independent copy of a region") {
|
||||
RECTF baseRect = { -1.0f, 1.0f, 1.0f, 2.0f };
|
||||
SRgnCombineRectf(region, &baseRect, nullptr, SRGN_OR);
|
||||
|
||||
HSRGN newrgn = nullptr;
|
||||
|
|
@ -133,6 +352,28 @@ TEST_CASE("SRgnDuplicate", "[region]") {
|
|||
CHECK_THAT(buffer[0], MatchesRect(baseRect));
|
||||
}
|
||||
|
||||
SECTION("copies parms") {
|
||||
SRgnCombineRectf(region, &baseRect, &baseRect, SRGN_PARAMONLY);
|
||||
|
||||
uint32_t numParams = 2;
|
||||
void* buffer[2];
|
||||
SRgnGetRectParamsf(region, &baseRect, &numParams, buffer);
|
||||
|
||||
CHECK(numParams == 1);
|
||||
CHECK(buffer[0] == &baseRect);
|
||||
|
||||
HSRGN newrgn = nullptr;
|
||||
SRgnDuplicate(region, &newrgn);
|
||||
|
||||
REQUIRE(newrgn != nullptr);
|
||||
SRgnClear(region);
|
||||
|
||||
SRgnGetRectParamsf(newrgn, &baseRect, &numParams, buffer);
|
||||
|
||||
CHECK(numParams == 1);
|
||||
CHECK(buffer[0] == &baseRect);
|
||||
}
|
||||
|
||||
SECTION("sets handle to null when using an invalid region object") {
|
||||
HSRGN inval = reinterpret_cast<HSRGN>(1234);
|
||||
|
||||
|
|
@ -244,6 +485,52 @@ TEST_CASE("SRgnGetRectsf", "[region]") {
|
|||
|
||||
CHECK_THAT(buffer[0], MatchesRect(rct1));
|
||||
}
|
||||
|
||||
SECTION("retrieves rects in order of top value") {
|
||||
RECTF rects[4] = {
|
||||
{ 0, 0, 1, 1 },
|
||||
{ 4, -2, 5, 5 },
|
||||
{ -2, 2, -1, 3 },
|
||||
{ 2, -2, 3, -1 },
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
SRgnCombineRectf(region, &rects[i], nullptr, SRGN_OR);
|
||||
}
|
||||
|
||||
uint32_t numrects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numrects, buffer);
|
||||
|
||||
CHECK(numrects == 4);
|
||||
CHECK_THAT(buffer[0], MatchesRect(rects[3]));
|
||||
CHECK_THAT(buffer[1], MatchesRect(rects[0]));
|
||||
CHECK_THAT(buffer[2], MatchesRect(rects[2]));
|
||||
CHECK_THAT(buffer[3], MatchesRect(rects[1]));
|
||||
}
|
||||
|
||||
SECTION("retrieves rects in order of left value when tops are equal") {
|
||||
RECTF rects[4] = {
|
||||
{ 0, 0, 1, 1 },
|
||||
{ 4, 0.5, 5, 1 },
|
||||
{ -2, -2, -1, 1 },
|
||||
{ 2, -1, 3, 1 },
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
SRgnCombineRectf(region, &rects[i], nullptr, SRGN_OR);
|
||||
}
|
||||
|
||||
uint32_t numrects = 5;
|
||||
RECTF buffer[5];
|
||||
SRgnGetRectsf(region, &numrects, buffer);
|
||||
|
||||
CHECK(numrects == 4);
|
||||
CHECK_THAT(buffer[0], MatchesRect(rects[2]));
|
||||
CHECK_THAT(buffer[1], MatchesRect(rects[0]));
|
||||
CHECK_THAT(buffer[2], MatchesRect(rects[3]));
|
||||
CHECK_THAT(buffer[3], MatchesRect(rects[1]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SRgnIsPointInRegionf", "[region]") {
|
||||
|
|
@ -311,7 +598,7 @@ TEST_CASE("SRgnIsRectInRegionf", "[region]") {
|
|||
CHECK_FALSE(SRgnIsRectInRegionf(inval, &rect));
|
||||
}
|
||||
|
||||
SECTION("reports if rects overlap a region") {
|
||||
SECTION("true if rects overlap a region") {
|
||||
RECTF checkRects[] = {
|
||||
{ 0.5f, 0.5f, 0.5f, 0.5f },
|
||||
{ 0.00001f, 0.00001f, 0.999999f, 0.999999f },
|
||||
|
|
@ -331,7 +618,7 @@ TEST_CASE("SRgnIsRectInRegionf", "[region]") {
|
|||
CHECK(SRgnIsRectInRegionf(region, &checkRects[4]));
|
||||
}
|
||||
|
||||
SECTION("reports if rects are outside a region") {
|
||||
SECTION("false if rects are outside a region") {
|
||||
RECTF checkRects[] = {
|
||||
{ 2.0f, 2.0f, 2.0f, 2.0f },
|
||||
{ 1.0f, 1.0f, 2.0f, 2.0f },
|
||||
|
|
@ -379,8 +666,8 @@ TEST_CASE("SRgnOffsetf", "[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 }
|
||||
{ -200.0f, -200.0f, -100.0f, -100.0f },
|
||||
{ 0.0f, 0.0f, 100.0f, 100.0f }
|
||||
};
|
||||
|
||||
SRgnCombineRectf(region, &rects[0], nullptr, SRGN_OR);
|
||||
|
|
@ -398,8 +685,8 @@ TEST_CASE("SRgnOffsetf", "[region]") {
|
|||
|
||||
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 }
|
||||
{ -200.0f, -200.0f, -100.0f, -100.0f },
|
||||
{ 0.0f, 0.0f, 100.0f, 100.0f }
|
||||
};
|
||||
|
||||
SRgnCombineRectf(region, &rects[0], nullptr, SRGN_OR);
|
||||
|
|
@ -413,14 +700,14 @@ TEST_CASE("SRgnOffsetf", "[region]") {
|
|||
RECTF buffer[2];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
CHECK_THAT(buffer[0], MatchesRect(rects[1]));
|
||||
CHECK_THAT(buffer[1], MatchesRect(rects[0]));
|
||||
CHECK_THAT(buffer[0], MatchesRect(rects[0]));
|
||||
CHECK_THAT(buffer[1], MatchesRect(rects[1]));
|
||||
}
|
||||
|
||||
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 }
|
||||
{ -200.0f, -200.0f, -100.0f, -100.0f },
|
||||
{ 0.0f, 0.0f, 100.0f, 100.0f }
|
||||
};
|
||||
|
||||
SRgnCombineRectf(region, &rects[0], nullptr, SRGN_OR);
|
||||
|
|
@ -432,7 +719,7 @@ TEST_CASE("SRgnOffsetf", "[region]") {
|
|||
RECTF buffer[2];
|
||||
SRgnGetRectsf(region, &numRects, buffer);
|
||||
|
||||
CHECK_THAT(buffer[0], MatchesRect(rects[1]));
|
||||
CHECK_THAT(buffer[1], MatchesRect(rects[0]));
|
||||
CHECK_THAT(buffer[0], MatchesRect(rects[0]));
|
||||
CHECK_THAT(buffer[1], MatchesRect(rects[1]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue