karlos/include/rect.h

66 lines
2.2 KiB
C

#ifndef KARLOS_RECT_H
#define KARLOS_RECT_H
#include <stdbool.h>
struct rect {
int x, y, xend, yend;
};
#define RECT_XYWH(x, y, w, h) (struct rect){ (x), (y), (x + w), (y + h) }
#define RECT_WIDTH(r) ((r).xend - (r).x)
#define RECT_HEIGHT(r) ((r).yend - (r).y)
#define RECT_XEND(r) ((r).xend)
#define RECT_YEND(r) ((r).yend)
// Moves `rect`.
void rect_translate(struct rect *rect, int delta_x, int delta_y);
void rect_translate_to(struct rect *rect, int new_x, int new_y);
// Clamps the rectangle `rect` to `boundary`.
// The rect is cut off at the edges of `boundary`.
void rect_clamp(struct rect *rect, const struct rect *boundary);
// Grows `rect` so that it encompasses both its original dimensions and `additional`.
void rect_union(struct rect *rect, const struct rect *additional);
// Grows (positive values) or shrinks (negative values) rect at specific sides.
#define RECT_RESIZE(rct, l, r, u, d) ((struct rect) { \
.x = (rct).x - l, \
.y = (rct).y - u, \
.xend = (rct).xend + r, \
.yend = (rct).yend + d, \
})
#define RECT_RESIZE_ALL(rct, val) RECT_RESIZE(rct, val, val, val, val)
// Rectangle is moved to lie inside the surrounding rect.
// It is also clamped to the surrounding rect.
// `rect` may be `NULL`, in which case it describes the entire `surrounding` rect.
// `surrounding` may not be `NULL`;
//
// Example:
// struct rect rect = RECT_XYWH(5, 10, 100, 100);
// struct rect surrounding = RECT_XYWH(200, 200, 50, 500);
// struct rect result = rect_local_to_global(&rect, &surrounding);
// ASSERT(result.x == 205 && result.y == 210);
// ASSERT(RECT_WIDTH(result) == 45 && RECT_HEIGHT(result) == 100);
struct rect rect_local_to_global(const struct rect *rect, const struct rect *surrounding);
#define RECT_EMPTY RECT_XYWH(0, 0, 0, 0)
#define RECT_IS_DEGENERATE(r) ((r).x > (r).xend || (r).y > (r).yend)
#define RECT_IS_EMPTY(r) ((r).x >= (r).xend || (r).y >= (r).yend)
#define RECT_AREA(r) (RECT_IS_EMPTY(r) ? 0 : (unsigned)((r).xend - (r).x) * ((r).yend - (r).y))
#define RECT_EQUAL(a, b) \
(a).x == (b).x \
&& (a).y == (b).y \
&& (a).xend == (b).xend \
&& (a).yend == (b).yend \
#define RECT_CONTAINS(r, vx, vy) \
((vx) >= (r).x && (vy) >= (r).y \
&& (vx) < RECT_XEND(r) && (vy) < RECT_YEND(r))
#endif