Wicked PDF +fonts+heroku+rails3.2
Asked Answered
S

3

11

I'm using wicked_pdf with rails 3.2.11 and ruby 1.9.3 to generate a PDF from HTML and deploying to Heroku.

My pdf.css.scss.erb:

<% app_fullhost = Constants["app_fullhost"] %>

@font-face {
  font-family:'DosisMedium'; font-style:normal; font-weight:500;
  src: url(<%=app_fullhost%>/app/font/dosis/Dosis-Medium.ttf) format('woff');
}

*, body {
  font-family: "DosisLight", 'Times New Roman', 'Arial', sans-serif;
} 

where app_fullhost is the exact host, in development or production.

My pdf layout includes among other things :

%html{:lang => I18n.locale}
  %head
    %meta{:charset => "utf-8"}
    %title= content_for?(:title) ? yield(:title) : Settings.app_name
    = wicked_pdf_stylesheet_link_tag "pdf"

In production.rb I have

config.assets.precompile +=%w(pdf.css)

This works without problems in development, but on Heroku the pdf file doesn't load the desired font. I have also tried different solutions like adding these in production.rb:

config.assets.paths << "#{Rails.root}/app/assets/fonts"
config.assets.precompile += %w(*.svg *.eot *.woff *.ttf) 
config.assets.precompile += %w(.svg .eot .woff .ttf) 

and I tried also to change ( in pdf.css.scss.erb ) :

@font-face {
  font-family:'Dosis'; font-style:normal; font-weight:500;
  src: url('Dosis-Medium.ttf') format('woff');
}

or

@font-face {
  font-family:'Dosis'; font-style:normal; font-weight:500;
  src: url(<%= asset_path('Dosis-Medium.ttf')%>) format('woff');
}

The fonts are in assets/fonts and also in public/app/font/dosis and url on Heroku respond correctly with:

..//myapp/app/font/dosis/Dosis-Medium.ttf" and 
..//myapp/assets/Dosis-Medium.ttf 

How can I get the font to load on Heroku?

Shingle answered 6/2, 2013 at 16:47 Comment(0)
F
9

wkhtmltopdf, the program underlying wicked_pdf, is notoriously funky when it comes to loading fonts through CSS. On some systems it works with absolute paths, sometimes it requires relative paths. Even if you get the paths correctly, it may get thrown off by inaccurate CSS deceleration, etc. There are dozens of questions regarding this just on SO alone.

The best, most flexible and most portable soltion that I've found is to Base64-encode the font you're trying to use, and include it directly into the CSS file:

@font-face {
    font-family: 'OpenSans';
    src: url(data:font/truetype;charset=utf-8;base64,AAEAAAATAQA...
}
Frequentation answered 18/7, 2013 at 0:33 Comment(8)
This definitely works, my only addition to this would be to use Font Squirell Generator to get the Base64 data.Gavra
The original website resource I had linked has gone offline. You can use Font Squirrel or this tool if you're using non-Font Squirrel fonts.Frequentation
Have you run into any caveats with multiple Base64-encoded @font-face entries in one file?Simasimah
@JamesChevalier: no caveats, you can use multiple fonts embedded into a single stylesheet with no issues.Frequentation
Does it makes a difference which font I need to convert to Base64 - eot, wott, ttf .. ? I keep seeing similar answer to this problem but no one clarifies that and for some reason this solution does not work for me. Thanks.Bread
I've used it with TTF files with no problems. Have you tried converting TTFs?Frequentation
This example explicitly shows using a TTF (the data:font/truetype bit). To use a WOTT, all you'd probably need to do is change the src to use the correct declaration: src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAwwBMA..., and the same with EOT.Frequentation
I would just point in here a handy way to convert to base64 via rails is here github.com/mileszs/wicked_pdf/issues/250Bread
A
3

I ran into this issue and followed the advice outlined by Arman H - I converted the font to base 64 and referenced it directly in the CSS/SCSS file. The rest of the steps I followed are very similar to those outlined in the original question.

I put together a full description (with a github link to the source code) here: http://apleroy.com/posts/custom-pdf-fonts-with-wicked_pdf-and-heroku

First I referenced the font within the font directory.

<%# /fonts/custom_fonts.css.scss.erb %>
@font-face {
    font-family: "SourceSansPro-Light";
    src: url('<%= asset_path("SourceSansPro-Light.otf") %>');
}

Then, to base 64 encode a font, I used this site (already addressed in a comment above): http://www.opinionatedgeek.com/dotnet/tools/base64encode/. The base-64 encoded output is a random string that is several hundred lines of alpha-numeric characters. I copied this output into the new pdf.css.scss file:

<%# /stylesheets/pdf.css.scss %>
@font-face {
  font-family: 'Source Sans Pro Light';
  src: url(data:font/truetype;charset=utf-8;base64,T1RUTw-----THIS IS HUNDREDS OF LINES LONG -------sGAnBSvO7nBqXQ==)
}

Within the actual html page (which is converted to PDF) I made reference using the wicked_pdf stylesheet tag - as addressed in the original question:

<%# views/pdf_pages/show.html.erb %>
<meta charset='utf-8' />
<%= wicked_pdf_stylesheet_link_tag "pdf" %>

Finally, I precompiled the pdf stylesheet so as to include it in the asset pipeline for deployment on Heroku:

#application.rb
config.assets.precompile += ['pdf.css']
Airedale answered 18/6, 2015 at 18:45 Comment(2)
Welcome to Stackoverflow. Could you put the main part of your answer into the text instead of a link? It will be much easier to find in the futureStrength
I just added in the relevant information. Thanks for your help calling that out.Airedale
B
1

Let me see if I have this right:

Server 1: building a PDF, needs fonts, and pulls them from a URL This works locally in dev, but not on heroku.

Is there anything in the logs? (do you see the http request for the font?)

You said it doesn't load the right font. Does it blow up, or just render as if it never loaded the font (eg a 404 on the font fetch).

Does this work if you don't pull the font file from heroku? (like use aws or some other font from another URL just as a test)

Are you pulling from the same server process that is currently running? Do you have more than one dyno or more than one unicorn process that can handle the current process (building the pdf), and the incoming request (serving the font file)

I've seen people run just a single dyno, but try to run two http events, and run into problems. If you only have one dyno (you didn't mention otherwise), add another one and see what happens, or add another unicorn process.

Biflagellate answered 8/5, 2013 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.