Function: image-animate-timeout
image-animate-timeout is a byte-compiled function defined in
image.el.gz.
Signature
(image-animate-timeout IMAGE N COUNT TIME-ELAPSED LIMIT TARGET-TIME)
Documentation
Display animation frame N of IMAGE.
N=0 refers to the initial animation frame.
COUNT is the total number of frames in the animation.
TIME-ELAPSED is the total time that has elapsed since
image-animate was called.
LIMIT determines when to stop. If t, loop forever. If nil, stop
after displaying the last animation frame. Otherwise, stop
after LIMIT seconds have elapsed.
The minimum delay between successive frames is image-minimum-frame-delay.
If the image has a non-nil :speed property, it acts as a multiplier for the animation speed. A negative value means to animate in reverse.
Source Code
;; Defined in /usr/src/emacs/lisp/image.el.gz
;; FIXME: The count argument is redundant; the value is also given by
;; the call to `image-multi-frame-p'.
(defun image-animate-timeout (image n count time-elapsed limit target-time)
"Display animation frame N of IMAGE.
N=0 refers to the initial animation frame.
COUNT is the total number of frames in the animation.
TIME-ELAPSED is the total time that has elapsed since
`image-animate' was called.
LIMIT determines when to stop. If t, loop forever. If nil, stop
after displaying the last animation frame. Otherwise, stop
after LIMIT seconds have elapsed.
The minimum delay between successive frames is `image-minimum-frame-delay'.
If the image has a non-nil :speed property, it acts as a multiplier
for the animation speed. A negative value means to animate in reverse."
;; We keep track of "how late" image frames arrive. We decay the
;; previous cumulative value by 10% and then add the current delay.
(plist-put (cdr image) :animate-tardiness
(+ (* (plist-get (cdr image) :animate-tardiness) 0.9)
(float-time (time-since target-time))))
(let* ((buffer (plist-get (cdr image) :animate-buffer))
(position (plist-get (cdr image) :animate-position))
(continue-animation
(and (buffer-live-p buffer)
;; If we have a :animate-position setting, the caller
;; has requested that the animation be stopped if the
;; image is no longer displayed in the buffer.
(or (null position)
(with-current-buffer buffer
(let ((disp (get-text-property position 'display)))
(and (consp disp)
(eq (car disp) 'image)
;; We can't check `eq'-ness of the image
;; itself, since that may change.
(eq position
(plist-get (cdr disp) :animate-position))))))
;; Cumulatively delayed two seconds more than expected.
(or (< (plist-get (cdr image) :animate-tardiness) 2)
(progn
(message "Stopping animation; animation possibly too big")
nil)))))
(if (not continue-animation)
;; Eject from the animation cache since we've decided not to
;; keep updating it. This helps stop unbounded RAM usage when
;; doing, for instance, `g' in an eww buffer with animated
;; images.
;; FIXME: This doesn't currently support ImageMagick.
(clear-image-cache nil image)
(let* ((time (current-time))
;; Each animation frame can have its own duration, so
;; (re)fetch its `image-metadata'. Do so before
;; `image-show-frame' to avoid an image cache miss per
;; animation frame (bug#47895, bug#66221).
(multi (prog1 (image-multi-frame-p image)
(image-show-frame image n t)))
(speed (image-animate-get-speed image))
(stated-delay-time
(/ (or (cdr multi) image-default-frame-delay)
(float (abs speed))))
(time-to-load-image (time-since time))
;; Subtract off the time we took to load the image from the
;; stated delay time.
(delay (max (float-time (time-subtract stated-delay-time
time-to-load-image))
image-minimum-frame-delay))
done)
(setq n (if (< speed 0)
(1- n)
(1+ n)))
(if limit
(cond ((>= n count) (setq n 0))
((< n 0) (setq n (1- count))))
(and (or (>= n count) (< n 0)) (setq done t)))
(setq time-elapsed (+ delay time-elapsed))
(if (numberp limit)
(setq done (>= time-elapsed limit)))
(unless done
(run-with-timer delay nil #'image-animate-timeout
image n count time-elapsed limit
(+ (float-time) delay)))))))