Skip to content

Commit

Permalink
Add OpenType Fonts support
Browse files Browse the repository at this point in the history
  • Loading branch information
pointlessone committed Jul 25, 2020
1 parent 41403fe commit 8ff67ad
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 14 deletions.
Binary file added data/fonts/Bodoni-Book.otf
Binary file not shown.
7 changes: 5 additions & 2 deletions lib/prawn/font.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class Font
require_relative 'fonts/afm'
require_relative 'fonts/ttf'
require_relative 'fonts/dfont'
require_relative 'fonts/otf'
require_relative 'fonts/ttc'

# @deprecated
Expand All @@ -305,9 +306,10 @@ class Font
# Fonts::AFM.new()
def self.load(document, src, options = {})
case font_format(src, options)
when 'ttf' then TTF.new(document, src, options)
when 'ttf' then TTF.new(document, src, options)
when 'otf' then Fonts::OTF.new(document, src, options)
when 'dfont' then DFont.new(document, src, options)
when 'ttc' then TTC.new(document, src, options)
when 'ttc' then TTC.new(document, src, options)
else AFM.new(document, src, options)
end
end
Expand All @@ -317,6 +319,7 @@ def self.font_format(src, options)

case src.to_s
when /\.ttf$/i then 'ttf'
when /\.otf$/i then 'otf'
when /\.dfont$/i then 'dfont'
when /\.ttc$/i then 'ttc'
else 'afm'
Expand Down
6 changes: 4 additions & 2 deletions lib/prawn/fonts/afm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ def compute_width_of(string, options = {}) #:nodoc:

# Returns true if the font has kerning data, false otherwise
#
# rubocop: disable Naming/PredicateName
def has_kerning_data?
@kern_pairs.any?
end
# rubocop: enable Naming/PredicateName

# built-in fonts only work with winansi encoding, so translate the
# string. Changes the encoding in-place, so the argument itself
Expand All @@ -113,8 +115,8 @@ def normalize_encoding(text)
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 external fonts instead of PDF's " \
"built-in fonts.\n"
'If you need full UTF-8 support, use external fonts instead of ' \
"PDF's built-in fonts.\n"
end

def to_utf8(text)
Expand Down
11 changes: 11 additions & 0 deletions lib/prawn/fonts/otf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require_relative 'ttf'

module Prawn
module Fonts
# @private
class OTF < TTF
end
end
end
3 changes: 3 additions & 0 deletions lib/prawn/fonts/ttf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ def bbox
end

# Returns true if the font has kerning data, false otherwise
#
# rubocop: disable Naming/PredicateName
def has_kerning_data?
@has_kerning_data
end
# rubocop: enable Naming/PredicateName

# Perform any changes to the string that need to happen
# before it is rendered to the canvas. Returns an array of
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn/text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def draw_text!(text, options)
unless font.unicode? || font.class.hide_m17n_warning || text.ascii_only?
warn "PDF's built-in fonts have very limited support for " \
"internationalized text.\nIf you need full UTF-8 support, " \
"consider using a TTF font instead.\n\nTo disable this " \
"consider using an external font instead.\n\nTo disable this " \
"warning, add the following line to your code:\n" \
"Prawn::Fonts::AFM.hide_m17n_warning = true\n"

Expand Down
2 changes: 1 addition & 1 deletion lib/prawn/text/box.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ module Text
# or right-to-left) [value of document.text_direction]
# <tt>:fallback_fonts</tt>::
# An array of font names. Each name must be the name of an AFM font or
# the name that was used to register a family of TTF fonts (see
# the name that was used to register a family of external fonts (see
# Prawn::Document#font_families). If present, then each glyph will be
# rendered using the first font that includes the glyph, starting with
# the current font and then moving through :fallback_fonts from
Expand Down
3 changes: 2 additions & 1 deletion manual/text/line_wrapping.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
# display space without allowing for a break.
#
# For writing styles that do not make use of spaces, the zero width space serves
# to mark word boundaries. Zero width spaces are available only with TTF fonts.
# to mark word boundaries. Zero width spaces are available only with external
# fonts.

