Skip to content

Commit 2c2841a

Browse files
committed
Fix pixbuf loader bug due to a double to uint64_t cast.
1 parent 5d8e3ce commit 2c2841a

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

contrib/gdk-pixbuf/loader.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ typedef struct {
2222
struct _AvifAnimation {
2323
GdkPixbufAnimation parent;
2424
GArray * frames;
25+
uint64_t animation_time;
2526

2627
GdkPixbufModuleSizeFunc size_func;
2728
GdkPixbufModuleUpdatedFunc updated_func;
@@ -140,16 +141,10 @@ static gboolean avif_animation_iter_advance(GdkPixbufAnimationIter * iter, const
140141
size_t prev_frame = avif_iter->current_frame;
141142
uint64_t elapsed_time = current_time->tv_sec * 1000 + current_time->tv_usec / 1000 - avif_iter->time_offset;
142143

143-
/*
144-
* duration in seconds stored in a double which is cast to uint64_t
145-
* is the precision loss here significant?
146-
*/
147-
uint64_t animation_time = (uint64_t)(context->decoder->duration * 1000);
148-
149-
if (context->decoder->repetitionCount > 0 && elapsed_time > animation_time * context->decoder->repetitionCount) {
144+
if (context->decoder->repetitionCount > 0 && elapsed_time > context->animation_time * context->decoder->repetitionCount) {
150145
avif_iter->current_frame = context->decoder->imageCount - 1;
151146
} else {
152-
elapsed_time = elapsed_time % animation_time;
147+
elapsed_time = elapsed_time % context->animation_time;
153148

154149
avif_iter->current_frame = 0;
155150
uint64_t frame_duration;
@@ -423,6 +418,7 @@ static gboolean avif_context_try_load(AvifAnimation * context, GError ** error)
423418
AvifAnimationFrame frame;
424419
frame.pixbuf = set_pixbuf(context, error);
425420
frame.duration_ms = (uint64_t)(decoder->imageTiming.duration * 1000);
421+
context->animation_time = frame.duration_ms;
426422

427423
if (frame.pixbuf == NULL) {
428424
return FALSE;
@@ -447,6 +443,13 @@ static gboolean avif_context_try_load(AvifAnimation * context, GError ** error)
447443
frame.pixbuf = set_pixbuf(context, error);
448444
frame.duration_ms = (uint64_t)(decoder->imageTiming.duration * 1000);
449445

446+
if (frame.pixbuf == NULL) {
447+
return FALSE;
448+
}
449+
450+
/* We don't use the animation duration from the AVIF structure directly due to precision problems */
451+
context->animation_time += frame.duration_ms;
452+
450453
g_array_append_val(context->frames, frame);
451454
}
452455
return TRUE;

0 commit comments

Comments
 (0)