Skip to content

Draw box shadows via AnyRender's box-based draw_box_shadow; pass CSS boxes as NonUniformRoundedRect - #1024

Draft
nicoburns wants to merge 11 commits into
mainfrom
devin/1791048554-inset-box-shadow
Draft

nicoburns wants to merge 11 commits into
mainfrom
devin/1791048554-inset-box-shadow

Conversation

@nicoburns

@nicoburns nicoburns commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Summary

Uses the new draw_box_shadow(transform, box_shape, offset, spread, std_dev, brush, kind) and NonUniformRoundedRect from DioxusLabs/anyrender#117, which works with the released vello 0.11 / vello_cpu 0.3. Blitz no longer computes any shadow geometry. Inset shadows lose their layers once DioxusLabs/anyrender#113 (vello#1718) lands; Blitz needs no further changes for that.

// outset (reversed, so the first shadow is on top)
scene.draw_box_shadow(self.transform, &border_box_shape, offset * scale, spread * scale,
                      blur * scale / 2.0, color, BoxShadowKind::Outset { clip_to_box });
// inset
scene.draw_box_shadow(self.transform, &padding_box_shape, ..., BoxShadowKind::Inset);
  • Removed: max_shadow_rect, CssBox::shadow_clip*, NonUniformRoundedRectRadii::average, the blur == 0 && spread == 0 special case and its clip layer, and the inset DestOut layers. AnyRender now computes the CSS spread radii and handles unblurred shadows exactly.
  • clip_to_box: this is opacity < 1 || background not opaque, the same condition as the old clip layer.
  • Rendering changes, all CSS fixes:
    • The blur is now passed as σ = blur radius / 2. It was passed as σ = blur radius, so shadows were about twice as blurry as they should be.
    • The outset blur and the inset offset are now scaled by self.scale.
    • Inset shadows are painted in reverse order, so the first is on top.
    • A transparent inset shadow no longer stops the remaining shadows from being drawn: it used to return instead of continue.
    • Unblurred shadows with spread keep exact per-corner radii.
  • CSS boxes as shapes: CssBox::{border,padding,content}_box_shape() return an anyrender::NonUniformRoundedRect. Backgrounds, background clips, overflow clips, masks and shadows use these instead of *_box_path(), so sharp-cornered boxes reach fill_rect / push_clip_rect and Skia's draw_rect / clip_rrect. Compound shapes (outlines, border rings) stay BezPath.

Do not merge yet: [patch.crates-io] points anyrender at the anyrender#117 branch. It can be removed once that's released.

Testing

cargo clippy --workspace and cargo test -p blitz-paint pass. I rendered a test page of inset and outset shadows, covering blur, spread, offset, radius and translucent backgrounds, at 1x and 2x on vello_cpu, vello classic (llvmpipe) and Skia raster:

before (vello_cpu) / after on vello_cpu, vello, skia

Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/45dbc6c083354777aaa43442ce8ef8ab
Open in Devin Desktop: https://dioxus.staging.devinenterprise.com/desktop/session/45dbc6c083354777aaa43442ce8ef8ab?variant=devin-insiders
Requested by: @nicoburns

WPT results

Subtests: 8 newly passing, 0 newly failing (net +8).

Full diff (8 changed tests)
+ FAIL => PASS  [1/1]  +1  css/CSS2/positioning/abspos-overflow-010.xht
+ FAIL => PASS  [1/1]  +1  css/css-backgrounds/box-shadow-radius-001.html
+ FAIL => PASS  [1/1]  +1  css/css-backgrounds/box-shadow-radius-002.html
+ FAIL => PASS  [1/1]  +1  css/css-backgrounds/css-box-shadow-001.html
+ FAIL => PASS  [1/1]  +1  css/css-borders/corner-shape/corner-shape-inset-shadow.html
+ FAIL => PASS  [1/1]  +1  css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-background-mismatch-alpha.html
+ FAIL => PASS  [1/1]  +1  css/css-color-adjust/rendering/dark-color-scheme/color-scheme-iframe-background-mismatch-opaque.html
+ FAIL => PASS  [1/1]  +1  css/css-transforms/fractional-scale-gradient-bg-obscure-red-bg.html

Generated by the WPT workflow.

Replaces the layer + DestOut implementation of inset box shadows with a
single draw_box_shadow call, and passes the shadow clip as the shape for
outset shadows instead of pushing a clip layer.

Temporarily patches anyrender to a local checkout and vello to the
linebender/vello#1718 branch, and updates to wgpu 30 / vello 0.11.
@staging-devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access that start with 'Devin'.

  • Disable automatic comment, CI, and merge conflict monitoring

…t-box-shadow

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	examples/paint_bench.rs
#	packages/blitz-paint/src/render/box_shadow.rs
@staging-devin-ai-integration staging-devin-ai-integration Bot changed the title Draw box shadows without compositing layers using draw_box_shadow's shape + inset Draw box shadows via AnyRender's box-based draw_box_shadow; pass CSS boxes as NonUniformRoundedRect Oct 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant