Google Web Fonts and PDF generation from HTML with wkhtmltopdf
Asked Answered
M

10

72

I am using wkhtmltopdf to convert HTML files in PDF format; it gives surprisingly good results, rendering the PDF exactly as WebKit would do.

I am using Google Web Fonts to give users the possibility to customize the appearence of the document they edited, offering them the possibility to choose between a few fonts. It also works perfectly in a browser.

Problem is, I don't get the Google Fonts working when converting such HTML files to PDF with wkhtmltopdf. I read other people had the same issue.

Could anyone please help me fixing this?

EDIT: declaring @font-face directly in the CSS does not work either.

Mikkel answered 17/7, 2011 at 1:8 Comment(0)
T
58

To convert HTML to PDF by wkhtmltopdf try to avoid woff font face. Use the truetype format of the Google Web Fonts with base64 encode.

Recently I tried to use a Google web font from Google Web Fonts. In the browser it shows correctly but it doesn't show after converting HTML to PDF.

After searching the web extensively, at last, I found tools to encode fonts to the base64 format and also got CSS for @font-face.

Read the solution here.

Toxinantitoxin answered 16/8, 2013 at 1:13 Comment(5)
+1. Note: as mentioned in a comment on the linked solution page: It does not seem to work on OS X (10.9) but does work under linux.Semipermeable
It works fine in Windows, and also with the node package wrapper for wkhtmltopdf.Hula
This still does not work with condensed fonts such as Roboto Condensed as per wkhtmltopdf-binary 0.12.3.1 with patched QT. Perhaps due to the persistent kerning bug..?Freeholder
Can you update the link? Page does not longer exist since last monthMacaluso
If it still does'nt work, convert the font to base64 string!Prosaic
M
42

A simple solution: Base64-encode your font and embed it in the CSS:

@font-face {
    font-family: 'OpenSans';
    src: url(data:font/truetype;charset=utf-8;base64,AAEAAAATAQA...
}

FontSquirrel can do this for you through the advanced options of their Webfont Generator; Google and other fonts can be encoded with this tool.

I've used this solution with pdfkit and wicked_pdf, which work through wkhtmltopdf, so I presume this should work with the native wkhtmltopdf as well.

Mudd answered 25/4, 2013 at 0:27 Comment(3)
I can confirm that this worked for me, however, I had to use v0.10.0-rc2 of wkhtmltopdf for OS X. The latest versions did not work for me in this regard.Orion
@Orion thank you for mentioning that -- I'm running into the same issue and it was hell to troubleshoot. wkhtmltopdf version 0.12.3 just won't cooperate with custom fonts when run on OSX, but seems to work fine on our Ubuntu staging & production servers.Primipara
@Topher Hunt Glad I came across you comment, I also experienced the same on OSX the font wouldn't work but when deployed to an Ubuntu server it does.Frump
K
14

I had this same problem and solved it by downloading the fonts and running it off of a local file in my web server with this font-face declaration:

@font-face {
    font-family: 'PT Sans';
    src: url( '/public/inc/fonts/PTS55F-webfont.eot');
    src: url( '/public/inc/fonts/PTS55F-webfont.eot?#iefix') format('embedded-opentype'),
         url( '/public/inc/fonts/PTS55F-webfont.woff') format('woff'),
         url( '/public/inc/fonts/PTS55F-webfont.ttf') format('truetype');
    font-weight: normal;
    font-style: normal;
}

I was able to find this font on Font Squirrel, but your mileage may vary.

I think what happens with the fonts off of Google is that it's trying to load only the format that it thinks this browser wants, which for WebKit is woff (I believe). But wkhtmltopdf can't embed a woff font in a PDF, and so defaults back to sans-serif. By declaring all of them, the TrueType font is included, which is what the PDF actually uses.

Also, you need to define the font you want used as the first one in any font-family CSS definition or wkhtmltopdf will just ignore it.

Kedah answered 20/1, 2012 at 18:48 Comment(4)
Good explanation. If you go to the GWF site and download the font's zip file it contains the TTF file, which wkhtmltopdf can handle. I'm not sure if all fonts on GWF contain the TTF however.Bickart
Thanks a lot! I personnally found a workaround by installing the fonts (they are downloadable from a repository) on my computer's X11 server.Mikkel
If somebody comes here as I searching for PISA PDF HTML Django issue with Google Fonts API, have a look at: xhtml2pdf.appspot.com/static/pisa-en.html and just use ttf fileRodenhouse
One more note about PISA - you will get the joke) there is one imporant issue about linking fonts in CSS. E.g on development server it will work with linking to statics, but on production to get it working, you have to link it not via http but link to the local file, so e.g use MEDIA_ROOT for this purpose.Rodenhouse
G
13

I've just tested that using the @importnotation works:

<style>
@import 'https://fonts.googleapis.com/css?family=Montserrat';
</style>

I'm using django-wkhtmltopdf version 2.0.3

UPDATE: still working in django-wkhtmltopdf 3.3.0

Gebhardt answered 26/8, 2016 at 8:17 Comment(1)
This is actually the best "workaround". IMHO, it's not even a workaround, it's just the cleanest way to use gfont with wkhtmltopdf. ThanksBetony
E
3

The following works for me. Notice the inclusion of extended character sets (if you need them):

