aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Porter2024-06-23 14:48:32 -0700
committerJim Porter2024-07-04 12:14:37 -0700
commit208207c1c07fb4669c6b7d64c27236074f996ae4 (patch)
tree8727370853cbdcc46899e1003863e139636075dd
parent6d082f3c79269f00308d6e8b7d31d6a119376fe2 (diff)
downloademacs-208207c1c07fb4669c6b7d64c27236074f996ae4.tar.gz
emacs-208207c1c07fb4669c6b7d64c27236074f996ae4.zip
Fix the different image zoom levels in SHR to work as expected
* lisp/net/shr.el (shr-image-zoom-levels): New option. (shr-image-zoom-level-alist): New variable. (shr-zoom-image): Take POSITION and ZOOM-LEVEL arguments. Consult 'shr-image-zoom-levels'. (shr-put-image): Use 'shr-image-zoom-level-alist'. (shr-rescale-image): Only reset width *or* height when either is too large. (shr--image-zoom-original-size, shr--image-zoom-image-size) (shr--image-zoom-fill-height): New functions. * etc/NEWS: Announce this change.
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/net/shr.el139
2 files changed, 93 insertions, 51 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 3e74d724f48..1af252e8a8f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -54,6 +54,11 @@ matter how large or small that was). Now, SHR slices any images taller
54than 'shr-sliced-image-height'. For more information, see the "(eww) 54than 'shr-sliced-image-height'. For more information, see the "(eww)
55Advanced" node in the EWW manual. 55Advanced" node in the EWW manual.
56 56
57---
58*** You can now customize the image zoom levels to cycle through.
59By customizing 'shr-image-zoom-levels', you can change the list of zoom
60levels that SHR cycles through when calling 'shr-zoom-image'.
61
57 62
58* New Modes and Packages in Emacs 31.1 63* New Modes and Packages in Emacs 31.1
59 64
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 7e9a8c6d1c0..8b62691bfb6 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -219,6 +219,25 @@ interpreted as a multiple of the height of default font."
219 :version "30.1" 219 :version "30.1"
220 :type '(choice (const nil) (cons number number))) 220 :type '(choice (const nil) (cons number number)))
221 221
222(defcustom shr-image-zoom-levels '(fit original fill-height)
223 "A list of image zoom levels to cycle through with `shr-zoom-image'.
224The first element in the list is the initial zoom level. Each element
225can be one of the following symbols:
226
227* `fit': Display the image at its original size as requested by the
228 page, shrinking it to fit in the current window if necessary.
229* `original': Display the image at its original size as requested by the
230 page.
231* `image': Display the image at its full size (ignoring the width/height
232 specified by the HTML).
233* `fill-height': Display the image zoomed to fill the height of the
234current window."
235 :version "31.1"
236 :type '(set (choice (const :tag "Fit to window size" fit)
237 (const :tag "Original size" original)
238 (const :tag "Full image size" image)
239 (const :tag "Fill window height" fill-height))))
240
222(defvar shr-content-function nil 241(defvar shr-content-function nil
223 "If bound, this should be a function that will return the content. 242 "If bound, this should be a function that will return the content.
224This is used for cid: URLs, and the function is called with the 243This is used for cid: URLs, and the function is called with the
@@ -621,35 +640,52 @@ the URL of the image to the kill buffer instead."
621 (list (current-buffer) (1- (point)) (point-marker)) 640 (list (current-buffer) (1- (point)) (point-marker))
622 t)))) 641 t))))
623 642
624(defun shr-zoom-image () 643(defvar shr-image-zoom-level-alist
625 "Cycle the image size. 644 `((fit "Zoom to fit" shr-rescale-image)
645 (original "Zoom to original size" shr--image-zoom-original-size)
646 (image "Zoom to full image size" shr--image-zoom-image-size)
647 (fill-height "Zoom to fill window height" shr--image-zoom-fill-height))
648 "An alist of possible image zoom levels.
649Each element is of the form (SYMBOL DESC FUNCTION). SYMBOL is the
650symbol identifying this level, as used by `shr-image-zoom-levels' (which
651see). DESC is a string describing the level.
652
653FUNCTION is a function that returns a properly-zoomed image; it takes
654the following arguments:
655
656* DATA: The image data in string form.
657* CONTENT-TYPE: The content-type of the image, if any.
658* WIDTH: The width as specified by the HTML \"width\" attribute, if any.
659* HEIGHT: The height as specified by the HTML \"height\" attribute, if
660 any.")
661
662(defun shr-zoom-image (&optional position zoom-level)
663 "Change the zoom level of the image at POSITION.
664
626The size will cycle through the default size, the original size, and 665The size will cycle through the default size, the original size, and
627full-buffer size." 666full-buffer size."
628 (interactive) 667 (interactive "d")
629 (let ((url (get-text-property (point) 'image-url))) 668 (unless position (setq position (point)))
669 (let ((url (get-text-property position 'image-url)))
630 (if (not url) 670 (if (not url)
631 (message "No image under point") 671 (message "No image under point")
632 (let* ((end (or (next-single-property-change (point) 'image-url) 672 (unless zoom-level
673 (let ((last-zoom (get-text-property position 'image-zoom)))
674 (setq zoom-level (or (cadr (memq last-zoom shr-image-zoom-levels))
675 (car shr-image-zoom-levels)))))
676 (let* ((end (or (next-single-property-change position 'image-url)
633 (point-max))) 677 (point-max)))
634 (start (or (previous-single-property-change end 'image-url) 678 (start (or (previous-single-property-change end 'image-url)
635 (point-min))) 679 (point-min)))
636 (dom-size (get-text-property (point) 'image-dom-size)) 680 (dom-size (get-text-property position 'image-dom-size))
637 (zoom (get-text-property (point) 'image-zoom))
638 (next-zoom (cond ((or (eq zoom 'default)
639 (null zoom))
640 'original)
641 ((eq zoom 'original)
642 'full)
643 ((eq zoom 'full)
644 'default)))
645 (buffer-read-only nil)) 681 (buffer-read-only nil))
646 ;; Delete the old picture. 682 ;; Delete the old picture.
647 (put-text-property start end 'display nil) 683 (put-text-property start end 'display nil)
648 (message "Inserting %s..." url) 684 (message "%s" (cadr (assq zoom-level shr-image-zoom-level-alist)))
649 (url-retrieve url #'shr-image-fetched 685 (url-retrieve url #'shr-image-fetched
650 `(,(current-buffer) ,start 686 `(,(current-buffer) ,start
651 ,(set-marker (make-marker) end) 687 ,(set-marker (make-marker) end)
652 (:zoom ,next-zoom 688 (:zoom ,zoom-level
653 :width ,(car dom-size) 689 :width ,(car dom-size)
654 :height ,(cdr dom-size))) 690 :height ,(cdr dom-size)))
655 t))))) 691 t)))))
@@ -1147,7 +1183,9 @@ You can specify the following optional properties:
1147* `:height': The height of the image as specified by the HTML 1183* `:height': The height of the image as specified by the HTML
1148 \"height\" attribute." 1184 \"height\" attribute."
1149 (if (display-graphic-p) 1185 (if (display-graphic-p)
1150 (let* ((zoom (plist-get flags :zoom)) 1186 (let* ((zoom (or (plist-get flags :zoom)
1187 (car shr-image-zoom-levels)))
1188 (zoom-function (nth 2 (assq zoom shr-image-zoom-level-alist)))
1151 (data (if (consp spec) 1189 (data (if (consp spec)
1152 (car spec) 1190 (car spec)
1153 spec)) 1191 spec))
@@ -1155,22 +1193,15 @@ You can specify the following optional properties:
1155 (cadr spec))) 1193 (cadr spec)))
1156 (start (point)) 1194 (start (point))
1157 (image (cond 1195 (image (cond
1158 ((eq zoom 'original)
1159 (create-image data nil t :ascent shr-image-ascent
1160 :format content-type))
1161 ((eq content-type 'image/svg+xml) 1196 ((eq content-type 'image/svg+xml)
1162 (when (image-type-available-p 'svg) 1197 (when (image-type-available-p 'svg)
1163 (create-image data 'svg t :ascent shr-image-ascent))) 1198 (create-image data 'svg t :ascent shr-image-ascent)))
1164 ((eq zoom 'full) 1199 (zoom-function
1165 (ignore-errors 1200 (ignore-errors
1166 (shr-rescale-image data content-type 1201 (funcall zoom-function data content-type
1167 (plist-get flags :width) 1202 (plist-get flags :width)
1168 (plist-get flags :height)))) 1203 (plist-get flags :height))))
1169 (t 1204 (t (error "Unrecognized zoom level %s" zoom)))))
1170 (ignore-errors
1171 (shr-rescale-image data content-type
1172 (plist-get flags :width)
1173 (plist-get flags :height)))))))
1174 (when image 1205 (when image
1175 ;; The trailing space can confuse shr-insert into not 1206 ;; The trailing space can confuse shr-insert into not
1176 ;; putting any space after inline images. 1207 ;; putting any space after inline images.
@@ -1243,27 +1274,33 @@ width/height instead."
1243 (or max-height 1274 (or max-height
1244 (- (nth 3 edges) (nth 1 edges)))))) 1275 (- (nth 3 edges) (nth 1 edges))))))
1245 (scaling (image-compute-scaling-factor image-scaling-factor))) 1276 (scaling (image-compute-scaling-factor image-scaling-factor)))
1246 (when (or (and width 1277 (when (and width (> (* width scaling) max-width))
1247 (> width max-width)) 1278 (setq width nil))
1248 (and height 1279 (when (and height (> (* height scaling) max-height))
1249 (> height max-height))) 1280 (setq height nil))
1250 (setq width nil 1281 (create-image
1251 height nil)) 1282 data (shr--image-type) t
1252 (if (and width height 1283 :ascent shr-image-ascent
1253 (< (* width scaling) max-width) 1284 :width width
1254 (< (* height scaling) max-height)) 1285 :height height
1255 (create-image 1286 :max-width max-width
1256 data (shr--image-type) t 1287 :max-height max-height
1257 :ascent shr-image-ascent 1288 :format content-type))))
1258 :width width 1289
1259 :height height 1290(defun shr--image-zoom-original-size (data content-type width height)
1260 :format content-type) 1291 (create-image data (shr--image-type) t :ascent shr-image-ascent
1261 (create-image 1292 :width width :height height :format content-type))
1262 data (shr--image-type) t 1293
1263 :ascent shr-image-ascent 1294(defun shr--image-zoom-image-size (data content-type _width _height)
1264 :max-width max-width 1295 (create-image data nil t :ascent shr-image-ascent :format content-type))
1265 :max-height max-height 1296
1266 :format content-type))))) 1297(defun shr--image-zoom-fill-height (data content-type _width _height)
1298 (let* ((edges (window-inside-pixel-edges
1299 (get-buffer-window (current-buffer))))
1300 (height (truncate (* shr-max-image-proportion
1301 (- (nth 3 edges) (nth 1 edges))))))
1302 (create-image data (shr--image-type) t :ascent shr-image-ascent
1303 :height height :format content-type)))
1267 1304
1268;; url-cache-extract autoloads url-cache. 1305;; url-cache-extract autoloads url-cache.
1269(declare-function url-cache-create-filename "url-cache" (url)) 1306(declare-function url-cache-create-filename "url-cache" (url))