* Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
@ 2024-10-23 5:01 Jimmy Yuen Ho Wong
2024-10-23 8:01 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-23 5:01 UTC (permalink / raw)
To: Emacs-Devel devel
[-- Attachment #1: Type: text/plain, Size: 1815 bytes --]
Dear emacs-devel,
Recently I've been trying to mold Corfu
<https://github.com/minad/corfu/pull/508> to render every string in every
face in pixel precision but I've run into some slight performance issues
when truncating strings. The motivation for this is
`truncate-string-to-width` not only does not speak pixels, but also doesn't
understand composed characters such as emojis. It just chops off the emoji
byte sequence in the middle as described in the PR, so I had to write a
custom `truncate-string-to-pixel-width` function using `string-glyph-split`
and `string-pixel-width` to measure character widths, which seems... silly.
I've looked into how to get the width of a glyph from a font object by
employing some dark magic of undocumented internal functions and wrongly
documented functions such as `char-displayable-p`, `font-info`,
`lglyth-width`, `lgstring-glyph`, `open-font` etc in combination of
`composition-get-gstring`, which is correct and fast enough.... for glyph
strings with no faces. Then I looked into reverse engineering the face font
selection process, which quickly pushed the run time up 2 orders of
magnitude due to the anonymous face + face attribute inheritance + face
lists madness. Then when I realized I still didn't deal with display text
properties, I threw my hands up.
It'd be really nice if we could have a really performant C function that
can truncate strings correctly and preferably in pixel precision.
Alternatively, a `glyph-pixel-width` that implements a fast path in C
that's somewhat akin to the process I described above, but also handles
display text properties correctly would be nice.
I don't really know enough about Emacs C internals WRT to font rendering to
implement this so I'm just throwing this idea out there.
Does this make sense?
Jimmy Yuen Ho Wong
[-- Attachment #2: Type: text/html, Size: 2224 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-23 5:01 Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C Jimmy Yuen Ho Wong
@ 2024-10-23 8:01 ` Eli Zaretskii
2024-10-23 13:52 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-23 8:01 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Wed, 23 Oct 2024 06:01:18 +0100
>
> Recently I've been trying to mold Corfu to render every string in every face in pixel precision but I've run into
> some slight performance issues when truncating strings. The motivation for this is `truncate-string-to-width`
> not only does not speak pixels, but also doesn't understand composed characters such as emojis. It just
> chops off the emoji byte sequence in the middle as described in the PR, so I had to write a custom
> `truncate-string-to-pixel-width` function using `string-glyph-split` and `string-pixel-width` to measure character
> widths, which seems... silly.
>
> I've looked into how to get the width of a glyph from a font object by employing some dark magic of
> undocumented internal functions and wrongly documented functions such as `char-displayable-p`, `font-info`,
> `lglyth-width`, `lgstring-glyph`, `open-font` etc in combination of `composition-get-gstring`, which is correct and
> fast enough.... for glyph strings with no faces. Then I looked into reverse engineering the face font selection
> process, which quickly pushed the run time up 2 orders of magnitude due to the anonymous face + face
> attribute inheritance + face lists madness. Then when I realized I still didn't deal with display text properties, I
> threw my hands up.
>
> It'd be really nice if we could have a really performant C function that can truncate strings correctly and
> preferably in pixel precision. Alternatively, a `glyph-pixel-width` that implements a fast path in C that's
> somewhat akin to the process I described above, but also handles display text properties correctly would be
> nice.
>
> I don't really know enough about Emacs C internals WRT to font rendering to implement this so I'm just
> throwing this idea out there.
I know next to nothing about Corfu, so I have hard time understanding
what you are trying to do and why. Basically, the Emacs display
engine already truncates stuff it displays, so it is completely
unclear to me why you'd need to do that in Lisp.
In particular, "truncate strings in pixel precision" makes no sense to
me, since strings on display are made of characters (more accurately,
"grapheme clusters"), so any reasonable truncation will always work at
the grapheme-cluster granularity, not at pixel granularity.
So please describe your problem in much more detail, assuming that I
know nothing about Corfu and its display-related tricks.
Thanks.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-23 8:01 ` Eli Zaretskii
@ 2024-10-23 13:52 ` Jimmy Yuen Ho Wong
2024-10-23 17:39 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-23 13:52 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1689 bytes --]
On Wed, Oct 23, 2024 at 9:01 AM Eli Zaretskii <eliz@gnu.org> wrote:
> I know next to nothing about Corfu, so I have hard time understanding
> what you are trying to do and why. Basically, the Emacs display
> engine already truncates stuff it displays, so it is completely
> unclear to me why you'd need to do that in Lisp.
>
Corfu is like Company, it's a completion frontend that formats a list of
completion candidates to fit inside a confined pop up box.
> In particular, "truncate strings in pixel precision" makes no sense to
> me, since strings on display are made of characters (more accurately,
> "grapheme clusters"), so any reasonable truncation will always work at
> the grapheme-cluster granularity, not at pixel granularity.
>
As described, `truncate-string-to-width` doesn't even truncate at grapheme
cluster granularity correctly.
A `truncate-string-to-pixel-width` function is needed because propertized
strings may consist of display space text properties, images, emojis in a
different font, and faces in variable fonts, which all affect glyph widths,
you can't simply assume every glyph will take up 1 column. As a result,
when you calculate some `end-column` and whether it has reached the width
constraint in pixels, one would necessarily need to know the exact width in
pixels for each glyph. Converting the width constraint in pixels to columns
in order to supply it as the second parameter to a correctly implemented
`truncate-string-to-width` amounts to the exact same procedure. Therefore,
either a `truncate-string-to-pixel-width` or `glyph-pixel-width` function
is needed, because `string-pixel-width` is very expensive.
[-- Attachment #2: Type: text/html, Size: 2282 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-23 13:52 ` Jimmy Yuen Ho Wong
@ 2024-10-23 17:39 ` Eli Zaretskii
2024-10-23 20:03 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-23 17:39 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Wed, 23 Oct 2024 14:52:53 +0100
> Cc: emacs-devel@gnu.org
>
> On Wed, Oct 23, 2024 at 9:01 AM Eli Zaretskii <eliz@gnu.org> wrote:
>
> I know next to nothing about Corfu, so I have hard time understanding
> what you are trying to do and why. Basically, the Emacs display
> engine already truncates stuff it displays, so it is completely
> unclear to me why you'd need to do that in Lisp.
>
> Corfu is like Company, it's a completion frontend that formats a list of completion candidates to fit inside a
> confined pop up box.
Thanks, but that doesn't explain enough. Please tell more about the
need to truncate completion candidates "inside a confined pop up box".
If that box is displayed, why doesn't Emacs truncate the text
automatically? Or maybe I don't understand how this "pop up box",
whatever it is, is displayed?
> A `truncate-string-to-pixel-width` function is needed because propertized strings may consist of display space
> text properties, images, emojis in a different font, and faces in variable fonts, which all affect glyph widths, you
> can't simply assume every glyph will take up 1 column. As a result, when you calculate some `end-column`
> and whether it has reached the width constraint in pixels, one would necessarily need to know the exact width
> in pixels for each glyph. Converting the width constraint in pixels to columns in order to supply it as the second
> parameter to a correctly implemented `truncate-string-to-width` amounts to the exact same procedure.
> Therefore, either a `truncate-string-to-pixel-width` or `glyph-pixel-width` function is needed, because
> `string-pixel-width` is very expensive.
So the issue is not "pixel-wise truncation", the issue is to take
variable-width display elements into account when truncating, is that
right?
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-23 17:39 ` Eli Zaretskii
@ 2024-10-23 20:03 ` Jimmy Yuen Ho Wong
2024-10-24 9:55 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-23 20:03 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1653 bytes --]
>
> Thanks, but that doesn't explain enough. Please tell more about the
> need to truncate completion candidates "inside a confined pop up box".
> If that box is displayed, why doesn't Emacs truncate the text
> automatically? Or maybe I don't understand how this "pop up box",
> whatever it is, is displayed?
Each completion in a list of completion candidates is a triple of
(candidate string, prefix, annotation), all in varying widths. Aligning
these 3 columns requires calculating paddings. Since there are paddings,
the padding between the candidate string and the annotation can also be
arbitrarily large. Naive truncation that truncates the entire concatenated
line against the width of the pop up box, which is actually the window
width in a child frame, may leave some arbitrarily long empty space in the
end. In addition, naive truncation does not replace extra characters in the
relevant columns with ellipses to indicate truncation happened. Please look
at the link in my first email for further details.
> So the issue is not "pixel-wise truncation", the issue is to take
> variable-width display elements into account when truncating, is that
> right?
>
To be precise, by " truncate strings correctly and preferably in pixel
precision", I mean truncation that respects pixel width constraints (and
grapheme clusters, as clarified by you). Truncating variable-width display
elements on GUIs necessitate the ability to calculate the widths of the
individual elements, I call this the hypothetical `glyph-pixel-width`.
Whether it is exposed to Elisp is less important to a hypothetical
`truncate-string-to-pixel-width` for my use case.
[-- Attachment #2: Type: text/html, Size: 2107 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-23 20:03 ` Jimmy Yuen Ho Wong
@ 2024-10-24 9:55 ` Eli Zaretskii
2024-10-24 14:26 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-24 9:55 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Wed, 23 Oct 2024 21:03:55 +0100
> Cc: emacs-devel@gnu.org
>
> Each completion in a list of completion candidates is a triple of (candidate string, prefix, annotation), all in
> varying widths. Aligning these 3 columns requires calculating paddings. Since there are paddings, the
> padding between the candidate string and the annotation can also be arbitrarily large. Naive truncation that
> truncates the entire concatenated line against the width of the pop up box, which is actually the window width
> in a child frame, may leave some arbitrarily long empty space in the end. In addition, naive truncation does
> not replace extra characters in the relevant columns with ellipses to indicate truncation happened. Please look
> at the link in my first email for further details.
>
> So the issue is not "pixel-wise truncation", the issue is to take
> variable-width display elements into account when truncating, is that
> right?
>
> To be precise, by " truncate strings correctly and preferably in pixel precision", I mean truncation that respects
> pixel width constraints (and grapheme clusters, as clarified by you). Truncating variable-width display
> elements on GUIs necessitate the ability to calculate the widths of the individual elements, I call this the
> hypothetical `glyph-pixel-width`. Whether it is exposed to Elisp is less important to a hypothetical
> `truncate-string-to-pixel-width` for my use case.
OK, thanks.
So let me see if I understand the issue. You want to create in a
child frame a display such as below:
<icon1><candidate1> <Type1>
<icon2><longer-name-candidate> <AnotherType>
...
And you want to do it in a way that all the "Type"s are aligned to the
right (i.e. end at the right edge of the frame), no matter what is
shown in the <icon>s and in the <candidate>s, which could be of
different width and could include characters of different fonts and
even images/emoji. Is that correct, or is there something else?
If the above is what you want, and since the popup is actually a
frame, my first suggestion would be to use :align-to display property
on the whitespace between the <candidate>s and the <Type>s. Did you
try that?
The advantage of :align-to is that you don't have to measure the
pixel-width of the candidate names, only the pixel-width of each
<Type> string (to correctly set up the offset from the right edge of
the text area) -- the rest will be done by the display engine. And
the display engine always does everything in pixel resolution.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 9:55 ` Eli Zaretskii
@ 2024-10-24 14:26 ` Jimmy Yuen Ho Wong
2024-10-24 14:39 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-24 14:26 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1717 bytes --]
>
> So let me see if I understand the issue. You want to create in a
> child frame a display such as below:
>
> <icon1><candidate1> <Type1>
> <icon2><longer-name-candidate> <AnotherType>
> ...
>
> And you want to do it in a way that all the "Type"s are aligned to the
> right (i.e. end at the right edge of the frame), no matter what is
> shown in the <icon>s and in the <candidate>s, which could be of
> different width and could include characters of different fonts and
> even images/emoji. Is that correct, or is there something else?
>
> If the above is what you want, and since the popup is actually a
> frame, my first suggestion would be to use :align-to display property
> on the whitespace between the <candidate>s and the <Type>s. Did you
> try that?
>
> The advantage of :align-to is that you don't have to measure the
> pixel-width of the candidate names, only the pixel-width of each
> <Type> string (to correctly set up the offset from the right edge of
> the text area) -- the rest will be done by the display engine. And
> the display engine always does everything in pixel resolution.
>
The current implementation wraps every line with some additional margin and
a custom thin scrollbar after formatting, both are propertized strings with
a display space property, before giving the final result to a buffer and
then the child frame. Letting the windowing system to do truncation will
truncate off the custom scrollbar and margin first, in addition to breaking
an existing API that downstream extension packages rely on and being a much
larger refactoring that will bring forth the much thicker and intrusive
default Emacs scroll bars. Otherwise, this will work.
[-- Attachment #2: Type: text/html, Size: 2090 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 14:26 ` Jimmy Yuen Ho Wong
@ 2024-10-24 14:39 ` Eli Zaretskii
2024-10-24 15:33 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-24 14:39 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Thu, 24 Oct 2024 15:26:46 +0100
> Cc: emacs-devel@gnu.org
>
> If the above is what you want, and since the popup is actually a
> frame, my first suggestion would be to use :align-to display property
> on the whitespace between the <candidate>s and the <Type>s. Did you
> try that?
>
> The advantage of :align-to is that you don't have to measure the
> pixel-width of the candidate names, only the pixel-width of each
> <Type> string (to correctly set up the offset from the right edge of
> the text area) -- the rest will be done by the display engine. And
> the display engine always does everything in pixel resolution.
>
> The current implementation wraps every line with some additional margin and a custom thin scrollbar after
> formatting, both are propertized strings with a display space property, before giving the final result to a buffer
> and then the child frame. Letting the windowing system to do truncation will truncate off the custom scrollbar
> and margin first, in addition to breaking an existing API that downstream extension packages rely on and
> being a much larger refactoring that will bring forth the much thicker and intrusive default Emacs scroll bars.
> Otherwise, this will work.
If the scroll bar and the margin are generated programmatically, then
presumably the program which creates them knows their width, or can
calculate that? If so, the :align-to value should take that into
consideration.
(Assuming I understood what you were describing.)
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 14:39 ` Eli Zaretskii
@ 2024-10-24 15:33 ` Jimmy Yuen Ho Wong
2024-10-24 16:02 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-24 15:33 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 591 bytes --]
>
> If the scroll bar and the margin are generated programmatically, then
> presumably the program which creates them knows their width, or can
> calculate that? If so, the :align-to value should take that into
> consideration.
>
As I said, the problem is letting the window system do the truncation
rather than in code. There's no way to tell Emacs to start truncating from
the actual content rather than UI elements that Emacs thinks are content.
Hence, the original ask. Correct and performant custom truncation that
respects pixel width is much much harder than it should be in Emacs.
[-- Attachment #2: Type: text/html, Size: 803 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 15:33 ` Jimmy Yuen Ho Wong
@ 2024-10-24 16:02 ` Eli Zaretskii
2024-10-24 16:49 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-24 16:02 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Thu, 24 Oct 2024 16:33:14 +0100
> Cc: emacs-devel@gnu.org
>
> If the scroll bar and the margin are generated programmatically, then
> presumably the program which creates them knows their width, or can
> calculate that? If so, the :align-to value should take that into
> consideration.
>
> As I said, the problem is letting the window system do the truncation rather than in code. There's no way to
> tell Emacs to start truncating from the actual content rather than UI elements that Emacs thinks are content.
I guess I don't understand the issue you are describing. Where does
window system come into play here? What are "UI elements that Emacs
thinks are content", and where are they in the screenshots shown in
https://github.com/minad/corfu/pull/508 ? And where in my suggestion
did I propose anything that would cause "truncation by window system"?
> Hence, the original ask. Correct and performant custom truncation that respects pixel width is much much
> harder than it should be in Emacs.
Lisp programs are not supposed to do layout calculations, plain and
simple. The reason is that layout calculations are impossible without
having a window with lots of stuff that determines how text is
displayed. So doing that on strings is meaningless.
Therefore, I'm trying to help you do the job using the existing
display facilities, because the kind of solution you have in mind is
unlikely to emerge. If you want me to keep coming up with ideas,
please help me understand better the issues you are describing. I
hope you do realize that to suggest viable solutions, I need to have a
good understanding of the problem.
But if my suggestions and questions annoy you, I can easily stop.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 16:02 ` Eli Zaretskii
@ 2024-10-24 16:49 ` Jimmy Yuen Ho Wong
2024-10-24 17:56 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-24 16:49 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1914 bytes --]
>
> I guess I don't understand the issue you are describing. Where does
> window system come into play here? What are "UI elements that Emacs
> thinks are content", and where are they in the screenshots shown in
> https://github.com/minad/corfu/pull/508 ? And where in my suggestion
> did I propose anything that would cause "truncation by window system"?
>
That thin white bar on the right of the box from the third screenshot
onwards is actually a string with a display space property in pixels, not a
real scroll bar.
Using :align-to in the padding between the candidate and annotation is not
a problem, the problem is if the concatenated line is too long, I'll need
to truncate. There are 2 options - `truncate-string-to-width`, which is
bugged, or set the `truncate-line` buffer local to t and let Emacs' window
system do its magic, which will be performant and correct, and I can even
replace the arrow in an ellipsis, but truncation will start to truncate off
the emulated scroll bar.
> Lisp programs are not supposed to do layout calculations, plain and
> simple. The reason is that layout calculations are impossible without
> having a window with lots of stuff that determines how text is
> displayed. So doing that on strings is meaningless.
>
As I described in my first email, this can almost be achieved from the
existing Elisp functions and C functions exposed Elisp. The performance
problem associated with resolving a font WRT the anonymous face and face
list craziness can be done in C, and already exists. The width of the
display space and string replacement text properties can be calculated by
`check_display_width` in `indent.c`, and rest is surely somewhere in
`image.c`. I hope you are not telling me that Emacs devs still refuse to
give people the ability to align text in pixel precisions programmatically
at the end of 2024. Browsers have had this ability for almost 30 years.
[-- Attachment #2: Type: text/html, Size: 2432 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 16:49 ` Jimmy Yuen Ho Wong
@ 2024-10-24 17:56 ` Eli Zaretskii
2024-10-24 21:11 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-24 17:56 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Thu, 24 Oct 2024 17:49:27 +0100
> Cc: emacs-devel@gnu.org
>
> I guess I don't understand the issue you are describing. Where does
> window system come into play here? What are "UI elements that Emacs
> thinks are content", and where are they in the screenshots shown in
> https://github.com/minad/corfu/pull/508 ? And where in my suggestion
> did I propose anything that would cause "truncation by window system"?
>
> That thin white bar on the right of the box from the third screenshot onwards is actually a string with a display
> space property in pixels, not a real scroll bar.
OK, but then the Lisp program which produces that bar knows its
pixel-width, and can account for it in the :align-to spec.
> Using :align-to in the padding between the candidate and annotation is not a problem, the problem is if the
> concatenated line is too long, I'll need to truncate.
Why would you need to truncate? and which part needs to be truncated?
My suggestion is to align the <Type>s part so that it and the
following pseudo-scrollbar end exactly at the window edge. With this
arrangement, you shouldn't need to truncate at least the <Type>s part.
This can be dome by using :align-to which counts from 'right', which
is the right edge of the text area.
Actually, I don't understand why you'd need to truncate anything,
since the dimensions of the child frame can be calculated such that
the longest completion candidate will still fit without truncation.
Or what am I missing?
> There are 2 options - `truncate-string-to-width`, which is
> bugged, or set the `truncate-line` buffer local to t and let Emacs' window system do its magic, which will be
> performant and correct, and I can even replace the arrow in an ellipsis, but truncation will start to truncate off
> the emulated scroll bar.
You assumed something I didn't say and didn't have in mind. There
should be no need to use truncate-lines.
> Lisp programs are not supposed to do layout calculations, plain and
> simple. The reason is that layout calculations are impossible without
> having a window with lots of stuff that determines how text is
> displayed. So doing that on strings is meaningless.
>
> As I described in my first email, this can almost be achieved from the existing Elisp functions and C functions
> exposed Elisp. The performance problem associated with resolving a font WRT the anonymous face and face
> list craziness can be done in C, and already exists. The width of the display space and string replacement text
> properties can be calculated by `check_display_width` in `indent.c`, and rest is surely somewhere in `image.c`.
I don't think you fully understand the code you are referring to,
because it will not do what you want. E.g., check_display_width calls
string-width, which you found problematic, and image.c doesn't handle
layout of images. More importantly, the _only_ place in Emacs where
we have code that lays out glyphs until it hits some specified
coordinates is in the display engine, where it arranges text for
display, one "display element" at a time. Exposing that to Lisp in a
useful way is a hellishly hard job, because that code was never meant
to be useful from a Lisp program, and from a POV of a Lisp programmer
in certain cases behaves nonsensically. That's one of the reasons why
vertical-motion has such a complicated implementation which deals with
half a dozen different complications when using the display code in
such way.
Of course, if someone wants to write such a code, and it will be clean
and correct, such patches will be welcome. But please believe me when
I tell you that it is much better to try to avoid that and use
existing display capabilities (which will also allow you to support
this in current Emacs versions, instead of waiting for some future
one).
> I hope you are not telling me that Emacs devs still refuse to give people the ability to align text in pixel
> precisions programmatically at the end of 2024. Browsers have had this ability for almost 30 years.
This is not about refusal. It isn't like what you are asking is easy
to do, and the "Emacs devs" are just a lazy bunch. I looked at the
code involved, and I currently have no idea how to implement what you
have in mind so that it works in all the cases, those which you
mentioned and those you didn't, and works in a way that will be useful
for Lisp programs. You may think it's easy, but it isn't. Some
things are even conceptually not simple, for example whether it is
okay or not to break a string between U+1F3C2 and the following
U+1F3FF, and if so, how to discover that subject to how the current
character-composition machinery in Emacs was designed and implemented.
Of course, it is possible that I'm missing something, so if someone
has ideas about implementing this, let alone code, I'm all ears.
But even if such ideas/code emerge, I think doing this job using
existing display capabilities is a better way, because it will work
immediately with existing Emacs versions, and will probably be more
reliable. I still don't see why you couldn't solve the problem using
:align-to and the other ideas I suggested.
Last, but not least: please don't forget that Emacs is a
volunteer-driven project, and the only resources we have are those of
people who decide they want to work on something, for whatever
reasons.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 17:56 ` Eli Zaretskii
@ 2024-10-24 21:11 ` Jimmy Yuen Ho Wong
2024-10-25 7:21 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-24 21:11 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 5361 bytes --]
>
> Why would you need to truncate? and which part needs to be truncated?
>
> My suggestion is to align the <Type>s part so that it and the
> following pseudo-scrollbar end exactly at the window edge. With this
> arrangement, you shouldn't need to truncate at least the <Type>s part.
> This can be dome by using :align-to which counts from 'right', which
> is the right edge of the text area.
> Actually, I don't understand why you'd need to truncate anything,
> since the dimensions of the child frame can be calculated such that
> the longest completion candidate will still fit without truncation.
> Or what am I missing?
The :align-to of the padding between candidate and annotation can only be
calculated by adding the prefix column width, calculated from the longest
prefix width, the candidate width, calculated the same way, and the suffix
column width minus the pixel width of the suffix. The reason for this is
that `string-pixel-width` will be called on all of these concatenated
strings, and the maximum of which will be given as the width to a function
to render the child frame. This also answers your next question, yes the
pop up width is already calculated dynamically, but against a max width,
this is what I mean by "confined", hence the need for truncation before
blitzing the strings to a child frame. :align-to (- right suffix-width)
will lead `string-pixel-width` to return a ridiculously large number that,
funnily enough, is calculated from the current window's text area width,
instead of the child frame's window, of which the size is unknown at this
time.
As to the reason for a max width, let's just say there exists language
servers such as Rust Analyzer, that will return the signature of a function
as the completion annotation, which can be quite long. Nobody wants their
completion pop up box taking up half the screen.
Of course, one can also adjusts the child frame parameters to let it deal
with min/max size, margins and allow the user to resize, but the
beautifully emulated scroll bar will have to be sacrificed because either I
delete it from Corfu or the window will start truncating from the scroll
bar when the user resizes the window to be smaller than the content width.
> > There are 2 options - `truncate-string-to-width`, which is
> > bugged, or set the `truncate-line` buffer local to t and let Emacs'
> window system do its magic, which will be
> > performant and correct, and I can even replace the arrow in an ellipsis,
> but truncation will start to truncate off
> > the emulated scroll bar.
>
> You assumed something I didn't say and didn't have in mind. There
> should be no need to use truncate-lines.
>
I didn't assume anything. It's just a logical conclusion. Do you have it in
mind now?
This is not about refusal. It isn't like what you are asking is easy
to do, and the "Emacs devs" are just a lazy bunch. I looked at the
> code involved, and I currently have no idea how to implement what you
> have in mind so that it works in all the cases, those which you
> mentioned and those you didn't, and works in a way that will be useful
> for Lisp programs. You may think it's easy, but it isn't. Some
> things are even conceptually not simple, for example whether it is
> okay or not to break a string between U+1F3C2 and the following
> U+1F3FF, and if so, how to discover that subject to how the current
> character-composition machinery in Emacs was designed and implemented.
>
You already have `string-glyph-split` which works correctly, (a job well
done BTW, even more comformant than Chrome and Webkit). There are only 3
things you need to do for a hypothetical `glyph-pixel-width`:
1. With no faces, find the width of a character glyph from the default font
or whatever `char-displayable-p` returns. This is easy, I can already do
this from Elisp reasonably fast by going straight to the terminal using
`composite-get-gstring`.
2. With faces, resolve the font from the faces, go to 1. Still no need
to deal with windows. Can be done correctly in Elisp, but incredibly slowly
due to anon faces, face lists and having to go through the recursive
`face-attribute-merged-with`. The logic in `face-attribute-merged-with` can
be duplicated and modified to deal with anon faces, and run iteratively,
but still a few orders of magnitude slower than it needs to be.
3. Display properties is when you start to need a window, as a first try,
you can delegate this back to the current slow path via
`window-text-pixel-size`.
1 and 2 will be the vast vast majority of the use case. It's okay to be
slower for 3 due to the involvement of a window.
As a point of reference, this benchmark finishes in ~0.10s in my MacBook
Pro M1 Pro, this is 6 FPS for measuring 10k glyph widths.
```elisp
(let ((s "1")) 'face 'completions-common-part)))
(benchmark-run 10000 (string-pixel-width s)))
```
The following finishes in ~0.9s. Using the procedure described in case 1
above already cuts the time down by half.
```elisp
(benchmark-run 10000 (string-pixel-width "1"))
```
Getting boths cases down 1 order of magnitude is all I'm hoping for.
I'm not saying emacs-devs are lazy, I'm just saying after 14 years, Emacs
finally can split strings with emojis correctly, can we go one step further
and give Emacs users the ability to layout in pixel precision in a
more performant manner please?
[-- Attachment #2: Type: text/html, Size: 6732 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-24 21:11 ` Jimmy Yuen Ho Wong
@ 2024-10-25 7:21 ` Eli Zaretskii
2024-10-25 13:35 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-25 7:21 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Thu, 24 Oct 2024 22:11:36 +0100
> Cc: emacs-devel@gnu.org
>
> Why would you need to truncate? and which part needs to be truncated?
>
> My suggestion is to align the <Type>s part so that it and the
> following pseudo-scrollbar end exactly at the window edge. With this
> arrangement, you shouldn't need to truncate at least the <Type>s part.
> This can be dome by using :align-to which counts from 'right', which
> is the right edge of the text area.
>
> Actually, I don't understand why you'd need to truncate anything,
> since the dimensions of the child frame can be calculated such that
> the longest completion candidate will still fit without truncation.
> Or what am I missing?
>
> The :align-to of the padding between candidate and annotation can only be calculated by adding the prefix
> column width, calculated from the longest prefix width, the candidate width, calculated the same way, and the
> suffix column width minus the pixel width of the suffix.
We are mis-communicating. My suggestion is _not_ to compute the
:align-to from the width of the prefix+candidate+suffix. My
suggestion is to calculate the width of <Type>+scroll-bar, then use
:align-to relative to the right edge of the window, like this:
:align-to (- right (N))
where N is the pixel-width of <Type>+scroll-bar
> The reason for this is that `string-pixel-width` will be
> called on all of these concatenated strings, and the maximum of which will be given as the width to a function
> to render the child frame. This also answers your next question, yes the pop up width is already calculated
> dynamically, but against a max width, this is what I mean by "confined", hence the need for truncation before
> blitzing the strings to a child frame. :align-to (- right suffix-width) will lead `string-pixel-width` to return a
> ridiculously large number that, funnily enough, is calculated from the current window's text area width, instead
> of the child frame's window, of which the size is unknown at this time.
I don't understand this. What is "suffix-width" in the above text,
and in what units is it measured? And why the size of the window is
unknown?
> As to the reason for a max width, let's just say there exists language servers such as Rust Analyzer, that will
> return the signature of a function as the completion annotation, which can be quite long. Nobody wants their
> completion pop up box taking up half the screen.
Long strings can be truncated with one of the known methods. Those
methods will not give you pixel accuracy, you don't need that if you
use :align-to relative to the right edge of the window.
> Of course, one can also adjusts the child frame parameters to let it deal with min/max size, margins and allow
> the user to resize, but the beautifully emulated scroll bar will have to be sacrificed because either I delete it
> from Corfu or the window will start truncating from the scroll bar when the user resizes the window to be
> smaller than the content width.
I don't understand this, either. Why cannot the calculation of the
frame parameters take the scroll-bar into account, so as to avoid its
deletion/truncation?
> You assumed something I didn't say and didn't have in mind. There
> should be no need to use truncate-lines.
>
> I didn't assume anything. It's just a logical conclusion. Do you have it in mind now?
Your logic applied to my suggestions will only be correct if you
understand my suggestions completely. Which I don't think happens
yet, because we still seem to be mis-communicating.
> This is not about refusal. It isn't like what you are asking is easy
>
> to do, and the "Emacs devs" are just a lazy bunch. I looked at the
> code involved, and I currently have no idea how to implement what you
> have in mind so that it works in all the cases, those which you
> mentioned and those you didn't, and works in a way that will be useful
> for Lisp programs. You may think it's easy, but it isn't. Some
> things are even conceptually not simple, for example whether it is
> okay or not to break a string between U+1F3C2 and the following
> U+1F3FF, and if so, how to discover that subject to how the current
> character-composition machinery in Emacs was designed and implemented.
>
> You already have `string-glyph-split` which works correctly, (a job well done BTW, even more comformant
> than Chrome and Webkit). There are only 3 things you need to do for a hypothetical `glyph-pixel-width`:
You originally asked for truncate-string-to-pixel-width which would
avoid splitting grapheme clusters. What is glyph-pixel-width, and
what should it do?
> 1. With no faces, find the width of a character glyph from the default font or whatever `char-displayable-p`
> returns. This is easy, I can already do this from Elisp reasonably fast by going straight to the terminal using
> `composite-get-gstring`.
This is incomplete and inaccurate, because it ignores some important
complications. First, you forget images. You also ignore the
problematic aspects of getting width from composite-get-gstring. And
there are other complications, for example with TAB characters.
> 2. With faces, resolve the font from the faces, go to 1. Still no need to deal with windows. Can be done
> correctly in Elisp, but incredibly slowly due to anon faces, face lists and having to go through the recursive
> `face-attribute-merged-with`. The logic in `face-attribute-merged-with` can be duplicated and modified to deal
> with anon faces, and run iteratively, but still a few orders of magnitude slower than it needs to be.
Faces cannot be resolved without a frame (because each frame can have
a different definition of the same face), thus a window is required.
A window is also required because overlays (which can define faces)
can be window-specific. In general you also need a buffer, because
there's buffer-face-mode. And knowing the font is far from enough,
because of text shaping (what we call "character composition"),
without which we cannot reliably know what glyph(s) from the font to
use for the metrics.
IOW, your proposed idea will work for the simple cases, but falls
apart for a general-purpose API which will rightfully be expected to
work in any situation and use case supported by Emacs.
> 3. Display properties is when you start to need a window, as a first try, you can delegate this back to the
> current slow path via `window-text-pixel-size`.
This is only a small part of the problem.
> I'm not saying emacs-devs are lazy, I'm just saying after 14 years, Emacs finally can split strings with emojis
> correctly, can we go one step further and give Emacs users the ability to layout in pixel precision in a more
> performant manner please?
I explained why this is hard to implement correctly, at least as long
as we are talking about truncate-string-to-pixel-width which should
avoid splitting grapheme clusters. string-glyph-split was relatively
easy because we were lucky to already have everything exposed to Lisp.
We are very far from that point with this request. The existing
high-level C APIs, which we use in window-text-pixel-size and its ilk,
are inappropriate, because they are unable to reliably find a buffer
or string position that corresponds to a given pixel-width. AFAIU, to
implement what you asked for, we'd need a whole new set of C APIs,
which will have to be implemented from scratch using the low-level
functions which move one display element at a time, and pay attention
to all the Emacs display complications: faces, character compositions,
display properties, overlays, images, xwidgets, word-wrap,
line-truncation, etc. Sure, the elements of all this exist, so "we
have the technology", but the problem is the higher-level logic that
would combine those elements into a coherent whole and produce results
that Lisp programs expect.
IOW, this is not just "go one step further", this is a huge step that
will require a lot of coding and debugging. Of course, if someone
sees a way to do it easier, let's see the code or at least an idea of
such a code. The ideas you presented are too simplistic to fit the
bill, unfortunately.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-25 7:21 ` Eli Zaretskii
@ 2024-10-25 13:35 ` Jimmy Yuen Ho Wong
2024-10-25 15:11 ` Eli Zaretskii
0 siblings, 1 reply; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-25 13:35 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 4899 bytes --]
>
> We are mis-communicating. My suggestion is _not_ to compute the
> :align-to from the width of the prefix+candidate+suffix. My
> suggestion is to calculate the width of <Type>+scroll-bar, then use
> :align-to relative to the right edge of the window, like this:
>
> :align-to (- right (N))
>
> where N is the pixel-width of <Type>+scroll-bar
>
> > The reason for this is that `string-pixel-width` will be
> > called on all of these concatenated strings, and the maximum of which
> will be given as the width to a function
> > to render the child frame. This also answers your next question, yes the
> pop up width is already calculated
> > dynamically, but against a max width, this is what I mean by "confined",
> hence the need for truncation before
> > blitzing the strings to a child frame. :align-to (- right suffix-width)
> will lead `string-pixel-width` to return a
> > ridiculously large number that, funnily enough, is calculated from the
> current window's text area width, instead
> > of the child frame's window, of which the size is unknown at this time.
>
> I don't understand this. What is "suffix-width" in the above text,
> and in what units is it measured? And why the size of the window is
> unknown?
>
> > As to the reason for a max width, let's just say there exists language
> servers such as Rust Analyzer, that will
> > return the signature of a function as the completion annotation, which
> can be quite long. Nobody wants their
> > completion pop up box taking up half the screen.
>
> Long strings can be truncated with one of the known methods. Those
> methods will not give you pixel accuracy, you don't need that if you
> use :align-to relative to the right edge of the window.
>
>
Here are more gaps to fill in for you. The margin and the scroll bar widths
are both calculated relative to the `default-font-width`, the reason for
that is, assuming most of the text is in the default font, if it is 20px
wide, it's undesirable to have a fixed scroll bar size of 3px. The scroll
bar and the margin need to scale with the default font size to fight for
just enough of the user's attention when viewed. This can be known with
some refactoring by the time `string-pixel-width` is called on all the
formatted completion strings, but the whole issue is the "right" in
:align-to (- right <whatever>) would be referring to the window from which
you calculate `string-pixel-width` from, not the window in the child frame,
because we are trying calculate the child frame width from the content
width at this point. What you are suggesting has a logical circular
dependency here, which is why I explained to you that :align-to can only be
calculated from `(+ prefix-column-width candidate--column-width (-
suffix-column-width suffix-width)`. The suffix width means the annotation's
pixel width, the part you keep calling type, which is not necessarily the
case. I.e:
```
;; you just calculated the width of the space from the left to the right
of the __current-window__ minus some offset
(let ((content-width (cl-loop for (prefix candidate suffix) in
formatted-lines maximize (string-pixel-width (concat prefix candidate
(propertize " " :align-to `(- right ,(whatever))) suffix)))))
....
;; now you just made a child frame as large as your current window's
width minus whatever, presumably much smaller than your current window's
width, thus this frame now covers most of your screen.
(make-frame `((width . ,content-width)))
```
> I don't understand this, either. Why cannot the calculation of the
> frame parameters take the scroll-bar into account, so as to avoid its
> deletion/truncation?
>
For the second time, there's a max child frame width variable that
"confines" how large it can be, the implication is it can be < content
width, therefore necessitates programmatic truncation of the content width,
which __does not__ include the scroll bar.
> IOW, your proposed idea will work for the simple cases, but falls
> apart for a general-purpose API which will rightfully be expected to
> work in any situation and use case supported by Emacs.
>
Ok, makes sense. Thanks for filling in the missing parts for me. Here's
some further questions.
WRT case 1, translating tab sizes is a simple multiplication, it sounds to
me it can still be fast by bypassing windows. Is this correct? Anything
else that can slow this case down?
WRT case 2, boldly extrapolating from my simple benchmarks, resolving the
font from faces takes ~10% of the time in `string-pixel-width`, besides
saving and restoring window states and scanning window positions, what else
does "string-pixel-width" spend on the other 90% of the time?
> The existing
> high-level C APIs, which we use in window-text-pixel-size and its ilk,
> are inappropriate, because they are unable to reliably find a buffer
> or string position that corresponds to a given pixel-width.
>
Agreed.
[-- Attachment #2: Type: text/html, Size: 5951 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-25 13:35 ` Jimmy Yuen Ho Wong
@ 2024-10-25 15:11 ` Eli Zaretskii
2024-10-28 20:21 ` Jimmy Yuen Ho Wong
0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2024-10-25 15:11 UTC (permalink / raw)
To: Jimmy Yuen Ho Wong; +Cc: emacs-devel
> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Fri, 25 Oct 2024 14:35:16 +0100
> Cc: emacs-devel@gnu.org
>
> Here are more gaps to fill in for you. The margin and the scroll bar widths are both calculated relative to the
> `default-font-width`, the reason for that is, assuming most of the text is in the default font, if it is 20px wide, it's
> undesirable to have a fixed scroll bar size of 3px. The scroll bar and the margin need to scale with the default
> font size to fight for just enough of the user's attention when viewed. This can be known with some refactoring
> by the time `string-pixel-width` is called on all the formatted completion strings, but the whole issue is the
> "right" in :align-to (- right <whatever>) would be referring to the window from which you calculate
> `string-pixel-width` from, not the window in the child frame, because we are trying calculate the child frame
> width from the content width at this point. What you are suggesting has a logical circular dependency here,
> which is why I explained to you that :align-to can only be calculated from `(+ prefix-column-width
> candidate--column-width (- suffix-column-width suffix-width)`. The suffix width means the annotation's pixel
> width, the part you keep calling type, which is not necessarily the case. I.e:
So the problem is that you perform all the calculations _before_ the
child frame is created and shown? If so, the :align-to will indeed be
incorrect, but the difference between the alignment you calculate and
the one you need is fixed: it's the difference in pixels between the
width of the selected window when you calculate the alignment and the
actual width of the window in the child frame where you will show the
completion candidates. How hard is it to walk over all the candidates
you prepared for display and adjust the :align-to values once the
child frame is created?
And if the problem is that the dimensions of the child frame depend on
the width of the candidates+suffix to begin with, then you could
perhaps break this circular dependency by estimating the expected
width of the candidates by some coarse method that ignores the
subtleties and adds some slack to be on the safe side.
> IOW, your proposed idea will work for the simple cases, but falls
> apart for a general-purpose API which will rightfully be expected to
> work in any situation and use case supported by Emacs.
>
> Ok, makes sense. Thanks for filling in the missing parts for me. Here's some further questions.
>
> WRT case 1, translating tab sizes is a simple multiplication, it sounds to me it can still be fast by bypassing
> windows. Is this correct? Anything else that can slow this case down?
The problem is that the actual width of a TAB on display depends on
the column where the TAB starts. IOW, a TAB is not shown as 8
columns, it is shown as the number of columns till the next tab stop.
So its width cannot be reliably known for an arbitrary string until
you know at which column that string will start on display.
string-pixel-width assumes the string starts at column zero, but that
might not be true.
> WRT case 2, boldly extrapolating from my simple benchmarks, resolving the font from faces takes ~10% of the
> time in `string-pixel-width`, besides saving and restoring window states and scanning window positions, what
> else does "string-pixel-width" spend on the other 90% of the time?
In what version of Emacs did you benchmark it? In Emacs 30, my
profiling indicates a large portion of the time is taken by
with-current-buffer. Emacs 31 cuts the time in half by using a fixed
work buffer, but still, the actual pixel-width calculation takes only
about 30% of the running time.
(You can profile it yourself using profiler-start, but I suggest to
load subr-x.el first as the .el file, so that the profile will be more
detailed in terms of Lisp code.)
Bottom line: string-pixel-width is hardly efficient enough when
invoked in a tight loop, so if you need to call it many times for many
strings, perhaps a better idea would be to insert all the strings into
a work buffer, then measure their width one by one using
window-text-pixel-size, each time calling it with different FROM and
TO values? That involves switching a window's buffer and then
switching it back, but maybe it will be faster?
Alternatively, if you only need the width of the widest string in a
collection, you could concatenate them separated by newlines, then
call string-pixel-width on the result.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
2024-10-25 15:11 ` Eli Zaretskii
@ 2024-10-28 20:21 ` Jimmy Yuen Ho Wong
0 siblings, 0 replies; 17+ messages in thread
From: Jimmy Yuen Ho Wong @ 2024-10-28 20:21 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 946 bytes --]
>
> Bottom line: string-pixel-width is hardly efficient enough when
> invoked in a tight loop, so if you need to call it many times for many
> strings, perhaps a better idea would be to insert all the strings into
> a work buffer, then measure their width one by one using
> window-text-pixel-size, each time calling it with different FROM and
> TO values? That involves switching a window's buffer and then
> switching it back, but maybe it will be faster?
>
> Alternatively, if you only need the width of the widest string in a
> collection, you could concatenate them separated by newlines, then
> call string-pixel-width on the result.
>
It took me a while to understand what this means, that's some leaky
abstraction we have here :)
I've found a solution after some refactoring. The simplest solution is just
don't use relative :align-to. As long as it's not used,
`string-pixel-width` will behave as expected.
Thanks for all your help.
[-- Attachment #2: Type: text/html, Size: 1210 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2024-10-28 20:21 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-23 5:01 Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C Jimmy Yuen Ho Wong
2024-10-23 8:01 ` Eli Zaretskii
2024-10-23 13:52 ` Jimmy Yuen Ho Wong
2024-10-23 17:39 ` Eli Zaretskii
2024-10-23 20:03 ` Jimmy Yuen Ho Wong
2024-10-24 9:55 ` Eli Zaretskii
2024-10-24 14:26 ` Jimmy Yuen Ho Wong
2024-10-24 14:39 ` Eli Zaretskii
2024-10-24 15:33 ` Jimmy Yuen Ho Wong
2024-10-24 16:02 ` Eli Zaretskii
2024-10-24 16:49 ` Jimmy Yuen Ho Wong
2024-10-24 17:56 ` Eli Zaretskii
2024-10-24 21:11 ` Jimmy Yuen Ho Wong
2024-10-25 7:21 ` Eli Zaretskii
2024-10-25 13:35 ` Jimmy Yuen Ho Wong
2024-10-25 15:11 ` Eli Zaretskii
2024-10-28 20:21 ` Jimmy Yuen Ho Wong
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.