colourpicker

Simple Colour Picker written in C
git clone anongit@rnpnr.xyz:colourpicker.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

Commit: 5a3fdd7fcfeb641f1976e86823e1b62494e56388
Parent: bf9e863d8cd9330221f0dd9709fd3566c46fa8b5
Author: Randy Palamar
Date:   Sat, 28 Mar 2026 07:00:45 -0600

import rstd headers

Diffstat:
Mcolourpicker.c | 79+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mgen_incs.c | 42++++++++++++++++++++++--------------------
Mmain.c | 10+++++-----
Arstd_compiler.h | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arstd_core.h | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arstd_intrinsics.h | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arstd_types.h | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mutil.c | 110++++++++++++++++++++++---------------------------------------------------------
8 files changed, 506 insertions(+), 145 deletions(-)

diff --git a/colourpicker.c b/colourpicker.c @@ -36,7 +36,7 @@ global struct { #endif function void -mem_move(u8 *dest, u8 *src, sz n) +mem_move(u8 *dest, u8 *src, s64 n) { if (dest < src) while (n) { *dest++ = *src++; n--; } else while (n) { n--; dest[n] = src[n]; } @@ -46,7 +46,7 @@ function b32 point_in_rect(v2 p, Rect r) { v2 end = add_v2(r.pos, r.size); - b32 result = BETWEEN(p.x, r.pos.x, end.x) & BETWEEN(p.y, r.pos.y, end.y); + b32 result = Between(p.x, r.pos.x, end.x) && Between(p.y, r.pos.y, end.y); return result; } @@ -94,7 +94,7 @@ measure_text(Font font, str8 text) { v2 result = {.y = font.baseSize}; - for (sz i = 0; i < text.len; i++) { + for (s64 i = 0; i < text.length; i++) { /* NOTE: assumes font glyphs are ordered (they are in our embedded fonts) */ s32 idx = (s32)text.data[i] - 32; result.x += font.glyphs[idx].advanceX; @@ -108,7 +108,7 @@ measure_text(Font font, str8 text) function void draw_text(Font font, str8 text, v2 pos, Color colour) { - for (sz i = 0; i < text.len; i++) { + for (s64 i = 0; i < text.length; i++) { /* NOTE: assumes font glyphs are ordered (they are in our embedded fonts) */ s32 idx = text.data[i] - 32; Rectangle dst = { @@ -164,7 +164,7 @@ center_align_text_in_rect(Rect r, str8 text, Font font) function Rect cut_rect_middle(Rect r, f32 left, f32 right) { - ASSERT(left <= right); + assert(left <= right); r.pos.x += r.size.w * left; r.size.w = r.size.w * (right - left); return r; @@ -191,7 +191,7 @@ hover_rect(v2 mouse, Rect rect, f32 *hover_t) b32 result = point_in_rect(mouse, rect); if (result) *hover_t += HOVER_SPEED * dt_for_frame; else *hover_t -= HOVER_SPEED * dt_for_frame; - CLAMP01(*hover_t); + *hover_t = Clamp01(*hover_t); return result; } @@ -239,7 +239,7 @@ draw_cardinal_triangle(v2 midpoint, v2 size, v2 scale, enum cardinal_direction d t2.x = midpoint.x + scale.x * size.y; t2.y = midpoint.y - scale.y * size.x; break; - default: ASSERT(0); return; + default: assert(0); return; } DrawTriangle(midpoint.rv, t1.rv, t2.rv, colour); @@ -306,7 +306,7 @@ get_slider_subrects(Rect r, Rect *label, Rect *slider, Rect *value) function void parse_and_store_text_input(ColourPickerCtx *ctx) { - str8 input = {.len = ctx->text_input_state.count, .data = ctx->text_input_state.buf}; + str8 input = {.length = ctx->text_input_state.count, .data = ctx->text_input_state.buf}; v4 new_colour = {0}; ColourKind new_mode = ColourKind_Last; if (ctx->text_input_state.idx == -1) { @@ -318,7 +318,7 @@ parse_and_store_text_input(ColourPickerCtx *ctx) new_mode = ctx->stored_colour_kind; new_colour = ctx->colour; f32 fv = parse_f64(input); - CLAMP01(fv); + fv = Clamp01(fv); switch(ctx->text_input_state.idx) { case INPUT_R: new_colour.r = fv; break; case INPUT_G: new_colour.g = fv; break; @@ -356,31 +356,31 @@ set_text_input_idx(ColourPickerCtx *ctx, enum input_indices idx, Rect r, v2 mous ctx->text_input_state.idx = idx; ctx->text_input_state.cursor = -1; - CLAMP(ctx->text_input_state.idx, -1, INPUT_A); + ctx->text_input_state.idx = Clamp(ctx->text_input_state.idx, -1, INPUT_A); if (ctx->text_input_state.idx == -1) return; - ASSERT(CheckCollisionPointRec(mouse.rv, r.rr)); + assert(CheckCollisionPointRec(mouse.rv, r.rr)); ctx->text_input_state.cursor_hover_p = (mouse.x - r.pos.x) / r.size.w; - CLAMP01(ctx->text_input_state.cursor_hover_p); + ctx->text_input_state.cursor_hover_p = Clamp01(ctx->text_input_state.cursor_hover_p); } function void do_text_input(ColourPickerCtx *ctx, Rect r, Color colour, s32 max_disp_chars) { TextInputState *is = &ctx->text_input_state; - v2 ts = measure_text(ctx->font, (str8){.len = is->count, .data = is->buf}); + v2 ts = measure_text(ctx->font, (str8){.length = is->count, .data = is->buf}); v2 pos = {.x = r.pos.x, .y = r.pos.y + (r.size.y - ts.y) / 2}; s32 buf_delta = is->count - max_disp_chars; if (buf_delta < 0) buf_delta = 0; - str8 buf = {.len = is->count - buf_delta, .data = is->buf + buf_delta}; + str8 buf = {.length = is->count - buf_delta, .data = is->buf + buf_delta}; { /* NOTE: drop a char if the subtext still doesn't fit */ v2 nts = measure_text(ctx->font, buf); if (nts.w > 0.96 * r.size.w) { buf.data++; - buf.len--; + buf.length--; } } draw_text(ctx->font, buf, pos, colour); @@ -411,12 +411,12 @@ do_text_input(ColourPickerCtx *ctx, Rect r, Color colour, s32 max_disp_chars) is->cursor = i; } - buf.len = is->cursor - buf_delta; + buf.length = is->cursor - buf_delta; v2 sts = measure_text(ctx->font, buf); f32 cursor_x = r.pos.x + sts.x; f32 cursor_width; - if (is->cursor == is->count) cursor_width = MIN(ctx->window_size.w * 0.03, 20); - else cursor_width = MIN(ctx->window_size.w * 0.01, 6); + if (is->cursor == is->count) cursor_width = Min(ctx->window_size.w * 0.03, 20); + else cursor_width = Min(ctx->window_size.w * 0.01, 6); Rect cursor_r = { .pos = {.x = cursor_x, .y = pos.y}, @@ -443,7 +443,7 @@ do_text_input(ColourPickerCtx *ctx, Rect r, Color colour, s32 max_disp_chars) if ((IsKeyPressed(KEY_BACKSPACE) || IsKeyPressedRepeat(KEY_BACKSPACE)) && is->cursor > 0) { is->cursor--; - if (is->cursor < countof(is->buf) - 1) { + if (is->cursor < (s32)countof(is->buf) - 1) { mem_move(is->buf + is->cursor, is->buf + is->cursor + 1, is->count - is->cursor - 1); @@ -474,7 +474,7 @@ do_button(ButtonState *btn, v2 mouse, Rect r, f32 hover_speed) if (hovered) btn->hover_t += hover_speed * dt_for_frame; else btn->hover_t -= hover_speed * dt_for_frame; - CLAMP01(btn->hover_t); + btn->hover_t = Clamp01(btn->hover_t); return pressed_mask; } @@ -529,7 +529,7 @@ do_slider(ColourPickerCtx *ctx, Rect r, s32 label_idx, v2 relative_mouse, str8 n if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) current = (relative_mouse.x - sr.pos.x) / sr.size.w; current += wheel / 255; - CLAMP01(current); + current = Clamp01(current); ctx->colour.E[ctx->held_idx] = current; ctx->flags |= ColourPickerFlag_RefillTexture; } @@ -563,7 +563,7 @@ do_slider(ColourPickerCtx *ctx, Rect r, s32 label_idx, v2 relative_mouse, str8 n } else { s->colour_t[label_idx] -= HOVER_SPEED * dt_for_frame; } - CLAMP01(s->colour_t[label_idx]); + s->colour_t[label_idx] = Clamp01(s->colour_t[label_idx]); if (!collides && ctx->text_input_state.idx == (label_idx + 1) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { @@ -582,7 +582,7 @@ do_slider(ColourPickerCtx *ctx, Rect r, s32 label_idx, v2 relative_mouse, str8 n u8 vbuf[4]; Stream vstream = {.data = vbuf, .cap = countof(vbuf)}; stream_append_f64(&vstream, current, 100); - str8 value = {.len = vstream.widx, .data = vbuf}; + str8 value = {.length = vstream.widx, .data = vbuf}; draw_text(ctx->font, value, left_align_text_in_rect(vr, value, ctx->font), colour_rl); } else { do_text_input(ctx, vr, colour_rl, 4); @@ -614,7 +614,7 @@ do_status_bar(ColourPickerCtx *ctx, Rect r, v2 relative_mouse) u8 hbuf[8]; Stream hstream = {.data = hbuf, .cap = countof(hbuf)}; stream_append_colour(&hstream, rl_colour_from_normalized(get_formatted_colour(ctx, ColourKind_RGB))); - str8 hex = {.len = hstream.widx, .data = hbuf}; + str8 hex = {.length = hstream.widx, .data = hbuf}; str8 label = str8("RGB: "); v2 label_size = measure_text(ctx->font, label); @@ -633,7 +633,7 @@ do_status_bar(ColourPickerCtx *ctx, Rect r, v2 relative_mouse) set_text_input_idx(ctx, -1, hex_r, relative_mouse); hstream.widx = 0; stream_append_colour(&hstream, rl_colour_from_normalized(get_formatted_colour(ctx, ColourKind_RGB))); - hex.len = hstream.widx; + hex.length = hstream.widx; } if (hex_collides && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) @@ -643,7 +643,7 @@ do_status_bar(ColourPickerCtx *ctx, Rect r, v2 relative_mouse) ctx->sbs.hex_hover_t += HOVER_SPEED * dt_for_frame; else ctx->sbs.hex_hover_t -= HOVER_SPEED * dt_for_frame; - CLAMP01(ctx->sbs.hex_hover_t); + ctx->sbs.hex_hover_t = Clamp01(ctx->sbs.hex_hover_t); v4 fg = normalize_colour(pack_rl_colour(ctx->fg)); v4 hex_colour = lerp_v4(fg, ctx->hover_colour, ctx->sbs.hex_hover_t); @@ -757,7 +757,7 @@ do_colour_selector(ColourPickerCtx *ctx, Rect r) ctx->selection_hover_t[i] -= HOVER_SPEED * dt_for_frame; } - CLAMP01(ctx->selection_hover_t[i]); + ctx->selection_hover_t[i] = Clamp01(ctx->selection_hover_t[i]); v4 colour = lerp_v4(fg, ctx->hover_colour, ctx->selection_hover_t[i]); @@ -873,14 +873,14 @@ do_vertical_slider(ColourPickerCtx *ctx, v2 test_pos, Rect r, s32 idx, if (hovering && ctx->held_idx == -1) { colour.x -= GetMouseWheelMove() * (bot_colour.x - top_colour.x) / 36; - CLAMP(colour.x, top_colour.x, bot_colour.x); + colour.x = Clamp(colour.x, top_colour.x, bot_colour.x); } if (hovering && IsMouseButtonDown(MOUSE_BUTTON_LEFT) && ctx->held_idx == -1) ctx->held_idx = idx; if (ctx->held_idx == idx) { - CLAMP(test_pos.y, r.pos.y, r.pos.y + r.size.h); + test_pos.y = Clamp(test_pos.y, r.pos.y, r.pos.y + r.size.h); f32 new_t = (test_pos.y - r.pos.y) / r.size.h; colour.x = top_colour.x + new_t * (bot_colour.x - top_colour.x); } @@ -891,7 +891,7 @@ do_vertical_slider(ColourPickerCtx *ctx, v2 test_pos, Rect r, s32 idx, (ctx->held_idx != -1 && ctx->held_idx == idx); if (should_scale) ctx->pms.scale_t[idx] += SLIDER_SCALE_SPEED * dt_for_frame; else ctx->pms.scale_t[idx] -= SLIDER_SCALE_SPEED * dt_for_frame; - CLAMP01(ctx->pms.scale_t[idx]); + ctx->pms.scale_t[idx] = Clamp01(ctx->pms.scale_t[idx]); f32 scale = lerp(1, SLIDER_SCALE_TARGET, ctx->pms.scale_t[idx]); v2 tri_scale = {.x = scale, .y = scale}; @@ -963,8 +963,8 @@ do_picker_mode(ColourPickerCtx *ctx, v2 relative_mouse) ctx->held_idx = PM_RIGHT; if (ctx->held_idx == PM_RIGHT) { - CLAMP(relative_mouse.x, sv.pos.x, sv.pos.x + sv.size.w); - CLAMP(relative_mouse.y, sv.pos.y, sv.pos.y + sv.size.h); + relative_mouse.x = Clamp(relative_mouse.x, sv.pos.x, sv.pos.x + sv.size.w); + relative_mouse.y = Clamp(relative_mouse.y, sv.pos.y, sv.pos.y + sv.size.h); colour.y = (relative_mouse.x - sv.pos.x) / sv.size.w; colour.z = (sv.pos.y + sv.size.h - relative_mouse.y) / sv.size.h; } @@ -976,7 +976,7 @@ do_picker_mode(ColourPickerCtx *ctx, v2 relative_mouse) (ctx->held_idx != -1 && ctx->held_idx == PM_RIGHT); if (should_scale) ctx->pms.scale_t[PM_RIGHT] += SLIDER_SCALE_SPEED * dt_for_frame; else ctx->pms.scale_t[PM_RIGHT] -= SLIDER_SCALE_SPEED * dt_for_frame; - CLAMP01(ctx->pms.scale_t[PM_RIGHT]); + ctx->pms.scale_t[PM_RIGHT] = Clamp01(ctx->pms.scale_t[PM_RIGHT]); f32 slider_scale = lerp(1, SLIDER_SCALE_TARGET, ctx->pms.scale_t[PM_RIGHT]); f32 line_len = 8; @@ -1123,7 +1123,7 @@ colour_picker_end_interact(ColourPickerCtx *ctx, b32 mouse_left_pressed, b32 mou } if (is->active->flags & VariableFlag_UpdateStoredMode) { - ASSERT(is->active->kind == VariableKind_Cycler); + assert(is->active->kind == VariableKind_Cycler); ctx->colour = convert_colour(ctx->colour, ctx->stored_colour_kind, is->active->cycler.state); ctx->stored_colour_kind = is->active->cycler.state; @@ -1283,11 +1283,10 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse break; case CPM_PICKER: do_picker_mode(ctx, ma_relative_mouse); - DrawTextureNPatch(ctx->picker_texture.texture, tnp, ma.rr, (Vector2){0}, - 0, WHITE); + DrawTextureNPatch(ctx->picker_texture.texture, tnp, ma.rr, (Vector2){0}, 0, WHITE); break; case CPM_LAST: - ASSERT(0); + assert(0); break; } DrawRectangleRec(ma.rr, fade(ctx->bg, 1 - ctx->mcs.mode_visible_t)); @@ -1339,7 +1338,7 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse } else { ctx->mcs.mode_visible_t += 2 * dt_for_frame; } - CLAMP01(ctx->mcs.mode_visible_t); + ctx->mcs.mode_visible_t = Clamp01(ctx->mcs.mode_visible_t); Texture *texture = NULL; switch (i) { @@ -1347,7 +1346,7 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse case CPM_SLIDERS: texture = &ctx->slider_texture.texture; break; case CPM_LAST: break; } - ASSERT(texture); + assert(texture); f32 scale = lerp(1, 1.1, ctx->mcs.buttons[i].hover_t); Rect txt_out = scale_rect_centered(mb, (v2){.x = 0.8 * scale, @@ -1378,7 +1377,7 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse if (do_text_button(ctx, ctx->buttons + 1, ctx->mouse_pos, btn_r, str8("Paste"), fg, bg)) { str8 txt = str8_from_c_str((char *)GetClipboardText()); - if (txt.len) { + if (txt.length) { v4 new_colour = normalize_colour(parse_hex_u32(txt)); ctx->colour = convert_colour(new_colour, ColourKind_RGB, ctx->stored_colour_kind); if (ctx->mode == CPM_PICKER) { diff --git a/gen_incs.c b/gen_incs.c @@ -1,23 +1,25 @@ #include <raylib.h> +#include "rstd_compiler.h" +#include "rstd_intrinsics.h" +#include "rstd_types.h" +#include "rstd_core.h" + +#include "config.h" + #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "config.h" - -#define function static #define ISSPACE(a) ((a) == ' ' || (a) == '\t') -typedef struct {uint8_t *data; ptrdiff_t len;} str8; - function str8 read_whole_file(char *name, str8 *mem) { - str8 res = {0}; + str8 result = {0}; FILE *fp = fopen(name, "r"); if (!fp) { @@ -26,34 +28,34 @@ read_whole_file(char *name, str8 *mem) } fseek(fp, 0, SEEK_END); - res.len = ftell(fp); + result.length = ftell(fp); rewind(fp); - if (mem->len < res.len) { + if (mem->length < result.length) { fputs("Not enough space for reading file!\n", stdout); exit(1); } - res.data = mem->data; - res.len = fread(res.data, 1, res.len, fp); + result.data = mem->data; + result.length = fread(result.data, 1, result.length, fp); fclose(fp); - mem->data += res.len; - mem->len -= res.len; + mem->data += result.length; + mem->length -= result.length; - return res; + return result; } /* NOTE: modified from raylib */ function void export_font_as_code(char *font_path, char *output_name, int font_size, str8 mem) { - str8 raw = read_whole_file(font_path, &mem); + str8 raw = read_whole_file(font_path, &mem); Font font = {0}; font.baseSize = font_size; font.glyphCount = 95; font.glyphPadding = 4; - font.glyphs = LoadFontData(raw.data, raw.len, font.baseSize, 0, font.glyphCount, FONT_DEFAULT); + font.glyphs = LoadFontData(raw.data, raw.length, font.baseSize, 0, font.glyphCount, FONT_DEFAULT); if (font.glyphs == NULL) { printf("Failed to load font data: %s\n", font_path); exit(1); @@ -127,19 +129,19 @@ export_font_as_code(char *font_path, char *output_name, int font_size, str8 mem) fclose(fp); } -int +extern s32 main(void) { - static uint8_t mem[2u * 1024u * 1024u]; - str8 smem = {.data = mem, .len = sizeof(mem)}; + local_persist u8 mem[2u * 1024u * 1024u]; + str8 smem = {.data = mem, .length = sizeof(mem)}; SetTraceLogLevel(LOG_NONE); int font_sizes[] = { FONT_SIZE, FONT_SIZE/2 }; for (unsigned int i = 0; i < sizeof(font_sizes)/sizeof(*font_sizes); i++) { str8 tmem = smem; str8 rmem = smem; - size_t tlen = snprintf((char *)tmem.data, tmem.len, "out/lora_sb_%d_inc.h", i); - rmem.len -= (tlen + 1); + size_t tlen = snprintf((char *)tmem.data, tmem.length, "out/lora_sb_%d_inc.h", i); + rmem.length -= (tlen + 1); rmem.data += (tlen + 1); export_font_as_code("assets/Lora-SemiBold.ttf", (char *)tmem.data, font_sizes[i], rmem); } diff --git a/main.c b/main.c @@ -131,11 +131,11 @@ main(s32 argc, char *argv[]) rgb = normalize_colour(parse_hex_u32(str8_from_c_str(argv[i + 1]))); ctx.colour = rgb_to_hsv(rgb); break; - case 'r': rgb.r = parse_f64(str8_from_c_str(argv[i + 1])); CLAMP01(rgb.r); break; - case 'g': rgb.g = parse_f64(str8_from_c_str(argv[i + 1])); CLAMP01(rgb.g); break; - case 'b': rgb.b = parse_f64(str8_from_c_str(argv[i + 1])); CLAMP01(rgb.b); break; - case 'a': rgb.a = parse_f64(str8_from_c_str(argv[i + 1])); CLAMP01(rgb.a); break; - default: usage(argv[0]); break; + case 'r':{rgb.r = parse_f64(str8_from_c_str(argv[i + 1])); rgb.r = Clamp01(rgb.r);}break; + case 'g':{rgb.g = parse_f64(str8_from_c_str(argv[i + 1])); rgb.g = Clamp01(rgb.g);}break; + case 'b':{rgb.b = parse_f64(str8_from_c_str(argv[i + 1])); rgb.b = Clamp01(rgb.b);}break; + case 'a':{rgb.a = parse_f64(str8_from_c_str(argv[i + 1])); rgb.a = Clamp01(rgb.a);}break; + default:{usage(argv[0]);}break; } i++; } else { diff --git a/rstd_compiler.h b/rstd_compiler.h @@ -0,0 +1,69 @@ +/////////////////////////////////// +// NOTE: Compiler Context Cracking +#ifndef RSTD_COMPILER_H +#define RSTD_COMPILER_H + +#if defined(__linux__) + #define OS_LINUX 1 +#elif defined(__APPLE__) + #define OS_MACOS 1 +#elif defined(_WIN32) + #define OS_WINDOWS 1 +#else + #error Unsupported Operating System +#endif + +#if defined(__clang__) + #define COMPILER_CLANG 1 +#elif defined(_MSC_VER) + #define COMPILER_MSVC 1 +#elif defined(__GNUC__) + #define COMPILER_GCC 1 +#else + #error Unsupported Compiler +#endif + +#if COMPILER_MSVC + #if defined(_M_AMD64) + #define ARCH_X64 1 + #elif defined(_M_ARM64) + #define ARCH_ARM64 1 + #else + #error Unsupported Architecture + #endif +#else + #if defined(__x86_64__) + #define ARCH_X64 1 + #elif defined(__aarch64__) + #define ARCH_ARM64 1 + #else + #error Unsupported Architecture + #endif +#endif + +#if !defined(OS_WINDOWS) + #define OS_WINDOWS 0 +#endif +#if !defined(OS_LINUX) + #define OS_LINUX 0 +#endif +#if !defined(OS_MACOS) + #define OS_MACOS 0 +#endif +#if !defined(COMPILER_CLANG) + #define COMPILER_CLANG 0 +#endif +#if !defined(COMPILER_MSVC) + #define COMPILER_MSVC 0 +#endif +#if !defined(COMPILER_GCC) + #define COMPILER_GCC 0 +#endif +#if !defined(ARCH_X64) + #define ARCH_X64 0 +#endif +#if !defined(ARCH_ARM64) + #define ARCH_ARM64 0 +#endif + +#endif /* RSTD_COMPILER_H */ diff --git a/rstd_core.h b/rstd_core.h @@ -0,0 +1,182 @@ +#ifndef RSTD_CORE_H +#define RSTD_CORE_H + +///////////////////////// +// NOTE: Standard Macros +#define function static +#define global static +#define local_persist static + +#ifndef asm + #define asm __asm__ +#endif + +#ifndef typeof + #define typeof __typeof__ +#endif + +#define alignof _Alignof +#define static_assert _Static_assert + +#define countof(a) (sizeof(a) / sizeof(*a)) + +#define arg_list(type, ...) (type []){__VA_ARGS__}, sizeof((type []){__VA_ARGS__}) / sizeof(type) + +#define Abs(a) ((a) < 0 ? (-a) : (a)) +#define Between(x, a, b) ((x) >= (a) && (x) <= (b)) +#define Clamp(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) +#define Clamp01(a) Clamp(a, 0, 1) +#define Min(a, b) ((a) < (b) ? (a) : (b)) +#define Max(a, b) ((a) > (b) ? (a) : (b)) + +#define IsDigit(c) (Between((c), '0', '9')) + +#ifdef _DEBUG + #define assert(c) do { if (!(c)) debugbreak(); } while (0) +#else /* !_DEBUG */ + #define assert(c) +#endif /* !_DEBUG */ + +#define InvalidCodePath assert(0) +#define InvalidDefaultCase default:{ assert(0); }break + +//////////////////////// +// NOTE: Core Functions + +#if COMPILER_MSVC + +function force_inline u32 +clz_u32(u32 a) +{ + u32 result = 32, index; + if (a) { + _BitScanReverse(&index, a); + result = index; + } + return result; +} + +function force_inline u32 +ctz_u32(u32 a) +{ + u32 result = 32, index; + if (a) { + _BitScanForward(&index, a); + result = index; + } + return result; +} + +function force_inline u64 +clz_u64(u64 a) +{ + u64 result = 64, index; + if (a) { + _BitScanReverse64(&index, a); + result = index; + } + return result; +} + +function force_inline u64 +ctz_u64(u64 a) +{ + u64 result = 64, index; + if (a) { + _BitScanForward64(&index, a); + result = index; + } + return result; +} + +#else /* !COMPILER_MSVC */ + +function force_inline u32 +clz_u32(u32 a) +{ + u32 result = 32; + if (a) result = (u32)__builtin_clz(a); + return result; +} + +function force_inline u32 +ctz_u32(u32 a) +{ + u32 result = 32; + if (a) result = (u32)__builtin_ctz(a); + return result; +} + +function force_inline u64 +clz_u64(u64 a) +{ + u64 result = 64; + if (a) result = (u64)__builtin_clzll(a); + return result; +} + +function force_inline u64 +ctz_u64(u64 a) +{ + u64 result = 64; + if (a) result = (u64)__builtin_ctzll(a); + return result; +} + +#endif /* !COMPILER_MSVC */ + +function void * +memory_clear(void *restrict destination, u8 byte, s64 size) +{ + u8 *p = destination; + while (size > 0) p[--size] = byte; + return p; +} + +function void +memory_copy(void *restrict destination, void *restrict source, s64 size) +{ + u8 *s = source, *d = destination; + for (; size > 0; size--) *d++ = *s++; +} + +function force_inline s64 +round_up_to(s64 value, s64 multiple) +{ + s64 result = value; + if (value % multiple != 0) + result += multiple - value % multiple; + return result; +} + +// NOTE: from Hacker's Delight +function force_inline u64 +round_down_power_of_two(u64 a) +{ + u64 result = 0x8000000000000000ULL >> clz_u64(a); + return result; +} + +function force_inline u64 +round_up_power_of_two(u64 a) +{ + u64 result = 0x8000000000000000ULL >> (clz_u64(a - 1) - 1); + return result; +} + + +////////////////////////// +// NOTE: String Functions + +function str8 +str8_from_c_str(char *s) +{ + str8 result = {.data = (u8 *)s}; + if (s) { + while (*s) s++; + result.length = (u8 *)s - result.data; + } + return result; +} + +#endif /* RSTD_CORE_H */ diff --git a/rstd_intrinsics.h b/rstd_intrinsics.h @@ -0,0 +1,68 @@ +/////////////////// +// NOTE: Intrisics +#ifndef RSTD_INTRINSICS_H +#define RSTD_INTRINSICS_H + +#if COMPILER_CLANG || COMPILER_GCC + #define force_inline inline __attribute__((always_inline)) +#elif COMPILER_MSVC + #define force_inline __forceinline +#endif + +#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) + #pragma section(".rdata$", read) + #define read_only __declspec(allocate(".rdata$")) +#elif COMPILER_CLANG + #define read_only __attribute__((section(".rodata"))) +#elif COMPILER_GCC + /* TODO(rnp): not supported on GCC, putting it in rodata causes warnings and writing to + * it doesn't cause a fault */ + #define read_only +#endif + +#if COMPILER_MSVC + + #define alignas(n) __declspec(align(n)) + #define no_return __declspec(noreturn) + + #define likely(x) (x) + #define unlikely(x) (x) + + #define assume(x) __assume(x) + #define debugbreak __debugbreak + #define unreachable() __assume(0) + + #if ARCH_ARM64 + #define cpu_yield() __yield() + #endif + +#else /* !COMPILER_MSVC */ + + #define alignas(n) __attribute__((aligned(n))) + #define no_return __attribute__((noreturn)) + + #define likely(x) (__builtin_expect(!!(x), 1)) + #define unlikely(x) (__builtin_expect(!!(x), 0)) + + #if COMPILER_CLANG + #define assume(x) __builtin_assume(x) + #else + #define assume(x) __attribute__((assume(x))) + #endif + #define unreachable() __builtin_unreachable() + + #if ARCH_ARM64 + /* TODO(rnp)? debuggers just loop here forever and need a manual PC increment (step over) */ + #define debugbreak() asm volatile ("brk 0xf000") + #define cpu_yield() asm volatile ("yield") + #else + #define debugbreak() asm volatile ("int3; nop") + #endif + +#endif /* !COMPILER_MSVC */ + +#if ARCH_X64 + #define cpu_yield() _mm_pause() +#endif + +#endif /* RSTD_INTRINSICS_H */ diff --git a/rstd_types.h b/rstd_types.h @@ -0,0 +1,91 @@ +//////////////////////// +// NOTE: Standard Types + +#ifndef RSTD_TYPES_H +#define RSTD_TYPES_H + +#if COMPILER_MSVC + typedef unsigned __int64 u64; + typedef signed __int64 s64; + typedef unsigned __int32 u32; + typedef signed __int32 s32; + typedef unsigned __int16 u16; + typedef signed __int16 s16; + typedef unsigned __int8 u8; + typedef signed __int8 s8; +#else + typedef __UINT64_TYPE__ u64; + typedef __INT64_TYPE__ s64; + typedef __UINT32_TYPE__ u32; + typedef __INT32_TYPE__ s32; + typedef __UINT16_TYPE__ u16; + typedef __INT16_TYPE__ s16; + typedef __UINT8_TYPE__ u8; + typedef __INT8_TYPE__ s8; + typedef _Float16 f16; +#endif + +typedef u8 b8; +typedef u16 b16; +typedef u32 b32; +typedef u64 b64; +typedef float f32; +typedef double f64; +typedef s64 sptr; +typedef u64 uptr; + +#define U64_MAX (0xFFFFFFFFFFFFFFFFull) +#define U32_MAX (0xFFFFFFFFul) +#define U16_MAX (0xFFFFu) +#define U8_MAX (0xFFu) +#define S64_MAX (0x7FFFFFFFFFFFFFFFll) +#define S32_MAX (0x7FFFFFFFl) +#define S16_MAX (0x7FFF) +#define S8_MAX (0x7F) + +#define GB(a) ((u64)(a) << 30ULL) +#define MB(a) ((u64)(a) << 20ULL) +#define KB(a) ((u64)(a) << 10ULL) + +typedef struct {s64 length; u16 *data;} str16; +typedef struct {s64 length; u8 *data;} str8; + +#define str8(s) (str8){.length = (s64)sizeof(s) - 1, .data = (u8 *)s} +#define str8_comp(s) {sizeof(s) - 1, (u8 *)s} + +#pragma pack(push, 1) +typedef struct { + u16 file_type; + u32 file_size; + u16 reserved_1; + u16 reserved_2; + u32 bitmap_offset; + + u32 size; + s32 width; + s32 height; + u16 planes; + u16 bits_per_pixel; + + u32 compression; + u32 size_of_bitmap; + + s32 horizontal_resolution; + s32 vertical_resolution; + u32 colours_used; + u32 colours_important; + + u32 red_mask; + u32 green_mask; + u32 blue_mask; + u32 alpha_mask; + + u32 colour_space_type; + u32 cie_xyz_triples[9]; + u32 gamma_red; + u32 gamma_green; + u32 gamma_blue; +} rstd_bitmap_header; +#pragma pack(pop) + +#endif /* RSTD_TYPES_H */ diff --git a/util.c b/util.c @@ -1,22 +1,11 @@ /* See LICENSE for copyright details */ #ifndef _UTIL_C_ #define _UTIL_C_ -#include <stddef.h> -#include <stdint.h> - -typedef uint8_t u8; -typedef int32_t s32; -typedef uint32_t u32; -typedef uint32_t b32; -typedef int64_t s64; -typedef uint64_t u64; -typedef float f32; -typedef double f64; -typedef ptrdiff_t sz; - -#define function static -#define global static -#define local_persist static + +#include "rstd_compiler.h" +#include "rstd_intrinsics.h" +#include "rstd_types.h" +#include "rstd_core.h" #include "lora_sb_0_inc.h" #include "lora_sb_1_inc.h" @@ -27,18 +16,10 @@ typedef ptrdiff_t sz; extern char _binary_slider_lerp_glsl_start[]; #endif -#ifndef asm -#define asm __asm__ -#endif - -#define FORCE_INLINE inline __attribute__((always_inline)) - #define fmod_f32(a, b) __builtin_fmodf((a), (b)) -#ifdef __ARM_ARCH_ISA_A64 -#define debugbreak() asm volatile ("brk 0xf000") - -function FORCE_INLINE u64 +#if ARCH_ARM64 +function force_inline u64 rdtsc(void) { register u64 cntvct asm("x0"); @@ -46,24 +27,16 @@ rdtsc(void) return cntvct; } -#elif __x86_64__ -#include <immintrin.h> -#define debugbreak() asm volatile ("int3; nop") - +#elif ARCH_X64 #define rdtsc() __rdtsc() #endif #ifdef _DEBUG -#define ASSERT(c) do { if (!(c)) debugbreak(); } while (0) #define DEBUG_EXPORT #else -#define ASSERT(c) #define DEBUG_EXPORT function #endif -typedef struct { sz len; u8 *data; } str8; -#define str8(s) (str8){.len = sizeof(s) - 1, .data = (u8 *)s} - typedef struct { u8 *data; u32 cap; @@ -295,26 +268,14 @@ typedef struct { enum colour_picker_mode mode; } ColourPickerCtx; -#define countof(a) (s64)(sizeof(a) / sizeof(*a)) - -#define ABS(x) ((x) < 0 ? (-x) : (x)) -#define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define CLAMP(x, a, b) ((x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)) -#define CLAMP01(a) CLAMP(a, 0, 1) - -#define ISDIGIT(a) ((a) >= '0' && (a) <= '9') -#define ISHEX(a) (ISDIGIT(a) || ((a) >= 'a' && (a) <= 'f') || ((a) >= 'A' && (a) <= 'F')) - -#define InvalidDefaultCase default: ASSERT(0); break +#define ISHEX(a) (IsDigit(a) || ((a) >= 'a' && (a) <= 'f') || ((a) >= 'A' && (a) <= 'F')) function v4 rgb_to_hsv(v4 rgb) { v4 hsv = {0}; - f32 M = MAX(rgb.r, MAX(rgb.g, rgb.b)); - f32 m = MIN(rgb.r, MIN(rgb.g, rgb.b)); + f32 M = Max(rgb.r, Max(rgb.g, rgb.b)); + f32 m = Min(rgb.r, Min(rgb.g, rgb.b)); if (M - m > 0) { f32 C = M - m; if (M == rgb.r) { @@ -336,11 +297,11 @@ hsv_to_rgb(v4 hsv) { v4 rgba; f32 k = fmod_f32(5 + hsv.x * 6, 6); - rgba.r = hsv.z - hsv.z * hsv.y * MAX(0, MIN(1, MIN(k, 4 - k))); + rgba.r = hsv.z - hsv.z * hsv.y * Max(0, Min(1, Min(k, 4 - k))); k = fmod_f32(3 + hsv.x * 6, 6); - rgba.g = hsv.z - hsv.z * hsv.y * MAX(0, MIN(1, MIN(k, 4 - k))); + rgba.g = hsv.z - hsv.z * hsv.y * Max(0, Min(1, Min(k, 4 - k))); k = fmod_f32(1 + hsv.x * 6, 6); - rgba.b = hsv.z - hsv.z * hsv.y * MAX(0, MIN(1, MIN(k, 4 - k))); + rgba.b = hsv.z - hsv.z * hsv.y * Max(0, Min(1, Min(k, 4 - k))); rgba.a = hsv.a; return rgba; } @@ -388,14 +349,14 @@ parse_hex_u32(str8 s) u32 res = 0; /* NOTE: skip over '0x' or '0X' */ - if (s.len > 2 && s.data[0] == '0' && (s.data[1] == 'x' || s.data[1] == 'X')) { - s.data += 2; - s.len -= 2; + if (s.length > 2 && s.data[0] == '0' && (s.data[1] == 'x' || s.data[1] == 'X')) { + s.data += 2; + s.length -= 2; } - for (; s.len > 0; s.len--, s.data++) { + for (; s.length > 0; s.length--, s.data++) { res <<= 4; - if (ISDIGIT(*s.data)) { + if (IsDigit(*s.data)) { res |= *s.data - '0'; } else if (ISHEX(*s.data)) { /* NOTE: convert to lowercase first then convert to value */ @@ -413,25 +374,25 @@ parse_f64(str8 s) { f64 integral = 0, fractional = 0, sign = 1; - if (s.len && *s.data == '-') { + if (s.length && *s.data == '-') { sign *= -1; s.data++; - s.len--; + s.length--; } - while (s.len && ISDIGIT(*s.data)) { + while (s.length && IsDigit(*s.data)) { integral *= 10; integral += *s.data - '0'; s.data++; - s.len--; + s.length--; } - if (s.len && *s.data == '.') { s.data++; s.len--; } + if (s.length && *s.data == '.') { s.data++; s.length--; } - while (s.len) { - ASSERT(s.data[s.len - 1] != '.'); + while (s.length) { + assert(s.data[s.length - 1] != '.'); fractional *= 0.1f; - fractional += (s.data[--s.len] - '0') * 0.1f; + fractional += (s.data[--s.length] - '0') * 0.1f; } f64 result = sign * (integral + fractional); @@ -439,17 +400,6 @@ parse_f64(str8 s) return result; } -function str8 -str8_from_c_str(char *s) -{ - str8 result = {.data = (u8 *)s}; - if (s) { - while (*s) s++; - result.len = (u8 *)s - result.data; - } - return result; -} - function void stream_append_byte(Stream *s, u8 b) { @@ -473,9 +423,9 @@ stream_append_hex_u8(Stream *s, u32 n) function void stream_append_str8(Stream *s, str8 str) { - s->errors |= (s->cap - s->widx) < str.len; + s->errors |= (s->cap - s->widx) < str.length; if (!s->errors) { - for (sz i = 0; i < str.len; i++) + for (s64 i = 0; i < str.length; i++) s->data[s->widx++] = str.data[i]; } } @@ -487,7 +437,7 @@ stream_append_u64(Stream *s, u64 n) u8 *end = tmp + sizeof(tmp); u8 *beg = end; do { *--beg = '0' + (n % 10); } while (n /= 10); - stream_append_str8(s, (str8){.len = end - beg, .data = beg}); + stream_append_str8(s, (str8){.length = end - beg, .data = beg}); } function void