colourpicker

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

Commit: 5ed25eb34f0e6be9f3a1e7a44799eb4aa161a0b4
Parent: 47bf2148cdb71c7fd1ac9bfc15f8b19faf432227
Author: Randy Palamar
Date:   Wed,  9 Oct 2024 22:36:04 -0600

drop raylib/stdio text formatting

Diffstat:
Mcolourpicker.c | 38++++++++++++++++++++++++++------------
Mutil.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 12 deletions(-)

diff --git a/colourpicker.c b/colourpicker.c @@ -1,7 +1,6 @@ /* See LICENSE for copyright details */ #include <raylib.h> #include <rlgl.h> -#include <stdio.h> #include "util.c" @@ -303,10 +302,9 @@ set_text_input_idx(ColourPickerCtx *ctx, enum input_indices idx, Rect r, v2 mous if (ctx->is.idx != (i32)idx) parse_and_store_text_input(ctx); + Stream in = {.data = ctx->is.buf, .cap = ARRAY_COUNT(ctx->is.buf)}; if (idx == INPUT_HEX) { - Color hc = colour_from_normalized(get_formatted_colour(ctx, CM_RGB)); - ctx->is.buf_len = snprintf((char *)ctx->is.buf, ARRAY_COUNT(ctx->is.buf), - "%02x%02x%02x%02x", hc.r, hc.g, hc.b, hc.a); + stream_append_colour(&in, colour_from_normalized(get_formatted_colour(ctx, CM_RGB))); } else { f32 fv = 0; switch (idx) { @@ -316,8 +314,9 @@ set_text_input_idx(ColourPickerCtx *ctx, enum input_indices idx, Rect r, v2 mous case INPUT_A: fv = ctx->colour.a; break; default: break; } - ctx->is.buf_len = snprintf((char *)ctx->is.buf, ARRAY_COUNT(ctx->is.buf), "%0.02f", fv); + stream_append_f64(&in, fv, 100); } + ctx->is.buf_len = in.widx; ctx->is.idx = idx; ctx->is.cursor = -1; @@ -551,7 +550,10 @@ do_slider(ColourPickerCtx *ctx, Rect r, i32 label_idx, v2 relative_mouse) set_text_input_idx(ctx, label_idx + 1, vr, relative_mouse); if (ctx->is.idx != (label_idx + 1)) { - s8 value = {.len = 4, .data = (u8 *)TextFormat("%0.02f", current)}; + u8 vbuf[4]; + Stream vstream = {.data = vbuf, .cap = ARRAY_COUNT(vbuf)}; + stream_append_f64(&vstream, current, 100); + s8 value = {.len = 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); @@ -584,8 +586,10 @@ do_status_bar(ColourPickerCtx *ctx, Rect r, v2 relative_mouse) if (mouse_mask & MOUSE_LEFT) step_colour_mode(ctx, 1); if (mouse_mask & MOUSE_RIGHT) step_colour_mode(ctx, -1); - Color hc = colour_from_normalized(get_formatted_colour(ctx, CM_RGB)); - s8 hex = {.len = 8, .data = (u8 *)TextFormat("%02x%02x%02x%02x", hc.r, hc.g, hc.b, hc.a)}; + u8 hbuf[8]; + Stream hstream = {.data = hbuf, .cap = ARRAY_COUNT(hbuf)}; + stream_append_colour(&hstream, colour_from_normalized(get_formatted_colour(ctx, CM_RGB))); + s8 hex = {.len = hstream.widx, .data = hbuf}; s8 label = s8("RGB: "); v2 label_size = measure_text(ctx->font, label); @@ -602,8 +606,9 @@ do_status_bar(ColourPickerCtx *ctx, Rect r, v2 relative_mouse) if (!hex_collides && ctx->is.idx == INPUT_HEX && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { set_text_input_idx(ctx, -1, hex_r, relative_mouse); - hc = colour_from_normalized(get_formatted_colour(ctx, CM_RGB)); - hex.data = (u8 *)TextFormat("%02x%02x%02x%02x", hc.r, hc.g, hc.b, hc.a); + hstream.widx = 0; + stream_append_colour(&hstream, colour_from_normalized(get_formatted_colour(ctx, CM_RGB))); + hex.len = hstream.widx; } if (hex_collides && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) @@ -987,6 +992,10 @@ do_picker_mode(ColourPickerCtx *ctx, v2 relative_mouse) END_CYCLE_COUNT(CC_DO_PICKER); } + +#ifdef _DEBUG +#include <stdio.h> +#endif static void debug_dump_info(ColourPickerCtx *ctx) { @@ -1223,8 +1232,13 @@ do_colour_picker(ColourPickerCtx *ctx, f32 dt, Vector2 window_pos, Vector2 mouse Rect btn_r = mb; btn_r.size.h *= 0.46; - if (do_text_button(ctx, ctx->buttons + 0, ctx->mouse_pos, btn_r, s8("Copy"), fg, bg)) - SetClipboardText(TextFormat("%02x%02x%02x%02x", bg.r, bg.g, bg.b, bg.a)); + if (do_text_button(ctx, ctx->buttons + 0, ctx->mouse_pos, btn_r, s8("Copy"), fg, bg)) { + /* NOTE: SetClipboardText needs a NUL terminated string */ + u8 cbuf[9] = {0}; + Stream cstream = {.data = cbuf, .cap = ARRAY_COUNT(cbuf) - 1}; + stream_append_colour(&cstream, bg); + SetClipboardText((char *)cbuf); + } btn_r.pos.y += 0.54 * mb.size.h; if (do_text_button(ctx, ctx->buttons + 1, ctx->mouse_pos, btn_r, s8("Paste"), fg, bg)) { diff --git a/util.c b/util.c @@ -29,6 +29,7 @@ typedef int32_t i32; typedef uint32_t u32; typedef uint32_t b32; typedef int64_t i64; +typedef uint64_t u64; typedef float f32; typedef double f64; typedef ptrdiff_t size; @@ -36,6 +37,14 @@ typedef ptrdiff_t size; typedef struct { size len; u8 *data; } s8; #define s8(s) (s8){.len = sizeof(s) - 1, .data = (u8 *)s} +typedef struct { + u8 *data; + u32 cap; + u32 widx; + i32 fd; + b32 errors; +} Stream; + typedef union { struct { u32 w, h; }; struct { u32 x, y; }; @@ -405,4 +414,79 @@ cstr_to_s8(char *s) return result; } +static void +stream_append_byte(Stream *s, u8 b) +{ + s->errors |= s->widx + 1 > s->cap; + if (!s->errors) + s->data[s->widx++] = b; +} + +static void +stream_append_hex_u8(Stream *s, u32 n) +{ + static u8 hex[16] = {"0123456789abcdef"}; + s->errors |= (s->cap - s->widx) < 2; + if (!s->errors) { + s->data[s->widx + 1] = hex[(n >> 0) & 0x0f]; + s->data[s->widx + 0] = hex[(n >> 4) & 0x0f]; + s->widx += 2; + } +} + +static void +stream_append_s8(Stream *s, s8 str) +{ + s->errors |= (s->cap - s->widx) < str.len; + if (!s->errors) { + for (size i = 0; i < str.len; i++) + s->data[s->widx++] = str.data[i]; + } +} + +static void +stream_append_u64(Stream *s, u64 n) +{ + u8 tmp[64]; + u8 *end = tmp + sizeof(tmp); + u8 *beg = end; + do { *--beg = '0' + (n % 10); } while (n /= 10); + stream_append_s8(s, (s8){.len = end - beg, .data = beg}); +} + +static void +stream_append_f64(Stream *s, f64 f, i64 prec) +{ + if (f < 0) { + stream_append_byte(s, '-'); + f *= -1; + } + + /* NOTE: round last digit */ + f += 0.5f / prec; + + if (f >= (f64)(-1UL >> 1)) { + stream_append_s8(s, s8("inf")); + } else { + u64 integral = f; + u64 fraction = (f - integral) * prec; + stream_append_u64(s, integral); + stream_append_byte(s, '.'); + for (u64 i = prec / 10; i > 1; i /= 10) { + if (i > fraction) + stream_append_byte(s, '0'); + } + stream_append_u64(s, fraction); + } +} + +static void +stream_append_colour(Stream *s, Color c) +{ + stream_append_hex_u8(s, c.r); + stream_append_hex_u8(s, c.g); + stream_append_hex_u8(s, c.b); + stream_append_hex_u8(s, c.a); +} + #endif /* _UTIL_C_ */