gofpdf
gofpdf copied to clipboard
Question: Font Embedding vs. Outlines
It seems now when I use a font, the entire font gets embedded into the document. For me this can lead to large file sizes, espcially if I only use that font for a few characters. Is there an option to only render the given characters as outlines rather than embedding the entire font? Or is it already doing that?
Rendering the characters as outlines isn't the right answer. Instead it needs to be able to select a font subset to embed. However I don't expect that to be an easy thing to achieve, with code pages and higher unicode involved.
This will become relevant to me if/when I complete the FPDI port and start combining multiple documents that each embed the same fonts, or different subsets of the same font. And for good reasons I've used fonts that cover a lot of alphabets (Russian, Polish etc) so they're going to be big fonts. Effective font subsetting will be essential.
Hi @marcusatbang thanks for responding. The reason I mentioned outlines, is that it is (or was at least) fairly common practice to simply outline your fonts before sending them to the printer. This way you avoid a lot of font headache. However subsetting does seem like a better solution. Does this mean the library would detect which characters were used and create a kind of dynamic font that only has those characters?
Don't thank me too much. I'm not actually going to write it. :)
That's how font subsetting works, in theory. A specific version of the font is built that contains the characters (or the character planes) you need. But this is more complicated in PDF because it predates Unicode, and fonts bigger than a single code page may end up represented in a complex way. I don't even understand all the complexities involved.
I imagine this could be an expensive operation, so it may be best to put it behind an explicit call or flag. Something like pdf.EnableFontSubset(true)
. Even so, some sort of font-combining may be inescapable when loading documents as templates.
If flattening glyphs to outlines is valuable step in print preflight, that would be a whole separate topic.
Good summary, @marcusatbang. I had not thought about the potential repercussions of font subsetting with templates.
@scisci If you know in advance which characters in a font you are going to use, you could manually create your own font subset using an external tool.
On the grounds that some sort of strategy should be used wherever file templates are used, and approaches may evolve over time, I'd like to amend my previous flag suggestion to something more flexible like:
pdf.SetFontStrategy(gofpdf.FontStrategyAlwaysSubset)
BTW, I've seen at least one source that suggested renaming subset fonts with a prefix like so: a95f6ec+MinionProRegular
In some cases, the files generated from makefont can be quite large. For people looking for a workaround until this is fixed, I was able to shrink the pdf size from a 15.5 MB file to a 270kb file by piping the output to ghostscript. incomplete example follows:
cmd := exec.Command("gs", "-sDEVICE=pdfwrite", "-dCompatibilityLevel=1.4", "-dPDFSETTINGS=/screen", "-dNOPAUSE", "-dQUIET", "-dBATCH", "-sOutputFile=-", "-")
inPipe, err := cmd.StdinPipe()
errChan := make(chan error, 1)
go func() {
errChan <- cmd.Start()
}()
pdf.Output(inPipe)
@farkerhaiku Thanks for this technique! I have added an example to the contrib directory that demonstrates this: ghostscript.go.