]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix animated gifs (Bug#6981).
authorChong Yidong <cyd@stupidchicken.com>
Sun, 29 May 2011 21:35:35 +0000 (17:35 -0400)
committerChong Yidong <cyd@stupidchicken.com>
Sun, 29 May 2011 21:35:35 +0000 (17:35 -0400)
* lisp/image-mode.el (image-toggle-display-image): Ensure that the
image spec passed to the animate timer is the same object as in
the the buffer's display property.
(image-transform-properties): Doc fix.

* lisp/image.el (image-animate-max-time): Default to nil.

* lisp/image.el (image-animate-max-time): Allow nil and t values.
Default to nil.
(create-animated-image): Doc fix.
(image-animate-start): Remove second arg; just use
image-animate-max-time.
(image-animate-timeout): Doc fix.  Args changed.

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

index c54e48ef52a21000ab98d88659c2f9c6f6202e9c..6d4752efec0f6b06a9f91ff2e959111b27c51a75 100644 (file)
@@ -1,3 +1,19 @@
+2011-05-29  Chong Yidong  <cyd@stupidchicken.com>
+
+       * image.el (image-animate-max-time): Allow nil and t values.
+       Default to nil.
+       (create-animated-image): Doc fix.
+       (image-animate-start): Remove second arg; just use
+       image-animate-max-time.
+       (image-animate-timeout): Doc fix.  Args changed.
+
+       * image-mode.el (image-toggle-display-image): Ensure that the
+       image spec passed to the animate timer is the same object as in
+       the the buffer's display property (Bug#6981).
+       (image-transform-properties): Doc fix.
+
+       * image.el (image-animate-max-time): Default to nil.
+
 2011-05-29  Martin Rudalics  <rudalics@gmx.at>
 
        * menu-bar.el (kill-this-buffer-enabled-p): Avoid looping over
index f4eb5eeaf451757e9dd247f04991b516ba09e0c5..145a15de24621e2aa32a6766233596371bdfd34e 100644 (file)
@@ -484,18 +484,26 @@ was inserted."
                            (buffer-substring-no-properties (point-min) (point-max)))
                         filename))
         (type (image-type file-or-data nil data-p))
