Skip to main content

Module filters

Module filters 

Source
Expand description

Filter wire types, built-in filters, and the filter registry: the layer-based filter style chain.

This module owns the filter wire format and registry the way crate::canvas/crate::animations own theirs: protocol/ reconcile/ui_map reference these types by module path, never the reverse. On the wire a filter is one {"name", "params"} object or an ordered array of them; params stays an untyped JSON map at this layer — typed validation happens later against the registry, not during decode.

Decoding follows the protocol’s warn-don’t-abort convention (see Length’s custom Deserialize): a malformed value emits a decode_warn and the whole chain degrades to empty, never failing the containing Style’s deserialization.

The typed layer below the wire — ReactFilter, the built-in param structs, and FilterRegistry — turns a FilterUse into ResolvedFilterPasses: deserialize the raw params (strict: deny-unknown-fields), pack them into a Vec4 uniform array with a ParamSlot layout (no-straddle rule: a slot never crosses a Vec4 boundary), and pick the pass shader. The ten built-ins register via register_builtin_filters; custom filters are #[react_filter] structs registered with add_react_filter.

The module also owns the runtime write path of a chain. resolve_chains turns a promoted root’s FilterInput into a ResolvedFilterChain component — resolving each entry against the registry (invalid entries skip with a filterParams warning), rewriting Length slots to physical px, stamping ResolvedFilterPass::wire_index, and summing the chain outset. The interpolation primitives (lerp_packed_params, lerp_angle) blend packed param arrays layout-aware for the easing paths. Exactly three systems write ResolvedFilterChain and bump its version counter: the resolver’s snap, the transition filter channel’s whole-value ease (transition.rs, planned by [plan_filter_ease] with identity-padding for chain extensions), and the animation per-param filter[<i>].<param> bindings (animations) — see ResolvedFilterChain::version for the writer registry and precedence.

File map: wire (the wire format + warn-don’t-abort decode), params (packing layout, caps, param value types, interpolation), registry (the ReactFilter trait, resolved passes, the registry), builtin (the ten built-ins), transition (whole-value filter transition planning), resolve (the chain resolve system). Submodules are private; everything is re-exported here, so crate::filters::X is the one path.

Structs§

BackdropInput
The wire backdropFilter chain of a node, mirrored off the applied style by crate::ui_map::apply_style_masked’s BACKDROP arm — present iff the style carries a non-empty chain. Same contract as FilterInput: the style apply owns writes (the applied style may be hover/press/focus-merged), the resolver only reads.
BloomParams
bloom: glow where bright areas bleed light — a bright-pass thresholded at threshold, blurred by radius, and added back onto the original scaled by intensity. { name: "bloom" } with no params is a visible glow (shorthand-default convention); the true identity is intensity: 0.
BlurParams
blur: separable Gaussian blur. radius defaults to 0 — CSS blur() with the value omitted means 0 (identity).
BrightnessParams
brightness: amount defaults to 1.0 — CSS brightness() with the value omitted means 1 (identity).
ChromaticAberrationParams
chromaticAberration: directional color fringing — the R channel’s image shifts offset px along angle (degrees, clockwise from +X in screen space; bare number = degrees, "0.25turn" etc. accepted), B the same distance opposite, G stays put. The split is uniform across the layer. { name: "chromaticAberration" } with no params is visible fringing (shorthand-default convention); the true identity is offset: 0.
ContrastParams
contrast: amount defaults to 1.0 — CSS contrast() with the value omitted means 1 (identity).
FilterChain
An ordered filter chain. Decodes from a single {"name", "params"} object (a 1-element chain) or an array of them (applied in order); any malformed entry — or non-object/array garbage — warns and degrades the whole value to an empty chain.
FilterColor
A color filter parameter: linear (shader-ready) straight-alpha RGBA.
FilterInput
The wire filter chain of a node, mirrored off the applied style by the apply path (crate::ui_map::apply_style_masked’s FILTER arm) — present iff the style carries a non-empty chain. The thin input side of the resolve_chains system, mirroring the crate::transition::TransitionInput pattern: the style apply owns writes, the resolver only reads. The applied style may be a hover/press/focus- merged one (the field is overlay), so an interaction flip re-stamps the merged chain here.
FilterRegistration
One registered filter: everything the chain resolver needs, baked into AssetServer-free fn pointers at registration time (shader loading stays lazy — the pointers receive the &AssetServer).
FilterRegistry
Known filters, keyed by wire name. Populated by register_builtin_filters; consumed by resolve_chains.
FilterUse
One filter invocation in a chain: a registry name plus its raw, untyped parameter map (empty when the wire object has no params or params is null).
GrayscaleParams
grayscale: amount defaults to 1.0 — CSS grayscale() with the value omitted means 1 (full effect; identity is 0), so a bare {name:"grayscale"} applies the effect.
HueRotateParams
hueRotate: angle defaults to 0deg — CSS hue-rotate() with the value omitted means 0deg (identity). Packs radians at params[1].z of the shared color-matrix packing.
InvertParams
invert: amount defaults to 1.0 — CSS invert() with the value omitted means 1 (full effect; identity is 0).
ParamSlot
Where one named parameter lands in a pass’s packed Vec4 array: vec is the Vec4 index, comp the starting component within it, len how many consecutive components the param spans.
ResolvedBackdropChain
A node’s fully resolved backdropFilter chain — a newtype over ResolvedFilterChain so extract, transitions, animations, and devtools reuse the inner type via .0. Attached to promoted roots by the backdrop resolve_chains instance; absent when the chain has no valid entries. Removed on demotion by evaluate_layer_promotions’s cleanup (like the content chain).
ResolvedFilterChain
A node’s fully resolved filter chain, attached to promoted layer roots by resolve_chains. Absent on a promoted root whose chain has no valid entries (pure capture/composite — no filter machinery).
ResolvedFilterPass
One resolved render pass of a filter chain.
SaturateParams
saturate: amount defaults to 1.0 — CSS saturate() with the value omitted means 1 (identity).
SepiaParams
sepia: amount defaults to 1.0 — CSS sepia() with the value omitted means 1 (full effect; identity is 0).

