layout: Convert animated image delays < 10ms into 100 ms delays (#39189)

Some animated images in the wild have delays <10ms and browsers usually
change them into 100ms as such small timings are unusual.

Relevant code in FF:
https://searchfox.org/firefox-main/source/image/FrameTimeout.h#35

Testing: Manually tested
Fixes: #39187

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
Sam 2025-09-08 16:16:21 +02:00 committed by GitHub
parent 30d3706a2b
commit 228b240635
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 3 deletions

View file

@ -287,7 +287,20 @@ pub struct RasterImage {
pub frames: Vec<ImageFrame>,
}
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
fn sensible_delay(delay: Duration) -> Duration {
// Very small timeout values are problematic for two reasons: we don't want
// to burn energy redrawing animated images extremely fast, and broken tools
// generate these values when they actually want a "default" value, so such
// images won't play back right without normalization.
// https://searchfox.org/firefox-main/rev/c79acad610ddbb31bd92e837e056b53716f5ccf2/image/FrameTimeout.h#35
if delay <= Duration::from_millis(10) {
Duration::from_millis(100)
} else {
delay
}
}
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct ImageFrame {
pub delay: Option<Duration>,
/// References a range of the `bytes` field from the image that this
@ -297,6 +310,12 @@ pub struct ImageFrame {
pub height: u32,
}
impl ImageFrame {
pub fn delay(&self) -> Option<Duration> {
self.delay.map(sensible_delay)
}
}
/// A non-owning reference to the data of an [ImageFrame]
pub struct ImageFrameView<'a> {
pub delay: Option<Duration>,
@ -305,6 +324,12 @@ pub struct ImageFrameView<'a> {
pub height: u32,
}
impl ImageFrameView<'_> {
pub fn delay(&self) -> Option<Duration> {
self.delay.map(sensible_delay)
}
}
impl RasterImage {
pub fn should_animate(&self) -> bool {
self.frames.len() > 1

View file

@ -661,7 +661,7 @@ impl ImageAnimationState {
.frames
.get(self.active_frame)
.unwrap()
.delay
.delay()
.unwrap()
.as_secs_f64();
let mut next_active_frame_id = self.active_frame;
@ -671,7 +671,7 @@ impl ImageAnimationState {
.frames
.get(next_active_frame_id)
.unwrap()
.delay
.delay()
.unwrap()
.as_secs_f64();
}