@@ -259,6 +259,16 @@ void native_document::update_style_animations(dom_node& node)
259259 != node.style .animations ().filter_keyframe_animation_signature ;
260260 const auto fill_mode_changed = animation.keyframe_fill_mode
261261 != node.style .animations ().keyframe_fill_mode ;
262+ const auto has_configured_keyframes =
263+ !node.style .animations ().opacity_keyframe_animation_signature .empty ()
264+ || !node.style .animations ().rotation_keyframe_animation_signature .empty ()
265+ || !node.style .animations ().filter_keyframe_animation_signature .empty ();
266+ const auto desired_keyframe_pause = has_configured_keyframes
267+ && node.style .animations ().keyframe_play_state
268+ == node_style::animation_data::play_kind::paused;
269+ const auto was_keyframe_paused = animation.keyframe_animation_paused ;
270+ const auto previous_pause_timestamp =
271+ animation.keyframe_animation_paused_at_ms ;
262272 animation.keyframe_fill_mode = node.style .animations ().keyframe_fill_mode ;
263273 if (opacity_keyframe_changed || rotation_keyframe_changed
264274 || filter_keyframe_changed) {
@@ -366,6 +376,32 @@ void native_document::update_style_animations(dom_node& node)
366376 animation.filter_keyframe_animation_valid ;
367377 }
368378 }
379+ const auto keyframe_identity_changed = opacity_keyframe_changed
380+ || rotation_keyframe_changed || filter_keyframe_changed;
381+ if (was_keyframe_paused
382+ && (!desired_keyframe_pause || keyframe_identity_changed)) {
383+ const auto held_duration = std::max (
384+ 0.0 , animation_frame_timestamp_ms_ - previous_pause_timestamp);
385+ if (!opacity_keyframe_changed
386+ && animation.opacity_keyframe_animation_active ) {
387+ animation.opacity_keyframe_animation_started_ms += held_duration;
388+ }
389+ if (!rotation_keyframe_changed
390+ && animation.rotation_keyframe_animation_active ) {
391+ animation.rotation_keyframe_animation_started_ms += held_duration;
392+ }
393+ if (!filter_keyframe_changed
394+ && animation.filter_keyframe_animation_active ) {
395+ animation.filter_keyframe_animation_started_ms += held_duration;
396+ }
397+ }
398+ animation.keyframe_animation_paused = desired_keyframe_pause;
399+ if (desired_keyframe_pause
400+ && (!was_keyframe_paused || keyframe_identity_changed)) {
401+ animation.keyframe_animation_paused_at_ms = animation_frame_timestamp_ms_;
402+ } else if (!has_configured_keyframes) {
403+ animation.keyframe_animation_paused_at_ms = 0 ;
404+ }
369405
370406 if (animation.opacity_animation_active && node.style .animations ().transition_property_value == " none" ) {
371407 transition_events_.push_back ({node.id ," transitioncancel" ," opacity" ,
@@ -1052,6 +1088,9 @@ bool native_document::advance_animations() noexcept
10521088 }
10531089
10541090 auto keyframe_animation_completed = false ;
1091+ const auto keyframe_timestamp_ms = animation.keyframe_animation_paused
1092+ ? animation.keyframe_animation_paused_at_ms
1093+ : animation_frame_timestamp_ms_;
10551094 if (animation.opacity_keyframe_animation_active ) {
10561095 const auto sample_opacity = [&](float cycle_progress) {
10571096 const auto & stops = node.style .animations ().opacity_keyframes ;
@@ -1084,7 +1123,7 @@ bool native_document::advance_animations() noexcept
10841123 }
10851124 };
10861125 const auto elapsed_ms = static_cast <float >(
1087- animation_frame_timestamp_ms_
1126+ keyframe_timestamp_ms
10881127 - animation.opacity_keyframe_animation_started_ms
10891128 - node.style .animations ().opacity_keyframe_delay_ms );
10901129 if (elapsed_ms < 0 ) {
@@ -1110,8 +1149,10 @@ bool native_document::advance_animations() noexcept
11101149 } else {
11111150 animation.painted_opacity = node.style .opacity ;
11121151 }
1113- animation.opacity_keyframe_animation_active = false ;
1114- keyframe_animation_completed = true ;
1152+ if (!animation.keyframe_animation_paused ) {
1153+ animation.opacity_keyframe_animation_active = false ;
1154+ keyframe_animation_completed = true ;
1155+ }
11151156 advanced = advanced || keyframe_paint_visible;
11161157 } else {
11171158 sample_opacity (active_keyframe_progress (
@@ -1154,7 +1195,7 @@ bool native_document::advance_animations() noexcept
11541195 }
11551196 };
11561197 const auto elapsed_ms = static_cast <float >(
1157- animation_frame_timestamp_ms_
1198+ keyframe_timestamp_ms
11581199 - animation.rotation_keyframe_animation_started_ms
11591200 - node.style .animations ().opacity_keyframe_delay_ms );
11601201 if (elapsed_ms < 0 ) {
@@ -1184,8 +1225,10 @@ bool native_document::advance_animations() noexcept
11841225 node.style .transform_rotate_degrees ;
11851226 animation.rotation_keyframe_animation_filled = false ;
11861227 }
1187- animation.rotation_keyframe_animation_active = false ;
1188- keyframe_animation_completed = true ;
1228+ if (!animation.keyframe_animation_paused ) {
1229+ animation.rotation_keyframe_animation_active = false ;
1230+ keyframe_animation_completed = true ;
1231+ }
11891232 advanced = advanced || keyframe_paint_visible;
11901233 } else {
11911234 sample_rotation (active_keyframe_progress (
@@ -1242,7 +1285,7 @@ bool native_document::advance_animations() noexcept
12421285 }
12431286 };
12441287 const auto elapsed_ms = static_cast <float >(
1245- animation_frame_timestamp_ms_
1288+ keyframe_timestamp_ms
12461289 - animation.filter_keyframe_animation_started_ms
12471290 - node.style .animations ().opacity_keyframe_delay_ms );
12481291 if (elapsed_ms < 0 ) {
@@ -1272,8 +1315,10 @@ bool native_document::advance_animations() noexcept
12721315 animation.filter_keyframe_underlying ;
12731316 animation.filter_keyframe_animation_filled = false ;
12741317 }
1275- animation.filter_keyframe_animation_active = false ;
1276- keyframe_animation_completed = true ;
1318+ if (!animation.keyframe_animation_paused ) {
1319+ animation.filter_keyframe_animation_active = false ;
1320+ keyframe_animation_completed = true ;
1321+ }
12771322 advanced = advanced || keyframe_paint_visible;
12781323 } else {
12791324 sample_filter (active_keyframe_progress (
@@ -1344,7 +1389,8 @@ bool native_document::has_active_animations() const noexcept
13441389 || animation->rotation_keyframe_animation_active
13451390 || animation->filter_keyframe_animation_active ;
13461391 return transition_active
1347- || (keyframe_active && intersects_visible_paint_area (*node));
1392+ || (keyframe_active && !animation->keyframe_animation_paused
1393+ && intersects_visible_paint_area (*node));
13481394 });
13491395 active_animation_demand_cache_valid_ = true ;
13501396 return active_animation_demand_cache_;
0 commit comments