SVG text does somtimes not show up with an embedded font
Categories
(Core :: Layout: Text and Fonts, defect)
Tracking
()
Tracking | Status | |
---|---|---|
firefox-esr115 | --- | unaffected |
firefox127 | --- | wontfix |
firefox128 | --- | verified |
firefox129 | --- | verified |
People
(Reporter: kontakt, Assigned: emilio)
References
Details
Attachments
(4 files, 1 obsolete file)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0
Steps to reproduce:
I am trying to use a base64-embedded font in an SVG file, and embed that SVG file in an HTML file using an <img> tag.
The SVG file looks like this (excluding the huge base64 blob):
<svg width="800" height="80"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
@font-face {
font-family: CascadiaCode;
src: url("data:font/woff2;base64,[base64 -w0 CascadiaCode.woff2]");
}
svg {
font-family: CascadiaCode;
}
@media (prefers-color-scheme: dark) {
text {
fill: blue;
}
}
@media (prefers-color-scheme: light) {
text {
fill: red;
}
}
</style>
<text x="50" y="50" font-size="50">Hello, world!</text>
</svg>
and the HTML file looks like this:
<!DOCTYPE html>
<img src="test.svg" alt="A test image">
Both files are also attached to this report.
Actual results:
When serving the HTML file with a HTTP server (python -m http.server) and opening the file in Firefox Nightly 128.0a1 (2024-06-08) (64-bit) on my Windows 10 machine, the "Hello, world!" text does not always show up.
When I force refresh the page (Ctrl+F5) a few times, sometimes the red text appears, and sometimes it doesn't.
In the cases where it doesn't, using the developer tools to switch to "prefers-color-scheme: dark" makes the blue text show up, but switching back yields a blank screen again.
I was unable to reproduce this behavior without an embedded font.
Expected results:
The red "Hello, world!" text should always show up.
Reporter | ||
Updated•4 months ago
|
Comment 1•4 months ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::Layout: Text and Fonts' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Comment 2•4 months ago
•
|
||
Regression window:
https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=7a7e10acc67d83c1b5d36bd0951bd37d1f7904a9&tochange=66d921932ca7cf275d17bf4942aa92a9b9ef9f9d
Good build: The text render as expected.
Bad build : The bug appears at initial load. And each reload (Ctrl+F5) alternates between this bug and normal drawing.
Updated•4 months ago
|
Updated•4 months ago
|
Comment 3•4 months ago
|
||
Comment 4•4 months ago
|
||
Updated•4 months ago
|
Comment 5•4 months ago
|
||
FWIW the patch in bug 1901378 does not fix this.
Comment 6•4 months ago
|
||
:dshin, since you are the author of the regressor, bug 1310170, could you take a look? Also, could you set the severity field?
For more information, please visit BugBot documentation.
Comment 7•4 months ago
|
||
Set release status flags based on info from the regressing bug 1310170
Updated•4 months ago
|
Updated•4 months ago
|
Comment 8•4 months ago
|
||
Ok.. Interesting.
It seems like we're rasterizing the SVG for <img>
before the font load completes - I see the text run being painted before nsFontFaceLoader::FontLoadComplete
triggers. Forcing the size change by 1 px afterwards triggers the re-rendering and makes the text appear.
Removing the line-height portion of finish_restyle
removes the issue, so there seems to be some kind of race involved.
Comment 9•4 months ago
|
||
Looking further: Calculating line-height is actually what triggers the request to load the user font. This causes us to take the deferred load path since we're in style thread.
Refreshing seems to hit the cache instead.
Assignee | ||
Comment 10•4 months ago
|
||
That should still block the document load event right? https://searchfox.org/mozilla-central/rev/aa9d148d5be3e7b606448f0b8da6e9f4fa43112f/layout/style/nsFontFaceLoader.cpp#65-71
Or is that somehow too late?
Comment 11•4 months ago
|
||
Ultimately nothing gets drawn because we set the flag to not draw anything as the font isn't loaded in yet.
This happens pre-lh/rlh work if the SVG's CSS is adjusted to ask for font metrics in styling, as attached (Confirmed with mozregression --launch 2023-09-01
).
Assignee | ||
Comment 12•4 months ago
|
||
(barely tested, and would need a test written, but it seems easy to do
based on the test case on the bug)
Comment 13•4 months ago
|
||
(Removing regression keyword as per comment 11)
Comment 14•4 months ago
|
||
Comment 16•4 months ago
|
||
Comment 17•4 months ago
|
||
Backed out for causing reftest failures related to CustomizableUI.sys.mjs
[task 2024-06-13T16:04:54.792Z] 16:04:54 INFO - REFTEST TEST-START | layout/printing/crashtests/1663722.html
[task 2024-06-13T16:04:54.796Z] 16:04:54 INFO - REFTEST INFO | SET PREFERENCE pref(dom.window.sizeToContent.enabled,true)
[task 2024-06-13T16:04:54.797Z] 16:04:54 INFO - REFTEST TEST-LOAD | file:///D:/task_171829326750694/build/tests/reftest/tests/layout/printing/crashtests/1663722.html | 3081 / 4037 (76%)
[task 2024-06-13T16:04:56.070Z] 16:04:56 INFO - 1718294696068 Marionette TRACE Received observer notification browser-delayed-startup-finished
[task 2024-06-13T16:04:56.415Z] 16:04:56 INFO - console.error: CustomizableUI:
[task 2024-06-13T16:04:56.417Z] 16:04:56 INFO - TypeError: can't access property "localName", aNode is null -- resource:///modules/CustomizableUI.sys.mjs:1724
[task 2024-06-13T16:04:56.800Z] 16:04:56 INFO - REFTEST TEST-PASS | layout/printing/crashtests/1663722.html | (LOAD ONLY)
[task 2024-06-13T16:04:56.801Z] 16:04:56 INFO - REFTEST TEST-END | layout/printing/crashtests/1663722.html
[task 2024-06-13T16:04:56.859Z] 16:04:56 INFO - REFTEST TEST-START | layout/printing/crashtests/1671503.html
Assignee | ||
Updated•4 months ago
|
Comment 19•4 months ago
|
||
Comment 20•4 months ago
|
||
Assignee | ||
Updated•4 months ago
|
Comment 21•4 months ago
|
||
Comment 22•4 months ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/8ce3de807170
https://hg.mozilla.org/mozilla-central/rev/9f913cbd60ee
https://hg.mozilla.org/mozilla-central/rev/80fd881ad06d
Comment 25•4 months ago
|
||
The patch landed in nightly and beta is affected.
:emilio, is this bug important enough to require an uplift?
- If yes, please nominate the patch for beta approval.
- If no, please set
status-firefox128
towontfix
.
For more information, please visit BugBot documentation.
Assignee | ||
Comment 26•4 months ago
|
||
Comment on attachment 9407001 [details]
Bug 1901414 - Flush layout before firing SVG image doc load. r=dshin
Beta/Release Uplift Approval Request
- User impact if declined: comment 0
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: Yes
- Needs manual test from QE?: Yes
- If yes, steps to reproduce: comment 0
- List of other uplifts needed: none
- Risk to taking this patch: Medium
- Why is the change risky/not risky? (and alternatives if risky): Small patch, but non-trivial.
- String changes made/needed: none
- Is Android affected?: Yes
Assignee | ||
Updated•4 months ago
|
Comment 27•4 months ago
|
||
Comment on attachment 9407001 [details]
Bug 1901414 - Flush layout before firing SVG image doc load. r=dshin
Approved for 128.0b5.
Updated•4 months ago
|
Comment 28•4 months ago
|
||
uplift |
Updated•4 months ago
|
Comment 29•4 months ago
|
||
Verified fixed on Nightly 129.0a1 (20240618214224) and Beta 128.0b5 (20240618035431) using the attachment from Comment 4.
Comment 31•4 months ago
|
||
From the diagnonsis in comments 8 through 12 and the comment in the patch, it sounds like the problem is that the font face load happens after load and the rendering in the img of the svg isn't updated. And the patch here was trying to make sure that font face load happens before load. svg in img should handle invalidates that happen after load, in fact bug 1805599 was specifically to restore that property which was inadvertently regressed. So it seems that the root cause here is that the invalidate from the font face load isn't getting all the way through to the rendering in the top level doc?
Assignee | ||
Comment 32•4 months ago
|
||
The way the font face invalidation and co works is that it marks stuff dirty and schedules a flush. As I understand it, right now SVG images only trigger rendering updates on-demand (as a result of animations and so on), so it's unclear to me how it's supposed to work? In any case font face loads and so on do block the load event, generally.
I was not familiar with that mechanism myself at least. Bug 1877126 is a very similar case where the "delayed" load is an image (because it is part of an <svg:use>
subtree, which gets updated from FlushPendingNotifications). So either bug 1805599 regressed again, or it never really worked as intended?
Comment 33•4 months ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #32)
The way the font face invalidation and co works is that it marks stuff dirty and schedules a flush. As I understand it, right now SVG images only trigger rendering updates on-demand (as a result of animations and so on), so it's unclear to me how it's supposed to work? In any case font face loads and so on do block the load event, generally.
The VectorImage has a SVGRenderingObserver, when something in the svg document happens that would change the rendering, OnRenderingChange should be called
In nsIFrame::SchedulePaint we have a InvalidateRenderingObservers call
that should cause an OnRenderingChange call. For non animated images that should get to VectorImage::SendInvalidationNotifications which should invalidate saved renderings (SurfaceCache::InvalidateImage) and then send out an image notification FLAG_FRAME_COMPLETE
which should reach any use of the image in a document and cause it to repaint.
I was not familiar with that mechanism myself at least. Bug 1877126 is a very similar case where the "delayed" load is an image (because it is part of an
<svg:use>
subtree, which gets updated from FlushPendingNotifications). So either bug 1805599 regressed again, or it never really worked as intended?
I think that bug 1805599 did work as intended and hasn't regressed because I spent a good chunk of time writing a reliable test for it that is still in tree. I suspect there is another bug at play.
In the past I think we've had bugs where we didn't call InvalidateRenderingObservers or something else in that path from some code, that would be a good guess as to what might be happening.
Assignee | ||
Comment 34•4 months ago
|
||
So what happens is that InvalidateRenderingObservers would be called only after reflow, and there's nothing triggering the reflow right?
Comment 35•4 months ago
|
||
How come nothing is triggering reflow? I'm not familiar with the font code.
Comment 36•4 months ago
|
||
So font loads up, and it tries to ensure that there will be a layout flush, but then doesn't do so - No reflow seems to happen afterwards. Perhaps because because mDocument->GetDisplayDocument() == nullptr
?
Assignee | ||
Comment 37•3 months ago
|
||
Right, it seems the cue for updating the containing documents should (also?) be EnsureLayoutFlush
Comment 38•3 months ago
|
||
I don't think svg images use the mDisplayDocument field on Document's, that is for svg filters referencing uris and things like that.
I think the problem is this
The above will ask for a refresh driver tick, but the timer won't get started. It's not an animated svg, so it doesn't get registered as an animated image, and hence VectorImage::RequestRefresh isn't called, and so the refresh driver for the svg document is not ticked, and the reflow doesn't happen.
I think the proper fix would be something like giving non-animated svg's being used as images one tick when requested. We tell if it's animated using this code https://searchfox.org/mozilla-central/rev/783fac5174123467e97fbb955a4ede7eb6e6f419/image/SVGDocumentWrapper.cpp#101
Description
•