Commit 3a2ddc2d authored by Glenn Morris's avatar Glenn Morris

Add functions to change the speed of animated images

* lisp/image-mode.el (image-mode-map): Add menu items to reverse,
increase, decrease, reset animation speed.
(image--set-speed, image-increase-speed, image-decrease-speed)
(image-reverse-speed, image-reset-speed): New functions.
(image-mode-map): Add bindings for speed commands.

* lisp/image.el (image-animate-get-speed, image-animate-set-speed):
New functions.
(image-animate-timeout): Respect image :speed property.

* etc/NEWS: Mention this.
parent bd805d5b
......@@ -347,6 +347,8 @@ directory, respectively.
`f' (`image-next-frame') and `b' (`image-previous-frame') visit the
next or previous frame. `F' (`image-goto-frame') shows a specific frame.
*** New commands to speed up, slow down, or reverse animation.
---
*** The command `image-mode-fit-frame' deletes other windows.
When toggling, it restores the frame's previous window configuration.
......@@ -683,6 +685,8 @@ Emacs uses `image-default-frame-delay'.
*** New functions `image-current-frame' and `image-show-frame' for getting
and setting the current frame of a multi-frame image.
*** You can change the speed of animated images.
** Changes in encoding and decoding of text
---
......
2013-08-16 Glenn Morris <rgm@gnu.org>
* image-mode.el (image-mode-map): Add menu items to reverse,
increase, decrease, reset animation speed.
(image--set-speed, image-increase-speed, image-decrease-speed)
(image-reverse-speed, image-reset-speed): New functions.
(image-mode-map): Add bindings for speed commands.
* image.el (image-animate-get-speed, image-animate-set-speed):
New functions.
(image-animate-timeout): Respect image :speed property.
2013-08-15 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/debug.el (debugger-setup-buffer): Put point on the
......
......@@ -354,6 +354,10 @@ call."
(define-key map "b" 'image-previous-frame)
(define-key map "n" 'image-next-file)
(define-key map "p" 'image-previous-file)
(define-key map "a+" 'image-increase-speed)
(define-key map "a-" 'image-decrease-speed)
(define-key map "a0" 'image-reset-speed)
(define-key map "ar" 'image-reverse-speed)
(define-key map [remap forward-char] 'image-forward-hscroll)
(define-key map [remap backward-char] 'image-backward-hscroll)
(define-key map [remap right-char] 'image-forward-hscroll)
......@@ -412,7 +416,23 @@ call."
(image-toggle-animation)))
:style toggle :selected image-animate-loop
:active image-multi-frame
:help "Animate images once, or forever?"]
:help "Animate images once, or forever?"]
["Reverse Animation" image-reverse-speed
:style toggle :selected (let ((image (image-get-display-property)))
(and image (<
(image-animate-get-speed image)
0)))
:active image-multi-frame
:help "Reverse direction of this image's animation?"]
["Speed Up Animation" image-increase-speed
:active image-multi-frame
:help "Speed up this image's animation"]
["Slow Down Animation" image-decrease-speed
:active image-multi-frame
:help "Slow down this image's animation"]
["Reset Animation Speed" image-reset-speed
:active image-multi-frame
:help "Reset the speed of this image's animation"]
["Next Frame" image-next-frame :active image-multi-frame
:help "Show the next frame of this image"]
["Previous Frame" image-previous-frame :active image-multi-frame
......@@ -437,7 +457,10 @@ call."
(defun image-mode ()
"Major mode for image files.
You can use \\<image-mode-map>\\[image-toggle-display]
to toggle between display as an image and display as text."
to toggle between display as an image and display as text.
Key bindings:
\\{image-mode-map}"
(interactive)
(condition-case err
(progn
......@@ -703,6 +726,48 @@ Otherwise it plays once, then stops."
(image-animate image index
(if image-animate-loop t)))))))))
(defun image--set-speed (speed &optional multiply)
"Set speed of an animated image to SPEED.
If MULTIPLY is non-nil, treat SPEED as a multiplication factor.
If SPEED is `reset', reset the magnitude of the speed to 1."
(let ((image (image-get-display-property)))
(cond
((null image)
(error "No image is present"))
((null image-multi-frame)
(message "No image animation."))
(t
(if (eq speed 'reset)
(setq speed (if (< (image-animate-get-speed image) 0)
-1 1)
multiply nil))
(image-animate-set-speed image speed multiply)
;; FIXME Hack to refresh an active image.
(when (image-animate-timer image)
(image-toggle-animation)
(image-toggle-animation))
(message "Image speed is now %s" (image-animate-get-speed image))))))
(defun image-increase-speed ()
"Increase the speed of current animated image by a factor of 2."
(interactive)
(image--set-speed 2 t))
(defun image-decrease-speed ()
"Decrease the speed of current animated image by a factor of 2."
(interactive)
(image--set-speed 0.5 t))
(defun image-reverse-speed ()
"Reverse the animation of the current image."
(interactive)
(image--set-speed -1 t))
(defun image-reset-speed ()
"Reset the animation speed of the current image."
(interactive)
(image--set-speed 'reset))
(defun image-goto-frame (n &optional relative)
"Show frame N of a multi-frame image.
Optional argument OFFSET non-nil means interpret N as relative to the
......
......@@ -687,6 +687,19 @@ do not check N is within the range of frames present in the image."
(plist-put (cdr image) :index n)
(force-window-update))
(defun image-animate-get-speed (image)
"Return the speed factor for animating IMAGE."
(or (plist-get (cdr image) :speed) 1))
(defun image-animate-set-speed (image value &optional multiply)
"Set the speed factor for animating IMAGE to VALUE.
With optional argument MULTIPLY non-nil, treat VALUE as a
multiplication factor for the current value."
(plist-put (cdr image) :speed
(if multiply
(* value (image-animate-get-speed image))
value)))
;; 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
......@@ -700,21 +713,28 @@ TIME-ELAPSED is the total time that has elapsed since
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'."
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."
(image-show-frame image n t)
(setq n (1+ n))
(let* ((time (float-time))
(let* ((speed (image-animate-get-speed image))
(time (float-time))
(animation (image-multi-frame-p image))
;; Subtract off the time we took to load the image from the
;; stated delay time.
(delay (max (+ (or (cdr animation) image-default-frame-delay)
(delay (max (+ (* (or (cdr animation) image-default-frame-delay)
(/ 1 (abs speed)))
time (- (float-time)))
image-minimum-frame-delay))
done)
(if (>= n count)
(if limit
(setq n 0)
(setq done t)))
(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)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment