GNU bug report logs - #77042
31.0.50; `string-pixel-width' could return wrong results with alternative properties

Previous Next

Package: emacs;

Reported by: David Ponce <da_vid <at> orange.fr>

Date: Sat, 15 Mar 2025 22:45:02 UTC

Severity: normal

Found in version 31.0.50

Done: Eli Zaretskii <eliz <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: David Ponce <da_vid <at> orange.fr>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 77042 <at> debbugs.gnu.org
Subject: bug#77042: 31.0.50; `string-pixel-width' could return wrong results with alternative properties
Date: Sun, 16 Mar 2025 11:31:21 +0100
[Message part 1 (text/plain, inline)]
On 2025-03-16 08:31, Eli Zaretskii wrote:
>> Date: Sat, 15 Mar 2025 23:43:33 +0100
>> From:  David Ponce via "Bug reports for GNU Emacs,
>>   the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>>
>> (let ((text0 (propertize "This text" 'face 'variable-pitch))
>>         (text1 (propertize "This text" 'my-face 'variable-pitch)))
>>     (with-temp-buffer
>>       (setq-local char-property-alias-alist '((face my-face)))
>>       (list
>>        (string-pixel-width text0 (current-buffer))
>>        (string-pixel-width text1 (current-buffer)))))
>>
>> Normally the result should be a list of two identical numbers.  But,
>> on my config, the result is (89 117) instead of expected (89 89).
>>
>> This problem is similar to the already solved case with
>> `face-remapping-alist', as is the solution.
>>                           
>> I propose the attached patch to fix this and slightly simplify the
>> code.  On my configuration, the new code has no significant impact on
>> performance.
> 
> Thanks, please see some comments below.
> 
>> +      ;; Setup current buffer to correctly compute pixel width.
>> +      (when buffer
>> +        (if (local-variable-p 'face-remapping-alist buffer)
>> +            (setq-local face-remapping-alist
>> +                        (buffer-local-value 'face-remapping-alist
>> +                                            buffer)))
>> +        (if (local-variable-p 'char-property-alias-alist buffer)
>> +            (setq-local char-property-alias-alist
>> +                        (buffer-local-value 'char-property-alias-alist
>> +                                            buffer))))
> 
> What about default-text-properties? shouldn't it get the same
> treatment?

Yes, you are right.  I updated the patch to include this case and a
new test.

2025-03-16  David Ponce  <da_vid <at> orange.fr>

	Fix possible wrong result of `string-pixel-width' with alternate
	and default properties.  Create regression tests.

	* lisp/emacs-lisp/subr-x.el (string-pixel-width): Like for
	`face-remapping-alist', use in work buffer the value of
	`char-property-alias-alist' and `default-text-properties'
	local to the passed buffer, to correctly compute pixel width.

	* test/lisp/misc-tests.el: Add tests for `string-pixel-width'.


> 
>> -      (add-text-properties
>> -       (point-min) (point-max) '(display-line-numbers-disable t))
>> -      ;; Prefer `remove-text-properties' to `propertize' to avoid
>> -      ;; creating a new string on each call.
>> -      (remove-text-properties
>> -       (point-min) (point-max) '(line-prefix nil wrap-prefix nil))
>> -      (setq line-prefix nil wrap-prefix nil)
>> +      (add-text-properties (point-min) (point-max)
>> +                           '( display-line-numbers-disable t
>> +                              line-prefix "" wrap-prefix ""))
> 
> What is the rationale for this hunk?  Was there any problem with the
> original code?

No problem.  But the new code is simpler and should be more efficient.
To disable `display-line-numbers', `line-prefix' and `wrap-prefix', an
unique call to `add-text-properties' can achieve the same result as
the previous implementation which called `add-text properties', then
`remove-text-properties', then `setq' twice.

> 
> In any case, please don't leave a space after an opening parenthesis.

Sorry, I thought it was correct to add a space after the opening
parenthesis to correctly indent a lisp data expression.  I rewrote the
expression to avoid this.

Regarding the proposed tests, I noticed that those involving faces
always pass when run in batch, but work as expected interactively.
Probably because face attributes don't make sense in batch mode?

I mentioned this point in a comment before such tests, because I don't
know if it is possible to limit them to be run interactively.

Thank you for your review and help!
[string-pixel-width-fix-alt-def-props-plus-tests-V1.patch (text/x-patch, attachment)]

This bug report was last modified 141 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.