Generating PDFs on Server Side

The troubles we faced to get PDF emails working in CentOS

 · 3 min read

Generating PDFs on server was easy. Or was it?

Once we figured out wkhtmltopdf, it was about 10 lines of new code that had it working. We felt embarrassed; why hadn’t we implemented this sooner!

But there's a catch. We do our development on macbooks. And on a mac, everything looks pretty. It was our folly that we expected it to work out of the box on a Linux server. (Sigh)

Once we deployed the new code with PDF print feature, and sent a test email, this is how it looked:
PDF with black boxes

The minimal CentOS system didn’t have any fonts! We quickly installed X11 font packages and dependencies. It got rid of the black boxes. Yet the rendered PDF looked ugly. The default font was uninspiring and the kerning was incorrect (the space between each character of a word).
PDF with bad kerning

So we installed Open Sans, and changed the font in the Print Format code. Now it was prettier, but the kerning was still not right.
PDF with Open Sans and bad kerning

We had a heated discussion about installing Infinality patches to freetype, but reached no conclusion. After some google searches, we found a discussion about the kerning issue on wkhtmltopdf’s github issues. We added the suggested fontconfig XML to enable hinting, anti-aliasing and lcd filter.

Now it looked harmonious. If only hinting and anti-alaising were the defaults! It could’ve saved the time of many a soul. Quoting Rushabh, “I am sure some beard would have shaken his head - ‘no we don't know the full consequences’”
PDF with hinting

But then we observered another problem. The rupee symbol (₹) was represented as a blank block. None of the fonts in the system had this glyph.
PDF with missing rupee symbol

A google search result suggested that we install the font DejaVu, which we did via yum install dejavu-sans-fonts. It was supposed to have the missing glyph. However, the result was the same. The generated PDF did not embed the font DejaVu Sans. We came to the conclusion that the glyph fallback system was not working.

We read about how fontconfig works and tried different configurations, but nothing worked.
  1. Diagnosing font issues on Linux
  2. Gentoo Fontconfig
  3. ArchLinux Font Configuration
  4. Font Insanity

While reading these articles, we realised that we didn’t have the fonts for other languages, which we confirmed by generating a PDF with Chinese characters in it. We quickly reverted the PDF generation code and gave up the fight for the day. Fonts are not easy on a Linux server.

-

The next day, we installed urw-fonts package based on a suggestion on Stack Overflow. This should have alleviated the other language problem, but it didn’t. We also tried out a few more font configurations, but in vain.

We needed to test our assumption about the need of a special font configuration for glyph fallback. We tested PDF generation on a laptop having Elementary OS and it worked without any special font configuration.

This revelation made us think of a quick hack. We spawned a new instance on Digital Ocean with CentOS, then installed fontconfig and X11 dependencies and wkhtmltopdf. Then we copied the default font config and all fonts of Elementary OS to this instance. And it worked! The rupee symbol was there and so was text in Japanese. The PDF embeded DejaVu Sans for the rupee symbol. This meant that the version of DejaVu Sans which we had installed via yum was too old, and urw-fonts package did not have support for Chinese and Japanese, probably because it too was an older version.
PDF with Rupee Symbol

PDF with Japanese

But we were releaved that a solution existed, albeit hacky. We could see a purist shaking his head in our mind.

In conclusion, wkhtmltopdf needs fonts installed on the system, for all possible characters it is going to print into a PDF, so that it could have fallback glyphs. So, on a CentOS system one would need to:

  1. Install libXrender, libXext, wkhtmltopdf
  2. Copy font configurations into /etc/fonts and font files into /usr/share/fonts. You can get them from this github repository. It uses fonts provided by Elementary OS.
  3. fc-cache to clear font cache


Anand Doshi

Anand is the Chief Technology Officer at ERPNext. He reads fiction, dabbles in photography and is always on the watch for the best ToDo app.

No comments yet

No comments yet. Start a new discussion.

Add Comment