opentype.js icon indicating copy to clipboard operation
opentype.js copied to clipboard

Loading the font with @fontface?

Open Aetherpoint opened this issue 11 years ago • 30 comments

Curious – is there anyway to access the font object with a CSS @fontface? Or would that require recompiling the font somehow?

Aetherpoint avatar Aug 14 '14 00:08 Aetherpoint

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...

fpirsch avatar Aug 14 '14 06:08 fpirsch

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.

moyogo avatar Aug 14 '14 09:08 moyogo

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?

Aetherpoint avatar Aug 20 '14 00:08 Aetherpoint

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.

fdb avatar Aug 20 '14 07:08 fdb

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.

davelab6 avatar Aug 20 '14 13:08 davelab6

Ah, I thought the WOFF was required, but it looks like browsers can just read OTF directly. Cool! I'll go try that.

fdb avatar Aug 20 '14 13:08 fdb

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.

davelab6 avatar Aug 20 '14 17:08 davelab6

Didn't know about that. Is that documented anywhere?

fdb avatar Aug 20 '14 18:08 fdb

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)

Pomax avatar Sep 24 '14 17:09 Pomax

@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/

raphaelokon avatar Mar 18 '15 20:03 raphaelokon

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.

Pomax avatar Mar 18 '15 20:03 Pomax

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.

raphaelokon avatar Mar 18 '15 21:03 raphaelokon

Has any of this been implemented?

cyberwombat avatar Nov 26 '16 16:11 cyberwombat

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.

fdb avatar Nov 26 '16 20:11 fdb

Thanks. I was able to use the toArrayBuffer() and convert to base64 and load it that way in my css.

cyberwombat avatar Nov 28 '16 00:11 cyberwombat

Yeah, we should probably add that to OpenType.js directly....

fdb avatar Nov 28 '16 08:11 fdb

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.

Pomax avatar Nov 28 '16 17:11 Pomax

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 avatar Feb 12 '23 13:02 Connum

@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.

ILOVEPIE avatar Feb 12 '23 22:02 ILOVEPIE

WOFF2 at least, then. WOFF was superceded quite a while ago =)

Pomax avatar Feb 12 '23 23:02 Pomax

@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.

ILOVEPIE avatar Feb 12 '23 23:02 ILOVEPIE

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.

Connum avatar Feb 13 '23 09:02 Connum

@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.

Pomax avatar Feb 13 '23 18:02 Pomax

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?

ILOVEPIE avatar Feb 13 '23 22:02 ILOVEPIE

@Pomax here's how you can export/import WOFF2 from opentype.js: https://github.com/opentypejs/opentype.js/issues/183#issuecomment-1147228025

ILOVEPIE avatar Feb 13 '23 22:02 ILOVEPIE

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 avatar Apr 21 '24 00:04 Connum

@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.

Pomax avatar Apr 21 '24 04:04 Pomax

It's pretty self-explanatory.

ILOVEPIE avatar Apr 21 '24 05:04 ILOVEPIE

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.

Connum avatar Apr 21 '24 09:04 Connum

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" =)

Pomax avatar Apr 21 '24 16:04 Pomax