fn_wasm_import void wasm_clear(void); fn_wasm_import void wasm_draw_text(isize str, i32 len, f64 x, f64 y, isize font_str, i32 font_len, i32 font_size, f32 r, f32 g, f32 b, f32 a); fn_wasm_import void wasm_draw_rect(f64 x, f64 y, f64 w, f64 h, f32 r, f32 g, f32 b, f32 a); fn_wasm_import f64 wasm_measure_text(isize str, i32 len, isize font_str, i32 font_len, i32 font_size); fn_wasm_import f64 wasm_get_font_height(isize font_str, i32 font_len, i32 font_size); fn_wasm_import void wasm_set_clip(f64 x, f64 y, f64 w, f64 h); global s8_t font_face = s8_const_lit("open_sans_regular"); fn void set_clip(r2f64_t rect) { wasm_set_clip(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y)); } fn f64 get_font_height(void) { return wasm_get_font_height((isize) font_face.str, font_face.len, 20*wasm_dpr) / wasm_dpr; } fn f64 measure_text_ex(char *str, i32 len) { return wasm_measure_text((isize)str, len, (isize) font_face.str, font_face.len, 20*wasm_dpr) / wasm_dpr; } fn f64 measure_text(char *str) { return measure_text_ex(str, str_len(str)); } fn void draw_text(v2f64_t pos, v4f32_t color, s8_t string) { wasm_draw_text((isize)string.str, string.len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face.str, font_face.len, 20*wasm_dpr, color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a); } fn void draw_textf(v2f64_t pos, char *str, ...) { char buff[1024]; va_list args; va_start(args, str); i32 len = stbsp_vsnprintf(buff, sizeof(buff), str, args); va_end(args); wasm_draw_text((isize)buff, len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face.str, font_face.len, 20*wasm_dpr, 0, 0, 0, 1); } fn void draw_rect(r2f64_t rect, v4f32_t color) { wasm_draw_rect(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y), color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a); } typedef enum { gfx2d_kind_null, gfx2d_kind_clear, gfx2d_kind_draw_rect, gfx2d_kind_draw_text, gfx2d_kind_set_clip, } gfx2d_kind_t; typedef struct gfx2d_cmd_t gfx2d_cmd_t; struct gfx2d_cmd_t { gfx2d_cmd_t *next; gfx2d_kind_t kind; r2f64_t rect; v4f32_t color; s8_t text; }; typedef struct gfx2d_t gfx2d_t; struct gfx2d_t { gfx2d_cmd_t *first; gfx2d_cmd_t *last; app_event_t *ev; }; void gfx2d_begin(gfx2d_t *gfx, app_event_t *ev) { gfx->ev = ev; } void gfx2d_end(gfx2d_t *gfx) { app_event_t *ev = gfx->ev; r2f64_t window = (r2f64_t){0, 0, ev->window_size.x, ev->window_size.y}; for (gfx2d_cmd_t *cmd = gfx->first; cmd; cmd = cmd->next) { if (cmd->kind == gfx2d_kind_clear) { wasm_clear(); draw_rect(window, cmd->color); } else if (cmd->kind == gfx2d_kind_draw_rect) { draw_rect(cmd->rect, cmd->color); } else if (cmd->kind == gfx2d_kind_draw_text) { draw_text(cmd->rect.min, cmd->color, cmd->text); } else if (cmd->kind == gfx2d_kind_set_clip) { set_clip(cmd->rect); } else { invalid_codepath; } } gfx->first = gfx->last = NULL; } void gfx2d_add_cmd(gfx2d_t *gfx, gfx2d_cmd_t cmd) { gfx2d_cmd_t *c = ma_push_type(tcx.temp, gfx2d_cmd_t); *c = cmd; SLLQ_APPEND(gfx->first, gfx->last, c); } void gfx2d_clear(gfx2d_t *gfx, v4f32_t color) { gfx2d_add_cmd(gfx, (gfx2d_cmd_t){ .kind = gfx2d_kind_clear, .color = color, }); } void gfx2d_rect(gfx2d_t *gfx, r2f64_t rect, v4f32_t color) { gfx2d_add_cmd(gfx, (gfx2d_cmd_t){ .kind = gfx2d_kind_draw_rect, .color = color, .rect = rect, }); } void gfx2d_set_clip(gfx2d_t *gfx, r2f64_t rect) { gfx2d_add_cmd(gfx, (gfx2d_cmd_t){ .kind = gfx2d_kind_set_clip, .rect = rect, }); } void gfx2d_text(gfx2d_t *gfx, v2f64_t pos, v4f32_t color, s8_t string) { gfx2d_add_cmd(gfx, (gfx2d_cmd_t){ .kind = gfx2d_kind_draw_text, .text = s8_copy(tcx.temp, string), .color = color, .rect.min = pos, }); } void gfx2d_textf(gfx2d_t *gfx, v2f64_t pos, v4f32_t color, char *str, ...) { S8_FMT(tcx.temp, str, text); gfx2d_add_cmd(gfx, (gfx2d_cmd_t){ .kind = gfx2d_kind_draw_text, .text = text, .color = color, .rect.min = pos, }); }