require_relative '../example_helper'

Expand Down
2 changes: 1 addition & 1 deletion manual/text/registering_families.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

filename = File.basename(__FILE__).gsub('.rb', '.pdf')
Prawn::ManualBuilder::Example.generate(filename) do
# Registering a single TTF font
# Registering a single external font
font_families.update(
'DejaVu Sans' => {
normal: "#{Prawn::DATADIR}/fonts/DejaVuSans.ttf"
Expand Down
2 changes: 1 addition & 1 deletion manual/text/utf8.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

move_down 20

text 'For full internationalized text support, we need to use TTF fonts:'
text 'For full internationalized text support, we need to use external fonts:'
move_down 20

font("#{Prawn::DATADIR}/fonts/DejaVuSans.ttf") do
Expand Down
2 changes: 1 addition & 1 deletion prawn.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
spec.licenses = %w[PRAWN GPL-2.0 GPL-3.0]

spec.add_dependency('pdf-core', '~> 0.8.1')
spec.add_dependency('ttfunk', '~> 1.5')
spec.add_dependency('ttfunk', '~> 1.6')

spec.add_development_dependency('pdf-inspector', '>= 1.2.1', '< 2.0.a')
spec.add_development_dependency('pdf-reader', ['~> 1.4', '>= 1.4.1'])
Expand Down
31 changes: 31 additions & 0 deletions spec/prawn/font_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,37 @@ def page_should_not_include_font(font)
end
end

describe 'OTF fonts' do
let(:font) { pdf.find_font "#{Prawn::DATADIR}/fonts/Bodoni-Book.otf" }

it 'calculates string width taking into account accented characters' do
expect(font.compute_width_of('é', size: 12)).to eq(
font.compute_width_of('e', size: 12)
)
end

it 'uses the ascender, descender, and cap height from the OTF verbatim' do
# These metrics are relative to the font's own bbox. They should not be
# scaled with font size.
ref = pdf.ref!({})
font.send :embed, ref, 0

# Pull out the embedded font descriptor
descriptor = ref.data[:FontDescriptor].data
expect(descriptor[:Ascent]).to eq(1023)
expect(descriptor[:Descent]).to eq(-200)
expect(descriptor[:CapHeight]).to eq(3072)
end

describe 'when normalizing encoding' do
it 'does not modify the original string with normalize_encoding()' do
original = 'Foo'
normalized = font.normalize_encoding(original)
expect(original).to_not be_equal(normalized)
end
end
end

describe 'DFont fonts' do
let(:file) { "#{Prawn::DATADIR}/fonts/Panic+Sans.dfont" }

Expand Down
8 changes: 4 additions & 4 deletions spec/prawn_manual_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
MANUAL_HASH =
case RUBY_ENGINE
when 'ruby'
'85d2ded146d1e6659e9db389a071896d6e57d7cc4210c6b7fc75fc4afe2b5697'\
'8a86baca785acd717964619dc234327ef59f5ba6d750dfd626279af0166f6c5e'
'b38bd8aaa7b419a2f594ee8837cd62f813141000393995b0c0456644b823a62a'\
'2f8031b2db0fc9e7c544b3946a9b0e60570d510564e6fed3931e0717dd49188a'
when 'jruby'
'85d2ded146d1e6659e9db389a071896d6e57d7cc4210c6b7fc75fc4afe2b5697'\
'8a86baca785acd717964619dc234327ef59f5ba6d750dfd626279af0166f6c5e'
'b38bd8aaa7b419a2f594ee8837cd62f813141000393995b0c0456644b823a62a'\
'2f8031b2db0fc9e7c544b3946a9b0e60570d510564e6fed3931e0717dd49188a'
end

RSpec.describe Prawn do
Expand Down

0 comments on commit 8ff67ad

Please sign in to comment.