Constants§

MAX_CHAIN_LEN
Longest decodable chain. ResolvedFilterPass::wire_index is a u8, so only entry indices 0..=u8::MAX are addressable; a longer chain is nonsense input and degrades whole-value like any other malformed chain.
MAX_FILTER_OUTSET_PX
Defensive cap on a chain’s summed outset, physical px per side. Far beyond any sane blur (quality is bounded well before this — see blur.wgsl’s MAX_HALF note), it bounds the inflation math: 2 * outset adds at most 2048 texels to the capture, leaving real headroom under wgpu’s default 8192 max_texture_dimension_2d for the content itself. (Texture-limit safety proper is the allocator’s concern, not this cap’s.)
MAX_FILTER_PARAM_VECS
Cap on the packed Vec4 array per pass — the fixed-size uniform array the filter shaders declare.

Traits§

ChainInput
Input side of one resolve_chains instance: which wire-chain component feeds it, its diag kinds, and per-instance semantics. Implemented by FilterInput (the content filter chain) and BackdropInput (backdropFilter).
ReactFilter
A typed, named filter: how its params deserialize (strict — built-ins use #[serde(deny_unknown_fields)]), pack into shader uniforms, and resolve into render passes.
ResolvedChain
Output side of one resolve_chains instance — a component wrapping (or being) a ResolvedFilterChain. The newtype projection keeps every downstream consumer (extract, transitions, animations, devtools) on the one inner type.

Functions§

length_logical_px
A Length filter param’s logical-px value. Only Px has a fixed logical size here — percent/viewport units have no basis for a filter param — so any other unit is rejected with a message naming it, instead of silently resolving to 0.0. Bare wire numbers decode as Px and stay accepted.
lerp_angle
Shortest-arc interpolation between two angles in radians, for packed ValueKind::Angle filter params.
lerp_packed_params
Interpolate two packed param arrays of the same layout, slot-by-slot: the layout (not the raw components) decides how each param blends.
quantize_outset
Quantize a physical-px outset up to the next multiple of 16 so an animated radius grows a layer texture in coarse steps instead of reallocating every frame.
register_builtin_filters
Register the ten built-in filters. Called by ReactUiPlugin::build. Deliberately AssetServer-free: shader loads happen lazily inside each entry’s resolve.
resolve_chains
Turn each promoted root’s wire chain input I into a packed resolved chain R. Two instances run in Update after the interaction restyle (the last input writer this frame) and before the transition/animation appliers — both write onto the resolved chain: the content instance (FilterInputResolvedFilterChain, the filter style) and the backdrop instance (BackdropInputResolvedBackdropChain, the backdropFilter style — see crate::filters::backdrop).
resolve_single_pass
The default single-pass resolve body: ReactFilter::pack + the param-vec cap check + one pass tagged wire_index: 0.