From 6e346a0cf874c3bc8438acfda230d057d3892a76 Mon Sep 17 00:00:00 2001 From: jim kolpack Date: Tue, 29 Sep 2026 19:23:06 -0400 Subject: [PATCH] Fix album art zoom always showing a cropped corner, not the full image The rest state used Scale(ART_SLOT/ART_SIZE, ...) (~0.71) on a 45x45 image to shrink it down and reveal the whole picture, but scaling below 1.0 turns out to be unsafe: empirically it reintroduces the black-border bug well before the math would predict any gap (a visible gap opens up below roughly 0.9-0.95, not just when the scaled image shrinks smaller than the display slot). So the whole "shrink down from oversized to reveal everything" design doesn't work. Instead, keep the oversized render just barely larger (36x36 vs. the 32x32 slot) so the safe floor of scale = 1.0 already shows ~89% of the image -- close enough to read as "fully zoomed out" -- while still leaving headroom above 1.0 for a real zoom-in effect. --- subwave_nowplaying.star | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/subwave_nowplaying.star b/subwave_nowplaying.star index 8a3d3b2..d613733 100644 --- a/subwave_nowplaying.star +++ b/subwave_nowplaying.star @@ -105,21 +105,22 @@ def main(config): # and it never appeared to "zoom back in". A short loop guarantees at least # one full out-and-back cycle plays before that happens. # -# Art is rendered oversized (45x45, vs. the 32x32 display slot) since -# animation.Scale has no visible effect on a widget whose declared size -# already matches its container. Only ever scaling *up* from 1.0 (never -# below) is deliberate, not cosmetic: this app originally scaled down to -# ~32/45 to "zoom out" from a corner reached via animation.Translate, which -# produced a real, on-device black border. Empirical testing (rendering the -# actual Row layout at native canvas size, no forced output dimensions) -# showed the outer Box auto-fits an oversized child to its own size at -# animation.Scale(1.0, 1.0) -- so scaling *down* from there shrinks the -# already-fitted image further, exposing background outside its bounds -# (the black border). Scaling *up* only ever crops further into the image, -# which is always safe. -ART_SIZE = 45 +# Art is rendered slightly oversized (36x36, vs. the 32x32 display slot). +# animation.Scale is only ever applied at 1.0 or above here -- empirically, +# scaling this *below* 1.0 (tried while chasing a "show the literal whole +# image at rest" design) reintroduces a real, on-device black-border bug: +# below roughly 0.9-0.95 a visible gap opens up along one edge, well before +# the math (scaled size vs. box size) would predict any gap at all, so it +# isn't a simple "runs out of image" overflow -- treat scale < 1.0 as +# unsafe regardless of the numbers. That rules out "native size at rest, +# shrink down to reveal everything" -- so instead ART_SIZE is kept just +# barely larger than ART_SLOT: at the safe floor of scale = 1.0, only +# ART_SLOT/ART_SIZE (~89%) of the image is visible, which reads as +# "fully zoomed out" (a sliver cropped off each edge, not noticeable) while +# leaving just enough headroom above 1.0 for a real zoom-in effect. +ART_SIZE = 36 ART_SLOT = 32 -ART_ZOOM_SCALE = 1.4 # how far in to zoom +ART_ZOOM_SCALE = 1.4 # how far in to zoom, relative to the rest state ART_ZOOM_DURATION = 200 # 10s round-trip (5s in, 5s out) at the default 50ms/tick def _art_widget(art_bytes):