A soft or auto hyphen within a possible ligature (eg 'f­f') paints a split ligature glyph
Categories
(Core :: Layout: Text and Fonts, defect)
Tracking
()
People
(Reporter: thomas.bsd, Assigned: r.majdodin)
References
(Blocks 2 open bugs, )
Details
Attachments
(7 files, 1 external file)
Updated•17 years ago
|
Comment 6•17 years ago
|
||
Comment 8•17 years ago
|
||
Comment 10•17 years ago
|
||
Comment 11•16 years ago
|
||
Comment 12•14 years ago
|
||
Comment 13•14 years ago
|
||
Comment 14•14 years ago
|
||
Comment 15•14 years ago
|
||
Comment 17•12 years ago
|
||
Comment 18•12 years ago
|
||
Comment 19•11 years ago
|
||
Comment 20•11 years ago
|
||
Comment 22•8 years ago
|
||
Comment 25•7 years ago
|
||
I thought I had found a new bug (https://twitter.com/LordPachelbel/status/1113475005600366592) but now I've learned it was first reported 10 years ago. As Liam said above, this issue is going to happen more often now that web fonts with ligatures are widely used.
Comment 26•7 years ago
|
||
Here's the "af" ligature at a different font size where it isn't being split and hyphenated.
The web font is called Premiera Book.
Comment 27•7 years ago
|
||
The URL I saw this on is http://clagnut.com/blog/2395. In this case the source code doesn't have ­ in the word:
<html lang="en">
...
<p>I presented some golden rules for typography on the web, and in the Q&A afterwards
I was asked about the current state of automatic hyphenation on the web. This was an apt
question considering that German is well known for its long words – noun compounds feature
commonly (for example <dfn lang="de">Verbesserungsvorschlag</dfn> meaning <i>suggestion for
improvement</i>) – so hyphenation is extensively used in most written media.</p>
Which means the split ligature is happening because of auto-hyphen styles:
font-size: 1.3125rem;
line-height: 1.428571429em;
font-family: "Premiera", "Cambria", "Roboto Slab", "Georgia", "Times New Roman", serif, ".PhoneFallback", "Arial Unicode MS";
font-feature-settings: normal;
font-variant-ligatures: common-ligatures;
font-kerning: normal;
font-variant-numeric: oldstyle-nums proportional-nums;
-webkit-hyphens: auto;
-webkit-hyphenate-limit-before: 4;
-webkit-hyphenate-limit-after: 3;
-webkit-hyphenate-limit-chars: 7 4 3;
-webkit-hyphenate-limit-lines: 2;
-webkit-hyphenate-limit-zone: 8%;
-webkit-hyphenate-limit-last: always;
-moz-hyphens: auto;
-moz-hyphenate-limit-chars: 7 4 3;
-moz-hyphenate-limit-lines: 2;
-moz-hyphenate-limit-zone: 8%;
-moz-hyphenate-limit-last: always;
-ms-hyphens: auto;
-ms-hyphenate-limit-chars: 7 4 3;
-ms-hyphenate-limit-lines: 2;
-ms-hyphenate-limit-zone: 8%;
-ms-hyphenate-limit-last: always;
hyphens: auto;
hyphenate-limit-chars: 7 4 3;
hyphenate-limit-lines: 2;
hyphenate-limit-zone: 8%;
hyphenate-limit-last: always;
Updated•7 years ago
|
Comment 29•7 years ago
|
||
I just ran into this in Firefox v69 on Mac (at https://www.gwern.net/Culture-is-not-about-Esthetics#the-experimental-results). "often" was split into "of- <linebreak> ten", but there's a blob above the t. It looks like the ft ligature was rendered and then split in two. Chrome handles it correctly.
Comment 30•6 years ago
|
||
Same here in this article: https://i.imgur.com/4FvM3Bw.png
Comment 31•6 years ago
|
||
It not only affects soft hyphens but also normal hyphenation in regular text. I've seen this a lot on websites everywhere. I'm wondering why this could even happen. A ligature must only be printed if both characters appear directly next to each other, not even with custom letter spacing, and certainly not across lines. Are there any plans to fix this?
Comment 33•4 years ago
|
||
Updated•4 years ago
|
Comment 35•4 years ago
|
||
The severity field for this bug is relatively low, S4. However, the bug has 7 duplicates and 14 votes.
:jfkthame, could you consider increasing the bug severity?
For more information, please visit auto_nag documentation.
Comment 36•4 years ago
|
||
The last needinfo from me was triggered in error by recent activity on the bug. I'm clearing the needinfo since this is a very old bug and I don't know if it's still relevant.
Comment 37•3 years ago
|
||
I was just about to report a similar issue and saw this bug. I see the same problem even without any hyphens. Is this a different bug, or does the title just need updating here?
Comment 38•3 years ago
|
||
Yes, the same issue can sometimes occur without any hyphens, if a line break is allowed within a character sequence that forms a ligature (e.g. as a result of overflow-wrap:anywhere).
So on macOS, for example,
data:text/html,<div style="font:40px times; overflow-wrap:anywhere; width: 1px">office
will show two halves of the "fi" ligature on separate lines, which looks a bit odd; the line-break should cause the ligature to be undone.
Hyphen breaks are the most common example where this occurs, but the bare line-wrap example is the same issue.
Comment 39•2 years ago
|
||
Wanted to report a similar bug, found that it is already here. A reduced case that I did encounter in practice: https://codepen.io/kizu/pen/XWGXYyp (probably only on macOS due to the font I used for this specific example).
Given Safari and Chrome handle this properly, it would be nice to fix this for interoperability.
Comment 41•2 years ago
|
||
(In reply to Chris Cowan from comment #29)
I just ran into this in Firefox v69 on Mac (at https://www.gwern.net/Culture-is-not-about-Esthetics#the-experimental-results)
I can confirm this bug is still being experienced on Gwern.net by my readers; most recently, a reader reported it happening with the Source Serif Pro on "Scaling Hypothesis" with Firefox for Android in our dark mode: https://gwern.net/doc/cs/css/2024-08-29-anonymous-firefox-android-bug479829fontligaturesplitting-gwernnetscreenshot.jpg ("suf-fice").
| Assignee | ||
Comment 44•1 month ago
|
||
A word is shaped whole before lines are broken, and its textrun is shared by
all the lines of the text. When a line break fell inside a ligature, each
line drew a clipped part of the ligature's glyph and measured an even share
of its advance.
Now each line gets the glyphs the font gives for its own part of the word.
gfxFontGroup::MakeTextRun takes cut positions and shapes a word with a cut
inside it as separate pieces, each passed to HarfBuzz with the rest of the
word as context, so that Arabic joining forms are kept.
gfxTextRun::BreakAndMeasureText decides a break opportunity inside a
ligature on the advance of the piece the line would hold, which
PropertyProvider::MakeWordRun shapes. A frame whose line starts or ends
inside a ligature gets a textrun of its own for the line, kept in a frame
property behind the state bit TEXT_HAS_LINE_TEXTRUN. Painting, hit testing,
caret, selection and overflow read it through nsTextFrame::GetDisplayTextRun.
The shared textrun is not changed, and reflow stays on it. Min-content width
measures a stretch bounded inside a ligature as its piece, and a line that
ends inside a word marks the next line dirty when its text changes. Where
::first-letter ends inside a ligature, the word is split into frames as at
a line break, and the first letter and the rest are shaped apart the same
way.
Lines are laid out as before, with the clipped ligature, where a word cannot
be shaped again on its own: transformed text, textruns with tabs, words of
more than 1024 characters, words that span content nodes, words that shaped
alone do not have the glyphs they have in the textrun, synthesized small
caps, and fonts shaped by Graphite or, where
gfx.font_rendering.coretext.enabled is set, by CoreText, neither of which
takes context.
The tests are reftests in layout/reftests/text rather than
web-platform-tests because they need a font with an ffi ligature, which the
reftest fonts directory has.
This work was done with AI assistance; I have reviewed and can explain
every line.
Updated•1 month ago
|
| Assignee | ||
Comment 45•1 month ago
|
||
I have submitted a patch: D328111. A word that is broken inside a ligature is shaped again as separate pieces, each with the rest of the word as shaping context, and each line measures and paints its own piece. Some cases are still laid out as before; the revision's summary lists them.
The attached page shows seven cases side by side: a screenshot from the try build without the patch, one from the build with it, and the same markup rendered live by the browser that opens the page.
Try runs on Linux, Windows and macOS, all on the same base:
- With the patch the eighteen new reftests
ligature-line-break-1to-18andwordbreak-7b.htmlpass, and so does a wider selection of reftests, crashtests, web-platform-tests, mochitests and gtest in the text, bidi, font and editor directories. - On upstream with only the new tests, tests 1 to 4, 7, 8, 12 to 14, 17, 18 and
wordbreak-7b.htmlfail, so they show the bug. The others pass either way; they guard against mistakes the patch could make.
This work was done with AI assistance; I have reviewed and can explain every line.
| Assignee | ||
Comment 46•1 month ago
|
||
The patch on D328111 is updated: its line-breaking loop was reworked after Speedometer 3, which emilio asked for in the review, showed a cost on Editor-TipTap. What the patch does is unchanged.
Try runs of the updated patch, on the same base as comment 45: with the patch, the same selection as there plus an Android arm build, all 78 jobs pass, the eighteen new reftests and wordbreak-7b.html included. The run of upstream with only the new tests is the one in comment 45.
Speedometer 3, twenty runs a side against the base (perf.compare): the score is unchanged on Linux, Windows and the Windows reference hardware (−0.09 %, −0.05 %, −0.28 %). Editor-TipTap, whose two synchronous steps each reflow a large document, is +1.2 % on Linux (81.5 → 82.5 ms per iteration) and unchanged on both Windows platforms (−0.4 %, −0.1 %); before the rework it was +2.3 % and +1.8 % (first comparison). TipTap has ligatures off, so what remains is the loop's test at each break opportunity, not the reshaping. Perfherder flags nothing else; the one flagged row, Charts-chartjs on Windows at +3.1 %, is a single job at 57.7 ms among nineteen at 37.8.
| Assignee | ||
Comment 47•1 month ago
|
||
:jfkthame :emilio
I updated the revisions 19 days ago to address your comments. If everything is clear now, could you accept them please?
Comment 48•1 month ago
|
||
Ai patches are rather hard to review (specially in terms of why a particular approach to solving the issue was chosen). Jonathan has a better sense of what the right approach here is and this is already on his review queue, please be patient.
| Assignee | ||
Comment 49•1 month ago
|
||
I have spent 12 days on this patch: guiding the agent through the subtle points with 451 messages, painstakingly refining it, and redesigning it.
I would gladly clarify the design choices; let's discuss them here.
Comment 50•24 days ago
|
||
Just a note -- I'm hoping to get time to go through this properly, but please understand that we've been fairly swamped with urgent issues recently. This patch addresses a very-longstanding issue that I'd love to see resolved! However, it's a substantial amount of non-trivial code that we need to review (and then maintain...), so please continue to be patient; we'll get to it when we can.
Description
•