Open raphaelokon opened 9 years ago
Hi @raphaelokon, I know this is old, but do you still have this issue? Could you provide me with the font so I can test it?
I'm able to reproduce this one.
Here's my source font file: https://www.dropbox.com/s/hxukwekcetivirc/FiraCode-Bold.otf?dl=0
Here's the subsetted version (created with opentype.js in node): https://www.dropbox.com/s/x6shux7arexvp9o/basic-latin2.otf?dl=0
@fdb could you take a look at why the subsetted version might yield the browser error: "Failed to decode downloaded font"?
Thanks! I'm just uploading these to GitHub to avoid future 404 links :)
This happens because both on Firefox and Chrome, fonts get "sanitized" using ots.
Trying this with the basic-latin2.otf
file, I get
$ ./ots-sanitize basic-latin2.otf
ERROR: CFF : Failed to parse table
Failed to sanitize file!
So this is a bug in the CFF
table but we don't know where. Since OTS is open-source I downloaded it in and uncommented #undef OTS_DEBUG
in config.h
to get more information about the error message. This gives me the following information:
ERROR at src/cff.cc:150 (ParseNameData)
ERROR at src/cff.cc:952 (Parse)
ERROR: CFF : Failed to parse table
Failed to sanitize file!
Looking at ParseNameData
on line 150, I find:
// non-ASCII characters are not recommended (except the first character).
if (name[j] < 33 || name[j] > 126) {
return OTS_FAILURE();
}
// [, ], ... are not allowed.
if (std::strchr("[](){}<>/% ", name[j])) {
return OTS_FAILURE();
}
So I've printed out the font name. The name OpenType.js generates is Fira CodeBold
(note the space). The original name is FiraCode-Bold
. This is what OTS is complaining about: spaces are not allowed in the CFF font name.
If we comment out that code from OTS, the font validates successfully.
So we need to fix this in OpenType.js: whenever we write out the font name in the CFF table, we should make sure it doesn't contain any spaces.
Weirdly enough, there is already an explicit fix for this. Unless you specify the postScriptName yourself, OpenType.js should never generate a name with spaces.
Here's the code I use to generate a subset font that passes through ots:
const opentype = require('../dist/opentype.js');
const font = opentype.loadSync('../fonts/FiraSansMedium.woff');
const uniqueChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 ';
let glyphs = font.stringToGlyphs(uniqueChars);
glyphs.unshift(font.glyphs.get(0)); // .notdef glyph
let subsetFont = new opentype.Font({
familyName: font.names.fontFamily.en,
styleName: font.names.fontSubfamily.en,
unitsPerEm: font.unitsPerEm,
ascender: font.ascender,
descender: font.descender,
glyphs: glyphs
});
console.log(subsetFont.names.postScriptName.en);
subsetFont.download('FiraSansSubset.otf');
@fdb This fix is actually recent and not pushed on npm
This seems related to #339. I propose hammering a bit more on checking the user-given and auto-generated names so they don't throw any errors in OTS.
The regex by @fpirsch (.replace(/[^!-~[\](){}<>/%]/g, '')
) seems suitable.
Also, I notice we do this in two places: in font.js and in sfnt.js when writing out the font. I propose just doing it in sfnt.js.
Also: should we throw an error if a user specifies a PostScript name that is not valid?
Note that the replace is just one part of the validation. The length of the name is also important.
@fdb the safest option so far is to do smething like this
var postScriptName = 'mySuper Font Bold'
// Remove white-space and everything that is not a-z A-Z 0-9 or a dash
.replace(/[^a-zA-Z0-9-]/g, '')
// Remove dash from beginning of name
.replace(/^[-]*/g, '');
With a max length of 29 chars. Also only 1 dash should be present to avoid any issue...
Hi guys. I am creating a subsetted TTF from a TTF like:
When I try to use this font with a @font-face I get a
Failed to decode downloaded font
message in browser. Any clues? Any help really appreciated.