]> git.eshelyaron.com Git - emacs.git/commitdiff
Add functions to change the speed of animated images
authorGlenn Morris <rgm@gnu.org>
Fri, 16 Aug 2013 06:33:08 +0000 (23:33 -0700)
committerGlenn Morris <rgm@gnu.org>
Fri, 16 Aug 2013 06:33:08 +0000 (23:33 -0700)
* 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.

etc/NEWS
lisp/ChangeLog
lisp/image-mode.el
lisp/image.el

index ef76f308303ac82939ec6491aae28e5046a05252..8bf72ddfedded202867051d137f0c75b1fb0cede 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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
 
 ---
index 9119b34d52c6964ad385604243712313b0a1e7c7..cad6788f0e80a928e119f3761132c9ce6bc7fdb2 100644 (file)
@@ -1,3 +1,15 @@
+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
index 30dfd045b466e7105164b8544b42774154e900cb..f9bbbcdb1abf7e4a2ad24ee449c0e065e7622cbd 100644 (file)
@@ -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
index d213c5d6d79ade57ed19cff904b52d02622ce59f..6c15a7d0b96836d42421351727e4519d3085a7e6 100644 (file)
@@ -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)))