Skip to main content

max / audiofiles

Cache theme-derived colors instead of blending per accessor call The row-stripe, selection, piano-key, and trim-wash accessors recomputed an OKLab blend on every call -- hundreds per frame. Blend them once into a cached DerivedColors struct kept in lockstep with THEME via a single install_theme() funnel; the plain accessors were already lock reads. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-23 20:21 UTC
Commit: 6ad3ec7e3a1b2acc7dc7dd1ab674ecdb821bbd20
Parent: 5a81b45
1 file changed, +50 insertions, -13 deletions
@@ -134,6 +134,49 @@ pub use makeover::ThemeMeta;
134 134
135 135 static THEME: LazyLock<RwLock<ThemeColors>> = LazyLock::new(|| RwLock::new(ThemeColors::default()));
136 136
137 + /// Colors derived from the base palette via OKLab blends (row striping,
138 + /// selection highlight, piano keys, the trim wash).
139 + ///
140 + /// These were previously recomputed on every accessor call — an OKLab blend per
141 + /// call, hundreds of times per frame for row striping and selection alone. They
142 + /// depend only on the palette, so they are now blended once whenever the theme
143 + /// changes and read straight from here. Kept in lockstep with `THEME` by routing
144 + /// every theme install through [`install_theme`].
145 + #[derive(Debug, Clone)]
146 + struct DerivedColors {
147 + row_even: Color32,
148 + selection: Color32,
149 + piano_white_key: Color32,
150 + piano_black_key: Color32,
151 + trim_mute_overlay: Color32,
152 + }
153 +
154 + impl DerivedColors {
155 + fn from_base(t: &ThemeColors) -> Self {
156 + let bg = t.surface_page;
157 + Self {
158 + row_even: lerp_color(t.surface_page, t.surface_overlay, 0.3),
159 + selection: lerp_color(t.surface_page, t.action, 0.3),
160 + piano_white_key: lerp_color(t.surface_raised, Color32::WHITE, 0.7),
161 + piano_black_key: lerp_color(t.surface_raised, Color32::BLACK, 0.7),
162 + // Dim toward the theme's own background rather than hardcoded black,
163 + // so the trimmed-region wash reads correctly on light themes too.
164 + trim_mute_overlay: Color32::from_rgba_unmultiplied(bg.r(), bg.g(), bg.b(), 160),
165 + }
166 + }
167 + }
168 +
169 + static DERIVED: LazyLock<RwLock<DerivedColors>> =
170 + LazyLock::new(|| RwLock::new(DerivedColors::from_base(&ThemeColors::default())));
171 +
172 + /// Install a freshly parsed theme, recomputing the cached derived colors so the
173 + /// two never drift. Every write to `THEME` goes through here.
174 + fn install_theme(colors: ThemeColors) {
175 + let derived = DerivedColors::from_base(&colors);
176 + *THEME.write() = colors;
177 + *DERIVED.write() = derived;
178 + }
179 +
137 180 // --- Derived color helpers ---
138 181 //
139 182 // The color math lives once in `makeover` (OKLab blends + WCAG contrast),
@@ -180,8 +223,7 @@ pub fn surface_sunken() -> Color32 {
180 223
181 224 /// Even-row background, derived by blending primary and secondary.
182 225 pub fn row_even() -> Color32 {
183 - let t = THEME.read();
184 - lerp_color(t.surface_page, t.surface_overlay, 0.3)
226 + DERIVED.read().row_even
185 227 }
186 228 /// Odd-row background (same as primary).
187 229 pub fn row_odd() -> Color32 {
@@ -193,8 +235,7 @@ pub fn hover_surface() -> Color32 {
193 235 }
194 236 /// Selected-row background, derived by blending primary with accent blue.
195 237 pub fn selection() -> Color32 {
196 - let t = THEME.read();
197 - lerp_color(t.surface_page, t.action, 0.3)
238 + DERIVED.read().selection
198 239 }
199 240
200 241 /// Primary text color.
@@ -256,22 +297,18 @@ pub fn grid_row_spacing() -> f32 {
256 297
257 298 /// Piano white key — always a light shade regardless of theme variant.
258 299 pub fn piano_white_key() -> Color32 {
259 - lerp_color(THEME.read().surface_raised, Color32::WHITE, 0.7)
300 + DERIVED.read().piano_white_key
260 301 }
261 302 /// Piano black key — always a dark shade regardless of theme variant.
262 303 pub fn piano_black_key() -> Color32 {
263 - lerp_color(THEME.read().surface_raised, Color32::BLACK, 0.7)
304 + DERIVED.read().piano_black_key
264 305 }
265 306
266 307 /// Semi-opaque overlay used by the edit panel's trim preview (C-1) to mark
267 308 /// regions that will be removed. Painted on top of the rendered waveform; the
268 309 /// underlying peaks stay partly visible so the user retains spatial reference.
269 310 pub fn trim_mute_overlay() -> Color32 {
270 - // Dim toward the theme's own background rather than hardcoded black, so the
271 - // trimmed-region wash reads correctly on light themes too (a black overlay
272 - // assumes a dark base).
273 - let bg = THEME.read().surface_page;
274 - Color32::from_rgba_unmultiplied(bg.r(), bg.g(), bg.b(), 160)
311 + DERIVED.read().trim_mute_overlay
275 312 }
276 313
277 314 // --- Theme discovery ---
@@ -509,7 +546,7 @@ pub fn set_theme(id: &str) {
509 546 if *bundled_id == id {
510 547 match parse_theme(content) {
511 548 Ok(colors) => {
512 - *THEME.write() = colors;
549 + install_theme(colors);
513 550 return;
514 551 }
515 552 Err(e) => {
@@ -526,7 +563,7 @@ pub fn set_theme(id: &str) {
526 563 if path.exists() {
527 564 match load_theme(&path) {
528 565 Ok(colors) => {
529 - *THEME.write() = colors;
566 + install_theme(colors);
530 567 return;
531 568 }
532 569 Err(e) => {