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
|
#include "rgl.h"
void RGL_DrawRect(RGL_Buffer *buf, RGL_Command *cmd) {
unsigned int x, y, insideX, insideY;
RGL_ASSERT(cmd->type != Rect, "expected rectangle type");
for (y = 0; y < buf->height; ++y) {
for (x = 0; x < buf->width; ++x) {
insideX = x >= cmd->data.rect.x &&
x <= (cmd->data.rect.x + cmd->data.rect.width);
insideY = y >= cmd->data.rect.y &&
y <= (cmd->data.rect.y + cmd->data.rect.height);
if (insideX && insideY) {
buf->data[x + (y * buf->width)] = cmd->data.rect.color;
}
}
}
}
void RGL_DrawStroke(RGL_Buffer *buf, RGL_PathHeader *path, RGL_Point *points) {
RGL_Point p1, p2;
unsigned int i;
int x0, x1, y0, y1, dx, dy, sx, sy, idx, err, e2;
for (i = 0; i < path->size; ++i) {
p1 = points[i], p2 = points[(i + 1) % path->size];
x0 = RGL_FixedToInt(p1.x), y0 = RGL_FixedToInt(p1.y);
x1 = RGL_FixedToInt(p2.x), y1 = RGL_FixedToInt(p2.y);
dx = RGL_ABS(x1 - x0);
sx = x0 < x1 ? 1 : -1;
dy = -RGL_ABS(y1 - y0);
sy = y0 < y1 ? 1 : -1;
err = dx + dy;
while (1) {
idx = x0 + (y0 * buf->width);
if (idx < buf->width * buf->height) {
buf->data[idx] = path->color;
}
if (x0 == x1 && y0 == y1)
break;
e2 = err * 2;
if (e2 >= dy) {
err += dy;
x0 += sx;
}
if (e2 <= dx) {
err += dx;
y0 += sy;
}
}
}
}
void RGL_DrawPath(RGL_Buffer *buf, RGL_PathHeader *path, RGL_Point *points) {
switch (path->verb) {
case PathStroke: {
RGL_DrawStroke(buf, path, points);
} break;
case PathFill: {
/* RGL_DrawFill(buf, path, points, col); */
RGL_CRASH("`RGL_DrawFill` not implemented");
} break;
default: {
RGL_CRASH("tried to handle unknown `path->verb`");
} break;
}
}
void RGL_Draw(RGL_Context *ctx, RGL_Buffer *buf) {
RGL_Command cmd;
int i;
for (i = 0; i < ctx->queue.size; ++i) {
cmd = ctx->queue.commands[i];
switch (cmd.type) {
case Rect: {
RGL_DrawRect(buf, &cmd);
} break;
case Path: {
RGL_Point *points = (RGL_Point *)&(ctx->queue.commands[i + 1]);
RGL_DrawPath(buf, &cmd.data.path, points);
/* Skip point list, so it points to a valid command */
ctx->queue.commands =
(RGL_Command *)((char *)ctx->queue.commands +
cmd.data.path.size * sizeof(RGL_Point));
} break;
default: {
RGL_CRASH("unknown `cmd.type`");
} break;
}
}
}
|