feat: SF Symbols variable-value rendering#813
Open
enieuwy wants to merge 1 commit into
Open
Conversation
7ebf7c2 to
248ba21
Compare
Adds a new `sf.<name>` image source that renders SF Symbols with
Apple's variable-value API. Lets configs drive progress-style indicators
(battery fill, wifi/speaker level, audio waveform, custom dials) from a
single symbol name + percentage without managing pre-rendered PNGs.
API additions (no breaking changes):
* `background.image=sf.<symbol-name>` (also under `icon.` and `label.`)
* `background.image.percentage` accepts `0..100` integers or `0.0..1.0`
floats; both are clamped to `[0,1]` internally
* `background.image.variable_value_mode={automatic|color|draw}`
(macOS 26+; parsed and stored on older systems for forward compat)
* `--query` round-trips the new `symbol`, `percentage`, and
`variable_value_mode` fields when the image is an SF Symbol
Implementation notes:
* New `src/symbol.{h,m}` wraps
`+[NSImage imageWithSystemSymbolName:variableValue:accessibilityDescription:]`
behind a runtime `respondsToSelector:` check; gracefully errors on
macOS <13.
* Image dedup via existing `image_set_image` data `memcmp` path —
identical pixel data short-circuits the redraw, so no churn at
steady state.
* Percentage uses the existing `ANIMATE_FLOAT` track, so
`--animate <fn> <ticks> --set foo background.image.percentage=…`
works for free.
* Deployment targets (`x86_64-apple-macos10.13`,
`arm64-apple-macos11`) and linked frameworks are unchanged.
248ba21 to
652139a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Adds variable-value SF Symbol rendering as a new image source. The use case is progress-style indicators (battery fill, wifi/speaker level, audio waveform, custom dials) driven by a single symbol name + percentage, without managing N pre-rendered PNGs or N font glyphs.
This is different from #63 (closed in 2021): that discussion was about static SF Symbols, which already work fine by pasting the glyph into
icon/labeltext. Variable-value rendering cannot be expressed as a Unicode glyph — Apple generates a per-frame Core Graphics image from a symbol name + a[0, 1]value, and that image is what changes as the value changes.Issue links
I did not find an open issue that this should close. I searched existing issues for SF Symbols, variable/value symbols, symbol images, battery/progress indicators, image tinting, symbol color, and palette support. The closest historical issue is #43 (
SF Symbols), but it is already closed and was about static SF Symbol support; this PR adds variable-value image rendering instead. Related discussion context: #63.What
Four additions to the existing
imagesub-domain. No breaking changes, no new sub-domain, no new frameworks linked.Works with
icon.background.image=,label.background.image=, andbackground.image=— anywhereimagealready accepts a source.--queryround-trips the new fields when the image source is an SF Symbol:symbol_coloris emitted only when explicitly set, so existing configs and query output for untinted SF Symbols remain unchanged.How
src/symbol.{h,m}wraps+[NSImage imageWithSystemSymbolName:variableValue:accessibilityDescription:]behind a runtimerespondsToSelector:check. The compile-time SDK already shipsNSImageSymbolVariableValueMode(macOS 26), so the mode branch is guarded with@available(macOS 26.0, *)rather thanNSInvocationtricks.image_loadadds ansf.*branch alongsideapp.*andspace.*. The existingget_key_value_pairsplits on the first., sosf.battery.100percent.circlecorrectly extractsbattery.100percent.circleas the symbol name.ANIMATE_FLOATtrack, so--animate sin 60 --set foo background.image.percentage=…animates for free. Verified locally — 0.42 → 1.0 over 60 ticks interpolates correctly.symbol_colorusesNSImageSymbolConfiguration configurationWithHierarchicalColor:when set. This is intentionally narrow: one ARGB tint for monochrome symbols. Palette, multicolor, and symbol-rendering-style configuration are still left out.kCGInterpolationNonebehavior.image_set_image's data-memcmpdedup short-circuits the redraw when the re-rendered symbol pixels are identical to the previous frame, so no churn at steady state. No extra cache layer needed..in the token routes throughtoken_to_float(Apple's native units); otherwise the token parses as an int and is divided by 100 (matchesslider.percentagesemantics).sf.*clears the symbol state cleanly (verified via--queryround-trip). Symbol name is duplicated intoimage->symbol_nameand freed inimage_destroy/image_clear_pointers.Compatibility
x86_64-apple-macos10.13andarm64-apple-macos11.make x86,make arm64,make universalall build with zero new warnings on Xcode 26.5 / SDK MacOSX26.5.sf.prefix is rejected with a clear error message; everything else (file paths,app.*,space.*,media.artwork) continues to work unchanged.AppKitis already linked.Out of scope (intentional — happy to follow up if useful)
NSImageSymbolConfigurationpalette colors or explicit rendering-style controls. This PR only adds the minimal monochromesymbol_colortint needed to make SF Symbol images usable across light, dark, and transparent bars.NSImageViewcache / per-item renderer change and felt too large for this PR.workspace_icon_for_app's sizing.Verification done locally
x86,arm64,universal) build clean.symbol.o) confirm: invalid names returnNULL; valid names return distinct pixel data for different values; same params produce byte-identical output (dedup property); out-of-range values clamp.sf.*to a file path and back — all verified through--queryJSON.sf.circle+symbol_color=0xff78a9ffconfirms tinted variable-draw output renders without a PNG fallback.