Something went wrong. Try again.
extremely opinionated bar. you don't want to use this
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281#include "bar/renderer.h"#include "bar/gfx.h"
#include "bar/config.h"#include "bar/modules.h"
#include <math.h>#include <stdlib.h>#include <string.h>#include <time.h>
struct renderer { struct fcft_font *font_small; struct fcft_font *font_large;
short max_segments; float *anim_w; float *anim_v;
struct timespec last_render_ts;};
static int compute_baseline(int my, int mh, struct fcft_font *font){ return my + (mh + font->ascent - font->descent) / 2;}
static int measure_segment(const segment_t *s, struct fcft_font *small, struct fcft_font *large){ struct fcft_font *f = s->font ? s->font : large; if (!s->is_multi_line) return measure_text(f, s->text); int a = measure_text(small, s->top); int b = measure_text(f, s->bottom); return b > a ? b : a;}
renderer_t *renderer_init(short max_segments){ renderer_t *r = calloc(1, sizeof *r); if (!r) return nullptr;
r->max_segments = max_segments; r->anim_w = calloc(max_segments, sizeof(float)); r->anim_v = calloc(max_segments, sizeof(float));
if (!r->anim_w || !r->anim_v) { if (r->anim_w) free(r->anim_w); if (r->anim_v) free(r->anim_v); return free(r), nullptr; }
for (short i = 0; i < max_segments; i++) { r->anim_w[i] = -1.0f; r->anim_v[i] = 0.0f; }
clock_gettime(CLOCK_MONOTONIC, &r->last_render_ts);
if (!fcft_init(FCFT_LOG_COLORIZE_NEVER, false, FCFT_LOG_CLASS_NONE)) { return renderer_destroy(r), nullptr; }
const char *small[] = {g_config.font_small, "monospace:size=11", nullptr}; const char *large[] = {g_config.font_large, "monospace:size=13.5", nullptr};
r->font_small = fcft_from_name(1, small, nullptr); r->font_large = fcft_from_name(1, large, nullptr);
if (!r->font_small || !r->font_large) { renderer_destroy(r); return nullptr; }
return r;}
bool renderer_draw(renderer_t *r, platform_t *pf, const segment_t *segments, short count){ if (!platform_ready(pf)) return true;
pixman_image_t *dest = nullptr; int bw = 0, bh = 0;
if (!platform_begin_frame(pf, &dest, &bw, &bh)) return false;
if (count > r->max_segments) count = r->max_segments;
struct timespec now_ts; clock_gettime(CLOCK_MONOTONIC, &now_ts); float dt = (float)(now_ts.tv_sec - r->last_render_ts.tv_sec) + (float)(now_ts.tv_nsec - r->last_render_ts.tv_nsec) * 1e-9f; r->last_render_ts = now_ts;
if (dt > 0.1f) dt = 0.1f;
bool animating = false; const float tension = 300.0f; const float omega = sqrtf(tension);
float *targets = malloc(r->max_segments * sizeof(float)); bool *active = calloc(r->max_segments, sizeof(bool)); if (!targets || !active) { if (targets) free(targets); if (active) free(active); return false; }
for (short i = 0; i < r->max_segments; i++) { targets[i] = 0.0f; }
const segment_t **lookup = calloc(r->max_segments, sizeof(segment_t *)); if (!lookup) { free(targets); free(active); return false; }
for (short i = 0; i < count; i++) { const segment_t *seg = &segments[i]; int anim_idx = (seg->module_id * MAX_SEGMENTS_PER_MODULE) + seg->seg_id; if (anim_idx >= r->max_segments) continue;
active[anim_idx] = true; lookup[anim_idx] = seg; targets[anim_idx] = (float)measure_segment(seg, r->font_small, r->font_large);
if (r->anim_w[anim_idx] < 0.0f) { r->anim_w[anim_idx] = 0.0f; r->anim_v[anim_idx] = 0.0f; } }
for (short i = 0; i < r->max_segments; i++) { if (r->anim_w[i] < 0.0f) continue;
float target = targets[i]; float x0 = r->anim_w[i]; float v0 = r->anim_v[i];
float A = x0 - target; float B = v0 + omega * A; float exp_term = expf(-omega * dt);
float next_w = target + (A + B * dt) * exp_term; float next_v = (B - omega * (A + B * dt)) * exp_term;
if (fabsf(next_w - target) < 0.05f && fabsf(next_v) < 0.05f) { r->anim_w[i] = target; r->anim_v[i] = 0.0f; } else { r->anim_w[i] = next_w; r->anim_v[i] = next_v; animating = true; }
if (!active[i] && r->anim_w[i] <= 0.0f) { r->anim_w[i] = -1.0f; r->anim_v[i] = 0.0f; } }
int total = 0; for (short i = 0; i < r->max_segments; i++) { if (r->anim_w[i] < 0.0f) continue;
int pad_l = g_config.module_padding_x; int pad_r = g_config.module_padding_x; bool connect_prev = false;
if (lookup[i]) { pad_l = lookup[i]->connect_prev ? g_config.inner_padding : g_config.module_padding_x; pad_r = lookup[i]->connect_next ? g_config.inner_padding : g_config.module_padding_x; connect_prev = lookup[i]->connect_prev; }
if (!connect_prev) total += g_config.module_gap;
total += (int)r->anim_w[i] + pad_l + pad_r; }
memset(pixman_image_get_data(dest), 0, (size_t)bw * (size_t)bh * 4); int x = (bw - total) / 2;
for (short i = 0; i < r->max_segments; i++) { if (r->anim_w[i] < 0.0f) continue;
int w = (int)r->anim_w[i]; int pad_l = g_config.module_padding_x; int pad_r = g_config.module_padding_x; bool connect_prev = false;
const segment_t *seg = lookup[i]; if (!seg) { if (!connect_prev) x += g_config.module_gap; x += w + pad_l + pad_r; continue; }
struct fcft_font *f = seg->font ? seg->font : r->font_large;
int rl = seg->connect_prev ? 0 : g_config.module_radius; int rr = seg->connect_next ? 0 : g_config.module_radius;
pad_l = seg->connect_prev ? g_config.inner_padding : g_config.module_padding_x; pad_r = seg->connect_next ? g_config.inner_padding : g_config.module_padding_x; connect_prev = seg->connect_prev;
if (!connect_prev) x += g_config.module_gap;
fill_pill(dest, x, 0, w + pad_l + pad_r, bh, rl, rr, seg->bg, seg->bg_image);
if (seg->is_multi_line) { int top_x = x + pad_l + (seg->align_right ? (w - measure_text(r->font_small, seg->top)) : 0);
if (seg->top) render_text(dest, r->font_small, seg->top, top_x, (bh / 2) - 4, seg->top_fg); if (seg->bottom) render_text(dest, f, seg->bottom, x + pad_l, (bh / 2) + 14, seg->bottom_fg); } else { render_text(dest, f, seg->text, x + pad_l, compute_baseline(0, bh, f), seg->fg); }
x += w + pad_l + pad_r; }
free(targets); free(active); free(lookup);
platform_end_frame(pf); return animating;}
void renderer_destroy(renderer_t *r){ if (!r) return; if (r->font_small) fcft_destroy(r->font_small); if (r->font_large) fcft_destroy(r->font_large); if (r->anim_w) free(r->anim_w); if (r->anim_v) free(r->anim_v); fcft_fini(); free(r);}