diff options
Diffstat (limited to 'Draw')
| -rw-r--r-- | Draw/draw.h | 307 |
1 files changed, 184 insertions, 123 deletions
diff --git a/Draw/draw.h b/Draw/draw.h index fded875..73b2b3e 100644 --- a/Draw/draw.h +++ b/Draw/draw.h @@ -5,178 +5,239 @@ #ifndef DRAW_H #define DRAW_H +/* CHANGE LOG + * 0.0.0 - @vasco - prototyping + */ + +#include <math.h> #include <stdint.h> -#include <string.h> #include <stdlib.h> -#include <math.h> +#include <string.h> + +#define DRAW__MIN(a, b) ((a) < (b) ? (a) : (b)) +#define DRAW__MAX(a, b) ((a) > (b) ? (a) : (b)) typedef struct Draw { - uint32_t *px; - int w, h; - int cx, cy, cw, ch; + uint32_t *px; + int w, h; + int cx, cy, cw, ch; } Draw; -#define DRAW__MIN(a, b) ((a) < (b) ? (a) : (b)) -#define DRAW__MAX(a, b) ((a) > (b) ? (a) : (b)) +static void draw_begin(Draw *d, uint32_t *px, int w, int h); +static void draw_clip(Draw *d, int x, int y, int w, int h); +static void draw_clip_reset(Draw *d); +static void draw_pixel(Draw *d, int x, int y, uint32_t color); +static uint32_t draw__lerp(uint32_t c0, uint32_t c1, float t); +static float draw__cross(float ax, float ay, float bx, float by, float cx, float cy); +static void draw_blit(Draw *d, int x, int y, const uint32_t *src, int sw, int sh); +static void draw_rect(Draw *d, int x, int y, int w, int h, uint32_t color); +static void draw_rect_gradient(Draw *d, int x, int y, int w, int h, uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3); +static void draw_tri(Draw *d, int x0, int y0, int x1, int y1, int x2, int y2, uint32_t c0, uint32_t c1, uint32_t c2); +static void draw_line(Draw *d, int x0, int y0, int x1, int y1, int width, uint32_t c0, uint32_t c1); -static inline void +void draw_begin(Draw *d, uint32_t *px, int w, int h) { - d->px = px; - d->w = w; - d->h = h; - d->cx = 0; - d->cy = 0; - d->cw = w; - d->ch = h; + d->px = px; + d->w = w; + d->h = h; + d->cx = 0; + d->cy = 0; + d->cw = w; + d->ch = h; } -static inline void +void draw_clip(Draw *d, int x, int y, int w, int h) { - d->cx = x; - d->cy = y; - d->cw = w; - d->ch = h; + d->cx = x; + d->cy = y; + d->cw = w; + d->ch = h; } -static inline void +void draw_clip_reset(Draw *d) { - d->cx = 0; - d->cy = 0; - d->cw = d->w; - d->ch = d->h; + d->cx = 0; + d->cy = 0; + d->cw = d->w; + d->ch = d->h; } -static inline void +void draw_pixel(Draw *d, int x, int y, uint32_t color) { - if (x < d->cx || x >= d->cx + d->cw || y < d->cy || y >= d->cy + d->ch) return; - if (x < 0 || x >= d->w || y < 0 || y >= d->h) return; - d->px[y * d->w + x] = color; + if (x < d->cx || x >= d->cx + d->cw || y < d->cy || y >= d->cy + d->ch) + return; + if (x < 0 || x >= d->w || y < 0 || y >= d->h) + return; + d->px[y * d->w + x] = color; } -static inline uint32_t +uint32_t draw__lerp(uint32_t c0, uint32_t c1, float t) { - if (t <= 0.0f) return c0; - if (t >= 1.0f) return c1; - uint32_t a0 = (c0 >> 24) & 0xFF, a1 = (c1 >> 24) & 0xFF; - uint32_t r0 = (c0 >> 16) & 0xFF, r1 = (c1 >> 16) & 0xFF; - uint32_t g0 = (c0 >> 8) & 0xFF, g1 = (c1 >> 8) & 0xFF; - uint32_t b0 = c0 & 0xFF, b1 = c1 & 0xFF; - uint32_t a = (uint32_t)(a0 + t * ((float)a1 - (float)a0)); - uint32_t r = (uint32_t)(r0 + t * ((float)r1 - (float)r0)); - uint32_t g = (uint32_t)(g0 + t * ((float)g1 - (float)g0)); - uint32_t b = (uint32_t)(b0 + t * ((float)b1 - (float)b0)); - return (a << 24) | (r << 16) | (g << 8) | b; + uint32_t a0, a1, r0, r1, g0, g1, b0, b1; + uint32_t a, r, g, b; + if (t <= 0.0f) + return c0; + if (t >= 1.0f) + return c1; + a0 = (c0 >> 24) & 0xFF; + a1 = (c1 >> 24) & 0xFF; + r0 = (c0 >> 16) & 0xFF; + r1 = (c1 >> 16) & 0xFF; + g0 = (c0 >> 8) & 0xFF; + g1 = (c1 >> 8) & 0xFF; + b0 = c0 & 0xFF; + b1 = c1 & 0xFF; + a = (uint32_t)(a0 + t * ((float)a1 - (float)a0)); + r = (uint32_t)(r0 + t * ((float)r1 - (float)r0)); + g = (uint32_t)(g0 + t * ((float)g1 - (float)g0)); + b = (uint32_t)(b0 + t * ((float)b1 - (float)b0)); + return (a << 24) | (r << 16) | (g << 8) | b; } -static inline float +float draw__cross(float ax, float ay, float bx, float by, float cx, float cy) { - return (cx - ax) * (by - ay) - (cy - ay) * (bx - ax); + return (cx - ax) * (by - ay) - (cy - ay) * (bx - ax); } -static inline void +void draw_blit(Draw *d, int x, int y, const uint32_t *src, int sw, int sh) { - for (int row = 0; row < sh; ++row) { - int ty = y + row; - if (ty < d->cy || ty >= d->cy + d->ch || ty < 0 || ty >= d->h) continue; - int x0 = DRAW__MAX(x, d->cx); - int x1 = DRAW__MIN(x + sw, d->cx + d->cw); - if (x0 >= x1) continue; - memcpy(&d->px[ty * d->w + x0], &src[row * sw + (x0 - x)], (size_t)(x1 - x0) * sizeof(uint32_t)); - } + int row, ty, x0, x1; + for (row = 0; row < sh; ++row) { + ty = y + row; + if (ty < d->cy || ty >= d->cy + d->ch || ty < 0 || ty >= d->h) + continue; + x0 = DRAW__MAX(x, d->cx); + x1 = DRAW__MIN(x + sw, d->cx + d->cw); + if (x0 >= x1) + continue; + memcpy(&d->px[ty * d->w + x0], &src[row * sw + (x0 - x)], (size_t)(x1 - x0) * sizeof(uint32_t)); + } } -static inline void +void draw_rect(Draw *d, int x, int y, int w, int h, uint32_t color) { - int x0 = DRAW__MAX(x, d->cx); - int y0 = DRAW__MAX(y, d->cy); - int x1 = DRAW__MIN(x + w, d->cx + d->cw); - int y1 = DRAW__MIN(y + h, d->cy + d->ch); - for (int py = y0; py < y1; ++py) { - if (py < 0 || py >= d->h) continue; - for (int px = x0; px < x1; ++px) { - if (px < 0 || px >= d->w) continue; - d->px[py * d->w + px] = color; - } - } + int x0, y0, x1, y1; + int py, px; + x0 = DRAW__MAX(x, d->cx); + y0 = DRAW__MAX(y, d->cy); + x1 = DRAW__MIN(x + w, d->cx + d->cw); + y1 = DRAW__MIN(y + h, d->cy + d->ch); + for (py = y0; py < y1; ++py) { + if (py < 0 || py >= d->h) + continue; + for (px = x0; px < x1; ++px) { + if (px < 0 || px >= d->w) + continue; + d->px[py * d->w + px] = color; + } + } } -static inline void +void draw_rect_gradient(Draw *d, int x, int y, int w, int h, uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3) { - for (int ry = 0; ry < h; ++ry) { - float ty = (h > 1) ? (float)ry / (float)(h - 1) : 0.0f; - uint32_t left = draw__lerp(c0, c3, ty); - uint32_t right = draw__lerp(c1, c2, ty); - for (int rx = 0; rx < w; ++rx) { - float tx = (w > 1) ? (float)rx / (float)(w - 1) : 0.0f; - draw_pixel(d, x + rx, y + ry, draw__lerp(left, right, tx)); - } - } + int ry, rx; + float ty, tx; + uint32_t left, right; + for (ry = 0; ry < h; ++ry) { + ty = (h > 1) ? (float)ry / (float)(h - 1) : 0.0f; + left = draw__lerp(c0, c3, ty); + right = draw__lerp(c1, c2, ty); + for (rx = 0; rx < w; ++rx) { + tx = (w > 1) ? (float)rx / (float)(w - 1) : 0.0f; + draw_pixel(d, x + rx, y + ry, draw__lerp(left, right, tx)); + } + } } -static inline void +void draw_tri(Draw *d, int x0, int y0, int x1, int y1, int x2, int y2, uint32_t c0, uint32_t c1, uint32_t c2) { - int min_x = DRAW__MIN(x0, DRAW__MIN(x1, x2)); - int max_x = DRAW__MAX(x0, DRAW__MAX(x1, x2)); - int min_y = DRAW__MIN(y0, DRAW__MIN(y1, y2)); - int max_y = DRAW__MAX(y0, DRAW__MAX(y1, y2)); - float area = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x2, (float)y2); - if (area == 0.0f) return; - int solid = (c0 == c1 && c1 == c2); - for (int y = min_y; y <= max_y; ++y) { - for (int x = min_x; x <= max_x; ++x) { - float w0 = draw__cross((float)x1, (float)y1, (float)x2, (float)y2, (float)x, (float)y); - float w1 = draw__cross((float)x2, (float)y2, (float)x0, (float)y0, (float)x, (float)y); - float w2 = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x, (float)y); - if ((w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 <= 0 && w1 <= 0 && w2 <= 0)) { - uint32_t c = c0; - if (!solid) { - w0 /= area; - w1 /= area; - w2 /= area; - c = draw__lerp(c0, c1, w1 / (w0 + w1 + 1e-6f)); - c = draw__lerp(c, c2, w2); - } - draw_pixel(d, x, y, c); - } - } - } + int min_x, max_x, min_y, max_y; + int solid; + int x, y; + float area; + float w0, w1, w2; + uint32_t c; + min_x = DRAW__MIN(x0, DRAW__MIN(x1, x2)); + max_x = DRAW__MAX(x0, DRAW__MAX(x1, x2)); + min_y = DRAW__MIN(y0, DRAW__MIN(y1, y2)); + max_y = DRAW__MAX(y0, DRAW__MAX(y1, y2)); + area = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x2, (float)y2); + if (area == 0.0f) + return; + solid = (c0 == c1 && c1 == c2); + for (y = min_y; y <= max_y; ++y) { + for (x = min_x; x <= max_x; ++x) { + w0 = draw__cross((float)x1, (float)y1, (float)x2, (float)y2, (float)x, (float)y); + w1 = draw__cross((float)x2, (float)y2, (float)x0, (float)y0, (float)x, (float)y); + w2 = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x, (float)y); + if ((w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 <= 0 && w1 <= 0 && w2 <= 0)) { + c = c0; + if (!solid) { + w0 /= area; + w1 /= area; + w2 /= area; + c = draw__lerp(c0, c1, w1 / (w0 + w1 + 1e-6f)); + c = draw__lerp(c, c2, w2); + } + draw_pixel(d, x, y, c); + } + } + } } -static inline void +void draw_line(Draw *d, int x0, int y0, int x1, int y1, int width, uint32_t c0, uint32_t c1) { - float total = 0.0f; - int grad = (c0 != c1); - if (grad) total = sqrtf((float)((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0))); - int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; - int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; - int err = dx + dy; - int ox0 = x0, oy0 = y0; - int hw = width / 2; - for (;;) { - uint32_t c = c0; - if (grad) { - float cd = sqrtf((float)((x0 - ox0) * (x0 - ox0) + (y0 - oy0) * (y0 - oy0))); - c = draw__lerp(c0, c1, total > 0.0f ? cd / total : 0.0f); - } - for (int ox = -hw; ox <= hw; ++ox) - for (int oy = -hw; oy <= hw; ++oy) - draw_pixel(d, x0 + ox, y0 + oy, c); - if (x0 == x1 && y0 == y1) break; - int e2 = 2 * err; - if (e2 >= dy) { err += dy; x0 += sx; } - if (e2 <= dx) { err += dx; y0 += sy; } - } + float total; + int grad; + int dx, sx, dy, sy, err; + int ox0, oy0, hw; + int ox, oy, e2; + uint32_t c; + total = 0.0f; + grad = (c0 != c1); + if (grad) + total = sqrtf((float)((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0))); + dx = abs(x1 - x0); + sx = x0 < x1 ? 1 : -1; + dy = -abs(y1 - y0); + sy = y0 < y1 ? 1 : -1; + err = dx + dy; + ox0 = x0; + oy0 = y0; + hw = width / 2; + for (;;) { + c = c0; + if (grad) { + float cd; + cd = sqrtf((float)((x0 - ox0) * (x0 - ox0) + (y0 - oy0) * (y0 - oy0))); + c = draw__lerp(c0, c1, total > 0.0f ? cd / total : 0.0f); + } + for (ox = -hw; ox <= hw; ++ox) + for (oy = -hw; oy <= hw; ++oy) + draw_pixel(d, x0 + ox, y0 + oy, c); + if (x0 == x1 && y0 == y1) + break; + e2 = 2 * err; + if (e2 >= dy) { + err += dy; + x0 += sx; + } + if (e2 <= dx) { + err += dx; + y0 += sy; + } + } } #endif /* DRAW_H */ |
