opentypejs / opentype.js

Read and write OpenType fonts using JavaScript.
https://opentype.js.org/
MIT License
4.49k stars 477 forks source link

Font outlines are broken #102

Open raphaelokon opened 9 years ago

raphaelokon commented 9 years ago

Hi.

I am creating a subset of a font in node.js and saving the new font back. But when I inspect the newly created font some of the anchor points are shifted. I tried with several fonts from the googlefontdirectory. Does anyone experience similar problems?

raphaelokon commented 9 years ago

When I test the original font with the opentype.js webdemo it works. I attached an image of the issue …

outlines_meow

fdb commented 9 years ago

Thanks for pointing this out! This happens when a TrueType font is converted to a PostScript font.

I've tracked it down to half-point values: fonts with TrueType outlines (but not PostScript) can have half-point values (e.g. 247.5) for coordinates. When converting to PostScript, the decimals are removed. But since the points are stored as delta values from the previous point, these differences add up, causing the beginning and end of the curve to not match up anymore.

This is actually mentioned in FontForge's Bézier splines page:

(Anish Mehta points out that in truetype it is possible to specify points which are in the middle of a pixel (ie. with an x or y value ending in 1/2). These will also introduce rounding errors when converted to postscript, but here the solution is simple: Scale the em-square of the font by a factor of 2 and the problem vanishes).

I'm not yet sure how to fix this. Scaling the em-square sounds like a good idea, but might be difficult to implement because of the generic nature of opentype.js.

raphaelokon commented 9 years ago

@fdb Thank you. By scaling you mean just to specify a multiplied version as em square when creating the font?

I'm not yet sure how to fix this. Scaling the em-square sounds like a good idea, but might be difficult to > implement because of the generic nature of opentype.js.

Well, couldn't we interpolate the TTF em square ×2 before converting to Postscript? And then convert the em square of the postscript back once we export?

Also: What leaves me puzzled is that when I upload the TTF font to your github demo page, the glyphs themselves look good, not offset of the start and end anchor.

raphaelokon commented 9 years ago

Okay, I fixed that just by using the .otfversion of the fonts.

fdb commented 9 years ago

The error manifests itself when converting from quadratic curves (used in TrueType outlines) to bézier curves (used in PostScript outlines). When parsing fonts with TrueType outlines, the paths are built and drawn using quadratic curves, so they render correctly.

In fact, the conversion to bézier is not even the problem. It's the fact that PostScript always stores relative coordinates from the previous point that increases the error; that is what makes the beginning and end of the path not match up.

fdb commented 9 years ago

Also, to fix this, I just round the values, which has the same effect as scaling up and back down. Results are good, except that I still need a small heuristic to see if the beginning and end of the path match up: that's important to get anti-aliasing look good.

raphaelokon commented 9 years ago

Yes, makes perfect sense to me! If I can help out let me know.