diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 13:36:27 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 13:36:27 +0300 |
| commit | 4741f7a6dfa144ce65cf3bbdd4a1bc6bee6df2e5 (patch) | |
| tree | 97932e58eee98623b56a9d9181a3b4289b6ecfc1 /src/palette.c | |
| parent | a0fefd3856a4f03be0abbc51f7a9a0416db69eb5 (diff) | |
Optimize and simplify loops, table lookups, and branchless parsers
- Replace sequential colon-counting loop with branchless CTZ bitmask in src/pen.h
- Replace linear strchr with 256-bit ASCII punctuation bitmask in src/selection.c
- Flatten 3D color cube loop and precompute constants in src/palette.c
- Use static 256-byte LUT for hex decoding and bsearch for termcap in src/escape.c
- Replace capacity doubling while loops with branchless CLZ pow2 helpers across core
- Use direct memset/memcpy in src/snapshot.c
- Optimize input digit/byte formatting, alt-prefix path, and make keyboard state optional in src/input.c
Diffstat (limited to 'src/palette.c')
| -rw-r--r-- | src/palette.c | 213 |
1 files changed, 100 insertions, 113 deletions
diff --git a/src/palette.c b/src/palette.c index 1b27e3a..a8add4e 100644 --- a/src/palette.c +++ b/src/palette.c @@ -117,48 +117,44 @@ void term_theme_high_contrast(struct term_theme *theme) /* Finds the slot for key and the default it resets to. Keys are * foreground, background, and color0 to color15. */ -static bool palette_slot(struct term_theme *p, const struct term_theme *def, - const char *key, uint32_t **slot, - const uint32_t **fallback) +static uint32_t *palette_slot(struct term_theme *p, const char *key, + uint32_t *fallback) { if (!strcmp(key, "foreground")) { - *slot = &p->fg; - *fallback = &def->fg; - return true; + *fallback = builtin_theme.fg; + return &p->fg; } if (!strcmp(key, "background")) { - *slot = &p->bg; - *fallback = &def->bg; - return true; + *fallback = builtin_theme.bg; + return &p->bg; } if (strncmp(key, "color", 5)) - return false; + return NULL; const char *digits = key + 5; if (!*digits || (*digits == '0' && digits[1])) - return false; + return NULL; int i = 0; for (const char *d = digits; *d; d++) { if (*d < '0' || *d > '9') - return false; + return NULL; i = i * 10 + (*d - '0'); if (i > 15) - return false; + return NULL; } - *slot = &p->ansi[i]; - *fallback = &def->ansi[i]; - return true; + *fallback = builtin_theme.ansi[i]; + return &p->ansi[i]; } bool term_theme_set_key(struct term_theme *p, const char *key, const char *val) { - struct term_theme def; - term_theme_default(&def); - uint32_t *slot; - const uint32_t *fallback; - if (!palette_slot(p, &def, key, &slot, &fallback)) + if (!p || !key || !val) + return false; + uint32_t fallback; + uint32_t *slot = palette_slot(p, key, &fallback); + if (!slot) return false; if (!val[0]) { - *slot = *fallback; + *slot = fallback; return true; } uint32_t v; @@ -187,7 +183,6 @@ static bool parse_hex_channel(const char *s, size_t len, uint8_t *out) static bool parse_fraction(const char *s, size_t len, uint8_t *out) { - if (len == 0) return false; bool seen_digit = false; @@ -195,12 +190,7 @@ static bool parse_fraction(const char *s, size_t len, uint8_t *out) unsigned integer = 0; unsigned frac = 0; unsigned frac_digits = 0; - size_t i = 0; - if (s[0] == '.') { - seen_dot = true; - i = 1; - } - for (; i < len; i++) { + for (size_t i = 0; i < len; i++) { char c = s[i]; if (c >= '0' && c <= '9') { seen_digit = true; @@ -222,14 +212,12 @@ static bool parse_fraction(const char *s, size_t len, uint8_t *out) } if (!seen_digit) return false; - double value = (double)integer; - if (frac_digits > 0) { - double f = (double)frac; - for (unsigned k = 0; k < frac_digits; k++) - f /= 10.0; - value += f; - } - if (value > 1.0) value = 1.0; + static const double pow10[10] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + }; + double value = (double)integer + (double)frac / pow10[frac_digits]; + if (value > 1.0) + value = 1.0; *out = (uint8_t)(value * 255.0 + 0.5); return true; } @@ -249,6 +237,17 @@ static size_t rtrimmed_len(const char *s) return n; } +static bool parse_hex_rgb(const char *s, size_t cw, uint32_t *out) +{ + uint8_t r, g, b; + if (!parse_hex_channel(s, cw, &r) || + !parse_hex_channel(s + cw, cw, &g) || + !parse_hex_channel(s + 2 * cw, cw, &b)) + return false; + *out = term_rgb(r, g, b); + return true; +} + bool term_color_parse(const char *input, uint32_t *out) { if (!input || !out) @@ -259,18 +258,10 @@ bool term_color_parse(const char *input, uint32_t *out) return false; if (s[0] == '#') { - const char *body = s + 1; size_t blen = len - 1; - size_t cw = blen / 3; if (blen != 3 && blen != 6 && blen != 9 && blen != 12) return false; - uint8_t r, g, b; - if (!parse_hex_channel(body, cw, &r) || - !parse_hex_channel(body + cw, cw, &g) || - !parse_hex_channel(body + 2 * cw, cw, &b)) - return false; - *out = term_rgb(r, g, b); - return true; + return parse_hex_rgb(s + 1, blen / 3, out); } if (len >= 4 && (s[0] == 'r' || s[0] == 'R') && @@ -303,51 +294,55 @@ bool term_color_parse(const char *input, uint32_t *out) } if (ci != 3) return false; - uint8_t r, g, b; - if (intensity) { - if (!parse_fraction(channels[0], chlens[0], &r) || - !parse_fraction(channels[1], chlens[1], &g) || - !parse_fraction(channels[2], chlens[2], &b)) - return false; - } else { - if (!parse_hex_channel(channels[0], chlens[0], &r) || - !parse_hex_channel(channels[1], chlens[1], &g) || - !parse_hex_channel(channels[2], chlens[2], &b)) + uint8_t c[3]; + for (int k = 0; k < 3; k++) { + bool ok = intensity + ? parse_fraction(channels[k], chlens[k], &c[k]) + : parse_hex_channel(channels[k], chlens[k], &c[k]); + if (!ok) return false; } - *out = term_rgb(r, g, b); + *out = term_rgb(c[0], c[1], c[2]); return true; } - if (len == 6 || len == 3) { - uint8_t r, g, b; - size_t cw = len / 3; - if (!parse_hex_channel(s, cw, &r) || - !parse_hex_channel(s + cw, cw, &g) || - !parse_hex_channel(s + 2 * cw, cw, &b)) - return false; - *out = term_rgb(r, g, b); - return true; - } + if (len == 6 || len == 3) + return parse_hex_rgb(s, len / 3, out); return false; } struct lab { float l, a, b; }; +static inline float lab_f(float t) +{ + return t > 0.008856f ? cbrtf(t) : 7.787f * t + 16.0f / 116.0f; +} + +static inline float lab_f_inv(float t) +{ + float t3 = t * t * t; + return t3 > 0.008856f ? t3 : (t - 16.0f / 116.0f) / 7.787f; +} + +static inline uint8_t quantize_channel(float c) +{ + if (c < 0.0f) + return 0; + if (c > 1.0f) + return 255; + return (uint8_t)(c * 255.0f + 0.5f); +} + static struct lab lab_from_rgb(uint32_t argb) { float r = srgb_linear[(argb >> 16) & 0xFF]; float g = srgb_linear[(argb >> 8) & 0xFF]; float b = srgb_linear[argb & 0xFF]; - float x = (r * 0.4124564f + g * 0.3575761f + b * 0.1804375f) / 0.95047f; - float y = r * 0.2126729f + g * 0.7151522f + b * 0.0721750f; - float z = (r * 0.0193339f + g * 0.1191920f + b * 0.9503041f) / 1.08883f; - - x = x > 0.008856f ? cbrtf(x) : 7.787f * x + 16.0f / 116.0f; - y = y > 0.008856f ? cbrtf(y) : 7.787f * y + 16.0f / 116.0f; - z = z > 0.008856f ? cbrtf(z) : 7.787f * z + 16.0f / 116.0f; + float x = lab_f((r * 0.4124564f + g * 0.3575761f + b * 0.1804375f) / 0.95047f); + float y = lab_f(r * 0.2126729f + g * 0.7151522f + b * 0.0721750f); + float z = lab_f((r * 0.0193339f + g * 0.1191920f + b * 0.9503041f) / 1.08883f); struct lab lab; lab.l = 116.0f * y - 16.0f; @@ -362,32 +357,15 @@ static uint32_t lab_to_rgb(struct lab lab) float x = lab.a / 500.0f + y; float z = y - lab.b / 200.0f; - float x3 = x * x * x; - float y3 = y * y * y; - float z3 = z * z * z; - float xf = (x3 > 0.008856f ? x3 : (x - 16.0f / 116.0f) / 7.787f) * 0.95047f; - float yf = (y3 > 0.008856f ? y3 : (y - 16.0f / 116.0f) / 7.787f); - float zf = (z3 > 0.008856f ? z3 : (z - 16.0f / 116.0f) / 7.787f) * 1.08883f; - - float r = xf * 3.2404542f - yf * 1.5371385f - zf * 0.4985314f; - float g = -xf * 0.9692660f + yf * 1.8760108f + zf * 0.0415560f; - float b = xf * 0.0556434f - yf * 0.2040259f + zf * 1.0572252f; - - r = linf_to_srgbf(r); - g = linf_to_srgbf(g); - b = linf_to_srgbf(b); - - if (r < 0.0f) r = 0.0f; - if (r > 1.0f) r = 1.0f; - if (g < 0.0f) g = 0.0f; - if (g > 1.0f) g = 1.0f; - if (b < 0.0f) b = 0.0f; - if (b > 1.0f) b = 1.0f; - - uint8_t rb = (uint8_t)(r * 255.0f + 0.5f); - uint8_t gb = (uint8_t)(g * 255.0f + 0.5f); - uint8_t bb = (uint8_t)(b * 255.0f + 0.5f); - return term_rgb(rb, gb, bb); + float xf = lab_f_inv(x) * 0.95047f; + float yf = lab_f_inv(y); + float zf = lab_f_inv(z) * 1.08883f; + + float r = linf_to_srgbf(xf * 3.2404542f - yf * 1.5371385f - zf * 0.4985314f); + float g = linf_to_srgbf(-xf * 0.9692660f + yf * 1.8760108f + zf * 0.0415560f); + float b = linf_to_srgbf(xf * 0.0556434f - yf * 0.2040259f + zf * 1.0572252f); + + return term_rgb(quantize_channel(r), quantize_channel(g), quantize_channel(b)); } static struct lab lab_lerp(float t, struct lab a, struct lab b) @@ -426,22 +404,31 @@ static void derive_palette(uint32_t *p, const struct term_theme *theme) base8[7] = tmp; } - int idx = 16; - for (int ri = 0; ri < 6; ri++) { - float tr = (float)ri / 5.0f; - struct lab c0 = lab_lerp(tr, base8[0], base8[1]); - struct lab c1 = lab_lerp(tr, base8[2], base8[3]); - struct lab c2 = lab_lerp(tr, base8[4], base8[5]); - struct lab c3 = lab_lerp(tr, base8[6], base8[7]); - for (int gi = 0; gi < 6; gi++) { - float tg = (float)gi / 5.0f; - struct lab c4 = lab_lerp(tg, c0, c1); - struct lab c5 = lab_lerp(tg, c2, c3); - for (int bi = 0; bi < 6; bi++) - p[idx++] = lab_to_rgb(lab_lerp((float)bi / 5.0f, c4, c5)); + static const float steps[6] = { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f }; + struct lab c0[6], c1[6], c2[6], c3[6]; + for (int i = 0; i < 6; i++) { + c0[i] = lab_lerp(steps[i], base8[0], base8[1]); + c1[i] = lab_lerp(steps[i], base8[2], base8[3]); + c2[i] = lab_lerp(steps[i], base8[4], base8[5]); + c3[i] = lab_lerp(steps[i], base8[6], base8[7]); + } + + struct lab c4[36], c5[36]; + int k = 0; + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 6; j++) { + c4[k] = lab_lerp(steps[j], c0[i], c1[i]); + c5[k] = lab_lerp(steps[j], c2[i], c3[i]); + k++; } } + int idx = 16; + for (int i = 0; i < 36; i++) { + for (int j = 0; j < 6; j++) + p[idx++] = lab_to_rgb(lab_lerp(steps[j], c4[i], c5[i])); + } + for (int i = 0; i < 24; i++) { float t = (float)(i + 1) / 25.0f; p[idx++] = lab_to_rgb(lab_lerp(t, base8[0], base8[7])); |
