fschutt / printpdf

An easy-to-use library for writing PDF in Rust
https://docs.rs/printpdf/
MIT License
805 stars 96 forks source link

TTC and OTC font files cause Rusttype(IllFormed) #28

Open t-shin-komae opened 5 years ago

t-shin-komae commented 5 years ago

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.

fschutt commented 5 years ago

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.

jrmuizel commented 5 years ago

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

fschutt commented 5 years ago

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.

jrmuizel commented 5 years ago

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?

messense commented 4 years ago

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

Ashashin commented 4 years ago

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

Unreleased

atauveron commented 4 years ago

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.

fschutt commented 4 years ago

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.

ghost commented 4 years ago

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

fschutt commented 4 years ago

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.

ghost commented 4 years ago

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 commented 4 years ago

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.

fschutt commented 4 years ago

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