/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ColorU, PropertyBinding}; use api::units::*; usecrate::border::{BorderRadiusAu}; usecrate::clip::{ClipItemEntry, ClipItemKey, ClipItemKeyKind, ClipNodeId}; usecrate::intern::{Handle as InternHandle, InternDebug, Internable}; usecrate::prim_store::{InternablePrimitive, PrimKey, PrimTemplate, PrimTemplateCommonData}; usecrate::prim_store::{PrimitiveKind, PrimitiveStore, VectorKey}; usecrate::prim_store::rectangle::RectanglePrim; usecrate::scene_building::{SceneBuilder, IsVisible}; usecrate::spatial_tree::SpatialNodeIndex; usecrate::internal_types::LayoutPrimitiveInfo;
// Maximum blur radius for box-shadows (different than blur filters). // Taken from nsCSSRendering.cpp in Gecko. pubconst MAX_BLUR_RADIUS: f32 = 300.;
// A cache key that uniquely identifies a minimally sized // and blurred box-shadow rect that can be stored in the // texture cache and applied to clip-masks. #[derive(Debug, Clone, Eq, Hash, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubstruct BoxShadowCacheKey { /// Blur sigma in device pixels at the mask resolution (≤ MAX_BLUR_STD_DEVIATION after Opt B). /// Stored as Au for sub-pixel precision; using i32 would round small sigmas to 0. pub blur_radius_dp: Au, pub clip_mode: BoxShadowClipMode, // NOTE(emilio): Only the original allocation size needs to be in the cache // key, since the actual size is derived from that. pub original_alloc_size: DeviceIntSize, pub br_top_left: DeviceIntSize, pub br_top_right: DeviceIntSize, pub br_bottom_right: DeviceIntSize, pub br_bottom_left: DeviceIntSize, pub device_pixel_scale: Au,
}
// Inset shadows get smaller as spread radius increases. let spread_amount = match clip_mode {
BoxShadowClipMode::Outset => spread_radius,
BoxShadowClipMode::Inset => -spread_radius,
};
// Ensure the blur radius is somewhat sensible.
blur_radius = f32::min(blur_radius, MAX_BLUR_RADIUS);
// Apply parameters that affect where the shadow rect // exists in the local space of the primitive. let shadow_rect = prim_info
.rect
.translate(*box_offset)
.inflate(spread_amount, spread_amount);
// If blur radius is zero, we can use a fast path with // no blur applied. if blur_radius == 0.0 { // Trivial reject of box-shadows that are not visible. if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 { return;
}
letmut clips = Vec::with_capacity(2); let (final_prim_rect, clip_radius) = match clip_mode {
BoxShadowClipMode::Outset => { if shadow_rect.is_empty() { return;
}
// TODO(gw): Add a fast path for ClipOut + zero border radius!
clips.push(ClipItemEntry {
key: ClipItemKey {
kind: ClipItemKeyKind::rounded_rect(
border_radius,
ClipMode::ClipOut,
),
},
spatial_node_index,
clip_rect: prim_info.rect,
});
self.add_primitive(
spatial_node_index,
clip_node_id,
&LayoutPrimitiveInfo::with_clip_rect(final_prim_rect, prim_info.clip_rect),
clips,
RectanglePrim {
color: PropertyBinding::Value(color.into()),
},
);
} else { // Box-shadows with a valid blur radius use the quad primitive // path; element clipping is handled analytically in the shader. let blur_offset = (BLUR_SAMPLE_SCALE * blur_radius).ceil();
// Get the local rect of where the shadow will be drawn, // expanded to include room for the blurred region. let dest_rect = shadow_rect.inflate(blur_offset, blur_offset);
match clip_mode {
BoxShadowClipMode::Outset => { // Certain spread-radii make the shadow invalid. if shadow_rect.is_empty() { return;
}
// Element clip is handled analytically in the shader. self.add_nonshadowable_primitive(
spatial_node_index,
clip_node_id,
&LayoutPrimitiveInfo::with_clip_rect(dest_rect, prim_info.clip_rect),
vec![],
BoxShadow {
color: color.into(),
blur_radius: Au::from_f32_px(blur_radius),
clip_mode,
shadow_radius: shadow_radius.into(),
element_radius: border_radius.into(),
box_offset: (*box_offset).into(),
spread_amount: Au::from_f32_px(spread_amount),
},
);
}
BoxShadowClipMode::Inset => { // If the inner shadow rect contains the prim // rect, no pixels will be shadowed. if border_radius.is_zero() && shadow_rect
.inflate(-blur_radius, -blur_radius)
.contains_box(&prim_info.rect)
{ return;
}
// Element clip is handled analytically in the shader. self.add_nonshadowable_primitive(
spatial_node_index,
clip_node_id,
&prim_info.clone(),
vec![],
BoxShadow {
color: color.into(),
blur_radius: Au::from_f32_px(blur_radius),
clip_mode,
shadow_radius: shadow_radius.into(),
element_radius: border_radius.into(),
box_offset: (*box_offset).into(),
spread_amount: Au::from_f32_px(spread_amount),
},
);
}
}
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.