Subject: bug#72771: 31.0.50; shr html renderer throwing "Specified window is not displaying the current buffer"

From: Jim Porter <[email-masked]>
Date: Sat, 24 Aug 2024 23:11:46 -0700

On 8/24/2024 10:05 PM, Eli Zaretskii wrote:
> Again, the simplicity here is deceptive.

Since you seemed so unsure about my earlier patch, I figured I should be 
extra careful to think about whether there's a better way.

Previously, you'd suggested using 'string-pixel-width' using a few 
characters to compute an average width. After thinking about it, I 
realized that it's actually possible to get the real 
'font->average_width' value using 'string-pixel-width': just use a 
display spec!

   (string-pixel-width
    (propertize some-length-1-string 'display '(space :width 1)))

That works out nicely since then the only function I'm using to compute 
string widths in this code is 'string-pixel-width', so there's less risk 
of different functions having slightly different font handling.

As an added bonus, this new implementation is even simpler than the 
original code that prompted this bug. See attached.

>> Thanks for prompting me to re-read the manual on this. I'd
>> misinterpreted this passage in the documentation for 'query-font':
[snip]
> I don't see how this is different from the text we already have,
> sorry.

Here's another variation on the documentation that might be clearer?

"The average width of the font characters. Emacs uses this value when 
calculating text layout on display. If this is zero, Emacs uses
the value of space-width instead."

(Maybe this could cross reference the section on pixel specifications 
too, or some other documentation about text layout.)

If that doesn't seem any better, that's ok. I'll stop suggesting further 
variations. :)

From 75805447a60e402adf0ff2496260b27ffe412b99 Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Fri, 23 Aug 2024 15:11:24 -0700
Subject: [PATCH] Improve computation of indent depth in SHR and
 'visual-wrap-prefix-mode'

Now, we get the average-width of the current font using
'string-pixel-width' and a specified space display spec, which doesn't
require the buffer to be displayed in a window (bug#72771).

* lisp/net/shr.el (shr-indent):
* lisp/visual-wrap.el (visual-wrap--content-prefix): Fix getting the
font when the buffer isn't displayed in a window.
(visual-wrap-fill-context-prefix): Fix indentation.
---
 lisp/net/shr.el     | 22 +++++++++++-----------
 lisp/visual-wrap.el | 20 +++++++-------------
 2 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index b9ac9f0c8c0..cd0e482aee7 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1051,17 +1051,17 @@ shr-indent
       (if (not shr-use-fonts)
           (insert-char ?\s shr-indentation)
         (insert ?\s)
-        (put-text-property
-         (1- (point)) (point) 'display
-         ;; Set the specified space width in terms of the default width
-         ;; of the current face, like (N . width).  That way, the
-         ;; indentation is calculated correctly when using
-         ;; `text-scale-adjust'.
-         `(space :width (,(if-let ((font (font-at (1- (point))))
-                                   (info (query-font font)))
-                              (/ (float shr-indentation) (aref info 7))
-                            shr-indentation)
-                         . width))))
+        ;; Set the specified space width in units of the average-width
+        ;; of the current font, like (N . width).  That way, the
+        ;; indentation is calculated correctly when using
+        ;; `text-scale-adjust'.
+        (let ((avg-space (propertize (buffer-substring (1- (point)) (point))
+                                     'display '(space :width 1))))
+          (put-text-property
+           (1- (point)) (point) 'display
+           `(space :width (,(/ (float shr-indentation)
+                               (string-pixel-width avg-space (current-buffer)))
+                           . width)))))
       (put-text-property start (+ (point) prefix)
                          'shr-prefix-length (+ prefix (- (point) start))))))
 
diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el
index 902a9e41c5e..76276c0f474 100644
--- a/lisp/visual-wrap.el
+++ b/lisp/visual-wrap.el
@@ -160,20 +160,14 @@ visual-wrap--content-prefix
     prefix)
    (t
     ;; Otherwise, we want the prefix to be whitespace of the same width
-    ;; as the first-line prefix.  If possible, compute the real pixel
-    ;; width of the first-line prefix in canonical-width characters.
-    ;; This is useful if the first-line prefix uses some very-wide
-    ;; characters.
-    (if-let ((font (font-at position))
-             (info (query-font font)))
+    ;; as the first-line prefix.  We want to return an integer width (in
+    ;; units of the font's average-width) large enough to fit the
+    ;; first-line prefix.
+    (let ((avg-space (propertize (buffer-substring position (1+ position))
+                                 'display '(space :width 1))))
         (max (string-width prefix)
              (ceiling (string-pixel-width prefix (current-buffer))
-                      (aref info 7)))
-      ;; We couldn't get the font, so we're in a terminal and
-      ;; `string-pixel-width' is really returning the number of columns.
-      ;; (This is different from `string-width', since that doesn't
-      ;; respect specified spaces.)
-      (string-pixel-width prefix)))))
+                      (string-pixel-width avg-space (current-buffer))))))))
 
 (defun visual-wrap-fill-context-prefix (beg end)
   "Compute visual wrap prefix from text between BEG and END.
@@ -189,7 +183,7 @@ visual-wrap-fill-context-prefix
           ;; make much sense (and is positively harmful in
           ;; taskpaper-mode where paragraph-start matches everything).
           (or (let ((paragraph-start regexp-unmatchable))
-                    (fill-context-prefix beg end))
+                (fill-context-prefix beg end))
                   ;; Note: fill-context-prefix may return nil; See:
                   ;; http://article.gmane.org/gmane.emacs.devel/156285
               ""))
-- 
2.25.1