-         (image0 (create-animated-image file-or-data type data-p))
-        (image (append image0
-                        (image-transform-properties image0)))
-        (props
+        ;; Don't use create-animated-image here; that would start the
+        ;; timer, which works by altering the spec destructively.
+        ;; But we still need to append the transformation properties,
+        ;; which would make a new list.
+        (image (create-image file-or-data type data-p))
+        (inhibit-read-only t)
+        (buffer-undo-list t)
+        (modified (buffer-modified-p))
+        props)
+
+    (setq image (append image (image-transform-properties image)))
+    (setq props
          `(display ,image
                    intangible ,image
                    rear-nonsticky (display intangible)
                    read-only t front-sticky (read-only)))
-        (inhibit-read-only t)
-        (buffer-undo-list t)
-        (modified (buffer-modified-p)))
     (image-flush image)
+    ;; Begin the animation, if any.
+    (image-animate-start image)
+
     (let ((buffer-file-truename nil)) ; avoid changing dir mtime by lock_file
       (add-text-properties (point-min) (point-max) props)
       (restore-buffer-modified-p modified))
@@ -584,10 +592,13 @@ Its value should be one of the following:
 (defvar image-transform-rotation 0.0)
 
 (defun image-transform-properties (display)
-  "Rescale and/or rotate the current image.
-The scale factor and rotation angle are given by the variables
-`image-transform-resize' and `image-transform-rotation'.  This
-takes effect only if Emacs is compiled with ImageMagick support."
+  "Return rescaling/rotation properties for the Image mode buffer.
+These properties are suitable for appending to an image spec;
+they are determined by the variables `image-transform-resize' and
+`image-transform-rotation'.
+
+Recaling and rotation properties only take effect if Emacs is
+compiled with ImageMagick support."
   (let* ((size (image-size display t))
         (height
          (cond
index 3f44be868cea374de3592e5d191b93f573dd9aa2..b9ed10eacf21a275c8b838f3de24fbbc358906b6 100644 (file)
@@ -590,9 +590,13 @@ Example:
 \f
 ;;; Animated image API
 
-(defcustom image-animate-max-time 30
-  "Time in seconds to animate images."
-  :type 'integer
+(defcustom image-animate-max-time nil
+  "Time in seconds to animate images.
+If the value is nil, play animations once.
+If the value is t, loop forever."
+  :type '(choice (const :tag "Play once" nil)
+                (const :tag "Loop forever" t)
+                integer)
   :version "24.1"
   :group 'image)
 
@@ -601,7 +605,7 @@ Example:
 
 ;;;###autoload
 (defun create-animated-image (file-or-data &optional type data-p &rest props)
-  "Create an animated image.
+  "Create an animated image, and begin animating it.
 FILE-OR-DATA is an image file name or image data.
 Optional TYPE is a symbol describing the image type.  If TYPE is omitted
 or nil, try to determine the image type from its first few bytes
@@ -638,22 +642,20 @@ Images should not be larger than specified by `max-image-size'."
        (setq timer nil)))
     timer))
 
-(defun image-animate-start (image &optional max-time)
-  "Start animation of image IMAGE.
-Optional second arg MAX-TIME is number of seconds to animate image,
-or t to animate infinitely."
+(defun image-animate-start (image)
+  "Start animating the image IMAGE.
+The variable `image-animate-max-time' determines how long to
+animate for."
   (let ((anim (image-animated-p image))
-       timer tmo)
+       delay ; in seconds
+       timer)
     (when anim
       (if (setq timer (image-animate-timer image))
-         (setcar (nthcdr 3 (aref timer 6)) max-time)
-       (setq tmo (* (cdr anim) 0.01))
-       (setq max-time (or max-time image-animate-max-time))
-       (run-with-timer tmo nil #'image-animate-timeout
-                       image 1 (car anim)
-                       (if (numberp max-time)
-                           (- max-time tmo)
-                         max-time))))))
+         (cancel-timer timer))
+      (setq delay (max (* (cdr anim) 0.01) 0.025))
+      (run-with-timer 0.2 nil #'image-animate-timeout
+                     image 0 (car anim)
+                     delay 0 image-animate-max-time))))
 
 (defun image-animate-stop (image)
   "Stop animation of image."
@@ -661,20 +663,31 @@ or t to animate infinitely."
     (when timer
       (cancel-timer timer))))
 
-(defun image-animate-timeout (image ino count time-left)
-  (if (>= ino count)
-      (setq ino 0))
-  (plist-put (cdr image) :index ino)
-  (force-window-update)
-  (let ((anim (image-animated-p image)) tmo)
-    (when anim
-      (setq tmo (* (cdr anim) 0.01))
-      (unless (and (= ino 0) (numberp time-left) (< time-left tmo))
-       (run-with-timer tmo nil #'image-animate-timeout
-                       image (1+ ino) count
-                       (if (numberp time-left)
-                           (- time-left tmo)
-                         time-left))))))
+(defun image-animate-timeout (image n count delay time-elapsed max)
+  "Display animation frame N of IMAGE.
+N=0 refers to the initial animation frame.
+COUNT is the total number of frames in the animation.
+DELAY is the time between animation frames, in seconds.
+TIME-ELAPSED is the total time that has elapsed since
+`image-animate-start' was called.
+MAX determines when to stop.  If t, loop forever.  If nil, stop
+ after displaying the last animation frame.  Otherwise, stop
+ after MAX seconds have elapsed."
+  (let (done)
+    (plist-put (cdr image) :index n)
+    (force-window-update)
+    (setq n (1+ n))
+    (if (>= n count)
+       (if max
+           (setq n 0)
+         (setq done t)))
+    (setq time-elapsed (+ delay time-elapsed))
+    (if (numberp max)
+       (setq done (>= time-elapsed max)))
+    (unless done
+      (run-with-timer delay nil 'image-animate-timeout
+                     image n count delay
+                     time-elapsed max))))
 
 (defun image-animated-p (image)
   "Return non-nil if image is animated.