diff options
| author | iamcheeseman <[email protected]> | 2026-05-10 00:28:14 -0400 |
|---|---|---|
| committer | iamcheeseman <[email protected]> | 2026-05-10 00:28:14 -0400 |
| commit | 576bd27e11ec70bdbd1b9a644d2e227b57586337 (patch) | |
| tree | 2dc41e3f88bb95568f73ee372fc35512afcbcf9b /teensy/teensy_renderer.c | |
| parent | 9ed5698b3c74c7ce1784d3bebe2aa73d5a0c319d (diff) | |
i ain't splitting alla this up
Diffstat (limited to 'teensy/teensy_renderer.c')
| -rw-r--r-- | teensy/teensy_renderer.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/teensy/teensy_renderer.c b/teensy/teensy_renderer.c new file mode 100644 index 0000000..b29e485 --- /dev/null +++ b/teensy/teensy_renderer.c @@ -0,0 +1,217 @@ +#include "teensy_renderer.h" + +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include "teensy_context.h" +#include "teensy_list.h" + +struct ty_renderer r; + +static +bool is_renderer_init(void) +{ + return r.screen.data != NULL && r.screen.width * r.screen.height != 0; +} + +static +void image_bounds_check(struct ty_image img, struct ty_vec2i pos) +{ +#ifdef TEENSY_DEBUG + if ( + pos.x < 0 || + pos.x >= img.width || + pos.y < 0 || + pos.y >= img.height + ) { + ty_log_fatal( + TY_ERR_RENDER_OOB, + "OOB (%d, %d). bounds are (%d, %d)", + pos.x, pos.y, + img.width, img.height + ); + } +#else + (void)img; + (void)pos; +#endif +} + +void ty_init_renderer(void) +{ + r.screen = ty_create_image( + ctx.hints.scr_width, + ctx.hints.scr_height, + NULL + ); +} + +void ty_deinit_renderer(void) +{ + assert(is_renderer_init()); + + ty_free_image(r.screen); +} + +struct ty_image ty_create_image(int w, int h, const struct ty_color* data) +{ + struct ty_image img; + + img.width = w; + img.height = h; + + size_t size = sizeof(struct ty_color) * w * h; + img.data = ty_alloc(size); + if (data) + memcpy(img.data, data, size); + else + memset(img.data, 0, size); + + return img; +} + +void ty_free_image(struct ty_image img) +{ + ty_free(img.data); +} + +struct ty_color ty_img_get_pixel(struct ty_image img, struct ty_vec2i pos) +{ + image_bounds_check(img, pos); + return img.data[pos.y * img.width + pos.x]; +} + +void ty_img_set_pixel( + struct ty_image img, + struct ty_vec2i pos, + struct ty_color color +) { + image_bounds_check(img, pos); + img.data[pos.y * img.width + pos.x] = color; +} + +void ty_draw_clear(struct ty_color col) +{ + assert(is_renderer_init()); + for (int i = 0; i < r.screen.width * r.screen.height; i++) { + r.screen.data[i] = col; + } +} + +void ty_draw_image(struct ty_image img, struct ty_vec2i pos) +{ + int x1 = fmin(fmax(floor(pos.x), 0), r.screen.width); + int y1 = fmin(fmax(floor(pos.y), 0), r.screen.height); + int x2 = fmin(fmax(floor(pos.x + img.width), 0), r.screen.width); + int y2 = fmin(fmax(floor(pos.y + img.height), 0), r.screen.height); + + for (int dy = y1; dy < y2; dy++) { + for (int dx = x1; dx < x2; dx++) { + ty_img_set_pixel( + r.screen, + ty_vec2i(dx, dy), + ty_img_get_pixel(img, ty_vec2i(dx - x1, dy - y1)) + ); + } + } +} + +void ty_draw_image_ex( + struct ty_image img, + struct ty_recti src, + struct ty_recti dst +) { + int x1 = fmin(fmax(floor(dst.x), 0), r.screen.width); + int y1 = fmin(fmax(floor(dst.y), 0), r.screen.height); + int x2 = fmin(fmax(floor(dst.x + dst.w), 0), r.screen.width); + int y2 = fmin(fmax(floor(dst.y + dst.h), 0), r.screen.height); + + for (int dy = y1; dy < y2; dy++) { + for (int dx = x1; dx < x2; dx++) { + int img_x = ((dx - x1) * src.w) / dst.w + src.x; + int img_y = ((dy - y1) * src.h) / dst.h + src.y; + + ty_img_set_pixel( + r.screen, + ty_vec2i(dx, dy), + ty_img_get_pixel(img, ty_vec2i(img_x, img_y)) + ); + } + } +} + +void ty_draw_rect(struct ty_recti rect, struct ty_color color) +{ + int x1 = fmin(fmax(floor(rect.x), 0), r.screen.width); + int y1 = fmin(fmax(floor(rect.y), 0), r.screen.height); + + int x2 = fmin(fmax(floor(rect.x + rect.w), 0), r.screen.width); + int y2 = fmin(fmax(floor(rect.y + rect.h), 0), r.screen.height); + + for (int dy = y1; dy < y2; dy++) { + for (int dx = x1; dx < x2; dx++) { + ty_img_set_pixel( + r.screen, + ty_vec2i(dx, dy), + color + ); + } + } +} + +void ty_draw_line( + struct ty_vec2i start, + struct ty_vec2i end, + struct ty_color color +) { + int dx = end.x - start.x; + int dy = end.y - start.y; + + if (abs(dx) > abs(dy)) { + if (start.x > end.x) { + int tmp = start.x; + start.x = end.x; + end.x = tmp; + + tmp = start.y; + start.y = end.y; + end.y = tmp; + } + + for (int x = start.x; x < end.x; x++) { + int y = start.y + dy * (x - start.x) / dx; + + ty_img_set_pixel( + r.screen, + ty_vec2i(x, y), + color + ); + } + } else { + if (start.y > end.y) { + int tmp = start.x; + start.x = end.x; + end.x = tmp; + + tmp = start.y; + start.y = end.y; + end.y = tmp; + } + + for (int y = start.y; y < end.y; y++) { + int x = start.x + dx * (y - start.y) / dy; + + ty_img_set_pixel( + r.screen, + ty_vec2i(x, y), + color + ); + } + } +} + +void ty_draw_end(void) +{ + assert(is_renderer_init()); +} |
