Files
banan-os/userspace/programs/WindowServer/Utils.h
Bananymous 4bde088b28 WindowServer: Store rectangles as min and max bounds
This makes some math easier than x,y and w,h
2026-04-11 06:35:45 +03:00

127 lines
2.5 KiB
C

#pragma once
#include <BAN/Math.h>
#include <BAN/Optional.h>
#include <stdint.h>
struct Position
{
int32_t x;
int32_t y;
};
struct Rectangle
{
int32_t min_x;
int32_t min_y;
int32_t max_x;
int32_t max_y;
int32_t width() const
{
return max_x - min_x;
}
int32_t height() const
{
return max_y - min_y;
}
int32_t area() const
{
return width() * height();
}
bool contains(Position position) const
{
if (position.x < min_x || position.x >= max_x)
return false;
if (position.y < min_y || position.y >= max_y)
return false;
return true;
}
BAN::Optional<Rectangle> get_overlap(Rectangle other) const
{
if (width() == 0 || height() == 0 || other.width() == 0 || other.height() == 0)
return {};
const auto min_x = BAN::Math::max(this->min_x, other.min_x);
const auto min_y = BAN::Math::max(this->min_y, other.min_y);
const auto max_x = BAN::Math::min(this->max_x, other.max_x);
const auto max_y = BAN::Math::min(this->max_y, other.max_y);
if (min_x >= max_x || min_y >= max_y)
return {};
return Rectangle {
.min_x = min_x,
.min_y = min_y,
.max_x = max_x,
.max_y = max_y,
};
}
Rectangle get_bounding_box(Rectangle other) const
{
const auto min_x = BAN::Math::min(this->min_x, other.min_x);
const auto min_y = BAN::Math::min(this->min_y, other.min_y);
const auto max_x = BAN::Math::max(this->max_x, other.max_x);
const auto max_y = BAN::Math::max(this->max_y, other.max_y);
return Rectangle {
.min_x = min_x,
.min_y = min_y,
.max_x = max_x,
.max_y = max_y,
};
}
bool operator==(const Rectangle& other) const
{
return min_x == other.min_x && min_y == other.min_y && max_x == other.max_x && max_y == other.max_y;
}
};
struct Circle
{
int32_t x;
int32_t y;
int32_t radius;
bool contains(Position position) const
{
int32_t dx = position.x - x;
int32_t dy = position.y - y;
return dx * dx + dy * dy <= radius * radius;
}
};
struct Range
{
uint32_t start { 0 };
uint32_t count { 0 };
bool is_continuous_with(const Range& range) const
{
return start <= range.start + range.count && range.start <= start + count;
}
uint32_t distance_between(const Range& range) const
{
if (is_continuous_with(range))
return 0;
if (start < range.start)
return range.start - (start + count);
return start - (range.start + range.count);
}
void merge_with(const Range& range)
{
const uint32_t new_start = BAN::Math::min(start, range.start);
const uint32_t new_end = BAN::Math::max(start + count, range.start + range.count);
start = new_start;
count = new_end - new_start;
}
};