mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
script: Properly root nodes with animating images (#37689)
This change fixes an issue and makes a few more minor improvements to the `ImageAnimationState`: 1. Image rooting and unrooted now happens in one step from `Window::update_animations_post_reflow`. 2. The `node_to_animating_image_map` is now stored as a shared `RwLock` so that it doesn't need to be taken and then replaced in the `ImageAnimationState` during reflow. This should prevent a hypothetical issue where image animations are restarted during empty reflows. 3. General naming and idiomatic Rust usage improvements. Testing: This doesn't really have any obvious behavioral changes, because all reflows currently trigger a restyle. It becomes a serious problem with #37677 and this change fixes the failing test there. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
b89a44c539
commit
a66a257b38
10 changed files with 107 additions and 118 deletions
|
@ -55,7 +55,10 @@ pub struct LayoutContext<'a> {
|
|||
pub resolved_images_cache:
|
||||
Arc<RwLock<FnvHashMap<(ServoUrl, UsePlaceholder), CachedImageOrError>>>,
|
||||
|
||||
pub node_image_animation_map: Arc<RwLock<FxHashMap<OpaqueNode, ImageAnimationState>>>,
|
||||
/// A shared reference to script's map of DOM nodes with animated images. This is used
|
||||
/// to manage image animations in script and inform the script about newly animating
|
||||
/// nodes.
|
||||
pub node_to_animating_image_map: Arc<RwLock<FxHashMap<OpaqueNode, ImageAnimationState>>>,
|
||||
|
||||
/// The DOM node that is highlighted by the devtools inspector, if any
|
||||
pub highlighted_dom_node: Option<OpaqueNode>,
|
||||
|
@ -153,31 +156,24 @@ impl LayoutContext<'_> {
|
|||
}
|
||||
|
||||
pub fn handle_animated_image(&self, node: OpaqueNode, image: Arc<RasterImage>) {
|
||||
let mut store = self.node_image_animation_map.write();
|
||||
let mut map = self.node_to_animating_image_map.write();
|
||||
if !image.should_animate() {
|
||||
map.remove(&node);
|
||||
return;
|
||||
}
|
||||
let new_image_animation_state = || {
|
||||
ImageAnimationState::new(
|
||||
image.clone(),
|
||||
self.shared_context().current_time_for_animations,
|
||||
)
|
||||
};
|
||||
|
||||
// 1. first check whether node previously being track for animated image.
|
||||
if let Some(image_state) = store.get(&node) {
|
||||
// a. if the node is not containing the same image as before.
|
||||
if image_state.image_key() != image.id {
|
||||
if image.should_animate() {
|
||||
// i. Register/Replace tracking item in image_animation_manager.
|
||||
store.insert(
|
||||
node,
|
||||
ImageAnimationState::new(
|
||||
image,
|
||||
self.shared_context().current_time_for_animations,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// ii. Cancel Action if the node's image is no longer animated.
|
||||
store.remove(&node);
|
||||
}
|
||||
}
|
||||
} else if image.should_animate() {
|
||||
store.insert(
|
||||
node,
|
||||
ImageAnimationState::new(image, self.shared_context().current_time_for_animations),
|
||||
);
|
||||
let entry = map.entry(node).or_insert_with(new_image_animation_state);
|
||||
|
||||
// If the entry exists, but it is for a different image id, replace it as the image
|
||||
// has changed during this layout.
|
||||
if entry.image.id != image.id {
|
||||
*entry = new_image_animation_state();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,10 @@ impl FragmentTree {
|
|||
// them. Create a set of all elements that used to be animating.
|
||||
let mut animations = layout_context.style_context.animations.sets.write();
|
||||
let mut invalid_animating_nodes: FxHashSet<_> = animations.keys().cloned().collect();
|
||||
let mut image_animations = layout_context.node_image_animation_map.write().to_owned();
|
||||
let mut image_animations = layout_context
|
||||
.node_to_animating_image_map
|
||||
.write()
|
||||
.to_owned();
|
||||
let mut invalid_image_animating_nodes: FxHashSet<_> = image_animations
|
||||
.keys()
|
||||
.cloned()
|
||||
|
|
|
@ -644,9 +644,7 @@ impl LayoutThread {
|
|||
resolved_images_cache: self.resolved_images_cache.clone(),
|
||||
pending_images: Mutex::default(),
|
||||
pending_rasterization_images: Mutex::default(),
|
||||
node_image_animation_map: Arc::new(RwLock::new(std::mem::take(
|
||||
&mut reflow_request.node_to_image_animation_map,
|
||||
))),
|
||||
node_to_animating_image_map: reflow_request.node_to_animating_image_map.clone(),
|
||||
iframe_sizes: Mutex::default(),
|
||||
use_rayon: rayon_pool.is_some(),
|
||||
highlighted_dom_node: reflow_request.highlighted_dom_node,
|
||||
|
@ -687,15 +685,12 @@ impl LayoutThread {
|
|||
let pending_rasterization_images =
|
||||
std::mem::take(&mut *layout_context.pending_rasterization_images.lock());
|
||||
let iframe_sizes = std::mem::take(&mut *layout_context.iframe_sizes.lock());
|
||||
let node_to_image_animation_map =
|
||||
std::mem::take(&mut *layout_context.node_image_animation_map.write());
|
||||
|
||||
Some(ReflowResult {
|
||||
built_display_list,
|
||||
pending_images,
|
||||
pending_rasterization_images,
|
||||
iframe_sizes,
|
||||
node_to_image_animation_map,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue