Skip to content
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

Image rendered before all required webfonts are loaded #166

Open
jammus opened this issue Nov 22, 2016 · 6 comments
Open

Image rendered before all required webfonts are loaded #166

jammus opened this issue Nov 22, 2016 · 6 comments

Comments

@jammus
Copy link

jammus commented Nov 22, 2016

We're seeing problems when multiple versions/character sets of a webfont are required. In this case the text with the superscript and the Japanese text are not rendered, likely because the font has not been loaded in time.

Is it possible to detect when all fonts have been loaded?

Test case
Open https://jsfiddle.net/urmeo3du/8/

Expected
See "HEADER 67ᵗʰ 浜崎あゆみ TEXT" repeated (once as HTML, once rendered on canvas)

Result
"HEADER TEXT" is displayed

Note
You may have to disable cache (eg, keeping the console open) when running the test. Also, subsequent runs of the test may render correctly.

(otherwise, this library is working great; thanks for making it available)

@cburgmer
Copy link
Owner

Thanks, very interesting find.

What I can reproduce:

  • Firefox so far in all cases looked good, both Latin and Japanese characters displayed,
  • Chrome would only render Japanese on the second run,
  • Safari would not render anything in the first run, Latin and Japanese on the second then.

This reminds me of an old problem we used to have with rendering images reliably. Initially both Firefox and WebKit had problems, but over time they got fixed. I did not do a good job in tracking the bug(s) I raised for this, so I would have to dig a little. However, I remember vaguely that the HTML5 specification did not design for the case of the data URIs being included in any kind of loading event. For the browser that meant that there was no way of knowing if the SVG (that we are creating internally) was ready to be rendered.
The workaround implemented did a mediocre job at best and was removed in 2014 (c3c04a1) as it was invasive and the problems in the browsers overall went away (and the workaround did not change anything for the remaining ones, see #81 ).

If I am correct and the issue we are facing does indeed rely on how the browser renders the SVG to the canvas, then there's nothing we can do directly. Once the library is done compiling the SVG, the browser is responsible for painting.

That said, there might be some room for a clever work around.

@cburgmer
Copy link
Owner

Here's the issue I just mentioned for Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=789249. I might have not filed any against Chrome/WebKit back then.

@jammus
Copy link
Author

jammus commented Dec 5, 2016

Thanks for taking a look, @cburgmer. We're currently getting around this by explicitly loading the fonts as base64 encoded strings (https://gist.github.com/stefanmaric/a5043c0998d9fc35483d) rather than having the browser fetch them on demand.

Not a clever work around, but a work around.

@cburgmer
Copy link
Owner

cburgmer commented Dec 6, 2016 via email

@cburgmer
Copy link
Owner

cburgmer commented Feb 9, 2017

To add another data point. Generally loading a webfont into a canvas works, as this is covered by the integration test (https://github.com/cburgmer/rasterizeHTML.js/blob/master/test/manualIntegrationTestForWebkit.html).

@whizark
Copy link

whizark commented Oct 15, 2019

I have faced the same issue.
Embedding Web fonts as Data URI (as janmus mentioned) solves the issue on Chrome 78, Firefox 69.
Polling with Server-side sleep script also solves the issue.

  1. add allow-scripts to sandbox iframe.
  2. load Web fonts with <link> and inject polling script in rasterizeHTML.drawHTML() content.
  3. start polling Server-side sleep script with iframe. (This delays load event.)
  4. load the same Web fonts with Web fonts loader.
  5. stop polling when the fonts are loaded.

However, these don't work at all on Safari 12-13.
Safari unstably produces incomplete canvas image. The elements not to draw are not only Web fonts but also normal img element with Data URI.
It seems HTMLImageElement (img) doesn't property trigger load event when the src is Data URI as cburgmer mentioned.

I tried to merge old workAroundBrowserBugForBackgroundImages() workaround with current version but it didn't work either,

As a workaround, delaying Canvas.drawImage() solves issue for my case (although it it messy and not stable depends on the resouces in content).
https://github.com/cburgmer/rasterizeHTML.js/blob/1.3.0/src/rasterize.js#L39

                    return new Promise(function (resolve, reject) {
                        setTimeout(function () {
                            drawImageOnCanvas(result.image, canvas);

                            resolve(result);
                        }, 5000);    // Delays Canvas.drawImage()
                    });

(rasterizeHTML.js 1.3.0)
Related: #81 #116


Added on 2019/10/15 13:32 (UTC):

(Combining Canvas.drawImage() delay) with old workAroundBrowserBugForBackgroundImages() workaround with delay seems to improve unstability a bit in my case.

c3c04a1#diff-acf7a42b742684614a3809fea6629faaL796

                    setTimeout(function () {    // Delay cleanup div for workaround.
                        cleanUpAfterWorkAroundForBackgroundImages(svg, canvas);
                    }, 50000);

Added on 2019/10/15 14:48 (UTC):

About Web fonts, workarounds above improve canvas rendering a bit but still unstable...
About Image with Data URI, sometimes it seems to be improved but almost not (probably depends on browser's disk/in-memory cache).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants