-
Notifications
You must be signed in to change notification settings - Fork 715
[css-text] [css-inline] Define how to deal with inline backgrounds whose boundary falls into a ligature #5251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
One interesting consequence of Chromium's approach is that you can't select the ligature individually... For editing it ends up working, IIRC, because they fallback to the legacy engine (which does the same thing WebKit does...) |
It also may be interesting to see what happens if you add I believe Gecko's approach (which @rocallahan implemented initially) involves estimating the boundary within the ligature based on the advances of the pre-ligature glyphs, although I'm not sure if this is still the case. It would be interesting to know if there are font metrics that could help with finding the boundary more accurately. I think the working group has discussed this issue at least once in the past. |
The approach I implemented simply divides the ligature into equal-sized horizontal pieces. Works OK for Latin text but fails spectacularly for vertical ligatures, for example. At the time I don't think fonts had any information we could use to make a better decision, but I think that might have changed. The Webkit approach seems bad to me because I've always assumed that wrapping inline content in an unstyled span, or adding decorative styles like "color", should not change layout. |
In theory, fonts can include information to help with dividing up the advance width of a ligature, so that for example an "st" ligature might have a boundary position at 2/3 of the advance rather than half-way. In practice, however, hardly any fonts actually have that data; and it wouldn't help with vertical ligatures such as may be found in some Asian scripts, etc. For the example here, I'd argue that gecko's behavior is clearly better than webkit or blink (and is what the spec calls for), even though there are certainly complex cases where the results are less than ideal. |
Blink supports caret-and-selection-within-a-ligature by, currently, similar method as Gecko, but as @jfkthame pointed out, OpenType has a table for caret position within a glyph. Ideally we'd like to support that, but it hasn't happened yet. IIRC @litherum had a WIP for WebKit for this. For painting, we don't apply this logic because while there are cases where this works good, like this example, as @jfkthame pointed out, there are cases where this looks strange. For example: I think it's better to let authors clarify what they want. If authors want color/background correctly, like when they want to show diff in colors, they should apply In whatwg/html#5611, we discussed whether to apply |
Partly, but not entirely. Using a font that supports an "ffi" ligature, for example:
If I drag-select slowly across this text, I can see that the individual characters making up the "ffi" ligature can be selected one by one; so I can, for instance select just the middle "f". But now try this version:
Here, when I try drag-selecting across the text, the "ffi" ligature gets highlighted as an indivisible unit.
Agreed, that looks strange, but I don't see how Blink's result (where the entire ligature is painted with the color/background of its first component) is better. That means the intended styling in something like
is essentially lost. If an author doesn't want the "strange" result Firefox gives with your jsbin example, they can disable the ligature, or they can apply the background to the whole word instead of a single character; but Blink's approach here makes it extremely awkward to go the other way. |
Thank you for finding it, it's likely a bug, we'll investigate.
Agreed it's not better. I think Blink behavior always makes it clear so that authors can notice easier, and encourages authors to clarify the intention. If "fi" and "ffi" works at some levels, I guess most Latin authors will not notice it may not work in some other cases. I tried Fira Code but it seems it does some magic to paint partial glyphs, haven't figured out what it does. |
Fira Code has an unconventional implementation whereby it inserts extra "spacer" glyphs to maintain monospaced rendering in the presence of ligatures:
I haven't been through all the font lookups to confirm the exact sequence of operations, but what has happened here is not a ligation, but two substitutions: "<" replaced by the |
Just to clarify, sorry if I mislead you, I didn't mean to say Blink's is better than others. I think I'm similar to @emilio, each option has reasons to choose, and I'm not sure which one is the best at this moment. We have only less than one year experiences of cross-element shaping yet. Looking at reported cases so far and cases we came up with, I started leaning towards to "break shaping at color/background/text-decorations boundary" -- so WebKit in this case -- is the most "not incorrect" option. WDYT? p.s., thank you @jfkthame for the analysis on Fira Code, this is very interesting technique. That explains how |
Breaking shaping at background etc. differences is a bit unfortunate, quoting @rocallahan above:
I think I agree and I would like to avoid layout invalidation due to background / color changes and such. |
Yes, agreed. FWIW, Webkit (Safari) seems to break shaping at inline boundaries even when there's no style difference at all. See https://codepen.io/jfkthame/pen/gOPRpQG, which shows a plausible usage of color on inline elements where interrupting shaping is definitely not desired. It looks fine in both Firefox and Chrome, but is broken in Safari; and it remains broken (i.e. the words are not shaped correctly) even if the |
Relevant spec sections, fwiw:
I think this is really a case where the spec should leave it undefined. There's no clearly correct answer, and what's possible depends on the font technology. |
I agree with @fantasai. Specifically, the existing part of spec text that is most relevant to this is:
|
Small clarification at d1714e7 |
I think there is not much else we can do here. @emilio , should I close the issue or do you want something additional? |
This is unhelpful advice. Authors can't know where ligatures may occur so it is not actionable (except maybe by not putting inline element boundaries inside "words"). Making shaping work across unstyled inline element boundaries does not depend on font technology. Why not at least mandate that? And why not recommend that browsers should make a best-effort attempt to support style changes? |
@rocallahan That is already required: https://www.w3.org/TR/css-text-3/#boundary-shaping |
Ah. That text does look pretty good. "no effective change in formatting" perhaps needs clarification, though. Does changing the color of a span count as "formatting"? I would say style changes that don't affect layout should not count as "formatting" here. |
No, I'm ok closing. |
@rocallahan I think that's too strict. Breaking optional ligatures to correctly handle a color change might be reasonable, for example. That's why the spec isn't so tight, because of cases like this. But if there's no change at all, the element boundary should cause no change in rendering. |
The browser cannot, in general, know which shaping behaviors are "optional" and which are required for orthographically correct rendering of the content. The spec need not mandate exactly how color changes get rendered if they occur in the midst of shaped sequences, given that sometimes there is no clear "right" answer, but I think it's a reasonable expectation that changing color should never affect layout. |
This is what
The author is asking for conflicting things. I don't know that there's a clearly correct answer to solving that conflict, so as currently drafted the specs are leaving that up to the UA to figure out. Probably you're right that changing color should not affect layout in a dynamic environment, but if some print implementation thinks that's a higher-fidelity interpretation of the author's intent than keeping the ligature all one color or divided by percentage... I don't think I want to make them non-conformant. |
That should be true, but the boundary is fuzzy even in the OpenType spec: Khmer, for instance, requires the "clig" (contextual ligatures) feature for layout, despite it being theoretically discretionary. |
There's that; and then there's also the fact that ligation (mapping two or more encoded text units to a single rendered glyph) can happen in other OpenType features, depending on details of font construction -- for example, various Indic shaping features may be implemented as ligatures. Ligature lookups are not limited to occurring in features called "ligatures". |
@jfkthame Sure, and, none of that invalidates what the spec already says. So I don't think there's an issue here to solve. |
For this test-case:
This is what I see on different browsers:
Both Gecko's and Blink's behavior make some amount of sense to me. It seems Blink puts the whole ligature inside the first inline box. Gecko instead does something where the text is painted atomically on top of the inline backgrounds, crossing the inline boundary.
WebKit's behavior of not shaping the ligature may also be reasonable for this case (not in general of course).
It's not clear to me what the right answer is... But maybe the spec ought to have a model of how this is supposed to work?
The text was updated successfully, but these errors were encountered: