Subject: Re: bug#71039: :box :line-width and :underline :position should accept fractional sizes

From: JD Smith <[email-masked]>
Date: Sun, 19 May 2024 09:45:52 -0400

> On May 19, 2024, at 2:37 AM, Eli Zaretskii <[email-masked]> wrote:
> 
>>  Normally of course you would not do this for random text.  Instead you'd apply targeted floating :box widths to short stretches of text, like labels.
> 
> I think it will look ugly, but I guess to each their own.

That's just a random example, not meant for appearance evaluation ;).  It's already the idea used for popular packages like org-modern (with some difficulty resulting from the limitations of :box).  The basic idea is to give more flexibility for box placement, which will open up many uses.

> Anyway, the line width is stored in the face structure when the face
> is realized, and kept there for when the box face needs to be drawn.
> If the values are relative, the drawing back-end will need to compute
> the corresponding absolute width values by accessing the font metrics

I guess this is how face must already handle :height, selecting a font based on that (after inheritance, and multiplying all the :height's together).  Perhaps turning fractional box size into pixel values could make use of that work?  Surely that is not back-end dependent.

> (or is it the height of the screen line?) at draw time.  

Ideally the fractional box widths would be relative to the font size itself, but I think line height would also be fine, if that were simpler and more performant.

>> I'm confident they'd be used quite a lot.  Do you have a sense of how difficult these improvements would be?  Since you can already now apply fractional specified space like (space :width (0.25 . width)), I was hopeful the calculations would be close at hand.
> 
> The space width is calculated in the back-end-independent part of the
> display code (xdisp.c), because it yields a stretch glyph of a certain
> width (which is later drawn on screen as a stretch of background
> color).  By contrast, the box face is implemented in back-end code
> (*term.c), since it needs to draw lines using the display-specific
> APIs.  So we cannot use the same code in these two cases.

I see, thanks.  Given that, it would probably be worthwhile to get broader input on what types of back-end dependent screen drawing improvements would be valuable for faces.

>> What the above proposal would do is allow you to specify the box width separately on all 4 sides of the affected text: left, right, top, and bottom.  So for example:
>> 
>> 	:line-width (4 0 -0.25 -0.1)
>> 
>> would push the box 4 pixel to the left, and pull the box down from the top more than up from the bottom. As a related idea, following your suggestion, you could keep :line-width as-is and add a :box :position attribute that shifts the box vertically (which would be the same except symmetric left/right).  
>> 
>> The floating point width is probably more important, but this would enable some useful effects like simple text-based progress bars, etc.
> 
> This will need to extend the face structure to store 4 line thickness
> values, not 2 as we do today.

Or 3, if the :position flavor were deemed superior.  

Thanks for the information.