5

Heroku support told me that in order to use custom fonts in my web app (not installed in the system, you can see the installed ones with fc-list in a bash console) I had to deploy a .fonts folder with all the fonts inside.

The problem is that I don't know how to do it. I mean, I don't know if the name of the file has to follow any special pattern for heroku or I must do something in my code to consider this fonts or it's something automatic if I include it in the folder...

The fact is that I tried changing the filename of the font in different ways and the font is not used at all.

To give you more details, the process were we're using the font is to convert a PDF to an image, more concretely, with the rghost gem. And the final image doesn't use the custom font at all.

Thanks in advance, any idea is welcome.

josal
  • 452
  • 7
  • 15

3 Answers3

6

I would just create a fonts/ directory in the root folder of the project and then load the fonts like this, for example in config/initializers/rghost.rb:

RGhost::Config::GS[:extensions] << "#{Rails.root}/fonts/LTSyntax.ttf"

The documentation states that you will also need a Fontmap file in the fonts directory, for example:

/Syntax (LTSyntax.ttf); 

Your problem is that the PDF references fonts that are not embedded into the PDF. You can obtain a list of fonts that are used in the PDF with xpdf, using the pdffonts command:

> pdffonts example.pdf
name                                 type              emb sub uni object ID
------------------------------------ ----------------- --- --- --- ---------
Syntax                               Type 1            no  no  no       8  0

Alternatively, you can also use this script from pdf-reader.

Patrick Oscity
  • 53,604
  • 17
  • 144
  • 168
  • Oh great, I have to try this. However, I'm using this method: `RGhost::Convert.new(tmpfile).to :jpg, multipage: true, resolution: resolution` in order to convert each page of the PDF file to an image, so, I wouldn't need to define the tags, maybe. Thanks, I'll come to you as soon as I can test it. – josal May 16 '13 at 17:33
  • I've tried @padde, it seems to get the font correctly but the final image is not using the custom font. Maybe is related to the name of the font, maybe is not matching the imported one and the detected one in the PDF. How could I know it? – josal May 17 '13 at 10:42
  • How are you setting the font? Try with a built in font first, when it works try your custom font. – Patrick Oscity May 17 '13 at 10:56
  • `/LucidaHandwriting (LucidaHandwriting-Italic.ttf);` in Fontmap and `RGhost::Config::GS[:extensions] << "#{Rails.root}/app/fonts"` in initializer rghost.rb, and the font is in LucidaHandwriting-Italic.ttf file inside app/fonts. Maybe ghostscript is looking for a font that is not called 'LucidaHandwriting' when calling `RGhost::Convert.new(tmpfile).to :jpg`? – josal May 17 '13 at 11:06
  • but tmpfile is already a PDF or not? You need to set the font earlier, when you build the PDF document. – Patrick Oscity May 17 '13 at 12:40
  • tmpfile is a PDF document sent by my client and I don't have control over it :( – josal May 17 '13 at 13:24
  • Then i'm afraid you cannot change the font. The Converter does nothing else than to “print” to a jpg file. PDF isn't meant to be modified in this way. Tell the client he must provide you with a PDF that has the proper fonts or let him give you the plain text and render the pdf yourself. Maybe you'll be able to extract the text from the PDF (for example with https://github.com/yob/pdf-reader) and re-render it yourself with the appropriate font. – Patrick Oscity May 17 '13 at 14:10
  • I don't want to change the PDF. I just want to detect the font correctly (I'm curreltly able), match it with a font file I can provide, let the converter know the available font when it needs it in the process of conversion and finally let the converter use it, obtaining the image with the correct font. Currently the final image doesn't have the installed font. I hope to have explained better the problem. Thanks for your comments @padde. – josal May 20 '13 at 08:14
  • So you mean the PDF already uses the custom fonts but the fonts are not embedded into the PDF? – Patrick Oscity May 20 '13 at 10:14
  • Exactly, the PDF uses the custom fonts and they are not embedded into the PDF, so it's necessary to tell GS that he has the fonts somewhere. I suspect it's necessary to tell it to him explicitly via Fontmap or something, because the custom font is already installed in the system and is not used. It seems like the Fontmap file is ignored completely. How can I know the fonts GS is considering? - I've tried with `RGhost::Config.enviroment_fonts.render :pdf, :filename => "/tmp/loaded_fonts.pdf"`but in production env it's not possible to create and read files easily. Any ideas? – josal May 20 '13 at 12:16
  • 1
    Install XPdf then use the command `pdffonts myfile.pdf` to find the fonts referenced in your PDF. You should use these names for your Fontmap file. – Patrick Oscity May 20 '13 at 12:30
  • PERFECT! So, there was just a naming problem!!! I'm not using XPDF to detect the names of the fonts, I'm using `https://github.com/yob/pdf-reader/blob/master/examples/extract_fonts.rb`, but the key is to include the detected name in the Fontmap file. Thanks a lot for your help and for following the discussion. – josal May 20 '13 at 12:44
  • Padde, now that I can detect and use any not-embedded font in any PDF, would you know how to embed this font in the original PDF file? – josal May 20 '13 at 20:56
  • How is the original PDF created? Which software is used? Or do you want to embed the fonts afterwards? – Patrick Oscity May 20 '13 at 23:12
  • Yes, the original PDF could be created with any kind of software, not controlled by us. We detect if it has the fonts embedded, and if not, we embed them. The goal is to avoid problems when printing, because the fonts could be not installed in the printing system. Another solution is to convert to image before printing, that's why we needed to use the proper fonts, no keep the original appearance. Is it possible to embed fonts in general in any PDF file? – josal May 21 '13 at 08:49
  • 1
    Yes it is possible, see http://stackoverflow.com/questions/4231656/how-do-i-embed-fonts-in-an-existing-pdf – Patrick Oscity May 21 '13 at 12:02
  • Oh, great, btw, do you know if this method would be available in rghost? I've not seen it yet. Or in other ruby gem? Thanks again! I'll try with a system() call anyway. – josal May 21 '13 at 12:08
  • 1
    You could simply try `Convert.new("/dir/myfile.pdf").to :pdf, :filename => "/tmp/with_embedded_fonts.pdf"` – Patrick Oscity May 21 '13 at 12:15
  • It works almost always. Sometimes I'm getting this error: `PDFDocEncoding 0 cannot be represented in Unicode`, however, the final PDF is written apparently well. Do you know what this error is related with and how to fix it? Thanks again @padde, you're helping me a lot with your comments. Btw, the `Convert` class would be `RGhost::Convert` – josal May 22 '13 at 11:13
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/30407/discussion-between-josal-and-padde) – josal May 22 '13 at 12:05
3

