printpdf icon indicating copy to clipboard operation
printpdf copied to clipboard

TTC and OTC font files cause Rusttype(IllFormed)

Open t-shin-komae opened this issue 6 years ago • 13 comments

Reading opentype fonts(.otf) or truetype collection files (.ttc) causes panic!

let mut font_reader = std::io::Cursor::new(include_bytes!("../assets/fonts/Cantarell-Bold.otf").as_ref());
let font = doc.add_external_font(&mut font_reader).unwrap();

The second line caused panic, and retrun Rusttype(IllFormed). I tried .ttc file and this also failed.

t-shin-komae avatar Feb 19 '19 07:02 t-shin-komae

Yes, rusttype doesn't support TTC and OTF files, only TTF (and OTF fonts that are a direct wrapper of a TTF font). The question is whether I'd want to go back to using freetype because it caused compliation problems on Windows.

fschutt avatar Feb 19 '19 17:02 fschutt

Perhaps it would work to use https://github.com/pcwalton/font-kit?

jrmuizel avatar Feb 19 '19 18:02 jrmuizel

No, font-kit is for finding fonts on the computer, not decoding them (it uses freetype for that). It's a completely different tool, it has nothing to do with decoding fonts.

fschutt avatar Feb 19 '19 18:02 fschutt

font-kit let's you get the metrics for fonts using the system font libraries. i.e. CoreText on Mac and DirectWrite on Windows. By default it will only use FreeType on Linux.

Is there information that printpdf needs to get from the fonts that font-kit doesn't provide?

jrmuizel avatar Feb 19 '19 19:02 jrmuizel

I wonder if we could replace rusttype with the allsorts crate.

messense avatar Dec 24 '19 05:12 messense

It seems rusttype is going to support OTF in a future release by using ttf-parser. According to the changelog :

Unreleased

  • Major rework to use crates ttf-parser & ab_glyph_rasterizer to respectively read and render OpenType .oft [sic] format fonts.

Ashashin avatar Apr 16 '20 16:04 Ashashin

rusttype now supports OTF (from release 0.9.0). From the changelog:

Major rework to use crates ttf-parser & ab_glyph_rasterizer to respectively read and render OpenType .oft format fonts.

atauveron avatar Apr 23 '20 16:04 atauveron

So this issue should be resolved by just updating rusttype to 0.9, shouldn't it?

It's good to hear that rusttype now supports OTF, but at some point I have to refactor it with something like a FontMetricsProvider trait - so that you can add a font from both freetype AND rusttype. Right now rusttype still doesn't do any font shaping, which might be an issue.

fschutt avatar Apr 24 '20 08:04 fschutt

Any updates on this? I'll take a stab at it myself. It's holding up the hack to get around #2, too.

ghost avatar Jun 25 '20 13:06 ghost

I tried updating to rusttype 0.9, but ran into some refactoring errors. You just need to update the crate and fix the resulting compilation errors.

fschutt avatar Jun 25 '20 16:06 fschutt

I think I've got it mostly sorted, just have to fix a few glyph size issues. Seems the rusttype guys ditched some key 0.8 apis that don't have direct equivalents.

It now handles .ttfs just as it used to. It's fine in that regard. ~~It now too can embed and use .otf glyphs, but there's no spacing and it appears that what text I give it and what text it outputs is (char + 44), (i.e., - -> q) for some reason.~~ This happens when loading Zilla Slab TTFs too. I've only modified a small portion of the code, so I know what part is breaking it, but I'll have to work at it a little more. I'll get a PR open ASAP.

ghost avatar Jun 28 '20 03:06 ghost

I'm a little stumped right now. The font embeds fine, but glyphs are mapped wrong, and what they're mapped to depends on the font.

For Zilla Slab Highlight Bold, the PDF contains "O" (0x004F) but displays Ć (0x0106). Furthermore, there's a complete lack of spacing. Characters simply stack on top of each other (though I can see this being a totally different problem). Again, these only apply to external fonts, both OTF and TTF.

My changes are at eitasuka/printpdf and the above broken pdf in this gist.

ghost avatar Jun 28 '20 07:06 ghost

@eitasuka It's likely because the Subtype of the font in the font descriptor is wrong.

See: https://github.com/fschutt/printpdf/commit/209bb910a19dc37fd7eac2d6c60c14f6387b84fb - you have to use the correct Subtype, since it's now OTF (CidFontType0C) instead of TTF (CidFontType2). I'll have to look up what the correct type is, the PDF spec has more info.

fschutt avatar Jun 28 '20 09:06 fschutt