opentype.js
opentype.js copied to clipboard
Loading the font with @fontface?
Curious – is there anyway to access the font object with a CSS @fontface? Or would that require recompiling the font somehow?
TL;DR : No way
The font object is an in-memory javascript representation of the font. CSS @fontface loads files encoded in specific formats, preferably over the network.
This would require creating a ttfor woff file and using a special encoding to load it.
Note that for compatibility's sake @fontface usually requires more than 1 file format (usually 3 or 4), and that the data-uri encoding makes files 33% bigger...
Actually, as I understand this is a goal of the project. The idea is to generate a font file, convert it to base64 and load it with CSS.
https://github.com/niklasvh/experiments.hertzen.com/tree/gh-pages/jsfont has fontface working in modern browsers with array buffers and blob URL's. Not sure how easy this would be to implement?
Yes indeed, the idea is to create WOFF files, encode them using a data: URL, and then load them back in. As soon as font writing works well, I'll implement the WOFF and data part.
Thanks @Aetherpoint for the reference – I didn't know about that one, might be interesting to look at.
Why is woff needed? On 20 Aug 2014 01:32, "Frederik De Bleser" [email protected] wrote:
Yes indeed, the idea is to create WOFF files, encode them using a data: URL, and then load them back in. As soon as font writing works well, I'll implement the WOFF and data part.
Thanks @Aetherpoint https://github.com/Aetherpoint for the reference – I didn't know about that one, might be interesting to look at.
— Reply to this email directly or view it on GitHub https://github.com/nodebox/opentype.js/issues/62#issuecomment-52742705.
Ah, I thought the WOFF was required, but it looks like browsers can just read OTF directly. Cool! I'll go try that.
EOT is required for older versions of MSIE, and newer versions will render OTF/TTFs as long as the fsType is 0. Anything that will render a WOFF will render OTF/TTFs; its just a compression format.
Didn't know about that. Is that documented anywhere?
not directly, but fsType determines the embedding policy and IE only lets you use fonts as webfonts if they have no embedding restrictions whatsoever. In order for a font to be used as webfont, that flag should be 0 already anyway because otherwise the browser downloading the font to cache counts as "installing" the font, violating the embedding policy =)
(as for WOFF as compression format, that's explained in the WOFF specs. Fun fact: WOFF can be used as a wrapper, but because the data must be compressible, has a few more restrictions on what the table layouts must be compared to regular opentype fonts. No table overlap or out-of-order tag directories allowed, for instance)
@fpirsch the 33% more additional base64 bytes should be mitigated by gzipping when you send the data ==> http://davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/
Note that if opentype.js is already running in-browser, then bear in mind that the data:uri will basically be immediately unpacked again in-memory, so you only save a bit of space in the data: string. The opentype.js font representation, and the font as loaded from data: source will both stay exactly the same sizes. For transmission, using gzipped tables inside the WOFF is a good idea. If it's all in the same client session, there's virtually no benefit.
Ah yes, if it is all in the client that would make no sense. I thought they want to persist it in a CSS/HTML and transfer the font embedded over network.
Has any of this been implemented?
OpenType.js doesn't have this yet, but Plumin.js (which is built on top of OpenType.js) uses this technique.
This is through the CSS font loading API. Note that this currently only works in Chrome and Firefox.
Thanks. I was able to use the toArrayBuffer() and convert to base64 and load it that way in my css.
Yeah, we should probably add that to OpenType.js directly....
As a small aside, given that this issue is grounded in the past (filed august 2014), when the webfont landscape was very different: these days you do want just WOFF (possibly with WOFF2), as eot is obsolete (MS no longer supports any browser that needs the eot format), svg has been disavowed (most browsers that still had support for it in 2014 have since removed support again), and ttf/otf are full system fonts, subject to potentially stricter validation than "explicitly for web" fonts.
I agree there should be an easy integrated way to use the (possibly modified) fonts for text preview in browser context. Doesn't have to be in 2.0.0, but it shouldn't be too complicated to have this soon in 2.x.x at least.
@Connum there's some problems with this, first off I don't think it should be the responsibility of our library to handle this, as it would introduce side effects. Secondly, this is already possible using Object URLs on the generated TTF or OTF files and embedding a new stylesheet that references the object URL. One thing we could do however is support outputting WOFF fonts, that could be useful.
WOFF2 at least, then. WOFF was superceded quite a while ago =)
@Pomax WOFF2 requires some fancy compression that is out of scope for this library, there are libraries that can be used with this one to read WOFF2 files.
Currently, we only have download() as a public method. If you want to only get a URL, you have to use all the more low-level methods yourself, building the DataView from the ArrayBuffer, the Blob from the DataView and finally the ObjectURL from the blob (or build a data: URL yourself by base64-encoding the data). I think it wouldn't hurt to expose a helper method (that we could then reuse in the download() method to download the file). After all, the download() method could be regarded as out-of-scope as well, as you could to that yourself from the underlying data.
As all modern browsers support TTF/OTF directly, I would also see this decoupled from WOFF writing support (which would nevertheless be nice to have), as it would be enough to simply preview the current state of the font object in an input/textarea/contenteditable element.
On a side node, we should probably call revokeObjectURL() in the download method to free up memory.
@ILOVEPIE certainly (I wish JS had a Compression object, given that the browser already has in/deflate, gzip, and brotli built in), but if you're not going to support WOFF2, there's probably not a lot of benefit to supporting WOFF, as the older, superseded standard.
Currently, we only have download() as a public method. If you want to only get a URL, you have to use all the more low-level methods yourself, building the DataView from the ArrayBuffer, the Blob from the DataView and finally the ObjectURL from the blob
iirc can't you just create a blob from an arraybuffer by passing it into the blob constructor?
@Pomax here's how you can export/import WOFF2 from opentype.js: https://github.com/opentypejs/opentype.js/issues/183#issuecomment-1147228025
I just did a quick proof-of-concept here: https://github.com/opentypejs/opentype.js/tree/font-face (font-inspector.html)
It's as easy as
<style>
textarea {
font-family: "OpentypeJsPreview";
}
</style>
<style id="opentypejs-preview-fontface"></style>
<textarea></textarea>
document.getElementById('opentypejs-preview-fontface').innerHTML = `
@font-face {
font-family: "OpentypeJsPreview";
src: url('${URL.createObjectURL(new Blob([font.toArrayBuffer()]))}');
}
`;
For a font editor, you could have a live preview, not having to rely on the not-so-complete rendering capabilities of our library, actually pretty cool. I don't think it would hurt to add a helper method for comfortability, but don't think we're in a hurry to implement that.
Therefore I'll close this issue now.
@Connum That sure sounds like something that needs documenting and surfacing =)
Closed issues are not discoverable. README.md files and docs sites are. So I'd strongly advocate reopening this until that approach has been added to the documentation and has been made easily discoverable.
It's not enough for "you" to know there's a solution: if that solution is not in the documentation, it's not so much a solution as something that only a dev with enough experience will think of. Users of opentype.js span the entire gamut from total newbies to seasoned pros, the latter don't need help, the former definitely need stuff like this covered by the docs, even (or rather, especially) if it seems obvious.
It's pretty self-explanatory.
Maybe we're overestimating the JS-savvyness of our user base. I definitely want to add the functionality at some point, it's just not a priority right now. Let's keep the issue open then.
Based on having helped folks do cool font-related things on the web involving opentype.js in some way, I can at least confirm that the JS-savvyness ranges from "seasoned web typography pro with a day-one typedrawers account and OpenType parsers to their name" to "literally someone's first foray into finally diving into JS" =)