Re: [csswg-drafts] [css-fonts-5] Text Fitting: Scaling of things based on font-size (#12888)

I also agree this all needs to be used-value time. We're in the middle of layout; computed values have already happened and we're doing used-value-time stuff now. I also don't think we should, by default, be scaling different units differently anyway. We have a long line of evidence that when units change their relative ratios in unexpected ways, pages tend to break because authors didn't expect that.

Also, to be a little clearer about what knobs are *actually* available for us to reasonably/performantly twiddle, here's (roughly) how Chrome's text-shaping and line-breaking works (and I believe other impls are roughly similar):

1. We have a paragraph-worth of text, and a list of fonts that can be used on that text.
2. We just toss both of these at Harfbuzz, who then lays out one big long line accordingly (shaping the text, using different fonts as needed when glyphs dont' exist, etc.
3. Harfbuzz returns an annotated list of (letter, position) pairs.
4. We identify the linebreak opportunities, and find the furthest-along one that is less than or equal to the available space we are laying a line into.
5. We ask Harfbuzz to lay out *just* the text up to that point. (It can reuse a lot of its previous shaping work, only redoing the last few glyphs usually.) 
6. It tells us the new positions. If they're the same or smaller, great! Line finished, move on to the next one. If they're larger, we back up to the *previous* line-breaking opportunity and ask it again. Repeat until it fits or we're at the smallest unit between linebreak opportunities.

Notably, in this process, exactly *what* Harfbuzz is doing with the text, and what the fonts *allow* it to do, are more or less opaque to us. For example, whether a font can do optical sizing adjustments is none of our business, generally.

Another notable bit is that font shaping is *entirely non-linear*. With common, well-behaved fonts it's usually *nearly* linear - lay out with twice the font-size, get text approximately twice the length - but absolutely nothing stops it from doing weird and wacky things. We *force* line layout to eventually hit a base-case by only ever going *backwards* in the break opportunities; even if breaking at a later point would alter shaping to allow it to fit, we won't discover that (as it would, in general, require laying out at *all possible linebreak opportunities*, which is ridiculously costly). Fonts are turing-complete programs and can do whatever they want. Even just a simple font-size change can result in having to use a different font for rendering, if it's a bitmap font, resulting in a completely unrelated line length.

----------

The upshot of this is that we really don't have much we can do to offer authors control over this, without an *enormous* amount of engineering effort to rip open the shaping process and expose a lot more of it to the broader browser process. This is why @tkent-google is trying to limit what we do. In particular, I think we've got three reasonable choices we can offer authors that don't require massive engineering efforts:

1. Do a literal scale(), just in the inline axis. No reshaping at all, just a visual transform. (This is done today in CJK text a lot. It's not great, but it doesn't change the line height, so sometimes it's worth it.)
2. Do a literal scale(), but the same in both axises. Still no reshaping at all, just a visual transform.
3. Change the font-size. Because fonts can do arbitrary stuff in response, we just make a *guess* at the target font-size, rerender with that, then do a scale (like option 2) to finish fitting it exactly.

In all these cases, there are a few other options we could offer, which are probably worth letting authors choose between:

1. Adjust each line individually, or adjust an entire IFC with a single scale so all lines are consistent, using the smallest factor among the lines. (Default: each individually, probably.)
2. Whether atomic inlines get scaled or left alone. (Default: scaled, probably.) (We don't really want to redo layout inside the atomic, because that's *another* case where the results can be completely non-linear; line-breaking inside the atomic might change, for instance. So by "scale" I literally mean transform-type scaling.)
3. Whether layout-effecting decorations, like borders and margins on the inlines, are scaled or not. (Default: not scaled, probably?)

(2) and (3) just change how many things participate in the scaling size determination, so they're not a big complexity hit.

--------

Any further controls would just be more shots in the dark that require correspondingly more whole-line/paragraph relayouts. For example, if we ask to do optical-sizing scaling, only *some* of the fonts on the line might support that. We don't know that, tho - only Harfbuzz does, currently. So it might result in our guess being way off, when only part of the text on a line ends up being scaled in this way, and so we either have a much larger transform-scale to get a perfect fit, or do another complete round of sizing with different values.

We certainly can ensure the syntax *allows for* more controls in the future, but I don't think we should offer them for now. Just the three scaling strategies, plus the options I listed, should be enough for now imo.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12888#issuecomment-3412949937 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Thursday, 16 October 2025 21:36:44 UTC