summaryrefslogtreecommitdiff
path: root/Peak/src/peak.c
diff options
context:
space:
mode:
authorVasco <[email protected]>2026-08-24 00:56:24 +0100
committerVasco <[email protected]>2026-08-24 00:56:24 +0100
commit5dc2716abd43166cd65133625f408ad36a6623b3 (patch)
tree19d89b838206b6bb11cc0b9f88311d855999d447 /Peak/src/peak.c
parentdc96fcd771bea09d726a760266739906e95c09a6 (diff)
Peak 0.4.0 and Draw
Diffstat (limited to 'Peak/src/peak.c')
-rw-r--r--Peak/src/peak.c296
1 files changed, 80 insertions, 216 deletions
diff --git a/Peak/src/peak.c b/Peak/src/peak.c
index 5e09070..6c4c038 100644
--- a/Peak/src/peak.c
+++ b/Peak/src/peak.c
@@ -1,254 +1,118 @@
-static inline void peak__put_pixel(int x, int y, uint32_t color);
-static inline uint32_t peak__lerp_color(uint32_t c0, uint32_t c1, float t);
-static inline float peak__edge_cross(float ax, float ay, float bx, float by, float cx, float cy);
-
-static uint32_t *peak_window_buffer;
-static size_t peak_window_width;
-static size_t peak_window_height;
-static int peak_clip_x;
-static int peak_clip_y;
-static size_t peak_clip_width;
-static size_t peak_clip_height;
-
-void
-peak__put_pixel(int x, int y, uint32_t color)
-{
- if (x < peak_clip_x || x >= (int)(peak_clip_x + peak_clip_width) ||
- y < peak_clip_y || y >= (int)(peak_clip_y + peak_clip_height)) {
- return;
- }
- if (x < 0 || x >= (int)peak_window_width || y < 0 || y >= (int)peak_window_height) {
- return;
- }
- peak_window_buffer[y * peak_window_width + x] = color;
-}
-
-uint32_t
-peak__lerp_color(uint32_t c0, uint32_t c1, float t)
+static uint32_t *
+peak_window_sync(PeakWindow *win, size_t *width, size_t *height)
{
- 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;
+ size_t w = 0, h = 0;
+ win->buffer = peak_platform_window_buffer(&win->internal, &w, &h);
+ win->width = (uint32_t)w;
+ win->height = (uint32_t)h;
+ win->bufsize = win->width * win->height;
+ if (width) *width = w;
+ if (height) *height = h;
+ return win->buffer;
}
-float
-peak__edge_cross(float ax, float ay, float bx, float by, float cx, float cy)
+int
+peak_init(void)
{
- return (cx - ax) * (by - ay) - (cy - ay) * (bx - ax);
+ return peak_platform_init();
}
void
-peak_init(void)
+peak_quit(void)
{
- peak_platform_window_open();
- peak_window_buffer = peak_platform_window_buffer(&peak_window_width, &peak_window_height);
- peak_clip_x = 0;
- peak_clip_y = 0;
- peak_clip_width = peak_window_width;
- peak_clip_height = peak_window_height;
+ peak_platform_quit();
}
-void
-peak_quit(void)
+PeakWindow
+peak_window_open(const char *name, uint32_t width, uint32_t height, uint32_t flags)
{
- peak_platform_window_close();
+ PeakWindow win = {0};
+ if (!name || !name[0]) name = "Peak";
+ if (!width) width = 800;
+ if (!height) height = 600;
+ win.internal = peak_platform_window_open(name, width, height, flags);
+ if (!peak_window_sync(&win, NULL, NULL)) return win;
+ win.running = 1;
+ return win;
}
void
-peak_extensions(void)
+peak_window_close(PeakWindow *win)
{
- // TODO
+ win->running = 0;
+ peak_platform_window_close(&win->internal);
+ win->buffer = NULL;
+ win->width = 0;
+ win->height = 0;
+ win->bufsize = 0;
}
-bool
-peak_poll_events(PeakEvent *ev)
+int
+peak_window_epoll(PeakWindow *win, PeakEvent *ev)
{
- return peak_platform_epoll(ev);
+ int got = peak_platform_epoll(&win->internal, ev);
+ if (got && ev->type == PEAK_EVENT_WINDOW_RESIZE)
+ peak_window_sync(win, NULL, NULL);
+ return got;
}
-void
-peak_blit(int offset_x, int offset_y, const uint32_t *rgba, size_t width, size_t height)
+uint32_t *
+peak_window_backbuffer(PeakWindow *win, size_t *width, size_t *height)
{
- for (size_t y = 0; y < height; ++y) {
- int target_y = offset_y + (int)y;
- if (target_y < peak_clip_y || target_y >= (int)(peak_clip_y + peak_clip_height) ||
- target_y < 0 || target_y >= (int)peak_window_height) continue;
-
- int start_x = offset_x < peak_clip_x ? peak_clip_x : offset_x;
- int end_x = (offset_x + (int)width) > (int)(peak_clip_x + peak_clip_width)
- ? (int)(peak_clip_x + peak_clip_width)
- : (offset_x + (int)width);
-
- if (start_x >= end_x) continue;
-
- size_t src_offset_x = (size_t)(start_x - offset_x);
- size_t copy_pixels = (size_t)(end_x - start_x);
-
- memcpy(&peak_window_buffer[target_y * peak_window_width + start_x], &rgba[y * width + src_offset_x], copy_pixels * sizeof(uint32_t));
- }
+ return peak_window_sync(win, width, height);
}
void
-peak_clip(int x, int y, size_t w, size_t h)
+peak_window_clear(PeakWindow *win, float r, float g, float b, float a)
{
- peak_clip_x = x;
- peak_clip_y = y;
- peak_clip_width = w;
- peak_clip_height = h;
+ uint32_t c, i;
+ if (!win || !win->buffer) return;
+#if defined(PEAK_WEB)
+ /* ImageData RGBA bytes = LE 0xAABBGGRR */
+ c = (uint32_t)(r * 255.f)
+ | ((uint32_t)(g * 255.f) << 8)
+ | ((uint32_t)(b * 255.f) << 16)
+ | ((uint32_t)(a * 255.f) << 24);
+#else
+ c = ((uint32_t)(a * 255.f) << 24)
+ | ((uint32_t)(r * 255.f) << 16)
+ | ((uint32_t)(g * 255.f) << 8)
+ | (uint32_t)(b * 255.f);
+#endif
+ for (i = 0; i < win->bufsize; i++)
+ win->buffer[i] = c;
}
void
-peak_clip_reset(void)
+peak_window_present(PeakWindow *win)
{
- peak_clip_x = 0;
- peak_clip_y = 0;
- peak_clip_width = peak_window_width;
- peak_clip_height = peak_window_height;
+ if (win) peak_platform_window_present(&win->internal);
}
-void
-peak_draw_rectangle(int x, int y, size_t w, size_t h, uint32_t color)
+#ifdef PEAK_WEB
+#include <emscripten.h>
+static void
+peak_internal_web_step(void *arg)
{
- int start_x = (x < peak_clip_x) ? peak_clip_x : x;
- int start_y = (y < peak_clip_y) ? peak_clip_y : y;
- int end_x = (x + (int)w > (int)(peak_clip_x + peak_clip_width)) ? (int)(peak_clip_x + peak_clip_width) : x + (int)w;
- int end_y = (y + (int)h > (int)(peak_clip_y + peak_clip_height)) ? (int)(peak_clip_y + peak_clip_height) : y + (int)h;
-
- for (int py = start_y; py < end_y; ++py) {
- if (py < 0 || py >= (int)peak_window_height) continue;
- for (int px = start_x; px < end_x; ++px) {
- if (px < 0 || px >= (int)peak_window_width) continue;
- peak_window_buffer[py * peak_window_width + px] = color;
- }
+ PeakWindow *win = arg;
+ if (!win->tick(win, win->userdata) || !win->running) {
+ win->running = 0;
+ emscripten_cancel_main_loop();
}
}
+#endif
void
-peak_draw_rectangle_gradient(int x, int y, size_t w, size_t h, uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3)
+peak_window_run(PeakWindow *win, int (*peak_tick)(PeakWindow *win, void *userdata), void *userdata)
{
- for (size_t ry = 0; ry < h; ++ry) {
- float ty = (h > 1) ? (float)ry / (float)(h - 1) : 0.0f;
- uint32_t left_color = peak__lerp_color(c0, c3, ty);
- uint32_t right_color = peak__lerp_color(c1, c2, ty);
-
- for (size_t rx = 0; rx < w; ++rx) {
- float tx = (w > 1) ? (float)rx / (float)(w - 1) : 0.0f;
- uint32_t final_color = peak__lerp_color(left_color, right_color, tx);
- peak__put_pixel(x + (int)rx, y + (int)ry, final_color);
- }
- }
+ assert(win && "peak_window_run needs a window");
+ assert(peak_tick && "peak_window_run needs tick callback");
+ win->tick = peak_tick;
+ win->userdata = userdata;
+ win->running = 1;
+#ifdef PEAK_WEB
+ emscripten_set_main_loop_arg(peak_internal_web_step, win, 0, 1);
+#else
+ while (win->running && win->tick(win, win->userdata));
+#endif
}
-
-void
-peak_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color)
-{
- int min_x = (x0 < x1) ? ((x0 < x2) ? x0 : x2) : ((x1 < x2) ? x1 : x2);
- int max_x = (x0 > x1) ? ((x0 > x2) ? x0 : x2) : ((x1 > x2) ? x1 : x2);
- int min_y = (y0 < y1) ? ((y0 < y2) ? y0 : y2) : ((y1 < y2) ? y1 : y2);
- int max_y = (y0 > y1) ? ((y0 > y2) ? y0 : y2) : ((y1 > y2) ? y1 : y2);
-
- float area = peak__edge_cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x2, (float)y2);
- if (area == 0.0f) return;
-
- for (int y = min_y; y <= max_y; ++y) {
- for (int x = min_x; x <= max_x; ++x) {
- float w0 = peak__edge_cross((float)x1, (float)y1, (float)x2, (float)y2, (float)x, (float)y);
- float w1 = peak__edge_cross((float)x2, (float)y2, (float)x0, (float)y0, (float)x, (float)y);
- float w2 = peak__edge_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)) {
- peak__put_pixel(x, y, color);
- }
- }
- }
-}
-
-void
-peak_draw_triangle_gradient(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t c0, uint32_t c1, uint32_t c2)
-{
- int min_x = (x0 < x1) ? ((x0 < x2) ? x0 : x2) : ((x1 < x2) ? x1 : x2);
- int max_x = (x0 > x1) ? ((x0 > x2) ? x0 : x2) : ((x1 > x2) ? x1 : x2);
- int min_y = (y0 < y1) ? ((y0 < y2) ? y0 : y2) : ((y1 < y2) ? y1 : y2);
- int max_y = (y0 > y1) ? ((y0 > y2) ? y0 : y2) : ((y1 > y2) ? y1 : y2);
-
- float area = peak__edge_cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x2, (float)y2);
- if (area == 0.0f) return;
-
- for (int y = min_y; y <= max_y; ++y) {
- for (int x = min_x; x <= max_x; ++x) {
- float w0 = peak__edge_cross((float)x1, (float)y1, (float)x2, (float)y2, (float)x, (float)y) / area;
- float w1 = peak__edge_cross((float)x2, (float)y2, (float)x0, (float)y0, (float)x, (float)y) / area;
- float w2 = peak__edge_cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x, (float)y) / area;
-
- if (w0 >= 0.0f && w1 >= 0.0f && w2 >= 0.0f) {
- uint32_t col_a = peak__lerp_color(c0, c1, w1 / (w0 + w1 + 1e-6f));
- uint32_t final_color = peak__lerp_color(col_a, c2, w2);
- peak__put_pixel(x, y, final_color);
- }
- }
- }
-}
-
-void
-peak_draw_line(int x0, int y0, int x1, int y1, size_t width, uint32_t color)
-{
- int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
- int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
- int err = dx + dy, e2;
-
- int half_w = (int)width / 2;
-
- while (1) {
- /* Draw square footprint for line thickness */
- for (int ox = -half_w; ox <= half_w; ++ox) {
- for (int oy = -half_w; oy <= half_w; ++oy) {
- peak__put_pixel(x0 + ox, y0 + oy, color);
- }
- }
- if (x0 == x1 && y0 == y1) break;
- e2 = 2 * err;
- if (e2 >= dy) { err += dy; x0 += sx; }
- if (e2 <= dx) { err += dx; y0 += sy; }
- }
-}
-
-void
-peak_draw_line_gradient(int x0, int y0, int x1, int y1, size_t width, uint32_t c0, uint32_t c1)
-{
- float total_dist = 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, e2;
-
- int orig_x0 = x0, orig_y0 = y0;
- int half_w = (int)width / 2;
-
- while (1) {
- float current_dist = sqrtf((float)((x0 - orig_x0)*(x0 - orig_x0) + (y0 - orig_y0)*(y0 - orig_y0)));
- float t = (total_dist > 0.0f) ? (current_dist / total_dist) : 0.0f;
- uint32_t color = peak__lerp_color(c0, c1, t);
-
- for (int ox = -half_w; ox <= half_w; ++ox) {
- for (int oy = -half_w; oy <= half_w; ++oy) {
- peak__put_pixel(x0 + ox, y0 + oy, color);
- }
- }
-
- if (x0 == x1 && y0 == y1) break;
- e2 = 2 * err;
- if (e2 >= dy) { err += dy; x0 += sx; }
- if (e2 <= dx) { err += dx; y0 += sy; }
- }
-}
-