Skip text shadow builder groups when no shadow pass runs

This commit is contained in:
Elena Torro 2026-08-17 13:55:03 +02:00
parent 730a2ea918
commit 0e31516761
2 changed files with 34 additions and 17 deletions

View File

@ -1688,23 +1688,34 @@ impl RenderState {
let inner_shadows = shape.inner_shadow_paints();
let blur_filter = shape.image_filter(1.);
let mut paragraphs_with_shadows =
text_content.paragraph_builder_group_from_text(Some(true));
let (mut stroke_paragraphs_with_shadows_list, _shadow_opacities): (
Vec<_>,
Vec<_>,
) = shape
.visible_strokes()
.rev()
.map(|stroke| {
text::stroke_paragraph_builder_group_from_text(
text_content,
stroke,
&shape.selrect(),
Some(true),
)
})
.unzip();
// Safe to leave empty: every consumer is inside `for shadow in
// <list>` or guarded by `!skip_drop_shadows`.
let has_shadow_passes = if parent_shadows.is_some() {
!skip_drop_shadows
} else {
!drop_shadows.is_empty() || !inner_shadows.is_empty()
};
let mut paragraphs_with_shadows = Vec::new();
let mut stroke_paragraphs_with_shadows_list = Vec::new();
if has_shadow_passes {
paragraphs_with_shadows =
text_content.paragraph_builder_group_from_text(Some(true));
stroke_paragraphs_with_shadows_list = shape
.visible_strokes()
.rev()
.map(|stroke| {
text::stroke_paragraph_builder_group_from_text(
text_content,
stroke,
&shape.selrect(),
Some(true),
)
.0
})
.collect();
}
if let Some(parent_shadows) = parent_shadows {
if !skip_drop_shadows {

View File

@ -155,6 +155,12 @@ pub fn render_text_shadows(
return Ok(());
}
// Before `canvas_and_mark_dirty`: an empty-but-dirty layer still costs a
// full surface composite.
if shadows.is_empty() {
return Ok(());
}
let canvas = render_state
.surfaces
.canvas_and_mark_dirty(surface_id.unwrap_or(SurfaceId::TextDropShadows));