ruby-on-railspdfprawn

How do I change font in Prawn


What I'm trying to do is generate a PDF using Prawn, while having some language specific characters.

And as a result I'm getting the following error:

raise Prawn::Errors::IncompatibleStringEncoding,
   "Your document includes text that's not compatible with the  Windows-1252 character set.\n" \
   "If you need full UTF-8 support, use TTF fonts instead of PDF's built-in fonts\n."

So I tried changing the font by doing this:

# app/models/prawn/change_font_decorator.rb

Prawn::Document.generate("output.pdf") do
  font_families.update("Arial" => {
    :normal => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf"),
    :italic => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf"),
    :bold => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf"),
    :bold_italic => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf")
  })
  font "Arial"
end

Yet, I'm getting the same error when trying to generate a PDF file.

Any ideas on how to solve this?


Solution

  • The prawn manual is an excellent reference, and includes sections on font usage. The "External Fonts" section is particularly relevant to your issue.

    Here's a basic case that should work, although it doesn't support bold and italic:

    Prawn::Document.generate("output.pdf") do
      font Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf")
      text "Euro €"
    end
    

    To also use bold and italic, it's best to register a font family that doesn't conflict with one of the standard PDF fonts:

    Prawn::Document.generate("output.pdf") do
      font_families.update("OpenSans" => {
        :normal => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf"),
        :italic => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf"),
        :bold => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf"),
        :bold_italic => Rails.root.join("app/assets/fonts/OpenSans-Regular.ttf")
      })
      font "OpenSans"
      text "Euro €"
    end
    

    Where do I put the above code?

    If you are inheriting from Prawn::Document you can try out the following:

    class SpreeInvoicePdf < Prawn::Document
      require 'prawn'
    
      def initialize(quote, line_items)
        self.font_families.update("OpenSans" => {
                                    :normal => Rails.root.join("vendor/assets/fonts/Open_Sans/OpenSans-Regular.ttf"),
                                    :italic => Rails.root.join("vendor/assets/fonts/Open_Sans/OpenSans-Italic.ttf"),
                                    :bold => Rails.root.join("vendor/assets/fonts/Open_Sans/OpenSans-Bold.ttf"),
                                    :bold_italic => Rails.root.join("vendor/assets/fonts/Open_Sans/OpenSans-BoldItalic.ttf")
        })
    
        font "OpenSans"
    
      # etc.
    

    You will of course need to go to Google fonts and download the fonts and place it in the vendor/assets/fonts/Open_Sans/ directory.