Just stuff about Preprocessor
ON Feb 23 2016
I WROTE ABOUT
, , ,

This is just some basic rectangle macros using the C preprocessor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifndef RECT_INCLUDED
#define RECT_INCLUDED

#define MAX(X,Y) ( (X) > (Y) ? (X) : (Y) )
#define MIN(X,Y) ( (X) < (Y) ? (X) : (Y) )

#define RECT(T) struct { T x; T y; T w; T h; }
typedef RECT(int)       rect_int_t;
typedef RECT(unsigned)  rect_uint_t;
typedef RECT(float)     rect_float_t;
typedef RECT(double)    rect_double_t;

#define RECT_AREA(r1)           ( (r1).w * (r1).h )
#define RECT_PERIMETER(r1)      ( ((r1).w * 2) + ((r1).h * 2) )
#define RECT_ISEMPTY(r1)        ( (r1).w <= 0 || (r1).h <= 0 ? 1 : 0 )

#define RECT_NOCONTACT(r1, r2) \
    (  (r1).x > (r2).x + (r2).w || (r1).y > (r2).y + (r2).h \
    || (r2).x > (r1).x + (r1).w || (r2).y > (r1).y + (r1).h )

#define RECT_EQUALS(r1, r2) \
    (  (r1).x == (r2).x && (r1).y == (r2).y \
    && (r1).w == (r2).w && (r1).h == (r2).h )

#define RECT_CONTAINS(r1, r2) \
    (  (r1).x < (r2).x && ((r1).x + (r1).w) > ((r2).x + (r2).w) \
    && (r1).y < (r2).y && ((r1).y + (r1).h) > ((r2).y + (r2).h) )

#define RECT_INTERSECTS(r1, r2) \
    (  (r1).x < (r2).x + (r2).w && (r2).x < (r1).x + (r1).w \
    && (r1).y < (r2).y + (r2).h && (r2).y < (r1).y + (r1).h )

#define RECT_CONTAINSPOINT(r1, px, py) \
    (  px >= (r1).x && px < (r1).x + (r1).w \
    && py >= (r1).y && py < (r1).y + (r1).h )

#define RECT_FIXNEGATIVE(r1) \
    { .x = (r1).w < 0 ? (r1).x + (r1).w : (r1).x, \
      .y = (r1).h < 0 ? (r1).y + (r1).h : (r1).y, \
      .w = (r1).w < 0 ? -((r1).w) : (r1).w, \
      .h = (r1).h < 0 ? -((r1).h) : (r1).h }

#define RECT_TRANSLATE(r1, tx, ty) \
    { .x = (r1).x + (tx), .y = (r1).y + (ty), .w = (r1).w, .h = (r1).h }

#define RECT_INTERSECTION(r1, r2) \
    { .x = MAX((r1).x, (r2).x), \
      .y = MAX((r1).y, (r2).y), \
      .w = (r1).x < (r2).x ? MIN((r2).w, ((r1).x + (r1).w - (r2).x)) \
                           : MIN((r1).w, ((r2).x + (r2).w - (r1).x)), \
      .h = (r1).y < (r2).y ? MIN((r2).h, ((r1).y + (r1).h - (r2).y)) \
                           : MIN((r1).h, ((r2).y + (r2).h - (r1).y)) }

#define RECT_INSET(r1, left, top, right, bottom) \
    { .x = (r1).x + left, \
      .y = (r1).y + top, \
      .w = (r1).w - left - right, \
      .h = (r1).h - top - bottom }

#define RECT_BOUND(r1, r2) \
    { .x = MIN((r1).x, (r2).x), \
      .y = MIN((r1).y, (r2).y), \
      .w = MAX(((r1).x + (r1).w), ((r2).x + (r2).w)) - MIN((r1).x, (r2).x), \
      .h = MAX(((r1).y + (r1).h), ((r2).y + (r2).h)) - MIN((r1).y, (r2).y) }

#endif

This is cool because it allows easy, inline conversion between rects of different types, and offloads the burden of verifying compatibility, warning about dangerous conversions, etc. onto the compiler.