diff options
| author | Chong Yidong | 2011-06-07 14:32:12 -0400 |
|---|---|---|
| committer | Chong Yidong | 2011-06-07 14:32:12 -0400 |
| commit | 18af70d0258153a042be9fd71d4eb090f7189a8f (patch) | |
| tree | 81449660fd53df5f0a6e97907e1aeaf631e13879 /lisp/image.el | |
| parent | 2c631e0e829031852440433ff248149c27ba3fde (diff) | |
| download | emacs-18af70d0258153a042be9fd71d4eb090f7189a8f.tar.gz emacs-18af70d0258153a042be9fd71d4eb090f7189a8f.zip | |
Some changes and re-organization for animated gif support.
* lisp/image.el (image-animate-max-time): Moved to image-mode.el.
(create-animated-image): Remove unnecessary function.
(image-animate): Rename from image-animate-start. New arg.
(image-animate-stop): Removed; just use image-animate-timer.
(image-animate-timer): Use car-safe.
(image-animate-timeout): Rename argument.
* lisp/image-mode.el (image-toggle-animation): New command.
(image-mode-map): Bind it to RET.
(image-mode): Update message.
(image-toggle-display-image): Avoid a spurious cache flush.
(image-transform-rotation): Doc fix.
(image-transform-properties): Return quickly in the normal case.
(image-animate-loop): Rename from image-animate-max-time.
Diffstat (limited to 'lisp/image.el')
| -rw-r--r-- | lisp/image.el | 127 |
1 files changed, 44 insertions, 83 deletions
diff --git a/lisp/image.el b/lisp/image.el index b9ed10eacf2..e076c2d09f1 100644 --- a/lisp/image.el +++ b/lisp/image.el | |||
| @@ -590,43 +590,45 @@ Example: | |||
| 590 | 590 | ||
| 591 | ;;; Animated image API | 591 | ;;; Animated image API |
| 592 | 592 | ||
| 593 | (defcustom image-animate-max-time nil | ||
| 594 | "Time in seconds to animate images. | ||
| 595 | If the value is nil, play animations once. | ||
| 596 | If the value is t, loop forever." | ||
| 597 | :type '(choice (const :tag "Play once" nil) | ||
| 598 | (const :tag "Loop forever" t) | ||
| 599 | integer) | ||
| 600 | :version "24.1" | ||
| 601 | :group 'image) | ||
| 602 | |||
| 603 | (defconst image-animated-types '(gif) | 593 | (defconst image-animated-types '(gif) |
| 604 | "List of supported animated image types.") | 594 | "List of supported animated image types.") |
| 605 | 595 | ||
| 606 | ;;;###autoload | 596 | (defun image-animated-p (image) |
| 607 | (defun create-animated-image (file-or-data &optional type data-p &rest props) | 597 | "Return non-nil if image can be animated. |
| 608 | "Create an animated image, and begin animating it. | 598 | Actually, the return value is a cons (NIMAGES . DELAY), where |
| 609 | FILE-OR-DATA is an image file name or image data. | 599 | NIMAGES is the number of sub-images in the animated image and |
| 610 | Optional TYPE is a symbol describing the image type. If TYPE is omitted | 600 | DELAY is the delay in 100ths of a second until the next sub-image |
| 611 | or nil, try to determine the image type from its first few bytes | 601 | shall be displayed." |
| 612 | of image data. If that doesn't work, and FILE-OR-DATA is a file name, | 602 | (cond |
| 613 | use its file extension as image type. | 603 | ((eq (plist-get (cdr image) :type) 'gif) |
| 614 | Optional DATA-P non-nil means FILE-OR-DATA is a string containing image data. | 604 | (let* ((metadata (image-metadata image)) |
| 615 | Optional PROPS are additional image attributes to assign to the image, | 605 | (images (plist-get metadata 'count)) |
| 616 | like, e.g. `:mask MASK'. | 606 | (extdata (plist-get metadata 'extension-data)) |
| 617 | Value is the image created, or nil if images of type TYPE are not supported. | 607 | (anim (plist-get extdata #xF9)) |
| 608 | (tmo (and (integerp images) (> images 1) | ||
| 609 | (stringp anim) (>= (length anim) 4) | ||
| 610 | (+ (aref anim 1) (* (aref anim 2) 256))))) | ||
| 611 | (when tmo | ||
| 612 | (if (eq tmo 0) (setq tmo 10)) | ||
| 613 | (cons images tmo)))))) | ||
| 618 | 614 | ||
| 619 | Images should not be larger than specified by `max-image-size'." | 615 | (defun image-animate (image &optional index limit) |
| 620 | (setq type (image-type file-or-data type data-p)) | 616 | "Start animating IMAGE. |
| 621 | (when (image-type-available-p type) | 617 | Animation occurs by destructively altering the IMAGE spec list. |
| 622 | (let* ((animate (memq type image-animated-types)) | 618 | |
| 623 | (image | 619 | With optional INDEX, begin animating from that animation frame. |
| 624 | (append (list 'image :type type (if data-p :data :file) file-or-data) | 620 | LIMIT specifies how long to animate the image. If omitted or |
| 625 | (if animate '(:index 0)) | 621 | nil, play the animation until the end. If t, loop forever. If a |
| 626 | props))) | 622 | number, play until that number of seconds has elapsed." |
| 627 | (if animate | 623 | (let ((anim (image-animated-p image)) |
| 628 | (image-animate-start image)) | 624 | delay timer) |
| 629 | image))) | 625 | (when anim |
| 626 | (if (setq timer (image-animate-timer image)) | ||
| 627 | (cancel-timer timer)) | ||
| 628 | (setq delay (max (* (cdr anim) 0.01) 0.025)) | ||
| 629 | (run-with-timer 0.2 nil #'image-animate-timeout | ||
| 630 | image (or index 0) (car anim) | ||
| 631 | delay 0 limit)))) | ||
| 630 | 632 | ||
| 631 | (defun image-animate-timer (image) | 633 | (defun image-animate-timer (image) |
| 632 | "Return the animation timer for image IMAGE." | 634 | "Return the animation timer for image IMAGE." |
| @@ -635,78 +637,37 @@ Images should not be larger than specified by `max-image-size'." | |||
| 635 | (while tail | 637 | (while tail |
| 636 | (setq timer (car tail) | 638 | (setq timer (car tail) |
| 637 | tail (cdr tail)) | 639 | tail (cdr tail)) |
| 638 | (if (and (eq (aref timer 5) #'image-animate-timeout) | 640 | (if (and (eq (aref timer 5) 'image-animate-timeout) |
| 639 | (consp (aref timer 6)) | 641 | (eq (car-safe (aref timer 6)) image)) |
| 640 | (eq (car (aref timer 6)) image)) | ||
| 641 | (setq tail nil) | 642 | (setq tail nil) |
| 642 | (setq timer nil))) | 643 | (setq timer nil))) |
| 643 | timer)) | 644 | timer)) |
| 644 | 645 | ||
| 645 | (defun image-animate-start (image) | 646 | (defun image-animate-timeout (image n count delay time-elapsed limit) |
| 646 | "Start animating the image IMAGE. | ||
| 647 | The variable `image-animate-max-time' determines how long to | ||
| 648 | animate for." | ||
| 649 | (let ((anim (image-animated-p image)) | ||
| 650 | delay ; in seconds | ||
| 651 | timer) | ||
| 652 | (when anim | ||
| 653 | (if (setq timer (image-animate-timer image)) | ||
| 654 | (cancel-timer timer)) | ||
| 655 | (setq delay (max (* (cdr anim) 0.01) 0.025)) | ||
| 656 | (run-with-timer 0.2 nil #'image-animate-timeout | ||
| 657 | image 0 (car anim) | ||
| 658 | delay 0 image-animate-max-time)))) | ||
| 659 | |||
| 660 | (defun image-animate-stop (image) | ||
| 661 | "Stop animation of image." | ||
| 662 | (let ((timer (image-animate-timer image))) | ||
| 663 | (when timer | ||
| 664 | (cancel-timer timer)))) | ||
| 665 | |||
| 666 | (defun image-animate-timeout (image n count delay time-elapsed max) | ||
| 667 | "Display animation frame N of IMAGE. | 647 | "Display animation frame N of IMAGE. |
| 668 | N=0 refers to the initial animation frame. | 648 | N=0 refers to the initial animation frame. |
| 669 | COUNT is the total number of frames in the animation. | 649 | COUNT is the total number of frames in the animation. |
| 670 | DELAY is the time between animation frames, in seconds. | 650 | DELAY is the time between animation frames, in seconds. |
| 671 | TIME-ELAPSED is the total time that has elapsed since | 651 | TIME-ELAPSED is the total time that has elapsed since |
| 672 | `image-animate-start' was called. | 652 | `image-animate-start' was called. |
| 673 | MAX determines when to stop. If t, loop forever. If nil, stop | 653 | LIMIT determines when to stop. If t, loop forever. If nil, stop |
| 674 | after displaying the last animation frame. Otherwise, stop | 654 | after displaying the last animation frame. Otherwise, stop |
| 675 | after MAX seconds have elapsed." | 655 | after LIMIT seconds have elapsed." |
| 676 | (let (done) | 656 | (let (done) |
| 677 | (plist-put (cdr image) :index n) | 657 | (plist-put (cdr image) :index n) |
| 678 | (force-window-update) | 658 | (force-window-update) |
| 679 | (setq n (1+ n)) | 659 | (setq n (1+ n)) |
| 680 | (if (>= n count) | 660 | (if (>= n count) |
| 681 | (if max | 661 | (if limit |
| 682 | (setq n 0) | 662 | (setq n 0) |
| 683 | (setq done t))) | 663 | (setq done t))) |
| 684 | (setq time-elapsed (+ delay time-elapsed)) | 664 | (setq time-elapsed (+ delay time-elapsed)) |
| 685 | (if (numberp max) | 665 | (if (numberp limit) |
| 686 | (setq done (>= time-elapsed max))) | 666 | (setq done (>= time-elapsed limit))) |
| 687 | (unless done | 667 | (unless done |
| 688 | (run-with-timer delay nil 'image-animate-timeout | 668 | (run-with-timer delay nil 'image-animate-timeout |
| 689 | image n count delay | 669 | image n count delay |
| 690 | time-elapsed max)))) | 670 | time-elapsed limit)))) |
| 691 | |||
| 692 | (defun image-animated-p (image) | ||
| 693 | "Return non-nil if image is animated. | ||
| 694 | Actually, return value is a cons (IMAGES . DELAY) where IMAGES | ||
| 695 | is the number of sub-images in the animated image, and DELAY | ||
| 696 | is the delay in 100ths of a second until the next sub-image | ||
| 697 | shall be displayed." | ||
| 698 | (cond | ||
| 699 | ((eq (plist-get (cdr image) :type) 'gif) | ||
| 700 | (let* ((metadata (image-metadata image)) | ||
| 701 | (images (plist-get metadata 'count)) | ||
| 702 | (extdata (plist-get metadata 'extension-data)) | ||
| 703 | (anim (plist-get extdata #xF9)) | ||
| 704 | (tmo (and (integerp images) (> images 1) | ||
| 705 | (stringp anim) (>= (length anim) 4) | ||
| 706 | (+ (aref anim 1) (* (aref anim 2) 256))))) | ||
| 707 | (when tmo | ||
| 708 | (if (eq tmo 0) (setq tmo 10)) | ||
| 709 | (cons images tmo)))))) | ||
| 710 | 671 | ||
| 711 | 672 | ||
| 712 | (defcustom imagemagick-types-inhibit | 673 | (defcustom imagemagick-types-inhibit |