diff options
Diffstat (limited to 'lisp/image-mode.el')
-rw-r--r-- | lisp/image-mode.el | 132 |
1 files changed, 94 insertions, 38 deletions
diff --git a/lisp/image-mode.el b/lisp/image-mode.el index 1eb7cd58c3d..b2af3f06a27 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -58,16 +58,25 @@ It is called with one argument, the initial WINPROPS.") "Non-nil to resize the image upon first display. Its value should be one of the following: - nil, meaning no resizing. - - t, meaning to fit the image to the window height and width. - - `fit-height', meaning to fit the image to the window height. - - `fit-width', meaning to fit the image to the window width. - - A number, which is a scale factor (the default size is 1)." + - t, meaning to scale the image down to fit in the window. + - `fit-window', meaning to fit the image to the window. + - A number, which is a scale factor (the default size is 1). + +Resizing will always preserve the aspect ratio of the image." :type '(choice (const :tag "No resizing" nil) - (other :tag "Fit height and width" t) - (const :tag "Fit height" fit-height) - (const :tag "Fit width" fit-width) + (const :tag "Fit to window" fit-window) + (other :tag "Scale down to fit window" t) (number :tag "Scale factor" 1)) - :version "27.1" + :version "29.1" + :group 'image) + +(defcustom image-auto-resize-max-scale-percent nil + "Max size (in percent) to scale up to when `image-auto-resize' is `fit-window'. +Can be either a number larger than 100, or nil, which means no +max size." + :type '(choice (const :tag "No max" nil) + natnum) + :version "29.1" :group 'image) (defcustom image-auto-resize-on-window-resize 1 @@ -82,12 +91,18 @@ resizing according to the value specified in `image-auto-resize'." (defvar-local image-transform-resize nil "The image resize operation. +Non-nil to resize the image upon first display. Its value should be one of the following: - nil, meaning no resizing. - - t, meaning to fit the image to the window height and width. + - t, meaning to scale the image down to fit in the window. + - `fit-window', meaning to fit the image to the window. + - A number, which is a scale factor (the default size is 1). + +There is also support for these values, obsolete since Emacs 29.1: - `fit-height', meaning to fit the image to the window height. - `fit-width', meaning to fit the image to the window width. - - A number, which is a scale factor (the default size is 1).") + +Resizing will always preserve the aspect ratio of the image.") (defvar-local image-transform-scale 1.0 "The scale factor of the image being displayed.") @@ -440,6 +455,15 @@ call." ;;; Image Mode setup +(defcustom image-text-based-formats '(svg xpm) + "List of image formats that use a plain text format. +For such formats, display a message that explains how to edit the +image as text, when opening such images in `image-mode'." + :type '(choice (const :tag "Disable completely" nil) + (repeat :tag "List of formats" sexp)) + :version "29.1" + :group 'image) + (defvar-local image-type nil "The image type for the current Image mode buffer.") @@ -455,8 +479,9 @@ call." ;; Transformation keys (define-key map "sf" 'image-mode-fit-frame) + (define-key map "sw" 'image-transform-fit-to-window) (define-key map "sh" 'image-transform-fit-to-height) - (define-key map "sw" 'image-transform-fit-to-width) + (define-key map "si" 'image-transform-fit-to-width) (define-key map "sb" 'image-transform-fit-both) (define-key map "ss" 'image-transform-set-scale) (define-key map "sr" 'image-transform-set-rotation) @@ -511,12 +536,10 @@ call." "--" ["Fit Frame to Image" image-mode-fit-frame :active t :help "Resize frame to match image"] - ["Fit Image to Window (Best Fit)" image-transform-fit-both - :help "Resize image to match the window height and width"] - ["Fit to Window Height" image-transform-fit-to-height - :help "Resize image to match the window height"] - ["Fit to Window Width" image-transform-fit-to-width - :help "Resize image to match the window width"] + ["Fit Image to Window" image-transform-fit-to-window + :help "Resize image to match the window height and width"] + ["Fit Image to Window (Scale down only)" image-transform-fit-both + :help "Scale image down to match the window height and width"] ["Zoom In" image-increase-size :help "Enlarge the image"] ["Zoom Out" image-decrease-size @@ -605,8 +628,9 @@ call." ;;;###autoload (defun image-mode () "Major mode for image files. -You can use \\<image-mode-map>\\[image-toggle-display] or \\<image-mode-map>\\[image-toggle-hex-display] -to toggle between display as an image and display as text or hex. +You can use \\<image-mode-map>\\[image-toggle-display] or \ +\\[image-toggle-hex-display] to toggle between display +as an image and display as text or hex. Key bindings: \\{image-mode-map}" @@ -680,12 +704,10 @@ Key bindings: (run-mode-hooks 'image-mode-hook) (let ((image (image-get-display-property)) - (msg1 (substitute-command-keys - "Type \\[image-toggle-display] or \\[image-toggle-hex-display] to view the image as ")) - animated) + msg animated) (cond ((null image) - (message "%s" (concat msg1 "an image."))) + (setq msg "an image")) ((setq animated (image-multi-frame-p image)) (setq image-multi-frame t mode-line-process @@ -703,10 +725,13 @@ Key bindings: keymap (down-mouse-1 . image-next-frame) (down-mouse-3 . image-previous-frame))))))) - (message "%s" - (concat msg1 "text. This image has multiple frames."))) + (setq msg "text. This image has multiple frames")) (t - (message "%s" (concat msg1 "text or hex.")))))) + (setq msg "text"))) + (when (memq (plist-get (cdr image) :type) image-text-based-formats) + (message (substitute-command-keys + "Type \\[image-toggle-display] to view the image as %s") + msg)))) ;;;###autoload (define-minor-mode image-minor-mode @@ -753,11 +778,11 @@ on these modes." (image-mode-to-text) ;; Turn on hexl-mode (hexl-mode) - (message "%s" (concat - (substitute-command-keys - "Type \\[image-toggle-hex-display] or \\[image-toggle-display] to view the image as ") - (if (image-get-display-property) - "hex" "an image or text") "."))) + (message (substitute-command-keys + "Type \\[image-toggle-hex-display] or \ +\\[image-toggle-display] to view the image as %s") + (if (image-get-display-property) + "hex" "an image or text"))) (defun image-mode-as-text () "Set a non-image mode as major mode in combination with image minor mode. @@ -773,11 +798,10 @@ See commands `image-mode' and `image-minor-mode' for more information on these modes." (interactive) (image-mode-to-text) - (message "%s" (concat - (substitute-command-keys - "Type \\[image-toggle-display] or \\[image-toggle-hex-display] to view the image as ") - (if (image-get-display-property) - "text" "an image or hex") "."))) + (message (substitute-command-keys + "Type \\[image-toggle-display] to view the image as %s") + (if (image-get-display-property) + "text" "an image"))) (defun image-toggle-display-text () "Show the image file as text. @@ -805,6 +829,21 @@ Remove text properties that display the image." (defvar tar-superior-buffer) (declare-function image-flush "image.c" (spec &optional frame)) +(defun image--scale-within-limits-p (image) + "Return t if `fit-window' will scale image within the customized limits. +The limits are given by the user option +`image-auto-resize-max-scale-percent'." + (or (not image-auto-resize-max-scale-percent) + (let ((scale (/ image-auto-resize-max-scale-percent 100)) + (mw (plist-get (cdr image) :max-width)) + (mh (plist-get (cdr image) :max-height)) + ;; Note: `image-size' looks up and thus caches the + ;; untransformed image. There's no easy way to + ;; prevent that. + (size (image-size image t))) + (or (<= mw (* (car size) scale)) + (<= mh (* (cdr size) scale)))))) + (defun image-toggle-display-image () "Show the image of the image file. Turn the image data into a real image, but only if the whole file @@ -839,7 +878,8 @@ was inserted." filename)) ;; If we have a `fit-width' or a `fit-height', don't limit ;; the size of the image to the window size. - (edges (when (eq image-transform-resize t) + (edges (when (or (eq image-transform-resize t) + (eq image-transform-resize 'fit-window)) (window-inside-pixel-edges (get-buffer-window)))) (max-width (when edges (- (nth 2 edges) (nth 0 edges)))) @@ -886,6 +926,14 @@ was inserted." ;; Type hint. :format (and filename data-p)))) + ;; Handle `fit-window'. + (when (and (eq image-transform-resize 'fit-window) + (image--scale-within-limits-p image)) + (setq image + (cons (car image) + (plist-put (cdr image) :width + (plist-get (cdr image) :max-width))))) + ;; Discard any stale image data before looking it up again. (image-flush image) (setq image (append image (image-transform-properties image))) @@ -1496,21 +1544,29 @@ return value is suitable for appending to an image spec." (defun image-transform-fit-to-height () "Fit the current image to the height of the current window." (interactive) + (declare (obsolete nil "29.1")) (setq image-transform-resize 'fit-height) (image-toggle-display-image)) (defun image-transform-fit-to-width () "Fit the current image to the width of the current window." + (declare (obsolete nil "29.1")) (interactive) (setq image-transform-resize 'fit-width) (image-toggle-display-image)) (defun image-transform-fit-both () - "Fit the current image both to the height and width of the current window." + "Scale the current image down to fit in the current window." (interactive) (setq image-transform-resize t) (image-toggle-display-image)) +(defun image-transform-fit-to-window () + "Fit the current image to the height and width of the current window." + (interactive) + (setq image-transform-resize 'fit-window) + (image-toggle-display-image)) + (defun image-transform-set-rotation (rotation) "Prompt for an angle ROTATION, and rotate the image by that amount. ROTATION should be in degrees." |