Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wicked PDF +fonts+heroku+rails3.2

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?

like image 823
Sten Ka Razin Avatar asked Feb 06 '13 16:02

Sten Ka Razin


3 Answers

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...
}
like image 168
Arman H Avatar answered Sep 24 '22 01:09

Arman H


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']
like image 25
apleroy Avatar answered Sep 26 '22 01:09

apleroy


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.

like image 36
J_McCaffrey Avatar answered Sep 26 '22 01:09

J_McCaffrey