Subject: 31.0.50; visual-wrap-prefix-mode miscalculates prefix width when scaling text
From: Kévin Le Gouguec <[email-masked]>
To: [email-masked]
Date: Sun, 02 Feb 2025 13:03:16 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

Heya!

Steps to reproduce from emacs -Q:

    C-x C-f repro.rst
    C-x C-+ + [+…]                  ; until e.g. "+6"
    - words
    M-x visual-wrap-prefix-mode

Expectation: no visual change.
Observation: the "- " prefix is propertized with…

    There are text properties here:
      display              (min-width ((6 . width)))
      face                 rst-block
      fontified            t
      wrap-prefix          (space :align-to (6 . width))

… which makes the text look like this:

    -     words

I believe the cause lies in visual-wrap--content-prefix; empirically the
attached patch shows good results on this reproducer, but I landed on it
more by trial-and-error than by rational analysis, so it may be
incorrect or suboptimal (e.g. there may be better text-scale or
string-width APIs to use).

Thanks for your time (& for the love & care visual-wrap has been
receiving lately).

diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el
index 1691ba9c500..12404127190 100644
--- a/lisp/visual-wrap.el
+++ b/lisp/visual-wrap.el
@@ -33,6 +33,8 @@
 
 ;;; Code:
 
+(require 'face-remap)
+
 (defcustom visual-wrap-extra-indent 0
   "Number of extra spaces to indent in `visual-wrap-prefix-mode'.
 
@@ -164,12 +166,16 @@ visual-wrap--content-prefix
     ;; 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))))
+                                 'display '(space :width 1)))
+          (scale (if text-scale-mode
+                     (expt text-scale-mode-step text-scale-mode-amount)
+                   1)))
       ;; Remove any `min-width' display specs since we'll replace with
       ;; our own later in `visual-wrap--apply-to-line' (bug#73882).
       (add-display-text-property 0 (length prefix) 'min-width nil prefix)
       (max (string-width prefix)
-           (ceiling (string-pixel-width prefix (current-buffer))
+           (ceiling (/ (string-pixel-width prefix (current-buffer))
+                       scale)
                     (string-pixel-width avg-space (current-buffer))))))))
 
 (defun visual-wrap-fill-context-prefix (beg end)

Configured using:
 'configure --prefix=/home/peniblec/apps/.emacs.2025-01-18 --with-cairo
 --with-native-compilation=no --with-sqlite3 --with-xinput2'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $LC_TIME: en_GB.UTF-8
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix