diff options
| author | Kim F. Storm | 2010-03-07 21:02:20 +0200 |
|---|---|---|
| committer | Juri Linkov | 2010-03-07 21:02:20 +0200 |
| commit | 0608aa457fd97d1c9a116152a77544b07f7fd55a (patch) | |
| tree | 40aaded8d817bc2a78a28cbfa6089c0f175db429 | |
| parent | dd5de7c6e4efc3c49e01ce75313303ba78e31b94 (diff) | |
| download | emacs-0608aa457fd97d1c9a116152a77544b07f7fd55a.tar.gz emacs-0608aa457fd97d1c9a116152a77544b07f7fd55a.zip | |
Animated image API.
http://lists.gnu.org/archive/html/emacs-devel/2010-03/msg00211.html
* image.el (image-animate-max-time): New defcustom.
(image-animated-types): New defconst.
(create-animated-image, image-animate-timer)
(image-animate-start, image-animate-stop, image-animate-timeout)
(image-animated-p): New functions.
* image-mode.el (image-toggle-display-image):
Replace `create-image' with `create-animated-image'.
| -rw-r--r-- | lisp/ChangeLog | 14 | ||||
| -rw-r--r-- | lisp/image-mode.el | 2 | ||||
| -rw-r--r-- | lisp/image.el | 104 |
3 files changed, 119 insertions, 1 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8ac8d5ed450..cf3be1586e5 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2010-03-07 Kim F. Storm <storm@cua.dk> | ||
| 2 | |||
| 3 | Animated image API. | ||
| 4 | http://lists.gnu.org/archive/html/emacs-devel/2010-03/msg00211.html | ||
| 5 | |||
| 6 | * image.el (image-animate-max-time): New defcustom. | ||
| 7 | (image-animated-types): New defconst. | ||
| 8 | (create-animated-image, image-animate-timer) | ||
| 9 | (image-animate-start, image-animate-stop, image-animate-timeout) | ||
| 10 | (image-animated-p): New functions. | ||
| 11 | |||
| 12 | * image-mode.el (image-toggle-display-image): | ||
| 13 | Replace `create-image' with `create-animated-image'. | ||
| 14 | |||
| 1 | 2010-01-27 Stephen Berman <stephen.berman@gmx.net> | 15 | 2010-01-27 Stephen Berman <stephen.berman@gmx.net> |
| 2 | 16 | ||
| 3 | * calendar/diary-lib.el (diary-unhide-everything): Handle narrowed | 17 | * calendar/diary-lib.el (diary-unhide-everything): Handle narrowed |
diff --git a/lisp/image-mode.el b/lisp/image-mode.el index f3cdc05da16..1d999b50007 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el | |||
| @@ -464,7 +464,7 @@ was inserted." | |||
| 464 | (buffer-substring-no-properties (point-min) (point-max))) | 464 | (buffer-substring-no-properties (point-min) (point-max))) |
| 465 | filename)) | 465 | filename)) |
| 466 | (type (image-type file-or-data nil data-p)) | 466 | (type (image-type file-or-data nil data-p)) |
| 467 | (image (create-image file-or-data type data-p)) | 467 | (image (create-animated-image file-or-data type data-p)) |
| 468 | (props | 468 | (props |
| 469 | `(display ,image | 469 | `(display ,image |
| 470 | intangible ,image | 470 | intangible ,image |
diff --git a/lisp/image.el b/lisp/image.el index 944c6135e23..e5dfe1a3996 100644 --- a/lisp/image.el +++ b/lisp/image.el | |||
| @@ -584,7 +584,111 @@ Example: | |||
| 584 | (declare (doc-string 3)) | 584 | (declare (doc-string 3)) |
| 585 | `(defvar ,symbol (find-image ',specs) ,doc)) | 585 | `(defvar ,symbol (find-image ',specs) ,doc)) |
| 586 | 586 | ||
| 587 | |||
| 588 | ;;; Animated image API | ||
| 587 | 589 | ||
| 590 | (defcustom image-animate-max-time 30 | ||
| 591 | "Time in seconds to animate images." | ||
| 592 | :type 'integer | ||
| 593 | :version "22.1" | ||
| 594 | :group 'image) | ||
| 595 | |||
| 596 | (defconst image-animated-types '(gif) | ||
| 597 | "List of supported animated image types.") | ||
| 598 | |||
| 599 | ;;;###autoload | ||
| 600 | (defun create-animated-image (file-or-data &optional type data-p &rest props) | ||
| 601 | "Create an animated image. | ||
| 602 | FILE-OR-DATA is an image file name or image data. | ||
| 603 | Optional TYPE is a symbol describing the image type. If TYPE is omitted | ||
| 604 | or nil, try to determine the image type from its first few bytes | ||
| 605 | of image data. If that doesn't work, and FILE-OR-DATA is a file name, | ||
| 606 | use its file extension as image type. | ||
| 607 | Optional DATA-P non-nil means FILE-OR-DATA is a string containing image data. | ||
| 608 | Optional PROPS are additional image attributes to assign to the image, | ||
| 609 | like, e.g. `:mask MASK'. | ||
| 610 | Value is the image created, or nil if images of type TYPE are not supported. | ||
| 611 | |||
| 612 | Images should not be larger than specified by `max-image-size'." | ||
| 613 | (setq type (image-type file-or-data type data-p)) | ||
| 614 | (when (image-type-available-p type) | ||
| 615 | (let* ((animate (memq type image-animated-types)) | ||
| 616 | (image | ||
| 617 | (append (list 'image :type type (if data-p :data :file) file-or-data) | ||
| 618 | (if animate '(:index 0 :mask heuristic)) | ||
| 619 | props))) | ||
| 620 | (if animate | ||
| 621 | (image-animate-start image)) | ||
| 622 | image))) | ||
| 623 | |||
| 624 | (defun image-animate-timer (image) | ||
| 625 | "Return the animation timer for image IMAGE." | ||
| 626 | ;; See cancel-function-timers | ||
| 627 | (let ((tail timer-list) timer) | ||
| 628 | (while tail | ||
| 629 | (setq timer (car tail) | ||
| 630 | tail (cdr tail)) | ||
| 631 | (if (and (eq (aref timer 5) #'image-animate-timeout) | ||
| 632 | (consp (aref timer 6)) | ||
| 633 | (eq (car (aref timer 6)) image)) | ||
| 634 | (setq tail nil) | ||
| 635 | (setq timer nil))) | ||
| 636 | timer)) | ||
| 637 | |||
| 638 | (defun image-animate-start (image &optional max-time) | ||
| 639 | "Start animation of image IMAGE. | ||
| 640 | Optional second arg MAX-TIME is number of seconds to animate image, | ||
| 641 | or t to animate infinitely." | ||
| 642 | (let ((anim (image-animated-p image)) | ||
| 643 | timer tmo) | ||
| 644 | (when anim | ||
| 645 | (if (setq timer (image-animate-timer image)) | ||
| 646 | (setcar (nthcdr 3 (aref timer 6)) max-time) | ||
| 647 | (setq tmo (* (cdr anim) 0.01)) | ||
| 648 | (setq max-time (or max-time image-animate-max-time)) | ||
| 649 | (run-with-timer tmo nil #'image-animate-timeout | ||
| 650 | image 1 (car anim) | ||
| 651 | (if (numberp max-time) | ||
| 652 | (- max-time tmo) | ||
| 653 | max-time)))))) | ||
| 654 | |||
| 655 | (defun image-animate-stop (image) | ||
| 656 | "Stop animation of image." | ||
| 657 | (let ((timer (image-animate-timer image))) | ||
| 658 | (when timer | ||
| 659 | (cancel-timer timer)))) | ||
| 660 | |||
| 661 | (defun image-animate-timeout (image ino count time-left) | ||
| 662 | (if (>= ino count) | ||
| 663 | (setq ino 0)) | ||
| 664 | (plist-put (cdr image) :index ino) | ||
| 665 | (force-window-update) | ||
| 666 | (let ((anim (image-animated-p image)) tmo) | ||
| 667 | (when anim | ||
| 668 | (setq tmo (* (cdr anim) 0.01)) | ||
| 669 | (unless (and (= ino 0) (numberp time-left) (< time-left tmo)) | ||
| 670 | (run-with-timer tmo nil #'image-animate-timeout | ||
| 671 | image (1+ ino) count | ||
| 672 | (if (numberp time-left) | ||
| 673 | (- time-left tmo) | ||
| 674 | time-left)))))) | ||
| 675 | |||
| 676 | (defun image-animated-p (image) | ||
| 677 | "Return non-nil if image is animated. | ||
| 678 | Actually, return value is a cons (IMAGES . DELAY) where IMAGES | ||
| 679 | is the number of sub-images in the animated image, and DELAY | ||
| 680 | is the delay in 100ths of a second until the next sub-image | ||
| 681 | shall be displayed." | ||
| 682 | (cond | ||
| 683 | ((eq (plist-get (cdr image) :type) 'gif) | ||
| 684 | (let* ((extdata (image-extension-data image)) | ||
| 685 | (images (plist-get extdata 'count)) | ||
| 686 | (anim (plist-get extdata #xF9))) | ||
| 687 | (and (integerp images) (> images 1) | ||
| 688 | (stringp anim) (>= (length anim) 4) | ||
| 689 | (cons images (+ (aref anim 1) (* (aref anim 2) 256)))))))) | ||
| 690 | |||
| 691 | |||
| 588 | (provide 'image) | 692 | (provide 'image) |
| 589 | 693 | ||
| 590 | ;; arch-tag: 8e76a07b-eb48-4f3e-a7a0-1a7ba9f096b3 | 694 | ;; arch-tag: 8e76a07b-eb48-4f3e-a7a0-1a7ba9f096b3 |