opentypejs / opentype.js

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

Renderer crashes with hinting error after ttfautohint #395

Open puzrin opened 5 years ago

puzrin commented 5 years ago

Expected Behavior

Current Behavior

crash with error:

Hinting error:Error: unknown instruction: 0x78
Note: further hinting errors are silenced

Steps to Reproduce (for bugs)

If you decide to reproduce via our (affected) script:

./lv_font_conv.js --size 14 --bpp 4 --format dump --font freesans_ttfa_hinted.ttf --symbols P -o 1111

For install instructions: https://github.com/littlevgl/lv_font_conv

Context

We do font convertor to generate bitmap fonts for embedded systems. Previous version was in PHP an used built-in renderer (freetype?).

While good quality possible only via pixel-perfect fonts, someone reported, that opentype.js result is worse than in php. See screenshots (and more data in previous posts)

I tried to disable & enable hinting in opentype.js and found no difference. My assymption was, that hinting info may exists only for very small size (not exists for 14px). So, tried to enforce this via ttfautohint. But when tried to generate bitmaps with rehinted font, script crashed.

Could you take a look what happens?

Your Environment

puzrin commented 5 years ago

@axkibe seems you are author of hinting processor. Any chance to fix ttfautohint support?

I've tried to add this function into instructions table:

    function JROT(state) {
        const e = state.stack.pop();
        const o = state.stack.pop();

        console.log(state.step, 'JROT[]', e, o);

        if (e) state.ip += o - 1;
    }

State machine itself works (no more errors), but result looks broken. Probably more errors in other commands.

axkibe commented 5 years ago

Sorry didn't get a notificiation of the mention from github.

As far I can tell your implementation of that instruction looks fine to me.

Second sorry, I don't think I can invest the time anytime soon to debug through that whole font. This is a large task. While the implementation is made according to the documentation from Apple and Microsoft, debugging the state machine is best done by writing a small demo .c file using freetype and inserting step by step debug output into freetype to see at which step the opentype.js state machine differs from it.

I implemented the existing TT hinting engine simply on a tight fit on the fonts I wanted to get hinted.

Ultimately I consider the idea of writing a full blown autohinting engine within the TT state machine a bit ridiculous. If we want autohinting, we could write that into opentype.js right away using javascript and by simulating another VM within JS.

BTW: I don't know where Windows is currently moving with this, but what I read Apple already made the step to completely ignore the hinting instructions from fonts and force their autohinter over it anyway. Which is allegedly better than what most fonts provide from themselves. However this is again not something easily duplicated as there went years of research into their autohinting engine and if the Linux desktop can't do it, I don't think we can do this in Javascript :)

puzrin commented 5 years ago

After investigating details - switched to FreeType webassembly build. When autohinting needed, it's not realistic to repeat all features in reasonable time.

https://github.com/littlevgl/lv_font_conv - if anyone intereated, you can inspect how to do that via docker (in dev branch, until landed).

But we still have to continue use opentype.js to extract simplified kerning info from GSUB table (when kern table missed). Because Freetype does not support this at all (doc says to use full-featured composer like Harfbuzz)