emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 80852f8 3/3: Use placeholder images in shr to avoid


From: Lars Ingebrigtsen
Subject: [Emacs-diffs] master 80852f8 3/3: Use placeholder images in shr to avoid text moving around
Date: Sat, 20 Feb 2016 07:04:25 +0000

branch: master
commit 80852f843e69b81618f29cfb9aa4b074946cb3c4
Author: Lars Ingebrigtsen <address@hidden>
Commit: Lars Ingebrigtsen <address@hidden>

    Use placeholder images in shr to avoid text moving around
    
    * lisp/net/shr.el (shr-rescale-image): Pass in width/height
    from the HTML.
    (shr-tag-img): Ditto.
    (shr-string-number): New function.
    (shr-make-placeholder-image): Make placeholder images.
    (shr-tag-img): Insert them if we have SVG support.
---
 etc/NEWS        |    7 +++
 lisp/net/shr.el |  111 +++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 99 insertions(+), 19 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 95ca8d3..33c1b13 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -779,6 +779,13 @@ textual parts of a web page and display only that, leaving 
menus and
 the like off the page.
 
 ---
+*** Images that are being loaded are now marked with grey
+"placeholder" images of the size specified by the HTML.  They are then
+replaced by the real images asynchronously, which will also now
+respect width/height HTML specs (unless they specify widths/heights
+bigger than the current window).
+
+---
 *** You can now use several eww buffers in parallel by renaming eww
 buffers you want to keep separate.
 
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 46aea79..78862b3 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -36,6 +36,7 @@
 (require 'subr-x)
 (require 'dom)
 (require 'seq)
+(require 'svg)
 
 (defgroup shr nil
   "Simple HTML Renderer"
@@ -963,10 +964,14 @@ element is the data blob and the second element is the 
content-type."
                      (create-image data 'svg t :ascent 100))
                     ((eq size 'full)
                      (ignore-errors
-                       (shr-rescale-image data content-type)))
+                       (shr-rescale-image data content-type
+                                           (plist-get flags :width)
+                                           (plist-get flags :height))))
                     (t
                      (ignore-errors
-                       (shr-rescale-image data content-type))))))
+                       (shr-rescale-image data content-type
+                                           (plist-get flags :width)
+                                           (plist-get flags :height)))))))
         (when image
          ;; When inserting big-ish pictures, put them at the
          ;; beginning of the line.
@@ -989,21 +994,37 @@ element is the data blob and the second element is the 
content-type."
        image)
     (insert (or alt ""))))
 
-(defun shr-rescale-image (data &optional content-type)
-  "Rescale DATA, if too big, to fit the current buffer."
+(defun shr-rescale-image (data content-type width height)
+  "Rescale DATA, if too big, to fit the current buffer.
+WIDTH and HEIGHT are the sizes given in the HTML data, if any."
   (if (not (and (fboundp 'imagemagick-types)
                 (get-buffer-window (current-buffer))))
       (create-image data nil t :ascent 100)
-    (let ((edges (window-inside-pixel-edges
-                 (get-buffer-window (current-buffer)))))
-      (create-image
-       data 'imagemagick t
-       :ascent 100
-       :max-width (truncate (* shr-max-image-proportion
-                              (- (nth 2 edges) (nth 0 edges))))
-       :max-height (truncate (* shr-max-image-proportion
-                               (- (nth 3 edges) (nth 1 edges))))
-       :format content-type))))
+    (let* ((edges (window-inside-pixel-edges
+                   (get-buffer-window (current-buffer))))
+           (max-width (truncate (* shr-max-image-proportion
+                                   (- (nth 2 edges) (nth 0 edges)))))
+           (max-height (truncate (* shr-max-image-proportion
+                                    (- (nth 3 edges) (nth 1 edges))))))
+      (when (or (and width
+                     (> width max-width))
+                (and height
+                     (> height max-height)))
+        (setq width nil
+              height nil))
+      (if (and width height)
+          (create-image
+           data 'imagemagick t
+           :ascent 100
+           :width width
+           :height height
+           :format content-type)
+        (create-image
+         data 'imagemagick t
+         :ascent 100
+         :max-width max-width
+         :max-height max-height
+         :format content-type)))))
 
 ;; url-cache-extract autoloads url-cache.
 (declare-function url-cache-create-filename "url-cache" (url))
