Open Bug 1759688 Opened 3 years ago Updated 3 years ago

Allow font families to be initialized synchronously, when needed by canvas rendering

Categories

(Core :: Layout: Text and Fonts, enhancement)

enhancement

Tracking

()

People

(Reporter: jfkthame, Unassigned)

References

(Blocks 1 open bug)

Details

For HTML rendering, we allow font Family records for the system's installed fonts to be initialized asynchronously, to avoid blocking layout; if a family isn't yet ready for use, fallback will happen, and then when initialization is complete, the content will be reflowed.

However, this doesn't work well for canvas, because it doesn't have the same built-in reflow mechanism available. If the canvas code calls for a font-family that is not yet fully initialized, and we draw with a fallback, that fallback rendering will persist until the canvas is explicitly redrawn -- and in general there's no way for the page to know that it needs to do so once the async font initialization is complete.

Therefore, I think canvas rendering should instead use a synchronous mechanism to initialize font-family records. This may sometimes block the initial rendering while font loading completes, but it is necessary for correctness.

This is an issue for regular canvas2d as well right?

Yes, it would be - it's just brought itself to my attention afresh when playing with offscreenCanvas stuff but I believe it's an issue for any canvas.

(In reply to Jonathan Kew (:jfkthame) from comment #2)

Yes, it would be - it's just brought itself to my attention afresh when playing with offscreenCanvas stuff but I believe it's an issue for any canvas.

Correction: actually, I don't think that's the case; I was mis-remembering the interactions that happen.

Regular canvas2d rendering runs on the main thread, and when gfxFontGroup::AddFamilyToFontList includes a family in the current fontGroup's list, it will synchronously call InitializeFamily if necessary.

The case where initialization happens asynchronously is when a stylo thread is the first thing to need a particular font family, because the InitializeFamily IPC message can only be sent from the main thread.

So main-thread canvas doesn't have an issue here after all. But for an offscreen canvas running in a worker, if we try calling gfxPlatformFontList::InitializeFamily, it sees that it's not on the main thread, and instead of synchronously doing the initialization, it just posts a Runnable to the main thread, and returns. Which means the current offscreen-canvas operation won't have the font available, and uses a fallback; only on the next canvas operation will the intended font be available.

(There's a somewhat parallel issue for regular main-thread canvas when webfont resources are involved, because the first access to the webfont just initiates an async load, and -- unless it's an inline data: URL -- the font is unlikely to be ready for use during the same call. But that's a well-understood result of lazy resource loading, and there's the CSS Font Loading API -- document.fonts.load(...) etc -- to allow authors to explicitly manage it. But that's only used for webfont resources, it's not applicable to the platform installed fonts.)

You need to log in before you can comment on or make changes to this bug.