Open gordyr opened 9 years ago
@gordyr thanks for an excellently-articulated rationale! Considering the small size of @zachleat's polyfill, I wouldn't mind using it as an optional dependency, similar to what we do with @mudcube's Event.js for gestures on mobile. We could then detect presence of FontFaceOnload and calculate chars width automatically (in fromObject and/or other places)
i could try to set it up.
@asturur Andrea, that would be great
Is FontFaceOnload library similar to Google's WebFont? Because when preloading fonts with WebFont, you still need to create a DOM element that uses that font-family before using that font-family in Fabric. Otherwise, that font doesn't get used unless you click on the canvas once.
See discussions here: https://groups.google.com/forum/#!topic/fabricjs/sV_9xanu6Bg http://stackoverflow.com/questions/28877001/canvas-only-renders-custom-webfont-on-click-event-with-fabric-js
I've found this method of "creating (off screen) a DOM element that uses the font family right before using it in the Canvas for the first time" to be reliable in ensuring that the font really gets used. You still need some preloading mechanism with callbacks like WebFont or FontFaceOnload. Was just wondering if FontFaceOnload prevents this hack of adding a DOM element.
No the new font loading API is entirely different to googles webfont loader which is just an abstraction built in JavaScript to approximate the detection of loaded webfonts
The new API is native to browsers and does not use any Dom elements.
Hm? Author of FontFaceOnload here.
When the CSS Font Loading API is available, it does not use DOM elements, sure. However, the polyfill behavior does. Native API support is limited http://caniuse.com/#feat=font-loading
TypeKit (which is what Google WebFonts uses) currently uses the polyfill behavior in all browsers (no CSS Font Loading API use yet).
Exactly, that's why I suggested using your library. So that we support browsers without native font loading.
Nice! Thanks for the clarification @gordyr @zachleat
@gordyr would you be willing to share your modifications of zachleat's fontfaceonload ? (Re: "The one I am using is a slightly modified version of this one: https://github.com/zachleat/fontfaceonload The only modifications I have made is to check for native websafe fonts first and abort the loading check and firing the callback right away if we know the browser already supports them (on fonts like Arial and Times new roman etc.) Thanks!
I wrote functions to load fonts from google webfonts library. Also i solved all issues with characters width/lines width and loading texts from json with google web fonts applied
@AlexanderIstomin how did you solve the issues with characters width and lines width? I am still getting extra spaces when using diacritics (modifying characters) in e.g. Arabic etc. Care to share any code? :)
i will create fiddle tomorrow with latest version of my code
just copied and pasted some code parts to jsfiddle. https://jsfiddle.net/765doq2b/1/
i would follow a slight different approach, instead of changing the font and then check if it needs to be loaded and resetting caches,
i would load the font, and then change the font to the object. In that case no reset is necessary at all.
Most font loader return a promise or take a callback, so you can change the font in the callback or in the then
part of the function.
Thanks for making a fiddle anyway!
agree. but i faced with char width problem somewhere in 1.4.x versions, so resetting is (as i remember) solved that issue.
There are several bugs within fabric caused by not always knowing when a webFont has been loaded.
A very easily reproducible one is as follows:
I-Text
object with several reasonable wide lines of text.Nosifer
from the google WebFonts directory as it is much wider than any native web safe fonts).backgroundColor
to theIText
box.JSON
then clear your browser cache.JSON
into either a static or interactive canvas usingloadFromJSON
.You will find that although the font gets drawn correctly (Browsers now account for this when using html5 canvas) the dimensions of the object are incorrect and therefore any background color or text that falls outside those incorrect dimensions, fails to render.
As shown here:
When it should look like this:
The reason for this is that fabric, rightfully, check and caches character widths of the loaded font and stores them in an object
_charWidthsCache
in order to prevent them having to be checked constantly during rendering.Now, although browsers will now wait for the font to be loaded (as long as the correct css for the font is in place before attempting to render it) they completely fail to do so when you check character widths. This results in fabrics cached character widths always being out of date, no matter how long you wait (since the cache never gets cleared when the font has loaded).
In the past @kangax has stated that he feels that font loading should be handled by the users app and for the most part I agree. However, when using
loadFromJSON
this is deal breaking as in many apps, you may not know what font a user has selected in advance and cannot therefore preload any fonts without parsing the fabricJSON
yourself before loading it, which I'm sure everyone would agree is a poor solution.Recently modern browsers have added a native font loading API to deal with this problem. Chrome has had it enable by default for a while now and Firefox is enabling it in version 37 in a couple of weeks. (right now you can enable it manually in
about:flags
.For more info see here:
https://dev.opera.com/articles/better-font-face/
And here for the spec:
http://dev.w3.org/csswg/css-font-loading/#font-load-event-examples
There are also several polyfills out there which mimic this behaviour on older browsers and appear to work perfectly.
The one I am using is a slightly modified version of this one:
https://github.com/zachleat/fontfaceonload
The only modifications I have made is to check for native websafe fonts first and abort the loading check and firing the callback right away if we know the browser already supports them (on fonts like Arial and Times new roman etc.) This is actually quite important as this particular fontloader may fail if attempting to load a metric compatible font. There are many others out there that may have this built in, but the solution is a trivial
indexOf
check versus an array of native websafe fonts.Anyway, the above fontLoader will use the new native font loading api of the browsers where available and fallback gracefully on older ones.
Fixing most font loading bugs are then as simple as patching fabric like so:
with the above polyfill and this tiny patch added
loadFromJSON
now works correctly with every webfont I have thrown at it, whatever the dimensions of the characters. Therefore fixing issue #2018 and many others.I believe that the polyfill could easily be added into the
fabric.util
class (perhaps modifying it like I do to avoid attempting to load websafe native fonts) and the above path could be applied to bothText
andIText
with only a tiny amount of code gain. This would solve a lot of peoples problems and prevent the constant recurring issues on here regarding this.Also, I would consider adding it into the
set
method when a user changesfontFamily
in the same manner thatloadImage
is currently used.The reason I have not created a
PR
is simply that I just do not have the time right now, I am swamped. But I would like to get the information here for those of us who have been frustrated with this issue.Hopefully @kangax could consider adding it in himself at some point. I hope this helps!
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.