Subject: Re: bug#73600: 31.0.50; Visual wrap prefix mode and image display

From: Eli Zaretskii <[email-masked]>
Date: Thu, 03 Oct 2024 13:59:35 +0300

> Date: Wed, 2 Oct 2024 09:37:48 -0700
> Cc: [email-masked]
> From: Jim Porter <[email-masked]>
> 
> On 10/2/2024 8:51 AM, Eli Zaretskii wrote:
> >> Cc: [email-masked]
> >> Date: Wed, 02 Oct 2024 18:42:09 +0300
> >> From: Eli Zaretskii <[email-masked]>
> >>
> >>> In emacs -Q:
> >>> - enable global-visual-wrap-prefix-mode,
> >>> - open the attached image.
> >>
> >> In a build with --enable-checking, this recipe causes an assertion
> >> violation:
> > 
> > And in Emacs 30 the problem doesn't happen, so this is some regression
> > in Emacs 31.  Probably due to my changes in commit 71505b723c9f.
> > 
> > Jim, any ideas or suggestions?
> 
> Strangely, this doesn't seem to happen with every image. "splash.png" in 
> the Emacs repository seems fine, for example. I also can't reproduce 
> this in EWW, even by opening the bad image reported in this bug.

It depends on the width of the image and the contents of the image
file.  As soon as you show an image whose width is as wide or wider
than the window, and/or the image file has newline bytes, the problem
happens.

Note that displaying splash.svg, the problem happens even through the
image is not wider than window.  See below why this happens.

I've installed a fix which avoids the assertion violations in a build
with --enable-checking.  The fix does not prevent displaying multiple
images where only one should be shown -- because that is AFAICT a bug
in visual-wrap-prefix-mode, and should be fixed there.

What happens is that displaying an image in a buffer places a single
'display' property on the entire buffer portion which should be
displayed as an image, and the value of the property is the image
spec.  When visiting an image file, that property spans the entire
contents of the image file.  In this situation, the analysis of the
buffer text performed by visual-wrap-prefix-mode, which looks at
newlines and tries to calculate the suitable prefix width, is
completely wrong, because the buffer text (which are just the raw
bytes of the image file) is replaced on display by the image, and the
calculations based on character width are all wrong.  But
visual-wrap-prefix-mode does still make these calculations, and as
result could decide that a min-width or align-to display property
should be placed on some of these raw bytes.  Since
visual-wrap-prefix-mode uses add-display-text-property, which attempts
to keep existing display properties when it adds additional ones, the
result is that the single display property that specified the image is
broken into several identical display properties (some with min-width
added, some without).  And since these properties are not 'eq' to one
another, Emacs shows N identical images instead of just one.

The solution, I think, is for visual-wrap-prefix-mode to ignore text
that is covered by replacing display properties, at least those which
specify images, xwidgets, fringes, etc.  It's possible that we want to
pay attention to display properties whose value is a string, but not
to any others.

> One option might simply be to disable 'visual-wrap-prefix-mode' when in 
> 'image-mode'. I don't think wrapping is useful in that context.

I think image-mode is just the tip of a very large iceberg, see above:
visual-wrap-prefix-mode currently doesn't correctly handle text
covered by display properties.  I think this bug was uncovered when we
removed on master a few artificial restrictions on min-width, such as
non-support for display and overlay strings.