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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "util.h"
#include "any_log.h"
void pair_copy(pair_t *copy, const pair_t *pair)
{
copy->key = strcopy(pair->key);
copy->value = strcopy(pair->value);
}
void pair_free(pair_t *pair)
{
free(pair->key);
free(pair->value);
}
char *color_to_string(color_t *color)
{
unsigned int r = color->r * 255,
g = color->g * 255,
b = color->b * 255,
a = color->a * 255;
char buffer[32];
int n = snprintf(buffer, 32, "#%02x%02x%02x%02x", r, g, b, a);
return strslice(buffer, 0, n);
}
void color_print(FILE *stream, color_t *color)
{
unsigned int r = color->r * 255,
g = color->g * 255,
b = color->b * 255,
a = color->a * 255;
fprintf(stream, "#%02x%02x%02x%02x", r, g, b, a);
}
struct timespec timespec_diff(struct timespec a, struct timespec b)
{
bool over = (b.tv_nsec - a.tv_nsec) < 0;
struct timespec diff = {
.tv_sec = b.tv_sec - a.tv_sec - over,
.tv_nsec = b.tv_nsec - a.tv_nsec + over * 1000000000ul,
};
return diff;
}
bool timespec_greater(struct timespec a, struct timespec b)
{
return a.tv_sec > b.tv_sec
|| (a.tv_sec == b.tv_sec && a.tv_nsec > b.tv_nsec);
}
void timespec_print(FILE *stream, struct timespec *ts)
{
fprintf(stream, "%ld.%.9ld", ts->tv_sec, ts->tv_nsec);
}
bool check_rect(int px, int py, int x, int y, int w, int h)
{
return px >= x && px <= x + w && py >= y && py <= y + h;
}
bool check_circle(int px, int py, int x, int y, int r)
{
int dx = x - px;
int dy = y - py;
return (dx * dx + dy * dy) <= r * r;
}
bool check_capsule(int px, int py, int x, int y, int w, int h)
{
assert(w >= h);
int radius = h / 2;
// Trivial case
if (w == h)
return check_circle(px, py, x + radius, y + radius, radius);
// General case
return check_circle(px, py, x + radius, y + radius, radius)
|| check_circle(px, py, x + w - radius, y + radius, radius)
|| check_rect(px, py, x + radius, y, w - 2 * radius, h);
}
char *strslice(const char *string, size_t start, size_t end)
{
if (string == NULL)
return NULL;
char *result = malloc(end - start + 1);
memcpy(result, string + start, end - start);
result[end - start] = '\0';
return result;
}
char *strcopy(const char *string)
{
if (string == NULL)
return NULL;
return strslice(string, 0, strlen(string));
}
void unreachable(void)
{
log_panic("Unreachable");
}
|