@@ -1427,6 +1448,8 @@ The preference is a float determined from 
`shr-prefer-media-type'."
     (when (> (current-column) 0)
       (insert "\n"))
     (let ((alt (dom-attr dom 'alt))
+          (width (shr-string-number (dom-attr dom 'width)))
+          (height (shr-string-number (dom-attr dom 'height)))
          (url (shr-expand-url (or url (dom-attr dom 'src)))))
       (let ((start (point-marker)))
        (when (zerop (length alt))
@@ -1440,7 +1463,8 @@ The preference is a float determined from 
`shr-prefer-media-type'."
               (string-match "\\`data:" url))
          (let ((image (shr-image-from-data (substring url (match-end 0)))))
            (if image
-               (funcall shr-put-image-function image alt)
+               (funcall shr-put-image-function image alt
+                         (list :width width :height height))
              (insert alt))))
         ((and (not shr-inhibit-images)
               (string-match "\\`cid:" url))
@@ -1449,7 +1473,8 @@ The preference is a float determined from 
`shr-prefer-media-type'."
            (if (or (not shr-content-function)
                    (not (setq image (funcall shr-content-function url))))
                (insert alt)
-             (funcall shr-put-image-function image alt))))
+             (funcall shr-put-image-function image alt
+                       (list :width width :height height)))))
         ((or shr-inhibit-images
              (and shr-blocked-images
                   (string-match shr-blocked-images url)))
@@ -1457,17 +1482,23 @@ The preference is a float determined from 
`shr-prefer-media-type'."
           (shr-insert alt))
         ((and (not shr-ignore-cache)
               (url-is-cached (shr-encode-url url)))
-         (funcall shr-put-image-function (shr-get-image-data url) alt))
+         (funcall shr-put-image-function (shr-get-image-data url) alt
+                   (list :width width :height height)))
         (t
-         (insert alt " ")
          (when (and shr-ignore-cache
                     (url-is-cached (shr-encode-url url)))
            (let ((file (url-cache-create-filename (shr-encode-url url))))
              (when (file-exists-p file)
                (delete-file file))))
+          (when (image-type-available-p 'svg)
+            (insert-image
+             (shr-make-placeholder-image dom)
+             (or alt "")))
+          (insert " ")
          (url-queue-retrieve
           (shr-encode-url url) 'shr-image-fetched
-          (list (current-buffer) start (set-marker (make-marker) (1- (point))))
+          (list (current-buffer) start (set-marker (make-marker) (1- (point)))
+                 (list :width width :height height))
           t t)))
        (when (zerop shr-table-depth) ;; We are not in a table.
          (put-text-property start (point) 'keymap shr-image-map)
@@ -1479,6 +1510,48 @@ The preference is a float determined from 
`shr-prefer-media-type'."
                             (shr-fill-text
                              (or (dom-attr dom 'title) alt))))))))
 
+(defun shr-string-number (string)
+  (if (null string)
+      nil
+    (setq string (replace-regexp-in-string "[^0-9]" "" string))
+    (if (zerop (length string))
+        nil
+      (string-to-number string))))
+
+(defun shr-make-placeholder-image (dom)
+  (let* ((edges (and
+                 (get-buffer-window (current-buffer))
+                 (window-inside-pixel-edges
+                  (get-buffer-window (current-buffer)))))
+         (scaling (image-compute-scaling-factor image-scaling-factor))
+         (width (truncate
+                 (* (or (shr-string-number (dom-attr dom 'width)) 100)
+                    scaling)))
+         (height (truncate
+                  (* (or (shr-string-number (dom-attr dom 'height)) 100)
+                     scaling)))
+         (max-width
+          (and edges
+               (truncate (* shr-max-image-proportion
+                            (- (nth 2 edges) (nth 0 edges))))))
+         (max-height (and edges
+                          (truncate (* shr-max-image-proportion
+                               (- (nth 3 edges) (nth 1 edges))))))
+         svg image)
+    (when (and max-width
+               (> width max-width))
+      (setq height (truncate (* (/ (float max-width) width) height))
+            width max-width))
+    (when (and max-height
+               (> height max-height))
+      (setq width (truncate (* (/ (float max-height) height) width))
+            height max-height))
+    (setq svg (svg-create width height))
+    (svg-gradient svg "background" 'linear '((0 . "#b0b0b0") (100 . 
"#808080")))
+    (svg-rectangle svg 0 0 width height :gradient "background")
+    (let ((image (svg-image svg)))
+      (image-set-property image :ascent 100))))
+
 (defun shr-tag-pre (dom)
   (let ((shr-folding-mode 'none)
        (shr-current-font 'default))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]