How do I change font in Prawn
Asked Answered
A

4

14

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?

Accumbent answered 17/11, 2016 at 9:40 Comment(0)
I
31

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.

Infidel answered 17/11, 2016 at 23:34 Comment(2)
How to implement that in table cell?Participate
Your answer totally solved a problem I that I have been tearing my head over for two weeks. Your second paragraph specifically. The key is to map all fontfaces to "regular". In my case, I was mapping ":normal" to "regular", ":bold" to "bold", etc, and was totally at a loss what I was doing wrong. Thanks!!!Telegraphic
I
3

If you're building your PDF using initialize, you can simply update your font families in the initialize method and then set the desired font.

class InvoicePdf < Prawn::Document

  def initialize()
    super()
    self.font_families.update("DejaVuSans" => {:normal => "#{Rails.root}/public/DejaVuSans.ttf"})
    font "DejaVuSans"
    business_logo
    invoice_items
    footer
  end

  def business_logo
    ##stuff here
  end

end
Illumination answered 24/1, 2018 at 14:39 Comment(1)
How can one go about using a default font? I get the same error but I'm not setting any font Prawn::Document.new(page_size: 'LETTER', margin: 0)Falkirk
H
0

If you want to change the default font in the entire document, then clear the font_families first and add yours. Prawn has its own set of default fonts which will fall back to it after you change the font using @doc.font. The code below clears the 3 font families that Prawn has as fallback and leave only your default font which forces it to use it as true "default".

Prawn::Document.generate(filename) do |doc|
   doc.font_families.clear
   doc.font_families.update(
     "DejaVuSans" => {
        :bold => Rails.root.join("app/assets/font/DejaVuSans-Bold.ttf"),
        :italic => Rails.root.join("app/assets/font/DejaVuSansOblique.ttf"),
        :normal => Rails.root.join("app/assets/font/DejaVuSans.ttf"),
     }
    )
    # more code
end
Huehuebner answered 16/2, 2022 at 13:12 Comment(0)
I
-2

I actually went into the gems folder and into Prawn/font.rb.

I found the following function:

def font_families
  @font_families ||= Hash.new { |h,k| h[k] = {} }.merge!(
    { "Courier"     => { :bold        => "Courier-Bold",
                         :italic      => "Courier-Oblique",
                         :bold_italic => "Courier-BoldOblique",
                         :normal      => "Courier" },

      "Times-Roman" => { :bold         => "Times-Bold",
                         :italic       => "Times-Italic",
                         :bold_italic  => "Times-BoldItalic",
                         :normal       => "Times-Roman" },

      "Helvetica"   => { :bold         => "Helvetica-Bold",
                         :italic       => "Helvetica-Oblique",
                         :bold_italic  => "Helvetica-BoldOblique",
                         :normal       => "Helvetica" }              
    })
end

I edited it to include Arial:

def font_families
  @font_families ||= Hash.new { |h,k| h[k] = {} }.merge!(
    { "Courier"     => { :bold        => "Courier-Bold",
                         :italic      => "Courier-Oblique",
                         :bold_italic => "Courier-BoldOblique",
                         :normal      => "Courier" },

      "Times-Roman" => { :bold         => "Times-Bold",
                         :italic       => "Times-Italic",
                         :bold_italic  => "Times-BoldItalic",
                         :normal       => "Times-Roman" },

      "Helvetica"   => { :bold         => "Helvetica-Bold",
                         :italic       => "Helvetica-Oblique",
                         :bold_italic  => "Helvetica-BoldOblique",
                         :normal       => "Helvetica" },

            "Arial" => { :normal => "public/fonts/arial.ttf",
                          :italic => "public/fonts/ariali.ttf.ttf",
                          :bold => "public/fonts/arialbd.ttf",
                          :bold_italic => "public/fonts/arialbi.ttf"}              
    })
end

and viola! it worked!

Isochronal answered 22/9, 2019 at 1:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.