diff options
| author | Lars Ingebrigtsen | 2016-02-10 12:03:55 +1100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2016-02-10 12:03:55 +1100 |
| commit | f7405a094b5f2ef642f920a17ce8e30ff81f6f35 (patch) | |
| tree | ca70eb2fb5c2777ba47e96e68e8ceb692b0e2cf9 | |
| parent | 6c54541fcc4cb4b57a476234f385aebdc3292a25 (diff) | |
| download | emacs-f7405a094b5f2ef642f920a17ce8e30ff81f6f35.tar.gz emacs-f7405a094b5f2ef642f920a17ce8e30ff81f6f35.zip | |
Put a keymap on images created with insert-image and friends
* lisp/image.el (image-save): New command.
(image-rotate): Ditto.
(image-map): New keymap.
(insert-image): Put the image-map on all images.
(insert-sliced-image): Ditto.
* doc/lispref/display.texi (Showing Images): Document the
image map.
| -rw-r--r-- | doc/lispref/display.texi | 20 | ||||
| -rw-r--r-- | etc/NEWS | 17 | ||||
| -rw-r--r-- | lisp/image.el | 63 |
3 files changed, 89 insertions, 11 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index c8e7e4fa5c1..26f3de40e91 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi | |||
| @@ -5508,6 +5508,26 @@ cache, it can always be displayed, even if the value of | |||
| 5508 | @code{max-image-size} is subsequently changed (@pxref{Image Cache}). | 5508 | @code{max-image-size} is subsequently changed (@pxref{Image Cache}). |
| 5509 | @end defvar | 5509 | @end defvar |
| 5510 | 5510 | ||
| 5511 | Images inserted with the insertion functions above also get a local | ||
| 5512 | keymap installed in the text properties (or overlays) that span the | ||
| 5513 | displayed image. This keymap defines the following commands: | ||
| 5514 | |||
| 5515 | @table @kbd | ||
| 5516 | @item + | ||
| 5517 | Increase the image size (@code{image-increase-size}). A prefix value | ||
| 5518 | of @samp{4} means to increase the size by 40%. The default is 20%. | ||
| 5519 | |||
| 5520 | @item - | ||
| 5521 | Decrease the image size (@code{image-increase-size}). A prefix value | ||
| 5522 | of @samp{4} means to decrease the size by 40%. The default is 20%. | ||
| 5523 | |||
| 5524 | @item r | ||
| 5525 | Rotate the image by 90 degrees (@code{image-rotate}). | ||
| 5526 | |||
| 5527 | @item o | ||
| 5528 | Save the image to a file (@code{image-save}). | ||
| 5529 | @end table | ||
| 5530 | |||
| 5511 | @node Multi-Frame Images | 5531 | @node Multi-Frame Images |
| 5512 | @subsection Multi-Frame Images | 5532 | @subsection Multi-Frame Images |
| 5513 | @cindex multi-frame images | 5533 | @cindex multi-frame images |
| @@ -824,11 +824,6 @@ while in non-`visual-line-mode' it will move the point to the indented | |||
| 824 | header’s value. | 824 | header’s value. |
| 825 | 825 | ||
| 826 | +++ | 826 | +++ |
| 827 | ** Images are automatically scaled before displaying based on the | ||
| 828 | `image-scaling-factor' variable (if Emacs supports scaling the images | ||
| 829 | in question). | ||
| 830 | |||
| 831 | +++ | ||
| 832 | ** In Show Paren Mode, a parenthesis can be highlighted when point | 827 | ** In Show Paren Mode, a parenthesis can be highlighted when point |
| 833 | stands inside it, and certain parens can be highlighted when point is | 828 | stands inside it, and certain parens can be highlighted when point is |
| 834 | at BOL or EOL, or in whitespace there. To enable these, customize, | 829 | at BOL or EOL, or in whitespace there. To enable these, customize, |
| @@ -839,6 +834,18 @@ respectively, `show-paren-when-point-inside-paren' or | |||
| 839 | ** If gpg2 exists on the system, it is now used as the default value | 834 | ** If gpg2 exists on the system, it is now used as the default value |
| 840 | of `epg-gpg-program' (instead of gpg). | 835 | of `epg-gpg-program' (instead of gpg). |
| 841 | 836 | ||
| 837 | ** Images | ||
| 838 | |||
| 839 | +++ | ||
| 840 | *** Images are automatically scaled before displaying based on the | ||
| 841 | `image-scaling-factor' variable (if Emacs supports scaling the images | ||
| 842 | in question). | ||
| 843 | |||
| 844 | *** Images inserted with `insert-image' and related functions get a | ||
| 845 | keymap put into the text properties (or overlays) that span the | ||
| 846 | image. This keymap binds keystrokes for manipulating size and | ||
| 847 | rotation, as well as saving the image to a file. | ||
| 848 | |||
| 842 | ** Lisp mode | 849 | ** Lisp mode |
| 843 | 850 | ||
| 844 | --- | 851 | --- |
diff --git a/lisp/image.el b/lisp/image.el index b69d3b15a43..4f2733adb7e 100644 --- a/lisp/image.el +++ b/lisp/image.el | |||
| @@ -139,6 +139,15 @@ based on the font pixel size." | |||
| 139 | :group 'image | 139 | :group 'image |
| 140 | :version "25.2") | 140 | :version "25.2") |
| 141 | 141 | ||
| 142 | ;; Map put into text properties on images. | ||
| 143 | (defvar image-map | ||
| 144 | (let ((map (make-keymap))) | ||
| 145 | (define-key map "-" 'image-decrease-size) | ||
| 146 | (define-key map "+" 'image-increase-size) | ||
| 147 | (define-key map "r" 'image-rotate) | ||
| 148 | (define-key map "o" 'image-save) | ||
| 149 | map)) | ||
| 150 | |||
| 142 | (defun image-load-path-for-library (library image &optional path no-error) | 151 | (defun image-load-path-for-library (library image &optional path no-error) |
| 143 | "Return a suitable search path for images used by LIBRARY. | 152 | "Return a suitable search path for images used by LIBRARY. |
| 144 | 153 | ||
| @@ -466,6 +475,7 @@ means display it in the right marginal area." | |||
| 466 | (put-text-property 0 (length string) 'display prop string) | 475 | (put-text-property 0 (length string) 'display prop string) |
| 467 | (overlay-put overlay 'put-image t) | 476 | (overlay-put overlay 'put-image t) |
| 468 | (overlay-put overlay 'before-string string) | 477 | (overlay-put overlay 'before-string string) |
| 478 | (overlay-put overlay 'map image-map) | ||
| 469 | overlay))) | 479 | overlay))) |
| 470 | 480 | ||
| 471 | 481 | ||
| @@ -505,7 +515,9 @@ height of the image; integer values are taken as pixel values." | |||
| 505 | (add-text-properties start (point) | 515 | (add-text-properties start (point) |
| 506 | `(display ,(if slice | 516 | `(display ,(if slice |
| 507 | (list (cons 'slice slice) image) | 517 | (list (cons 'slice slice) image) |
| 508 | image) rear-nonsticky (display))))) | 518 | image) |
| 519 | rear-nonsticky (display) | ||
| 520 | keymap ,image-map)))) | ||
| 509 | 521 | ||
| 510 | 522 | ||
| 511 | ;;;###autoload | 523 | ;;;###autoload |
| @@ -541,7 +553,8 @@ The image is automatically split into ROWS x COLS slices." | |||
| 541 | (insert string) | 553 | (insert string) |
| 542 | (add-text-properties start (point) | 554 | (add-text-properties start (point) |
| 543 | `(display ,(list (list 'slice x y dx dy) image) | 555 | `(display ,(list (list 'slice x y dx dy) image) |
| 544 | rear-nonsticky (display))) | 556 | rear-nonsticky (display) |
| 557 | keymap ,image-map)) | ||
| 545 | (setq x (+ x dx)))) | 558 | (setq x (+ x dx)))) |
| 546 | (setq x 0.0 | 559 | (setq x 0.0 |
| 547 | y (+ y dy)) | 560 | y (+ y dy)) |
| @@ -931,17 +944,55 @@ default is 20%." | |||
| 931 | (- 1 (/ n 10)) | 944 | (- 1 (/ n 10)) |
| 932 | 0.8))) | 945 | 0.8))) |
| 933 | 946 | ||
| 934 | (defun image-change-size (factor) | 947 | (defun image--get-image () |
| 935 | (unless (fboundp 'imagemagick-types) | 948 | (let ((image (or (get-text-property (point) 'display) |
| 936 | (error "Can't rescale images without ImageMagick support")) | 949 | ;; `put-image' uses overlays, so find an image in |
| 937 | (let ((image (get-text-property (point) 'display))) | 950 | ;; the overlays. |
| 951 | (seq-find (lambda (overlay) | ||
| 952 | (overlay-get overlay 'display)) | ||
| 953 | (overlays-at (point)))))) | ||
| 938 | (when (or (not (consp image)) | 954 | (when (or (not (consp image)) |
| 939 | (not (eq (car image) 'image))) | 955 | (not (eq (car image) 'image))) |
| 940 | (error "No image under point")) | 956 | (error "No image under point")) |
| 957 | image)) | ||
| 958 | |||
| 959 | (defun image--get-imagemagick-and-warn () | ||
| 960 | (unless (fboundp 'imagemagick-types) | ||
| 961 | (error "Can't rescale images without ImageMagick support")) | ||
| 962 | (let ((image (image--get-image))) | ||
| 963 | (image-flush image) | ||
| 941 | (plist-put (cdr image) :type 'imagemagick) | 964 | (plist-put (cdr image) :type 'imagemagick) |
| 965 | image)) | ||
| 966 | |||
| 967 | (defun image-change-size (factor) | ||
| 968 | (let ((image (image--get-imagemagick-and-warn))) | ||
| 942 | (plist-put (cdr image) :scale | 969 | (plist-put (cdr image) :scale |
| 943 | (* (or (plist-get (cdr image) :scale) 1) factor)))) | 970 | (* (or (plist-get (cdr image) :scale) 1) factor)))) |
| 944 | 971 | ||
| 972 | (defun image-rotate () | ||
| 973 | "Rotate the image under point by 90 degrees clockwise." | ||
| 974 | (interactive) | ||
| 975 | (let ((image (image--get-imagemagick-and-warn))) | ||
| 976 | (plist-put (cdr image) :rotation | ||
| 977 | (float (+ (or (plist-get (cdr image) :rotation) 0) 90))))) | ||
| 978 | |||
| 979 | (defun image-save () | ||
| 980 | "Save the image under point." | ||
| 981 | (interactive) | ||
| 982 | (let ((image (get-text-property (point) 'display))) | ||
| 983 | (when (or (not (consp image)) | ||
| 984 | (not (eq (car image) 'image))) | ||
| 985 | (error "No image under point")) | ||
| 986 | (with-temp-buffer | ||
| 987 | (let ((file (plist-get (cdr image) :file))) | ||
| 988 | (if file | ||
| 989 | (if (not (file-exists-p file)) | ||
| 990 | (error "File %s no longer exists" file) | ||
| 991 | (insert-file-contents-literally file)) | ||
| 992 | (insert (plist-get (cdr image) :data)))) | ||
| 993 | (write-region (point-min) (point-max) | ||
| 994 | (read-file-name "Write image to file: "))))) | ||
| 995 | |||
| 945 | (provide 'image) | 996 | (provide 'image) |
| 946 | 997 | ||
| 947 | ;;; image.el ends here | 998 | ;;; image.el ends here |