summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChong Yidong <cyd@stupidchicken.com>2011-05-29 17:35:35 -0400
committerChong Yidong <cyd@stupidchicken.com>2011-05-29 17:35:35 -0400
commite8cbec34e8ef069f54c1189a7b6109f768047be8 (patch)
tree1890ec0a32380fed7a288e602405ed14e1c30a5b
parent34809aa6007e2c8ff75f9ec43500e6d34cc43aa3 (diff)
Fix animated gifs (Bug#6981).
* 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.
-rw-r--r--lisp/ChangeLog16
-rw-r--r--lisp/image-mode.el33
-rw-r--r--lisp/image.el75
3 files changed, 82 insertions, 42 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index c54e48ef52..6d4752efec 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -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
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index f4eb5eeaf4..145a15de24 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -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
diff --git a/lisp/image.el b/lisp/image.el
index 3f44be868c..b9ed10eacf 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -590,9 +590,13 @@ Example:
;;; 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.