<style type="text/css">
@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,600&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese);
</style>
Eugeneeugenia answered 8/11, 2019 at 15:31 Comment(0)
B
2

I must have tried a gazillion variations to get this work (from local). I am trying to get Open Sans Condensed embedded into a pdf via WKHtmlToPdf.

I think it is important that you download and install the Open Sans Condensed ttf directly from google and install it. It is also important to reboot to allow other services access after install. I downloaded the ttf from font-squirrel originally and condensed was listed as "Open Sans" in windows/fonts, which is wrong, if you look after the google install it is listed as "Open Sans Condensed Light" so even google's local('Open Sans Cond Light') script is wrong.

As mentioned before you need to be explicit with the stretch and weights, so this is what has worked for me:

    @font-face { 
     font-family: 'Open Sans'; 
     font-style: normal; 
     font-weight: 400; 
     src: local('Open Sans');
    }

    @font-face { 
     font-family: 'Open Sans Condensed'; 
     font-stretch:condensed; 
     font-style: normal; 
     font-weight: 300; 
     src: local('Open Sans Condensed Light');
    }

@@font-face { font-family: 'Open Sans Condensed Bold'; font-stretch:condensed; font-style: normal; font-weight: 700; src: local('Open Sans Condensed'), local('Open Sans Condensed Bold');}
Blinding answered 31/5, 2013 at 9:5 Comment(0)
O
2

I've been struggling with this for about two days now, my advice to you if none of the answers above work for you:

Install the font (ttf) in the machine that hosts the webserver and just require it in the css just like you would do with a common font.

body{
    font-family: 'Lato';
}

Now wkhtmltopdf should be able to include the font

Ovariotomy answered 16/5, 2016 at 21:59 Comment(3)
Since he allows users to select the font they want to use based on the available google fonts, this could mean installing an increasing number of fontsGebhardt
Thanks. I tried other answers about embedding some huge base64-encoded-font string into my code, but don't think that's a good idea. At last, I installed fonts I need since I don't need too many fonts.Weatherbound
Could you please give more details on how to include it? For example, src: {{ public_path('fonts/noto-sans.regular.ttf') }}; How did you import it?Snook
A
2

In my case I just had to add this option

--javascript-delay 1000

and Google Font text started to show up.

[wkhtmltopdf 0.12.4 (with patched qt)]

Aspergillum answered 16/4, 2018 at 21:17 Comment(0)
T
1

Make sure you're not declaring what font you are printing with in your print stylesheet.

Trinatrinal answered 17/7, 2011 at 4:13 Comment(6)
I am getting this problem with one stylesheet per document.Mikkel
Did some testing and i found that the only way you can get the web font to print is to state the full @font-face code in your css, though support in firefox 3.6.13 appears to be sketchy at best (sometimes it printed, sometimes did not) but it works ok in all other browsers. So go ahead and grab the @font-face code from google's automatically embedded css and add it directly to your css and try it out.Trinatrinal
Try printing this out in a updated browser, like FF4 or Chrome, fiddle.jshell.net/WZYmq/showTrinatrinal
Printing from a web browser works perfectly. As previously written, what causes trouble is PDF generation with wkhtmltopdf.Mikkel
Do you think another solution might work out in your enviroment? such as cute pdf writerTrinatrinal
I chose this command-line tool to automatically convert HTML pages to PDF on a Linux server... which Cute PDF does not allow me to do. Thank you for your help thoughMikkel
A
1

Using @import was key to getting Google Fonts working with wkhtmltopdf but then I had issues with CJK (Chinese, Japanese, and Korean) characters not appearing. The solution was to switch to version 2 of the Google Font API (https://fonts.googleapis.com/css2).

Below is the code snippet I inserted into my HTML to get all the languages I needed to be supported via a test PDF. Keep in mind the performance implications of loading dozens of remote fonts.

<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans";
[lang="sq"] {font-family: 'Noto Sans', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic";
[lang="ar"] {font-family: 'Noto Sans Arabic', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Bengali";
[lang="bn"] {font-family: 'Noto Sans Bengali', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Georgian";
[lang="ka"] {font-family: 'Noto Sans Georgian', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Gujarati";
[lang="gu"] {font-family: 'Noto Sans Gujarati', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew";
[lang="he"] {font-family: 'Noto Sans Hebrew', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari";
[lang="hi"] {font-family: 'Noto Sans Devanagari', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Serif+Tibetan";
[lang="bo"] {font-family: 'Noto Serif Tibetan', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Gurmukhi";
[lang="pa"] {font-family: 'Noto Sans Gurmukhi', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Nastaliq+Urdu";
[lang="ur"] {font-family: 'Noto Nastaliq Urdu', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+Tai+Viet";
[lang="vi"] {font-family: 'Noto Sans Tai Viet', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+SC";
[lang="zh-hans"] {font-family: 'Noto Sans SC', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+TC";
[lang="zh-hant"] {font-family: 'Noto Sans TC', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+JP";
[lang="ja"] {font-family: 'Noto Sans JP', sans-serif !important;}
</style>
<style>
@import "https://fonts.googleapis.com/css2?family=Noto+Sans+KR";
[lang="ko"] {font-family: 'Noto Sans KR', sans-serif !important;}
</style>
Albert answered 13/4, 2022 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.