The way I did it was to put all of the fonts in lib/assets/fonts.

Add these lines to config/application.rb

config.assets.paths << Rails.root.join('lib', 'assets', 'fonts')
config.assets.precompile += %w(.svg .eot .woff .ttf)

I then include the fonts in the stylesheets in lib/assets/stylehseets/fonts.css, for each font do something like:

@font-face {
  font-family: 'AvenirLTStd-Black';
  src: font-url('avenirltstdblack.eot');
  src: font-url('avenirltstdblack.eot?#iefix') format('embedded-opentype'),
  font-url('avenirltstdblack.woff') format('woff'),
  font-url('avenirltstdblack.ttf') format('truetype'),
  font-url('avenirltstdblack.svg#avenirltstdblack') format('svg');
  font-weight: normal;
  font-style: normal;
}

And include that file in the app/assets/stylesheets/application.css

*= require fonts

In your app css (scss) you can use:

font-family: 'AvenirLTStd-Black';

Then just recompile assets $ rake assets:precompile and redeploy. Let me know if that works for you, may have missed a step as I did this months ago!

AJcodez
  • 31,780
  • 20
  • 84
  • 118
  • I think the OP does not want to serve webfonts, he wants to use the fonts to generate PDF, so it's more like using system fonts. – Patrick Oscity May 16 '13 at 17:17
  • Exactly, the task is not to serve webfonts (although I'll take not for the future, thanks!), it's about generate images from not-embedded fonts in PDF files. In this case, it's necessary to use or system fonts (limited and fixed) or to create a .fonts folder in the app, which is the most flexible option, I believe. – josal May 16 '13 at 17:21
  • my bad, saw the words "font" and "rails" and went on a rampage haha – AJcodez May 16 '13 at 21:15
  • This is fantastic, AJcodez, you like your work! :-) Anyway, I want to do what you told me regarding webfonts. Thanks indeed!! – josal May 17 '13 at 07:53
0

This article seems to point out a way of getting custom fonts working in Heroku

http://www.mobalean.com/blog/2011/08/02/pdf-generation-and-heroku

The short answer is that you can:

  1. Add them to the remote file system via GIT checkin
  2. Use Ruby to create the $HOME/.font directory (if it does not already exist)
  3. Use Ruby to create a symlink for each of the font files from the $HOME/.font folder pointing to where they are hosted in the file system (again, if these do not already exist)
  4. Voila!
Steven de Salas
  • 20,944
  • 9
  • 74
  • 82
  • Thanks for the answer. The context is different, but I will take it into account for the future. – josal Sep 05 '13 at 07:26