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 delay may not be the same for different sub-images,
;; hence we need to call image-multi-frame-p to return it.
;; But it also returns count, so why do we bother passing that as an
;; argument?
(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.
(clear-image-cache nil image)
(let* ((time (prog1 (current-time)
(image-show-frame image n t)))
(speed (image-animate-get-speed image))
(time-to-load-image (time-since time))
(stated-delay-time
(/ (or (cdr (plist-get (cdr image) :animate-multi-frame-data))
image-default-frame-delay)
(float (abs speed))))
;; 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)))))))